[gradle] 01/08: Imported Upstream version 1.8
Eugene Zhukov
eugene-guest at moszumanska.debian.org
Fri May 16 07:04:41 UTC 2014
This is an automated email from the git hooks/post-receive script.
eugene-guest pushed a commit to branch 1.8
in repository gradle.
commit 510b0c4550a413d4495b7fc0d80239fe131aa6de
Author: Eugene Zhukov <jevgeni.zh at gmail.com>
Date: Wed Apr 23 08:40:22 2014 +0000
Imported Upstream version 1.8
---
build.gradle | 21 +-
buildSrc/build.gradle | 2 +-
.../main/groovy/org/gradle/build/BuildTypes.groovy | 2 +-
.../main/groovy/org/gradle/build/JarJarJar.groovy | 6 +-
.../build/docs/SampleElementValidator.groovy | 2 -
.../build/docs/UserGuideTransformTask.groovy | 5 +-
.../build/docs/dsl/docbook/JavadocConverter.java | 17 +
.../docs/dsl/source/ExtractDslMetaDataTask.groovy | 4 +-
.../dsl/source/GenerateDefaultImportsTask.java | 148 ++++
.../docs/model/SimpleClassMetaDataRepository.java | 10 +-
.../docs/dsl/docbook/JavadocConverterTest.groovy | 10 +
.../model/SimpleClassMetaDataRepositoryTest.groovy | 26 +-
config/checkstyle/checkstyle.xml | 3 +
gradle/buildReceipt.gradle | 1 +
gradle/dependencies.gradle | 6 +-
gradle/groovyProject.gradle | 20 +-
gradle/integTest.gradle | 8 +-
gradle/testGroupings.gradle | 13 +
gradle/versioning.gradle | 4 +
gradle/wrapper.gradle | 28 +-
gradle/wrapper/gradle-wrapper.properties | 4 +-
settings.gradle | 5 +
subprojects/announce/announce.gradle | 3 +-
.../api/plugins/announce/AnnouncePlugin.groovy | 5 +-
.../announce/AnnouncePluginExtension.groovy | 36 +-
.../announce/internal/AnnouncerFactory.groovy | 3 -
.../internal/DefaultAnnouncerFactory.groovy | 3 -
.../plugins/announce/internal/NotifySend.groovy | 3 -
.../api/plugins/announce/internal/Twitter.groovy | 8 +-
.../announce/AnnouncePluginExtensionTest.groovy | 8 +-
.../api/plugins/announce/AnnouncePluginTest.groovy | 9 +-
.../announce/BuildAnnouncementsPluginTest.groovy | 4 +-
.../internal/DefaultAnnouncerFactoryTest.groovy | 7 +-
subprojects/antlr/antlr.gradle | 2 +-
.../org/gradle/api/plugins/antlr/AntlrPlugin.java | 6 +-
.../plugins/antlr/AntlrSourceVirtualDirectory.java | 2 -
.../org/gradle/api/plugins/antlr/AntlrTask.java | 14 +-
.../internal/AntlrSourceVirtualDirectoryImpl.java | 2 -
.../api/plugins/antlr/internal/GenerationPlan.java | 2 -
.../antlr/internal/GenerationPlanBuilder.java | 12 +-
.../plugins/antlr/internal/GrammarDelegate.java | 10 +-
.../antlr/internal/GrammarFileMetadata.java | 6 +-
.../plugins/antlr/internal/GrammarMetadata.java | 8 +-
.../plugins/antlr/internal/MetadataExtracter.java | 10 +-
.../gradle/api/plugins/antlr/internal/XRef.java | 8 +-
.../api/plugins/antlr/AntlrPluginTest.groovy | 8 +-
.../base-services-groovy.gradle | 2 +-
.../main/groovy/org/gradle/api/specs/AndSpec.java | 1 -
.../groovy/org/gradle/api/specs/AndSpecTest.java | 4 +-
subprojects/base-services/base-services.gradle | 4 +-
.../main/java/org/gradle/api/GradleException.java | 2 -
.../src/main/java/org/gradle/api/JavaVersion.java | 4 +
.../main/java/org/gradle/api/internal/Factory.java | 4 +-
.../java/org/gradle/api/internal/Transformers.java | 48 ++
.../api/internal/project/ServiceRegistry.java | 4 +-
.../java/org/gradle/api/specs/CompositeSpec.java | 1 -
.../main/java/org/gradle/api/specs/NotSpec.java | 1 -
.../src/main/java/org/gradle/api/specs/OrSpec.java | 1 -
.../src/main/java/org/gradle/api/specs/Spec.java | 1 -
.../java/org/gradle/internal/LazyIterable.java | 33 -
.../internal/classloader/CachingClassLoader.java | 66 ++
.../internal/classloader/ClassLoaderFactory.java | 47 ++
.../internal/classloader/ClassLoaderHierarchy.java | 21 +
.../internal/classloader/ClassLoaderSpec.java | 45 ++
.../internal/classloader/ClassLoaderVisitor.java | 52 ++
.../gradle/internal/classloader/ClasspathUtil.java | 101 +++
.../classloader/DefaultClassLoaderFactory.java | 111 +++
.../internal/classloader/FilteringClassLoader.java | 275 ++++++++
.../classloader/MultiParentClassLoader.java | 126 ++++
.../classloader/MutableURLClassLoader.java | 89 +++
.../classloader/TransformingClassLoader.java | 63 ++
.../internal/concurrent/ServiceLifecycle.java | 118 ++++
.../org/gradle/internal/jvm/JavaHomeException.java | 3 -
.../java/org/gradle/internal/jvm/JavaInfo.java | 3 -
.../src/main/java/org/gradle/internal/jvm/Jre.java | 26 +
.../src/main/java/org/gradle/internal/jvm/Jvm.java | 80 ++-
.../org/gradle/internal/os/OperatingSystem.java | 51 +-
.../internal/reflect/DirectInstantiator.java | 2 +-
.../org/gradle/internal/reflect/Instantiator.java | 2 +-
.../internal/reflect/JavaReflectionUtil.java | 346 ++++++++-
.../internal/reflect/NoSuchPropertyException.java | 26 +
.../gradle/internal/reflect/PropertyAccessor.java | 25 +
.../gradle/internal/reflect/PropertyMutator.java | 25 +
.../gradle/internal/service/ServiceLocator.java | 88 ++-
.../service/SynchronizedServiceRegistry.java | 3 -
.../main/java/org/gradle/util/CollectionUtils.java | 20 +
.../src/main/java/org/gradle/util/JavaMethod.java | 75 ++
.../main/java}/org/gradle/util/hash/HashUtil.java | 0
.../main/java}/org/gradle/util/hash/HashValue.java | 0
.../gradle/api/internal/TransformersTest.groovy | 24 +
.../org/gradle/internal/LazyIterableTest.groovy | 37 -
.../classloader/CachingClassLoaderTest.groovy | 78 +++
.../DefaultClassLoaderFactoryTest.groovy | 91 +++
.../DefaultClassLoaderFactoryTestHelper.java | 35 +
.../classloader/FilteringClassLoaderTest.groovy | 235 +++++++
.../classloader/MultiParentClassLoaderTest.groovy | 123 ++++
.../classloader/MutableURLClassLoaderTest.groovy | 39 ++
.../concurrent/ServiceLifecycleTest.groovy | 203 ++++++
.../groovy/org/gradle/internal/jvm/JvmTest.groovy | 224 ++++--
.../gradle/internal/os/OperatingSystemTest.groovy | 33 +
.../internal/reflect/JavaReflectionUtilTest.groovy | 242 ++++++-
.../gradle/internal/reflect/JavaTestSubject.java | 99 +++
.../internal/reflect/JavaTestSubjectSubclass.java | 31 +
.../internal/service/ServiceLocatorTest.groovy | 136 +++-
.../service/SynchronizedServiceRegistryTest.groovy | 3 -
.../org/gradle/util/CollectionUtilsTest.groovy | 5 +
.../groovy/org/gradle/util/JavaMethodTest.java | 71 ++
.../org/gradle/util/hash/HashValueTest.groovy | 0
.../resources/org/gradle/util/ClassLoaderTest.txt | 0
.../build-comparison/build-comparison.gradle | 6 +-
.../gradle/CompareGradleBuilds.java | 2 +-
.../internal/ComparableGradleBuildExecuter.java | 2 +-
.../internal/DefaultGradleBuildInvocationSpec.java | 3 -
.../gradle/internal/GradleBuildComparison.java | 2 +-
.../internal/GradleBuildOutcomeSetInferrer.java | 10 +-
.../internal/GradleBuildOutcomeSetTransformer.java | 12 +-
.../outcome/internal/FileOutcomeIdentifier.java | 41 ++
.../archive/GeneratedArchiveBuildOutcome.java | 10 +-
.../tooling/DefaultGradleBuildOutcome.java | 46 ++
.../tooling/DefaultGradleFileBuildOutcome.java | 42 ++
.../internal/tooling/DefaultProjectOutcomes.java | 79 +++
.../tooling/ProjectOutcomesModelBuilder.java | 67 ++
...blishArtifactToFileBuildOutcomeTransformer.java | 97 +++
.../tooling/ToolingRegistrationAction.java | 27 +
...le.configuration.project.ProjectConfigureAction | 1 +
.../DefaultGradleBuildInvocationSpecTest.groovy | 4 +-
.../GradleBuildOutcomeSetInferrerTest.groovy | 2 +-
.../GradleBuildOutcomeSetTransformerTest.groovy | 26 +-
...neratedArchiveBuildOutcomeComparatorTest.groovy | 8 +-
...rtifactToFileBuildOutcomeTransformerTest.groovy | 87 +++
subprojects/build-setup/build-setup.gradle | 25 +
.../plugins/BuildSetupPluginIntegrationTest.groovy | 204 ++++++
.../plugins/JavaLibrarySetupIntegrationTest.groovy | 76 ++
.../plugins/MavenConversionIntegrationTest.groovy | 202 ++++++
.../plugins/WrapperPluginIntegrationTest.groovy | 35 +
.../plugins/fixtures/WrapperTestFixture.groovy | 50 ++
.../WrapperPluginAutoApplyActionIntegTest.groovy | 99 +++
.../enforcerplugin/pom.xml | 0
.../enforcerplugin/src/main/java/Foo.java | 0
.../flatmultimodule/webinar-api/pom.xml | 0
.../src/main/java/webinar/Demoable.java | 0
.../flatmultimodule/webinar-impl/pom.xml | 0
.../src/main/java/webinar/Webinar.java | 0
.../src/test/java/webinar/WebinarTest.java | 0
.../flatmultimodule/webinar-parent/pom.xml | 0
.../flatmultimodule/webinar-war/pom.xml | 0
.../webinar-war/src/main/webapp/WEB-INF/web.xml | 0
.../webinar-war/src/main/webapp/index.jsp | 0
.../mavenExtensions/pom.xml | 47 ++
.../mavenExtensions/test-core/pom.xml | 22 +
.../multiModule/pom.xml | 0
.../multiModule/webinar-api/pom.xml | 0
.../src/main/java/webinar/Demoable.java | 0
.../multiModule/webinar-impl/pom.xml | 0
.../src/main/java/webinar/Webinar.java | 0
.../src/test/java/webinar/WebinarTest.java | 0
.../multiModule/webinar-war/pom.xml | 0
.../webinar-war/src/main/webapp/WEB-INF/web.xml | 0
.../webinar-war/src/main/webapp/index.jsp | 0
.../providedNotWar/pom.xml | 30 +
.../singleModule/pom.xml | 0
.../singleModule/src/main/java/Foo.java | 0
.../singleModule/src/test/java/FooTest.java | 0
.../MavenConversionIntegrationTest/testjar/pom.xml | 0
.../testjar/src/main/java/Foo.java | 0
.../testjar/src/test/java/FooTest.java | 0
.../org/gradle/api/tasks/wrapper/Wrapper.java | 278 ++++++++
.../org/gradle/api/tasks/wrapper/package-info.java | 0
.../buildsetup/plugins/BuildSetupPlugin.groovy | 87 +++
.../gradle/buildsetup/plugins/WrapperPlugin.groovy | 34 +
.../internal/BasicProjectSetupDescriptor.groovy | 41 ++
.../internal/BuildSetupAutoApplyAction.java | 33 +
.../plugins/internal/BuildSetupTypeIds.java | 27 +
.../JavaLibraryProjectSetupDescriptor.groovy | 57 ++
.../internal/PomProjectSetupDescriptor.groovy | 51 ++
.../internal/ProjectLayoutSetupRegistry.groovy | 47 ++
.../ProjectLayoutSetupRegistryFactory.groovy | 47 ++
.../plugins/internal/ProjectSetupDescriptor.groovy | 25 +
.../TemplateBasedProjectSetupDescriptor.groovy | 73 ++
.../buildsetup/plugins/internal/TemplateValue.java | 67 ++
.../internal/WrapperPluginAutoApplyAction.groovy | 32 +
.../plugins/internal/maven/Maven2Gradle.groovy | 514 ++++++++++++++
.../internal/maven/MavenConversionException.java | 29 +
.../internal/maven/MavenProjectXmlWriter.java | 58 ++
.../internal/maven/MavenProjectsCreator.java | 92 +++
.../org/gradle/buildsetup/tasks/SetupBuild.groovy | 59 ++
.../META-INF/gradle-plugins/build-setup.properties | 1 +
.../META-INF/gradle-plugins/wrapper.properties | 17 +
...le.configuration.project.ProjectConfigureAction | 2 +
.../tasks/templates/Library.java.template | 11 +
.../tasks/templates/LibraryTest.java.template | 15 +
.../tasks/templates/build.gradle.template | 32 +
.../templates/java-library-build.gradle.template | 30 +
.../tasks/templates/settings.gradle.template | 19 +
.../org/gradle/api/tasks/wrapper/WrapperTest.java | 161 +++++
.../buildsetup/plugins/BuildSetupPluginSpec.groovy | 77 ++
.../buildsetup/plugins/WrapperPluginSpec.groovy | 36 +
.../internal/BuildSetupAutoApplyActionSpec.groovy | 72 ++
.../ProjectLayoutSetupRegistryFactoryTest.groovy | 52 ++
.../internal/ProjectLayoutSetupRegistrySpec.groovy | 58 ++
.../TemplateBasedProjectSetupDescriptorSpec.groovy | 105 +++
.../plugins/internal/TemplateValueTest.groovy | 48 ++
.../maven/MavenProjectXmlWriterTest.groovy | 31 +
.../internal/maven/MavenProjectsCreatorSpec.groovy | 117 ++++
.../gradle/buildsetup/tasks/SetupBuildSpec.groovy | 69 ++
subprojects/cli/cli.gradle | 2 +-
.../gradle/cli/CommandLineArgumentException.java | 2 -
.../java/org/gradle/cli/CommandLineConverter.java | 3 -
.../java/org/gradle/cli/CommandLineOption.java | 20 +-
.../java/org/gradle/cli/CommandLineParser.java | 22 +-
.../java/org/gradle/cli/ParsedCommandLine.java | 4 +
.../org/gradle/cli/CommandLineParserTest.groovy | 50 +-
.../gradle/cli/ParsedCommandLineOptionSpec.groovy | 3 -
.../org/gradle/cli/ParsedCommandLineTest.groovy | 3 -
subprojects/code-quality/code-quality.gradle | 2 +-
.../quality/CheckstylePluginIntegrationTest.groovy | 6 +-
.../quality/CodeNarcPluginIntegrationTest.groovy | 18 +-
.../CodeQualityPluginIntegrationTest.groovy | 18 +-
.../quality/FindBugsPluginIntegrationTest.groovy | 2 +-
.../quality/PmdPluginIntegrationTest.groovy | 4 +-
.../quality/PmdPluginVersionIntegrationTest.groovy | 4 +-
.../api/plugins/quality/CheckstyleReports.java | 7 +-
.../org/gradle/api/plugins/quality/CodeNarc.groovy | 22 +-
.../api/plugins/quality/CodeNarcExtension.groovy | 15 +
.../api/plugins/quality/CodeNarcPlugin.groovy | 8 +-
.../api/plugins/quality/CodeNarcReports.java | 11 +-
.../api/plugins/quality/FindBugsPlugin.groovy | 2 +-
.../api/plugins/quality/FindBugsReports.java | 13 +-
.../org/gradle/api/plugins/quality/JDepend.groovy | 2 +-
.../gradle/api/plugins/quality/JDependReports.java | 9 +-
.../gradle/api/plugins/quality/PmdExtension.groovy | 1 +
.../org/gradle/api/plugins/quality/PmdReports.java | 10 +-
.../internal/AbstractCodeQualityPlugin.groovy | 4 +-
.../plugins/quality/CheckstylePluginTest.groovy | 8 +-
.../api/plugins/quality/CheckstyleTest.groovy | 2 +-
.../api/plugins/quality/CodeNarcPluginTest.groovy | 35 +-
.../plugins/quality/CodeQualityPluginTest.groovy | 12 +-
.../api/plugins/quality/FindBugsPluginTest.groovy | 9 +-
.../gradle/api/plugins/quality/FindBugsTest.groovy | 2 +-
.../api/plugins/quality/JDependPluginTest.groovy | 8 +-
.../api/plugins/quality/PmdPluginTest.groovy | 8 +-
subprojects/core-impl/core-impl.gradle | 5 +-
.../ArtifactDependenciesIntegrationTest.groovy | 36 +-
...ModuleDependenciesResolveIntegrationTest.groovy | 3 -
.../DependencyNotationIntegrationSpec.groovy | 3 -
.../DependencyResolveRulesIntegrationTest.groovy | 36 +-
.../DetachedConfigurationsIntegrationTest.groovy | 62 ++
.../ExtendingConfigurationsIntegrationTest.groovy | 60 ++
.../resolve/ForcedModulesIntegrationTest.groovy | 5 +-
.../ProjectDependenciesIntegrationTest.groovy | 5 +-
.../ProjectDependencyResolveIntegrationTest.groovy | 41 +-
.../ResolutionResultApiIntegrationTest.groovy | 75 ++
...ResolutionStrategySamplesIntegrationTest.groovy | 5 +-
.../ResolveCrossVersionIntegrationTest.groovy | 20 +-
.../ResolvedConfigurationIntegrationTest.groovy | 6 +-
...VersionConflictResolutionIntegrationTest.groovy | 153 +++-
...actCacheReuseCrossVersionIntegrationTest.groovy | 3 -
...AliasedArtifactResolutionIntegrationTest.groovy | 21 +-
...ependencyMetadataInMemoryIntegrationTest.groovy | 197 ++++++
.../FileSystemResolverIntegrationTest.groovy | 12 +-
.../custom/IvySFtpResolverIntegrationTest.groovy | 8 +-
.../custom/IvyUrlResolverIntegrationTest.groovy | 6 +-
.../IvyBrokenRemoteResolveIntegrationTest.groovy | 33 +-
...angingModuleRemoteResolveIntegrationTest.groovy | 1 -
...IvyComponentMetadataRulesIntegrationTest.groovy | 132 ++++
...CustomStatusLatestVersionIntegrationTest.groovy | 62 ++
.../ivy/IvyDescriptorResolveIntegrationTest.groovy | 140 +++-
...amicRevisionRemoteResolveIntegrationTest.groovy | 43 ++
...IvyDynamicRevisionResolveIntegrationTest.groovy | 125 +++-
.../IvyMetadataConsistencyIntegrationTest.groovy | 54 ++
.../ivy/IvyModuleResolveIntegrationTest.groovy | 209 ++++++
.../resolve/ivy/IvyResolveIntegrationTest.groovy | 108 +--
.../maven/BadPomFileResolveIntegrationTest.groovy | 50 +-
.../LegacyMavenRepoResolveIntegrationTest.groovy | 19 +-
.../MavenBrokenRemoteResolveIntegrationTest.groovy | 50 ++
...venComponentMetadataRulesIntegrationTest.groovy | 61 ++
.../MavenDependencyResolveIntegrationTest.groovy | 3 +
...nJcenterDependencyResolveIntegrationTest.groovy | 72 ++
.../maven/MavenLatestResolveIntegrationTest.groovy | 91 +++
.../MavenParentPomResolveIntegrationTest.groovy | 85 +++
.../MavenSnapshotResolveIntegrationTest.groovy | 13 +-
.../canNestModules/projectWithNestedModules.gradle | 2 +-
.../projectWithConflicts.gradle | 2 +-
.../artifacts/ArtifactDependencyResolver.java | 3 -
.../BuildableModuleVersionPublishMetaData.java | 28 +
.../internal/artifacts/ConfigurationResolver.java | 3 -
.../artifacts/DefaultArtifactIdentifier.java | 119 ++++
.../artifacts/DefaultDependencyFactory.java | 3 -
.../DefaultDependencyManagementServices.java | 114 +--
.../artifacts/DefaultModuleVersionIdentifier.java | 5 +
.../DefaultModuleVersionPublishMetaData.java | 52 ++
.../artifacts/DefaultModuleVersionSelector.java | 8 +-
.../artifacts/DefaultProjectDependencyFactory.java | 3 -
.../artifacts/DefaultResolvedArtifact.java | 28 +-
.../artifacts/DefaultResolvedDependency.java | 17 +-
.../artifacts/ModuleMetadataProcessor.java | 22 +
.../ModuleVersionIdentifierSerializer.java | 26 +-
.../artifacts/ModuleVersionSelectorSerializer.java | 41 ++
.../internal/artifacts/PlexusLoggerAdapter.java | 3 -
.../artifacts/ResolvedConfigurationIdentifier.java | 6 +-
.../ResolvedConfigurationIdentifierSerializer.java | 39 ++
.../api/internal/artifacts/ResolverResults.java | 3 -
.../artifacts/configurations/Configurations.java | 8 -
.../configurations/ConfigurationsProvider.java | 3 -
.../configurations/DefaultConfiguration.java | 4 +
.../DefaultConfigurationContainer.java | 8 +-
.../DetachedConfigurationsProvider.java | 3 -
.../artifacts/dsl/DefaultArtifactHandler.groovy | 5 +-
.../dsl/DefaultComponentMetadataHandler.java | 43 ++
.../dsl/ModuleVersionSelectorParsers.java | 3 -
.../artifacts/dsl/ParsedModuleStringNotation.java | 3 -
.../dsl/PublishArtifactNotationParserFactory.java | 3 -
.../ivyservice/BuildableArtifactResolveResult.java | 6 +-
.../DefaultBuildableArtifactResolveResult.java | 4 +-
...DefaultBuildableModuleVersionResolveResult.java | 6 +-
.../ivyservice/DefaultCacheLockingManager.java | 3 +-
.../DefaultDependencyResolveDetails.java | 3 -
.../ivyservice/DefaultIvyContextManager.java | 104 +++
.../ivyservice/DefaultIvyDependencyPublisher.java | 136 +---
.../artifacts/ivyservice/DefaultIvyFactory.java | 38 -
.../ivyservice/DefaultLenientConfiguration.java | 113 +--
.../ivyservice/DefaultResolvedConfiguration.java | 13 +-
.../ivyservice/DefaultSettingsConverter.java | 70 --
.../ivyservice/DependencyToModuleResolver.java | 28 -
.../DependencyToModuleVersionResolver.java | 28 +
.../ErrorHandlingArtifactDependencyResolver.java | 108 ++-
.../ivyservice/IvyBackedArtifactPublisher.java | 66 +-
.../artifacts/ivyservice/IvyContextManager.java | 39 ++
.../ivyservice/IvyDependencyPublisher.java | 14 +-
.../internal/artifacts/ivyservice/IvyFactory.java | 26 -
.../artifacts/ivyservice/IvyLoggingAdaper.java | 18 +-
.../ivyservice/IvyModuleDescriptorWriter.java | 0
.../IvyResolverBackedModuleVersionPublisher.java | 66 ++
.../artifacts/ivyservice/IvySettingsFactory.java | 40 --
.../api/internal/artifacts/ivyservice/IvyUtil.java | 3 -
.../ivyservice/IvyXmlModuleDescriptorWriter.java | 7 +-
.../ivyservice/ModuleDescriptorConverter.java | 26 +
.../ivyservice/ModuleToModuleVersionResolver.java | 29 +
.../ivyservice/ModuleVersionResolveException.java | 10 +-
.../ivyservice/ResolvedArtifactFactory.java | 28 +-
.../ivyservice/ResolvedConfigurationBuilder.java | 31 -
.../artifacts/ivyservice/SettingsConverter.java | 34 -
...cuitEmptyConfigsArtifactDependencyResolver.java | 4 +-
.../SubstitutedModuleVersionIdResolveResult.java | 3 -
.../clientmodule/ClientModuleResolver.java | 13 +-
.../DefaultCachedModuleResolution.java | 11 +-
.../DefaultResolvedModuleVersion.java | 10 +-
.../dynamicversions/ModuleResolutionCache.java | 6 +-
.../SingleFileBackedModuleResolutionCache.java | 75 +-
.../AbstractDependencyResolverAdapter.java | 55 --
.../ivyresolve/ArtifactNotFoundException.java | 6 +-
.../ivyresolve/ArtifactResolveException.java | 26 +-
.../ivyresolve/BuildableModuleVersionMetaData.java | 78 ---
...uildableModuleVersionMetaDataResolveResult.java | 83 +++
.../CacheLockingModuleVersionRepository.java | 6 +-
.../ivyresolve/CachingModuleVersionRepository.java | 64 +-
.../ivyresolve/ConfigurationMetaData.java | 42 ++
.../ConfiguredModuleVersionRepository.java | 23 +
.../DefaultBuildableModuleVersionMetaData.java | 137 ----
...uildableModuleVersionMetaDataResolveResult.java | 286 ++++++++
.../ivyresolve/DefaultDependencyMetaData.java | 8 +-
.../ivyservice/ivyresolve/DefaultIvyAdapter.java | 25 +-
.../ivyresolve/DelegatingDependencyResolver.java | 149 ----
.../ivyservice/ivyresolve/DependencyMetaData.java | 2 +
.../ivyresolve/DependencyResolverIdentifier.java | 42 +-
.../ExternalResourceResolverAdapter.java | 47 --
.../ivyservice/ivyresolve/IvyAdapter.java | 11 +-
.../IvyAwareModuleVersionRepository.java | 6 +-
.../ivyservice/ivyresolve/IvyContextualiser.java | 36 +-
.../ivyresolve/IvyDependencyResolverAdapter.java | 57 +-
.../IvyDynamicResolveModuleVersionRepository.java | 16 +-
.../ivyresolve/LazyDependencyToModuleResolver.java | 8 +-
.../LocalAwareModuleVersionRepository.java | 6 +-
.../ivyresolve/LocalModuleVersionRepository.java | 8 +-
.../ivyresolve/LoopbackDependencyResolver.java | 94 ++-
.../ivyservice/ivyresolve/ModuleSource.java | 8 +-
.../ivyresolve/ModuleVersionMetaData.java | 10 +-
.../ivyresolve/ModuleVersionRepository.java | 14 +-
.../ivyresolve/MutableModuleVersionMetaData.java | 24 +
.../ivyservice/ivyresolve/ResolveIvyFactory.java | 83 ++-
.../ivyresolve/RestrictedDependencyResolver.java | 36 -
.../StartParameterResolutionOverride.java | 6 +-
.../ivyservice/ivyresolve/UserResolverChain.java | 43 +-
.../ivyservice/ivyresolve/VersionInfo.java | 39 ++
.../artifacts/ivyservice/ivyresolve/Versioned.java | 20 +
.../memcache/CachedModuleVersionResult.java | 64 ++
.../ivyresolve/memcache/CachedRepository.java | 65 ++
.../memcache/DependencyMetadataCache.java | 84 +++
.../memcache/DependencyMetadataCacheStats.java | 29 +
.../memcache/InMemoryDependencyMetadataCache.java | 62 ++
.../parser/AbstractDescriptorParseContext.java | 66 ++
.../parser/AbstractModuleDescriptorParser.java | 48 ++
.../ivyresolve/parser/DefaultMetaDataParser.java | 34 +
.../ivyresolve/parser/DescriptorParseContext.java | 36 +
.../parser/DisconnectedDescriptorParseContext.java | 46 ++
.../parser/DisconnectedParserSettings.java | 110 ---
.../DownloadedIvyModuleDescriptorParser.java | 11 +-
.../parser/GradlePomModuleDescriptorBuilder.java | 67 +-
.../parser/GradlePomModuleDescriptorParser.java | 364 ++++------
.../parser/IvyXmlModuleDescriptorParser.java | 482 ++++++++++---
.../ivyresolve/parser/MetaDataParseException.java | 32 +
.../ivyresolve/parser/MetaDataParser.java | 23 +
.../ivyresolve/parser/ModuleDescriptorAdapter.java | 87 +++
.../ivyresolve/parser/ModuleDescriptorParser.java | 31 +
.../parser/ModuleScopedParserSettings.java | 102 ---
.../ivyresolve/parser/ParserRegistry.java | 5 +-
.../ivyservice/ivyresolve/parser/PomReader.java | 577 +++++++++++++++
.../ivyresolve/strategy/ChainVersionMatcher.java | 64 ++
.../ivyresolve/strategy/ExactVersionMatcher.java | 113 +++
.../ivyresolve/strategy/LatestStrategy.java | 42 ++
.../ivyresolve/strategy/LatestVersionMatcher.java | 47 ++
.../ivyresolve/strategy/LatestVersionStrategy.java | 66 ++
.../ivyresolve/strategy/ResolverStrategy.java | 62 ++
.../ivyresolve/strategy/SubVersionMatcher.java | 59 ++
.../ivyresolve/strategy/VersionMatcher.java | 68 ++
.../ivyresolve/strategy/VersionRangeMatcher.java | 180 +++++
.../CachedModuleDescriptorParseContext.java | 53 ++
.../modulecache/DefaultCachedModuleDescriptor.java | 7 +-
.../modulecache/DefaultModuleDescriptorCache.java | 70 +-
.../modulecache/ModuleDescriptorCache.java | 4 +-
.../modulecache/ModuleDescriptorStore.java | 35 +-
.../ArtifactsExtraAttributesStrategy.java | 27 -
.../ArtifactsToModuleDescriptorConverter.java | 7 +-
.../ConfigurationsToModuleDescriptorConverter.java | 3 -
...efaultArtifactsToModuleDescriptorConverter.java | 29 +-
...tConfigurationsToModuleDescriptorConverter.java | 3 -
.../DefaultExcludeRuleConverter.java | 3 -
.../DefaultModuleDescriptorFactory.java | 24 +-
.../moduleconverter/ExcludeRuleConverter.java | 3 -
.../moduleconverter/ModuleDescriptorFactory.java | 3 -
.../PublishModuleDescriptorConverter.java | 25 +-
.../ResolveModuleDescriptorConverter.java | 23 +-
.../AbstractIvyDependencyDescriptorFactory.java | 3 -
...ClientModuleIvyDependencyDescriptorFactory.java | 3 -
...ultDependenciesToModuleDescriptorConverter.java | 3 -
.../DefaultDependencyDescriptorFactory.java | 3 -
...aultModuleDescriptorFactoryForClientModule.java | 5 +-
.../DependenciesToModuleDescriptorConverter.java | 3 -
.../dependencies/DependencyDescriptorFactory.java | 3 -
...ternalModuleIvyDependencyDescriptorFactory.java | 3 -
.../ModuleDescriptorFactoryForClientModule.java | 3 -
.../ProjectIvyDependencyDescriptorFactory.java | 9 +-
.../DefaultProjectModuleRegistry.java | 23 +-
.../projectmodule/ProjectDependencyResolver.java | 55 +-
.../projectmodule/ProjectModuleRegistry.java | 4 +-
.../DefaultResolutionStrategy.java | 3 -
.../LatestConflictResolution.java | 2 -
.../ModuleForcingResolveRule.java | 3 -
.../StrictConflictResolution.java | 2 -
.../resolveengine/DefaultDependencyResolver.java | 72 +-
.../DefaultDependencyToConfigurationResolver.java | 78 +++
.../resolveengine/DependencyGraphBuilder.java | 548 +++++++--------
.../DependencyToConfigurationResolver.java | 30 +
.../LatestModuleConflictResolver.java | 19 +-
.../resolveengine/ModuleConflictResolver.java | 2 +-
.../resolveengine/ModuleRevisionResolveState.java | 5 +-
.../resolveengine/StrictConflictResolver.java | 2 +-
.../VersionSelectionReasonResolver.java | 7 +-
.../DefaultResolvedConfigurationBuilder.java | 134 ++++
.../DefaultTransientConfigurationResults.java | 45 ++
.../oldresult/ResolvedConfigurationBuilder.java | 43 ++
.../oldresult/ResolvedConfigurationResults.java | 32 +
.../oldresult/ResolvedContentsMapping.java | 28 +
.../oldresult/TransientConfigurationResults.java | 32 +
.../oldresult/TransientResultsStore.java | 185 +++++
.../result/CachingDependencyResultFactory.java | 6 +-
.../result/DefaultInternalDependencyResult.java | 59 ++
.../result/DefaultModuleVersionSelection.java | 38 +
.../result/InternalDependencyResult.java | 3 -
.../result/InternalDependencyResultSerializer.java | 61 ++
.../result/ModuleVersionSelection.java | 3 -
.../ModuleVersionSelectionReasonSerializer.java | 59 ++
.../result/ModuleVersionSelectionSerializer.java | 43 ++
.../result/ResolutionResultBuilder.java | 24 +-
.../result/ResolvedConfigurationListener.java | 6 +-
.../result/StreamingResolutionResultBuilder.java | 196 ++++++
.../result/VersionSelectionReasons.java | 3 -
.../resolveengine/store/CachedStoreFactory.java | 101 +++
.../resolveengine/store/DefaultBinaryStore.java | 138 ++++
.../resolveengine/store/EncodedWriteAction.java | 31 +
.../store/ResolutionResultsStoreFactory.java | 103 +++
.../DefaultLocalMavenRepositoryLocator.java | 7 +-
.../mvnsettings/DefaultMavenFileLocations.java | 3 -
.../mvnsettings/DefaultMavenSettingsProvider.java | 3 -
.../repositories/DefaultBaseRepositoryFactory.java | 47 +-
.../DefaultFlatDirArtifactRepository.java | 45 +-
.../repositories/DefaultIvyArtifactRepository.java | 37 +-
.../DefaultMavenArtifactRepository.java | 27 +-
.../FixedResolverArtifactRepository.java | 10 +-
.../repositories/LegacyDependencyResolver.java | 44 +-
.../repositories/LegacyMavenResolver.java | 5 +-
.../repositories/ResolutionAwareRepository.java | 4 +-
.../AbstractRepositoryArtifactCache.java | 20 +
.../AbstractRepositoryCacheManager.java | 86 ---
.../DownloadingRepositoryArtifactCache.java | 73 ++
.../DownloadingRepositoryCacheManager.java | 164 -----
.../EnhancedArtifactDownloadReport.java | 38 -
.../LocalFileRepositoryArtifactCache.java | 43 ++
.../LocalFileRepositoryCacheManager.java | 88 ---
.../cachemanager/RepositoryArtifactCache.java | 45 ++
.../repositories/layout/MavenRepositoryLayout.java | 2 +-
.../legacy/AbstractRepositoryCacheManager.java | 85 +++
.../legacy/CustomIvyResolverRepositoryFactory.java | 42 ++
.../legacy/DownloadingRepositoryCacheManager.java | 155 +++++
.../legacy/EnhancedArtifactDownloadReport.java | 38 +
.../LegacyDependencyResolverRepositoryFactory.java | 24 +
.../legacy/LegacyResolverParserSettings.java | 98 +++
.../legacy/LocalFileRepositoryCacheManager.java | 88 +++
.../repositories/resolver/AbstractVersionList.java | 40 +-
.../resolver/ChainedVersionLister.java | 16 +-
.../resolver/ComponentMetadataDetailsAdapter.java | 58 ++
.../repositories/resolver/DefaultVersionList.java | 21 +-
.../resolver/ExternalResourceResolver.java | 771 +++++++--------------
...rnalResourceResolverDescriptorParseContext.java | 58 ++
.../repositories/resolver/IvyResolver.java | 15 +-
.../repositories/resolver/MavenMetadataLoader.java | 37 +-
.../repositories/resolver/MavenResolver.java | 45 +-
.../repositories/resolver/MavenVersionLister.java | 8 +-
.../resolver/PatternBasedResolver.java | 4 +-
.../resolver/ResourceVersionLister.java | 8 +-
.../repositories/resolver/VersionList.java | 39 +-
.../repositories/resolver/VersionLister.java | 6 +-
.../transport/RepositoryTransportFactory.java | 10 +-
.../artifacts/result/AbstractDependencyResult.java | 3 -
.../artifacts/result/DefaultResolutionResult.java | 20 +-
.../result/DefaultResolvedDependencyResult.java | 3 -
.../result/DefaultResolvedModuleVersionResult.java | 8 -
.../result/DefaultUnresolvedDependencyResult.java | 3 -
.../externalresource/AbstractExternalResource.java | 24 +-
.../DefaultLocallyAvailableExternalResource.java | 48 ++
.../externalresource/ExternalResource.java | 60 +-
.../LocallyAvailableExternalResource.java | 34 +-
.../externalresource/UrlExternalResource.java | 65 ++
.../ArtifactAtRepositoryCachedArtifactIndex.java | 67 +-
.../ivy/ArtifactAtRepositoryKey.java | 31 +-
.../CompositeLocallyAvailableResourceFinder.java | 1 +
.../local/DefaultLocallyAvailableResource.java | 65 --
.../LazyLocallyAvailableResourceCandidates.java | 2 +
.../local/LocallyAvailableResource.java | 31 -
.../local/LocallyAvailableResourceCandidates.java | 1 +
.../local/LocallyAvailableResourceFinder.java | 2 +-
...leResourceFinderSearchableFileStoreAdapter.java | 10 +-
.../ivy/LocallyAvailableResourceFinderFactory.java | 11 +-
.../DefaultCacheAwareExternalResourceAccessor.java | 6 +-
.../ProgressLoggingExternalResourceAccessor.java | 15 +-
.../transport/file/FileResourceConnector.java | 11 +-
.../transport/file/FileTransport.java | 6 +-
.../http/ApacheDirectoryListingParser.java | 9 +-
.../transport/http/HttpResourceLister.java | 33 +-
.../transport/http/HttpTransport.java | 6 +-
.../ClientModuleNotationParserFactory.java | 3 -
.../notations/DependencyMapNotationParser.java | 5 +-
.../notations/DependencyNotationParser.java | 3 -
.../notations/DependencyProjectNotationParser.java | 3 -
.../notations/DependencyStringNotationParser.java | 3 -
.../notations/ProjectDependencyFactory.java | 3 -
.../gradle/api/artifacts/ArtifactsTestUtils.java | 62 --
.../artifacts/DefaultArtifactIdentifierTest.groovy | 46 ++
.../DefaultDependencyManagementServicesTest.groovy | 1 +
.../DefaultModuleVersionSelectorTest.groovy | 16 +-
.../artifacts/DefaultResolvedArtifactTest.groovy | 29 +-
.../artifacts/DefaultResolvedDependencySpec.groovy | 2 +-
.../artifacts/DefaultResolvedDependencyTest.java | 74 +-
.../ModuleVersionSelectorSerializerTest.groovy | 33 +
...vedConfigurationIdentifierSerializerTest.groovy | 37 +
.../ResolvedConfigurationIdentifierSpec.groovy | 14 +-
.../internal/artifacts/ResolverResultsSpec.groovy | 3 -
.../configurations/ConfigurationsTest.java | 8 -
.../DefaultConfigurationContainerSpec.groovy | 2 +-
.../DefaultConfigurationContainerTest.groovy | 33 +-
.../configurations/DefaultConfigurationTest.java | 12 +-
.../internal/artifacts/dsl/ArtifactFileTest.groovy | 3 -
.../dsl/DefaultArtifactHandlerTest.groovy | 7 +-
.../dsl/ModuleVersionSelectorParsersTest.groovy | 3 -
...PublishArtifactNotationParserFactoryTest.groovy | 3 -
...efaultBuildableArtifactResolveResultTest.groovy | 5 +-
.../DefaultDependencyResolveDetailsSpec.groovy | 5 +-
.../ivyservice/DefaultIvyContextManagerTest.groovy | 225 ++++++
.../ivyservice/DefaultIvyFactoryTest.groovy | 40 --
.../ivyservice/DefaultSettingsConverterTest.groovy | 114 ---
.../DefaultUnresolvedDependencySpec.groovy | 3 -
...orHandlingArtifactDependencyResolverTest.groovy | 61 +-
.../ivyservice/IvyBackedArtifactPublisherTest.java | 173 -----
.../ivyservice/IvySettingsFactoryTest.groovy | 37 -
.../artifacts/ivyservice/IvyUtilTest.groovy | 4 +-
.../ModuleVersionNotFoundExceptionTest.groovy | 6 +-
.../ModuleVersionResolveExceptionTest.groovy | 6 +-
.../ivyservice/ResolvedArtifactFactoryTest.groovy | 23 +-
.../clientmodule/ClientModuleResolverTest.groovy | 9 +-
.../CachingModuleVersionRepositoryTest.groovy | 46 +-
...leModuleVersionMetaDataResolveResultTest.groovy | 428 ++++++++++++
...efaultBuildableModuleVersionMetaDataTest.groovy | 244 -------
.../DependencyResolverIdentifierTest.groovy | 15 +-
...ynamicResolveModuleVersionRepositoryTest.groovy | 10 +-
.../LazyDependencyToModuleResolverTest.groovy | 9 +-
.../ivyresolve/UserResolverChainTest.groovy | 26 +-
.../memcache/CachedModuleVersionResultTest.groovy | 85 +++
.../memcache/CachedRepositoryTest.groovy | 117 ++++
.../memcache/DependencyMetadataCacheTest.groovy | 126 ++++
.../InMemoryDependencyMetadataCacheTest.groovy | 76 ++
.../DownloadedIvyModuleDescriptorParserTest.groovy | 11 +-
.../GradlePomModuleDescriptorParserTest.groovy | 81 ++-
.../parser/IvyXmlModuleDescriptorParserTest.groovy | 245 ++++++-
.../strategy/ChainVersionMatcherTest.groovy | 129 ++++
.../strategy/ExactVersionMatcherTest.groovy | 181 +++++
.../strategy/LatestVersionMatcherTest.groovy | 83 +++
.../strategy/LatestVersionStrategyTest.groovy | 78 +++
.../strategy/SubVersionMatcherTest.groovy | 84 +++
.../strategy/VersionRangeMatcherTest.groovy | 208 ++++++
.../modulecache/ModuleDescriptorStoreTest.groovy | 10 +-
...ltArtifactsToModuleDescriptorConverterTest.java | 63 +-
...figurationsToModuleDescriptorConverterTest.java | 14 +-
.../DefaultExcludeRuleConverterTest.java | 3 -
.../DefaultModuleDescriptorFactoryTest.groovy | 38 +-
.../moduleconverter/IvyConverterTestUtil.java | 3 -
.../PublishModuleDescriptorConverterTest.groovy | 20 +-
.../ResolveModuleDescriptorConverterTest.groovy | 19 +-
...actDependencyDescriptorFactoryInternalTest.java | 7 +-
...lientModuleDependencyDescriptorFactoryTest.java | 3 -
...ependenciesToModuleDescriptorConverterTest.java | 7 +-
...ModuleDescriptorFactoryForClientModuleTest.java | 3 -
...ernalModuleDependencyDescriptorFactoryTest.java | 3 -
.../ProjectDependencyDescriptorFactoryTest.groovy | 64 ++
.../ProjectDependencyDescriptorFactoryTest.java | 65 --
...eflectiveDependencyDescriptorFactoryTest.groovy | 5 +-
.../ProjectDependencyResolverTest.groovy | 39 +-
.../DefaultResolutionStrategySpec.groovy | 3 -
.../ModuleForcingResolveRuleSpec.groovy | 3 -
.../DependencyGraphBuilderTest.groovy | 192 ++---
.../VersionSelectionReasonResolverTest.groovy | 10 +-
.../CachingDependencyResultFactoryTest.groovy | 7 +-
.../resolveengine/result/DummyBinaryStore.groovy | 48 ++
.../resolveengine/result/DummyStore.groovy | 24 +
.../InternalDependencyResultSerializerTest.groovy | 80 +++
...duleVersionSelectionReasonSerializerTest.groovy | 54 ++
.../ModuleVersionSelectionSerializerTest.groovy | 37 +
.../result/ResolutionResultBuilderSpec.groovy | 58 +-
.../result/ResolutionResultPrinter.groovy | 47 ++
.../StreamingResolutionResultBuilderTest.groovy | 137 ++++
.../result/VersionSelectionReasonsTest.groovy | 3 -
.../store/CachedStoreFactoryTest.groovy | 40 ++
.../store/DefaultBinaryStoreTest.groovy | 82 +++
.../store/ResolutionResultsStoreFactoryTest.groovy | 88 +++
.../DefaultLocalMavenRepositoryLocatorTest.groovy | 4 +-
.../DefaultBaseRepositoryFactoryTest.groovy | 165 +++--
.../DefaultFlatDirArtifactRepositoryTest.groovy | 32 +-
.../DefaultIvyArtifactRepositoryTest.groovy | 78 ++-
.../DefaultMavenArtifactRepositoryTest.groovy | 54 +-
.../DownloadingRepositoryCacheManagerTest.groovy | 71 --
.../DownloadingRepositoryCacheManagerTest.groovy | 66 ++
.../resolver/ChainedVersionListerTest.groovy | 38 +-
.../resolver/ExternalResourceResolverTest.groovy | 63 +-
.../repositories/resolver/MavenResolverTest.groovy | 6 +-
.../resolver/MavenVersionListerTest.groovy | 65 +-
.../resolver/ResourceVersionListerTest.groovy | 47 +-
.../DefaultArtifactResolutionCacheTest.groovy | 80 ---
.../result/DefaultResolutionResultTest.groovy | 16 +-
.../DefaultResolvedModuleVersionResultSpec.groovy | 4 -
.../CachedExternalResourceAdapterTest.groovy | 83 ---
.../CachedExternalResourceAdapterTest.groovy | 82 +++
.../DefaultArtifactResolutionCacheTest.groovy | 79 +++
...ifactAtRepositoryCachedArtifactIndexTest.groovy | 10 +-
...positeLocallyAvailableResourceFinderTest.groovy | 1 +
.../DefaultLocallyAvailableResourceTest.groovy | 66 --
...ltCacheAwareExternalResourceAccessorTest.groovy | 6 +-
...gressLoggingExternalResourceAccessorTest.groovy | 15 +-
.../http/ApacheDirectoryListingParserTest.groovy | 16 +-
.../transport/http/HttpResourceListerTest.groovy | 3 +-
.../DependencyMapNotationParserTest.groovy | 8 +-
.../notations/DependencyNotationParserTest.groovy | 3 -
.../DependencyStringNotationParserTest.groovy | 12 +-
.../notations/ProjectDependencyFactoryTest.groovy | 3 -
.../ivyresolve/parser/test-bad-confs.xml | 27 -
.../ivyresolve/parser/test-cyclic-confs1.xml | 28 -
.../ivyresolve/parser/test-empty-dependencies.xml | 28 -
.../ivyservice/ivyresolve/parser/test-full.xml | 4 +-
.../result/ResolutionResultDataBuilder.groovy | 5 +-
subprojects/core/core.gradle | 6 +-
.../DeprecationHandlingIntegrationTest.groovy | 125 ++++
.../org/gradle/api/ApplyPluginIntegSpec.groovy | 84 +++
.../api/BuildScriptErrorIntegrationTest.groovy | 98 +++
.../ConfigurationOnDemandIntegrationTest.groovy | 95 ++-
.../api/CrossProcessFileLockIntegrationTest.groovy | 71 ++
...rredConfigurableExtensionIntegrationTest.groovy | 174 +++++
.../api/ExternalScriptErrorIntegrationTest.groovy | 87 +++
.../gradle/api/FinalizerTaskIntegrationTest.groovy | 248 +++++++
.../gradle/api/GradlePluginIntegrationTest.groovy | 97 +++
.../api/InitScriptErrorIntegrationTest.groovy | 58 ++
.../org/gradle/api/ProfilingIntegrationTest.groovy | 46 ++
.../api/ProjectConfigurationIntegrationTest.groovy | 3 -
...ojectConfigureEventsErrorIntegrationTest.groovy | 114 +++
.../api/SettingsPluginIntegrationSpec.groovy | 83 +++
.../api/SettingsScriptErrorIntegrationTest.groovy | 41 ++
.../api/dsl/ConcurrentClassDecorationSpec.groovy | 48 ++
.../gradle/api/tasks/ArchiveIntegrationTest.groovy | 80 ++-
.../api/tasks/CopyTaskIntegrationSpec.groovy | 89 +++
.../api/tasks/CopyTaskIntegrationTest.groovy | 74 ++
...kCommandLineConfigurationIntegrationSpec.groovy | 249 +++++++
.../api/tasks/bundling/ZipIntegrationTest.groovy | 100 +++
.../internal/PathLimitationIntegTest.groovy | 277 ++++++++
.../internal/WorkerProcessIntegrationTest.java | 3 +-
.../src/main/groovy/org/gradle/BuildListener.java | 4 +-
.../src/main/groovy/org/gradle/CacheUsage.java | 1 -
.../src/main/groovy/org/gradle/GradleLauncher.java | 45 +-
.../src/main/groovy/org/gradle/StartParameter.java | 57 +-
.../groovy/org/gradle/TaskExecutionLogger.java | 2 +-
.../org/gradle/api/CircularReferenceException.java | 2 -
.../main/groovy/org/gradle/api/DefaultTask.java | 2 -
...ExtensiblePolymorphicDomainObjectContainer.java | 28 +
.../org/gradle/api/GradleScriptException.java | 2 -
.../org/gradle/api/IllegalDependencyNotation.java | 2 -
.../IllegalOperationAtExecutionTimeException.java | 3 +-
.../org/gradle/api/InvalidUserDataException.java | 2 -
.../gradle/api/NamedDomainObjectCollection.java | 14 +-
.../org/gradle/api/NamedDomainObjectContainer.java | 10 +
.../main/groovy/org/gradle/api/NonExtensible.java | 31 +
.../src/main/groovy/org/gradle/api/Plugin.java | 3 +-
.../src/main/groovy/org/gradle/api/Project.java | 11 +-
.../gradle/api/ProjectConfigurationException.java | 29 +
.../org/gradle/api/ProjectEvaluationListener.java | 2 -
.../main/groovy/org/gradle/api/ProjectState.java | 3 +
.../core/src/main/groovy/org/gradle/api/Rule.java | 2 -
.../core/src/main/groovy/org/gradle/api/Task.java | 109 ++-
.../org/gradle/api/UnknownProjectException.java | 2 -
.../org/gradle/api/UnknownTaskException.java | 2 -
.../main/groovy/org/gradle/api/XmlProvider.java | 2 -
.../gradle/api/artifacts/ArtifactIdentifier.java | 12 +-
.../api/artifacts/ArtifactRepositoryContainer.java | 42 +-
.../org/gradle/api/artifacts/ClientModule.java | 2 -
.../api/artifacts/ComponentMetadataDetails.java | 86 +++
.../api/artifacts/ConfigurationContainer.java | 14 +-
.../org/gradle/api/artifacts/Dependency.java | 5 +-
.../gradle/api/artifacts/DependencyArtifact.java | 6 +-
.../org/gradle/api/artifacts/ExcludeRule.java | 4 +-
.../gradle/api/artifacts/ExcludeRuleContainer.java | 2 -
.../gradle/api/artifacts/ExternalDependency.java | 2 -
.../api/artifacts/ExternalModuleDependency.java | 2 -
.../groovy/org/gradle/api/artifacts/Module.java | 2 -
.../gradle/api/artifacts/ProjectDependency.java | 4 +-
.../org/gradle/api/artifacts/PublishArtifact.java | 6 +-
.../org/gradle/api/artifacts/ResolveException.java | 2 -
.../org/gradle/api/artifacts/ResolvedArtifact.java | 2 -
.../gradle/api/artifacts/ResolvedDependency.java | 2 -
.../api/artifacts/UnknownRepositoryException.java | 2 -
.../gradle/api/artifacts/dsl/ArtifactHandler.java | 2 -
.../artifacts/dsl/ComponentMetadataHandler.java | 54 ++
.../api/artifacts/dsl/DependencyHandler.java | 35 +-
.../api/artifacts/dsl/RepositoryHandler.java | 71 +-
.../repositories/IvyArtifactRepository.java | 2 +-
.../gradle/api/component/SoftwareComponent.java | 3 +-
.../org/gradle/api/dsl/ConventionProperty.java | 2 -
.../gradle/api/execution/TaskExecutionAdapter.java | 2 +-
.../groovy/org/gradle/api/file/CopySourceSpec.java | 2 -
.../main/groovy/org/gradle/api/file/CopySpec.java | 53 +-
.../groovy/org/gradle/api/file/DeleteAction.java | 2 -
.../api/file/DuplicateFileCopyingException.java | 35 +
.../org/gradle/api/file/DuplicatesStrategy.java | 59 ++
.../org/gradle/api/file/EmptyFileVisitor.java | 2 -
.../org/gradle/api/file/FileCopyDetails.java | 24 +
.../main/groovy/org/gradle/api/file/FileTree.java | 2 +-
.../groovy/org/gradle/api/file/FileVisitor.java | 2 -
.../groovy/org/gradle/api/file/RelativePath.java | 2 -
.../api/initialization/ProjectDescriptor.java | 2 -
.../org/gradle/api/initialization/Settings.java | 5 +-
.../api/internal/AbstractClassGenerator.java | 12 +
.../AbstractNamedDomainObjectContainer.java | 12 +-
.../AbstractPolymorphicDomainObjectContainer.java | 8 +-
.../org/gradle/api/internal/AbstractTask.java | 65 +-
.../api/internal/AsmBackedClassGenerator.java | 177 +++--
.../org/gradle/api/internal/BeanDynamicObject.java | 60 +-
.../api/internal/CachingDirectedGraphWalker.java | 176 -----
.../internal/ClassGeneratorBackedInstantiator.java | 2 +-
.../api/internal/CompositeDomainObjectSet.java | 8 +-
.../gradle/api/internal/ConventionAwareHelper.java | 17 +-
.../org/gradle/api/internal/ConventionTask.java | 3 -
.../DefaultNamedDomainObjectCollection.java | 8 +
.../DefaultPolymorphicDomainObjectContainer.java | 45 +-
.../internal/DependencyInjectingInstantiator.java | 2 +-
.../org/gradle/api/internal/DirectedGraph.java | 26 -
.../api/internal/DirectedGraphWithEdgeValues.java | 25 -
.../gradle/api/internal/DocumentationRegistry.java | 29 +-
.../org/gradle/api/internal/GradleInternal.java | 14 +-
.../org/gradle/api/internal/GraphAggregator.java | 90 ---
.../org/gradle/api/internal/IConventionAware.java | 2 -
...amedDomainObjectContainerConfigureDelegate.java | 6 +-
...phicDomainObjectContainerConfigureDelegate.java | 14 +-
.../org/gradle/api/internal/SettingsInternal.java | 4 +-
.../org/gradle/api/internal/TaskInternal.java | 8 +-
.../gradle/api/internal/TaskOutputsInternal.java | 1 +
.../artifacts/ArtifactPublicationServices.java | 7 -
.../api/internal/artifacts/ArtifactPublisher.java | 3 -
.../internal/artifacts/BaseRepositoryFactory.java | 2 +
.../artifacts/CachingDependencyResolveContext.java | 6 +-
.../artifacts/DefaultArtifactIdentifier.java | 55 --
.../DefaultArtifactRepositoryContainer.java | 8 +-
.../api/internal/artifacts/DefaultExcludeRule.java | 5 -
.../artifacts/DefaultExcludeRuleContainer.java | 3 -
.../api/internal/artifacts/DefaultModule.java | 3 -
.../artifacts/DependencyResolutionServices.java | 3 +
.../DependencyResolveDetailsInternal.java | 3 -
.../artifacts/ExcludeRuleNotationParser.java | 3 -
.../artifacts/ModuleVersionPublishMetaData.java | 32 +
.../internal/artifacts/ModuleVersionPublisher.java | 27 +
.../artifacts/ModuleVersionSelectorStrictSpec.java | 3 -
.../configurations/ConfigurationInternal.java | 2 +
.../configurations/DependencyMetaDataProvider.java | 3 -
.../artifacts/dependencies/AbstractDependency.java | 5 +-
.../dependencies/DefaultClientModule.java | 3 -
.../DefaultExternalModuleDependency.java | 3 -
.../dependencies/DefaultProjectDependency.java | 9 +-
.../dependencies/ProjectDependencyInternal.java | 28 +
.../artifacts/dsl/DefaultRepositoryHandler.java | 19 +-
.../dependencies/DefaultDependencyHandler.groovy | 23 +-
.../dsl/dependencies/DependencyFactory.java | 3 -
.../dependencies/ModuleDescriptorDelegate.groovy | 3 -
.../dsl/dependencies/ModuleFactoryHelper.java | 5 +-
.../artifacts/dsl/dependencies/ProjectFinder.java | 3 -
.../ivyservice/ModuleDescriptorConverter.java | 35 -
.../artifacts/publish/AbstractPublishArtifact.java | 3 -
.../artifacts/publish/ArchivePublishArtifact.java | 3 -
.../artifacts/publish/DefaultPublishArtifact.java | 3 -
.../repositories/PublicationAwareRepository.java | 4 +-
.../version/LatestVersionSemanticComparator.java | 49 --
.../org/gradle/api/internal/cache/BinaryStore.java | 41 ++
.../org/gradle/api/internal/cache/Store.java | 22 +
.../CacheBackedFileSnapshotRepository.java | 44 --
.../CacheBackedTaskHistoryRepository.java | 174 -----
.../CacheLockHandlingTaskExecuter.java | 38 -
.../internal/changedetection/CachingHasher.java | 78 ---
.../changedetection/CompositeUpToDateRule.java | 52 --
.../changedetection/DefaultFileCacheListener.java | 45 --
.../changedetection/DefaultFileSnapshotter.java | 158 -----
.../internal/changedetection/DefaultHasher.java | 26 -
.../DefaultTaskArtifactStateCacheAccess.java | 85 ---
.../DefaultTaskArtifactStateRepository.java | 172 -----
...eCacheBroadcastTaskArtifactStateRepository.java | 63 --
.../changedetection/FileCacheListener.java | 35 -
.../changedetection/FileCollectionSnapshot.java | 59 --
.../changedetection/FileSnapshotRepository.java | 24 -
.../internal/changedetection/FileSnapshotter.java | 35 -
.../api/internal/changedetection/Hasher.java | 22 -
.../changedetection/InMemoryIndexedCache.java | 65 --
.../InputFilesChangedUpToDateRule.java | 63 --
.../InputPropertiesChangedUpToDateRule.java | 55 --
.../changedetection/MapMergeChangeListener.java | 67 --
.../OutputFilesChangedUpToDateRule.java | 85 ---
.../changedetection/OutputFilesSnapshotter.java | 154 ----
.../ShortCircuitTaskArtifactStateRepository.java | 96 ---
.../changedetection/TaskArtifactState.java | 11 +-
.../TaskArtifactStateCacheAccess.java | 50 --
.../TaskCacheLockHandlingBuildExecuter.java | 35 -
.../internal/changedetection/TaskExecution.java | 67 --
.../changedetection/TaskHistoryRepository.java | 30 -
.../TaskTypeChangedUpToDateRule.java | 42 --
.../api/internal/changedetection/UpToDateRule.java | 48 --
.../changes/ChangesOnlyIncrementalTaskInputs.java | 57 ++
.../DefaultTaskArtifactStateRepository.java | 133 ++++
.../changes/NoHistoryArtifactState.java | 52 ++
.../changes/RebuildIncrementalTaskInputs.java | 73 ++
.../ShortCircuitTaskArtifactStateRepository.java | 96 +++
.../changes/StatefulIncrementalTaskInputs.java | 49 ++
.../rules/CachingTaskStateChanges.java | 86 +++
.../internal/changedetection/rules/ChangeType.java | 33 +
.../changedetection/rules/DescriptiveChange.java | 29 +
.../internal/changedetection/rules/FileChange.java | 60 ++
.../changedetection/rules/InputFileChange.java | 31 +
.../rules/InputFilesStateChangeRule.java | 77 ++
.../rules/InputPropertiesStateChangeRule.java | 54 ++
.../rules/NoHistoryStateChangeRule.java | 35 +
.../changedetection/rules/OutputFileChange.java | 29 +
.../rules/OutputFilesStateChangeRule.java | 100 +++
.../rules/SimpleTaskStateChanges.java | 38 +
.../rules/SummaryTaskStateChanges.java | 76 ++
.../changedetection/rules/TaskStateChange.java | 21 +
.../changedetection/rules/TaskStateChanges.java | 25 +
.../rules/TaskTypeStateChangeRule.java | 43 ++
.../changedetection/rules/TaskUpToDateState.java | 66 ++
.../state/CacheBackedFileSnapshotRepository.java | 44 ++
.../state/CacheBackedTaskHistoryRepository.java | 273 ++++++++
.../changedetection/state/CachingHasher.java | 76 ++
.../state/DefaultFileSnapshotter.java | 185 +++++
.../state/DefaultFileSnapshotterSerializer.java | 68 ++
.../changedetection/state/DefaultHasher.java | 26 +
.../state/DefaultTaskArtifactStateCacheAccess.java | 80 +++
.../state/FileCollectionSnapshot.java | 61 ++
.../state/FileSnapshotRepository.java | 24 +
.../state/FileSnapshotSerializer.java | 52 ++
.../changedetection/state/FileSnapshotter.java | 35 +
.../api/internal/changedetection/state/Hasher.java | 22 +
.../state/MapMergeChangeListener.java | 67 ++
.../state/OutputFilesSnapshotSerializer.java | 61 ++
.../state/OutputFilesSnapshotter.java | 218 ++++++
.../state/TaskArtifactStateCacheAccess.java | 48 ++
.../changedetection/state/TaskExecution.java | 66 ++
.../state/TaskHistoryRepository.java | 30 +
.../internal/classpath/DefaultModuleRegistry.java | 2 +-
.../api/internal/classpath/EffectiveClassPath.java | 2 +-
.../api/internal/classpath/ManifestUtil.java | 1 -
.../coerce/MethodArgumentsTransformer.java | 36 +
.../TypeCoercingMethodArgumentsTransformer.java | 109 +++
.../api/internal/coerce/TypeCoercionException.java | 28 +
.../api/internal/file/AbstractFileResolver.java | 8 +
.../api/internal/file/AbstractFileResource.java | 3 -
.../internal/file/AntFileCollectionBuilder.groovy | 5 +-
.../api/internal/file/BaseDirFileResolver.java | 3 -
.../file/CopyActionProcessingStreamAction.java | 25 +
.../internal/file/DefaultCompositeFileTree.java | 45 ++
.../api/internal/file/DefaultFileOperations.java | 42 +-
.../file/DefaultTemporaryFileProvider.java | 3 +-
.../gradle/api/internal/file/FileOperations.java | 6 +
.../org/gradle/api/internal/file/FileResolver.java | 8 +
.../org/gradle/api/internal/file/FileResource.java | 3 -
.../api/internal/file/IdentityFileResolver.java | 7 +-
.../internal/file/MaybeCompressedFileResource.java | 3 -
.../api/internal/file/archive/TarCopyAction.java | 117 ++++
.../internal/file/archive/TarCopySpecVisitor.java | 88 ---
.../api/internal/file/archive/ZipCopyAction.java | 89 ++-
.../internal/file/archive/ZipCopySpecVisitor.java | 81 ---
.../file/archive/compression/Bzip2Archiver.java | 3 -
.../file/archive/compression/GzipArchiver.java | 3 -
.../file/archive/compression/SimpleCompressor.java | 3 -
.../collections/DefaultConfigurableFileTree.java | 39 +-
.../file/collections/DelegatingFileCollection.java | 111 +++
.../file/collections/DirectoryFileTree.java | 4 +-
.../LazilyInitializedFileCollection.java | 35 +
.../collections/SingleIncludePatternFileTree.java | 1 -
.../internal/file/copy/AbstractZipCompressor.java | 2 +
.../api/internal/file/copy/ArchiveCopyAction.java | 25 -
.../gradle/api/internal/file/copy/CopyAction.java | 49 +-
.../api/internal/file/copy/CopyActionExecuter.java | 41 ++
.../api/internal/file/copy/CopyActionImpl.java | 235 +------
.../file/copy/CopyActionProcessingStream.java | 25 +
.../CopySpecBackedCopyActionProcessingStream.java | 68 ++
.../api/internal/file/copy/CopySpecImpl.java | 461 ------------
.../api/internal/file/copy/CopySpecInternal.java | 45 ++
.../api/internal/file/copy/CopySpecSource.java | 2 +-
.../api/internal/file/copy/CopySpecVisitor.java | 36 -
.../api/internal/file/copy/DefaultCopySpec.java | 462 ++++++++++++
.../internal/file/copy/DefaultFileCopyDetails.java | 218 ++++++
.../api/internal/file/copy/DelegatingCopySpec.java | 224 ++++++
.../file/copy/DelegatingCopySpecVisitor.java | 54 --
.../api/internal/file/copy/DeleteActionImpl.java | 3 -
.../file/copy/DestinationRootCopySpec.java | 51 ++
.../copy/DuplicateHandlingCopyActionDecorator.java | 66 ++
.../internal/file/copy/EmptyCopySpecVisitor.java | 39 --
.../gradle/api/internal/file/copy/FileCopier.java | 66 ++
.../api/internal/file/copy/FileCopyAction.java | 32 +-
.../api/internal/file/copy/FileCopyActionImpl.java | 33 +-
.../file/copy/FileCopyDetailsInternal.java | 25 +
.../internal/file/copy/FileCopySpecVisitor.java | 61 --
.../internal/file/copy/MappingCopySpecVisitor.java | 230 ------
.../api/internal/file/copy/MatchingCopyAction.java | 40 ++
.../file/copy/NormalizingCopyActionDecorator.java | 189 +++++
.../file/copy/NormalizingCopySpecVisitor.java | 121 ----
.../api/internal/file/copy/ReadableCopySpec.java | 32 +-
.../api/internal/file/copy/RegExpNameMapper.java | 3 -
.../internal/file/copy/RelativizedCopySpec.java | 51 ++
.../file/copy/SyncCopyActionDecorator.java | 92 +++
.../internal/file/copy/SyncCopySpecVisitor.java | 90 ---
.../file/pattern/DefaultPatternMatcher.java | 5 +-
.../internal/file/pattern/GreedyPatternStep.java | 3 -
.../file/pattern/NameOnlyPatternMatcher.java | 1 -
.../file/pattern/PatternMatcherFactory.java | 3 -
.../api/internal/file/pattern/PatternStep.java | 3 -
.../internal/file/pattern/RegExpPatternStep.java | 3 -
.../internal/filestore/AbstractFileStoreEntry.java | 28 -
.../gradle/api/internal/filestore/FileStore.java | 31 -
.../api/internal/filestore/FileStoreEntry.java | 29 -
.../api/internal/filestore/FileStoreSearcher.java | 25 -
.../filestore/GroupedAndNamedUniqueFileStore.java | 11 +-
.../api/internal/filestore/PathKeyFileStore.java | 26 +-
.../filestore/PathNormalisingKeyFileStore.java | 11 +-
.../internal/filestore/UniquePathKeyFileStore.java | 7 +-
.../initialization/AbstractScriptHandler.java | 4 +-
.../initialization/DefaultScriptHandler.java | 2 +-
.../DefaultScriptHandlerFactory.java | 2 +-
.../NoClassLoaderUpdateScriptHandler.java | 2 +-
.../internal/notations/NotationParserBuilder.java | 3 -
.../gradle/api/internal/notations/TypeInfo.java | 4 +-
.../api/internal/notations/api/NotationParser.java | 3 -
.../parsers/ClosureToSpecNotationParser.java | 3 -
.../notations/parsers/CompositeNotationParser.java | 3 -
.../parsers/ErrorHandlingNotationParser.java | 3 -
.../notations/parsers/JustReturningParser.java | 3 -
.../notations/parsers/MapNotationParser.java | 2 +-
.../notations/parsers/NormalizedTimeUnit.java | 3 -
.../notations/parsers/TimeUnitsParser.java | 3 -
.../notations/parsers/TypedNotationParser.java | 9 +-
.../api/internal/plugins/DefaultConvention.java | 11 +-
.../plugins/DefaultObjectConfigurationAction.java | 18 +-
.../internal/plugins/DefaultPluginContainer.java | 107 +++
.../internal/plugins/DefaultPluginRegistry.java | 4 -
.../plugins/DefaultProjectsPluginContainer.java | 110 ---
.../plugins/ExtensionContainerInternal.java | 29 +
.../api/internal/plugins/ExtensionsStorage.java | 28 +-
.../api/internal/plugins/PluginRegistry.java | 3 -
.../api/internal/project/AbstractPluginAware.java | 45 ++
.../api/internal/project/AbstractProject.java | 76 +-
.../api/internal/project/DefaultAntBuilder.groovy | 2 +-
.../internal/project/DefaultAntBuilderFactory.java | 3 -
.../project/DefaultIsolatedAntBuilder.groovy | 4 +
.../api/internal/project/DefaultProject.java | 1 +
.../project/DefaultProjectAccessListener.java | 3 -
.../internal/project/DefaultProjectRegistry.java | 9 +-
.../internal/project/GlobalServicesRegistry.java | 113 ---
.../project/GradleInternalServiceRegistry.java | 92 ---
.../api/internal/project/IProjectFactory.java | 2 -
.../api/internal/project/IProjectRegistry.java | 40 --
.../api/internal/project/ProjectFactory.java | 5 +-
.../api/internal/project/ProjectInternal.java | 9 +-
.../project/ProjectInternalServiceRegistry.java | 180 -----
.../api/internal/project/ProjectRegistry.java | 37 +
.../api/internal/project/ProjectStateInternal.java | 4 +
.../internal/project/ServiceRegistryFactory.java | 31 -
.../internal/project/TaskExecutionServices.java | 86 ---
.../project/TaskInternalServiceRegistry.java | 61 --
.../project/TopLevelBuildServiceRegistry.java | 253 -------
.../internal/project/ant/AntLoggingAdapter.java | 3 -
.../AnnotationProcessingTaskFactory.java | 200 ++++--
.../internal/project/taskfactory/ITaskFactory.java | 3 -
.../internal/project/taskfactory/TaskFactory.java | 27 +-
.../internal/resources/DefaultResourceHandler.java | 3 -
.../gradle/api/internal/resources/URIBuilder.java | 3 -
.../gradle/api/internal/specs/ExplainingSpecs.java | 3 -
.../tasks/CachingTaskDependencyResolveContext.java | 6 +-
.../api/internal/tasks/ContextAwareTaskAction.java | 24 +
.../api/internal/tasks/DefaultTaskContainer.java | 109 ++-
.../api/internal/tasks/SimpleWorkResult.java | 30 +
.../api/internal/tasks/TaskContainerInternal.java | 22 +-
.../gradle/api/internal/tasks/TaskExecuter.java | 2 +-
.../api/internal/tasks/TaskExecutionContext.java | 24 +
.../api/internal/tasks/TaskStatusNagger.java | 9 +-
.../execution/DefaultTaskExecutionContext.java | 31 +
.../execution/ExecuteActionsTaskExecuter.java | 26 +-
.../execution/ExecuteAtMostOnceTaskExecuter.java | 5 +-
.../PostExecutionAnalysisTaskExecuter.java | 5 +-
.../SkipEmptySourceFilesTaskExecuter.java | 5 +-
.../tasks/execution/SkipOnlyIfTaskExecuter.java | 5 +-
.../execution/SkipTaskWithNoActionsExecuter.java | 5 +-
.../tasks/execution/SkipUpToDateTaskExecuter.java | 39 +-
.../tasks/execution/ValidatingTaskExecuter.java | 5 +-
.../gradle/api/internal/xml/SimpleXmlWriter.java | 2 -
.../groovy/org/gradle/api/invocation/Gradle.java | 3 +-
.../groovy/org/gradle/api/logging/LogLevel.java | 2 -
.../groovy/org/gradle/api/logging/Logging.java | 2 -
.../groovy/org/gradle/api/plugins/Convention.java | 2 -
.../org/gradle/api/plugins/ExtensionContainer.java | 2 +
.../groovy/org/gradle/api/plugins/PluginAware.java | 62 ++
.../org/gradle/api/plugins/PluginCollection.java | 8 +-
.../org/gradle/api/plugins/PluginContainer.java | 2 -
.../api/plugins/PluginInstantiationException.java | 2 -
.../gradle/api/plugins/UnknownPluginException.java | 2 -
.../main/groovy/org/gradle/api/specs/Specs.java | 2 -
.../org/gradle/api/tasks/AbstractCopyTask.java | 83 ++-
.../org/gradle/api/tasks/AntBuilderAware.groovy | 2 -
.../org/gradle/api/tasks/ConventionValue.java | 1 -
.../src/main/groovy/org/gradle/api/tasks/Copy.java | 79 ++-
.../main/groovy/org/gradle/api/tasks/Delete.java | 2 -
.../src/main/groovy/org/gradle/api/tasks/Exec.java | 2 -
.../groovy/org/gradle/api/tasks/GradleBuild.java | 12 +-
.../main/groovy/org/gradle/api/tasks/JavaExec.java | 5 +-
.../org/gradle/api/tasks/StopActionException.java | 2 -
.../gradle/api/tasks/StopExecutionException.java | 2 -
.../src/main/groovy/org/gradle/api/tasks/Sync.java | 32 +-
.../groovy/org/gradle/api/tasks/TaskContainer.java | 123 +++-
.../main/groovy/org/gradle/api/tasks/Upload.java | 19 +-
.../api/tasks/bundling/AbstractArchiveTask.java | 3 +-
.../org/gradle/api/tasks/bundling/Compression.java | 2 -
.../groovy/org/gradle/api/tasks/bundling/Tar.java | 42 +-
.../groovy/org/gradle/api/tasks/bundling/Zip.java | 59 +-
.../tasks/incremental/IncrementalTaskInputs.java | 122 ++++
.../api/tasks/incremental/InputFileDetails.java | 50 ++
.../gradle/api/tasks/incremental/package-info.java | 20 +
.../org/gradle/api/tasks/util/PatternSet.java | 7 +-
.../groovy/org/gradle/cache/CacheValidator.java | 2 +-
.../gradle/cache/internal/DefaultCacheAccess.java | 233 ++++---
.../cache/internal/DefaultFileLockManager.java | 242 +++++--
.../org/gradle/cache/internal/FileAccess.java | 2 +-
.../groovy/org/gradle/cache/internal/FileLock.java | 5 +
.../cache/internal/FileLockCommunicator.java | 87 +++
.../org/gradle/cache/internal/FileLockManager.java | 9 +
.../cache/internal/GracefullyStoppedException.java | 19 +
.../MultiProcessSafePersistentIndexedCache.java | 2 +-
.../gradle/cache/internal/OnDemandFileAccess.java | 4 +
.../gradle/cache/internal/SimpleStateCache.java | 14 +-
.../btree/BTreePersistentIndexedCache.java | 16 +-
.../cacheops/CacheAccessOperationsStack.java | 90 +++
.../cache/internal/cacheops/CacheOperation.java | 27 +
.../internal/cacheops/CacheOperationStack.java | 70 ++
.../DefaultFileLockContentionHandler.java | 160 +++++
.../locklistener/FileLockContentionHandler.java | 27 +
.../NoOpFileLockContentionHandler.java | 31 +
.../gradle/configuration/BuildScriptProcessor.java | 45 --
.../configuration/DefaultBuildConfigurer.java | 22 +-
.../configuration/DefaultScriptPluginFactory.java | 21 +-
.../configuration/ImplicitTasksConfigurer.java | 13 +-
.../org/gradle/configuration/ImportsReader.java | 34 +-
.../configuration/LifecycleProjectEvaluator.java | 51 --
.../ProjectDependencies2TaskResolver.java | 47 --
.../org/gradle/configuration/ProjectEvaluator.java | 23 -
.../project/BuildScriptProcessor.java | 43 ++
.../project/ConfigureActionsProjectEvaluator.java | 37 +
...DefaultProjectConfigurationActionContainer.java | 45 ++
.../project/DelayedConfigurationActions.java | 33 +
.../project/LifecycleProjectEvaluator.java | 82 +++
.../project/PluginsProjectConfigureActions.java | 34 +
.../ProjectConfigurationActionContainer.java | 40 ++
.../project/ProjectConfigureAction.java | 30 +
.../project/ProjectDependencies2TaskResolver.java | 41 ++
.../configuration/project/ProjectEvaluator.java | 23 +
.../gradle/execution/ProjectEvaluatingAction.java | 2 -
.../org/gradle/execution/TaskNameResolver.java | 47 +-
.../gradle/execution/TaskPathProjectEvaluator.java | 3 -
.../org/gradle/execution/TaskSelectionResult.java | 23 +
.../groovy/org/gradle/execution/TaskSelector.java | 23 +-
.../commandline/CommandLineTaskConfigurer.java | 6 +-
.../commandline/CommandLineTaskParser.java | 3 -
.../taskgraph/AbstractTaskPlanExecutor.java | 87 +++
.../taskgraph/DefaultTaskExecutionPlan.java | 297 ++++++--
.../taskgraph/DefaultTaskGraphExecuter.java | 42 +-
.../taskgraph/DefaultTaskPlanExecutor.java | 45 +-
.../taskgraph/ParallelTaskPlanExecutor.java | 82 +--
.../execution/taskgraph/TaskDependencyGraph.java | 52 ++
.../execution/taskgraph/TaskExecutionPlan.java | 17 +-
.../org/gradle/execution/taskgraph/TaskInfo.java | 112 ++-
.../taskgraph/TaskPlanExecutorFactory.java | 7 +-
.../taskpath/ProjectFinderByTaskPath.java | 3 -
.../execution/taskpath/ResolvedTaskPath.java | 3 -
.../execution/taskpath/TaskPathResolver.java | 3 -
.../org/gradle/groovy/scripts/BasicScript.java | 8 +-
.../org/gradle/groovy/scripts/DefaultScript.java | 18 +-
.../scripts/DefaultScriptCompilerFactory.java | 7 +-
.../groovy/scripts/ScriptCompilerFactory.java | 2 -
.../internal/AsmBackedEmptyScriptGenerator.java | 10 +-
.../internal/ClasspathScriptTransformer.java | 4 +-
.../internal/DefaultScriptCompilationHandler.java | 3 -
.../scripts/internal/ScriptCompilationHandler.java | 3 -
.../gradle/initialization/AbstractProjectSpec.java | 8 +-
.../org/gradle/initialization/BaseSettings.java | 63 +-
.../org/gradle/initialization/BuildAction.java | 31 +
.../org/gradle/initialization/BuildController.java | 45 ++
.../initialization/BuildFileProjectSpec.java | 4 +-
.../initialization/BuildLayoutParameters.java | 25 +-
.../gradle/initialization/BuildSourceBuilder.java | 155 -----
.../gradle/initialization/ClassLoaderRegistry.java | 16 +-
.../initialization/DefaultClassLoaderRegistry.java | 14 +-
.../DefaultCommandLineConverter.java | 34 +-
.../initialization/DefaultGradleLauncher.java | 2 +-
.../DefaultGradleLauncherFactory.java | 28 +-
.../DefaultGradlePropertiesLoader.java | 3 -
.../initialization/DefaultProjectDescriptor.java | 16 +-
.../DefaultProjectDescriptorRegistry.java | 5 +-
.../gradle/initialization/DefaultProjectSpec.java | 4 +-
.../gradle/initialization/DefaultSettings.groovy | 13 +-
.../initialization/DefaultSettingsFinder.java | 3 -
.../initialization/DependencyResolutionLogger.java | 1 -
.../initialization/GradleLauncherAction.java | 43 --
.../initialization/GradleLauncherFactory.java | 2 -
.../initialization/IGradlePropertiesLoader.java | 3 -
.../initialization/IProjectDescriptorRegistry.java | 26 -
.../org/gradle/initialization/ISettingsFinder.java | 3 -
.../initialization/InstantiatingBuildLoader.java | 3 -
.../initialization/LayoutCommandLineConverter.java | 9 +-
.../initialization/ProjectAccessListener.java | 2 -
.../initialization/ProjectDescriptorRegistry.java | 23 +
.../ProjectDirectoryProjectSpec.java | 4 +-
.../ProjectPropertySettingBuildLoader.java | 3 -
.../org/gradle/initialization/ProjectSpec.java | 6 +-
.../PropertiesLoadingSettingsProcessor.java | 6 +-
.../ScriptEvaluatingSettingsProcessor.java | 12 +-
.../org/gradle/initialization/SettingsFactory.java | 17 +-
.../org/gradle/initialization/SettingsHandler.java | 9 +-
.../gradle/initialization/SettingsProcessor.java | 6 +-
.../buildsrc/BuildSourceBuilder.java | 86 +++
.../buildsrc/BuildSrcBuildListenerFactory.java | 61 ++
.../buildsrc/BuildSrcUpdateFactory.java | 61 ++
.../featurelifecycle/DeprecatedFeatureHandler.java | 26 +
.../featurelifecycle/DeprecatedFeatureUsage.java | 77 ++
.../LoggingDeprecatedFeatureHandler.java | 76 ++
.../ScriptUsageLocationReporter.java | 91 +++
.../featurelifecycle/UsageLocationReporter.java | 21 +
.../internal/graph/CachingDirectedGraphWalker.java | 203 ++++++
.../org/gradle/internal/graph/DirectedGraph.java | 26 +
.../internal/graph/DirectedGraphRenderer.java | 80 +++
.../graph/DirectedGraphWithEdgeValues.java | 25 +
.../org/gradle/internal/graph/GraphAggregator.java | 90 +++
.../gradle/internal/graph/GraphNodeRenderer.java | 22 +
.../org/gradle/internal/graph/GraphRenderer.java | 69 ++
.../service/scopes/BuildScopeServices.java | 265 +++++++
.../service/scopes/GlobalScopeServices.java | 148 ++++
.../service/scopes/GradleScopeServices.java | 98 +++
.../service/scopes/PluginServiceRegistry.java | 28 +
.../service/scopes/ProjectScopeServices.java | 200 ++++++
.../service/scopes/ServiceRegistryFactory.java | 31 +
.../service/scopes/SettingsScopeServices.java | 59 ++
.../service/scopes/TaskExecutionServices.java | 93 +++
.../internal/service/scopes/TaskScopeServices.java | 62 ++
.../invocation/BuildClassLoaderRegistry.java | 32 +
.../DefaultBuildClassLoaderRegistry.java | 39 ++
.../org/gradle/invocation/DefaultGradle.java | 54 +-
.../org/gradle/logging/StandardOutputCapture.java | 3 -
.../logging/internal/DefaultLoggingManager.java | 3 -
.../logging/internal/EmbeddedLoggingServices.java | 3 -
.../internal/LoggingCommandLineConverter.java | 59 +-
.../gradle/logging/internal/LoggingConfigurer.java | 3 -
.../gradle/logging/internal/NoOpLoggingSystem.java | 3 -
.../logging/internal/StdErrLoggingSystem.java | 3 -
.../logging/internal/StdOutLoggingSystem.java | 3 -
.../internal/logback/LogbackLoggingConfigurer.java | 6 +-
.../main/groovy/org/gradle/model/ModelType.java | 28 +
.../internal/PersistentModelObjectRegistry.java | 136 ++++
.../groovy/org/gradle/process/BaseExecSpec.java | 2 -
.../main/groovy/org/gradle/process/ExecResult.java | 2 -
.../main/groovy/org/gradle/process/ExecSpec.java | 2 -
.../groovy/org/gradle/process/JavaExecSpec.java | 2 -
.../internal/AbstractExecHandleBuilder.java | 3 -
.../process/internal/BadExitCodeException.java | 3 -
.../gradle/process/internal/DefaultExecAction.java | 3 -
.../gradle/process/internal/DefaultExecHandle.java | 11 +-
.../process/internal/DefaultJavaExecAction.java | 3 -
.../internal/DefaultWorkerProcessFactory.java | 2 +-
.../org/gradle/process/internal/ExecAction.java | 5 +-
.../org/gradle/process/internal/ExecException.java | 3 -
.../org/gradle/process/internal/ExecHandle.java | 3 -
.../gradle/process/internal/ExecHandleBuilder.java | 3 -
.../process/internal/ExecHandleListener.java | 3 -
.../gradle/process/internal/ExecHandleRunner.java | 3 -
.../internal/ExecHandleShutdownHookAction.java | 2 -
.../gradle/process/internal/ExecHandleState.java | 3 -
.../gradle/process/internal/JavaExecAction.java | 5 +-
.../process/internal/ProcessBuilderFactory.java | 2 -
.../internal/ProcessParentingInitializer.java | 1 -
.../gradle/process/internal/ProcessSettings.java | 3 -
.../process/internal/child/EncodedStream.java | 2 -
.../child/ImplementationClassLoaderWorker.java | 6 +-
.../IsolatedApplicationClassLoaderWorker.java | 2 +-
.../child/SystemApplicationClassLoaderWorker.java | 1 -
.../child/WorkerProcessClassPathProvider.java | 1 +
.../shutdown/ShutdownHookActionRegister.java | 3 -
.../internal/streams/ExecOutputHandleRunner.java | 3 -
.../process/internal/streams/SafeStreams.java | 3 -
.../process/internal/streams/StreamsForwarder.java | 8 +-
.../process/internal/streams/StreamsHandler.java | 3 -
.../groovy/org/gradle/profile/BuildProfile.java | 126 ++--
.../org/gradle/profile/CompositeOperation.java | 4 +
.../org/gradle/profile/ContinuousOperation.java | 20 +-
.../gradle/profile/DependencyResolveProfile.java | 30 -
.../org/gradle/profile/EvalutationOperation.java | 31 -
.../main/groovy/org/gradle/profile/Operation.java | 21 +
.../org/gradle/profile/ProfileEventAdapter.java | 40 +-
.../org/gradle/profile/ProfileReportRenderer.java | 59 +-
.../groovy/org/gradle/profile/ProjectProfile.java | 54 +-
.../groovy/org/gradle/profile/TaskExecution.java | 23 +-
.../org/gradle/reporting/ReportRenderer.java | 4 +-
.../testfixtures/internal/GlobalTestServices.java | 60 --
.../internal/InMemoryCacheFactory.java | 1 -
.../internal/InMemoryIndexedCache.java | 70 ++
.../testfixtures/internal/ProjectBuilderImpl.java | 17 +-
.../internal/TestBuildScopeServices.java | 52 ++
.../internal/TestGlobalScopeServices.java | 60 ++
.../internal/TestTopLevelBuildServiceRegistry.java | 52 --
.../provider/model/ToolingModelBuilder.java | 29 +
.../model/ToolingModelBuilderRegistry.java | 29 +
.../provider/model/UnknownModelException.java | 31 +
.../DefaultToolingModelBuilderRegistry.java | 64 ++
.../model/internal/LegacyConsumerInterface.java | 25 +
.../tooling/provider/model/package-info.java | 20 +
.../src/main/groovy/org/gradle/util/AntUtil.java | 7 +-
.../org/gradle/util/AvailablePortFinder.java | 2 -
.../util/ClassLoaderBackedClasspathSource.java | 43 --
.../groovy/org/gradle/util/ClassLoaderFactory.java | 41 --
.../groovy/org/gradle/util/ClasspathSource.java | 23 -
.../main/groovy/org/gradle/util/ClasspathUtil.java | 98 ---
.../src/main/groovy/org/gradle/util/Clock.java | 3 -
.../main/groovy/org/gradle/util/ConfigureUtil.java | 3 -
.../org/gradle/util/DefaultClassLoaderFactory.java | 86 ---
.../main/groovy/org/gradle/util/DeleteOnExit.java | 52 --
.../org/gradle/util/FilteringClassLoader.java | 212 ------
.../main/groovy/org/gradle/util/GFileUtils.java | 17 -
.../main/groovy/org/gradle/util/GStreamUtil.java | 33 +
.../src/main/groovy/org/gradle/util/GUtil.java | 3 -
.../main/groovy/org/gradle/util/GradleVersion.java | 116 ++--
.../src/main/groovy/org/gradle/util/JarUtil.java | 5 +-
.../main/groovy/org/gradle/util/JavaMethod.java | 75 --
.../org/gradle/util/LineBufferingOutputStream.java | 2 -
.../org/gradle/util/MultiParentClassLoader.java | 103 ---
.../org/gradle/util/MutableURLClassLoader.java | 48 --
.../core/src/main/groovy/org/gradle/util/Path.java | 3 -
.../groovy/org/gradle/util/ReflectionUtil.groovy | 46 --
.../org/gradle/util/SingleMessageLogger.java | 185 ++---
.../src/main/groovy/org/gradle/util/TextUtil.java | 7 +
.../main/groovy/org/gradle/util/VersionNumber.java | 19 +-
.../gradle/util/internal/LimitedDescription.java | 2 -
.../org/gradle/configuration/default-imports.txt | 38 -
.../buildsrc/defaultBuildSourceScript.txt | 6 +
.../initialization/defaultBuildSourceScript.txt | 5 -
.../groovy/org/gradle/StartParameterTest.groovy | 28 -
.../org/gradle/api/AllGradleExceptionsTest.groovy | 6 +-
.../org/gradle/api/file/ProjectCopySpecTest.groovy | 104 +++
.../AbstractNamedDomainObjectContainerTest.groovy | 166 +++--
.../gradle/api/internal/AbstractTaskSpec.groovy | 4 +-
.../AsmBackedClassGeneratorGroovyTest.groovy | 221 +++++-
.../api/internal/AsmBackedClassGeneratorTest.java | 4 +-
.../internal/CachingDirectedGraphWalkerTest.groovy | 197 ------
.../api/internal/ChainingTransformerTest.java | 12 +-
.../internal/CompositeDomainObjectSetTest.groovy | 29 +-
.../api/internal/ConventionAwareHelperTest.java | 15 +-
.../DefaultDomainObjectCollectionTest.java | 24 +-
.../internal/DefaultNamedDomainObjectSetTest.java | 20 +-
...PolymorphicDomainObjectContainerBaseTest.groovy | 43 ++
...tPolymorphicDomainObjectContainerDslTest.groovy | 88 ++-
...aultPolymorphicDomainObjectContainerTest.groovy | 63 +-
.../org/gradle/api/internal/DefaultTaskTest.groovy | 37 +-
.../api/internal/DocumentationRegistryTest.groovy | 47 +-
.../api/internal/ExtensibleDynamicObjectTest.java | 6 +-
.../gradle/api/internal/GraphAggregatorTest.groovy | 65 --
.../artifacts/DefaultExcludeRuleContainerTest.java | 3 -
.../artifacts/ProjectBackedModuleTest.groovy | 4 +-
.../AbstractModuleDependencySpec.groovy | 4 +-
.../dependencies/AbstractModuleDependencyTest.java | 7 +-
.../dependencies/DefaultClientModuleTest.java | 3 -
.../DefaultDependencyArtifactTest.java | 6 +-
.../DefaultExternalModuleDependencyTest.java | 3 -
.../DefaultProjectDependencyTest.groovy | 14 +-
.../DefaultDependencyHandlerTest.groovy | 8 +-
.../dependencies/ModuleFactoryDelegateTest.java | 9 +-
.../publish/AbstractPublishArtifactTest.java | 6 +-
.../publish/ArchivePublishArtifactTest.groovy | 3 -
.../publish/DefaultPublishArtifactTest.java | 3 -
...meAfterContainerInclusionDeprecationTest.groovy | 11 +-
.../LatestVersionSemanticComparatorSpec.groovy | 76 --
.../CacheBackedFileSnapshotRepositoryTest.groovy | 65 --
.../changedetection/CachingHasherTest.java | 108 ---
.../CompositeUpToDateRuleTest.groovy | 69 --
.../DefaultFileSnapshotterTest.groovy | 330 ---------
.../DefaultTaskArtifactStateCacheAccessTest.groovy | 53 --
.../DefaultTaskArtifactStateRepositoryTest.java | 606 ----------------
...BroadcastTaskArtifactStateRepositoryTest.groovy | 107 ---
...hortCircuitTaskArtifactStateRepositoryTest.java | 165 -----
.../DefaultTaskArtifactStateRepositoryTest.groovy | 683 ++++++++++++++++++
...rtCircuitTaskArtifactStateRepositoryTest.groovy | 112 +++
.../rules/CachingTaskStateChangesTest.groovy | 84 +++
.../rules/InputFilesStateChangeRuleTest.groovy | 78 +++
.../rules/OutputFilesStateChangeRuleTest.groovy | 82 +++
.../rules/SimpleTaskStateChangesTest.groovy | 56 ++
.../rules/SummaryTaskStateChangesTest.groovy | 89 +++
.../CacheBackedFileSnapshotRepositoryTest.groovy | 66 ++
.../changedetection/state/CachingHasherTest.java | 108 +++
.../DefaultFileSnapshotterSerializerTest.groovy | 38 +
.../state/DefaultFileSnapshotterTest.groovy | 346 +++++++++
.../DefaultTaskArtifactStateCacheAccessTest.groovy | 55 ++
.../state/FileSnapshotSerializerTest.groovy | 45 ++
.../state/OutputFilesSnapshotSerializerTest.groovy | 36 +
...peCoercingMethodArgumentsTransformerTest.groovy | 67 ++
.../internal/file/AbstractFileCollectionTest.java | 10 +-
.../internal/file/BaseDirFileResolverTest.groovy | 3 -
.../internal/file/CompositeFileCollectionTest.java | 6 +-
.../api/internal/file/CompositeFileTreeTest.java | 6 +-
.../file/DefaultCompositeFileTreeTest.groovy | 68 ++
.../internal/file/DefaultFileOperationsTest.groovy | 25 +-
.../file/DelegatingFileCollectionTest.groovy | 104 +++
.../LazilyInitializedFileCollectionTest.groovy | 52 ++
.../file/MaybeCompressedFileResourceTest.groovy | 3 -
.../internal/file/archive/TarCopyActionTest.java | 244 +++++++
.../file/archive/TarCopySpecVisitorTest.java | 250 -------
.../internal/file/archive/ZipCopyActionTest.java | 215 ++++++
.../file/archive/ZipCopySpecVisitorTest.java | 245 -------
.../file/archive/compression/ArchiversTest.groovy | 3 -
.../DefaultConfigurableFileCollectionTest.java | 12 +-
.../DefaultConfigurableFileTreeTest.groovy | 17 +-
.../file/collections/DirectoryFileTreeTest.java | 6 +-
.../internal/file/collections/MapFileTreeTest.java | 8 +-
.../file/copy/CopyActionExecuterTest.groovy | 74 ++
.../internal/file/copy/CopyActionImplTest.groovy | 95 ---
.../api/internal/file/copy/CopySpecImplTest.groovy | 350 ----------
.../internal/file/copy/CopySpecMatchingTest.groovy | 88 +++
.../internal/file/copy/DefaultCopySpecTest.groovy | 394 +++++++++++
.../internal/file/copy/DeleteActionImplTest.groovy | 3 -
...DuplicateHandlingCopyActionDecoratorTest.groovy | 196 ++++++
.../internal/file/copy/FileCopyActionImplTest.java | 54 --
.../api/internal/file/copy/FileCopyActionTest.java | 67 ++
.../file/copy/FileCopySpecVisitorTest.java | 92 ---
.../api/internal/file/copy/FilterChainTest.java | 4 +-
.../file/copy/MappingCopySpecVisitorTest.java | 400 -----------
.../copy/NormalizingCopyActionDecoratorTest.java | 151 ++++
.../file/copy/NormalizingCopySpecVisitorTest.java | 226 ------
.../file/copy/SyncCopyActionDecoratorTest.groovy | 58 ++
.../file/copy/SyncCopySpecVisitorTest.java | 169 -----
.../file/pattern/RegExpPatternStepTest.java | 4 +-
.../DefaultScriptHandlerFactoryTest.groovy | 2 +-
.../initialization/DefaultScriptHandlerTest.groovy | 97 ++-
.../parsers/ClosureToSpecNotationParserTest.groovy | 3 -
.../notations/parsers/TimeUnitsParserTest.groovy | 3 -
.../parsers/TypedNotationParserTest.groovy | 3 -
.../internal/plugins/DefaultConventionTest.groovy | 6 +-
.../plugins/DefaultPluginContainerTest.java | 128 ++++
.../DefaultProjectsPluginContainerTest.java | 131 ----
.../internal/plugins/ExtensionContainerTest.groovy | 3 -
.../internal/plugins/ExtensionsStorageTest.groovy | 76 ++
.../project/DefaultAntBuilderFactoryTest.groovy | 4 +-
.../internal/project/DefaultAntBuilderTest.groovy | 4 +-
.../project/DefaultIsolatedAntBuilderTest.groovy | 4 +-
.../project/DefaultProjectRegistryTest.java | 23 +-
.../api/internal/project/DefaultProjectTest.groovy | 81 ++-
.../project/GlobalServicesRegistryTest.java | 142 ----
.../GradleInternalServiceRegistryTest.groovy | 102 ---
.../internal/project/NewDefaultProjectTest.groovy | 7 +-
.../api/internal/project/ProjectFactoryTest.java | 16 +-
.../ProjectInternalServiceRegistryTest.java | 276 --------
.../project/TaskExecutionServicesTest.groovy | 54 --
.../project/TaskInternalServiceRegistryTest.java | 90 ---
.../gradle/api/internal/project/TestPlugin1.groovy | 3 -
.../gradle/api/internal/project/TestPlugin2.groovy | 3 -
.../TopLevelBuildServiceRegistryTest.groovy | 264 -------
.../AnnotationProcessingTaskFactoryTest.java | 95 ++-
.../project/taskfactory/TaskFactoryTest.groovy | 25 +-
.../api/internal/resource/UriResourceTest.groovy | 5 +-
.../api/internal/resources/URIBuilderTest.groovy | 3 -
.../internal/tasks/DefaultTaskContainerTest.groovy | 84 ++-
.../execution/ExecuteActionsTaskExecuterTest.java | 79 ++-
.../ExecuteAtMostOnceTaskExecuterTest.groovy | 22 +-
.../PostExecutionAnalysisTaskExecuterTest.groovy | 66 +-
.../SkipEmptySourceFilesTaskExecuterTest.groovy | 12 +-
.../execution/SkipOnlyIfTaskExecuterTest.java | 11 +-
.../SkipTaskWithNoActionsExecuterTest.groovy | 14 +-
.../execution/SkipUpToDateTaskExecuterTest.groovy | 110 +++
.../execution/SkipUpToDateTaskExecuterTest.java | 141 ----
.../execution/ValidatingTaskExecuterTest.groovy | 16 +-
.../tasks/util/DefaultJavaForkOptionsTest.groovy | 9 +-
.../api/internal/xml/SimpleXmlWriterSpec.groovy | 5 +-
.../api/plugins/TestPluginConvention1.groovy | 3 -
.../api/plugins/TestPluginConvention2.groovy | 3 -
.../gradle/api/tasks/AbstractCopyTaskTest.groovy | 80 +++
.../org/gradle/api/tasks/AbstractCopyTaskTest.java | 99 ---
.../groovy/org/gradle/api/tasks/CopyTest.groovy | 67 +-
.../groovy/org/gradle/api/tasks/DeleteTest.java | 3 -
.../org/gradle/api/tasks/DirectoryTest.groovy | 8 +-
.../org/gradle/api/tasks/GradleBuildTest.groovy | 63 +-
.../groovy/org/gradle/api/tasks/SyncTest.groovy | 27 +
.../groovy/org/gradle/api/tasks/UploadTest.groovy | 4 +-
.../org/gradle/api/tasks/ant/AntTargetTest.java | 10 +-
.../org/gradle/api/tasks/bundling/TarTest.groovy | 10 +-
.../org/gradle/api/tasks/bundling/ZipTest.groovy | 6 +-
.../tasks/util/AbstractTestForPatternSet.groovy | 12 +-
.../cache/internal/DefaultCacheAccessTest.groovy | 449 +++++-------
.../cache/internal/DefaultCacheFactoryTest.groovy | 3 +-
.../internal/DefaultFileLockManagerTest.groovy | 16 +-
.../DefaultPersistentDirectoryCacheTest.java | 3 +-
.../cache/internal/FileLockCommunicatorTest.groovy | 99 +++
.../cacheops/CacheAccessOperationsStackTest.groovy | 142 ++++
.../cacheops/CacheOperationStackTest.groovy | 126 ++++
.../DefaultFileLockContentionHandlerTest.groovy | 185 +++++
.../configuration/BuildScriptProcessorTest.java | 59 --
.../DefaultBuildConfigurerTest.groovy | 21 +-
.../DefaultScriptPluginFactoryTest.java | 13 +-
.../ImplicitTasksConfigurerTest.groovy | 33 -
.../gradle/configuration/ImportsReaderTest.groovy | 33 +-
.../LifecycleProjectEvaluatorTest.groovy | 90 ---
.../ProjectDependencies2TaskResolverTest.groovy | 40 --
.../project/BuildScriptProcessorTest.groovy | 43 ++
.../ConfigureActionsProjectEvaluatorTest.groovy | 59 ++
...tProjectConfigurationActionContainerTest.groovy | 52 ++
.../project/DelayedConfigurationActionsTest.groovy | 70 ++
.../project/LifecycleProjectEvaluatorTest.groovy | 152 ++++
.../PluginsProjectConfigureActionsTest.groovy | 52 ++
.../ProjectDependencies2TaskResolverTest.groovy | 37 +
.../execution/ProjectEvaluatingActionTest.groovy | 3 -
.../gradle/execution/TaskNameResolverTest.groovy | 50 +-
...kNameResolvingBuildConfigurationActionTest.java | 43 +-
.../execution/TaskPathProjectEvaluatorTest.groovy | 3 -
.../CommandLineTaskConfigurerSpec.groovy | 3 -
.../commandline/CommandLineTaskParserSpec.groovy | 26 +-
.../taskgraph/DefaultTaskExecutionPlanTest.groovy | 613 +++++++++++-----
.../taskgraph/DefaultTaskGraphExecuterTest.java | 36 +-
.../taskgraph/ParallelTaskExecutionPlanTest.groovy | 26 -
.../taskgraph/TaskDependencyGraphTest.groovy | 77 ++
.../taskgraph/TaskPlanExecutorFactoryTest.groovy | 2 +-
.../taskpath/ProjectFinderByTaskPathTest.groovy | 11 +-
.../execution/taskpath/ResolvedTaskPathTest.groovy | 3 -
.../execution/taskpath/TaskPathResolverTest.groovy | 3 -
.../gradle/groovy/scripts/DefaultScriptTest.groovy | 15 +-
.../org/gradle/groovy/scripts/EmptyScript.java | 3 -
.../DefaultScriptCompilationHandlerTest.java | 3 -
.../initialization/BuildFileProjectSpecTest.java | 6 +-
.../BuildLayoutParametersTest.groovy | 51 ++
.../initialization/BuildSourceBuilderTest.groovy | 171 -----
.../DefaultCommandLineConverterTest.java | 3 -
.../DefaultGradleLauncherFactoryTest.groovy | 5 +-
.../initialization/DefaultGradleLauncherTest.java | 14 +-
.../DefaultGradlePropertiesLoaderTest.java | 3 -
.../DefaultProjectDescriptorRegistryTest.java | 19 +-
.../DefaultProjectDescriptorTest.java | 43 +-
.../initialization/DefaultSettingsTest.groovy | 94 ++-
.../InstantiatingBuildLoaderTest.groovy | 15 +-
.../LayoutCommandLineConverterTest.groovy | 45 +-
.../ProjectDirectoryProjectSpecTest.java | 6 +-
.../ProjectPropertySettingBuildLoaderTest.groovy | 7 +-
.../ScriptEvaluatingSettingsProcessorTest.groovy | 24 +-
.../gradle/initialization/SettingsFactoryTest.java | 43 +-
.../gradle/initialization/SettingsHandlerTest.java | 23 +-
.../buildsrc/BuildSourceBuilderTest.groovy | 58 ++
.../BuildSrcBuildListenerFactoryTest.groovy | 62 ++
.../buildsrc/BuildSrcUpdateFactoryTest.groovy | 67 ++
.../DeprecatedFeatureUsageTest.groovy | 38 +
.../LoggingDeprecatedFeatureHandlerTest.groovy | 57 ++
.../ScriptUsageLocationReporterTest.groovy | 126 ++++
.../graph/CachingDirectedGraphWalkerTest.groovy | 266 +++++++
.../graph/DirectedGraphRendererTest.groovy | 140 ++++
.../internal/graph/GraphAggregatorTest.groovy | 65 ++
.../service/scopes/BuildScopeServicesTest.groovy | 270 ++++++++
.../service/scopes/GlobalScopeServicesTest.java | 161 +++++
.../service/scopes/GradleScopeServicesTest.groovy | 119 ++++
.../service/scopes/ProjectScopeServicesTest.groovy | 222 ++++++
.../scopes/SettingsScopeServicesTest.groovy | 75 ++
.../scopes/TaskExecutionServicesTest.groovy | 57 ++
.../service/scopes/TaskScopeServicesTest.java | 91 +++
.../DefaultBuildClassLoaderRegistryTest.groovy | 49 ++
.../org/gradle/invocation/DefaultGradleTest.java | 29 +-
.../internal/DefaultLoggingManagerTest.java | 6 +-
.../LoggingCommandLineConverterTest.groovy | 16 +-
.../PersistentModelObjectRegistryTest.groovy | 166 +++++
.../org/gradle/model/internal/TestModel.java | 52 ++
.../process/internal/DefaultExecHandleSpec.groovy | 3 -
.../internal/DefaultWorkerProcessTest.groovy | 2 +-
.../internal/JavaExecHandleBuilderTest.groovy | 15 +-
.../gradle/process/internal/JvmOptionsTest.groovy | 10 +-
.../child/ImplementationClassLoaderWorkerTest.java | 2 +-
.../internal/child/SerializableMockHelper.groovy | 8 +-
.../org/gradle/profile/BuildProfileTest.groovy | 80 ++-
.../profile/ProfileReportRendererTest.groovy | 227 ++++++
.../org/gradle/profile/ProjectProfileTest.groovy | 34 +
.../org/gradle/profile/TaskExecutionTest.groovy | 43 ++
.../DefaultToolingModelBuilderRegistryTest.groovy | 76 ++
.../util/DefaultClassLoaderFactoryTest.groovy | 91 ---
.../util/DefaultClassLoaderFactoryTestHelper.java | 35 -
.../gradle/util/FilteringClassLoaderTest.groovy | 182 -----
.../groovy/org/gradle/util/GFileUtilsTest.groovy | 3 -
.../groovy/org/gradle/util/GStreamUtilTest.groovy | 38 +
.../org/gradle/util/GradleVersionTest.groovy | 124 ++--
.../groovy/org/gradle/util/JavaMethodTest.java | 68 --
.../groovy/org/gradle/util/MatchersTest.groovy | 3 -
.../gradle/util/MultiParentClassLoaderTest.groovy | 152 ----
.../test/groovy/org/gradle/util/PathTest.groovy | 6 +-
.../org/gradle/util/SingleMessageLoggerTest.groovy | 49 +-
.../test/groovy/org/gradle/util/StageTest.groovy | 3 -
.../groovy/org/gradle/util/TextUtilTest.groovy | 26 +-
.../org/gradle/util/VersionNumberTest.groovy | 18 +-
.../util/internal/ArgumentsSplitterTest.groovy | 4 +-
.../util/internal/LimitedDescriptionTest.groovy | 3 -
.../org/gradle/api/internal/file/TestFiles.java | 7 +-
.../internal/file/copy/CopyActionExecuterUtil.java | 40 ++
.../api/tasks/AbstractConventionTaskTest.java | 12 +-
.../api/tasks/AbstractCopyTaskContractTest.groovy | 44 ++
.../gradle/api/tasks/AbstractSpockTaskTest.groovy | 18 +-
.../org/gradle/api/tasks/AbstractTaskTest.java | 20 +-
.../tasks/bundling/AbstractArchiveTaskTest.groovy | 10 +-
.../DefaultFileLockManagerTestHelper.groovy | 8 +-
.../org/gradle/util/ConcurrentSpecification.groovy | 3 -
.../groovy/org/gradle/util/HelperUtil.groovy | 143 ----
.../groovy/org/gradle/util/TestTask.groovy | 3 -
.../groovy/org/gradle/util/TestUtil.groovy | 140 ++++
subprojects/cpp/cpp.gradle | 4 +-
...tLanguageIncrementalBuildIntegrationTest.groovy | 327 +++++++++
.../cpp/AbstractLanguageIntegrationTest.groovy | 208 ++++++
.../cpp/AssemblyLanguageIntegrationTest.groovy | 78 +++
.../cpp/BinaryFlavorsIntegrationTest.groovy | 217 ++++++
.../cpp/CCallingCppLanguageIntegrationTest.groovy | 25 +
...CLanguageIncrementalBuildIntegrationTest.groovy | 27 +
.../language/cpp/CLanguageIntegrationTest.groovy | 52 ++
.../language/cpp/CppBinariesIntegrationTest.groovy | 219 ++++++
.../cpp/CppCallingCLanguageIntegrationTest.groovy | 25 +
.../cpp/CppExePluginGoodBehaviourTest.groovy | 25 +
.../cpp/CppExePluginIntegrationTest.groovy | 65 ++
...pLanguageIncrementalBuildIntegrationTest.groovy | 25 +
.../language/cpp/CppLanguageIntegrationTest.groovy | 53 ++
.../cpp/CppLibPluginGoodBehaviourTest.groovy | 25 +
.../cpp/CppLibPluginIntegrationTest.groovy | 61 ++
.../language/cpp/CppPluginGoodBehaviourTest.groovy | 25 +
.../language/cpp/CppPluginIntegrationTest.groovy | 138 ++++
.../language/cpp/CppSamplesIntegrationTest.groovy | 189 +++++
.../cpp/MixedLanguageIntegrationTest.groovy | 81 +++
.../cpp/MultipleToolChainIntegrationTest.groovy | 116 ++++
.../cpp/NativeBinariesPluginIntegrationTest.groovy | 222 ++++++
...bstractInstalledToolChainIntegrationSpec.groovy | 51 ++
.../language/cpp/fixtures/AvailableToolChains.java | 312 +++++++++
.../language/cpp/fixtures/ExecutableFixture.groovy | 31 +
.../cpp/fixtures/NativeBinaryFixture.groovy | 67 ++
.../cpp/fixtures/NativeInstallationFixture.groovy | 73 ++
.../cpp/fixtures/SharedLibraryFixture.groovy | 43 ++
.../cpp/fixtures/SingleToolChainTestRunner.java | 76 ++
.../fixtures/app/CCallingCppHelloWorldApp.groovy | 75 ++
.../cpp/fixtures/app/CHelloWorldApp.groovy | 112 +++
.../fixtures/app/CppCallingCHelloWorldApp.groovy | 70 ++
.../cpp/fixtures/app/CppHelloWorldApp.groovy | 111 +++
.../language/cpp/fixtures/app/HelloWorldApp.java | 73 ++
.../cpp/fixtures/app/IncrementalHelloWorldApp.java | 27 +
.../fixtures/app/MixedLanguageHelloWorldApp.groovy | 162 +++++
.../language/cpp/fixtures/app/SourceFile.java | 52 ++
.../cpp/AbstractBinariesIntegrationSpec.groovy | 33 -
.../org/gradle/plugins/cpp/AvailableCompilers.java | 171 -----
.../cpp/CppExePluginGoodBehaviourTest.groovy | 25 -
.../plugins/cpp/CppIntegrationTestRunner.java | 96 ---
.../cpp/CppLibPluginGoodBehaviourTest.groovy | 25 -
.../plugins/cpp/CppPluginIntegrationTest.groovy | 220 ------
.../plugins/cpp/CppSamplesIntegrationTest.groovy | 85 ---
.../gradle/nativecode/base/DependentSourceSet.java | 45 ++
.../org/gradle/nativecode/base/Executable.java | 26 +
.../gradle/nativecode/base/ExecutableBinary.java | 26 +
.../nativecode/base/ExecutableContainer.java | 25 +
.../groovy/org/gradle/nativecode/base/Flavor.java | 34 +
.../gradle/nativecode/base/FlavorContainer.java | 27 +
.../nativecode/base/HeaderExportingSourceSet.java | 38 +
.../groovy/org/gradle/nativecode/base/Library.java | 40 ++
.../org/gradle/nativecode/base/LibraryBinary.java | 30 +
.../gradle/nativecode/base/LibraryContainer.java | 25 +
.../gradle/nativecode/base/LibraryResolver.java | 32 +
.../org/gradle/nativecode/base/NativeBinary.java | 131 ++++
.../gradle/nativecode/base/NativeComponent.java | 73 ++
.../nativecode/base/NativeDependencySet.java | 40 ++
.../nativecode/base/SharedLibraryBinary.java | 25 +
.../nativecode/base/StaticLibraryBinary.java | 37 +
.../org/gradle/nativecode/base/ToolChain.java | 28 +
.../gradle/nativecode/base/ToolChainRegistry.java | 44 ++
.../base/internal/AbstractToolChain.java | 139 ++++
.../nativecode/base/internal/BinaryToolSpec.java | 27 +
.../base/internal/ConfigurableLibraryResolver.java | 27 +
.../ConfigurationBasedNativeDependencySet.groovy | 90 +++
.../base/internal/CreateNativeBinariesAction.java | 57 ++
.../base/internal/DefaultExecutable.java | 30 +
.../base/internal/DefaultExecutableBinary.java | 39 ++
.../base/internal/DefaultExecutableContainer.java | 33 +
.../nativecode/base/internal/DefaultFlavor.java | 65 ++
.../base/internal/DefaultFlavorContainer.java | 57 ++
.../nativecode/base/internal/DefaultLibrary.java | 78 +++
.../base/internal/DefaultLibraryContainer.java | 37 +
.../base/internal/DefaultLibraryResolver.java | 56 ++
.../base/internal/DefaultNativeBinary.java | 150 ++++
.../base/internal/DefaultNativeComponent.java | 77 ++
.../base/internal/DefaultSharedLibraryBinary.java | 86 +++
.../base/internal/DefaultStaticLibraryBinary.java | 96 +++
.../base/internal/DefaultToolChainRegistry.java | 164 +++++
.../base/internal/ExecutableLinkerSpec.java | 20 +
.../nativecode/base/internal/LinkerSpec.java | 42 ++
.../base/internal/NativeBinaryFactory.java | 63 ++
.../base/internal/NativeBinaryInternal.java | 27 +
.../internal/ResolvableNativeDependencySet.java | 61 ++
.../base/internal/SharedLibraryLinkerSpec.java | 23 +
.../base/internal/SourceSetNotationParser.java | 73 ++
.../base/internal/StaticLibraryArchiverSpec.java | 34 +
.../base/internal/ToolChainAvailability.java | 48 ++
.../base/internal/ToolChainInternal.java | 47 ++
.../org/gradle/nativecode/base/package-info.java | 20 +
.../base/plugins/NativeBinariesModelPlugin.java | 68 ++
.../base/plugins/NativeBinariesPlugin.groovy | 118 ++++
.../nativecode/base/plugins/package-info.java | 20 +
.../nativecode/base/tasks/AbstractLinkTask.groovy | 117 ++++
.../nativecode/base/tasks/BuildBinaryTask.java | 28 +
.../base/tasks/CreateStaticLibrary.groovy | 103 +++
.../nativecode/base/tasks/InstallExecutable.groovy | 150 ++++
.../nativecode/base/tasks/LinkExecutable.groovy | 40 ++
.../nativecode/base/tasks/LinkSharedLibrary.groovy | 44 ++
.../gradle/nativecode/base/tasks/package-info.java | 20 +
.../org/gradle/nativecode/cdt/CdtIdePlugin.groovy | 79 +++
.../nativecode/cdt/model/CprojectDescriptor.groovy | 117 ++++
.../nativecode/cdt/model/CprojectSettings.groovy | 106 +++
.../nativecode/cdt/model/ProjectDescriptor.groovy | 48 ++
.../nativecode/cdt/model/ProjectSettings.groovy | 43 ++
.../cdt/tasks/GenerateMetadataFileTask.groovy | 53 ++
.../language/asm/AssemblerSourceSet.java | 24 +
.../language/asm/internal/AssembleSpec.java | 38 +
.../language/asm/internal/DefaultAssembleSpec.java | 22 +
.../asm/internal/DefaultAssemblerSourceSet.java | 28 +
.../nativecode/language/asm/package-info.java | 20 +
.../asm/plugins/AssemblerLangPlugin.groovy | 64 ++
.../nativecode/language/asm/tasks/Assemble.groovy | 89 +++
.../base/internal/AbstractBaseCompileSpec.java | 78 +++
.../base/internal/AbstractBaseSourceSet.java | 107 +++
.../language/base/internal/NativeCompileSpec.java | 50 ++
.../base/tasks/AbstractNativeCompileTask.groovy | 127 ++++
.../gradle/nativecode/language/c/CSourceSet.java | 28 +
.../language/c/internal/CCompileSpec.java | 23 +
.../language/c/internal/DefaultCCompileSpec.java | 31 +
.../language/c/internal/DefaultCSourceSet.java | 28 +
.../gradle/nativecode/language/c/package-info.java | 20 +
.../language/c/plugins/CLangPlugin.groovy | 72 ++
.../nativecode/language/c/tasks/CCompile.groovy | 40 ++
.../nativecode/language/cpp/CppSourceSet.java | 28 +
.../language/cpp/internal/CppCompileSpec.java | 23 +
.../cpp/internal/DefaultCppCompileSpec.java | 31 +
.../language/cpp/internal/DefaultCppSourceSet.java | 28 +
.../nativecode/language/cpp/package-info.java | 20 +
.../cpp/plugins/CppExeConventionPlugin.groovy | 74 ++
.../language/cpp/plugins/CppLangPlugin.groovy | 71 ++
.../cpp/plugins/CppLibConventionPlugin.groovy | 84 +++
.../language/cpp/plugins/CppPlugin.groovy | 125 ++++
.../language/cpp/plugins/package-info.java | 20 +
.../language/cpp/tasks/CppCompile.groovy | 40 ++
.../language/cpp/tasks/package-info.java | 20 +
.../toolchain/ConfigurableToolChain.java | 65 ++
.../org/gradle/nativecode/toolchain/Gcc.java | 26 +
.../org/gradle/nativecode/toolchain/Tool.java | 36 +
.../org/gradle/nativecode/toolchain/VisualCpp.java | 38 +
.../CommandLineCompilerArgumentsToOptionFile.java | 58 ++
.../toolchain/internal/CommandLineTool.java | 98 +++
.../toolchain/internal/ToolRegistry.java | 78 +++
.../nativecode/toolchain/internal/ToolType.java | 42 ++
.../internal/gpp/ArStaticLibraryArchiver.java | 52 ++
.../toolchain/internal/gpp/Assembler.java | 65 ++
.../toolchain/internal/gpp/CCompiler.java | 50 ++
.../toolchain/internal/gpp/CppCompiler.java | 52 ++
.../internal/gpp/GccCompileSourcesToArguments.java | 34 +
.../internal/gpp/GccCompileSpecToArguments.java | 51 ++
.../toolchain/internal/gpp/GccToolRegistry.java | 49 ++
.../gpp/GeneralGccCompileOptionsToArguments.java | 40 ++
.../toolchain/internal/gpp/GppLinker.java | 80 +++
.../toolchain/internal/gpp/GppToolChain.java | 139 ++++
.../internal/gpp/version/GppVersionDeterminer.java | 105 +++
.../toolchain/internal/msvcpp/Assembler.java | 64 ++
.../toolchain/internal/msvcpp/CCompiler.java | 50 ++
.../toolchain/internal/msvcpp/CppCompiler.java | 49 ++
.../GeneralVisualCppCompileSpecToArguments.java | 44 ++
.../msvcpp/LibExeStaticLibraryArchiver.java | 53 ++
.../toolchain/internal/msvcpp/LinkExeLinker.java | 63 ++
.../internal/msvcpp/VisualCppToolChain.java | 127 ++++
.../internal/msvcpp/VisualStudioInstall.java | 76 ++
.../gradle/nativecode/toolchain/package-info.java | 20 +
.../toolchain/plugins/GppCompilerPlugin.groovy | 57 ++
.../plugins/MicrosoftVisualCppPlugin.groovy | 60 ++
.../nativecode/toolchain/plugins/package-info.java | 20 +
.../gradle/plugins/binaries/BinariesPlugin.java | 66 --
.../org/gradle/plugins/binaries/model/Binary.java | 39 --
.../gradle/plugins/binaries/model/CompileSpec.java | 51 --
.../gradle/plugins/binaries/model/Compiler.java | 24 -
.../plugins/binaries/model/CompilerRegistry.java | 31 -
.../gradle/plugins/binaries/model/Executable.java | 23 -
.../binaries/model/HeaderExportingSourceSet.java | 27 -
.../org/gradle/plugins/binaries/model/Library.java | 27 -
.../plugins/binaries/model/LibraryCompileSpec.java | 32 -
.../model/NativeDependencyCapableSourceSet.java | 25 -
.../binaries/model/NativeDependencySet.java | 28 -
.../gradle/plugins/binaries/model/SourceSet.java | 25 -
.../binaries/model/internal/BinaryCompileSpec.java | 23 -
.../model/internal/BinaryCompileSpecFactory.java | 27 -
.../model/internal/CompileSpecFactory.java | 29 -
.../binaries/model/internal/CompileTaskAware.java | 23 -
.../binaries/model/internal/CompilerAdapter.java | 32 -
.../ConfigurationBasedNativeDependencySet.groovy | 86 ---
.../binaries/model/internal/DefaultBinary.java | 66 --
.../model/internal/DefaultCompilerRegistry.java | 90 ---
.../binaries/model/internal/DefaultExecutable.java | 31 -
.../binaries/model/internal/DefaultLibrary.java | 76 --
.../binaries/model/internal/package-info.java | 20 -
.../plugins/binaries/model/package-info.java | 20 -
.../org/gradle/plugins/binaries/package-info.java | 20 -
.../plugins/binaries/tasks/package-info.java | 20 -
.../org/gradle/plugins/cpp/CppCompile.groovy | 33 -
.../plugins/cpp/CppExeConventionPlugin.groovy | 58 --
.../org/gradle/plugins/cpp/CppExtension.java | 50 --
.../plugins/cpp/CppLibConventionPlugin.groovy | 68 --
.../groovy/org/gradle/plugins/cpp/CppPlugin.groovy | 99 ---
.../org/gradle/plugins/cpp/CppSourceSet.java | 65 --
.../org/gradle/plugins/cpp/cdt/CdtIdePlugin.groovy | 77 --
.../cpp/cdt/model/CprojectDescriptor.groovy | 115 ---
.../plugins/cpp/cdt/model/CprojectSettings.groovy | 107 ---
.../plugins/cpp/cdt/model/ProjectDescriptor.groovy | 46 --
.../plugins/cpp/cdt/model/ProjectSettings.groovy | 40 --
.../cpp/cdt/tasks/GenerateMetadataFileTask.groovy | 51 --
.../cpp/compiler/capability/AgainstLibrary.java | 31 -
.../cpp/compiler/capability/CompilesCpp.java | 30 -
.../compiler/capability/StandardCppCompiler.java | 23 -
.../cpp/compiler/capability/package-info.java | 20 -
.../compiler/internal/CommandLineCppCompiler.java | 68 --
.../internal/CommandLineCppCompilerAdapter.java | 59 --
...ommandLineCppCompilerArgumentsToOptionFile.java | 56 --
.../plugins/cpp/compiler/internal/CppCompiler.java | 24 -
.../gradle/plugins/cpp/gpp/GppCompileSpec.groovy | 218 ------
.../plugins/cpp/gpp/GppCompilerPlugin.groovy | 53 --
.../plugins/cpp/gpp/GppLibraryCompileSpec.groovy | 40 --
.../cpp/gpp/internal/GppCompileSpecFactory.java | 42 --
.../gpp/internal/GppCompileSpecToArguments.java | 55 --
.../plugins/cpp/gpp/internal/GppCompiler.java | 44 --
.../cpp/gpp/internal/GppCompilerAdapter.java | 106 ---
.../gpp/internal/version/GppVersionDeterminer.java | 105 ---
.../org/gradle/plugins/cpp/gpp/package-info.java | 20 -
.../plugins/cpp/internal/CppCompileSpec.java | 33 -
.../plugins/cpp/internal/DefaultCppSourceSet.java | 90 ---
.../cpp/msvcpp/MicrosoftVisualCppPlugin.groovy | 61 --
.../internal/VisualCppCompileSpecToArguments.java | 47 --
.../cpp/msvcpp/internal/VisualCppCompiler.java | 36 -
.../msvcpp/internal/VisualCppCompilerAdapter.java | 51 --
.../org/gradle/plugins/cpp/package-info.java | 20 -
.../META-INF/gradle-plugins/binaries.properties | 2 +-
.../META-INF/gradle-plugins/cpp-exe.properties | 2 +-
.../META-INF/gradle-plugins/cpp-lib.properties | 2 +-
.../META-INF/gradle-plugins/cpp.properties | 2 +-
.../META-INF/gradle-plugins/eclipse-cdt.properties | 2 +-
.../gradle-plugins/gpp-compiler.properties | 2 +-
.../META-INF/gradle-plugins/visual-cpp.properties | 1 +
.../cdt/model/defaultCproject-linux.xml | 0
.../cdt/model/defaultCproject-macos.xml | 0
.../cdt/model/defaultProject.xml | 0
.../internal/DefaultExecutableBinaryTest.groovy | 41 ++
.../base/internal/DefaultExecutableTest.groovy | 28 +
.../internal/DefaultFlavorContainerTest.groovy | 60 ++
.../base/internal/DefaultFlavorTest.groovy | 38 +
.../internal/DefaultLibraryResolverTest.groovy | 128 ++++
.../base/internal/DefaultLibraryTest.groovy | 62 ++
.../base/internal/DefaultNativeBinaryTest.groovy | 127 ++++
.../internal/DefaultNativeComponentTest.groovy | 77 ++
.../internal/DefaultSharedLibraryBinaryTest.groovy | 70 ++
.../internal/DefaultStaticLibraryBinaryTest.groovy | 61 ++
.../internal/DefaultToolChainRegistryTest.groovy | 176 +++++
.../base/internal/NativeBinaryFactoryTest.groovy | 97 +++
.../internal/SourceSetNotationParserTest.groovy | 52 ++
.../base/plugins/NativeBinariesPluginTest.groovy | 115 +++
.../cdt/model/CprojectSettingsSpec.groovy | 58 ++
.../cdt/model/ProjectDescriptorSpec.groovy | 48 ++
.../cpp/internal/DefaultCppSourceSetTest.groovy | 65 ++
.../cpp/plugins/CppExeConventionPluginTest.groovy | 37 +
.../cpp/plugins/CppLibConventionPluginTest.groovy | 34 +
.../language/cpp/plugins/CppPluginTest.groovy | 235 +++++++
.../toolchain/internal/gpp/GppToolChainTest.groovy | 67 ++
.../gpp/version/GppVersionDeterminerTest.groovy | 142 ++++
.../internal/msvcpp/VisualCppToolChainTest.groovy | 127 ++++
.../plugins/MicrosoftVisualCppPluginTest.groovy | 63 ++
.../internal/DefaultCompilerRegistryTest.groovy | 130 ----
.../plugins/cpp/CppExeConventionPluginTest.groovy | 37 -
.../plugins/cpp/CppLibConventionPluginTest.groovy | 39 --
.../org/gradle/plugins/cpp/CppPluginTest.groovy | 235 -------
.../cpp/cdt/model/CprojectSettingsSpec.groovy | 58 --
.../cpp/cdt/model/ProjectDescriptorSpec.groovy | 48 --
.../plugins/cpp/gpp/GppCompileSpecTest.groovy | 40 --
.../cpp/gpp/GppLibraryCompileSpecTest.groovy | 37 -
.../version/GppVersionDeterminerTest.groovy | 142 ----
subprojects/diagnostics/diagnostics.gradle | 2 +-
...pendencyInsightReportTaskIntegrationTest.groovy | 146 +++-
.../DependencyReportTaskIntegrationTest.groovy | 10 +-
.../ResolutionResultApiIntegrationTest.groovy | 79 ---
.../TaskReportTaskIntegrationTest.groovy | 2 +-
.../org/gradle/api/plugins/HelpTasksPlugin.groovy | 23 +-
.../gradle/api/plugins/ProjectReportsPlugin.java | 8 +-
.../plugins/internal/HelpTasksAutoApplyAction.java | 26 +
.../api/tasks/diagnostics/AbstractReportTask.java | 2 +-
.../diagnostics/DependencyInsightReportTask.groovy | 2 +-
.../tasks/diagnostics/DependencyReportTask.java | 2 -
.../api/tasks/diagnostics/ProjectReportTask.java | 2 +-
.../internal/DependencyReportRenderer.java | 2 -
.../tasks/diagnostics/internal/GraphRenderer.java | 69 --
.../internal/SingleProjectTaskReportModel.java | 6 +-
.../diagnostics/internal/TaskReportRenderer.java | 2 -
.../AsciiDependencyReportRenderer.java | 4 +-
.../internal/dsl/DependencyResultSpec.java | 3 -
.../dsl/DependencyResultSpecNotationParser.java | 3 -
.../internal/graph/DependencyGraphRenderer.groovy | 5 +-
.../diagnostics/internal/graph/NodeRenderer.groovy | 3 -
.../internal/graph/SimpleNodeRenderer.java | 3 -
.../nodes/AbstractRenderableModuleResult.java | 3 -
.../nodes/InvertedRenderableModuleResult.java | 2 -
.../internal/graph/nodes/RenderableDependency.java | 3 -
.../graph/nodes/RenderableDependencyResult.java | 3 -
.../graph/nodes/RenderableModuleResult.java | 3 -
.../insight/DependencyInsightReporter.groovy | 2 -
.../internal/insight/DependencyResultSorter.java | 27 +-
...le.configuration.project.ProjectConfigureAction | 1 +
.../gradle/api/plugins/HelpTasksPluginSpec.groovy | 26 +-
.../api/plugins/ProjectReportsPluginTest.java | 4 +-
.../ReportingBasePluginConventionTest.groovy | 64 --
.../api/plugins/ReportingBasePluginTest.groovy | 46 --
.../tasks/diagnostics/AbstractReportTaskTest.java | 8 +-
.../DependencyInsightReportTaskSpec.groovy | 15 +-
.../diagnostics/DependencyReportTaskTest.groovy | 19 +-
.../tasks/diagnostics/ProjectReportTaskTest.groovy | 14 +-
.../tasks/diagnostics/PropertyReportTaskTest.java | 4 +-
.../api/tasks/diagnostics/TaskReportTaskTest.java | 4 +-
.../internal/TaskReportRendererTest.groovy | 3 -
.../AsciiDependencyReportRendererTest.groovy | 4 +-
.../DependencyResultSpecNotationParserSpec.groovy | 5 +-
.../internal/dsl/DependencyResultSpecTest.groovy | 4 -
.../graph/DependencyGraphRendererSpec.groovy | 5 +-
.../AbstractRenderableDependencyResultSpec.groovy | 3 -
.../nodes/RenderableDependencyResultTest.groovy | 3 -
.../internal/graph/nodes/SimpleDependency.java | 0
.../insight/DependencyInsightReporterSpec.groovy | 6 +-
.../insight/DependencyResultSorterSpec.groovy | 52 +-
subprojects/distributions/distributions.gradle | 14 +-
.../gradle/AllDistributionIntegrationSpec.groovy | 2 +-
.../org/gradle/DistributionIntegrationSpec.groovy | 7 +-
subprojects/docs/docs.gradle | 46 +-
subprojects/docs/src/docs/css/release-notes.css | 29 +-
subprojects/docs/src/docs/dsl/dsl.xml | 89 ++-
.../docs/src/docs/dsl/org.gradle.api.Task.xml | 12 +
....gradle.api.artifacts.dsl.DependencyHandler.xml | 6 +
....gradle.api.artifacts.dsl.RepositoryHandler.xml | 3 +
...dle.api.plugins.ApplicationPluginConvention.xml | 6 +-
...adle.api.plugins.jetty.AbstractJettyRunTask.xml | 8 +
.../org.gradle.api.plugins.jetty.JettyRunWar.xml | 8 +
.../org.gradle.api.plugins.quality.CodeNarc.xml | 12 +
...radle.api.plugins.quality.CodeNarcExtension.xml | 15 +
...org.gradle.api.publish.PublicationContainer.xml | 3 -
.../org.gradle.api.publish.ivy.IvyPublication.xml | 24 +
...g.gradle.api.publish.maven.MavenPublication.xml | 9 +
...gradle.api.reporting.GenerateBuildDashboard.xml | 3 -
.../docs/dsl/org.gradle.api.reporting.Report.xml | 37 +
.../org.gradle.api.reporting.ReportContainer.xml | 25 +
.../dsl/org.gradle.api.reporting.Reporting.xml | 28 +
...org.gradle.api.reporting.ReportingExtension.xml | 28 +
.../dsl/org.gradle.api.tasks.AbstractCopyTask.xml | 10 +
.../src/docs/dsl/org.gradle.api.tasks.Copy.xml | 2 +-
.../dsl/org.gradle.api.tasks.GroovyRuntime.xml | 25 +
.../docs/dsl/org.gradle.api.tasks.ScalaRuntime.xml | 31 +
...le.api.tasks.application.CreateStartScripts.xml | 3 +-
.../org.gradle.api.tasks.compile.GroovyCompile.xml | 2 +-
...api.tasks.incremental.IncrementalTaskInputs.xml | 25 +
.../org.gradle.api.tasks.incremental.InputFile.xml | 26 +
.../org.gradle.api.tasks.scala.ScalaCompile.xml | 2 +-
.../dsl/org.gradle.api.tasks.scala.ScalaDoc.xml | 2 +-
.../docs/dsl/org.gradle.api.tasks.testing.Test.xml | 11 +
.../dsl/org.gradle.api.tasks.wrapper.Wrapper.xml | 4 +-
.../dsl/org.gradle.buildsetup.tasks.SetupBuild.xml | 43 ++
.../org.gradle.language.base.BinaryContainer.xml | 38 +
.../dsl/org.gradle.nativecode.base.Executable.xml | 38 +
...org.gradle.nativecode.base.ExecutableBinary.xml | 38 +
....gradle.nativecode.base.ExecutableContainer.xml | 38 +
.../dsl/org.gradle.nativecode.base.Library.xml | 47 ++
.../org.gradle.nativecode.base.LibraryBinary.xml | 41 ++
...org.gradle.nativecode.base.LibraryContainer.xml | 38 +
.../org.gradle.nativecode.base.NativeBinary.xml | 77 ++
.../org.gradle.nativecode.base.NativeComponent.xml | 56 ++
....gradle.nativecode.base.SharedLibraryBinary.xml | 38 +
....gradle.nativecode.base.StaticLibraryBinary.xml | 38 +
.../dsl/org.gradle.nativecode.base.ToolChain.xml | 38 +
...rg.gradle.nativecode.base.ToolChainRegistry.xml | 44 ++
...adle.nativecode.base.tasks.AbstractLinkTask.xml | 59 ++
...e.nativecode.base.tasks.CreateStaticLibrary.xml | 50 ++
...dle.nativecode.base.tasks.InstallExecutable.xml | 50 ++
...gradle.nativecode.base.tasks.LinkExecutable.xml | 38 +
...dle.nativecode.base.tasks.LinkSharedLibrary.xml | 38 +
...adle.nativecode.language.asm.tasks.Assemble.xml | 47 ++
...nguage.base.tasks.AbstractNativeCompileTask.xml | 56 ++
...gradle.nativecode.language.c.tasks.CCompile.xml | 38 +
...language.cpp.plugins.CppExeConventionPlugin.xml | 38 +
...ativecode.language.cpp.plugins.CppExtension.xml | 41 ++
...language.cpp.plugins.CppLibConventionPlugin.xml | 38 +
...e.nativecode.language.cpp.plugins.CppPlugin.xml | 38 +
...le.nativecode.language.cpp.tasks.CppCompile.xml | 38 +
...ivecode.toolchain.plugins.GppCompilerPlugin.xml | 38 +
....toolchain.plugins.MicrosoftVisualCppPlugin.xml | 38 +
...g.gradle.plugins.ide.idea.model.IdeaProject.xml | 2 +-
...esting.jacoco.plugins.JacocoPluginExtension.xml | 50 ++
....testing.jacoco.plugins.JacocoTaskExtension.xml | 77 ++
.../org.gradle.testing.jacoco.tasks.JacocoBase.xml | 45 ++
...org.gradle.testing.jacoco.tasks.JacocoMerge.xml | 50 ++
...rg.gradle.testing.jacoco.tasks.JacocoReport.xml | 69 ++
subprojects/docs/src/docs/dsl/plugins.xml | 10 +
.../docs/src/docs/release/content/script.js | 26 +-
.../docs/src/docs/release/notes-template.md | 14 +-
subprojects/docs/src/docs/release/notes.md | 557 +++++++--------
subprojects/docs/src/docs/stylesheets/dslHtml.xsl | 10 +-
.../src/docs/stylesheets/userGuideHtmlCommon.xsl | 2 +-
.../docs/src/docs/userguide/artifactMngmt.xml | 4 +-
.../docs/src/docs/userguide/bootstrapPlugin.xml | 88 ---
.../docs/userguide/buildAnnouncementsPlugin.xml | 2 +-
.../src/docs/userguide/buildDashboardPlugin.xml | 20 +-
.../docs/src/docs/userguide/buildLifecycle.xml | 6 +-
.../docs/src/docs/userguide/buildSetupPlugin.xml | 177 +++++
.../docs/src/docs/userguide/comparingBuilds.xml | 4 +-
subprojects/docs/src/docs/userguide/cpp.xml | 174 ++++-
.../docs/src/docs/userguide/customTasks.xml | 142 ++++
subprojects/docs/src/docs/userguide/depMngmt.xml | 144 ++--
.../docs/src/docs/userguide/distributionPlugin.xml | 206 ++++--
.../docs/src/docs/userguide/eclipsePlugin.xml | 4 +-
.../docs/src/docs/userguide/gradleDaemon.xml | 4 +-
.../docs/src/docs/userguide/gradleWrapper.xml | 64 +-
.../docs/src/docs/userguide/groovyPlugin.xml | 70 +-
.../docs/src/docs/userguide/groovyTutorial.xml | 4 +-
subprojects/docs/src/docs/userguide/ideSupport.xml | 2 +-
subprojects/docs/src/docs/userguide/ideaPlugin.xml | 4 +-
.../src/docs/userguide/img/jacocoHtmlReport.png | Bin 0 -> 103803 bytes
.../docs/src/docs/userguide/initscripts.xml | 19 +-
.../docs/src/docs/userguide/jacocoPlugin.xml | 248 +++++++
.../userguide/javaLibraryDistributionPlugin.xml | 3 +-
subprojects/docs/src/docs/userguide/javaPlugin.xml | 38 +-
.../docs/src/docs/userguide/javaTutorial.xml | 8 +-
.../docs/src/docs/userguide/mavenPlugin.xml | 2 +-
.../docs/src/docs/userguide/multiproject.xml | 4 +-
.../docs/src/docs/userguide/organizeBuildLogic.xml | 2 +-
.../docs/src/docs/userguide/publishingIvy.xml | 47 +-
.../docs/src/docs/userguide/publishingMaven.xml | 33 +-
.../docs/src/docs/userguide/scalaPlugin.xml | 35 +-
.../docs/src/docs/userguide/sonarPlugin.xml | 40 +-
.../docs/src/docs/userguide/sonarRunnerPlugin.xml | 4 +-
.../docs/src/docs/userguide/standardPlugins.xml | 170 +++--
subprojects/docs/src/docs/userguide/tasks.xml | 84 ++-
.../docs/src/docs/userguide/thisAndThat.xml | 3 +-
subprojects/docs/src/docs/userguide/userguide.xml | 6 +-
subprojects/docs/src/docs/userguide/warPlugin.xml | 2 +-
.../docs/src/docs/userguide/workingWithFiles.xml | 41 +-
.../docs/src/docs/userguide/wrapperPlugin.xml | 59 ++
.../src/docs/userguide/writingBuildScripts.xml | 2 +-
.../docs/src/samples/buildDashboard/build.gradle | 2 +-
.../src/main/java/org/gradle/sample/Person.java | 15 +
.../docs/src/samples/codeQuality/build.gradle | 2 +-
.../src/samples/cpp/c-with-assembler/build.gradle | 46 ++
.../c-with-assembler/src/main/asm_i386_gcc/sum.s | 6 +
.../c-with-assembler/src/main/asm_i386_masm/sum.s | 12 +
.../c-with-assembler/src/main/asm_i386_osx/sum.s | 10 +
.../c-with-assembler/src/main/asm_x64_gcc/sum.s | 7 +
.../samples/cpp/c-with-assembler/src/main/c/main.c | 8 +
.../cpp/c-with-assembler/src/main/headers/sum.h | 1 +
subprojects/docs/src/samples/cpp/c/build.gradle | 80 +++
.../src/main/cpp/main.cpp => c/src/exe/c/main.c} | 0
.../docs/src/samples/cpp/c/src/lib/c/hello.c | 6 +
.../docs/src/samples/cpp/c/src/lib/headers/hello.h | 8 +
.../docs/src/samples/cpp/cpp-exe/build.gradle | 33 +
.../docs/src/samples/cpp/cpp-exe/settings.gradle | 1 +
.../cpp/{exe => cpp-exe}/src/main/cpp/hello.cpp | 0
.../docs/src/samples/cpp/cpp-lib/build.gradle | 14 +
.../docs/src/samples/cpp/cpp-lib/settings.gradle | 1 +
.../src/samples/cpp/cpp-lib/src/main/cpp/hello.cpp | 14 +
.../lib => cpp-lib}/src/main/headers/hello.h | 0
subprojects/docs/src/samples/cpp/cpp/build.gradle | 64 ++
.../exe/src/main => cpp/src/exe}/cpp/main.cpp | 0
.../docs/src/samples/cpp/cpp/src/lib/cpp/hello.cpp | 6 +
.../src/samples/cpp/cpp/src/lib/headers/hello.h | 7 +
.../docs/src/samples/cpp/dependencies/build.gradle | 12 +-
subprojects/docs/src/samples/cpp/exe/build.gradle | 11 -
.../docs/src/samples/cpp/exewithlib/build.gradle | 18 -
.../src/samples/cpp/multi-project/build.gradle | 18 +
.../exe/src/main/cpp/main.cpp | 0
.../lib/src/main/cpp/hello.cpp | 0
.../lib/src/main/headers/hello.h | 0
.../{exewithlib => multi-project}/settings.gradle | 0
.../docs/src/samples/cpp/variants/build.gradle | 39 ++
.../exe/src/main => variants/src/exe}/cpp/main.cpp | 0
.../src/samples/cpp/variants/src/lib/cpp/hello.cpp | 10 +
.../samples/cpp/variants/src/lib/headers/hello.h | 10 +
.../groovy/org/gradle/samples/ProductPlugin.groovy | 2 +-
.../samples/customDistribution/plugin/build.gradle | 2 +-
.../src/samples/customPlugin/plugin/build.gradle | 2 +-
.../main/groovy/org/gradle/GroovyJavaPerson.java | 3 -
.../src/main/groovy/org/gradle/GroovyPerson.groovy | 3 -
.../src/main/java/org/gradle/JavaPerson.java | 3 -
.../descriptor-customization/build.gradle | 4 +-
.../ivy-publish/java-multi-project/build.gradle | 2 +-
.../ivy-publish/multiple-publications/build.gradle | 83 +++
.../multiple-publications/output/project1.ivy.xml | 15 +
.../output/project2-api.ivy.xml | 13 +
.../output/project2-impl.ivy.xml | 16 +
.../multiple-publications/settings.gradle | 2 +
.../samples/ivy-publish/quickstart/build.gradle | 2 +-
.../java/org/gradle/webservice/TestTestTest.java | 3 -
.../docs/src/samples/java/quickstart/build.gradle | 8 +-
.../samples/maven-publish/javaProject/build.gradle | 2 +-
.../multiple-publications/build.gradle | 69 ++
.../multiple-publications/output/project1.pom.xml | 17 +
.../output/project2-api.pom.xml | 9 +
.../output/project2-impl.pom.xml | 23 +
.../multiple-publications/settings.gradle | 2 +
.../maven-publish/pomCustomization/build.gradle | 4 +-
.../samples/maven-publish/quickstart/build.gradle | 2 +-
.../multiProjectBuildSrc/buildSrc/build.gradle | 2 +-
subprojects/docs/src/samples/osgi/build.gradle | 4 +-
.../main/groovy/org/gradle/GradleActivator.groovy | 5 -
.../samples/sonarRunner/multiProject/build.gradle | 4 +-
.../samples/sonarRunner/quickstart/build.gradle | 4 +-
.../src/main => src/main/cpp/library}/cpp/main.cpp | 0
.../testing/jacoco/application/build.gradle | 35 +
.../src/main/java/org/gradle/MyMain.java | 30 +
.../samples/testing/jacoco/quickstart/build.gradle | 58 ++
.../src/main/java/org/gradle/Person.java | 24 +
.../src/test/java/org/gradle/PersonTest.java | 41 ++
.../samples/testing/junit/categories/build.gradle | 18 +
.../org/gradle/junit/CategorizedJUnitTest.java | 35 +
.../src/test/java/org/gradle/junit/CategoryA.java | 21 +
.../src/test/java/org/gradle/junit/CategoryB.java | 21 +
.../java/org/gradle/junit/SimpleJUnitTest.java | 27 +
.../src/samples/testing/testReport/build.gradle | 2 +-
.../src/samples/testing/testng/groups/build.gradle | 18 +
.../org/gradle/testng/SimpleIntegrationTest.java | 29 +
.../java/org/gradle/testng/SimpleUnitTest.java | 29 +
.../src/main/java/org/gradle/testng/User.java | 3 -
.../src/main/java/org/gradle/testng/UserImpl.java | 3 -
.../test/java/org/gradle/testng/UserImplTest.java | 3 -
.../toolingApi/customModel/plugin/build.gradle | 20 +
.../java/org/gradle/sample/plugin/CustomModel.java | 14 +
.../org/gradle/sample/plugin/CustomPlugin.java | 39 ++
.../org/gradle/sample/plugin/DefaultModel.java | 20 +
.../gradle-plugins/custom-plugin.properties | 1 +
.../src/samples/toolingApi/customModel/readme.xml | 3 +
.../customModel/sampleBuild/build.gradle | 10 +
.../customModel/sampleBuild/settings.gradle | 16 +
.../toolingApi/customModel/tooling/build.gradle | 22 +
.../src/main/java/org/gradle/sample/Main.java | 39 ++
.../src/main/java/org/gradle/sample/Main.java | 5 +-
.../idea/src/main/java/org/gradle/sample/Main.java | 3 +-
.../src/main/java/org/gradle/sample/Main.java | 5 +-
.../src/main/java/org/gradle/sample/Main.java | 3 -
.../artifacts/componentMetadata/build.gradle | 41 ++
.../repo/air.birds/albatros/1.9/ivy-1.9.xml | 9 +
.../repo/air.birds/albatros/2.0/ivy-2.0.xml | 9 +
.../repo/sea.fish/tuna/1.3/ivy-1.3.xml | 9 +
.../repo/sea.fish/tuna/1.4/ivy-1.4.xml | 9 +
.../repo/sea.fish/tuna/1.5/ivy-1.5.xml | 9 +
.../artifacts/defineRepository/build.gradle | 6 +
.../userguide/artifacts/uploading/build.gradle | 4 +-
.../samples/userguide/distribution/build.gradle | 36 +-
.../src/samples/userguide/files/copy/build.gradle | 15 +
.../userguide/groovy/groovyDependency/build.gradle | 6 -
.../userguide/initScripts/plugins/build.gradle | 27 +
.../userguide/initScripts/plugins/init.gradle | 34 +
.../firstMessages/messages/build.gradle | 1 +
.../firstMessages/messages/consumer/build.gradle | 3 +-
.../messages/build.gradle | 1 +
.../messages/consumer/build.gradle | 2 +-
.../messages/build.gradle | 1 +
.../messages/consumer/build.gradle | 3 +-
.../messages/build.gradle | 1 +
.../messages/consumer/build.gradle | 2 +-
.../messagesHack/messages/build.gradle | 1 +
.../messagesHack/messages/consumer/build.gradle | 3 +-
.../messagesTaskDependencies/messages/build.gradle | 1 +
.../messages/consumer/build.gradle | 3 +-
.../messagesWithDependencies/messages/build.gradle | 1 +
.../messages/consumer/build.gradle | 3 +-
.../multiproject/standardLayouts/settings.gradle | 2 +-
.../tasks/addToTaskContainer/build.gradle | 4 +-
.../tasks/customTaskWithProperty/build.gradle | 2 +-
.../userguide/tasks/finalizers/build.gradle | 8 +
.../tasks/finalizersWithFailure/build.gradle | 9 +
.../userguide/tasks/incrementalTask/build.gradle | 66 ++
.../userguide/tasks/mustRunAfter/build.gradle | 7 +
.../tutorial/groovyWithFlatDir/build.gradle | 10 +-
.../userguide/wrapper/customized/build.gradle | 4 -
.../samples/userguide/wrapper/simple/build.gradle | 2 +-
.../configurationHandlingAllFiles.out | 4 +-
.../samples/userguideOutput/customStatusScheme.out | 1 +
.../userguideOutput/externalDependencies.out | 4 +-
.../incrementalTaskChangedProperty.out | 4 +
.../userguideOutput/incrementalTaskFirstRun.out | 4 +
.../incrementalTaskNoChange.out} | 0
.../incrementalTaskRemovedInput.out | 2 +
.../incrementalTaskRemovedOutput.out | 4 +
.../incrementalTaskUpdatedInputs.out | 3 +
.../src/samples/userguideOutput/latestSelector.out | 3 +
.../src/samples/userguideOutput/mustRunAfter.out | 2 +
.../userguideOutput/mustRunAfterSingleTask.out | 1 +
.../publishingIvyGenerateDescriptor.out | 2 +-
.../publishingIvyPublishLifecycle.out | 2 +-
.../userguideOutput/publishingIvyPublishSingle.out | 2 +-
.../src/samples/userguideOutput/taskFinalizers.out | 2 +
.../userguideOutput/taskFinalizersWithFailure.out | 2 +
.../samples/userguideOutput/taskListAllReport.out | 5 +
.../src/samples/userguideOutput/taskListReport.out | 5 +
.../userguideOutput/usePluginsInInitScripts.out | 1 +
.../samples/webApplication/customised/readme.xml | 3 -
.../{customised => customized}/build.gradle | 0
.../samples/webApplication/customized/readme.xml | 3 +
.../src/additionalWebInf/additional.xml | 0
.../src/main/java/org/gradle/HelloServlet.java | 0
.../src/main/java/org/gradle/MyClass.java | 0
.../src/main/webapp/WEB-INF/webapp.xml | 0
.../src/main/webapp/webapp.html | 0
.../src/rootContent/root.txt | 0
.../{customised => customized}/src/someWeb.xml | 0
.../src/test/java/org/gradle/MyClassTest.java | 0
.../releasenotes/FunctionalReleaseNotesTest.groovy | 6 +-
.../docs/src/transforms/release-notes.gradle | 36 +-
subprojects/ear/ear.gradle | 1 -
.../plugins/ear/EarPluginIntegrationTest.groovy | 84 ++-
.../main/groovy/org/gradle/plugins/ear/Ear.groovy | 31 +-
.../groovy/org/gradle/plugins/ear/EarPlugin.java | 8 +-
.../ear/descriptor/DeploymentDescriptor.java | 2 -
.../gradle/plugins/ear/descriptor/EarModule.java | 2 -
.../plugins/ear/descriptor/EarSecurityRole.java | 2 -
.../plugins/ear/descriptor/EarWebModule.java | 2 -
.../internal/DefaultDeploymentDescriptor.groovy | 3 -
.../descriptor/internal/DefaultEarModule.groovy | 3 -
.../internal/DefaultEarSecurityRole.groovy | 3 -
.../descriptor/internal/DefaultEarWebModule.groovy | 3 -
.../org/gradle/plugins/ear/EarPluginTest.groovy | 16 +-
.../groovy/org/gradle/plugins/ear/EarTest.groovy | 8 +-
.../DefaultDeploymentDescriptorTest.groovy | 3 -
subprojects/ide/ide.gradle | 2 +-
.../ide/AutoTestedSamplesIntegrationTest.groovy | 3 -
.../eclipse/EclipseClasspathIntegrationTest.groovy | 3 -
.../ide/eclipse/EclipseEarIntegrationTest.groovy | 3 -
.../EclipseMultiModuleIntegrationTest.groovy | 3 -
.../eclipse/EclipseProjectIntegrationTest.groovy | 3 -
.../eclipse/EclipseWtpModelIntegrationTest.groovy | 3 -
.../plugins/ide/idea/IdeaIntegrationTest.groovy | 74 +-
.../ide/idea/IdeaMultiModuleIntegrationTest.groovy | 3 -
.../ide/idea/IdeaWorkspaceIntegrationTest.groovy | 3 -
.../expectedFiles/project1/project1.iml.xml | 32 -
.../expectedFiles/project2/project2.iml.xml | 32 -
.../expectedFiles/project3/project3.iml.xml | 32 -
.../expectedFiles/root.ipr.xml | 123 ----
.../plugins/ide/api/FileContentMerger.groovy | 2 -
.../plugins/ide/api/XmlFileContentMerger.groovy | 4 +-
.../plugins/ide/eclipse/EclipsePlugin.groovy | 6 +-
.../plugins/ide/eclipse/EclipseWtpPlugin.groovy | 9 +-
.../ide/eclipse/GenerateEclipseClasspath.groovy | 2 -
.../ide/eclipse/GenerateEclipseProject.groovy | 2 -
.../ide/eclipse/GenerateEclipseWtpComponent.groovy | 2 -
.../ide/eclipse/GenerateEclipseWtpFacet.groovy | 2 -
.../ide/eclipse/internal/EclipseNameDeduper.groovy | 3 -
.../eclipse/internal/LinkedResourcesCreator.groovy | 5 +-
.../eclipse/model/AbstractClasspathEntry.groovy | 3 -
.../ide/eclipse/model/AbstractLibrary.groovy | 3 -
.../plugins/ide/eclipse/model/AccessRule.groovy | 3 -
.../plugins/ide/eclipse/model/BuildCommand.groovy | 3 -
.../plugins/ide/eclipse/model/Classpath.groovy | 4 +-
.../plugins/ide/eclipse/model/ClasspathEntry.java | 2 -
.../plugins/ide/eclipse/model/Container.groovy | 3 -
.../ide/eclipse/model/EclipseClasspath.groovy | 4 +-
.../ide/eclipse/model/EclipseDomainModel.groovy | 2 -
.../plugins/ide/eclipse/model/EclipseJdt.groovy | 2 -
.../plugins/ide/eclipse/model/EclipseModel.groovy | 2 -
.../ide/eclipse/model/EclipseProject.groovy | 8 +-
.../plugins/ide/eclipse/model/EclipseWtp.groovy | 2 -
.../ide/eclipse/model/EclipseWtpComponent.groovy | 8 +-
.../ide/eclipse/model/EclipseWtpFacet.groovy | 6 +-
.../gradle/plugins/ide/eclipse/model/Facet.groovy | 3 -
.../plugins/ide/eclipse/model/Library.groovy | 3 -
.../gradle/plugins/ide/eclipse/model/Link.groovy | 3 -
.../gradle/plugins/ide/eclipse/model/Output.groovy | 3 -
.../plugins/ide/eclipse/model/Project.groovy | 2 -
.../ide/eclipse/model/ProjectDependency.groovy | 3 -
.../plugins/ide/eclipse/model/SourceFolder.groovy | 2 -
.../plugins/ide/eclipse/model/Variable.groovy | 3 -
.../ide/eclipse/model/WbDependentModule.groovy | 3 -
.../plugins/ide/eclipse/model/WbProperty.groovy | 3 -
.../plugins/ide/eclipse/model/WbResource.groovy | 3 -
.../plugins/ide/eclipse/model/WtpComponent.groovy | 2 -
.../plugins/ide/eclipse/model/WtpFacet.groovy | 2 -
.../model/internal/ClassFoldersCreator.groovy | 2 -
.../eclipse/model/internal/ClasspathFactory.groovy | 5 +-
.../model/internal/ExportedEntriesUpdater.groovy | 3 -
.../ide/eclipse/model/internal/PathUtil.groovy | 3 -
.../model/internal/ProjectDependencyBuilder.groovy | 3 -
.../model/internal/SourceFoldersCreator.groovy | 3 -
.../model/internal/WtpComponentFactory.groovy | 3 -
.../plugins/ide/idea/GenerateIdeaModule.groovy | 2 -
.../plugins/ide/idea/GenerateIdeaProject.groovy | 2 -
.../plugins/ide/idea/GenerateIdeaWorkspace.groovy | 2 -
.../org/gradle/plugins/ide/idea/IdeaPlugin.groovy | 9 +-
.../ide/idea/internal/IdeaNameDeduper.groovy | 3 -
.../ide/idea/internal/IdeaScalaConfigurer.groovy | 13 +-
.../gradle/plugins/ide/idea/model/Dependency.java | 2 -
.../ide/idea/model/IdeaLanguageLevel.groovy | 2 -
.../gradle/plugins/ide/idea/model/IdeaModel.groovy | 1 -
.../plugins/ide/idea/model/IdeaModule.groovy | 8 +-
.../plugins/ide/idea/model/IdeaModuleIml.groovy | 2 -
.../plugins/ide/idea/model/IdeaProject.groovy | 6 +-
.../plugins/ide/idea/model/IdeaWorkspace.groovy | 6 +-
.../plugins/ide/idea/model/JarDirectory.groovy | 2 -
.../org/gradle/plugins/ide/idea/model/Jdk.groovy | 2 -
.../gradle/plugins/ide/idea/model/Module.groovy | 2 -
.../plugins/ide/idea/model/ModuleDependency.groovy | 4 +-
.../plugins/ide/idea/model/ModuleLibrary.groovy | 4 +-
.../org/gradle/plugins/ide/idea/model/Path.groovy | 2 -
.../gradle/plugins/ide/idea/model/Project.groovy | 2 -
.../gradle/plugins/ide/idea/model/Workspace.groovy | 2 -
.../model/internal/IdeaDependenciesProvider.groovy | 3 -
.../model/internal/ModuleDependencyBuilder.groovy | 3 -
.../ide/internal/IdeDependenciesExtractor.groovy | 5 +-
.../gradle/plugins/ide/internal/IdePlugin.groovy | 2 +-
.../internal/JavadocAndSourcesDownloader.groovy | 11 +-
.../internal/configurer/DeduplicationTarget.groovy | 3 -
.../internal/configurer/ModuleNameDeduper.groovy | 1 -
.../ide/internal/configurer/ProjectDeduper.groovy | 3 -
.../internal/tooling/BasicIdeaModelBuilder.java | 33 +
.../ide/internal/tooling/EclipseModelBuilder.java | 151 ++++
.../ide/internal/tooling/GradleBuildBuilder.java | 54 ++
.../ide/internal/tooling/GradleProjectBuilder.java | 82 +++
.../ide/internal/tooling/IdeaModelBuilder.java | 138 ++++
.../plugins/ide/internal/tooling/TasksFactory.java | 46 ++
.../tooling/ToolingRegistrationAction.java | 32 +
.../eclipse/DefaultEclipseExternalDependency.java | 54 ++
.../eclipse/DefaultEclipseLinkedResource.java | 52 ++
.../tooling/eclipse/DefaultEclipseProject.java | 135 ++++
.../eclipse/DefaultEclipseProjectDependency.java | 44 ++
.../eclipse/DefaultEclipseSourceDirectory.java | 44 ++
.../tooling/eclipse/DefaultEclipseTask.java | 56 ++
.../tooling/idea/DefaultIdeaCompilerOutput.java | 65 ++
.../tooling/idea/DefaultIdeaContentRoot.java | 80 +++
.../tooling/idea/DefaultIdeaDependency.java | 22 +
.../tooling/idea/DefaultIdeaDependencyScope.java | 64 ++
.../tooling/idea/DefaultIdeaLanguageLevel.java | 82 +++
.../internal/tooling/idea/DefaultIdeaModule.java | 120 ++++
.../tooling/idea/DefaultIdeaModuleDependency.java | 61 ++
.../internal/tooling/idea/DefaultIdeaProject.java | 107 +++
.../DefaultIdeaSingleEntryLibraryDependency.java | 97 +++
.../tooling/idea/DefaultIdeaSourceDirectory.java | 43 ++
.../internal/idea/DefaultIdeaModuleDependency.java | 27 +
.../DefaultIdeaSingleEntryLibraryDependency.java | 27 +
.../internal/provider/BasicIdeaModelBuilder.java | 36 -
.../internal/provider/BuildModelAction.java | 88 ---
.../tooling/internal/provider/BuildsModel.java | 28 -
.../internal/provider/EclipseModelBuilder.java | 162 -----
.../internal/provider/FileOutcomeIdentifier.java | 41 --
.../internal/provider/GradleProjectBuilder.java | 80 ---
.../internal/provider/IdeaModelBuilder.java | 144 ----
.../internal/provider/NullResultBuilder.java | 30 -
.../provider/ProjectOutcomesModelBuilder.java | 71 --
...blishArtifactToFileBuildOutcomeTransformer.java | 98 ---
.../tooling/internal/provider/TasksFactory.java | 46 --
...le.configuration.project.ProjectConfigureAction | 1 +
.../plugins/ide/eclipse/EclipsePluginTest.groovy | 7 +-
.../ide/eclipse/EclipseWtpPluginTest.groovy | 7 +-
.../eclipse/GenerateEclipseClasspathTest.groovy | 3 -
.../eclipse/GenerateEclipseWtpComponentTest.groovy | 3 -
.../ide/eclipse/GenerateEclipseWtpFacetTest.groovy | 3 -
.../plugins/ide/eclipse/model/ClasspathTest.groovy | 3 -
.../plugins/ide/eclipse/model/ContainerTest.groovy | 3 -
.../ide/eclipse/model/EclipseModelTest.groovy | 3 -
.../ide/eclipse/model/EclipseProjectTest.groovy | 3 -
.../plugins/ide/eclipse/model/FacetTest.groovy | 7 +-
.../plugins/ide/eclipse/model/LibraryTest.groovy | 3 -
.../plugins/ide/eclipse/model/OutputTest.groovy | 3 -
.../ide/eclipse/model/ProjectDependencyTest.groovy | 3 -
.../plugins/ide/eclipse/model/ProjectTest.groovy | 3 -
.../ide/eclipse/model/SourceFolderTest.groovy | 3 -
.../plugins/ide/eclipse/model/VariableTest.groovy | 3 -
.../ide/eclipse/model/WbDependentModuleTest.groovy | 3 -
.../ide/eclipse/model/WbPropertyTest.groovy | 3 -
.../ide/eclipse/model/WbResourceTest.groovy | 3 -
.../ide/eclipse/model/WtpComponentTest.groovy | 3 -
.../plugins/ide/eclipse/model/WtpFacetTest.groovy | 3 -
.../internal/ProjectDependencyBuilderTest.groovy | 7 +-
.../ide/idea/ GenerateIdeaModuleTest.groovy | 11 +-
.../gradle/plugins/ide/idea/IdeaPluginTest.groovy | 25 +-
.../ide/idea/model/IdeaLanguageLevelTest.groovy | 3 -
.../ide/idea/model/ModuleDependencyTest.groovy | 3 -
.../ide/idea/model/ModuleLibraryTest.groovy | 3 -
.../plugins/ide/idea/model/ModuleTest.groovy | 3 -
.../ide/idea/model/ProjectLibraryTest.groovy | 7 +-
.../plugins/ide/idea/model/ProjectTest.groovy | 3 -
.../internal/ModuleDependencyBuilderTest.groovy | 7 +-
.../plugins/ide/internal/GeneratorTaskTest.groovy | 4 +-
.../plugins/ide/internal/IdePluginTest.groovy | 4 +-
.../configurer/DeduplicationTargetTest.groovy | 15 +-
.../configurer/ModuleNameDeduperTest.groovy | 3 -
.../internal/configurer/ProjectDeduperTest.groovy | 11 +-
.../internal/tooling/GradleBuildBuilderTest.groovy | 46 ++
.../tooling/GradleProjectBuilderTest.groovy | 42 ++
.../ide/internal/tooling/TasksFactoryTest.groovy | 52 ++
.../eclipse/DefaultEclipseProjectTest.groovy | 27 +
...rtifactToFileBuildOutcomeTransformerTest.groovy | 86 ---
.../internal/provider/TasksFactoryTest.groovy | 52 --
subprojects/integ-test/integ-test.gradle | 7 +-
...kCommandLineConfigurationIntegrationSpec.groovy | 252 -------
.../org/gradle/debug/GradleBuildRunner.groovy | 2 -
.../org/gradle/debug/GradleRunConfiguration.groovy | 2 -
.../integtests/ApplicationIntegrationSpec.groovy | 2 +-
.../integtests/ApplicationIntegrationTest.groovy | 146 ++++
.../BuildAggregationIntegrationTest.groovy | 5 +-
.../BuildScriptClasspathIntegrationTest.java | 1 -
.../BuildScriptErrorIntegrationTest.java | 108 ---
.../BuildScriptExecutionIntegrationTest.groovy | 1 -
.../integtests/CacheProjectIntegrationTest.groovy | 18 +-
.../integtests/CustomPluginIntegrationTest.groovy | 4 +-
.../DistributionLocatorIntegrationTest.groovy | 8 +-
.../ExternalScriptErrorIntegrationTest.groovy | 93 ---
.../ExternalScriptExecutionIntegrationTest.groovy | 2 -
...ementalGroovyProjectBuildIntegrationTest.groovy | 2 +-
.../IncrementalTasksIntegrationTest.groovy | 343 +++++++++
.../IncrementalTestIntegrationTest.groovy | 94 ---
.../integtests/InitScriptErrorIntegrationTest.java | 51 --
.../InitScriptExecutionIntegrationTest.groovy | 1 -
.../integtests/JavaProjectIntegrationTest.groovy | 10 +-
.../MixedNativeAndJvmProjectIntegrationTest.groovy | 39 ++
.../MultiProjectDependencyIntegrationTest.groovy | 12 +-
.../OsgiProjectSampleIntegrationTest.groovy | 5 +-
.../ParallelProjectExecutionIntegrationTest.groovy | 39 +-
.../PluginCrossVersionIntegrationTest.groovy | 72 --
.../integtests/ProfilingIntegrationTest.groovy | 41 --
.../integtests/ProjectLayoutIntegrationTest.groovy | 15 +-
.../SettingsScriptErrorIntegrationTest.java | 39 --
.../SettingsScriptExecutionIntegrationTest.groovy | 1 -
.../TaskDefinitionIntegrationSpec.groovy | 30 +
.../TaskErrorExecutionIntegrationTest.groovy | 8 +-
.../integtests/TaskExecutionIntegrationTest.groovy | 341 +++++++++
.../integtests/TaskExecutionIntegrationTest.java | 180 -----
...ssingBinaryCompatibilityCrossVersionSpec.groovy | 81 +++
.../integtests/WaterProjectIntegrationTest.groovy | 3 -
.../integtests/WebProjectIntegrationTest.java | 2 +-
.../BuildEnvironmentIntegrationTest.groovy | 3 -
.../fixture/TempDirIsUniquePerTestSpec.groovy | 3 -
.../logging/LoggingIntegrationTest.groovy | 36 -
.../ivy/IvyHttpPublishIntegrationTest.groovy | 141 ++--
.../ivy/IvyLocalPublishIntegrationTest.groovy | 5 +-
.../ivy/IvySFtpPublishIntegrationTest.groovy | 11 +-
.../IvyUrlResolverPublishIntegrationTest.groovy | 75 ++
.../ivy/SamplesIvyPublishIntegrationTest.groovy | 3 -
...SamplesMavenPomGenerationIntegrationTest.groovy | 5 +-
.../SamplesMavenQuickstartIntegrationTest.groovy | 3 -
.../AutoTestedSamplesCoreIntegrationTest.groovy | 3 -
.../AutoTestedSamplesPluginsIntegrationTest.groovy | 3 -
.../samples/JUnitSamplesIntegrationTest.groovy | 42 ++
.../SamplesCodeQualityIntegrationTest.groovy | 3 -
...lesExcludesAndClassifiersIntegrationTest.groovy | 3 -
...SamplesGroovyMultiProjectIntegrationTest.groovy | 3 -
.../samples/SamplesJUnitIntegrationTest.groovy | 44 ++
.../samples/SamplesJavaBaseIntegrationTest.groovy | 3 -
...mplesJavaCustomizedLayoutIntegrationTest.groovy | 3 -
.../SamplesJavaMultiProjectIntegrationTest.groovy | 3 -
...esJavaProjectWithIntTestsIntegrationTest.groovy | 3 -
.../SamplesJavaQuickstartIntegrationTest.groovy | 3 -
.../SamplesRepositoriesIntegrationTest.groovy | 3 -
.../SamplesWebProjectIntegrationTest.groovy | 11 +-
.../SamplesWebQuickstartIntegrationTest.groovy | 3 -
.../canExecuteCommands/canExecuteCommands.gradle | 4 +-
.../canExecuteJava/canExecuteJava.gradle | 4 +-
.../LoggingIntegrationTest/deprecated/build.gradle | 7 -
.../logging/project1/build.gradle | 8 +-
.../internal-integ-testing.gradle | 4 +-
.../fixtures/AbstractAutoTestedSamplesTest.groovy | 5 +-
.../fixtures/AbstractCompatibilityTestRunner.java | 18 +-
.../fixtures/AbstractIntegrationSpec.groovy | 14 +-
.../fixtures/AbstractMultiTestRunner.java | 314 ++++++---
.../fixtures/AutoTestedSamplesUtil.groovy | 3 -
.../integtests/fixtures/AvailableJavaHomes.java | 41 +-
.../fixtures/CrossVersionTestRunner.groovy | 2 +-
.../integtests/fixtures/IntegrationTestHint.java | 3 -
.../fixtures/KillProcessAvailability.groovy | 3 -
.../fixtures/TestNGExecutionResult.groovy | 11 +-
.../fixtures/UserGuideSamplesRunner.groovy | 12 +-
.../fixtures/executer/AnyOrderOutputMatcher.groovy | 51 ++
.../executer/DefaultGradleDistribution.java | 28 +-
.../executer/DependencyResolutionFailure.groovy | 3 -
.../executer/DetailedExecutionFailure.groovy | 5 +-
.../executer/DownloadableGradleDistribution.groovy | 3 +-
.../fixtures/executer/ExecutionResult.java | 2 +-
.../fixtures/executer/GradleDistribution.java | 5 +
.../fixtures/executer/InProcessGradleExecuter.java | 119 ++--
.../executer/InitScriptExecuterFixture.groovy | 7 +-
.../executer/OutputScrapingExecutionFailure.java | 80 ++-
.../executer/OutputScrapingExecutionResult.java | 7 +-
.../executer/ParallelForkingGradleHandle.java | 5 +-
.../fixtures/executer/ParallelOutputMatcher.groovy | 51 --
.../org/gradle/test/fixtures/AbstractModule.groovy | 77 ++
.../test/fixtures/ivy/AbstractIvyModule.groovy | 25 -
.../gradle/test/fixtures/ivy/IvyDescriptor.groovy | 2 +
.../gradle/test/fixtures/ivy/IvyFileModule.groovy | 71 +-
.../test/fixtures/ivy/IvyFileRepository.groovy | 8 +
.../gradle/test/fixtures/ivy/IvyHttpModule.groovy | 48 +-
.../org/gradle/test/fixtures/ivy/IvyModule.java | 11 +-
.../gradle/test/fixtures/maven/HttpArtifact.groovy | 4 +
.../test/fixtures/maven/MavenDependency.groovy | 5 +
.../test/fixtures/maven/MavenFileModule.groovy | 122 ++--
.../gradle/test/fixtures/maven/MavenModule.groovy | 3 +-
.../gradle/test/fixtures/maven/MavenScope.groovy | 2 +-
.../gradle/test/fixtures/publish/Identifier.java | 101 ---
.../test/fixtures/server/http/HttpServer.groovy | 27 +-
.../fixtures/server/http/ServletContainer.groovy | 43 ++
.../internal-testing/internal-testing.gradle | 3 +-
.../fixtures/DefaultTestExecutionResult.groovy | 8 +
.../fixtures/HtmlTestExecutionResult.groovy | 17 +-
.../fixtures/JUnitTestClassExecutionResult.groovy | 160 +++++
.../fixtures/JUnitXmlTestExecutionResult.groovy | 123 +---
.../fixtures/TestClassExecutionResult.java | 4 +
.../fixtures/TestResultOutputAssociation.java | 22 +
.../fixtures/archive/ArchiveTestFixture.groovy | 81 +++
.../test/fixtures/archive/JarTestFixture.groovy | 31 +
.../test/fixtures/archive/TarTestFixture.groovy | 41 ++
.../test/fixtures/archive/ZipTestFixture.groovy | 37 +
.../gradle/test/fixtures/encoding/Identifier.java | 100 +++
.../gradle/test/fixtures/file/ExecOutput.groovy | 29 +
.../org/gradle/test/fixtures/file/TestFile.java | 12 +-
.../test/fixtures/file/TestFileHelper.groovy | 14 +-
.../gradle/test/fixtures/file/WorkspaceTest.groovy | 34 +
.../gradle/testing/internal/util/Network.groovy | 29 -
.../main/groovy/org/gradle/util/Assertions.groovy | 3 -
.../org/gradle/util/JUnit4GroovyMockery.java | 3 -
.../org/gradle/util/ReflectionEqualsMatcher.java | 3 -
.../src/main/groovy/org/gradle/util/Resources.java | 2 +-
.../groovy/org/gradle/util/TestClassLoader.groovy | 62 ++
.../groovy/org/gradle/util/TestPrecondition.groovy | 18 +-
.../groovy/org/gradle/util/AssertionsTest.groovy | 3 -
.../gradle/util/TempDirIsUniquePerTestSpec.groovy | 3 -
subprojects/ivy/ivy.gradle | 2 +-
...IvyPublishArtifactCustomisationIntegTest.groovy | 321 ---------
...IvyPublishArtifactCustomizationIntegTest.groovy | 321 +++++++++
.../publish/ivy/IvyPublishBasicIntegTest.groovy | 5 +-
.../ivy/IvyPublishCoordinatesIntegTest.groovy | 132 ++++
.../IvyPublishCrossVersionIntegrationTest.groovy | 30 +-
...yPublishDescriptorCustomisationIntegTest.groovy | 147 ----
...yPublishDescriptorCustomizationIntegTest.groovy | 149 ++++
.../api/publish/ivy/IvyPublishHttpIntegTest.groovy | 145 ++--
.../IvyPublishIdentifierValidationIntegTest.groovy | 4 +-
.../api/publish/ivy/IvyPublishJavaIntegTest.groovy | 1 -
.../ivy/IvyPublishMultiProjectIntegTest.groovy | 56 ++
.../ivy/SamplesIvyPublishIntegrationTest.groovy | 42 +-
.../org/gradle/api/publish/ivy/IvyArtifactSet.java | 2 +-
.../api/publish/ivy/IvyConfigurationContainer.java | 2 +-
.../org/gradle/api/publish/ivy/IvyDependency.java | 15 +
.../api/publish/ivy/IvyModuleDescriptor.java | 10 +
.../org/gradle/api/publish/ivy/IvyPublication.java | 52 +-
.../ivy/internal/artifact/DefaultIvyArtifact.java | 5 +
.../artifact/IvyArtifactNotationParserFactory.java | 39 +-
.../internal/dependency/DefaultIvyDependency.java | 40 +-
.../internal/dependency/IvyDependencyInternal.java | 4 +-
...tionDynamicDescriptorGenerationTaskCreator.java | 9 +-
.../plugins/IvyPublishDynamicTaskCreator.java | 5 +-
.../publication/DefaultIvyModuleDescriptor.java | 3 +-
.../publication/DefaultIvyPublication.java | 46 +-
.../publication/IvyModuleDescriptorInternal.java | 4 -
.../publication/IvyPublicationInternal.java | 3 +-
.../publisher/ContextualizingIvyPublisher.java | 40 ++
.../publisher/DependencyResolverIvyPublisher.java | 16 +-
.../publisher/IvyDescriptorFileGenerator.java | 22 +-
.../internal/publisher/ValidatingIvyPublisher.java | 19 +-
.../api/publish/ivy/plugins/IvyPublishPlugin.java | 22 +-
.../publish/ivy/tasks/PublishToIvyRepository.java | 10 +-
.../IvyArtifactNotationParserFactoryTest.groovy | 9 +-
...namicDescriptorGenerationTaskCreatorTest.groovy | 8 +-
.../IvyPublishDynamicTaskCreatorTest.groovy | 4 +-
.../publication/DefaultIvyPublicationTest.groovy | 195 +++++-
.../IvyDescriptorFileGeneratorTest.groovy | 34 +-
.../publisher/ValidatingIvyPublisherTest.groovy | 3 +-
.../ivy/plugins/IvyPublishPluginTest.groovy | 14 +-
.../ivy/tasks/PublishToIvyRepositoryTest.groovy | 6 +-
subprojects/jacoco/jacoco.gradle | 27 +
.../plugins/JacocoPluginGoodBehaviourTest.groovy | 33 +
.../plugins/JacocoPluginIntegrationTest.groovy | 199 ++++++
.../jacoco/plugins/JacocoVersionIntegTest.groovy | 69 ++
.../gradle/internal/jacoco/JacocoAgentJar.groovy | 57 ++
.../jacoco/JacocoReportsContainerImpl.java | 49 ++
.../testing/jacoco/plugins/JacocoPlugin.groovy | 188 +++++
.../jacoco/plugins/JacocoPluginExtension.groovy | 87 +++
.../jacoco/plugins/JacocoTaskExtension.groovy | 189 +++++
.../gradle/testing/jacoco/tasks/JacocoBase.groovy | 33 +
.../gradle/testing/jacoco/tasks/JacocoMerge.groovy | 92 +++
.../testing/jacoco/tasks/JacocoReport.groovy | 258 +++++++
.../jacoco/tasks/JacocoReportsContainer.java | 47 ++
.../gradle/testing/jacoco/tasks/package-info.java | 20 +
.../META-INF/gradle-plugins/jacoco.properties | 1 +
.../testing/jacoco/plugins/JacocoPluginSpec.groovy | 59 ++
.../jacoco/plugins/JacocoTaskExtensionSpec.groovy | 99 +++
subprojects/javascript/javascript.gradle | 2 +-
.../coffeescript/CoffeeScriptBasePlugin.groovy | 2 +-
.../plugins/javascript/envjs/EnvJsPlugin.groovy | 2 +-
.../plugins/javascript/jshint/JsHintPlugin.groovy | 2 +-
subprojects/jetty/jetty.gradle | 2 +-
.../api/plugins/jetty/AbstractJettyRunTask.java | 41 +-
.../org/gradle/api/plugins/jetty/JettyPlugin.java | 8 +-
.../api/plugins/jetty/JettyPluginConvention.java | 2 -
.../org/gradle/api/plugins/jetty/JettyRun.java | 4 +-
.../api/plugins/jetty/JettyPluginTest.groovy | 8 +-
subprojects/language-base/language-base.gradle | 7 +
.../groovy/org/gradle/language/base/Binary.java | 28 +
.../org/gradle/language/base/BinaryContainer.java | 25 +
.../language/base/BuildableModelElement.java | 39 ++
.../gradle/language/base/FunctionalSourceSet.java | 27 +
.../gradle/language/base/LanguageSourceSet.java | 41 ++
.../org/gradle/language/base/ProjectSourceSet.java | 26 +
.../internal/AbstractBuildableModelElement.java | 51 ++
.../language/base/internal/BinaryInternal.java | 23 +
.../language/base/internal/BinaryNamingScheme.java | 31 +
.../base/internal/DefaultBinaryContainer.java | 27 +
.../base/internal/DefaultBinaryNamingScheme.java | 106 +++
.../base/internal/DefaultFunctionalSourceSet.java | 34 +
.../base/internal/DefaultProjectSourceSet.java | 32 +
.../base/internal/LanguageSourceSetInternal.java | 29 +
.../org/gradle/language/base/package-info.java | 23 +
.../language/base/plugins/LanguageBasePlugin.java | 59 ++
.../gradle/language/base/plugins/package-info.java | 23 +
.../base/internal/BuildableModelElementTest.groovy | 54 ++
.../internal/DefaultBinaryNamingSchemeTest.groovy | 69 ++
subprojects/language-jvm/language-jvm.gradle | 7 +
.../org/gradle/language/java/JavaSourceSet.java | 28 +
.../java/internal/DefaultJavaSourceSet.java | 78 +++
.../org/gradle/language/java/package-info.java | 23 +
.../gradle/language/jvm/ClassDirectoryBinary.java | 40 ++
.../groovy/org/gradle/language/jvm/Classpath.java | 28 +
.../org/gradle/language/jvm/ResourceSet.java | 25 +
.../internal/ClassDirectoryBinaryNamingScheme.java | 63 ++
.../jvm/internal/DefaultClassDirectoryBinary.java | 79 +++
.../language/jvm/internal/DefaultClasspath.java | 39 ++
.../language/jvm/internal/DefaultResourceSet.java | 60 ++
.../jvm/internal/SimpleStaleClassCleaner.java | 38 +
.../language/jvm/internal/StaleClassCleaner.java | 43 ++
.../org/gradle/language/jvm/package-info.java | 23 +
.../language/jvm/plugins/JvmLanguagePlugin.java | 107 +++
.../gradle/language/jvm/plugins/package-info.java | 23 +
.../language/jvm/tasks/ProcessResources.java | 35 +
.../gradle/language/jvm/tasks/package-info.java | 23 +
.../java/internal/DefaultJavaSourceSetTest.groovy | 33 +
.../ClassDirectoryBinaryNamingSchemeTest.groovy | 62 ++
.../DefaultClassDirectoryBinaryTest.groovy | 78 +++
.../jvm/internal/DefaultResourceSetTest.groovy | 32 +
subprojects/launcher/launcher.gradle | 12 +-
.../ConfigurationOnDemandIntegrationTest.groovy | 3 -
...EnablingParallelExecutionIntegrationTest.groovy | 3 -
.../GradleConfigurabilityIntegrationSpec.groovy | 4 -
.../daemon/DaemonFeedbackIntegrationSpec.groovy | 3 -
...itialCommunicationFailureIntegrationSpec.groovy | 3 -
.../launcher/daemon/DaemonIntegrationSpec.groovy | 3 -
.../launcher/daemon/DaemonLifecycleSpec.groovy | 2 +-
.../daemon/DispachingFailureIntegrationSpec.groovy | 3 -
.../launcher/daemon/EmbeddedDaemonSmokeTest.groovy | 4 +-
.../gradle/launcher/daemon/ExecuteBuildAction.java | 28 +
.../daemon/SingleUseDaemonIntegrationTest.groovy | 3 +-
.../daemon/StoppingDaemonIntegrationSpec.groovy | 3 -
.../daemon/testing/DaemonContextParser.java | 3 -
.../daemon/testing/DaemonLogsAnalyzer.groovy | 3 -
.../main/java/org/gradle/launcher/GradleMain.java | 3 -
.../src/main/java/org/gradle/launcher/Main.java | 4 +-
.../launcher/bootstrap/ProcessBootstrap.java | 6 +-
.../gradle/launcher/cli/BuildActionsFactory.java | 93 ++-
.../gradle/launcher/cli/ExecuteBuildAction.java | 20 +-
.../org/gradle/launcher/cli/RunBuildAction.java | 6 +-
.../cli/converter/DaemonCommandLineConverter.java | 50 ++
.../cli/converter/LayoutToPropertiesConverter.java | 73 ++
.../PropertiesToDaemonParametersConverter.java | 68 ++
.../PropertiesToStartParameterConverter.java | 36 +
.../launcher/daemon/DaemonExecHandleBuilder.java | 3 -
.../launcher/daemon/bootstrap/DaemonGreeter.java | 3 -
.../daemon/bootstrap/DaemonOutputConsumer.java | 3 -
.../bootstrap/DaemonStartupCommunication.java | 3 -
.../launcher/daemon/client/DaemonClient.java | 30 +-
.../daemon/client/DaemonClientConnection.java | 42 +-
.../daemon/client/DaemonClientServicesSupport.java | 11 +-
.../daemon/client/DaemonConnectionException.java | 30 +
.../launcher/daemon/client/DaemonConnector.java | 9 +-
.../client/DaemonInitialConnectException.java | 4 +
.../daemon/client/DefaultDaemonConnector.java | 61 +-
.../client/EmbeddedDaemonClientServices.java | 10 +-
.../client/NoUsableDaemonFoundException.java | 3 -
.../daemon/client/SingleUseDaemonClient.java | 17 +-
.../daemon/client/StaleDaemonAddressException.java | 29 +
.../daemon/client/StopDaemonClientServices.java | 2 +-
.../launcher/daemon/client/StopDispatcher.java | 3 -
.../daemon/configuration/DaemonParameters.java | 40 +-
.../configuration/DaemonServerConfiguration.java | 3 -
.../DefaultDaemonServerConfiguration.java | 3 -
.../ForegroundDaemonConfiguration.java | 3 -
.../daemon/configuration/GradleProperties.java | 177 +----
.../configuration/GradlePropertiesConfigurer.java | 48 --
.../daemon/diagnostics/DaemonDiagnostics.java | 2 -
.../daemon/diagnostics/DaemonStartupInfo.java | 3 -
.../org/gradle/launcher/daemon/protocol/Build.java | 8 +-
.../launcher/daemon/protocol/BuildAndStop.java | 4 +-
.../daemon/registry/DaemonRegistryContent.java | 3 -
.../daemon/registry/DaemonRegistryServices.java | 5 +-
.../daemon/registry/PersistentDaemonRegistry.java | 30 +-
.../launcher/daemon/server/DaemonServices.java | 8 +-
.../daemon/server/DomainRegistryUpdater.java | 3 -
.../server/SynchronizedDispatchConnection.java | 2 -
.../launcher/daemon/server/exec/ExecuteBuild.java | 4 +-
.../daemon/server/exec/ForwardClientInput.java | 4 +-
.../gradle/launcher/exec/BuildActionExecuter.java | 29 +
.../exec/GradleLauncherActionExecuter.java | 29 -
.../exec/InProcessBuildActionExecuter.java | 77 ++
.../InProcessGradleLauncherActionExecuter.java | 46 --
.../gradle/launcher/exec/InitializationAware.java | 22 -
.../internal/provider/BuildActionResult.java | 33 +
.../internal/provider/BuildModelAction.java | 99 +++
.../internal/provider/ClassLoaderDetails.java | 36 +
.../internal/provider/ClasspathInferer.java | 131 ++++
.../provider/ClientProvidedBuildAction.java | 81 +++
.../ClientSidePayloadClassLoaderRegistry.java | 142 ++++
.../internal/provider/ConfiguringBuildAction.java | 47 +-
.../internal/provider/ConnectionScopeServices.java | 47 ++
.../provider/DaemonBuildActionExecuter.java | 47 ++
.../DaemonGradleLauncherActionExecuter.java | 47 --
.../internal/provider/DefaultBuildController.java | 61 ++
.../internal/provider/DefaultConnection.java | 200 +++---
.../provider/DefaultConnectionMetaData.java | 30 +
.../DefaultPayloadClassLoaderRegistry.java | 174 +++++
.../provider/DelegatingBuildModelAction.java | 58 --
.../tooling/internal/provider/DeserializeMap.java | 24 +
.../internal/provider/EmbeddedExecuterSupport.java | 45 --
.../internal/provider/ExecuteBuildAction.java | 33 -
.../LoggingBridgingBuildActionExecuter.java | 75 ++
...oggingBridgingGradleLauncherActionExecuter.java | 75 --
.../internal/provider/ModelClassLoaderFactory.java | 126 ++++
.../provider/PayloadClassLoaderRegistry.java | 26 +
.../internal/provider/PayloadSerializer.java | 155 +++++
.../internal/provider/ProviderConnection.java | 165 +++++
.../internal/provider/ReflectionClassLookup.java | 44 ++
.../tooling/internal/provider/SerializeMap.java | 36 +
.../internal/provider/SerializedPayload.java | 37 +
.../provider/ToolingGlobalScopeServices.java | 27 +
.../tooling/internal/provider/ToolingServices.java | 27 +
.../connection/AdaptedOperationParameters.java | 5 +-
.../connection/ProviderOperationParameters.java | 2 -
.../internal/provider/jdk6/Jdk6ClassLookup.java | 27 +
...e.internal.service.scopes.PluginServiceRegistry | 1 +
.../launcher/cli/BuildActionsFactoryTest.groovy | 53 +-
.../gradle/launcher/cli/RunBuildActionTest.groovy | 4 +-
.../DaemonCommandLineConverterTest.groovy | 39 ++
.../LayoutToPropertiesConverterTest.groovy | 95 +++
...ropertiesToDaemonParametersConverterTest.groovy | 106 +++
.../PropertiesToStartParameterConverterTest.groovy | 36 +
.../daemon/DaemonExecHandleBuilderSpec.groovy | 3 -
.../daemon/bootstrap/DaemonGreeterTest.groovy | 3 -
.../bootstrap/DaemonOutputConsumerTest.groovy | 3 -
.../DaemonStartupCommunicationSpec.groovy | 3 -
.../client/DaemonClientConnectionTest.groovy | 78 ++-
.../daemon/client/DaemonClientServicesTest.groovy | 3 +-
.../launcher/daemon/client/DaemonClientTest.groovy | 18 +-
.../client/DefaultDaemonConnectorTest.groovy | 37 +-
.../daemon/client/StopDispatcherTest.groovy | 5 +-
.../daemon/configuration/CurrentProcessTest.groovy | 3 +-
.../configuration/DaemonParametersTest.groovy | 82 +--
.../GradlePropertiesConfigurerTest.groovy | 77 --
.../configuration/GradlePropertiesTest.groovy | 218 ------
.../diagnostics/DaemonDiagnosticsTest.groovy | 3 -
.../registry/DomainRegistryUpdaterTest.groovy | 3 -
.../registry/PersistentDaemonRegistryTest.groovy | 34 +-
.../DaemonServerExceptionHandlingTest.groovy | 17 +-
.../server/DaemonStateCoordinatorTest.groovy | 3 -
.../exec/DefaultBuildActionParametersTest.groovy | 8 +-
.../exec/InProcessBuildActionExecuterTest.groovy | 156 +++++
...nProcessGradleLauncherActionExecuterTest.groovy | 100 ---
.../provider/AbstractClassGraphSpec.groovy | 63 ++
.../internal/provider/ClasspathInfererTest.groovy | 66 ++
.../provider/ConfiguringBuildActionTest.groovy | 36 +-
.../provider/ConnectionScopeServicesTest.groovy | 34 +
.../tooling/internal/provider/CustomAction.java | 34 +
.../tooling/internal/provider/CustomModel.java | 24 +
.../tooling/internal/provider/CustomPayload.java | 29 +
.../provider/DaemonBuildActionExecuterTest.groovy | 45 ++
.../DaemonGradleLauncherActionExecuterTest.groovy | 45 --
.../provider/DefaultBuildControllerTest.groovy | 92 +++
.../provider/ExecuteBuildActionTest.groovy | 37 -
.../LoggingBridgingBuildActionExecuterTest.groovy | 74 ++
...BridgingGradleLauncherActionExecuterTest.groovy | 74 --
.../provider/ModelClassLoaderFactoryTest.groovy | 36 +
.../internal/provider/PayloadInterface.java | 21 +
.../internal/provider/PayloadSerializerTest.groovy | 204 ++++++
.../provider/ToolingGlobalScopeServicesTest.groovy | 28 +
.../tooling/internal/provider/WrapperPayload.java | 27 +
.../AdaptedOperationParametersTest.groovy | 3 -
.../connection/BuildLogLevelMixInTest.groovy | 3 -
subprojects/maven/maven.gradle | 2 +-
.../maven/MavenConversionIntegrationTest.groovy | 161 -----
.../maven/AbstractMavenPublishIntegTest.groovy | 11 +-
...venPublishArtifactCustomisationIntegTest.groovy | 228 ------
...venPublishArtifactCustomizationIntegTest.groovy | 255 +++++++
.../maven/MavenPublishBasicIntegTest.groovy | 8 +-
.../maven/MavenPublishCoordinatesIntegTest.groovy | 140 ++++
.../MavenPublishCrossVersionIntegrationTest.groovy | 21 +-
...avenPublishIdentifierValidationIntegTest.groovy | 4 +-
.../maven/MavenPublishIssuesIntegTest.groovy | 51 ++
.../publish/maven/MavenPublishJavaIntegTest.groovy | 30 +-
.../maven/MavenPublishMultiProjectIntegTest.groovy | 88 ++-
.../MavenPublishPomCustomisationIntegTest.groovy | 174 -----
.../MavenPublishPomCustomizationIntegTest.groovy | 206 ++++++
.../SamplesMavenPublishIntegrationTest.groovy | 42 +-
.../api/artifacts/maven/Conf2ScopeMapping.java | 2 -
.../maven/Conf2ScopeMappingContainer.java | 10 +-
.../api/artifacts/maven/GroovyMavenDeployer.java | 2 -
.../gradle/api/artifacts/maven/MavenDeployer.java | 6 +-
.../api/artifacts/maven/MavenDeployment.java | 2 +-
.../org/gradle/api/artifacts/maven/MavenPom.java | 34 +-
.../gradle/api/artifacts/maven/MavenResolver.java | 4 +-
.../api/artifacts/maven/PomFilterContainer.java | 40 +-
.../gradle/api/artifacts/maven/PublishFilter.java | 2 -
.../groovy/org/gradle/api/plugins/MavenPlugin.java | 6 +-
.../gradle/api/plugins/MavenPluginConvention.java | 2 -
.../plugins/MavenRepositoryHandlerConvention.java | 2 +-
.../api/plugins/maven/ConvertMaven2Gradle.groovy | 54 --
.../api/plugins/maven/Maven2GradlePlugin.groovy | 36 -
.../api/plugins/maven/internal/Maven2Gradle.groovy | 552 ---------------
.../maven/internal/MavenProjectXmlWriter.java | 61 --
.../maven/internal/MavenProjectsCreator.java | 98 ---
.../publication/maven/internal/ArtifactPom.java | 3 -
.../maven/internal/ArtifactPomContainer.java | 3 -
.../maven/internal/ArtifactPomFactory.java | 3 -
.../maven/internal/BasePomFilterContainer.java | 3 -
.../maven/internal/DefaultArtifactPom.java | 3 -
.../internal/DefaultArtifactPomContainer.java | 3 -
.../maven/internal/DefaultArtifactPomFactory.java | 3 -
.../DefaultConf2ScopeMappingContainer.java | 5 +-
.../maven/internal/DefaultMavenDeployment.java | 3 -
.../maven/internal/DefaultMavenPom.java | 5 +-
.../maven/internal/DefaultMavenPomFactory.java | 5 +-
.../maven/internal/DefaultPomFilter.java | 3 -
.../maven/internal/ExcludeRuleConverter.java | 3 -
.../maven/internal/PomDependenciesConverter.java | 3 -
.../api/publication/maven/internal/PomFilter.java | 3 -
.../maven/internal/ant/AbstractMavenResolver.java | 13 +-
.../maven/internal/ant/BaseMavenDeployer.java | 5 +-
.../maven/internal/ant/BaseMavenInstaller.java | 5 +-
.../maven/internal/ant/CustomDeployTask.java | 2 -
.../ant/CustomInstallDeployTaskSupport.java | 5 +-
.../maven/internal/ant/CustomInstallTask.java | 3 -
.../internal/ant/DefaultDeployTaskFactory.java | 3 -
.../internal/ant/DefaultExcludeRuleConverter.java | 3 -
.../internal/ant/DefaultGroovyMavenDeployer.groovy | 4 -
.../internal/ant/DefaultInstallTaskFactory.java | 3 -
.../ant/DefaultPomDependenciesConverter.java | 3 -
.../internal/ant/EmptyMavenSettingsSupplier.java | 3 -
.../maven/internal/ant/LoggingHelper.java | 3 -
.../maven/internal/ant/MavenSettingsSupplier.java | 3 -
.../ant/MaybeUserMavenSettingsSupplier.java | 3 -
.../maven/internal/ant/RepositoryBuilder.java | 3 -
.../maven/internal/ant/RepositoryFactory.java | 3 -
.../gradle/api/publish/maven/MavenArtifactSet.java | 2 +-
.../gradle/api/publish/maven/MavenDependency.java | 41 ++
.../org/gradle/api/publish/maven/MavenPom.java | 13 +-
.../gradle/api/publish/maven/MavenPublication.java | 38 +-
.../internal/artifact/DefaultMavenArtifact.java | 5 +
.../dependencies/DefaultMavenDependency.java | 56 ++
.../dependencies/MavenDependencyInternal.java | 25 +
.../internal/plugins/GeneratePomTaskCreator.java | 4 +-
.../plugins/MavenPublishDynamicTaskCreator.java | 5 +-
.../MavenPublishLocalDynamicTaskCreator.java | 7 +-
.../internal/publication/DefaultMavenPom.java | 14 +-
.../publication/DefaultMavenPublication.java | 63 +-
.../internal/publication/MavenPomInternal.java | 6 +-
.../publication/MavenPublicationInternal.java | 7 +-
.../publisher/AntTaskBackedMavenPublisher.java | 2 +-
.../publisher/MavenDeployerConfigurer.java | 55 --
.../publisher/MavenRemoteRepositoryFactory.java | 50 ++
.../publisher/ValidatingMavenPublisher.java | 22 +-
.../internal/tasks/MavenPomFileGenerator.java | 87 +--
.../publish/maven/plugins/MavenPublishPlugin.java | 12 +-
.../api/publish/maven/tasks/GenerateMavenPom.java | 37 +-
.../gradle-plugins/maven2Gradle.properties | 1 -
.../api/artifacts/maven/Conf2ScopeMappingTest.java | 3 -
.../api/plugins/MavenPluginConventionTest.groovy | 14 +-
.../org/gradle/api/plugins/MavenPluginTest.java | 9 +-
.../plugins/maven/Maven2GradlePluginSpec.groovy | 36 -
.../internal/MavenProjectXmlWriterTest.groovy | 34 -
.../maven/internal/MavenProjectsCreatorSpec.groovy | 118 ----
.../maven/internal/BasePomFilterContainerTest.java | 3 -
.../maven/internal/DefaultArtifactPomTest.java | 3 -
.../DefaultConf2ScopeMappingContainerTest.java | 3 -
.../internal/DefaultMavenPomFactoryTest.groovy | 7 +-
.../maven/internal/DefaultPomFilterTest.java | 3 -
.../internal/ant/AbstractMavenResolverTest.java | 5 +-
.../maven/internal/ant/BaseMavenDeployerTest.java | 5 +-
.../maven/internal/ant/BaseMavenInstallerTest.java | 5 +-
.../internal/ant/DefaultDeployTaskFactoryTest.java | 7 +-
.../ant/DefaultExcludeRuleConverterTest.java | 3 -
.../ant/DefaultGroovyMavenDeployerTest.groovy | 5 +-
.../ant/DefaultGroovyPomFilterContainerTest.groovy | 7 +-
.../ant/DefaultPomDependenciesConverterTest.java | 3 -
.../ant/EmptyMavenSettingsSupplierTest.groovy | 3 -
.../ant/MaybeUserMavenSettingsSupplierTest.groovy | 4 -
...ectDependencyArtifactIdExtractorHackTest.groovy | 5 +-
.../MavenArtifactNotationParserFactoryTest.groovy | 4 +-
.../publication/DefaultMavenPublicationTest.groovy | 179 ++++-
.../publisher/ValidatingMavenPublisherTest.groovy | 41 +-
.../tasks/MavenPomFileGeneratorTest.groovy | 70 +-
.../maven/plugins/MavenPublishPluginTest.groovy | 18 +-
.../tasks/PublishToMavenRepositoryTest.groovy | 6 +-
subprojects/messaging/messaging.gradle | 2 +-
.../messaging/serialize/AbstractDecoder.java | 60 ++
.../messaging/serialize/AbstractEncoder.java | 56 ++
.../serialize/DataStreamBackedSerializer.java | 36 -
.../org/gradle/messaging/serialize/Decoder.java | 106 +++
.../messaging/serialize/DefaultSerializer.java | 12 +-
.../org/gradle/messaging/serialize/Encoder.java | 85 +++
.../messaging/serialize/FlushableEncoder.java | 24 +
.../serialize/InputStreamBackedDecoder.java | 79 +++
.../gradle/messaging/serialize/LongSerializer.java | 29 +
.../serialize/OutputStreamBackedEncoder.java | 85 +++
.../org/gradle/messaging/serialize/Serializer.java | 7 +-
.../serialize/kryo/KryoBackedDecoder.java | 121 ++++
.../serialize/kryo/KryoBackedEncoder.java | 77 ++
.../messaging/serialize/AbstractCodecTest.groovy | 387 +++++++++++
.../serialize/DefaultSerializerTest.groovy | 8 +-
.../messaging/serialize/LongSerializerTest.groovy | 34 +
.../serialize/StreamBackedCodecTest.groovy | 31 +
.../serialize/kryo/KryoBackedCodecTest.groovy | 36 +
.../messaging/serialize/SerializerSpec.groovy | 30 +
subprojects/native/native.gradle | 3 +-
.../nativeplatform/ReflectiveEnvironment.java | 2 -
.../filesystem/FileSystemServices.java | 5 +-
.../nativeplatform/jna/JnaBootPathConfigurer.java | 3 -
subprojects/open-api/open-api.gradle | 2 +-
...CrossVersionCompatibilityIntegrationTest.groovy | 4 +-
.../integtests/openapi/OutputUILordTest.groovy | 2 -
.../TestAlternateUIInteractionVersion1.java | 2 -
.../openapi/TestSettingsNodeVersion1.java | 2 -
.../TestSingleDualPaneUIInteractionVersion1.java | 1 -
.../org/gradle/foundation/BootstrapLoader.java | 189 -----
.../gradle/foundation/ParentLastClassLoader.java | 73 --
.../gradle/openapi/external/ExternalUtility.java | 168 -----
.../foundation/GradleInterfaceVersion1.java | 89 ---
.../foundation/GradleInterfaceVersion2.java | 89 ---
.../external/foundation/ProjectVersion1.java | 83 ---
.../foundation/RequestObserverVersion1.java | 52 --
.../external/foundation/RequestVersion1.java | 62 --
.../openapi/external/foundation/TaskVersion1.java | 61 --
.../foundation/favorites/FavoriteTaskVersion1.java | 48 --
.../favorites/FavoritesEditorVersion1.java | 105 ---
.../external/runner/GradleRunnerFactory.java | 134 ----
.../runner/GradleRunnerInteractionVersion1.java | 83 ---
.../external/runner/GradleRunnerVersion1.java | 35 -
.../ui/AlternateUIInteractionVersion1.java | 59 --
.../openapi/external/ui/BasicGradleUIVersion1.java | 199 ------
...ommandLineArgumentAlteringListenerVersion1.java | 32 -
.../external/ui/DualPaneUIInteractionVersion1.java | 29 -
.../openapi/external/ui/DualPaneUIVersion1.java | 56 --
.../openapi/external/ui/GradleTabVersion1.java | 51 --
.../external/ui/GradleUIInteractionVersion1.java | 42 --
.../external/ui/OutputObserverVersion1.java | 56 --
.../openapi/external/ui/OutputUILordVersion1.java | 70 --
.../openapi/external/ui/SettingsNodeVersion1.java | 67 --
.../ui/SinglePaneUIInteractionVersion1.java | 29 -
.../openapi/external/ui/SinglePaneUIVersion1.java | 39 --
.../org/gradle/openapi/external/ui/UIFactory.java | 239 -------
.../org/gradle/foundation/BootstrapLoader.java | 187 +++++
.../gradle/foundation/ParentLastClassLoader.java | 72 ++
.../gradle/openapi/external/ExternalUtility.java | 166 +++++
.../foundation/GradleInterfaceVersion1.java | 89 +++
.../foundation/GradleInterfaceVersion2.java | 88 +++
.../external/foundation/ProjectVersion1.java | 83 +++
.../foundation/RequestObserverVersion1.java | 52 ++
.../external/foundation/RequestVersion1.java | 62 ++
.../openapi/external/foundation/TaskVersion1.java | 61 ++
.../foundation/favorites/FavoriteTaskVersion1.java | 45 ++
.../favorites/FavoritesEditorVersion1.java | 105 +++
.../external/runner/GradleRunnerFactory.java | 133 ++++
.../runner/GradleRunnerInteractionVersion1.java | 85 +++
.../external/runner/GradleRunnerVersion1.java | 35 +
.../ui/AlternateUIInteractionVersion1.java | 59 ++
.../openapi/external/ui/BasicGradleUIVersion1.java | 199 ++++++
...ommandLineArgumentAlteringListenerVersion1.java | 32 +
.../external/ui/DualPaneUIInteractionVersion1.java | 30 +
.../openapi/external/ui/DualPaneUIVersion1.java | 59 ++
.../openapi/external/ui/GradleTabVersion1.java | 48 ++
.../external/ui/GradleUIInteractionVersion1.java | 41 ++
.../external/ui/OutputObserverVersion1.java | 59 ++
.../openapi/external/ui/OutputUILordVersion1.java | 70 ++
.../openapi/external/ui/SettingsNodeVersion1.java | 67 ++
.../ui/SinglePaneUIInteractionVersion1.java | 30 +
.../openapi/external/ui/SinglePaneUIVersion1.java | 40 ++
.../org/gradle/openapi/external/ui/UIFactory.java | 238 +++++++
subprojects/osgi/osgi.gradle | 4 +-
.../plugins/osgi/ContainedVersionAnalyzer.java | 2 +-
.../plugins/osgi/DefaultAnalyzerFactory.java | 3 -
.../internal/plugins/osgi/DefaultOsgiManifest.java | 5 +-
.../api/internal/plugins/osgi/OsgiHelper.java | 3 -
.../org/gradle/api/plugins/osgi/OsgiManifest.java | 4 +-
.../org/gradle/api/plugins/osgi/OsgiPlugin.groovy | 2 -
.../api/plugins/osgi/OsgiPluginConvention.java | 2 -
.../plugins/osgi/DefaultAnalyzerFactoryTest.java | 4 +-
.../plugins/osgi/DefaultOsgiManifestTest.groovy | 8 +-
.../plugins/osgi/OsgiPluginConventionTest.groovy | 12 +-
.../gradle/api/plugins/osgi/OsgiPluginTest.groovy | 4 +-
subprojects/performance/performance.gradle | 107 ++-
.../performance/CleanBuildPerformanceTest.groovy | 8 +-
.../DependencyReportPerformanceTest.groovy | 12 +-
.../DependencyResolutionStressTest.groovy | 5 +-
.../performance/FirstBuildPerformanceTest.groovy | 47 ++
.../IdeIntegrationPerformanceTest.groovy | 14 +-
.../TestExecutionPerformanceTest.groovy | 10 +-
.../UpToDateBuildPerformanceTest.groovy | 8 +-
.../src/templates/project-with-source/build.gradle | 1 +
.../gradle/performance/ResultSpecification.groovy | 48 ++
.../gradle/performance/fixture/AmountTest.groovy | 231 ------
.../gradle/performance/fixture/DurationTest.groovy | 59 --
.../fixture/PerformanceResultsTest.groovy | 181 ++---
.../fixture/PerformanceTestRunnerTest.groovy | 105 +++
.../fixture/PrettyCalculatorSpec.groovy | 5 +-
.../gradle/performance/fixture/UnitsTest.groovy | 34 -
.../gradle/performance/measure/AmountTest.groovy | 231 ++++++
.../gradle/performance/measure/DurationTest.groovy | 59 ++
.../gradle/performance/measure/UnitsTest.groovy | 34 +
.../performance/results/ReportGeneratorTest.groovy | 44 ++
.../performance/results/ResultsStoreTest.groovy | 181 +++++
.../fixture/AbstractPerformanceTest.groovy | 30 +-
.../org/gradle/performance/fixture/Amount.java | 162 -----
.../performance/fixture/BaselineVersion.groovy | 20 +-
.../performance/fixture/CompositeDataReporter.java | 39 ++
.../org/gradle/performance/fixture/DataAmount.java | 37 -
.../gradle/performance/fixture/DataCollector.java | 5 +-
.../org/gradle/performance/fixture/Duration.java | 45 --
.../org/gradle/performance/fixture/Git.groovy | 42 ++
.../performance/fixture/MeasuredOperation.groovy | 41 --
.../fixture/MeasuredOperationList.groovy | 8 +-
.../performance/fixture/MemoryInfoCollector.groovy | 6 +-
.../gradle/performance/fixture/OperationTimer.java | 36 +
.../performance/fixture/PerformanceResults.groovy | 51 +-
.../fixture/PerformanceTestRunner.groovy | 65 +-
.../performance/fixture/PrettyCalculator.groovy | 7 +-
.../performance/fixture/TestProjectLocator.groovy | 3 -
.../fixture/TextFileDataReporter.groovy | 13 +-
.../org/gradle/performance/fixture/Units.java | 193 ------
.../org/gradle/performance/measure/Amount.java | 163 +++++
.../org/gradle/performance/measure/DataAmount.java | 41 ++
.../org/gradle/performance/measure/Duration.java | 45 ++
.../performance/measure/MeasuredOperation.groovy | 22 +
.../org/gradle/performance/measure/Units.java | 193 ++++++
.../gradle/performance/results/FileRenderer.java | 34 +
.../gradle/performance/results/FormatSupport.java | 56 ++
.../performance/results/HtmlPageGenerator.java | 51 ++
.../performance/results/IndexPageGenerator.java | 106 +++
.../performance/results/ReportGenerator.java | 53 ++
.../gradle/performance/results/ResultsStore.java | 239 +++++++
.../performance/results/TestDataGenerator.java | 102 +++
.../performance/results/TestExecutionHistory.java | 66 ++
.../performance/results/TestPageGenerator.java | 143 ++++
.../resources/org/gradle/reporting/style.css | 59 ++
subprojects/plugins/plugins.gradle | 5 +-
.../gradle/api/plugins/BuildSrcPluginTest.groovy | 2 +-
.../api/tasks/bundling/JarIntegrationTest.groovy | 155 ++++-
.../tasks/bundling/WarTaskIntegrationTest.groovy | 102 +++
.../groovy/GroovyBasePluginIntegrationTest.groovy | 80 ++-
.../groovy/GroovyPluginIntegrationTest.groovy | 52 ++
.../AntForkingGroovyCompilerIntegrationTest.groovy | 2 +-
.../BasicGroovyCompilerIntegrationSpec.groovy | 2 +-
.../compile/GroovyCompilerIntegrationSpec.groovy | 12 +
.../JreJavaHomeGroovyIntegrationTest.groovy | 29 +-
.../gradle/java/JavaPluginGoodBehaviourTest.groovy | 22 +
.../JreJavaHomeJavaIntegrationTest.groovy | 30 +-
.../testing/IncrementalTestIntegrationTest.groovy | 123 ++++
.../testing/TestReportIntegrationTest.groovy | 251 ++++++-
.../gradle/testing/TestTaskIntegrationTest.groovy | 51 ++
.../gradle/testing/TestingIntegrationTest.groovy | 34 +
.../junit/JUnitAssumptionsIntegrationTest.groovy | 60 ++
...nitCategoriesCrossVersionIntegrationSpec.groovy | 96 +++
.../junit/JUnitCategoriesIntegrationSpec.groovy | 82 +++
.../junit/JUnitCrossVersionIntegrationSpec.groovy | 25 +-
...itIgnoreClassCrossVersionIntegrationSpec.groovy | 58 ++
.../testing/junit/JUnitIntegrationTest.groovy | 21 +-
.../testng/SampleTestNGIntegrationTest.groovy | 3 -
.../testing/testng/TestNGIntegrationProject.groovy | 67 --
.../testing/testng/TestNGIntegrationTest.groovy | 3 -
.../testng/TestNGLoggingIntegrationTest.groovy | 107 ++-
.../TestNGProducesOldReportsIntegrationTest.groovy | 4 +-
...tNGXmlResultAndHtmlReportIntegrationTest.groovy | 299 +++++++-
.../shared/build.gradle | 2 +-
.../build.gradle | 10 +
.../src/main/groovy/GroovyCode.groovy | 1 +
.../src/main/groovy/JavaCode.java | 3 +
.../build.gradle | 2 +-
.../recompilesDependentClasses/build.gradle | 2 +-
.../build.gradle | 2 +-
.../doesNotRunStaleTests/src/test/java/Broken.java | 0
.../NewMainClass.java | 0
.../executesTestsWhenSourceChanges/NewOk.java | 0
.../src/main/java/MainClass.java | 0
.../build.gradle | 0
.../src/test/java/JUnitExtra.java | 0
.../src/test/java/JUnitTest.java | 0
.../src/test/java/TestNGTest.java | 0
.../shared/build.gradle | 0
.../shared/src/test/java/Ok.java | 0
.../supportsAssumptions/build.gradle | 18 +
.../test/java/org/gradle/TestWithAssumptions.java | 32 +
.../build.gradle | 28 +
.../src/test/java/org/gradle/CategoryA.java | 20 +
.../src/test/java/org/gradle/LocaleHolder.java | 32 +
.../src/test/java/org/gradle/Locales.java | 80 +++
.../src/test/java/org/gradle/SomeLocaleTests.java | 19 +
.../test/java/org/gradle/SomeMoreLocalTests.java | 35 +
.../canSpecifyExcludesOnly/build.gradle | 26 +
.../src/test/java/org/gradle/CatATests.java | 41 ++
.../src/test/java/org/gradle/CategoryA.java | 20 +
.../src/test/java/org/gradle/NoCatTests.java | 30 +
.../src/test/java/org/gradle/SomeOtherCat.java | 20 +
.../test/java/org/gradle/SomeOtherCatTests.java | 32 +
.../src/test/java/org/gradle/SomeTests.java | 40 ++
.../build.gradle | 28 +
.../src/test/java/org/gradle/CatACTests.java | 40 ++
.../src/test/java/org/gradle/CatADTests.java | 42 ++
.../src/test/java/org/gradle/CatATests.java | 40 ++
.../src/test/java/org/gradle/CatBTests.java | 40 ++
.../src/test/java/org/gradle/CatCBTests.java | 42 ++
.../src/test/java/org/gradle/CatCTests.java | 40 ++
.../src/test/java/org/gradle/CatDTests.java | 40 ++
.../src/test/java/org/gradle/CatZTests.java | 40 ++
.../src/test/java/org/gradle/CategoryA.java | 20 +
.../src/test/java/org/gradle/CategoryB.java | 20 +
.../src/test/java/org/gradle/CategoryC.java | 20 +
.../src/test/java/org/gradle/CategoryD.java | 20 +
.../src/test/java/org/gradle/CategoryZ.java | 20 +
.../src/test/java/org/gradle/MixedTests.java | 44 ++
.../src/test/java/org/gradle/NoCatTests.java | 38 +
.../reportsUnloadableCategories/build.gradle | 27 +
.../src/test/java/org/gradle/SomeTestClass.java | 13 +
.../build.gradle | 16 +
.../src/test/java/org/gradle/SomeTest.java | 12 +
.../canHandleClassLevelIgnoredTests/build.gradle | 23 +
.../test/java/org/gradle/CustomIgnoredTest.java | 70 ++
.../src/test/java/org/gradle/IgnoredTest.java | 12 +
.../build.gradle | 6 +-
.../build.gradle | 6 +-
.../canRunTestsUsingJUnit3/build.gradle | 25 +
.../JUnitIntegrationTest/junit3Tests/build.gradle | 9 -
.../JUnitIntegrationTest/junit4Tests/build.gradle | 9 -
.../test/java/org/gradle/CustomIgnoredTest.java | 71 --
.../src/test/java/org/gradle/IgnoredTest.java | 12 -
.../src/test/java/org/gradle/Junit4Test.java | 11 +-
.../build.gradle | 8 +-
.../supportsTestCategories/build.gradle | 16 +
.../src/test/java/org/gradle/CategoryA.java | 4 +
.../src/test/java/org/gradle/CategoryB.java | 4 +
.../src/test/java/org/gradle/CategoryC.java | 4 +
.../src/test/java/org/gradle/SomeTest.java | 27 +
.../shared/build.gradle | 24 -
.../src/test/groovy/org/gradle/TestNGTest.groovy | 42 --
.../standardOutputLogging/build.gradle | 35 -
.../org/gradle/TestNGStandardOutputTest.groovy | 27 -
.../org/gradle/api/distribution/Distribution.java | 28 +-
.../distribution/internal/DefaultDistribution.java | 8 +-
.../internal/DefaultDistributionContainer.java | 13 +-
.../distribution/plugins/DistributionPlugin.groovy | 82 +--
.../gradle/api/internal/java/WebApplication.java | 2 +-
.../internal/plugins/BuildConfigurationRule.java | 2 +-
.../org/gradle/api/internal/plugins/CleanRule.java | 2 +-
.../api/internal/plugins/ProcessResources.java | 21 +-
.../internal/plugins/StartScriptGenerator.groovy | 37 +
.../gradle/api/internal/plugins/UploadRule.java | 2 +-
.../internal/tasks/DefaultBinariesContainer.java | 27 -
.../tasks/DefaultClassDirectoryBinary.java | 109 ---
.../api/internal/tasks/DefaultClasspath.java | 38 -
.../internal/tasks/DefaultFunctionalSourceSet.java | 34 -
.../api/internal/tasks/DefaultJavaSourceSet.java | 72 --
.../internal/tasks/DefaultJvmBinaryContainer.java | 36 -
.../internal/tasks/DefaultProjectSourceSet.java | 32 -
.../api/internal/tasks/DefaultResourceSet.java | 53 --
.../api/internal/tasks/DefaultSourceSet.java | 2 +-
.../internal/tasks/DefaultSourceSetContainer.java | 3 +
.../api/internal/tasks/DefaultSourceSetOutput.java | 3 -
.../internal/tasks/SourceSetCompileClasspath.java | 5 +-
.../compile/AntDependsStaleClassCleaner.groovy | 6 +-
.../tasks/compile/AntGroovyCompiler.groovy | 2 -
.../internal/tasks/compile/AntJavaCompiler.groovy | 7 +-
.../internal/tasks/compile/ApiGroovyCompiler.java | 5 +-
.../api/internal/tasks/compile/ArgCollector.java | 2 +
.../api/internal/tasks/compile/ArgWriter.java | 7 +
.../tasks/compile/CommandLineJavaCompiler.java | 4 +-
.../CommandLineJavaCompilerArgumentsGenerator.java | 7 +-
.../tasks/compile/DefaultJavaCompilerFactory.java | 26 +-
.../tasks/compile/ExecSpecBackedArgCollector.java | 5 +
.../GroovyCompileTransformingClassLoader.java | 124 ++++
.../compile/InProcessJavaCompilerFactory.java | 4 +-
.../tasks/compile/IncrementalGroovyCompiler.java | 2 +
.../tasks/compile/IncrementalJavaCompiler.java | 4 +-
.../compile/IncrementalJavaCompilerSupport.java | 2 +-
.../tasks/compile/NoOpStaleClassCleaner.java | 2 +
.../tasks/compile/NormalizingGroovyCompiler.java | 1 +
.../tasks/compile/NormalizingJavaCompiler.java | 1 +
.../tasks/compile/SimpleStaleClassCleaner.java | 38 -
.../internal/tasks/compile/SimpleWorkResult.java | 30 -
.../internal/tasks/compile/StaleClassCleaner.java | 53 --
.../internal/tasks/compile/SunJavaCompiler.java | 1 +
.../tasks/compile/TransformingClassLoader.java | 152 ----
.../daemon/InProcessCompilerDaemonFactory.java | 1 +
.../tasks/compile/jdk6/Jdk6JavaCompiler.java | 26 +-
.../tasks/testing/DefaultJUnitXmlReport.java | 41 ++
.../tasks/testing/DefaultTestClassRunInfo.java | 3 -
.../tasks/testing/DefaultTestOutputEvent.java | 28 +
.../tasks/testing/DefaultTestTaskReports.java | 46 ++
.../internal/tasks/testing/TestClassProcessor.java | 2 -
.../internal/tasks/testing/TestClassRunInfo.java | 3 -
.../api/internal/tasks/testing/TestFramework.java | 5 +-
.../detection/AbstractTestFrameworkDetector.java | 3 -
.../detection/ClassFileExtractionManager.java | 2 -
.../testing/detection/DefaultTestClassScanner.java | 2 -
.../testing/detection/DefaultTestExecuter.java | 2 -
.../testing/detection/JarFilePackageListener.java | 3 -
.../testing/detection/JarFilePackageLister.java | 3 -
.../tasks/testing/detection/TestClassVisitor.java | 2 -
.../tasks/testing/detection/TestExecuter.java | 3 -
.../testing/detection/TestFrameworkDetector.java | 3 -
.../tasks/testing/junit/CategoryFilter.java | 112 +++
.../tasks/testing/junit/JUnitDetector.java | 3 -
.../internal/tasks/testing/junit/JUnitSpec.java | 45 ++
.../testing/junit/JUnitTestClassDetecter.java | 3 -
.../testing/junit/JUnitTestClassExecuter.java | 40 +-
.../testing/junit/JUnitTestClassProcessor.java | 10 +-
.../tasks/testing/junit/JUnitTestFramework.java | 30 +-
.../testing/junit/JUnitTestMethodDetecter.java | 3 -
.../tasks/testing/junit/report/AllTestResults.java | 8 +-
.../testing/junit/report/ClassPageRenderer.java | 16 +-
.../testing/junit/report/ClassTestResults.java | 8 +-
.../testing/junit/report/DefaultTestReport.java | 6 +-
.../junit/report/LocaleSafeDecimalFormat.java | 3 -
.../testing/junit/report/OverviewPageRenderer.java | 2 +-
.../testing/junit/report/PackageTestResults.java | 8 +-
.../junit/result/AggregateTestResultsProvider.java | 73 +-
.../result/Binary2JUnitXmlReportGenerator.java | 4 +-
.../BinaryResultBackedTestResultsProvider.java | 36 +-
.../testing/junit/result/CachingFileWriter.java | 100 ---
.../junit/result/InMemoryTestResultsProvider.java | 63 ++
.../testing/junit/result/JUnitXmlResultWriter.java | 44 +-
.../testing/junit/result/TestClassResult.java | 14 +-
.../testing/junit/result/TestMethodResult.java | 17 +-
.../junit/result/TestOutputAssociation.java | 22 +
.../testing/junit/result/TestOutputSerializer.java | 90 ---
.../testing/junit/result/TestOutputStore.java | 388 +++++++++++
.../junit/result/TestReportDataCollector.java | 74 +-
.../testing/junit/result/TestResultSerializer.java | 43 +-
.../testing/junit/result/TestResultsProvider.java | 23 +-
.../internal/tasks/testing/results/TestState.java | 5 -
.../testing/results/UnknownTestDescriptor.java | 10 +-
.../tasks/testing/testng/TestNGDetector.java | 3 -
.../testng/TestNGListenerAdapterFactory.java | 25 +-
.../testing/testng/TestNGTestClassDetecter.java | 3 -
.../testing/testng/TestNGTestClassProcessor.java | 2 -
.../tasks/testing/testng/TestNGTestFramework.java | 5 +-
.../testing/testng/TestNGTestMethodDetecter.java | 3 -
.../testng/TestNGTestResultProcessorAdapter.java | 42 +-
.../testng/UnrepresentableParameterException.java | 32 +
.../org/gradle/api/java/archives/Attributes.java | 2 -
.../api/java/archives/ManifestException.java | 2 -
.../java/archives/internal/DefaultAttributes.java | 3 -
.../java/archives/internal/DefaultManifest.java | 3 -
.../internal/DefaultManifestMergeDetails.java | 3 -
.../gradle/api/plugins/ApplicationPlugin.groovy | 18 +-
.../api/plugins/ApplicationPluginConvention.groovy | 7 +-
.../groovy/org/gradle/api/plugins/BasePlugin.java | 8 +-
.../org/gradle/api/plugins/GroovyBasePlugin.java | 91 ++-
.../org/gradle/api/plugins/GroovyPlugin.java | 4 +-
.../org/gradle/api/plugins/JavaBasePlugin.java | 52 +-
.../org/gradle/api/plugins/JavaLanguagePlugin.java | 77 +-
.../plugins/JavaLibraryDistributionPlugin.groovy | 2 -
.../groovy/org/gradle/api/plugins/JavaPlugin.java | 12 +-
.../gradle/api/plugins/JavaPluginConvention.groovy | 2 -
.../org/gradle/api/plugins/JvmLanguagePlugin.java | 128 ----
.../org/gradle/api/plugins/LanguageBasePlugin.java | 60 --
.../groovy/org/gradle/api/plugins/WarPlugin.java | 10 +-
.../org/gradle/api/tasks/BinariesContainer.java | 27 -
.../org/gradle/api/tasks/ClassDirectoryBinary.java | 49 --
.../groovy/org/gradle/api/tasks/Classpath.java | 28 -
.../org/gradle/api/tasks/FunctionalSourceSet.java | 27 -
.../groovy/org/gradle/api/tasks/GroovyRuntime.java | 131 ++++
.../groovy/org/gradle/api/tasks/JavaSourceSet.java | 24 -
.../org/gradle/api/tasks/JvmBinaryContainer.java | 27 -
.../org/gradle/api/tasks/JvmLanguageSourceSet.java | 26 -
.../org/gradle/api/tasks/LanguageSourceSet.java | 33 -
.../org/gradle/api/tasks/ProjectSourceSet.java | 26 -
.../groovy/org/gradle/api/tasks/ResourceSet.java | 24 -
.../org/gradle/api/tasks/SourceSetContainer.java | 4 +
.../tasks/application/CreateStartScripts.groovy | 15 +-
.../org/gradle/api/tasks/bundling/Jar.groovy | 19 +-
.../org/gradle/api/tasks/bundling/War.groovy | 9 +-
.../gradle/api/tasks/compile/AbstractOptions.java | 6 +-
.../gradle/api/tasks/compile/BaseForkOptions.java | 3 -
.../org/gradle/api/tasks/compile/Compile.java | 9 +-
.../gradle/api/tasks/compile/CompileOptions.java | 21 +-
.../org/gradle/api/tasks/compile/DebugOptions.java | 2 -
.../gradle/api/tasks/compile/DependOptions.java | 2 -
.../org/gradle/api/tasks/compile/ForkOptions.java | 2 -
.../gradle/api/tasks/compile/GroovyCompile.java | 11 +-
.../api/tasks/compile/GroovyCompileOptions.java | 3 -
.../api/tasks/compile/GroovyForkOptions.java | 2 -
.../gradle/api/tasks/javadoc/AntGroovydoc.groovy | 3 -
.../org/gradle/api/tasks/javadoc/AntJavadoc.groovy | 3 +-
.../org/gradle/api/tasks/javadoc/Groovydoc.java | 16 +-
.../org/gradle/api/tasks/javadoc/Javadoc.java | 5 +-
.../gradle/api/tasks/testing/JUnitXmlReport.java | 39 ++
.../groovy/org/gradle/api/tasks/testing/Test.java | 258 ++++---
.../gradle/api/tasks/testing/TestDescriptor.java | 3 +
.../org/gradle/api/tasks/testing/TestReport.java | 34 +-
.../gradle/api/tasks/testing/TestTaskReports.java | 42 ++
.../api/tasks/testing/junit/JUnitOptions.groovy | 51 ++
.../api/tasks/testing/junit/JUnitOptions.java | 25 -
.../api/tasks/testing/testng/TestNGOptions.groovy | 15 +-
.../org/gradle/api/tasks/wrapper/Wrapper.java | 280 --------
.../external/javadoc/CoreJavadocOptions.java | 2 -
.../external/javadoc/JavadocMemberLevel.java | 2 -
.../external/javadoc/JavadocOfflineLink.java | 2 -
.../external/javadoc/JavadocOptionFileOption.java | 1 -
.../external/javadoc/JavadocOutputLevel.java | 2 -
.../external/javadoc/MinimalJavadocOptions.java | 2 -
.../javadoc/OptionLessJavadocOptionFileOption.java | 1 -
.../javadoc/StandardJavadocDocletOptions.java | 12 +-
.../internal/AbstractJavadocOptionFileOption.java | 1 -
.../AbstractListJavadocOptionFileOption.java | 3 +-
.../internal/BooleanJavadocOptionFileOption.java | 2 -
.../internal/EnumJavadocOptionFileOption.java | 1 -
.../internal/FileJavadocOptionFileOption.java | 2 -
.../internal/GroupsJavadocOptionFileOption.java | 2 -
.../javadoc/internal/JavadocExecHandleBuilder.java | 3 -
.../javadoc/internal/JavadocOptionFile.java | 3 -
.../javadoc/internal/JavadocOptionFileWriter.java | 3 -
.../internal/JavadocOptionFileWriterContext.java | 5 +-
.../LinksOfflineJavadocOptionFileOption.java | 7 +-
.../MultilineStringsJavadocOptionFileOption.java | 7 +-
.../OptionLessStringsJavadocOptionFileOption.java | 7 +-
.../internal/PathJavadocOptionFileOption.java | 5 +-
.../internal/StringJavadocOptionFileOption.java | 3 -
.../internal/StringsJavadocOptionFileOption.java | 7 +-
.../META-INF/gradle-plugins/jvm-lang.properties | 2 +-
.../META-INF/gradle-plugins/lang-base.properties | 2 +-
.../api/internal/plugins/unixStartScript.txt | 2 +-
.../api/internal/plugins/windowsStartScript.txt | 2 +-
.../plugins/DistributionPluginTest.groovy | 4 +-
.../plugins/StartScriptGeneratorTest.groovy | 99 +++
.../api/internal/tasks/DefaultSourceSetTest.groovy | 2 +-
.../compile/DefaultJavaCompilerFactoryTest.groovy | 4 +-
...GroovyCompileTransformingClassLoaderTest.groovy | 96 +++
.../compile/IncrementalJavaCompilerTest.groovy | 1 +
.../compile/SimpleStaleClassCleanerTest.groovy | 1 +
.../compile/TransformingClassLoaderTest.groovy | 96 ---
.../tasks/testing/AbstractTestFrameworkTest.java | 3 -
.../junit/JUnitTestClassProcessorTest.groovy | 4 +-
.../testing/junit/JUnitTestFrameworkTest.java | 12 +-
.../testing/junit/report/AllTestResultsTest.groovy | 4 +-
.../junit/report/ClassTestResultsTest.groovy | 4 +-
.../junit/report/CompositeTestResultsTest.groovy | 2 +-
.../junit/report/DefaultTestReportTest.groovy | 253 +------
.../junit/report/LocaleSafeDecimalFormatTest.java | 3 -
.../Binary2JUnitXmlReportGeneratorSpec.groovy | 23 +-
.../junit/result/CachingFileWriterSpec.groovy | 83 ---
.../junit/result/JUnitXmlResultWriterSpec.groovy | 101 ++-
.../junit/result/TestClassResultSpec.groovy | 11 +-
.../junit/result/TestOutputSerializerTest.groovy | 72 --
.../junit/result/TestOutputStoreSpec.groovy | 118 ++++
.../result/TestReportDataCollectorSpec.groovy | 75 +-
.../junit/result/TestResultSerializerTest.groovy | 25 +-
.../tasks/testing/logging/SimpleTestResult.groovy | 31 -
.../testing/logging/TestEventLoggerTest.groovy | 6 +-
.../testing/results/DefaultTestResultTest.groovy | 3 -
.../testing/testng/TestNGTestFrameworkTest.groovy | 7 +-
.../archives/internal/DefaultAttributesTest.groovy | 5 +-
.../internal/DefaultManifestMergeSpecTest.groovy | 3 -
.../archives/internal/DefaultManifestTest.groovy | 3 -
.../api/plugins/ApplicationPluginTest.groovy | 27 +-
.../api/plugins/BasePluginConventionTest.groovy | 8 +-
.../org/gradle/api/plugins/BasePluginTest.groovy | 24 +-
.../gradle/api/plugins/GroovyBasePluginTest.groovy | 31 +-
.../org/gradle/api/plugins/GroovyPluginTest.groovy | 7 +-
.../gradle/api/plugins/JavaBasePluginTest.groovy | 61 +-
.../api/plugins/JavaLanguagePluginTest.groovy | 17 +-
.../JavaLibraryDistributionPluginTest.groovy | 4 +-
.../api/plugins/JavaPluginConventionTest.groovy | 7 +-
.../org/gradle/api/plugins/JavaPluginTest.groovy | 17 +-
.../api/plugins/JvmLanguagePluginTest.groovy | 64 +-
.../api/plugins/LanguageBasePluginTest.groovy | 29 +-
.../org/gradle/api/plugins/WarPluginTest.groovy | 12 +-
.../org/gradle/api/tasks/GroovyRuntimeTest.groovy | 116 ++++
.../application/CreateStartScriptsTest.groovy | 4 +-
.../org/gradle/api/tasks/bundling/JarTest.groovy | 4 +-
.../org/gradle/api/tasks/bundling/WarTest.groovy | 4 +-
.../api/tasks/compile/CompileOptionsTest.groovy | 8 +-
.../api/tasks/compile/DebugOptionsTest.groovy | 3 -
.../api/tasks/compile/ForkOptionsTest.groovy | 6 +-
.../tasks/compile/GroovyCompileOptionsTest.groovy | 6 +-
.../api/tasks/compile/GroovyCompileTest.java | 16 +-
.../api/tasks/compile/GroovyForkOptionsTest.groovy | 6 +-
.../gradle/api/tasks/compile/JavaCompileTest.java | 3 -
.../gradle/api/tasks/javadoc/GroovydocTest.java | 7 +-
.../org/gradle/api/tasks/javadoc/JavadocTest.java | 2 +-
.../testing/AbstractTestFrameworkOptionsTest.java | 3 -
.../gradle/api/tasks/testing/TestReportTest.groovy | 6 +-
.../gradle/api/tasks/testing/TestTaskSpec.groovy | 7 +-
.../org/gradle/api/tasks/testing/TestTest.java | 13 +-
.../tasks/testing/testng/TestNGOptionsTest.groovy | 13 +-
.../org/gradle/api/tasks/wrapper/WrapperTest.java | 164 -----
.../javadoc/StandardJavadocDocletOptionsTest.java | 20 +-
.../BooleanJavadocOptionFileOptionTest.java | 9 +-
.../internal/EnumJavadocOptionFileOptionTest.java | 7 +-
.../internal/FileJavadocOptionFileOptionTest.java | 7 +-
.../GroupsJavadocOptionFileOptionTest.java | 7 +-
.../internal/JavadocExecHandleBuilderTest.groovy | 9 +-
.../javadoc/internal/JavadocOptionFileTest.java | 3 -
.../JavadocOptionFileWriterContextTest.java | 7 +-
.../LinksOfflineJavadocOptionFileOptionTest.java | 7 +-
...ultilineStringsJavadocOptionFileOptionTest.java | 5 +-
...tionLessStringsJavadocOptionFileOptionTest.java | 5 +-
.../internal/PathJavadocOptionFileOptionTest.java | 7 +-
.../StringJavadocOptionFileOptionTest.java | 5 +-
.../StringsJavadocOptionFileOptionTest.java | 5 +-
.../tasks/testing/BuildableTestMethodResult.groovy | 71 ++
.../testing/BuildableTestResultsProvider.groovy | 175 +++++
.../tasks/testing/MethodTestOutputEvent.groovy | 29 +
.../internal/tasks/testing/SimpleTestResult.groovy | 35 +
.../junit/report/HtmlTestResultsFixture.groovy | 157 +++++
.../api/tasks/compile/AbstractCompileTest.java | 5 +-
subprojects/publish/publish.gradle | 4 +-
.../gradle/api/publish/PublicationContainer.java | 55 +-
.../gradle/api/publish/PublishingExtension.java | 23 +
.../internal/CompositePublicationFactory.java | 39 --
.../internal/DefaultPublicationContainer.java | 25 +-
.../internal/GroovyPublicationContainer.groovy | 35 -
.../ProjectDependencyPublicationResolver.java | 57 ++
.../internal/PublicationContainerInternal.java | 23 -
.../api/publish/internal/PublicationFactory.java | 22 -
.../api/publish/internal/PublicationInternal.java | 23 +
.../api/publish/plugins/PublishingPlugin.java | 29 +-
.../DefaultPublicationContainerTest.groovy | 48 +-
...ProjectDependencyPublicationResolverTest.groovy | 134 ++++
.../publish/plugins/PublishingPluginTest.groovy | 4 +-
subprojects/reporting/reporting.gradle | 3 +-
.../internal/TaskReportContainerIntegTest.groovy | 0
.../BuildDashboardPluginIntegrationTest.groovy | 328 +++++++--
.../api/reporting/BuildDashboardReports.java | 8 +-
.../gradle/api/reporting/ConfigurableReport.java | 34 +
.../org/gradle/api/reporting/DirectoryReport.java | 47 ++
.../api/reporting/GenerateBuildDashboard.java | 58 +-
.../groovy/org/gradle/api/reporting/Report.java | 20 +-
.../org/gradle/api/reporting/ReportContainer.java | 14 +-
.../groovy/org/gradle/api/reporting/Reporting.java | 40 +-
.../gradle/api/reporting/ReportingExtension.java | 15 +-
.../org/gradle/api/reporting/SingleFileReport.java | 12 +-
.../internal/BuildDashboardGenerator.java | 70 +-
.../internal/DefaultBuildDashboardReports.java | 14 +-
.../reporting/internal/DefaultReportContainer.java | 5 +-
.../TaskGeneratedSingleDirectoryReport.java | 45 ++
.../reporting/plugins/BuildDashboardPlugin.groovy | 58 --
.../reporting/plugins/BuildDashboardPlugin.java | 73 ++
.../org/gradle/api/reporting/internal/style.css | 3 +
.../ReportingBasePluginConventionTest.groovy | 65 ++
.../api/plugins/ReportingBasePluginTest.groovy | 48 ++
.../reporting/GenerateBuildDashboardSpec.groovy | 4 +-
.../internal/BuildDashboardGeneratorSpec.groovy | 22 +-
subprojects/resources/resources.gradle | 11 +
.../org/gradle/internal/filestore/FileStore.java | 32 +
.../internal/filestore/FileStoreSearcher.java | 27 +
.../local/AbstractLocallyAvailableResource.java | 55 ++
.../local/DefaultLocallyAvailableResource.java | 37 +
.../resource/local/LocallyAvailableResource.java | 31 +
.../DefaultLocallyAvailableResourceTest.groovy | 66 ++
subprojects/scala/scala.gradle | 5 +-
.../integtests/ScalaPluginGoodBehaviourTest.groovy | 0
.../integtests/ScalaProjectIntegrationTest.java | 0
.../SamplesMixedJavaAndScalaIntegrationTest.groovy | 0
...plesScalaCustomizedLayoutIntegrationTest.groovy | 0
.../SamplesScalaQuickstartIntegrationTest.groovy | 0
.../samples/SamplesScalaZincIntegrationTest.groovy | 0
.../scala/ScalaBasePluginIntegrationTest.groovy | 88 ++-
.../JreJavaHomeScalaIntegrationTest.groovy | 12 +-
.../internal/tasks/scala/AntScalaCompiler.groovy | 2 +-
.../tasks/scala/IncrementalScalaCompiler.java | 2 +
.../tasks/scala/NormalizingScalaCompiler.java | 4 +-
.../tasks/scala/jdk6/ZincScalaCompiler.java | 3 +-
.../api/plugins/scala/ScalaBasePlugin.groovy | 142 ++--
.../gradle/api/plugins/scala/ScalaPlugin.groovy | 5 +-
.../org/gradle/api/tasks/ScalaRuntime.groovy | 158 +++++
.../org/gradle/api/tasks/scala/ScalaCompile.java | 3 +-
.../api/plugins/scala/ScalaBasePluginTest.groovy | 140 +---
.../api/plugins/scala/ScalaPluginTest.groovy | 4 +-
.../org/gradle/api/tasks/ScalaRuntimeTest.groovy | 124 ++++
.../gradle/api/tasks/scala/ScalaCompileTest.java | 9 +-
subprojects/signing/signing.gradle | 2 +-
.../gradle/plugins/signing/SigningExtension.groovy | 8 +-
.../plugins/signing/SigningPluginConvention.groovy | 8 +-
.../plugins/signing/SigningProjectSpec.groovy | 4 +-
subprojects/sonar/sonar.gradle | 3 +-
.../plugins/sonar/SonarSmokeIntegrationTest.groovy | 16 +-
.../runner/SonarRunnerSmokeIntegrationTest.groovy | 16 +-
.../shared/javaProject/build.gradle | 2 -
.../shared/javaProjectWithJacoco/build.gradle | 5 +
.../org/gradle/test/javaProject/Production1.java | 0
.../org/gradle/test/javaProject/Production10.java | 0
.../org/gradle/test/javaProject/Production2.java | 0
.../org/gradle/test/javaProject/Production3.java | 0
.../org/gradle/test/javaProject/Production4.java | 0
.../org/gradle/test/javaProject/Production5.java | 0
.../org/gradle/test/javaProject/Production6.java | 0
.../org/gradle/test/javaProject/Production7.java | 0
.../org/gradle/test/javaProject/Production8.java | 0
.../org/gradle/test/javaProject/Production9.java | 0
.../gradle/test/javaProject/productionResource.xml | 0
.../java/org/gradle/test/javaProject/Test1.java | 0
.../java/org/gradle/test/javaProject/Test10.java | 0
.../java/org/gradle/test/javaProject/Test2.java | 0
.../java/org/gradle/test/javaProject/Test3.java | 0
.../java/org/gradle/test/javaProject/Test4.java | 0
.../java/org/gradle/test/javaProject/Test5.java | 0
.../java/org/gradle/test/javaProject/Test6.java | 0
.../java/org/gradle/test/javaProject/Test7.java | 0
.../java/org/gradle/test/javaProject/Test8.java | 0
.../java/org/gradle/test/javaProject/Test9.java | 0
.../org/gradle/test/javaProject/testResource.xml | 0
.../shared/settings.gradle | 2 +-
.../shared/javaProject/build.gradle | 2 -
.../shared/javaProjectWithJacoco/build.gradle | 5 +
.../org/gradle/test/javaProject/Production1.java | 0
.../org/gradle/test/javaProject/Production10.java | 0
.../org/gradle/test/javaProject/Production2.java | 0
.../org/gradle/test/javaProject/Production3.java | 0
.../org/gradle/test/javaProject/Production4.java | 0
.../org/gradle/test/javaProject/Production5.java | 0
.../org/gradle/test/javaProject/Production6.java | 0
.../org/gradle/test/javaProject/Production7.java | 0
.../org/gradle/test/javaProject/Production8.java | 0
.../org/gradle/test/javaProject/Production9.java | 0
.../gradle/test/javaProject/productionResource.xml | 0
.../java/org/gradle/test/javaProject/Test1.java | 0
.../java/org/gradle/test/javaProject/Test10.java | 0
.../java/org/gradle/test/javaProject/Test2.java | 0
.../java/org/gradle/test/javaProject/Test3.java | 0
.../java/org/gradle/test/javaProject/Test4.java | 0
.../java/org/gradle/test/javaProject/Test5.java | 0
.../java/org/gradle/test/javaProject/Test6.java | 0
.../java/org/gradle/test/javaProject/Test7.java | 0
.../java/org/gradle/test/javaProject/Test8.java | 0
.../java/org/gradle/test/javaProject/Test9.java | 0
.../org/gradle/test/javaProject/testResource.xml | 0
.../shared/settings.gradle | 2 +-
.../gradle/api/plugins/sonar/SonarAnalyze.groovy | 2 +-
.../gradle/api/plugins/sonar/SonarPlugin.groovy | 17 +-
.../api/sonar/runner/SonarRunnerPlugin.groovy | 34 +-
.../api/plugins/sonar/SonarAnalyzeTest.groovy | 2 +-
.../api/plugins/sonar/SonarPluginTest.groovy | 27 +-
.../api/sonar/runner/SonarRunnerPluginTest.groovy | 30 +-
.../tooling/AutoTestedSamplesToolingApiTest.groovy | 5 +-
.../ToolingApiClasspathIntegrationTest.groovy | 9 +-
.../tooling/ToolingApiIntegrationTest.groovy | 14 -
...lingApiUnsupportedVersionIntegrationTest.groovy | 62 ++
.../tooling/fixture/ConfigurableOperation.groovy | 3 -
.../fixture/ExternalToolingApiDistribution.groovy | 18 +-
.../tooling/fixture/IncludeAllPermutations.java | 23 -
.../tooling/fixture/MaxTargetGradleVersion.java | 25 -
.../tooling/fixture/MinTargetGradleVersion.java | 25 -
.../tooling/fixture/MinToolingApiVersion.java | 25 -
.../tooling/fixture/TargetGradleVersion.java | 31 +
.../TestClasspathToolingApiDistribution.groovy | 7 +-
.../integtests/tooling/fixture/ToolingApi.groovy | 36 +-
.../ToolingApiCompatibilitySuiteRunner.groovy | 74 +-
.../tooling/fixture/ToolingApiDistribution.groovy | 6 +-
.../fixture/ToolingApiDistributionResolver.groovy | 30 +-
.../tooling/fixture/ToolingApiSpecification.groovy | 27 +-
.../tooling/fixture/ToolingApiVersion.java | 31 +
.../m3/ToolingApiLoggingCrossVersionSpec.groovy | 103 +++
...piEclipseLinkedResourcesCrossVersionSpec.groovy | 11 +-
...ngApiEclipseMinimalModelCrossVersionSpec.groovy | 4 +-
...EclipseModelWithFlatRepoCrossVersionSpec.groovy | 4 +-
...ToolingApiBuildExecutionCrossVersionSpec.groovy | 8 +-
...ildableEclipseModelFixesCrossVersionSpec.groovy | 8 +-
.../ToolingApiEclipseModelCrossVersionSpec.groovy | 6 +-
.../ToolingApiGradleProjectCrossVersionSpec.groovy | 6 +-
...orsProjectCustomizationsCrossVersionSpec.groovy | 8 +-
.../m5/ToolingApiIdeaModelCrossVersionSpec.groovy | 8 +-
.../m5/ToolingApiModelCrossVersionSpec.groovy | 8 +-
...ReceivingStandardStreamsCrossVersionSpec.groovy | 8 +-
...UnsupportedModelFeedbackCrossVersionSpec.groovy | 38 +
.../BuildEnvironmentModelCrossVersionSpec.groovy | 8 +-
.../ConsumingStandardInputCrossVersionSpec.groovy | 8 +-
...adlePropertiesToolingApiCrossVersionSpec.groovy | 8 +-
.../m8/JavaConfigurabilityCrossVersionSpec.groovy | 8 +-
...rictLongRunningOperationCrossVersionSpec.groovy | 25 +-
.../ToolingApiEclipseModelCrossVersionSpec.groovy | 10 +-
.../m8/ToolingApiLoggingCrossVersionSpec.groovy | 63 +-
.../m8/UnknownModelFeedbackCrossVersionSpec.groovy | 42 --
...sionOnlyBuildEnvironmentCrossVersionSpec.groovy | 10 +-
.../m9/DaemonErrorFeedbackCrossVersionSpec.groovy | 10 +-
.../M9JavaConfigurabilityCrossVersionSpec.groovy | 10 +-
...singCommandLineArgumentsCrossVersionSpec.groovy | 13 +-
.../DependencyMetaDataCrossVersionSpec.groovy | 8 +-
.../r12rc1/BuildModelCrossVersionSpec.groovy | 8 +-
.../ProjectOutcomesModuleCrossVersionSpec.groovy | 8 +-
...pportedOperationFeedbackCrossVersionSpec.groovy | 10 +-
...ApiInitScriptCrossVersionIntegrationTest.groovy | 4 +-
...ningCommandLineArgumentsCrossVersionSpec.groovy | 8 +-
...ApiConfigurationOnDemandCrossVersionSpec.groovy | 8 +-
.../gradle/integtests/tooling/r16/CustomModel.java | 31 +
.../r16/CustomToolingModelCrossVersionSpec.groovy | 81 +++
...knownCustomModelFeedbackCrossVersionSpec.groovy | 58 ++
.../integtests/tooling/r18/BrokenAction.java | 29 +
.../tooling/r18/BuildActionCrossVersionSpec.groovy | 104 +++
.../r18/BuildScriptModelCrossVersionSpec.groovy | 73 ++
.../gradle/integtests/tooling/r18/CustomModel.java | 27 +
.../integtests/tooling/r18/FetchCustomModel.java | 31 +
.../integtests/tooling/r18/FetchIdeaModel.java | 27 +
.../integtests/tooling/r18/FetchUnknownModel.java | 32 +
.../r18/GradleBuildModelCrossVersionSpec.groovy | 57 ++
.../gradle/integtests/tooling/r18/NullAction.java | 26 +
.../r18/ProjectLevelModelCrossVersionSpec.groovy | 111 +++
.../r18/UseGradleBuildToFetchProjectModel.java | 37 +
.../r18/UseOtherTypesToFetchProjectModel.java | 56 ++
.../main/java/org/gradle/tooling/BuildAction.java | 41 ++
.../org/gradle/tooling/BuildActionExecuter.java | 60 ++
.../tooling/BuildActionFailureException.java | 31 +
.../java/org/gradle/tooling/BuildController.java | 112 +++
.../java/org/gradle/tooling/BuildException.java | 4 +-
.../java/org/gradle/tooling/BuildLauncher.java | 20 +-
.../gradle/tooling/GradleConnectionException.java | 2 +
.../org/gradle/tooling/LongRunningOperation.java | 26 +-
.../main/java/org/gradle/tooling/ModelBuilder.java | 27 +-
.../java/org/gradle/tooling/ProjectConnection.java | 59 +-
.../org/gradle/tooling/UnknownModelException.java | 4 +
.../tooling/UnsupportedVersionException.java | 2 +
.../UnsupportedBuildArgumentException.java | 6 +-
.../tooling/internal/adapter/CollectionMapper.java | 50 ++
.../internal/adapter/CompatibleIntrospector.java | 76 ++
.../tooling/internal/adapter/MethodInvocation.java | 79 +++
.../tooling/internal/adapter/MethodInvoker.java | 21 +
.../internal/adapter/NoOpMethodInvoker.java | 24 +
.../internal/adapter/ProtocolToModelAdapter.java | 489 +++++++++++++
.../internal/adapter/SourceObjectMapping.java | 28 +
.../internal/adapter/TargetTypeProvider.java | 26 +
.../internal/build/DefaultBuildEnvironment.java | 19 +-
.../build/VersionOnlyBuildEnvironment.java | 19 +-
.../consumer/AbstractLongRunningOperation.java | 70 ++
.../internal/consumer/BlockingResultHandler.java | 16 +-
.../internal/consumer/ConnectionFactory.java | 21 +-
.../internal/consumer/ConnectorServices.java | 7 +-
.../consumer/DefaultBuildActionExecuter.java | 63 ++
.../internal/consumer/DefaultBuildLauncher.java | 81 +--
.../internal/consumer/DefaultGradleConnector.java | 4 -
.../internal/consumer/DefaultModelBuilder.java | 107 +--
.../consumer/DefaultProjectConnection.java | 40 +-
.../tooling/internal/consumer/LoggingProvider.java | 3 -
.../tooling/internal/consumer/ModelProvider.java | 80 ---
.../internal/consumer/SynchronizedLogging.java | 4 +-
.../internal/consumer/async/AsyncConnection.java | 30 -
.../async/AsyncConsumerActionExecutor.java | 39 ++
.../consumer/async/DefaultAsyncConnection.java | 88 ---
.../async/DefaultAsyncConsumerActionExecutor.java | 66 ++
.../connection/AbstractConsumerConnection.java | 13 +-
.../AbstractPost12ConsumerConnection.java | 38 +
.../AbstractPre12ConsumerConnection.java | 62 ++
.../connection/ActionAwareConsumerConnection.java | 59 ++
.../consumer/connection/AdaptedConnection.java | 55 --
.../BuildActionRunnerBackedConsumerConnection.java | 61 +-
.../connection/BuildControllerAdapter.java | 81 +++
...ConnectionVersion4BackedConsumerConnection.java | 125 ++++
.../consumer/connection/ConsumerAction.java | 25 +
.../connection/ConsumerActionExecutor.java | 29 +
.../consumer/connection/ConsumerConnection.java | 8 +-
.../connection/ConsumerConnectionMetadata.java | 44 --
...InternalConnectionBackedConsumerConnection.java | 53 +-
.../consumer/connection/LazyConnection.java | 143 ----
.../connection/LazyConsumerActionExecutor.java | 115 +++
.../connection/LoggingInitializerConnection.java | 54 --
.../LoggingInitializerConsumerActionExecutor.java | 46 ++
.../ModelBuilderBackedConsumerConnection.java | 69 ++
.../connection/NoToolingApiConnection.java | 49 ++
.../connection/ProgressLoggingConnection.java | 102 ---
.../ProgressLoggingConsumerActionExecutor.java | 85 +++
.../converters/ConsumerTargetTypeProvider.java | 47 ++
.../converters/GradleProjectConverter.java | 3 -
.../converters/GradleProjectMixInHandler.java | 30 +
.../converters/PropertyHandlerFactory.java | 44 ++
.../loader/DefaultToolingImplementationLoader.java | 42 +-
.../SynchronizedToolingImplementationLoader.java | 3 -
.../parameters/ConsumerOperationParameters.java | 4 +-
.../protocoladapter/ConsumerPropertyHandler.java | 41 --
.../consumer/protocoladapter/MethodInvocation.java | 76 --
.../consumer/protocoladapter/MethodInvoker.java | 21 -
.../protocoladapter/ProtocolToModelAdapter.java | 358 ----------
.../protocoladapter/TargetTypeProvider.java | 55 --
.../internal/consumer/versioning/ModelMapping.java | 118 +++-
.../consumer/versioning/VersionDetails.java | 52 +-
.../eclipse/DefaultEclipseExternalDependency.java | 54 --
.../eclipse/DefaultEclipseLinkedResource.java | 55 --
.../internal/eclipse/DefaultEclipseProject.java | 134 ----
.../eclipse/DefaultEclipseProjectDependency.java | 44 --
.../eclipse/DefaultEclipseSourceDirectory.java | 44 --
.../internal/eclipse/DefaultEclipseTask.java | 56 --
.../internal/gradle/BasicGradleProject.java | 80 +++
.../internal/gradle/DefaultGradleBuild.java | 43 ++
.../gradle/DefaultGradleModuleVersion.java | 3 -
.../internal/gradle/DefaultGradleProject.java | 12 +-
.../internal/gradle/DefaultGradleScript.java | 34 +
.../tooling/internal/gradle/DefaultGradleTask.java | 3 -
.../internal/gradle/GradleProjectIdentity.java | 21 +
.../internal/idea/DefaultIdeaCompilerOutput.java | 68 --
.../internal/idea/DefaultIdeaContentRoot.java | 83 ---
.../internal/idea/DefaultIdeaDependencyScope.java | 67 --
.../internal/idea/DefaultIdeaLanguageLevel.java | 85 ---
.../tooling/internal/idea/DefaultIdeaModule.java | 125 ----
.../internal/idea/DefaultIdeaModuleDependency.java | 69 --
.../tooling/internal/idea/DefaultIdeaProject.java | 117 ----
.../DefaultIdeaSingleEntryLibraryDependency.java | 103 ---
.../internal/idea/DefaultIdeaSourceDirectory.java | 46 --
.../outcomes/DefaultGradleBuildOutcome.java | 46 --
.../outcomes/DefaultGradleFileBuildOutcome.java | 42 --
.../internal/outcomes/DefaultProjectOutcomes.java | 80 ---
.../internal/protocol/BuildActionRunner.java | 16 +
.../internal/protocol/BuildExceptionVersion1.java | 5 +-
.../protocol/BuildOperationParametersVersion1.java | 23 +
.../tooling/internal/protocol/BuildParameters.java | 4 +-
.../internal/protocol/BuildParametersVersion1.java | 7 +
.../internal/protocol/ConfigurableConnection.java | 14 +
.../internal/protocol/ConnectionVersion4.java | 59 +-
.../protocol/InternalBasicIdeaProject.java | 4 +-
.../internal/protocol/InternalBuildAction.java | 36 +
.../protocol/InternalBuildActionExecutor.java | 51 ++
.../InternalBuildActionFailureException.java | 30 +
.../internal/protocol/InternalBuildController.java | 53 ++
.../protocol/InternalBuildEnvironment.java | 3 +-
.../internal/protocol/InternalConnection.java | 17 +-
.../internal/protocol/InternalGradleProject.java | 2 +
.../internal/protocol/InternalIdeaProject.java | 2 +
.../internal/protocol/InternalProjectOutcomes.java | 7 +-
.../protocol/InternalProtocolInterface.java | 12 +-
.../internal/protocol/InternalTestModel.java | 24 -
.../InternalUnsupportedModelException.java | 31 +
.../LongRunningOperationParametersVersion1.java | 8 +
.../tooling/internal/protocol/ModelBuilder.java | 51 ++
.../tooling/internal/protocol/ModelIdentifier.java | 42 ++
.../tooling/internal/protocol/ProjectVersion3.java | 17 +
.../eclipse/EclipseLinkedResourceVersion1.java | 2 -
.../protocol/eclipse/EclipseProjectVersion3.java | 2 +
.../HierarchicalEclipseProjectVersion1.java | 2 +
.../internal/reflect/CompatibleIntrospector.java | 71 --
.../org/gradle/tooling/model/BuildableElement.java | 1 +
.../java/org/gradle/tooling/model/Element.java | 2 +
.../gradle/tooling/model/ExternalDependency.java | 2 +-
.../gradle/tooling/model/GradleModuleVersion.java | 2 +-
.../org/gradle/tooling/model/GradleProject.java | 21 +-
.../gradle/tooling/model/HierarchicalElement.java | 2 +
.../main/java/org/gradle/tooling/model/Model.java | 1 +
.../main/java/org/gradle/tooling/model/Task.java | 6 +
.../tooling/model/build/BuildEnvironment.java | 7 +-
.../tooling/model/build/GradleEnvironment.java | 2 +
.../tooling/model/build/JavaEnvironment.java | 4 +
.../gradle/tooling/model/build/package-info.java | 2 +-
.../model/eclipse/EclipseLinkedResource.java | 10 +-
.../tooling/model/eclipse/EclipseProject.java | 15 +-
.../gradle/tooling/model/eclipse/EclipseTask.java | 5 +-
.../model/eclipse/HierarchicalEclipseProject.java | 5 +
.../gradle/tooling/model/eclipse/package-info.java | 2 +-
.../tooling/model/gradle/BasicGradleProject.java | 69 ++
.../gradle/tooling/model/gradle/GradleBuild.java | 42 ++
.../gradle/tooling/model/gradle/GradleScript.java | 40 ++
.../gradle/tooling/model/gradle/package-info.java | 20 +
.../tooling/model/idea/BasicIdeaProject.java | 2 +
.../org/gradle/tooling/model/idea/IdeaModule.java | 9 +-
.../org/gradle/tooling/model/idea/IdeaProject.java | 7 +-
.../gradle/tooling/model/idea/package-info.java | 2 +-
.../gradle/tooling/model/internal/Exceptions.java | 41 +-
.../gradle/tooling/model/internal/TestModel.java | 26 -
.../org/gradle/tooling/model/package-info.java | 2 +-
.../tooling/fixture/GradleVersionSpecTest.groovy | 146 ++++
.../internal/adapter/CollectionMapperTest.groovy | 49 ++
.../adapter/CompatibleIntrospectorTest.groovy | 79 +++
.../adapter/ProtocolToModelAdapterTest.groovy | 467 +++++++++++++
.../internal/consumer/ConnectionFactoryTest.groovy | 17 +-
.../internal/consumer/ConnectorServicesTest.groovy | 3 -
.../consumer/DefaultBuildActionExecuterTest.groovy | 164 +++++
.../consumer/DefaultBuildLauncherTest.groovy | 176 +++--
.../consumer/DefaultModelBuilderTest.groovy | 159 +++--
.../consumer/DefaultProjectConnectionTest.groovy | 30 +-
.../consumer/DistributionFactoryTest.groovy | 6 +-
.../consumer/ProtocolToModelAdapterTest.groovy | 68 --
.../consumer/SynchronizedLoggingTest.groovy | 3 -
.../DefaultAsyncConsumerActionExecutorTest.groovy | 81 +++
.../ActionAwareConsumerConnectionTest.groovy | 75 ++
.../connection/AdaptedConnectionTest.groovy | 50 --
...ActionRunnerBackedConsumerConnectionTest.groovy | 91 ++-
.../connection/BuildControllerAdapterTest.groovy | 122 ++++
...tionVersion4BackedConsumerConnectionTest.groovy | 258 +++++++
...alConnectionBackedConsumerConnectionTest.groovy | 94 ++-
.../consumer/connection/LazyConnectionTest.groovy | 107 ---
.../LazyConsumerActionExecutorTest.groovy | 106 +++
...ModelBuilderBackedConsumerConnectionTest.groovy | 109 +++
.../ProgressLoggingConnectionTest.groovy | 55 --
...rogressLoggingConsumerActionExecutorTest.groovy | 55 ++
.../DefaultToolingImplementationLoaderTest.groovy | 94 ++-
...chronizedToolingImplementationLoaderTest.groovy | 3 -
.../ConsumerOperationParametersTest.groovy | 3 -
.../ProtocolToModelAdapterTest.groovy | 271 --------
.../consumer/versioning/ModelMappingTest.groovy | 115 +++
.../eclipse/DefaultEclipseProjectTest.groovy | 27 -
.../reflect/CompatibleIntrospectorTest.groovy | 59 --
.../tooling/fixture/GradleVersionSpec.java | 83 +++
subprojects/tooling-api/tooling-api.gradle | 7 +-
.../integtests/FavoritesIntegrationTest.java | 2 -
.../integtests/LiveOutputIntegrationTest.groovy | 5 -
...projectProjectAndTaskListIntegrationTest.groovy | 3 -
.../gradle/foundation/CommandLineAssistant.java | 2 -
.../org/gradle/foundation/PathParserPortion.java | 2 -
.../org/gradle/foundation/ProjectConverter.java | 2 -
.../java/org/gradle/foundation/ProjectView.java | 2 -
.../main/java/org/gradle/foundation/TaskView.java | 2 -
.../gradle/foundation/common/ListReorderer.java | 2 -
.../org/gradle/foundation/common/ObserverLord.java | 3 -
.../gradle/foundation/common/ReorderableList.java | 3 -
.../gradle/foundation/ipc/basic/ClientProcess.java | 2 -
.../gradle/foundation/ipc/basic/ExecutionInfo.java | 4 -
.../gradle/foundation/ipc/basic/MessageObject.java | 2 -
.../foundation/ipc/basic/ObjectSocketWrapper.java | 2 -
.../ipc/basic/ProcessLauncherServer.java | 2 -
.../org/gradle/foundation/ipc/basic/Server.java | 2 -
.../ipc/gradle/AbstractGradleServerProtocol.java | 2 -
.../gradle/ExecuteGradleCommandClientProtocol.java | 2 -
.../gradle/ExecuteGradleCommandServerProtocol.java | 2 -
.../gradle/foundation/ipc/gradle/IPCUtilities.java | 2 -
.../ipc/gradle/KillGradleClientProtocol.java | 2 -
.../ipc/gradle/KillGradleServerProtocol.java | 2 -
.../foundation/ipc/gradle/ProtocolConstants.java | 2 -
.../ipc/gradle/TaskListClientProtocol.java | 2 -
.../ipc/gradle/TaskListServerProtocol.java | 2 -
.../org/gradle/foundation/output/FileLink.java | 2 -
.../foundation/output/FileLinkDefinitionLord.java | 2 -
.../gradle/foundation/output/LiveOutputParser.java | 2 -
.../org/gradle/foundation/output/OutputParser.java | 2 -
.../definitions/ExtensionFileLinkDefinition.java | 2 -
.../output/definitions/FileLinkDefinition.java | 2 -
.../OptionalLineNumberFileLinkDefinition.java | 2 -
.../definitions/PrefixedFileLinkDefinition.java | 2 -
.../definitions/TestReportFileLinkDefinition.java | 2 -
.../gradle/foundation/queue/ExecutionQueue.java | 2 -
.../visitors/AllProjectsAndTasksVisitor.java | 10 -
.../visitors/TaskTreePopulationVisitor.java | 10 -
.../visitors/UniqueNameProjectAndTaskVisitor.java | 4 -
.../CommandLineArgumentAlteringListener.java | 2 -
.../gradleplugin/foundation/DOM4JSerializer.java | 2 -
.../gradleplugin/foundation/Dom4JUtility.java | 1 -
.../foundation/ExtensionFileFilter.java | 2 -
.../gradleplugin/foundation/GradlePluginLord.java | 2 -
.../foundation/favorites/FavoriteTask.java | 2 -
.../foundation/favorites/FavoritesEditor.java | 2 -
.../favorites/FavoritesSerializable.java | 5 +-
.../filters/AllowAllProjectAndTaskFilter.java | 2 -
.../foundation/filters/BasicFilterEditor.java | 2 -
.../filters/BasicProjectAndTaskFilter.java | 2 -
.../foundation/filters/ProjectAndTaskFilter.java | 3 -
.../foundation/request/AbstractRequest.java | 2 -
.../foundation/request/ExecutionRequest.java | 2 -
.../foundation/request/RefreshTaskListRequest.java | 2 -
.../gradleplugin/foundation/request/Request.java | 2 -
.../foundation/runner/GradleRunner.java | 2 -
.../foundation/search/BasicTextSearchCriteria.java | 2 -
.../foundation/search/TextBlockSearchEditor.java | 3 -
.../foundation/settings/DOM4JSettingsNode.java | 2 -
.../foundation/settings/SettingsNode.java | 2 -
.../foundation/settings/SettingsSerializable.java | 3 -
.../userinterface/AlternateUIInteraction.java | 3 -
.../swing/common/BorderlessImageButton.java | 2 -
.../swing/common/BorderlessImageToggleButton.java | 3 -
.../swing/common/BorderlessUtility.java | 2 -
.../swing/common/PreferencesAssistant.java | 2 -
.../userinterface/swing/common/SearchPanel.java | 21 +-
.../swing/common/TextPaneSearchInteraction.java | 4 +-
.../swing/generic/AbstractGradleUIInstance.java | 3 -
.../userinterface/swing/generic/BasicGradleUI.java | 10 -
.../swing/generic/DualPaneUIInstance.java | 2 -
.../swing/generic/MainGradlePanel.java | 2 -
.../userinterface/swing/generic/OutputPanel.java | 26 +-
.../swing/generic/OutputPanelLord.java | 9 +-
.../userinterface/swing/generic/OutputTab.java | 16 +-
.../swing/generic/SinglePaneUIInstance.java | 2 -
.../SwingAddMultipleFavoritesInteraction.java | 2 -
.../generic/SwingEditFavoriteInteraction.java | 10 +-
.../swing/generic/SwingExportInteraction.java | 8 +-
.../swing/generic/SwingImportInteraction.java | 2 -
.../swing/generic/TaskTreeComponent.java | 6 +-
.../userinterface/swing/generic/Utility.java | 18 +-
.../generic/filter/AbstractFilterEditorPanel.java | 2 -
.../generic/filter/ProjectAndTaskFilterDialog.java | 2 -
.../swing/generic/tabs/CommandLineTab.java | 2 -
.../swing/generic/tabs/FavoriteTasksTab.java | 2 -
.../swing/generic/tabs/GradleTab.java | 3 -
.../userinterface/swing/generic/tabs/SetupTab.java | 2 -
.../swing/generic/tabs/TaskTreeTab.java | 3 -
.../swing/standalone/Application.java | 2 -
.../swing/standalone/BlockingApplication.java | 2 -
.../openapi/wrappers/RunnerWrapperFactory.java | 3 -
.../gradle/openapi/wrappers/UIWrapperFactory.java | 2 -
.../foundation/GradleInterfaceWrapperVersion1.java | 2 -
.../foundation/GradleInterfaceWrapperVersion2.java | 2 -
.../wrappers/foundation/ProjectWrapper.java | 2 -
.../foundation/RequestObserverWrapper.java | 2 -
.../wrappers/foundation/RequestWrapper.java | 2 -
.../openapi/wrappers/foundation/TaskWrapper.java | 2 -
.../foundation/favorites/FavoriteTaskWrapper.java | 2 -
.../favorites/FavoritesEditorWrapper.java | 2 -
.../runner/GradleRunnerInteractionWrapper.java | 2 -
.../wrappers/runner/GradleRunnerWrapper.java | 2 -
.../wrappers/ui/AbstractOpenAPIUIWrapper.java | 3 -
.../ui/AlternateUIInteractionVersionWrapper.java | 2 -
...CommandLineArgumentAlteringListenerWrapper.java | 2 -
.../openapi/wrappers/ui/DualPaneUIWrapper.java | 2 -
.../wrappers/ui/GradleTabVersionWrapper.java | 2 -
.../openapi/wrappers/ui/OutputObserverWrapper.java | 2 -
.../openapi/wrappers/ui/OutputUILordWrapper.java | 2 -
.../wrappers/ui/SettingsNodeVersionWrapper.java | 2 -
.../openapi/wrappers/ui/SinglePaneUIWrapper.java | 2 -
.../org/gradle/foundation/BuildInformation.java | 7 +-
.../gradle/foundation/CommandLineParsingTest.java | 2 -
.../gradle/foundation/DOM4JSettingsNodeTest.java | 2 -
.../org/gradle/foundation/FavoritesTest.java | 2 -
.../org/gradle/foundation/FileLinkTests.java | 1 -
.../groovy/org/gradle/foundation/FilterTest.java | 2 -
.../gradle/foundation/LiveOutputParserTests.java | 2 -
.../groovy/org/gradle/foundation/TestUtility.java | 4 +-
.../foundation/TextBlockSearchEditorTests.java | 2 -
subprojects/ui/ui.gradle | 2 +-
.../WrapperConcurrentDownloadTest.groovy | 89 +++
.../WrapperGenerationIntegrationTest.groovy | 49 ++
.../integtests/WrapperHttpIntegrationTest.groovy | 148 ++++
.../WrapperProjectIntegrationTest.groovy | 125 +---
.../org/gradle/integtests/WrapperSetup.groovy | 28 +
.../WrapperUserHomeIntegrationTest.groovy | 72 ++
.../org/gradle/wrapper/BootstrapMainStarter.java | 3 -
.../src/main/java/org/gradle/wrapper/Download.java | 7 -
.../gradle/wrapper/ExclusiveFileAccessManager.java | 95 +++
.../java/org/gradle/wrapper/GradleWrapperMain.java | 51 +-
.../main/java/org/gradle/wrapper/IDownload.java | 3 -
.../src/main/java/org/gradle/wrapper/Install.java | 111 +--
.../java/org/gradle/wrapper/PathAssembler.java | 3 -
.../gradle/wrapper/SystemPropertiesHandler.java | 3 -
.../org/gradle/wrapper/WrapperConfiguration.java | 21 -
.../java/org/gradle/wrapper/WrapperExecutor.java | 3 -
.../groovy/org/gradle/wrapper/DownloadTest.groovy | 3 -
.../groovy/org/gradle/wrapper/InstallTest.groovy | 97 +--
.../org/gradle/wrapper/PathAssemblerTest.java | 3 -
.../wrapper/SystemPropertiesHandlerTest.groovy | 3 -
subprojects/wrapper/wrapper.gradle | 3 +-
version.txt | 2 +-
3896 files changed, 102930 insertions(+), 50908 deletions(-)
diff --git a/build.gradle b/build.gradle
index d5bca86..df49a77 100644
--- a/build.gradle
+++ b/build.gradle
@@ -28,23 +28,26 @@ buildTypes {
sanityCheck "classes", "doc:checkstyleApi", "codeQuality", "docs:check"
// The minimum to be run before check-in
- preCommitBuild "doc:checkstyleApi", "docs:check", "codeQuality", "classes", "test", noDistTests: true
- quickCheck "doc:checkstyleApi", "docs:check", "codeQuality", "classes", "test", noDistTests: true
+ preCommitBuild "doc:checkstyleApi", "docs:check", "codeQuality", "classes", "test"
+ quickCheck "doc:checkstyleApi", "docs:check", "codeQuality", "classes", "test"
// A full (in-process) test
developerBuild "check"
// Used by the first phase of the build pipeline
- quickTest "test", "integTest", noDistTests: true, noDocsTests: true
+ quickTest "runtimeTests", "runtimeIntegTests"
+
+ // Used for builds to run all tests, but not necessarily on all platforms
+ fullTest "runtimeTests", "runtimeIntegTests", useIncomingDistributions: true, defaultIntegTestExecuter: "forking"
// Used for builds to test the code on certain platforms
- platformTest "test", "forkingIntegTest", noDistTests: true, noDocsTests: true, useIncomingDistributions: true
+ platformTest "runtimeTests", "runtimeIntegTests", useIncomingDistributions: true, defaultIntegTestExecuter: "forking", testAllPlatforms: true
// Tests using the daemon mode
- daemonTest "daemonIntegTest", noDistTests: true, noDocsTests: true, useIncomingDistributions: true
+ daemonTest "runtimeIntegTests", useIncomingDistributions: true, defaultIntegTestExecuter: "daemon"
// Run the integration tests using the parallel executer
- parallelTest "parallelIntegTest", noDistTests: true, noDocsTests: true, useIncomingDistributions: true
+ parallelTest "runtimeIntegTests", useIncomingDistributions: true, defaultIntegTestExecuter: "parallel"
// Run the performance tests
performanceTest "performance:integTest", useIncomingDistributions: true
@@ -53,7 +56,7 @@ buildTypes {
localPerformanceTest "performance:integTest"
// Used for cross version tests on CI
- crossVersionTest "forkingIntegTest", crossVersionTestsOnly: "", testAllVersions: "", noDistTests: true, useIncomingDistributions: true
+ crossVersionTest "runtimeIntegTests", crossVersionTestsOnly: "", testAllVersions: "", useIncomingDistributions: true, defaultIntegTestExecuter: "forking"
// Used to build production distros and smoke test them
packageBuild "verifyIsProductionBuildEnvironment", "clean", "buildDists", "distributions:integTest"
@@ -87,7 +90,7 @@ ext {
pluginProjects = [
'plugins', 'codeQuality', 'jetty', 'antlr', 'wrapper', 'osgi', 'maven',
'ide', 'announce', 'scala', 'sonar', 'signing', 'cpp', 'ear', 'javascript', 'buildComparison',
- 'diagnostics', 'reporting', 'publish', 'ivy'
+ 'diagnostics', 'reporting', 'publish', 'ivy', 'jacoco', 'buildSetup', 'languageJvm', 'languageBase', 'buildSetup'
].collect {
project(it)
}
@@ -102,6 +105,7 @@ apply from: "gradle/idea.gradle"
apply from: "gradle/eclipse.gradle"
apply from: "gradle/classycle.gradle"
apply from: "gradle/noDependencyResolutionDuringConfiguration.gradle"
+apply from: "gradle/testGroupings.gradle"
allprojects {
group = 'org.gradle'
@@ -193,4 +197,5 @@ task installAll(type: Install) {
installDirPropertyName = 'gradle_installPath'
}
+
apply from: "gradle/intTestImage.gradle"
\ No newline at end of file
diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle
index 6973939..3047a80 100644
--- a/buildSrc/build.gradle
+++ b/buildSrc/build.gradle
@@ -29,7 +29,7 @@ dependencies {
compile gradleApi()
compile 'com.google.guava:guava:11.0.2 at jar'
compile 'commons-lang:commons-lang:2.6 at jar'
- groovy localGroovy()
+ compile localGroovy()
testCompile 'junit:junit:4.11 at jar'
testCompile 'org.spockframework:spock-core:0.7-groovy-1.8 at jar', 'cglib:cglib-nodep:2.2', 'org.objenesis:objenesis:1.2'
diff --git a/buildSrc/src/main/groovy/org/gradle/build/BuildTypes.groovy b/buildSrc/src/main/groovy/org/gradle/build/BuildTypes.groovy
index 4490268..e582417 100644
--- a/buildSrc/src/main/groovy/org/gradle/build/BuildTypes.groovy
+++ b/buildSrc/src/main/groovy/org/gradle/build/BuildTypes.groovy
@@ -64,7 +64,7 @@ class BuildTypes {
if (!project.hasProperty(k)) {
project.ext."$k" = null
}
- project.properties."$k" = v
+ project."$k" = v
}
}
diff --git a/buildSrc/src/main/groovy/org/gradle/build/JarJarJar.groovy b/buildSrc/src/main/groovy/org/gradle/build/JarJarJar.groovy
index 0af4c56..9b9e789 100644
--- a/buildSrc/src/main/groovy/org/gradle/build/JarJarJar.groovy
+++ b/buildSrc/src/main/groovy/org/gradle/build/JarJarJar.groovy
@@ -17,14 +17,12 @@
package org.gradle.build
import org.gradle.api.tasks.bundling.Jar
-import org.gradle.api.*
-import org.gradle.api.file.*
-import org.gradle.api.tasks.*
import com.tonicsystems.jarjar.Main as JarJarMain
+import org.gradle.api.tasks.Input
/*
* a Jar task that performs JarJar repackaging after archive is created
-* */
+ */
class JarJarJar extends Jar {
@Input def rules = [:]
@Input def keeps = []
diff --git a/buildSrc/src/main/groovy/org/gradle/build/docs/SampleElementValidator.groovy b/buildSrc/src/main/groovy/org/gradle/build/docs/SampleElementValidator.groovy
index ca0e38c..6a917b6 100644
--- a/buildSrc/src/main/groovy/org/gradle/build/docs/SampleElementValidator.groovy
+++ b/buildSrc/src/main/groovy/org/gradle/build/docs/SampleElementValidator.groovy
@@ -19,8 +19,6 @@ import org.w3c.dom.Element
/**
* Validates sample element - looks for missing attributes.
- *
- * @author Tomek Kaczanowski
*/
public class SampleElementValidator {
diff --git a/buildSrc/src/main/groovy/org/gradle/build/docs/UserGuideTransformTask.groovy b/buildSrc/src/main/groovy/org/gradle/build/docs/UserGuideTransformTask.groovy
index 02dad83..bde13c9 100644
--- a/buildSrc/src/main/groovy/org/gradle/build/docs/UserGuideTransformTask.groovy
+++ b/buildSrc/src/main/groovy/org/gradle/build/docs/UserGuideTransformTask.groovy
@@ -29,7 +29,7 @@ import org.w3c.dom.Element
import org.gradle.api.tasks.*
/**
- * Transforms userguide source into docbook, replacing custom xml elements.
+ * Transforms userguide source into docbook, replacing custom XML elements.
*
* Takes the following as input:
* <ul>
@@ -227,8 +227,9 @@ public class UserGuideTransformTask extends DefaultTask {
String args = child.'@args'
String outputFile = child.'@outputFile' ?: "${sampleId}.out"
boolean ignoreExtraLines = child.'@ignoreExtraLines' ?: false
+ boolean ignoreLineOrder = child.'@ignoreLineOrder' ?: false
- samplesXml << { sample(id: sampleId, dir: srcDir, args: args, outputFile: outputFile, ignoreExtraLines: ignoreExtraLines) }
+ samplesXml << { sample(id: sampleId, dir: srcDir, args: args, outputFile: outputFile, ignoreExtraLines: ignoreExtraLines, ignoreLineOrder: ignoreLineOrder) }
Element outputTitle = doc.createElement("para")
outputTitle.appendChild(doc.createTextNode("Output of "))
diff --git a/buildSrc/src/main/groovy/org/gradle/build/docs/dsl/docbook/JavadocConverter.java b/buildSrc/src/main/groovy/org/gradle/build/docs/dsl/docbook/JavadocConverter.java
index 5685f02..64f27b6 100644
--- a/buildSrc/src/main/groovy/org/gradle/build/docs/dsl/docbook/JavadocConverter.java
+++ b/buildSrc/src/main/groovy/org/gradle/build/docs/dsl/docbook/JavadocConverter.java
@@ -123,6 +123,7 @@ public class JavadocConverter {
handler.add(new LinkHandler(nodes, linkConverter, classMetaData, listener));
handler.add(new InheritDocHandler(nodes, inheritedCommentSource));
handler.add(new ValueTagHandler(nodes, linkConverter, classMetaData, listener));
+ handler.add(new LiteralTagHandler(nodes));
handler.add(new TableHandler(nodes, document));
handler.add(new DlElementHandler(nodes, document));
handler.add(new AnchorElementHandler(nodes, document, classMetaData));
@@ -665,6 +666,22 @@ public class JavadocConverter {
}
}
+ private static class LiteralTagHandler implements JavadocTagHandler {
+ private final DocBookBuilder nodes;
+
+ private LiteralTagHandler(DocBookBuilder nodes) {
+ this.nodes = nodes;
+ }
+
+ public boolean onJavadocTag(String tag, String value) {
+ if (!tag.equals("literal")) {
+ return false;
+ }
+ nodes.appendChild(value);
+ return true;
+ }
+ }
+
private static class LinkHandler implements JavadocTagHandler {
private final DocBookBuilder nodes;
private final JavadocLinkConverter linkConverter;
diff --git a/buildSrc/src/main/groovy/org/gradle/build/docs/dsl/source/ExtractDslMetaDataTask.groovy b/buildSrc/src/main/groovy/org/gradle/build/docs/dsl/source/ExtractDslMetaDataTask.groovy
index 9ca6c6c..8333f67 100644
--- a/buildSrc/src/main/groovy/org/gradle/build/docs/dsl/source/ExtractDslMetaDataTask.groovy
+++ b/buildSrc/src/main/groovy/org/gradle/build/docs/dsl/source/ExtractDslMetaDataTask.groovy
@@ -40,8 +40,8 @@ import org.gradle.build.docs.DocGenerationException
import org.gradle.api.Transformer
/**
- * Extracts meta-data from the Groovy and Java source files which make up the Gradle DSL. Persists the meta-data to a file
- * for later use in generating the docbook source for the DSL, such as by {@link org.gradle.build.docs.dsl.docbook.AssembleDslDocTask}.
+ * Extracts meta-data from the Groovy and Java source files which make up the Gradle API. Persists the meta-data to a file
+ * for later use in generating documentation for the DSL, such as by {@link org.gradle.build.docs.dsl.docbook.AssembleDslDocTask}.
*/
class ExtractDslMetaDataTask extends SourceTask {
@OutputFile
diff --git a/buildSrc/src/main/groovy/org/gradle/build/docs/dsl/source/GenerateDefaultImportsTask.java b/buildSrc/src/main/groovy/org/gradle/build/docs/dsl/source/GenerateDefaultImportsTask.java
new file mode 100644
index 0000000..2d4a45d
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/gradle/build/docs/dsl/source/GenerateDefaultImportsTask.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.build.docs.dsl.source;
+
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
+import org.gradle.api.Action;
+import org.gradle.api.DefaultTask;
+import org.gradle.api.tasks.Input;
+import org.gradle.api.tasks.InputFile;
+import org.gradle.api.tasks.OutputFile;
+import org.gradle.api.tasks.TaskAction;
+import org.gradle.build.docs.dsl.source.model.ClassMetaData;
+import org.gradle.build.docs.model.SimpleClassMetaDataRepository;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.*;
+
+public class GenerateDefaultImportsTask extends DefaultTask {
+ private File metaDataFile;
+ private File destFile;
+ private Set<String> excludePatterns = new HashSet<String>();
+ private Set<String> extraPackages = new HashSet<String>();
+
+ @InputFile
+ public File getMetaDataFile() {
+ return metaDataFile;
+ }
+
+ public void setMetaDataFile(File metaDataFile) {
+ this.metaDataFile = metaDataFile;
+ }
+
+ @OutputFile
+ public File getDestFile() {
+ return destFile;
+ }
+
+ public void setDestFile(File destFile) {
+ this.destFile = destFile;
+ }
+
+ @Input
+ public Set<String> getExcludedPackages() {
+ return excludePatterns;
+ }
+
+ public void setExcludedPackages(Set<String> excludedPackages) {
+ this.excludePatterns = excludedPackages;
+ }
+
+ /**
+ * Package name can end with '.**' to exclude subpackages as well.
+ */
+ public void excludePackage(String name) {
+ excludePatterns.add(name);
+ }
+
+ public Set<String> getExtraPackages() {
+ return extraPackages;
+ }
+
+ public void setExtraPackages(Set<String> extraPackages) {
+ this.extraPackages = extraPackages;
+ }
+
+ public void extraPackage(String name) {
+ extraPackages.add(name);
+ }
+
+ @TaskAction
+ public void generate() throws IOException {
+ SimpleClassMetaDataRepository<ClassMetaData> repository = new SimpleClassMetaDataRepository<ClassMetaData>();
+ repository.load(getMetaDataFile());
+
+ final Set<String> excludedPrefixes = new HashSet<String>();
+ final Set<String> excludedPackages = new HashSet<String>();
+ for (String excludePattern : excludePatterns) {
+ if (excludePattern.endsWith(".**")) {
+ String baseName = excludePattern.substring(0, excludePattern.length() - 3);
+ excludedPrefixes.add(baseName + '.');
+ excludedPackages.add(baseName);
+ } else {
+ excludedPackages.add(excludePattern);
+ }
+ }
+ final Set<String> packages = new TreeSet<String>();
+ packages.addAll(extraPackages);
+ final Multimap<String, String> simpleNames = HashMultimap.create();
+
+ repository.each(new Action<ClassMetaData>() {
+ public void execute(ClassMetaData classMetaData) {
+ if (classMetaData.getOuterClassName() != null) {
+ // Ignore inner classes
+ return;
+ }
+ String packageName = classMetaData.getPackageName();
+ if (excludedPackages.contains(packageName)) {
+ return;
+ }
+ for (String excludedPrefix : excludedPrefixes) {
+ if (packageName.startsWith(excludedPrefix)) {
+ return;
+ }
+ }
+ simpleNames.put(classMetaData.getSimpleName(), classMetaData.getClassName());
+ packages.add(packageName);
+ }
+ });
+
+ for (Map.Entry<String, Collection<String>> entry : simpleNames.asMap().entrySet()) {
+ if (entry.getValue().size() > 1) {
+ System.out.println(String.format("Multiple DSL types have short name '%s'", entry.getKey()));
+ for (String className : entry.getValue()) {
+ System.out.println(" * " + className);
+ }
+ }
+ }
+
+ final PrintWriter writer = new PrintWriter(new FileWriter(getDestFile()));
+ try {
+ for (String packageName : packages) {
+ writer.print("import ");
+ writer.print(packageName);
+ writer.println(".*");
+ }
+ } finally {
+ writer.close();
+ }
+ }
+}
diff --git a/buildSrc/src/main/groovy/org/gradle/build/docs/model/SimpleClassMetaDataRepository.java b/buildSrc/src/main/groovy/org/gradle/build/docs/model/SimpleClassMetaDataRepository.java
index f5ec24e..3811902 100644
--- a/buildSrc/src/main/groovy/org/gradle/build/docs/model/SimpleClassMetaDataRepository.java
+++ b/buildSrc/src/main/groovy/org/gradle/build/docs/model/SimpleClassMetaDataRepository.java
@@ -16,12 +16,12 @@
package org.gradle.build.docs.model;
import groovy.lang.Closure;
+import org.gradle.api.Action;
import org.gradle.api.GradleException;
import org.gradle.api.UnknownDomainObjectException;
import java.io.*;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.*;
public class SimpleClassMetaDataRepository<T extends Attachable<T>> implements ClassMetaDataRepository<T> {
private final Map<String, T> classes = new HashMap<String, T>();
@@ -82,4 +82,10 @@ public class SimpleClassMetaDataRepository<T extends Attachable<T>> implements C
cl.call(new Object[]{entry.getKey(), entry.getValue()});
}
}
+
+ public void each(Action<? super T> action) {
+ for (T t : classes.values()) {
+ action.execute(t);
+ }
+ }
}
diff --git a/buildSrc/src/test/groovy/org/gradle/build/docs/dsl/docbook/JavadocConverterTest.groovy b/buildSrc/src/test/groovy/org/gradle/build/docs/dsl/docbook/JavadocConverterTest.groovy
index 9749b9d..e44d297 100644
--- a/buildSrc/src/test/groovy/org/gradle/build/docs/dsl/docbook/JavadocConverterTest.groovy
+++ b/buildSrc/src/test/groovy/org/gradle/build/docs/dsl/docbook/JavadocConverterTest.groovy
@@ -140,6 +140,16 @@ line 2</para>'''
format(result.docbook) == '''<para>This is <literal>code</literal>. So is <literal>this</literal>.</para>'''
}
+ def convertsLiteralTagsToText() {
+ _ * classMetaData.rawCommentText >> '{@literal <b>markup</b> {@ignore}}'
+
+ when:
+ def result = parser.parse(classMetaData, listener)
+
+ then:
+ format(result.docbook) == '''<para><b>markup</b> {@ignore}</para>'''
+ }
+
def doesNotInterpretContentsOfCodeTagAsHtml() {
_ * classMetaData.rawCommentText >> '{@code List<String> && a < 9} <code>&</code>'
diff --git a/buildSrc/src/test/groovy/org/gradle/build/docs/model/SimpleClassMetaDataRepositoryTest.groovy b/buildSrc/src/test/groovy/org/gradle/build/docs/model/SimpleClassMetaDataRepositoryTest.groovy
index 23e867b..1ce3f08 100644
--- a/buildSrc/src/test/groovy/org/gradle/build/docs/model/SimpleClassMetaDataRepositoryTest.groovy
+++ b/buildSrc/src/test/groovy/org/gradle/build/docs/model/SimpleClassMetaDataRepositoryTest.groovy
@@ -15,10 +15,14 @@
*/
package org.gradle.build.docs.model
-import spock.lang.Specification
+import org.gradle.api.Action
import org.gradle.api.UnknownDomainObjectException
+import org.junit.Rule
+import org.junit.rules.TemporaryFolder
+import spock.lang.Specification
class SimpleClassMetaDataRepositoryTest extends Specification {
+ @Rule TemporaryFolder tmpDir
final SimpleClassMetaDataRepository<TestDomainObject> repository = new SimpleClassMetaDataRepository<TestDomainObject>()
def canAddMetaData() {
@@ -46,7 +50,7 @@ class SimpleClassMetaDataRepositoryTest extends Specification {
e.message == 'No meta-data is available for class \'unknown\'.'
}
- def canIterateOverClasses() {
+ def canIterateOverClassesUsingClosure() {
TestDomainObject value1 = new TestDomainObject('a')
TestDomainObject value2 = new TestDomainObject('a')
repository.put('class1', value1)
@@ -62,9 +66,25 @@ class SimpleClassMetaDataRepositoryTest extends Specification {
0 * cl._
}
+ def canIterateOverClassesUsingAction() {
+ TestDomainObject value1 = new TestDomainObject('a')
+ TestDomainObject value2 = new TestDomainObject('a')
+ repository.put('class1', value1)
+ repository.put('class2', value2)
+ Action action = Mock()
+
+ when:
+ repository.each(action)
+
+ then:
+ 1 * action.execute(value1)
+ 1 * action.execute(value2)
+ 0 * action._
+ }
+
def canPersistMetaData() {
TestDomainObject value = new TestDomainObject('a')
- File file = File.createTempFile("test-repository", "bin")
+ File file = tmpDir.newFile()
repository.put('class', value)
when:
diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml
index 6b0b710..742953d 100644
--- a/config/checkstyle/checkstyle.xml
+++ b/config/checkstyle/checkstyle.xml
@@ -111,6 +111,9 @@
<module name="RegexpSingleline">
<property name="format" value="Created with IntelliJ IDEA"/>
</module>
+ <module name="RegexpSingleline">
+ <property name="format" value="^\s*\*\s*@author"/>
+ </module>
<!-- allows suppressing using the //CHECKSTYLE:ON //CHECKSTYLE:OFF -->
<module name="SuppressionCommentFilter"/>
diff --git a/gradle/buildReceipt.gradle b/gradle/buildReceipt.gradle
index 3139797..eb0209e 100644
--- a/gradle/buildReceipt.gradle
+++ b/gradle/buildReceipt.gradle
@@ -118,6 +118,7 @@ task createBuildReceipt(dependsOn: determineCommitId) {
isSnapshot: isSnapshot,
rcNumber: rcNumber == null ? "" : rcNumber,
buildTimestamp: buildTimestamp,
+ buildNumber: System.properties["build.number"] ?: 'none',
username: System.properties["user.name"],
hostname: hostName,
javaVersion: System.properties["java.version"],
diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle
index 0face90..0f8f692 100755
--- a/gradle/dependencies.gradle
+++ b/gradle/dependencies.gradle
@@ -21,8 +21,8 @@ ext {
versions.commons_io = 'commons-io:commons-io:1.4'
-libraries.ant = dependencies.module('org.apache.ant:ant:1.8.4') {
- dependency 'org.apache.ant:ant-launcher:1.8.4 at jar'
+libraries.ant = dependencies.module('org.apache.ant:ant:1.9.2') {
+ dependency 'org.apache.ant:ant-launcher:1.9.2 at jar'
}
libraries.asm = 'org.ow2.asm:asm-all:4.0 at jar'
@@ -76,7 +76,7 @@ libraries.maven_ant_tasks = dependencies.module("org.apache.maven:maven-ant-task
}
libraries += [
- ant_antlr: 'org.apache.ant:ant-antlr:1.8.4 at jar',
+ ant_antlr: 'org.apache.ant:ant-antlr:1.9.2 at jar',
antlr: 'antlr:antlr:2.7.7 at jar',
dom4j: 'dom4j:dom4j:1.6.1 at jar',
guava: 'com.google.guava:guava:11.0.2 at jar',
diff --git a/gradle/groovyProject.gradle b/gradle/groovyProject.gradle
index f69306b..6b7b3dc 100644
--- a/gradle/groovyProject.gradle
+++ b/gradle/groovyProject.gradle
@@ -8,7 +8,6 @@ sourceCompatibility = 1.5
targetCompatibility = 1.5
ext {
- hasGroovySource = sourceSets.main.groovy.srcDirs.any { it.exists() }
compileTasks = tasks.matching { it instanceof Compile || it instanceof GroovyCompile }
testTasks = tasks.withType(Test)
generatedResourcesDir = file("$buildDir/generated-resources/main")
@@ -20,11 +19,6 @@ dependencies {
testCompile libraries.junit, libraries.jmock, libraries.spock
}
-if (!hasGroovySource) {
- // Remove Groovy configuration from compile classpath
- configurations.compile.extendsFrom = []
-}
-
// Extracted as it's also used by buildSrc
apply from: "$rootDir/gradle/compile.gradle"
@@ -97,4 +91,16 @@ class ClasspathManifest extends DefaultTask {
manifestFile.withOutputStream { properties.save(it, 'module definition') }
}
}
-ext.ClasspathManifest = ClasspathManifest
\ No newline at end of file
+ext.ClasspathManifest = ClasspathManifest
+
+// This is here mostly for the TravisCI build.
+// It advertises as an ANSI capable terminal but isn't, so we run with -q there to make
+// the output legible, but we still want test result info
+tasks.withType(Test) {
+ testLogging {
+ quiet {
+ events "failed"
+ exceptionFormat "full"
+ }
+ }
+}
\ No newline at end of file
diff --git a/gradle/integTest.gradle b/gradle/integTest.gradle
index d5b36ca..6c8944e 100644
--- a/gradle/integTest.gradle
+++ b/gradle/integTest.gradle
@@ -29,7 +29,7 @@ integTestTasks.all { Test task ->
testSrcDirs = []
jvmArgs '-Xmx512m', '-XX:MaxPermSize=256m', '-XX:+HeapDumpOnOutOfMemoryError'
- testResultsDir = file("${project.testResultsDir}/$name")
+ reports.junitXml.destination = file("${project.testResultsDir}/$name")
systemProperties['org.gradle.integtest.versions'] = project.hasProperty("testAllVersions") ? 'all' : 'latest'
if (project.hasProperty('crossVersionTestsOnly')) {
@@ -37,9 +37,11 @@ integTestTasks.all { Test task ->
forkEvery = 1
}
+ systemProperties['org.gradle.integtest.cpp.toolChains'] = project.hasProperty("testAllPlatforms") ? 'all' : 'default';
+
dependsOn project.task("configure${task.name.capitalize()}") << {
configure(task) {
- testReportDir = file("${project.reporting.baseDir}/$name")
+ reports.html.destination = file("${project.reporting.baseDir}/$name")
systemProperties['integTest.gradleHomeDir'] = rootProject.intTestImage.destinationDir.absolutePath
systemProperties['integTest.gradleUserHomeDir'] = rootProject.file('intTestHomeDir').absolutePath
systemProperties['integTest.libsRepo'] = rootProject.file('build/repo')
@@ -63,7 +65,7 @@ check.dependsOn(integTest)
['embedded', 'forking', 'daemon', 'embeddedDaemon', 'parallel'].each { mode ->
def taskName = "${mode}IntegTest"
- tasks.add(taskName, Test).configure {
+ tasks.create(taskName, Test).configure {
systemProperties['org.gradle.integtest.executer'] = mode
}
}
diff --git a/gradle/testGroupings.gradle b/gradle/testGroupings.gradle
new file mode 100644
index 0000000..52945e1
--- /dev/null
+++ b/gradle/testGroupings.gradle
@@ -0,0 +1,13 @@
+// only the projects that contribute runtime code
+def runtimeProjects = subprojects - [':docs', ':distributions', ':performance'].collect { project(it) }
+
+def runtimeProjectTasks = { String taskName ->
+ runtimeProjects.collect { it.tasks.findByPath(taskName) }.findAll { it != null }
+}
+task runtimeTests {
+ dependsOn { runtimeProjectTasks("test") }
+}
+
+task runtimeIntegTests {
+ dependsOn { runtimeProjectTasks("integTest") }
+}
\ No newline at end of file
diff --git a/gradle/versioning.gradle b/gradle/versioning.gradle
index 7b715eb..1d93b09 100644
--- a/gradle/versioning.gradle
+++ b/gradle/versioning.gradle
@@ -1,6 +1,10 @@
def timestampFormat = new java.text.SimpleDateFormat('yyyyMMddHHmmssZ')
timestampFormat.timeZone = TimeZone.getTimeZone("UTC")
+if (buildTypes.isActive("promotionBuild")) {
+ logger.lifecycle "Invocation tasks: $gradle.startParameter.taskNames\nInvocation properties: $gradle.startParameter.projectProperties"
+}
+
if (incomingDistributionsBuildReceipt) {
ext.versionBase = incomingDistributionsBuildReceipt.versionBase
ext.buildTimestamp = incomingDistributionsBuildReceipt.buildTimestamp
diff --git a/gradle/wrapper.gradle b/gradle/wrapper.gradle
index 5fd0747..dc447f5 100644
--- a/gradle/wrapper.gradle
+++ b/gradle/wrapper.gradle
@@ -15,19 +15,27 @@
*/
def wrapperUpdateTask = { name, label ->
- task "${name}Wrapper"(type: Wrapper) {
- group = "wrapper"
- doFirst {
- def version = new groovy.json.JsonSlurper().parseText(new URL("http://services.gradle.org/versions/$label").text)
- if (version.empty) {
- throw new GradleException("Cannot update wrapper to '${label}' version as there is currently no version of that label")
+ def wrapperTaskName = "${name}Wrapper"
+ def configureWrapperTaskName = "configure${wrapperTaskName.capitalize()}"
+
+ task "$configureWrapperTaskName" {
+ doLast {
+ configure(tasks."$wrapperTaskName") {
+ def version = new groovy.json.JsonSlurper().parseText(new URL("http://services.gradle.org/versions/$label").text)
+ if (version.empty) {
+ throw new GradleException("Cannot update wrapper to '${label}' version as there is currently no version of that label")
+ }
+ println "updating wrapper to $label version: $version.version (downloadUrl: $version.downloadUrl)"
+ distributionUrl version.downloadUrl
}
- println "updating wrapper to $label version: $version.version (downloadUrl: $version.downloadUrl)"
- distributionUrl version.downloadUrl
}
+ }
+
+ task "${wrapperTaskName}"(type: Wrapper, dependsOn: configureWrapperTaskName) {
+ group = "wrapper"
+ def jvmOpts = "-Xmx1024m -XX:MaxPermSize=256m -Dfile.encoding=UTF-8"
+ inputs.property("jvmOpts", jvmOpts)
doLast {
- def jvmOpts = "-Xmx1024m -XX:MaxPermSize=256m -Dfile.encoding=UTF-8"
- inputs.property("jvmOpts", jvmOpts)
def optsEnvVar = "DEFAULT_JVM_OPTS"
scriptFile.write scriptFile.text.replace("$optsEnvVar=\"\"", "$optsEnvVar=\"$jvmOpts\"")
batchScript.write batchScript.text.replace("set $optsEnvVar=", "set $optsEnvVar=$jvmOpts")
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 8e1362d..95f5809 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Mon Mar 11 12:15:50 GMT 2013
+#Tue Aug 06 12:46:48 BST 2013
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=http\://services.gradle.org/distributions/gradle-1.5-rc-1-bin.zip
+distributionUrl=http\://services.gradle.org/distributions/gradle-1.7-bin.zip
diff --git a/settings.gradle b/settings.gradle
index 801a90d..2b7976f 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -22,6 +22,7 @@ include 'wrapper'
include 'cli'
include 'launcher'
include 'messaging'
+include 'resources'
include 'plugins'
include 'scala'
include 'ide'
@@ -50,6 +51,10 @@ include 'reporting'
include 'diagnostics'
include 'publish'
include 'ivy'
+include 'jacoco'
+include 'buildSetup'
+include 'languageBase'
+include 'languageJvm'
rootProject.name = 'gradle'
rootProject.children.each {project ->
diff --git a/subprojects/announce/announce.gradle b/subprojects/announce/announce.gradle
index 68a1e47..6787365 100644
--- a/subprojects/announce/announce.gradle
+++ b/subprojects/announce/announce.gradle
@@ -14,8 +14,7 @@
* limitations under the License.
*/
dependencies {
- groovy libraries.groovy
-
+ compile libraries.groovy
compile libraries.slf4j_api
compile project(':core')
integTestRuntime project(':plugins')
diff --git a/subprojects/announce/src/main/groovy/org/gradle/api/plugins/announce/AnnouncePlugin.groovy b/subprojects/announce/src/main/groovy/org/gradle/api/plugins/announce/AnnouncePlugin.groovy
index 87d879d..d9b630e 100644
--- a/subprojects/announce/src/main/groovy/org/gradle/api/plugins/announce/AnnouncePlugin.groovy
+++ b/subprojects/announce/src/main/groovy/org/gradle/api/plugins/announce/AnnouncePlugin.groovy
@@ -18,16 +18,13 @@ package org.gradle.api.plugins.announce
import org.gradle.api.Plugin
import org.gradle.api.Project
-import org.gradle.api.internal.project.ProjectInternal
/**
* This plugin allows to send announce messages to Twitter.
- *
- * @author hackergarten
*/
class AnnouncePlugin implements Plugin<Project> {
void apply(Project project) {
- project.extensions.add("announce", new AnnouncePluginExtension((ProjectInternal)project))
+ project.extensions.create("announce", AnnouncePluginExtension.class, project)
}
}
diff --git a/subprojects/announce/src/main/groovy/org/gradle/api/plugins/announce/AnnouncePluginExtension.groovy b/subprojects/announce/src/main/groovy/org/gradle/api/plugins/announce/AnnouncePluginExtension.groovy
index ab6f62c..55ffd22 100644
--- a/subprojects/announce/src/main/groovy/org/gradle/api/plugins/announce/AnnouncePluginExtension.groovy
+++ b/subprojects/announce/src/main/groovy/org/gradle/api/plugins/announce/AnnouncePluginExtension.groovy
@@ -37,14 +37,14 @@ class AnnouncePluginExtension {
*/
String password
- Announcer local
-
+ private final onDemandLocalAnnouncer
private final Project project
AnnouncerFactory announcerFactory
AnnouncePluginExtension(ProjectInternal project) {
this.project = project
this.announcerFactory = new DefaultAnnouncerFactory(this, project, new DefaultIconProvider(project.services.get(GradleDistributionLocator)))
+ this.onDemandLocalAnnouncer = new LocalAnnouncer(this)
}
/**
@@ -53,14 +53,14 @@ class AnnouncePluginExtension {
* @return The announcer.
*/
Announcer getLocal() {
- return new Announcer() {
- void send(String title, String message) {
- if (local == null) {
- local = announcerFactory.createAnnouncer("local")
- }
- local.send(title, message)
- }
- }
+ return onDemandLocalAnnouncer
+ }
+
+ /**
+ * Sets the {@link Announcer} that should be used to send announcements to the local desktop.
+ */
+ void setLocal(Announcer localAnnouncer) {
+ onDemandLocalAnnouncer.local = localAnnouncer
}
/**
@@ -76,4 +76,20 @@ class AnnouncePluginExtension {
logger.warn("Failed to send message '$msg' to '$type'", e)
}
}
+
+ private static class LocalAnnouncer implements Announcer {
+ AnnouncePluginExtension extension
+ Announcer local
+
+ LocalAnnouncer(AnnouncePluginExtension extension) {
+ this.extension = extension
+ }
+
+ void send(String title, String message) {
+ if (local == null) {
+ local = extension.getAnnouncerFactory().createAnnouncer("local")
+ }
+ local.send(title, message)
+ }
+ }
}
diff --git a/subprojects/announce/src/main/groovy/org/gradle/api/plugins/announce/internal/AnnouncerFactory.groovy b/subprojects/announce/src/main/groovy/org/gradle/api/plugins/announce/internal/AnnouncerFactory.groovy
index edd5270..b11870f 100644
--- a/subprojects/announce/src/main/groovy/org/gradle/api/plugins/announce/internal/AnnouncerFactory.groovy
+++ b/subprojects/announce/src/main/groovy/org/gradle/api/plugins/announce/internal/AnnouncerFactory.groovy
@@ -17,9 +17,6 @@ package org.gradle.api.plugins.announce.internal
import org.gradle.api.plugins.announce.Announcer
-/**
- * @author Hans Dockter
- */
interface AnnouncerFactory {
Announcer createAnnouncer(String type)
}
diff --git a/subprojects/announce/src/main/groovy/org/gradle/api/plugins/announce/internal/DefaultAnnouncerFactory.groovy b/subprojects/announce/src/main/groovy/org/gradle/api/plugins/announce/internal/DefaultAnnouncerFactory.groovy
index 8c5b687..d78f09a 100755
--- a/subprojects/announce/src/main/groovy/org/gradle/api/plugins/announce/internal/DefaultAnnouncerFactory.groovy
+++ b/subprojects/announce/src/main/groovy/org/gradle/api/plugins/announce/internal/DefaultAnnouncerFactory.groovy
@@ -22,9 +22,6 @@ import org.gradle.api.plugins.announce.AnnouncePluginExtension
import org.gradle.api.plugins.announce.Announcer
import org.gradle.internal.os.OperatingSystem
-/**
- * @author Hans Dockter
- */
class DefaultAnnouncerFactory implements AnnouncerFactory {
private final AnnouncePluginExtension announcePluginConvention
private final IconProvider iconProvider
diff --git a/subprojects/announce/src/main/groovy/org/gradle/api/plugins/announce/internal/NotifySend.groovy b/subprojects/announce/src/main/groovy/org/gradle/api/plugins/announce/internal/NotifySend.groovy
index f74a00f..ebcc3d4 100644
--- a/subprojects/announce/src/main/groovy/org/gradle/api/plugins/announce/internal/NotifySend.groovy
+++ b/subprojects/announce/src/main/groovy/org/gradle/api/plugins/announce/internal/NotifySend.groovy
@@ -23,10 +23,7 @@ import org.gradle.internal.os.OperatingSystem
/**
* This class wraps the Ubuntu Notify Send functionality.
- *
- * @author Hackergarten
*/
-
class NotifySend implements Announcer {
private final IconProvider iconProvider
private final ProcessOperations processOperations
diff --git a/subprojects/announce/src/main/groovy/org/gradle/api/plugins/announce/internal/Twitter.groovy b/subprojects/announce/src/main/groovy/org/gradle/api/plugins/announce/internal/Twitter.groovy
index a697f15..70e0664 100644
--- a/subprojects/announce/src/main/groovy/org/gradle/api/plugins/announce/internal/Twitter.groovy
+++ b/subprojects/announce/src/main/groovy/org/gradle/api/plugins/announce/internal/Twitter.groovy
@@ -14,17 +14,15 @@
* limitations under the License.
*/
-package org.gradle.api.plugins.announce.internal;
+package org.gradle.api.plugins.announce.internal
+import org.gradle.api.plugins.announce.Announcer
+import org.slf4j.Logger
import org.slf4j.LoggerFactory
import sun.misc.BASE64Encoder
-import org.slf4j.Logger
-import org.gradle.api.plugins.announce.Announcer
/**
* This class allows to send announce messages to Twitter.
- *
- * @author Hackergarten
*/
class Twitter implements Announcer {
private static final Logger logger = LoggerFactory.getLogger(Twitter)
diff --git a/subprojects/announce/src/test/groovy/org/gradle/api/plugins/announce/AnnouncePluginExtensionTest.groovy b/subprojects/announce/src/test/groovy/org/gradle/api/plugins/announce/AnnouncePluginExtensionTest.groovy
index a2279f4..0d7b22f 100644
--- a/subprojects/announce/src/test/groovy/org/gradle/api/plugins/announce/AnnouncePluginExtensionTest.groovy
+++ b/subprojects/announce/src/test/groovy/org/gradle/api/plugins/announce/AnnouncePluginExtensionTest.groovy
@@ -17,16 +17,12 @@ package org.gradle.api.plugins.announce
import org.gradle.api.internal.project.ProjectInternal
import org.gradle.api.plugins.announce.internal.AnnouncerFactory
+import org.gradle.util.TestUtil
import spock.lang.Specification
-import org.gradle.util.HelperUtil
-
-/**
- * @author Hans Dockter
- */
class AnnouncePluginExtensionTest extends Specification {
final AnnouncerFactory announcerFactory = Mock()
- final ProjectInternal project = HelperUtil.createRootProject()
+ final ProjectInternal project = TestUtil.createRootProject()
final AnnouncePluginExtension announcePluginConvention = new AnnouncePluginExtension(project)
def setup() {
diff --git a/subprojects/announce/src/test/groovy/org/gradle/api/plugins/announce/AnnouncePluginTest.groovy b/subprojects/announce/src/test/groovy/org/gradle/api/plugins/announce/AnnouncePluginTest.groovy
index 939c63b..b03bbe4 100644
--- a/subprojects/announce/src/test/groovy/org/gradle/api/plugins/announce/AnnouncePluginTest.groovy
+++ b/subprojects/announce/src/test/groovy/org/gradle/api/plugins/announce/AnnouncePluginTest.groovy
@@ -15,16 +15,13 @@
*/
package org.gradle.api.plugins.announce
-import spock.lang.Specification
-import org.gradle.util.HelperUtil
import org.gradle.api.Project
+import org.gradle.util.TestUtil
+import spock.lang.Specification
-/**
- * @author Hans Dockter
- */
class AnnouncePluginTest extends Specification {
AnnouncePlugin announcePlugin = new AnnouncePlugin()
- Project project = HelperUtil.createRootProject()
+ Project project = TestUtil.createRootProject()
def addExtensionObject() {
when:
diff --git a/subprojects/announce/src/test/groovy/org/gradle/api/plugins/announce/BuildAnnouncementsPluginTest.groovy b/subprojects/announce/src/test/groovy/org/gradle/api/plugins/announce/BuildAnnouncementsPluginTest.groovy
index 3604998..178ea23 100644
--- a/subprojects/announce/src/test/groovy/org/gradle/api/plugins/announce/BuildAnnouncementsPluginTest.groovy
+++ b/subprojects/announce/src/test/groovy/org/gradle/api/plugins/announce/BuildAnnouncementsPluginTest.groovy
@@ -16,11 +16,11 @@
package org.gradle.api.plugins.announce
import spock.lang.Specification
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import org.gradle.api.Project
class BuildAnnouncementsPluginTest extends Specification {
- final Project project = HelperUtil.createRootProject()
+ final Project project = TestUtil.createRootProject()
final BuildAnnouncementsPlugin plugin = new BuildAnnouncementsPlugin()
def "applies announce plugin"() {
diff --git a/subprojects/announce/src/test/groovy/org/gradle/api/plugins/announce/internal/DefaultAnnouncerFactoryTest.groovy b/subprojects/announce/src/test/groovy/org/gradle/api/plugins/announce/internal/DefaultAnnouncerFactoryTest.groovy
index 48dcbe3..97289bf 100644
--- a/subprojects/announce/src/test/groovy/org/gradle/api/plugins/announce/internal/DefaultAnnouncerFactoryTest.groovy
+++ b/subprojects/announce/src/test/groovy/org/gradle/api/plugins/announce/internal/DefaultAnnouncerFactoryTest.groovy
@@ -18,14 +18,11 @@ package org.gradle.api.plugins.announce.internal
import org.gradle.api.internal.ProcessOperations
import org.gradle.api.plugins.announce.AnnouncePluginExtension
import org.gradle.internal.os.OperatingSystem
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import spock.lang.Specification
-/**
- * @author Hans Dockter
- */
class DefaultAnnouncerFactoryTest extends Specification {
- final project = HelperUtil.createRootProject()
+ final project = TestUtil.createRootProject()
final extension = new AnnouncePluginExtension(project)
final ProcessOperations processOperations = Mock()
final IconProvider iconProvider = Mock()
diff --git a/subprojects/antlr/antlr.gradle b/subprojects/antlr/antlr.gradle
index 5c614f1..9a1eca4 100644
--- a/subprojects/antlr/antlr.gradle
+++ b/subprojects/antlr/antlr.gradle
@@ -14,7 +14,7 @@
* limitations under the License.
*/
dependencies {
- groovy libraries.groovy
+ compile libraries.groovy
compile project(':core')
compile project(':plugins')
diff --git a/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/AntlrPlugin.java b/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/AntlrPlugin.java
index ee2a663..56dfe62 100644
--- a/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/AntlrPlugin.java
+++ b/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/AntlrPlugin.java
@@ -36,8 +36,6 @@ import static org.gradle.api.plugins.JavaPlugin.COMPILE_CONFIGURATION_NAME;
/**
* A plugin for adding Antlr support to {@link JavaPlugin java projects}.
- *
- * @author Steve Ebersole
*/
public class AntlrPlugin implements Plugin<ProjectInternal> {
public static final String ANTLR_CONFIGURATION_NAME = "antlr";
@@ -53,7 +51,7 @@ public class AntlrPlugin implements Plugin<ProjectInternal> {
// set up a configuration named 'antlr' for the user to specify the antlr libs to use in case
// they want a specific version etc.
- Configuration antlrConfiguration = project.getConfigurations().add(ANTLR_CONFIGURATION_NAME).setVisible(false)
+ Configuration antlrConfiguration = project.getConfigurations().create(ANTLR_CONFIGURATION_NAME).setVisible(false)
.setTransitive(false).setDescription("The Antlr libraries to be used for this project.");
project.getConfigurations().getByName(COMPILE_CONFIGURATION_NAME).extendsFrom(antlrConfiguration);
@@ -73,7 +71,7 @@ public class AntlrPlugin implements Plugin<ProjectInternal> {
// 2) create an AntlrTask for this sourceSet following the gradle
// naming conventions via call to sourceSet.getTaskName()
final String taskName = sourceSet.getTaskName("generate", "GrammarSource");
- AntlrTask antlrTask = project.getTasks().add(taskName, AntlrTask.class);
+ AntlrTask antlrTask = project.getTasks().create(taskName, AntlrTask.class);
antlrTask.setDescription(String.format("Processes the %s Antlr grammars.",
sourceSet.getName()));
diff --git a/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/AntlrSourceVirtualDirectory.java b/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/AntlrSourceVirtualDirectory.java
index 2907b23..cd71f72 100644
--- a/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/AntlrSourceVirtualDirectory.java
+++ b/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/AntlrSourceVirtualDirectory.java
@@ -24,8 +24,6 @@ import org.gradle.api.file.SourceDirectorySet;
* injecting a virtual directory named 'antlr' into the project's various {@link org.gradle.api.tasks.SourceSet source
* sets}. Its implementation gets pushed onto the {@link org.gradle.api.internal.DynamicObjectAware} portion of the
* source set under the name 'antlr'.
- *
- * @author Steve Ebersole
*/
public interface AntlrSourceVirtualDirectory {
public static final String NAME = "antlr";
diff --git a/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/AntlrTask.java b/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/AntlrTask.java
index 452f97a..44a2696 100644
--- a/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/AntlrTask.java
+++ b/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/AntlrTask.java
@@ -16,24 +16,24 @@
package org.gradle.api.plugins.antlr;
-import java.io.File;
-import java.util.List;
-
import org.apache.tools.ant.taskdefs.optional.ANTLR;
import org.apache.tools.ant.types.Path;
import org.gradle.api.file.FileCollection;
import org.gradle.api.plugins.antlr.internal.GenerationPlan;
+import org.gradle.api.plugins.antlr.internal.GenerationPlanBuilder;
+import org.gradle.api.plugins.antlr.internal.MetadataExtracter;
+import org.gradle.api.plugins.antlr.internal.XRef;
import org.gradle.api.tasks.InputFiles;
import org.gradle.api.tasks.OutputDirectory;
import org.gradle.api.tasks.SourceTask;
import org.gradle.api.tasks.TaskAction;
-import org.gradle.api.plugins.antlr.internal.MetadataExtracter;
-import org.gradle.api.plugins.antlr.internal.XRef;
-import org.gradle.api.plugins.antlr.internal.GenerationPlanBuilder;
import org.gradle.util.GFileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.io.File;
+import java.util.List;
+
/**
* <p>Generates parsers from Antlr grammars.</p>
*
@@ -42,8 +42,6 @@ import org.slf4j.LoggerFactory;
* classpath it uses to perform generation execution. This <b>should</b> really only require the antlr jar. In {@link
* AntlrPlugin} usage, this would happen simply by adding your antlr jar into the 'antlr' dependency configuration
* created and exposed by the {@link AntlrPlugin} itself.</p>
- *
- * @author Steve Ebersole
*/
public class AntlrTask extends SourceTask {
private static final Logger LOGGER = LoggerFactory.getLogger(AntlrTask.class);
diff --git a/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/internal/AntlrSourceVirtualDirectoryImpl.java b/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/internal/AntlrSourceVirtualDirectoryImpl.java
index 27dced5..006320d 100644
--- a/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/internal/AntlrSourceVirtualDirectoryImpl.java
+++ b/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/internal/AntlrSourceVirtualDirectoryImpl.java
@@ -24,8 +24,6 @@ import org.gradle.util.ConfigureUtil;
/**
* The implementation of the {@link org.gradle.api.plugins.antlr.AntlrSourceVirtualDirectory} contract.
- *
- * @author Steve Ebersole
*/
public class AntlrSourceVirtualDirectoryImpl implements AntlrSourceVirtualDirectory {
private final SourceDirectorySet antlr;
diff --git a/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/internal/GenerationPlan.java b/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/internal/GenerationPlan.java
index a6b0db7..97d1247 100644
--- a/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/internal/GenerationPlan.java
+++ b/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/internal/GenerationPlan.java
@@ -19,8 +19,6 @@ import java.io.File;
/**
* Models information relevant to generation of a particular Antlr grammar file.
- *
- * @author Steve Ebersole
*/
public class GenerationPlan {
private final File source;
diff --git a/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/internal/GenerationPlanBuilder.java b/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/internal/GenerationPlanBuilder.java
index 0cad3f1..2d82713 100644
--- a/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/internal/GenerationPlanBuilder.java
+++ b/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/internal/GenerationPlanBuilder.java
@@ -15,21 +15,19 @@
*/
package org.gradle.api.plugins.antlr.internal;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import java.io.File;
+import java.util.ArrayList;
+import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
-import java.util.Iterator;
-import java.util.ArrayList;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
/**
* Builder for the properly order list of {@link GenerationPlan generation plans}.
*
* <p>IMPL NOTE : Uses recursive calls to achieve ordering.</p>
- *
- * @author Steve Ebersole
*/
public class GenerationPlanBuilder {
private static final Logger LOGGER = LoggerFactory.getLogger(GenerationPlanBuilder.class);
diff --git a/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/internal/GrammarDelegate.java b/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/internal/GrammarDelegate.java
index 255fd29..497eb88 100644
--- a/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/internal/GrammarDelegate.java
+++ b/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/internal/GrammarDelegate.java
@@ -15,19 +15,17 @@
*/
package org.gradle.api.plugins.antlr.internal;
+import antlr.collections.impl.IndexedVector;
+import antlr.preprocessor.GrammarFile;
+
import java.lang.reflect.Method;
-import java.util.Enumeration;
import java.util.ArrayList;
+import java.util.Enumeration;
import java.util.List;
-import antlr.collections.impl.IndexedVector;
-import antlr.preprocessor.GrammarFile;
-
/**
* Antlr defines its {@link antlr.preprocessor.Grammar} class as package-protected for some unfortunate reason. So this class acts as a delegate to the Antlr {@link antlr.preprocessor.Grammar} class,
* hiding all the ugly necessary reflection code.
- *
- * @author Steve Ebersole
*/
public class GrammarDelegate {
public static List<GrammarDelegate> extractGrammarDelegates(GrammarFile antlrGrammarFile) {
diff --git a/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/internal/GrammarFileMetadata.java b/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/internal/GrammarFileMetadata.java
index 0ef041f..7d3daa5 100644
--- a/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/internal/GrammarFileMetadata.java
+++ b/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/internal/GrammarFileMetadata.java
@@ -15,15 +15,13 @@
*/
package org.gradle.api.plugins.antlr.internal;
-import java.util.List;
-import java.util.ArrayList;
import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
/**
* Models information about an Antlr grammar file, including the inidividual {@link #getGrammars grammars} (lexers,
* parsers, etc) contained within it.
- *
- * @author Steve Ebersole
*/
public class GrammarFileMetadata {
private final File filePath;
diff --git a/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/internal/GrammarMetadata.java b/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/internal/GrammarMetadata.java
index 796370f..371715e 100644
--- a/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/internal/GrammarMetadata.java
+++ b/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/internal/GrammarMetadata.java
@@ -15,15 +15,13 @@
*/
package org.gradle.api.plugins.antlr.internal;
-import java.io.File;
-
-import antlr.TreeParser;
import antlr.Parser;
+import antlr.TreeParser;
+
+import java.io.File;
/**
* Models a grammar defined within an Antlr grammar file.
- *
- * @author Steve Ebersole
*/
public class GrammarMetadata {
private final GrammarFileMetadata grammarFileMetadata;
diff --git a/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/internal/MetadataExtracter.java b/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/internal/MetadataExtracter.java
index 35e480f..fee4fd8 100644
--- a/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/internal/MetadataExtracter.java
+++ b/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/internal/MetadataExtracter.java
@@ -15,20 +15,14 @@
*/
package org.gradle.api.plugins.antlr.internal;
-import java.io.File;
-import java.io.BufferedReader;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.FileNotFoundException;
-
import org.gradle.api.UncheckedIOException;
import org.gradle.api.file.FileTree;
+import java.io.*;
+
/**
* Preprocess an Antlr grammar file so that dependencies between grammars can be properly determined such that they can
* be processed for generation in proper order later.
- *
- * @author Steve Ebersole
*/
public class MetadataExtracter {
diff --git a/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/internal/XRef.java b/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/internal/XRef.java
index 2b73ded..976fee9 100644
--- a/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/internal/XRef.java
+++ b/subprojects/antlr/src/main/groovy/org/gradle/api/plugins/antlr/internal/XRef.java
@@ -15,17 +15,15 @@
*/
package org.gradle.api.plugins.antlr.internal;
-import java.util.LinkedHashMap;
+import antlr.preprocessor.Hierarchy;
+
import java.util.HashMap;
import java.util.Iterator;
-
-import antlr.preprocessor.Hierarchy;
+import java.util.LinkedHashMap;
/**
* Models cross-reference (x-ref) info about {@link GrammarFileMetadata grammar files} such as {@link #filesByPath},
* {@link #filesByExportVocab} and {@link #filesByClassName}.
- *
- * @author Steve Ebersole
*/
public class XRef {
private final Hierarchy antlrHierarchy;
diff --git a/subprojects/antlr/src/test/groovy/org/gradle/api/plugins/antlr/AntlrPluginTest.groovy b/subprojects/antlr/src/test/groovy/org/gradle/api/plugins/antlr/AntlrPluginTest.groovy
index b94619d..42fccb2 100644
--- a/subprojects/antlr/src/test/groovy/org/gradle/api/plugins/antlr/AntlrPluginTest.groovy
+++ b/subprojects/antlr/src/test/groovy/org/gradle/api/plugins/antlr/AntlrPluginTest.groovy
@@ -18,10 +18,10 @@ package org.gradle.api.plugins.antlr
import spock.lang.Specification
import org.gradle.api.Project
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
class AntlrPluginTest extends Specification {
- private final Project project = HelperUtil.createRootProject()
+ private final Project project = TestUtil.createRootProject()
def addsAntlrPropertiesToEachSourceSet() {
when:
@@ -35,7 +35,7 @@ class AntlrPluginTest extends Specification {
test.antlr.srcDirs == [project.file('src/test/antlr')] as Set
when:
- project.sourceSets.add('custom')
+ project.sourceSets.create('custom')
then:
def custom = project.sourceSets.custom
@@ -56,7 +56,7 @@ class AntlrPluginTest extends Specification {
project.tasks.compileTestJava.taskDependencies.getDependencies(null).contains(test)
when:
- project.sourceSets.add('custom')
+ project.sourceSets.create('custom')
then:
def custom = project.tasks.generateCustomGrammarSource
diff --git a/subprojects/base-services-groovy/base-services-groovy.gradle b/subprojects/base-services-groovy/base-services-groovy.gradle
index 90d6a16..c50fe5d 100644
--- a/subprojects/base-services-groovy/base-services-groovy.gradle
+++ b/subprojects/base-services-groovy/base-services-groovy.gradle
@@ -15,7 +15,7 @@
*/
dependencies {
- groovy libraries.groovy
+ compile libraries.groovy
compile project(":baseServices")
}
diff --git a/subprojects/base-services-groovy/src/main/groovy/org/gradle/api/specs/AndSpec.java b/subprojects/base-services-groovy/src/main/groovy/org/gradle/api/specs/AndSpec.java
index 7da1f73..90cce09 100644
--- a/subprojects/base-services-groovy/src/main/groovy/org/gradle/api/specs/AndSpec.java
+++ b/subprojects/base-services-groovy/src/main/groovy/org/gradle/api/specs/AndSpec.java
@@ -26,7 +26,6 @@ import java.util.List;
* A {@link org.gradle.api.specs.CompositeSpec} which requires all its specs to be true in order to evaluate to true.
* Uses lazy evaluation.
*
- * @author Hans Dockter
* @param <T> The target type for this Spec
*/
public class AndSpec<T> extends CompositeSpec<T> {
diff --git a/subprojects/base-services-groovy/src/test/groovy/org/gradle/api/specs/AndSpecTest.java b/subprojects/base-services-groovy/src/test/groovy/org/gradle/api/specs/AndSpecTest.java
index a26dda9..37f447b 100644
--- a/subprojects/base-services-groovy/src/test/groovy/org/gradle/api/specs/AndSpecTest.java
+++ b/subprojects/base-services-groovy/src/test/groovy/org/gradle/api/specs/AndSpecTest.java
@@ -15,7 +15,7 @@
*/
package org.gradle.api.specs;
-import org.gradle.util.HelperUtil;
+import org.gradle.util.TestUtil;
import org.junit.Test;
import static org.junit.Assert.assertFalse;
@@ -51,7 +51,7 @@ public class AndSpecTest extends AbstractCompositeSpecTest {
@Test
public void canAddClosureAsASpec() {
AndSpec<Object> spec = new AndSpec<Object>(createAtomicElements(true));
- spec = spec.and(HelperUtil.toClosure("{ false }"));
+ spec = spec.and(TestUtil.toClosure("{ false }"));
assertFalse(spec.isSatisfiedBy(new Object()));
}
}
diff --git a/subprojects/base-services/base-services.gradle b/subprojects/base-services/base-services.gradle
index f825ab8..2a2dcff 100644
--- a/subprojects/base-services/base-services.gradle
+++ b/subprojects/base-services/base-services.gradle
@@ -5,9 +5,9 @@
* application (eg as part of the tooling API).
*/
dependencies {
- groovy libraries.groovy
-
publishCompile libraries.slf4j_api
+ compile libraries.guava
+ testCompile libraries.groovy
}
useTestFixtures()
diff --git a/subprojects/base-services/src/main/java/org/gradle/api/GradleException.java b/subprojects/base-services/src/main/java/org/gradle/api/GradleException.java
index 788305f..430a702 100644
--- a/subprojects/base-services/src/main/java/org/gradle/api/GradleException.java
+++ b/subprojects/base-services/src/main/java/org/gradle/api/GradleException.java
@@ -18,8 +18,6 @@ package org.gradle.api;
/**
* <p><code>GradleException</code> is the base class of all exceptions thrown by Gradle.</p>
- *
- * @author Hans Dockter
*/
public class GradleException extends RuntimeException {
public GradleException() {
diff --git a/subprojects/base-services/src/main/java/org/gradle/api/JavaVersion.java b/subprojects/base-services/src/main/java/org/gradle/api/JavaVersion.java
index b1b430f..9804ed5 100644
--- a/subprojects/base-services/src/main/java/org/gradle/api/JavaVersion.java
+++ b/subprojects/base-services/src/main/java/org/gradle/api/JavaVersion.java
@@ -114,4 +114,8 @@ public enum JavaVersion {
private String getName() {
return name().substring("VERSION_".length()).replace('_', '.');
}
+
+ public String getMajorVersion() {
+ return name().substring(10);
+ }
}
diff --git a/subprojects/base-services/src/main/java/org/gradle/api/internal/Factory.java b/subprojects/base-services/src/main/java/org/gradle/api/internal/Factory.java
index 0e4242e..7464292 100644
--- a/subprojects/base-services/src/main/java/org/gradle/api/internal/Factory.java
+++ b/subprojects/base-services/src/main/java/org/gradle/api/internal/Factory.java
@@ -16,8 +16,10 @@
package org.gradle.api.internal;
/**
+ * DO NOT REMOVE.
+ *
* @deprecated This is here because tasks implemented in Groovy that are compiled against older versions of Gradle have this type baked into their byte-code, and cannot be loaded if it's not found.
*/
@Deprecated
-public interface Factory<T> extends org.gradle.internal.Factory<T> {
+public interface Factory<T> {
}
diff --git a/subprojects/base-services/src/main/java/org/gradle/api/internal/Transformers.java b/subprojects/base-services/src/main/java/org/gradle/api/internal/Transformers.java
index c066c8e..cc94eae 100644
--- a/subprojects/base-services/src/main/java/org/gradle/api/internal/Transformers.java
+++ b/subprojects/base-services/src/main/java/org/gradle/api/internal/Transformers.java
@@ -16,9 +16,15 @@
package org.gradle.api.internal;
+import org.gradle.api.Action;
import org.gradle.api.Named;
import org.gradle.api.Namer;
import org.gradle.api.Transformer;
+import org.gradle.internal.UncheckedException;
+
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
/**
* Utility transformers.
@@ -92,4 +98,46 @@ public abstract class Transformers {
}
}
+ /**
+ * A getClass() transformer.
+ *
+ * @param <T> The type of the object
+ * @return A getClass() transformer.
+ */
+ public static <T> Transformer<Class<T>, T> type() {
+ return new Transformer<Class<T>, T>() {
+ public Class<T> transform(T original) {
+ @SuppressWarnings("unchecked")
+ Class<T> aClass = (Class<T>) original.getClass();
+ return aClass;
+ }
+ };
+ }
+
+ /**
+ * Converts an {@link Action} to a {@link Transformer} that runs the action against the input value and returns {@code null}.
+ */
+ public static <R, I> Transformer<R, I> toTransformer(final Action<? super I> action) {
+ return new Transformer<R, I>() {
+ public R transform(I original) {
+ action.execute(original);
+ return null;
+ }
+ };
+ }
+
+ /**
+ * Converts a URL to a URI
+ */
+ public static Transformer<URL, URI> toURL() {
+ return new Transformer<URL, URI>() {
+ public URL transform(URI original) {
+ try {
+ return original.toURL();
+ } catch (MalformedURLException e) {
+ throw UncheckedException.throwAsUncheckedException(e);
+ }
+ }
+ };
+ }
}
diff --git a/subprojects/base-services/src/main/java/org/gradle/api/internal/project/ServiceRegistry.java b/subprojects/base-services/src/main/java/org/gradle/api/internal/project/ServiceRegistry.java
index 92825aa..2f45094 100644
--- a/subprojects/base-services/src/main/java/org/gradle/api/internal/project/ServiceRegistry.java
+++ b/subprojects/base-services/src/main/java/org/gradle/api/internal/project/ServiceRegistry.java
@@ -16,8 +16,10 @@
package org.gradle.api.internal.project;
/**
+ * DO NOT REMOVE.
+ *
* @deprecated This is here because tasks implemented in Groovy that are compiled against older versions of Gradle have this type baked into their byte-code, and cannot be loaded if it's not found.
*/
@Deprecated
-public interface ServiceRegistry extends org.gradle.internal.service.ServiceRegistry {
+public interface ServiceRegistry {
}
diff --git a/subprojects/base-services/src/main/java/org/gradle/api/specs/CompositeSpec.java b/subprojects/base-services/src/main/java/org/gradle/api/specs/CompositeSpec.java
index f3ce645..b605164 100644
--- a/subprojects/base-services/src/main/java/org/gradle/api/specs/CompositeSpec.java
+++ b/subprojects/base-services/src/main/java/org/gradle/api/specs/CompositeSpec.java
@@ -23,7 +23,6 @@ import java.util.List;
/**
* A {@link org.gradle.api.specs.Spec} which aggregates a sequence of other {@code Spec} instances.
*
- * @author Hans Dockter
* @param <T> The target type for this Spec
*/
abstract public class CompositeSpec<T> implements Spec<T> {
diff --git a/subprojects/base-services/src/main/java/org/gradle/api/specs/NotSpec.java b/subprojects/base-services/src/main/java/org/gradle/api/specs/NotSpec.java
index 6938d8b..be6db06 100644
--- a/subprojects/base-services/src/main/java/org/gradle/api/specs/NotSpec.java
+++ b/subprojects/base-services/src/main/java/org/gradle/api/specs/NotSpec.java
@@ -18,7 +18,6 @@ package org.gradle.api.specs;
/**
* A {@link org.gradle.api.specs.Spec} implementation which negates another {@code Spec}.
*
- * @author Hans Dockter
* @param <T> The target type for this Spec
*/
public class NotSpec<T> implements Spec<T> {
diff --git a/subprojects/base-services/src/main/java/org/gradle/api/specs/OrSpec.java b/subprojects/base-services/src/main/java/org/gradle/api/specs/OrSpec.java
index 9f63a61..3c84c8c 100644
--- a/subprojects/base-services/src/main/java/org/gradle/api/specs/OrSpec.java
+++ b/subprojects/base-services/src/main/java/org/gradle/api/specs/OrSpec.java
@@ -21,7 +21,6 @@ import java.util.List;
* A {@link CompositeSpec} which requires any one of its specs to be true in order to evaluate to
* true. Uses lazy evaluation.
*
- * @author Hans Dockter
* @param <T> The target type for this Spec
*/
public class OrSpec<T> extends CompositeSpec<T> {
diff --git a/subprojects/base-services/src/main/java/org/gradle/api/specs/Spec.java b/subprojects/base-services/src/main/java/org/gradle/api/specs/Spec.java
index a6522b4..ebb6ae7 100644
--- a/subprojects/base-services/src/main/java/org/gradle/api/specs/Spec.java
+++ b/subprojects/base-services/src/main/java/org/gradle/api/specs/Spec.java
@@ -18,7 +18,6 @@ package org.gradle.api.specs;
/**
* Represents some predicate against objects of type T.
*
- * @author Hans Dockter
* @param <T> The target type for this Spec
*/
public interface Spec<T> {
diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/LazyIterable.java b/subprojects/base-services/src/main/java/org/gradle/internal/LazyIterable.java
deleted file mode 100644
index 74ea26d..0000000
--- a/subprojects/base-services/src/main/java/org/gradle/internal/LazyIterable.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.internal;
-
-import java.util.Iterator;
-
-public class LazyIterable<T> implements Iterable<T> {
-
- private final Factory<Iterable<T>> factory;
-
- public LazyIterable(Factory<Iterable<T>> factory) {
- this.factory = factory;
- }
-
- public Iterator<T> iterator() {
- return factory.create().iterator();
- }
-
-}
diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/classloader/CachingClassLoader.java b/subprojects/base-services/src/main/java/org/gradle/internal/classloader/CachingClassLoader.java
new file mode 100644
index 0000000..7bad876
--- /dev/null
+++ b/subprojects/base-services/src/main/java/org/gradle/internal/classloader/CachingClassLoader.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.classloader;
+
+import com.google.common.collect.MapMaker;
+
+import java.util.concurrent.ConcurrentMap;
+
+public class CachingClassLoader extends ClassLoader implements ClassLoaderHierarchy {
+ private static final Object MISSING_CLASS = new Object();
+ private final ConcurrentMap<String, Object> loadedClasses = new MapMaker().weakValues().makeMap();
+
+ public CachingClassLoader(ClassLoader parent) {
+ super(parent);
+ }
+
+ @Override
+ protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
+ Object cachedValue = loadedClasses.get(name);
+ if (cachedValue instanceof Class) {
+ return (Class<?>) cachedValue;
+ } else if (cachedValue == MISSING_CLASS) {
+ throw new ClassNotFoundException(name);
+ }
+ Class<?> result;
+ try {
+ result = super.loadClass(name, resolve);
+ } catch (ClassNotFoundException e) {
+ loadedClasses.putIfAbsent(name, MISSING_CLASS);
+ throw e;
+ }
+ loadedClasses.putIfAbsent(name, result);
+ return result;
+ }
+
+ public void visit(ClassLoaderVisitor visitor) {
+ visitor.visitSpec(new Spec());
+ visitor.visitParent(getParent());
+ }
+
+ public static class Spec extends ClassLoaderSpec {
+ @Override
+ public boolean equals(Object obj) {
+ return obj != null && obj.getClass().equals(Spec.class);
+ }
+
+ @Override
+ public int hashCode() {
+ return getClass().getName().hashCode();
+ }
+ }
+}
diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/classloader/ClassLoaderFactory.java b/subprojects/base-services/src/main/java/org/gradle/internal/classloader/ClassLoaderFactory.java
new file mode 100644
index 0000000..90d37a8
--- /dev/null
+++ b/subprojects/base-services/src/main/java/org/gradle/internal/classloader/ClassLoaderFactory.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.classloader;
+
+import org.gradle.internal.classpath.ClassPath;
+
+import java.net.URI;
+import java.util.List;
+
+public interface ClassLoaderFactory {
+ /**
+ * Creates a ClassLoader implementation which has only the classes from the specified URIs and the Java API visible.
+ */
+ ClassLoader createIsolatedClassLoader(ClassPath classPath);
+
+ /**
+ * Creates a ClassLoader implementation which has only the classes from the specified URIs and the Java API visible.
+ */
+ ClassLoader createIsolatedClassLoader(Iterable<URI> uris);
+
+ /**
+ * Creates a ClassLoader implementation which has, by default, only the classes from the Java API visible, but which can allow access
+ * to selected classes from the given parent ClassLoader.
+ *
+ * @param parent the parent ClassLoader
+ * @return The ClassLoader
+ */
+ FilteringClassLoader createFilteringClassLoader(ClassLoader parent);
+
+ /**
+ * Creates a ClassLoader from its spec.
+ */
+ ClassLoader createClassLoader(ClassLoaderSpec spec, List<? extends ClassLoader> parents);
+}
diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/classloader/ClassLoaderHierarchy.java b/subprojects/base-services/src/main/java/org/gradle/internal/classloader/ClassLoaderHierarchy.java
new file mode 100644
index 0000000..241c0ac
--- /dev/null
+++ b/subprojects/base-services/src/main/java/org/gradle/internal/classloader/ClassLoaderHierarchy.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.classloader;
+
+public interface ClassLoaderHierarchy {
+ void visit(ClassLoaderVisitor visitor);
+}
diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/classloader/ClassLoaderSpec.java b/subprojects/base-services/src/main/java/org/gradle/internal/classloader/ClassLoaderSpec.java
new file mode 100644
index 0000000..8b96204
--- /dev/null
+++ b/subprojects/base-services/src/main/java/org/gradle/internal/classloader/ClassLoaderSpec.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.classloader;
+
+import java.io.Serializable;
+
+/**
+ * An immutable description of a ClassLoader hierarchy that can be used to recreate the hierarchy in a different process.
+ *
+ * Subclasses should implement equals() and hashCode(), so that the spec can be used as a hashmap key.
+ */
+public abstract class ClassLoaderSpec implements Serializable {
+ public static final ClassLoaderSpec SYSTEM_CLASS_LOADER = new SystemClassLoaderSpec();
+
+ private static class SystemClassLoaderSpec extends ClassLoaderSpec {
+ @Override
+ public boolean equals(Object obj) {
+ return obj != null && obj.getClass().equals(getClass());
+ }
+
+ @Override
+ public String toString() {
+ return "system";
+ }
+
+ @Override
+ public int hashCode() {
+ return 121;
+ }
+ }
+}
diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/classloader/ClassLoaderVisitor.java b/subprojects/base-services/src/main/java/org/gradle/internal/classloader/ClassLoaderVisitor.java
new file mode 100644
index 0000000..92cc137
--- /dev/null
+++ b/subprojects/base-services/src/main/java/org/gradle/internal/classloader/ClassLoaderVisitor.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.classloader;
+
+import java.net.URL;
+import java.net.URLClassLoader;
+
+public class ClassLoaderVisitor {
+ private final ClassLoader stopAt = ClassLoader.getSystemClassLoader() == null ? null : ClassLoader.getSystemClassLoader().getParent();
+
+ public void visit(ClassLoader classLoader) {
+ if (classLoader == stopAt) {
+ visitSpec(ClassLoaderSpec.SYSTEM_CLASS_LOADER);
+ return;
+ }
+
+ if (classLoader instanceof ClassLoaderHierarchy) {
+ ((ClassLoaderHierarchy) classLoader).visit(this);
+ } else {
+ if (classLoader instanceof URLClassLoader) {
+ visitClassPath(((URLClassLoader) classLoader).getURLs());
+ }
+ if (classLoader.getParent() != null) {
+ visitParent(classLoader.getParent());
+ }
+ }
+ }
+
+ public void visitSpec(ClassLoaderSpec spec) {
+ }
+
+ public void visitClassPath(URL[] classPath) {
+ }
+
+ public void visitParent(ClassLoader classLoader) {
+ visit(classLoader);
+ }
+}
diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/classloader/ClasspathUtil.java b/subprojects/base-services/src/main/java/org/gradle/internal/classloader/ClasspathUtil.java
new file mode 100644
index 0000000..f1e2ac6
--- /dev/null
+++ b/subprojects/base-services/src/main/java/org/gradle/internal/classloader/ClasspathUtil.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.classloader;
+
+import org.gradle.api.GradleException;
+import org.gradle.internal.UncheckedException;
+
+import java.io.File;
+import java.lang.reflect.Method;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class ClasspathUtil {
+ public static void addUrl(URLClassLoader classLoader, Iterable<URL> classpathElements) {
+ try {
+ Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
+ method.setAccessible(true);
+ for (URL classpathElement : classpathElements) {
+ method.invoke(classLoader, classpathElement);
+ }
+ } catch (Throwable t) {
+ throw new RuntimeException("Error, could not add URL to classloader", t);
+ }
+ }
+
+ public static List<URL> getClasspath(ClassLoader classLoader) {
+ final List<URL> implementationClassPath = new ArrayList<URL>();
+ new ClassLoaderVisitor() {
+ @Override
+ public void visitClassPath(URL[] classPath) {
+ implementationClassPath.addAll(Arrays.asList(classPath));
+ }
+ }.visit(classLoader);
+ return implementationClassPath;
+ }
+
+ public static File getClasspathForClass(Class<?> targetClass) {
+ URI location;
+ try {
+ location = targetClass.getProtectionDomain().getCodeSource().getLocation().toURI();
+ } catch (URISyntaxException e) {
+ throw UncheckedException.throwAsUncheckedException(e);
+ }
+ if (!location.getScheme().equals("file")) {
+ throw new GradleException(String.format("Cannot determine classpath for %s from codebase '%s'.", targetClass.getName(), location));
+ }
+ return new File(location.getPath());
+ }
+
+ public static File getClasspathForResource(ClassLoader classLoader, String name) {
+ if (classLoader == null) {
+ return getClasspathForResource(ClassLoader.getSystemResource(name), name);
+ } else {
+ return getClasspathForResource(classLoader.getResource(name), name);
+ }
+ }
+
+ public static File getClasspathForResource(URL resource, String name) {
+ URI location;
+ try {
+ location = resource.toURI();
+ String path = location.getPath();
+ if (location.getScheme().equals("file")) {
+ assert path.endsWith("/" + name);
+ return new File(path.substring(0, path.length() - (name.length() + 1)));
+ } else if (location.getScheme().equals("jar")) {
+ String schemeSpecificPart = location.getRawSchemeSpecificPart();
+ int pos = schemeSpecificPart.indexOf("!");
+ if (pos > 0) {
+ assert schemeSpecificPart.substring(pos + 1).equals("/" + name);
+ URI jarFile = new URI(schemeSpecificPart.substring(0, pos));
+ if (jarFile.getScheme().equals("file")) {
+ return new File(jarFile.getPath());
+ }
+ }
+ }
+ } catch (URISyntaxException e) {
+ throw UncheckedException.throwAsUncheckedException(e);
+ }
+ throw new GradleException(String.format("Cannot determine classpath for resource '%s' from location '%s'.", name, location));
+ }
+}
diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/classloader/DefaultClassLoaderFactory.java b/subprojects/base-services/src/main/java/org/gradle/internal/classloader/DefaultClassLoaderFactory.java
new file mode 100644
index 0000000..68dc2d5
--- /dev/null
+++ b/subprojects/base-services/src/main/java/org/gradle/internal/classloader/DefaultClassLoaderFactory.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.classloader;
+
+import org.gradle.api.internal.Transformers;
+import org.gradle.internal.UncheckedException;
+import org.gradle.internal.classpath.ClassPath;
+import org.gradle.internal.service.ServiceLocator;
+import org.gradle.util.CollectionUtils;
+
+import javax.xml.datatype.DatatypeFactory;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.SAXParserFactory;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Collection;
+import java.util.List;
+
+public class DefaultClassLoaderFactory implements ClassLoaderFactory {
+ public ClassLoader createIsolatedClassLoader(Iterable<URI> uris) {
+ return doCreateIsolatedClassLoader(CollectionUtils.collect(uris, Transformers.toURL()));
+ }
+
+ public ClassLoader createIsolatedClassLoader(ClassPath classPath) {
+ return doCreateIsolatedClassLoader(classPath.getAsURLs());
+ }
+
+ private ClassLoader doCreateIsolatedClassLoader(Collection<URL> classpath) {
+ // This piece of ugliness copies the JAXP (ie XML API) provider, if any, from the system ClassLoader. Here's why:
+ //
+ // 1. When looking for a provider, JAXP looks for a service resource in the context ClassLoader, which is our isolated ClassLoader. If our classpath above does not contain a
+ // provider, this returns null. If it does contain a provider, JAXP extracts the classname from the service resource.
+ // 2. If not found, JAXP looks for a service resource in the system ClassLoader. This happens to include all the application classes specified on the classpath. If the application
+ // classpath does not contain a provider, this returns null. If it does contain a provider, JAXP extracts the implementation classname from the service resource.
+ // 3. If not found, JAXP uses a default classname
+ // 4. JAXP attempts to load the provider using the context ClassLoader. which is our isolated ClassLoader. This is fine if the classname came from step 1 or 3. It blows up if the
+ // classname came from step 2.
+ //
+ // So, as a workaround, locate and include the JAXP provider jar in the classpath for our isolated ClassLoader.
+ //
+ // Note that in practise, this is only triggered when running in our tests
+
+ if (needJaxpImpl()) {
+ try {
+ classpath.add(ClasspathUtil.getClasspathForResource(ClassLoader.getSystemClassLoader(), "META-INF/services/javax.xml.parsers.SAXParserFactory").toURI().toURL());
+ } catch (MalformedURLException e) {
+ throw UncheckedException.throwAsUncheckedException(e);
+ }
+ }
+
+ return new URLClassLoader(classpath.toArray(new URL[classpath.size()]), ClassLoader.getSystemClassLoader().getParent());
+ }
+
+ public FilteringClassLoader createFilteringClassLoader(ClassLoader parent) {
+ // See the comment for {@link #createIsolatedClassLoader} above
+ FilteringClassLoader classLoader = new FilteringClassLoader(parent);
+ if (needJaxpImpl()) {
+ ServiceLocator locator = new ServiceLocator(ClassLoader.getSystemClassLoader());
+ makeServiceVisible(locator, classLoader, SAXParserFactory.class);
+ makeServiceVisible(locator, classLoader, DocumentBuilderFactory.class);
+ makeServiceVisible(locator, classLoader, DatatypeFactory.class);
+ }
+ return classLoader;
+ }
+
+ public ClassLoader createClassLoader(ClassLoaderSpec spec, List<? extends ClassLoader> parents) {
+ if (spec instanceof MultiParentClassLoader.Spec) {
+ return new MultiParentClassLoader(parents);
+ }
+ if (parents.size() != 1) {
+ throw new IllegalArgumentException("Expected a single parent.");
+ }
+ ClassLoader parent = parents.get(0);
+ if (spec instanceof MutableURLClassLoader.Spec) {
+ MutableURLClassLoader.Spec clSpec = (MutableURLClassLoader.Spec) spec;
+ return new MutableURLClassLoader(parent, clSpec);
+ }
+ if (spec instanceof CachingClassLoader.Spec) {
+ return new CachingClassLoader(parent);
+ }
+ if (spec instanceof FilteringClassLoader.Spec) {
+ FilteringClassLoader.Spec clSpec = (FilteringClassLoader.Spec) spec;
+ return new FilteringClassLoader(parent, clSpec);
+ }
+ throw new IllegalArgumentException(String.format("Don't know how to create a ClassLoader from spec %s", spec));
+ }
+
+ private void makeServiceVisible(ServiceLocator locator, FilteringClassLoader classLoader, Class<?> serviceType) {
+ classLoader.allowClass(locator.getFactory(serviceType).getImplementationClass());
+ classLoader.allowResource("META-INF/services/" + serviceType.getName());
+ }
+
+ private boolean needJaxpImpl() {
+ return ClassLoader.getSystemResource("META-INF/services/javax.xml.parsers.SAXParserFactory") != null;
+ }
+}
diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/classloader/FilteringClassLoader.java b/subprojects/base-services/src/main/java/org/gradle/internal/classloader/FilteringClassLoader.java
new file mode 100644
index 0000000..6ffa40a
--- /dev/null
+++ b/subprojects/base-services/src/main/java/org/gradle/internal/classloader/FilteringClassLoader.java
@@ -0,0 +1,275 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.classloader;
+
+import org.gradle.internal.reflect.JavaReflectionUtil;
+import org.gradle.util.JavaMethod;
+
+import java.io.IOException;
+import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.*;
+
+/**
+ * A ClassLoader which hides all non-system classes, packages and resources. Allows certain non-system packages and classes to be declared as visible. By default, only the Java system classes,
+ * packages and resources are visible.
+ */
+public class FilteringClassLoader extends ClassLoader implements ClassLoaderHierarchy {
+ private static final Set<ClassLoader> SYSTEM_CLASS_LOADERS = new HashSet<ClassLoader>();
+ private static final ClassLoader EXT_CLASS_LOADER;
+ private static final Set<String> SYSTEM_PACKAGES = new HashSet<String>();
+ private final Set<String> packageNames = new HashSet<String>();
+ private final Set<String> packagePrefixes = new HashSet<String>();
+ private final Set<String> resourcePrefixes = new HashSet<String>();
+ private final Set<String> resourceNames = new HashSet<String>();
+ private final Set<String> classNames = new HashSet<String>();
+ private final Set<String> disallowedClassNames = new HashSet<String>();
+
+ static {
+ EXT_CLASS_LOADER = ClassLoader.getSystemClassLoader().getParent();
+ for (ClassLoader cl = EXT_CLASS_LOADER; cl != null; cl = cl.getParent()) {
+ SYSTEM_CLASS_LOADERS.add(cl);
+ }
+ JavaMethod<ClassLoader, Package[]> method = JavaReflectionUtil.method(ClassLoader.class, Package[].class, "getPackages");
+ Package[] systemPackages = method.invoke(EXT_CLASS_LOADER);
+ for (Package p : systemPackages) {
+ SYSTEM_PACKAGES.add(p.getName());
+ }
+ }
+
+ public FilteringClassLoader(ClassLoader parent) {
+ super(parent);
+ }
+
+ public FilteringClassLoader(ClassLoader parent, Spec spec) {
+ super(parent);
+ packageNames.addAll(spec.packageNames);
+ packagePrefixes.addAll(spec.packagePrefixes);
+ resourceNames.addAll(spec.resourceNames);
+ resourcePrefixes.addAll(spec.resourcePrefixes);
+ classNames.addAll(spec.classNames);
+ disallowedClassNames.addAll(spec.classNames);
+ }
+
+ public void visit(ClassLoaderVisitor visitor) {
+ visitor.visitSpec(new Spec(classNames, packageNames, packagePrefixes, resourcePrefixes, resourceNames, disallowedClassNames));
+ visitor.visitParent(getParent());
+ }
+
+ @Override
+ protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
+ Class<?> cl;
+ try {
+ cl = super.loadClass(name, false);
+ } catch (NoClassDefFoundError e) {
+ if (classAllowed(name)) {
+ throw e;
+ }
+ // The class isn't visible
+ throw new ClassNotFoundException(String.format("%s not found.", name));
+ }
+
+ if (!allowed(cl)) {
+ throw new ClassNotFoundException(String.format("%s not found.", cl.getName()));
+ }
+ if (resolve) {
+ resolveClass(cl);
+ }
+
+ return cl;
+ }
+
+ @Override
+ protected Package getPackage(String name) {
+ Package p = super.getPackage(name);
+ if (p == null || !allowed(p)) {
+ return null;
+ }
+ return p;
+ }
+
+ @Override
+ protected Package[] getPackages() {
+ List<Package> packages = new ArrayList<Package>();
+ for (Package p : super.getPackages()) {
+ if (allowed(p)) {
+ packages.add(p);
+ }
+ }
+ return packages.toArray(new Package[packages.size()]);
+ }
+
+ @Override
+ public URL getResource(String name) {
+ if (allowed(name)) {
+ return super.getResource(name);
+ }
+ return EXT_CLASS_LOADER.getResource(name);
+ }
+
+ @Override
+ public Enumeration<URL> getResources(String name) throws IOException {
+ if (allowed(name)) {
+ return super.getResources(name);
+ }
+ return EXT_CLASS_LOADER.getResources(name);
+ }
+
+ private boolean allowed(String resourceName) {
+ if (resourceNames.contains(resourceName)) {
+ return true;
+ }
+ for (String resourcePrefix : resourcePrefixes) {
+ if (resourceName.startsWith(resourcePrefix)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean allowed(Package pkg) {
+ if (SYSTEM_PACKAGES.contains(pkg.getName())) {
+ return true;
+ }
+ if (packageNames.contains(pkg.getName())) {
+ return true;
+ }
+ for (String packagePrefix : packagePrefixes) {
+ if (pkg.getName().startsWith(packagePrefix)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean allowed(final Class<?> clazz) {
+ boolean systemClass = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
+ public Boolean run() {
+ return clazz.getClassLoader() == null || SYSTEM_CLASS_LOADERS.contains(clazz.getClassLoader());
+ }
+ });
+ return systemClass || classAllowed(clazz.getName());
+ }
+
+ private boolean classAllowed(String className) {
+ if (disallowedClassNames.contains(className)) {
+ return false;
+ }
+ if (classNames.contains(className)) {
+ return true;
+ }
+ for (String packagePrefix : packagePrefixes) {
+ if (className.startsWith(packagePrefix)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Marks a package and all its sub-packages as visible. Also makes resources in those packages visible.
+ *
+ * @param packageName the package name
+ */
+ public void allowPackage(String packageName) {
+ packageNames.add(packageName);
+ packagePrefixes.add(packageName + ".");
+ resourcePrefixes.add(packageName.replace('.', '/') + '/');
+ }
+
+ /**
+ * Marks a single class as visible.
+ *
+ * @param clazz the class
+ */
+ public void allowClass(Class<?> clazz) {
+ classNames.add(clazz.getName());
+ }
+
+ /**
+ * Marks a single class as not visible.
+ *
+ * @param className the class name
+ */
+ public void disallowClass(String className) {
+ disallowedClassNames.add(className);
+ }
+
+ /**
+ * Marks all resources with the given prefix as visible.
+ *
+ * @param resourcePrefix the resource prefix
+ */
+ public void allowResources(String resourcePrefix) {
+ resourcePrefixes.add(resourcePrefix + "/");
+ }
+
+ /**
+ * Marks a single resource as visible.
+ *
+ * @param resourceName the resource name
+ */
+ public void allowResource(String resourceName) {
+ resourceNames.add(resourceName);
+ }
+
+ public static class Spec extends ClassLoaderSpec {
+ final Set<String> packageNames;
+ final Set<String> packagePrefixes;
+ final Set<String> resourcePrefixes;
+ final Set<String> resourceNames;
+ final Set<String> classNames;
+ final Set<String> disallowedClassNames;
+
+ public Spec(Set<String> classNames, Set<String> packageNames, Set<String> packagePrefixes, Set<String> resourcePrefixes, Set<String> resourceNames, Set<String> disallowedClassNames) {
+ this.classNames = new HashSet<String>(classNames);
+ this.packageNames = new HashSet<String>(packageNames);
+ this.packagePrefixes = new HashSet<String>(packagePrefixes);
+ this.resourcePrefixes = new HashSet<String>(resourcePrefixes);
+ this.resourceNames = new HashSet<String>(resourceNames);
+ this.disallowedClassNames = new HashSet<String>(disallowedClassNames);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (obj == null || obj.getClass() != getClass()) {
+ return false;
+ }
+ Spec other = (Spec) obj;
+ return other.packageNames.equals(packageNames)
+ && other.packagePrefixes.equals(packagePrefixes)
+ && other.resourceNames.equals(resourceNames)
+ && other.resourcePrefixes.equals(resourcePrefixes)
+ && other.classNames.equals(classNames)
+ && other.disallowedClassNames.equals(disallowedClassNames);
+ }
+
+ @Override
+ public int hashCode() {
+ return packageNames.hashCode()
+ ^ packagePrefixes.hashCode()
+ ^ resourceNames.hashCode()
+ ^ resourcePrefixes.hashCode()
+ ^ classNames.hashCode()
+ ^ disallowedClassNames.hashCode();
+ }
+ }
+}
diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/classloader/MultiParentClassLoader.java b/subprojects/base-services/src/main/java/org/gradle/internal/classloader/MultiParentClassLoader.java
new file mode 100644
index 0000000..8406559
--- /dev/null
+++ b/subprojects/base-services/src/main/java/org/gradle/internal/classloader/MultiParentClassLoader.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.classloader;
+
+import org.gradle.internal.reflect.JavaReflectionUtil;
+import org.gradle.util.JavaMethod;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.*;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+/**
+ * A {@code ClassLoader} which delegates to multiple parent ClassLoaders.
+ *
+ * Note: It's usually a good idea to add a {@link CachingClassLoader} between this ClassLoader and any
+ * ClassLoaders that use it as a parent, to prevent every path in the ClassLoader graph being searched.
+ */
+public class MultiParentClassLoader extends ClassLoader implements ClassLoaderHierarchy {
+ private final List<ClassLoader> parents;
+ private final JavaMethod<ClassLoader, Package[]> getPackagesMethod;
+ private final JavaMethod<ClassLoader, Package> getPackageMethod;
+
+ public MultiParentClassLoader(ClassLoader... parents) {
+ this(Arrays.asList(parents));
+ }
+
+ public MultiParentClassLoader(Collection<? extends ClassLoader> parents) {
+ super(null);
+ this.parents = new CopyOnWriteArrayList<ClassLoader>(parents);
+ getPackagesMethod = JavaReflectionUtil.method(ClassLoader.class, Package[].class, "getPackages");
+ getPackageMethod = JavaReflectionUtil.method(ClassLoader.class, Package.class, "getPackage", String.class);
+ }
+
+ public void addParent(ClassLoader parent) {
+ parents.add(parent);
+ }
+
+ public void visit(ClassLoaderVisitor visitor) {
+ visitor.visitSpec(new Spec());
+ for (ClassLoader parent : parents) {
+ visitor.visitParent(parent);
+ }
+ }
+
+ @Override
+ protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
+ for (ClassLoader parent : parents) {
+ try {
+ return parent.loadClass(name);
+ } catch (ClassNotFoundException e) {
+ // Expected
+ }
+ }
+ throw new ClassNotFoundException(String.format("%s not found.", name));
+ }
+
+ @Override
+ protected Package getPackage(String name) {
+ for (ClassLoader parent : parents) {
+ Package p = getPackageMethod.invoke(parent, name);
+ if (p != null) {
+ return p;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ protected Package[] getPackages() {
+ Set<Package> packages = new LinkedHashSet<Package>();
+ for (ClassLoader parent : parents) {
+ Package[] parentPackages = getPackagesMethod.invoke(parent);
+ packages.addAll(Arrays.asList(parentPackages));
+ }
+ return packages.toArray(new Package[packages.size()]);
+ }
+
+ @Override
+ public URL getResource(String name) {
+ for (ClassLoader parent : parents) {
+ URL resource = parent.getResource(name);
+ if (resource != null) {
+ return resource;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public Enumeration<URL> getResources(String name) throws IOException {
+ Set<URL> resources = new LinkedHashSet<URL>();
+ for (ClassLoader parent : parents) {
+ Enumeration<URL> parentResources = parent.getResources(name);
+ while (parentResources.hasMoreElements()) {
+ resources.add(parentResources.nextElement());
+ }
+ }
+ return Collections.enumeration(resources);
+ }
+
+ public static class Spec extends ClassLoaderSpec {
+ @Override
+ public boolean equals(Object obj) {
+ return obj != null && obj.getClass().equals(Spec.class);
+ }
+
+ @Override
+ public int hashCode() {
+ return getClass().getName().hashCode();
+ }
+ }
+}
diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/classloader/MutableURLClassLoader.java b/subprojects/base-services/src/main/java/org/gradle/internal/classloader/MutableURLClassLoader.java
new file mode 100755
index 0000000..4f5f6ea
--- /dev/null
+++ b/subprojects/base-services/src/main/java/org/gradle/internal/classloader/MutableURLClassLoader.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.classloader;
+
+import org.gradle.internal.classpath.ClassPath;
+import org.gradle.util.CollectionUtils;
+
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Collection;
+import java.util.List;
+
+public class MutableURLClassLoader extends URLClassLoader implements ClassLoaderHierarchy {
+ public MutableURLClassLoader(ClassLoader parent, URL... urls) {
+ super(urls, parent);
+ }
+
+ public MutableURLClassLoader(ClassLoader parent, Collection<URL> urls) {
+ super(urls.toArray(new URL[urls.size()]), parent);
+ }
+
+ public MutableURLClassLoader(ClassLoader parent, ClassPath classPath) {
+ super(classPath.getAsURLArray(), parent);
+ }
+
+ public MutableURLClassLoader(ClassLoader parent, Spec spec) {
+ this(parent, spec.classpath);
+ }
+
+ public void visit(ClassLoaderVisitor visitor) {
+ visitor.visitSpec(new Spec(CollectionUtils.toList(getURLs())));
+ visitor.visitClassPath(getURLs());
+ visitor.visitParent(getParent());
+ }
+
+ @Override
+ public void addURL(URL url) {
+ super.addURL(url);
+ }
+
+ public void addURLs(Iterable<URL> urls) {
+ for (URL url : urls) {
+ addURL(url);
+ }
+ }
+
+ public static class Spec extends ClassLoaderSpec {
+ final List<URL> classpath;
+
+ public Spec(List<URL> classpath) {
+ this.classpath = classpath;
+ }
+
+ public List<URL> getClasspath() {
+ return classpath;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (obj == null || obj.getClass() != getClass()) {
+ return false;
+ }
+ Spec other = (Spec) obj;
+ return classpath.equals(other.classpath);
+ }
+
+ @Override
+ public int hashCode() {
+ return classpath.hashCode();
+ }
+ }
+}
diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/classloader/TransformingClassLoader.java b/subprojects/base-services/src/main/java/org/gradle/internal/classloader/TransformingClassLoader.java
new file mode 100644
index 0000000..41c4a8d
--- /dev/null
+++ b/subprojects/base-services/src/main/java/org/gradle/internal/classloader/TransformingClassLoader.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.classloader;
+
+import com.google.common.io.ByteStreams;
+import org.gradle.api.GradleException;
+import org.gradle.internal.classpath.ClassPath;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Collection;
+
+public abstract class TransformingClassLoader extends MutableURLClassLoader {
+ public TransformingClassLoader(ClassLoader parent, ClassPath classPath) {
+ super(parent, classPath);
+ }
+
+ public TransformingClassLoader(ClassLoader parent, Collection<URL> urls) {
+ super(parent, urls);
+ }
+
+ @Override
+ protected Class<?> findClass(String name) throws ClassNotFoundException {
+ URL resource = findResource(name.replace(".", "/") + ".class");
+ if (resource == null) {
+ throw new ClassNotFoundException(name);
+ }
+ byte[] bytes;
+ try {
+ bytes = loadBytecode(resource);
+ bytes = transform(bytes);
+ } catch (Exception e) {
+ throw new GradleException(String.format("Could not load class '%s' from %s.", name, resource), e);
+ }
+ return defineClass(name, bytes, 0, bytes.length);
+ }
+
+ private byte[] loadBytecode(URL resource) throws IOException {
+ InputStream inputStream = resource.openStream();
+ try {
+ return ByteStreams.toByteArray(inputStream);
+ } finally {
+ inputStream.close();
+ }
+ }
+
+ protected abstract byte[] transform(byte[] bytes);
+}
diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/concurrent/ServiceLifecycle.java b/subprojects/base-services/src/main/java/org/gradle/internal/concurrent/ServiceLifecycle.java
new file mode 100644
index 0000000..98642c0
--- /dev/null
+++ b/subprojects/base-services/src/main/java/org/gradle/internal/concurrent/ServiceLifecycle.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.concurrent;
+
+import org.gradle.internal.UncheckedException;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * Manages the lifecycle of some thread-safe service or resource.
+ */
+public class ServiceLifecycle implements AsyncStoppable {
+ private enum State {RUNNING, STOPPING, STOPPED}
+
+ private final String displayName;
+ private final Lock lock = new ReentrantLock();
+ private final Condition condition = lock.newCondition();
+ private State state = State.RUNNING;
+ private Map<Thread, Integer> usages = new HashMap<Thread, Integer>();
+
+ public ServiceLifecycle(String displayName) {
+ this.displayName = displayName;
+ }
+
+ public void use(Runnable runnable) {
+ lock.lock();
+ try {
+ switch (state) {
+ case STOPPING:
+ throw new IllegalStateException(String.format("Cannot use %s as it is currently stopping.", displayName));
+ case STOPPED:
+ throw new IllegalStateException(String.format("Cannot use %s as it has been stopped.", displayName));
+ }
+ Integer depth = usages.get(Thread.currentThread());
+ if (depth == null) {
+ usages.put(Thread.currentThread(), 1);
+ } else {
+ usages.put(Thread.currentThread(), depth + 1);
+ }
+ } finally {
+ lock.unlock();
+ }
+
+ try {
+ runnable.run();
+ } finally {
+ lock.lock();
+ try {
+ Integer depth = usages.remove(Thread.currentThread());
+ if (depth > 1) {
+ usages.put(Thread.currentThread(), depth - 1);
+ }
+ if (usages.isEmpty()) {
+ condition.signalAll();
+ if (state == State.STOPPING) {
+ state = State.STOPPED;
+ }
+ }
+ } finally {
+ lock.unlock();
+ }
+ }
+ }
+
+ public void requestStop() {
+ lock.lock();
+ try {
+ if (state == State.RUNNING) {
+ if (usages.isEmpty()) {
+ state = State.STOPPED;
+ } else {
+ state = State.STOPPING;
+ }
+ }
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public void stop() {
+ lock.lock();
+ try {
+ if (usages.containsKey(Thread.currentThread())) {
+ throw new IllegalStateException(String.format("Cannot stop %s from a thread that is using it.", displayName));
+ }
+ while (!usages.isEmpty()) {
+ try {
+ condition.await();
+ } catch (InterruptedException e) {
+ throw UncheckedException.throwAsUncheckedException(e);
+ }
+ }
+ if (state != State.STOPPED) {
+ state = State.STOPPED;
+ }
+ } finally {
+ lock.unlock();
+ }
+ }
+}
diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/jvm/JavaHomeException.java b/subprojects/base-services/src/main/java/org/gradle/internal/jvm/JavaHomeException.java
index 92335e4..57e9dda 100644
--- a/subprojects/base-services/src/main/java/org/gradle/internal/jvm/JavaHomeException.java
+++ b/subprojects/base-services/src/main/java/org/gradle/internal/jvm/JavaHomeException.java
@@ -16,9 +16,6 @@
package org.gradle.internal.jvm;
-/**
- * by Szczepan Faber, created at: 1/23/12
- */
public class JavaHomeException extends RuntimeException {
public JavaHomeException(String message) {
super(message);
diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/jvm/JavaInfo.java b/subprojects/base-services/src/main/java/org/gradle/internal/jvm/JavaInfo.java
index cb4e842..0967b36 100644
--- a/subprojects/base-services/src/main/java/org/gradle/internal/jvm/JavaInfo.java
+++ b/subprojects/base-services/src/main/java/org/gradle/internal/jvm/JavaInfo.java
@@ -19,9 +19,6 @@ package org.gradle.internal.jvm;
import java.io.File;
import java.util.Map;
-/**
- * by Szczepan Faber, created at: 2/6/12
- */
public interface JavaInfo {
/**
* @return the executable
diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/jvm/Jre.java b/subprojects/base-services/src/main/java/org/gradle/internal/jvm/Jre.java
new file mode 100644
index 0000000..af50c3c
--- /dev/null
+++ b/subprojects/base-services/src/main/java/org/gradle/internal/jvm/Jre.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.jvm;
+
+import java.io.File;
+
+/**
+ * Represents a JRE installation.
+ */
+public abstract class Jre {
+ public abstract File getHomeDir();
+}
diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/jvm/Jvm.java b/subprojects/base-services/src/main/java/org/gradle/internal/jvm/Jvm.java
index db4b1f9..bbca272 100644
--- a/subprojects/base-services/src/main/java/org/gradle/internal/jvm/Jvm.java
+++ b/subprojects/base-services/src/main/java/org/gradle/internal/jvm/Jvm.java
@@ -17,6 +17,7 @@
package org.gradle.internal.jvm;
import org.gradle.api.JavaVersion;
+import org.gradle.api.Nullable;
import org.gradle.internal.SystemProperties;
import org.gradle.internal.UncheckedException;
import org.gradle.internal.os.OperatingSystem;
@@ -27,6 +28,7 @@ import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
public class Jvm implements JavaInfo {
@@ -39,12 +41,18 @@ public class Jvm implements JavaInfo {
private final File javaHome;
private final boolean userSupplied;
private final JavaVersion javaVersion;
+ private static final AtomicReference<Jvm> CURRENT = new AtomicReference<Jvm>();
public static Jvm current() {
- return create(null);
+ Jvm jvm = CURRENT.get();
+ if (jvm == null) {
+ CURRENT.compareAndSet(null, create(null));
+ jvm = CURRENT.get();
+ }
+ return jvm;
}
- private static Jvm create(File javaBase) {
+ static Jvm create(File javaBase) {
String vendor = System.getProperty("java.vm.vendor");
if (vendor.toLowerCase().startsWith("apple inc.")) {
return new AppleJvm(OperatingSystem.current(), javaBase);
@@ -143,6 +151,10 @@ public class Jvm implements JavaInfo {
return findExecutable("java");
}
+ public File getJavacExecutable() throws JavaHomeException {
+ return findExecutable("javac");
+ }
+
/**
* {@inheritDoc}
*/
@@ -187,6 +199,10 @@ public class Jvm implements JavaInfo {
*/
public File getRuntimeJar() {
File runtimeJar = new File(javaBase, "lib/rt.jar");
+ if (runtimeJar.exists()) {
+ return runtimeJar;
+ }
+ runtimeJar = new File(javaBase, "jre/lib/rt.jar");
return runtimeJar.exists() ? runtimeJar : null;
}
@@ -197,6 +213,39 @@ public class Jvm implements JavaInfo {
return findToolsJar(javaBase);
}
+ /**
+ * Locates a stand-alone JRE installation for this JVM. Returns null if not found.
+ */
+ @Nullable
+ public Jre getStandaloneJre() {
+ if (os.isWindows()) {
+ File jreDir;
+ if (javaVersion.isJava5()) {
+ jreDir = new File(javaHome.getParentFile(), String.format("jre%s", SystemProperties.getJavaVersion()));
+ } else {
+ jreDir = new File(javaHome.getParentFile(), String.format("jre%s", javaVersion.getMajorVersion()));
+ }
+ if (jreDir.isDirectory()) {
+ return new DefaultJre(jreDir);
+ }
+ }
+ if (!new File(javaHome, "jre").isDirectory()) {
+ return new DefaultJre(javaHome);
+ }
+ return null;
+ }
+
+ /**
+ * Locates the JRE installation for this JVM.
+ */
+ public Jre getJre() {
+ File jreDir = new File(javaBase, "jre");
+ if (jreDir.isDirectory()) {
+ return new DefaultJre(jreDir);
+ }
+ return new DefaultJre(javaBase);
+ }
+
private File findToolsJar(File javaHome) {
File toolsJar = new File(javaHome, "lib/tools.jar");
if (toolsJar.exists()) {
@@ -209,11 +258,15 @@ public class Jvm implements JavaInfo {
return toolsJar;
}
}
- if (javaHome.getName().matches("jre\\d+") && os.isWindows()) {
- javaHome = new File(javaHome.getParentFile(), String.format("jdk%s", SystemProperties.getJavaVersion()));
- toolsJar = new File(javaHome, "lib/tools.jar");
- if (toolsJar.exists()) {
- return toolsJar;
+
+ if (os.isWindows()) {
+ String version = SystemProperties.getJavaVersion();
+ if (javaHome.getName().matches("jre\\d+") || javaHome.getName().equals(String.format("jre%s", version))) {
+ javaHome = new File(javaHome.getParentFile(), String.format("jdk%s", version));
+ toolsJar = new File(javaHome, "lib/tools.jar");
+ if (toolsJar.exists()) {
+ return toolsJar;
+ }
}
}
@@ -288,4 +341,17 @@ public class Jvm implements JavaInfo {
return vars;
}
}
+
+ private static class DefaultJre extends Jre {
+ private final File jreDir;
+
+ public DefaultJre(File jreDir) {
+ this.jreDir = jreDir;
+ }
+
+ @Override
+ public File getHomeDir() {
+ return jreDir;
+ }
+ }
}
diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/os/OperatingSystem.java b/subprojects/base-services/src/main/java/org/gradle/internal/os/OperatingSystem.java
index 08dd03d..cb87123 100755
--- a/subprojects/base-services/src/main/java/org/gradle/internal/os/OperatingSystem.java
+++ b/subprojects/base-services/src/main/java/org/gradle/internal/os/OperatingSystem.java
@@ -15,6 +15,8 @@
*/
package org.gradle.internal.os;
+import org.gradle.api.Nullable;
+
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
@@ -82,9 +84,12 @@ public abstract class OperatingSystem {
public abstract String getSharedLibraryName(String libraryName);
+ public abstract String getStaticLibraryName(String libraryName);
+
/**
* Locates the given executable in the system path. Returns null if not found.
*/
+ @Nullable
public File findInPath(String name) {
String exeName = getExecutableName(name);
if (exeName.contains(File.separator)) {
@@ -117,8 +122,8 @@ public abstract class OperatingSystem {
return all;
}
- List<File> getPath() {
- String path = System.getenv("PATH");
+ List<File> getPath() {
+ String path = System.getenv(getPathVar());
if (path == null) {
return Collections.emptyList();
}
@@ -129,6 +134,10 @@ public abstract class OperatingSystem {
return entries;
}
+ public String getPathVar() {
+ return "PATH";
+ }
+
static class Windows extends OperatingSystem {
@Override
public boolean isWindows() {
@@ -137,10 +146,7 @@ public abstract class OperatingSystem {
@Override
public String getScriptName(String scriptPath) {
- if (scriptPath.toLowerCase().endsWith(".bat")) {
- return scriptPath;
- }
- return scriptPath + ".bat";
+ return withSuffix(scriptPath, ".bat");
}
@Override
@@ -154,6 +160,11 @@ public abstract class OperatingSystem {
}
@Override
+ public String getStaticLibraryName(String libraryName) {
+ return withSuffix(libraryName, ".lib");
+ }
+
+ @Override
public String getNativePrefix() {
String arch = System.getProperty("os.arch");
if ("i386".equals(arch)) {
@@ -166,7 +177,23 @@ public abstract class OperatingSystem {
if (executablePath.toLowerCase().endsWith(extension)) {
return executablePath;
}
- return executablePath + extension;
+ return removeExtension(executablePath) + extension;
+ }
+
+ private String removeExtension(String executablePath) {
+ int fileNameStart = Math.max(executablePath.lastIndexOf('/'), executablePath.lastIndexOf('\\'));
+ int extensionPos = executablePath.lastIndexOf('.');
+
+ if (extensionPos > fileNameStart) {
+ return executablePath.substring(0, extensionPos);
+ }
+ return executablePath;
+ }
+
+
+ @Override
+ public String getPathVar() {
+ return "Path";
}
}
@@ -183,7 +210,10 @@ public abstract class OperatingSystem {
@Override
public String getSharedLibraryName(String libraryName) {
- String suffix = getSharedLibSuffix();
+ return getLibraryName(libraryName, getSharedLibSuffix());
+ }
+
+ private String getLibraryName(String libraryName, String suffix) {
if (libraryName.endsWith(suffix)) {
return libraryName;
}
@@ -200,6 +230,11 @@ public abstract class OperatingSystem {
}
@Override
+ public String getStaticLibraryName(String libraryName) {
+ return getLibraryName(libraryName, ".a");
+ }
+
+ @Override
public boolean isUnix() {
return true;
}
diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/reflect/DirectInstantiator.java b/subprojects/base-services/src/main/java/org/gradle/internal/reflect/DirectInstantiator.java
index 65a2ac0..cd7f87f 100644
--- a/subprojects/base-services/src/main/java/org/gradle/internal/reflect/DirectInstantiator.java
+++ b/subprojects/base-services/src/main/java/org/gradle/internal/reflect/DirectInstantiator.java
@@ -22,7 +22,7 @@ import java.util.Arrays;
import java.util.List;
public class DirectInstantiator implements Instantiator {
- public <T> T newInstance(Class<T> type, Object... params) {
+ public <T> T newInstance(Class<? extends T> type, Object... params) {
try {
List<Constructor<?>> matches = new ArrayList<Constructor<?>>();
for (Constructor<?> constructor : type.getConstructors()) {
diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/reflect/Instantiator.java b/subprojects/base-services/src/main/java/org/gradle/internal/reflect/Instantiator.java
index 6c50e84..a131ccd 100644
--- a/subprojects/base-services/src/main/java/org/gradle/internal/reflect/Instantiator.java
+++ b/subprojects/base-services/src/main/java/org/gradle/internal/reflect/Instantiator.java
@@ -25,6 +25,6 @@ public interface Instantiator {
*
* @throws ObjectInstantiationException On failure to create the new instance.
*/
- <T> T newInstance(Class<T> type, Object... parameters) throws ObjectInstantiationException;
+ <T> T newInstance(Class<? extends T> type, Object... parameters) throws ObjectInstantiationException;
}
\ No newline at end of file
diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/reflect/JavaReflectionUtil.java b/subprojects/base-services/src/main/java/org/gradle/internal/reflect/JavaReflectionUtil.java
index 215786c..b6bce36 100644
--- a/subprojects/base-services/src/main/java/org/gradle/internal/reflect/JavaReflectionUtil.java
+++ b/subprojects/base-services/src/main/java/org/gradle/internal/reflect/JavaReflectionUtil.java
@@ -16,46 +16,134 @@
package org.gradle.internal.reflect;
+import org.gradle.api.Transformer;
+import org.gradle.api.specs.Spec;
import org.gradle.internal.UncheckedException;
+import org.gradle.util.CollectionUtils;
+import org.gradle.util.JavaMethod;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.Inherited;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.*;
-/**
- * Simple implementations of some reflection capabilities. In contrast to org.gradle.util.ReflectionUtil,
- * this class doesn't make use of Groovy.
- */
public class JavaReflectionUtil {
- public static Object readProperty(Object target, String property) {
- try {
- Method getterMethod;
- try {
- getterMethod = target.getClass().getMethod(toMethodName("get", property));
- } catch (NoSuchMethodException e) {
- try {
- getterMethod = target.getClass().getMethod(toMethodName("is", property));
- } catch (NoSuchMethodException e2) {
- throw e;
- }
+ /**
+ * Locates the readable properties of the given type. Searches only public properties.
+ */
+ public static Map<String, PropertyAccessor> readableProperties(Class<?> target) {
+ HashMap<String, PropertyAccessor> properties = new HashMap<String, PropertyAccessor>();
+ for (Method method : target.getMethods()) {
+ if (method.getName().startsWith("get") && isGetter(method)) {
+ String propertyName = method.getName().substring(3);
+ propertyName = Character.toLowerCase(propertyName.charAt(0)) + propertyName.substring(1);
+ properties.put(propertyName, new GetterMethodBackedPropertyAccessor(propertyName, method));
+ } else if (method.getName().startsWith("is") && isBooleanGetter(method)) {
+ String propertyName = method.getName().substring(2);
+ propertyName = Character.toLowerCase(propertyName.charAt(0)) + propertyName.substring(1);
+ properties.put(propertyName, new GetterMethodBackedPropertyAccessor(propertyName, method));
}
- return getterMethod.invoke(target);
- } catch (Exception e) {
- throw UncheckedException.throwAsUncheckedException(e);
}
+ return properties;
+ }
+
+ /**
+ * Locates the property with the given name as a readable property. Searches only public properties.
+ *
+ * @throws NoSuchPropertyException when the given property does not exist.
+ */
+ public static PropertyAccessor readableProperty(Class<?> target, String property) {
+ final Method getterMethod = findGetterMethod(target, property);
+ if (getterMethod == null) {
+ throw new NoSuchPropertyException(String.format("Could not find getter method for property '%s' on class %s.", property, target.getSimpleName()));
+ }
+ return new GetterMethodBackedPropertyAccessor(property, getterMethod);
}
- public static void writeProperty(Object target, String property, Object value) {
+ private static Method findGetterMethod(Class<?> target, String property) {
try {
- String setterName = toMethodName("set", property);
- for (Method method: target.getClass().getMethods()) {
- if (!method.getName().equals(setterName)) { continue; }
- if (method.getParameterTypes().length != 1) { continue; }
- method.invoke(target, value);
- return;
+ Method getterMethod = target.getMethod(toMethodName("get", property));
+ if (isGetter(getterMethod)) {
+ return getterMethod;
+ }
+ } catch (NoSuchMethodException e) {
+ // Ignore
+ }
+ try {
+ Method getterMethod = target.getMethod(toMethodName("is", property));
+ if (isBooleanGetter(getterMethod)) {
+ return getterMethod;
+ }
+ } catch (NoSuchMethodException e2) {
+ // Ignore
+ }
+ return null;
+ }
+
+ private static boolean isGetter(Method method) {
+ return method.getParameterTypes().length == 0 && !Modifier.isStatic(method.getModifiers()) && !method.getReturnType().equals(Void.TYPE);
+ }
+
+ private static boolean isBooleanGetter(Method method) {
+ Class<?> returnType = method.getReturnType();
+ return method.getParameterTypes().length == 0 && !Modifier.isStatic(method.getModifiers()) && (returnType.equals(Boolean.TYPE) || returnType.equals(Boolean.class));
+ }
+
+ /**
+ * Locates the property with the given name as a writable property. Searches only public properties.
+ *
+ * @throws NoSuchPropertyException when the given property does not exist.
+ */
+ public static PropertyMutator writeableProperty(Class<?> target, String property) {
+ String setterName = toMethodName("set", property);
+ for (final Method method : target.getMethods()) {
+ if (!method.getName().equals(setterName)) {
+ continue;
+ }
+ if (method.getParameterTypes().length != 1) {
+ continue;
+ }
+ if (Modifier.isStatic(method.getModifiers())) {
+ continue;
+ }
+ return new MethodBackedPropertyMutator(property, method);
+ }
+ throw new NoSuchPropertyException(String.format("Could not find setter method for property '%s' on class %s.", property, target.getSimpleName()));
+ }
+
+ public static <T> T readField(Object target, Class<T> type, String name) {
+ Class<?> objectType = target.getClass();
+ while (objectType != null) {
+ try {
+ Field field = objectType.getDeclaredField(name);
+ if (type.isAssignableFrom(field.getType())) {
+ field.setAccessible(true);
+ Object value;
+ try {
+ value = field.get(target);
+ } catch (IllegalAccessException e) {
+ throw UncheckedException.throwAsUncheckedException(e);
+ }
+
+ if (type.isPrimitive()) {
+ @SuppressWarnings("unchecked")
+ T cast = (T) getWrapperTypeForPrimitiveType(type).cast(value);
+ return cast;
+ } else {
+ return type.cast(value);
+ }
+ }
+ } catch (NoSuchFieldException ignore) {
+ // ignore
}
- throw new NoSuchMethodException(String.format("could not find setter method '%s'", setterName));
- } catch (Exception e) {
- throw UncheckedException.throwAsUncheckedException(e);
+
+ objectType = objectType.getSuperclass();
}
+
+ throw UncheckedException.throwAsUncheckedException(new NoSuchFieldException("Could not find field '" + name + "' with type '" + type.getClass() + "' on class '" + target.getClass() + "'"));
}
private static String toMethodName(String prefix, String propertyName) {
@@ -80,4 +168,206 @@ public class JavaReflectionUtil {
}
throw new IllegalArgumentException(String.format("Don't know how wrapper type for primitive type %s.", type));
}
+
+ public static <T, R> JavaMethod<T, R> method(Class<T> target, Class<R> returnType, String name, Class<?>... paramTypes) {
+ return new JavaMethod<T, R>(target, returnType, name, paramTypes);
+ }
+
+ public static <T, R> JavaMethod<T, R> method(T target, Class<R> returnType, String name, Class<?>... paramTypes) {
+ @SuppressWarnings("unchecked")
+ Class<T> targetClass = (Class<T>) target.getClass();
+ return method(targetClass, returnType, name, paramTypes);
+ }
+
+ public static <T, R> JavaMethod<T, R> method(Class<T> target, Class<R> returnType, Method method) {
+ return new JavaMethod<T, R>(target, returnType, method);
+ }
+
+ public static <T, R> JavaMethod<T, R> method(T target, Class<R> returnType, Method method) {
+ @SuppressWarnings("unchecked")
+ Class<T> targetClass = (Class<T>) target.getClass();
+ return new JavaMethod<T, R>(targetClass, returnType, method);
+ }
+
+ /**
+ * Search methods in an inheritance aware fashion, stopping when stopIndicator returns true.
+ */
+ public static void searchMethods(Class<?> target, final Transformer<Boolean, Method> stopIndicator) {
+ Spec<Method> stopIndicatorAsSpec = new Spec<Method>() {
+ public boolean isSatisfiedBy(Method element) {
+ return stopIndicator.transform(element);
+ }
+ };
+
+ findAllMethodsInternal(target, stopIndicatorAsSpec, new MultiMap<String, Method>(), new ArrayList<Method>(1), true);
+ }
+
+ public static Method findMethod(Class<?> target, Spec<Method> predicate) {
+ List<Method> methods = findAllMethodsInternal(target, predicate, new MultiMap<String, Method>(), new ArrayList<Method>(1), true);
+ return methods.isEmpty() ? null : methods.get(0);
+ }
+
+ // Not hasProperty() because that's awkward with Groovy objects implementing it
+ public static boolean propertyExists(Object target, String propertyName) {
+ Class<?> targetType = target.getClass();
+ Method getterMethod = findGetterMethod(target.getClass(), propertyName);
+ if (getterMethod == null) {
+ try {
+ Field field = targetType.getField(propertyName);
+ return true;
+ } catch (NoSuchFieldException ignore) {
+ // ignore
+ }
+ } else {
+ return true;
+ }
+
+ return false;
+ }
+
+ private static class MultiMap<K, V> extends HashMap<K, List<V>> {
+ @Override
+ public List<V> get(Object key) {
+ if (!containsKey(key)) {
+ @SuppressWarnings("unchecked") K keyCast = (K) key;
+ put(keyCast, new LinkedList<V>());
+ }
+
+ return super.get(key);
+ }
+ }
+
+ private static List<Method> findAllMethodsInternal(Class<?> target, Spec<Method> predicate, MultiMap<String, Method> seen, List<Method> collector, boolean stopAtFirst) {
+ for (final Method method : target.getDeclaredMethods()) {
+ List<Method> seenWithName = seen.get(method.getName());
+ Method override = CollectionUtils.findFirst(seenWithName, new Spec<Method>() {
+ public boolean isSatisfiedBy(Method potentionOverride) {
+ return potentionOverride.getName().equals(method.getName())
+ && Arrays.equals(potentionOverride.getParameterTypes(), method.getParameterTypes());
+ }
+ });
+
+
+ if (override == null) {
+ seenWithName.add(method);
+ if (predicate.isSatisfiedBy(method)) {
+ collector.add(method);
+ if (stopAtFirst) {
+ return collector;
+ }
+ }
+ }
+ }
+
+ Class<?> parent = target.getSuperclass();
+ if (parent != null) {
+ return findAllMethodsInternal(parent, predicate, seen, collector, stopAtFirst);
+ }
+
+ return collector;
+ }
+
+ public static <A extends Annotation> A getAnnotation(Class<?> type, Class<A> annotationType) {
+ return getAnnotation(type, annotationType, true);
+ }
+
+ private static <A extends Annotation> A getAnnotation(Class<?> type, Class<A> annotationType, boolean checkType) {
+ A annotation;
+ if (checkType) {
+ annotation = type.getAnnotation(annotationType);
+ if (annotation != null) {
+ return annotation;
+ }
+ }
+
+ if (annotationType.getAnnotation(Inherited.class) != null) {
+ for (Class<?> anInterface : type.getInterfaces()) {
+ annotation = getAnnotation((Class<?>) anInterface, (Class<A>) annotationType, true);
+ if (annotation != null) {
+ return annotation;
+ }
+ }
+ }
+
+ if (type.isInterface() || type.equals(Object.class)) {
+ return null;
+ } else {
+ return getAnnotation((Class<?>) type.getSuperclass(), (Class<A>) annotationType, false);
+ }
+ }
+
+ public static boolean isClassAvailable(String className) {
+ try {
+ JavaReflectionUtil.class.getClassLoader().loadClass(className);
+ return true;
+ } catch (ClassNotFoundException e) {
+ return false;
+ }
+ }
+
+ private static class GetterMethodBackedPropertyAccessor implements PropertyAccessor {
+ private final String property;
+ private final Method method;
+
+ public GetterMethodBackedPropertyAccessor(String property, Method method) {
+ this.property = property;
+ this.method = method;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("property %s.%s", method.getDeclaringClass().getSimpleName(), property);
+ }
+
+ public String getName() {
+ return property;
+ }
+
+ public Class<?> getType() {
+ return method.getClass();
+ }
+
+ public Object getValue(Object target) {
+ try {
+ return method.invoke(target);
+ } catch (InvocationTargetException e) {
+ throw UncheckedException.unwrapAndRethrow(e);
+ } catch (Exception e) {
+ throw UncheckedException.throwAsUncheckedException(e);
+ }
+ }
+ }
+
+ private static class MethodBackedPropertyMutator implements PropertyMutator {
+ private final String property;
+ private final Method method;
+
+ public MethodBackedPropertyMutator(String property, Method method) {
+ this.property = property;
+ this.method = method;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("property %s.%s", method.getDeclaringClass().getSimpleName(), property);
+ }
+
+ public String getName() {
+ return property;
+ }
+
+ public Class<?> getType() {
+ return method.getParameterTypes()[0];
+ }
+
+ public void setValue(Object target, Object value) {
+ try {
+ method.invoke(target, value);
+ } catch (InvocationTargetException e) {
+ throw UncheckedException.unwrapAndRethrow(e);
+ } catch (Exception e) {
+ throw UncheckedException.throwAsUncheckedException(e);
+ }
+ }
+ }
}
diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/reflect/NoSuchPropertyException.java b/subprojects/base-services/src/main/java/org/gradle/internal/reflect/NoSuchPropertyException.java
new file mode 100644
index 0000000..9f96809
--- /dev/null
+++ b/subprojects/base-services/src/main/java/org/gradle/internal/reflect/NoSuchPropertyException.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.reflect;
+
+/**
+ * Thrown when a requested property cannot be found.
+ */
+public class NoSuchPropertyException extends RuntimeException {
+ public NoSuchPropertyException(String message) {
+ super(message);
+ }
+}
diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/reflect/PropertyAccessor.java b/subprojects/base-services/src/main/java/org/gradle/internal/reflect/PropertyAccessor.java
new file mode 100644
index 0000000..3d02e6c
--- /dev/null
+++ b/subprojects/base-services/src/main/java/org/gradle/internal/reflect/PropertyAccessor.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.reflect;
+
+public interface PropertyAccessor {
+ String getName();
+
+ Class<?> getType();
+
+ Object getValue(Object target);
+}
diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/reflect/PropertyMutator.java b/subprojects/base-services/src/main/java/org/gradle/internal/reflect/PropertyMutator.java
new file mode 100644
index 0000000..9780742
--- /dev/null
+++ b/subprojects/base-services/src/main/java/org/gradle/internal/reflect/PropertyMutator.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.reflect;
+
+public interface PropertyMutator {
+ String getName();
+
+ Class<?> getType();
+
+ void setValue(Object target, Object value);
+}
diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/service/ServiceLocator.java b/subprojects/base-services/src/main/java/org/gradle/internal/service/ServiceLocator.java
index dacebfa..6487fd7 100644
--- a/subprojects/base-services/src/main/java/org/gradle/internal/service/ServiceLocator.java
+++ b/subprojects/base-services/src/main/java/org/gradle/internal/service/ServiceLocator.java
@@ -25,15 +25,14 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
+import java.util.*;
/**
* Uses the Jar service resource specification to locate service implementations.
*/
public class ServiceLocator extends AbstractServiceRegistry {
private final ClassLoader classLoader;
- private final Map<Class<?>, Object> implementations = new ConcurrentHashMap<Class<?>, Object>();
+ private final Map<Class<?>, Object> implementations = new HashMap<Class<?>, Object>();
public ServiceLocator(ClassLoader classLoader) {
this.classLoader = classLoader;
@@ -50,6 +49,15 @@ public class ServiceLocator extends AbstractServiceRegistry {
}
}
+ public <T> List<T> getAll(Class<T> serviceType) {
+ List<ServiceFactory<T>> factories = findFactoriesForServiceType(serviceType);
+ ArrayList<T> services = new ArrayList<T>();
+ for (ServiceFactory<T> factory : factories) {
+ services.add(factory.create());
+ }
+ return services;
+ }
+
public <T> ServiceFactory<T> getFactory(final Class<T> serviceType) throws UnknownServiceException {
ServiceFactory<T> factory = findFactory(serviceType);
if (factory == null) {
@@ -62,55 +70,79 @@ public class ServiceLocator extends AbstractServiceRegistry {
* Locates a factory for a given service. Returns null when no service implementation is available.
*/
public <T> ServiceFactory<T> findFactory(Class<T> serviceType) {
- Class<? extends T> implementationClass = findServiceImplementationClass(serviceType);
- if (implementationClass == null) {
+ List<ServiceFactory<T>> factories = findFactoriesForServiceType(serviceType);
+ if (factories.isEmpty()) {
return null;
}
- return new ServiceFactory<T>(serviceType, implementationClass);
+ return factories.get(0);
}
- <T> Class<? extends T> findServiceImplementationClass(Class<T> serviceType) {
- String implementationClassName;
+ private <T> List<ServiceFactory<T>> findFactoriesForServiceType(Class<T> serviceType) {
+ List<Class<? extends T>> implementationClasses;
try {
- implementationClassName = findServiceImplementationClassName(serviceType);
+ implementationClasses = findServiceImplementations(serviceType);
+ } catch (ServiceLookupException e) {
+ throw e;
} catch (Exception e) {
- throw new ServiceLookupException(String.format("Could not determine implementation class for service '%s'.", serviceType.getName()), e);
- }
- if (implementationClassName == null) {
- return null;
+ throw new ServiceLookupException(String.format("Could not determine implementation classes for service '%s'.", serviceType.getName()), e);
}
- try {
- Class<?> implClass = classLoader.loadClass(implementationClassName);
- if (!serviceType.isAssignableFrom(implClass)) {
- throw new RuntimeException(String.format("Implementation class '%s' is not assignable to service class '%s'.", implementationClassName, serviceType.getName()));
- }
- return implClass.asSubclass(serviceType);
- } catch (Throwable t) {
- throw new ServiceLookupException(String.format("Could not load implementation class '%s' for service '%s'.", implementationClassName, serviceType.getName()), t);
+ List<ServiceFactory<T>> factories = new ArrayList<ServiceFactory<T>>();
+ for (Class<? extends T> implementationClass : implementationClasses) {
+ factories.add(new ServiceFactory<T>(serviceType, implementationClass));
}
+ return factories;
}
- private String findServiceImplementationClassName(Class<?> serviceType) throws IOException {
+ private <T> List<Class<? extends T>> findServiceImplementations(Class<T> serviceType) throws IOException {
String resourceName = "META-INF/services/" + serviceType.getName();
- URL resource = classLoader.getResource(resourceName);
- if (resource == null) {
- return null;
+ Enumeration<URL> resources = classLoader.getResources(resourceName);
+ Set<String> implementationClassNames = new HashSet<String>();
+ List<Class<? extends T>> implementations = new ArrayList<Class<? extends T>>();
+ while (resources.hasMoreElements()) {
+ URL resource = resources.nextElement();
+ List<String> implementationClassNamesFromResource;
+ try {
+ implementationClassNamesFromResource = extractImplementationClassNames(resource);
+ if (implementationClassNamesFromResource.isEmpty()) {
+ throw new RuntimeException(String.format("No implementation class for service '%s' specified.", serviceType.getName()));
+ }
+ } catch (Exception e) {
+ throw new ServiceLookupException(String.format("Could not determine implementation class for service '%s' specified in resource '%s'.", serviceType.getName(), resource), e);
+ }
+
+ for (String implementationClassName : implementationClassNamesFromResource) {
+ if (implementationClassNames.add(implementationClassName)) {
+ try {
+ Class<?> implClass = classLoader.loadClass(implementationClassName);
+ if (!serviceType.isAssignableFrom(implClass)) {
+ throw new RuntimeException(String.format("Implementation class '%s' is not assignable to service class '%s'.", implementationClassName, serviceType.getName()));
+ }
+ implementations.add(implClass.asSubclass(serviceType));
+ } catch (Exception e) {
+ throw new ServiceLookupException(String.format("Could not load implementation class '%s' for service '%s' specified in resource '%s'.", implementationClassName, serviceType.getName(), resource), e);
+ }
+ }
+ }
}
+ return implementations;
+ }
+ private List<String> extractImplementationClassNames(URL resource) throws IOException {
InputStream inputStream = resource.openStream();
try {
- BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
+ BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
+ List<String> implemetationClassNames = new ArrayList<String>();
String line;
while ((line = reader.readLine()) != null) {
line = line.replaceAll("#.*", "").trim();
if (line.length() > 0) {
- return line;
+ implemetationClassNames.add(line);
}
}
+ return implemetationClassNames;
} finally {
inputStream.close();
}
- throw new RuntimeException(String.format("No implementation class for service '%s' specified in resource '%s'.", serviceType.getName(), resource));
}
public static class ServiceFactory<T> implements Factory<T> {
diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/service/SynchronizedServiceRegistry.java b/subprojects/base-services/src/main/java/org/gradle/internal/service/SynchronizedServiceRegistry.java
index 868ba39..2a6c046 100644
--- a/subprojects/base-services/src/main/java/org/gradle/internal/service/SynchronizedServiceRegistry.java
+++ b/subprojects/base-services/src/main/java/org/gradle/internal/service/SynchronizedServiceRegistry.java
@@ -21,9 +21,6 @@ import org.gradle.internal.concurrent.Synchronizer;
import java.lang.reflect.Type;
-/**
- * by Szczepan Faber, created at: 11/24/11
- */
public class SynchronizedServiceRegistry implements ServiceRegistry {
private final Synchronizer synchronizer = new Synchronizer();
private final ServiceRegistry delegate;
diff --git a/subprojects/base-services/src/main/java/org/gradle/util/CollectionUtils.java b/subprojects/base-services/src/main/java/org/gradle/util/CollectionUtils.java
index 3b790f3..cf52c32 100644
--- a/subprojects/base-services/src/main/java/org/gradle/util/CollectionUtils.java
+++ b/subprojects/base-services/src/main/java/org/gradle/util/CollectionUtils.java
@@ -37,6 +37,10 @@ public abstract class CollectionUtils {
return null;
}
+ public static <T> boolean any(Iterable<? extends T> source, Spec<? super T> filter) {
+ return findFirst(source, filter) != null;
+ }
+
public static <T> Set<T> filter(Set<? extends T> set, Spec<? super T> filter) {
return filter(set, new LinkedHashSet<T>(), filter);
}
@@ -104,6 +108,10 @@ public abstract class CollectionUtils {
return collect(set, new HashSet<R>(), transformer);
}
+ public static <R, I> List<R> collect(Iterable<? extends I> source, Transformer<? extends R, ? super I> transformer) {
+ return collect(source, new LinkedList<R>(), transformer);
+ }
+
public static <R, I, C extends Collection<R>> C collect(Iterable<? extends I> source, C destination, Transformer<? extends R, ? super I> transformer) {
for (I item : source) {
destination.add(transformer.transform(item));
@@ -193,6 +201,18 @@ public abstract class CollectionUtils {
return list;
}
+ public static <T> List<T> toList(T[] things) {
+ if (things == null || things.length == 0) {
+ return new ArrayList<T>(0);
+ }
+
+ List<T> list = new ArrayList<T>(things.length);
+ for (T thing : things) {
+ list.add(thing);
+ }
+ return list;
+ }
+
public static <T> Set<T> toSet(Iterable<? extends T> things) {
if (things == null) {
return new HashSet<T>(0);
diff --git a/subprojects/base-services/src/main/java/org/gradle/util/JavaMethod.java b/subprojects/base-services/src/main/java/org/gradle/util/JavaMethod.java
new file mode 100644
index 0000000..73420db
--- /dev/null
+++ b/subprojects/base-services/src/main/java/org/gradle/util/JavaMethod.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.util;
+
+import org.gradle.api.GradleException;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Arrays;
+
+public class JavaMethod<T, R> {
+ private final Method method;
+ private final Class<R> returnType;
+
+ public JavaMethod(Class<T> target, Class<R> returnType, String name, Class<?>... paramTypes) {
+ this.returnType = returnType;
+ method = findMethod(target, target, name, paramTypes);
+ method.setAccessible(true);
+ }
+
+ public JavaMethod(Class<T> target, Class<R> returnType, Method method) {
+ this.returnType = returnType;
+ this.method = method;
+ method.setAccessible(true);
+ }
+
+ private Method findMethod(Class origTarget, Class target, String name, Class<?>[] paramTypes) {
+ for (Method method : target.getDeclaredMethods()) {
+ if (Modifier.isStatic(method.getModifiers())) {
+ continue;
+ }
+ if (method.getName().equals(name) && Arrays.equals(method.getParameterTypes(), paramTypes)) {
+ return method;
+ }
+ }
+
+ Class<?> parent = target.getSuperclass();
+ if (parent == null) {
+ throw new GradleException(String.format("Could not find method %s(%s) on %s", name, Arrays.toString(paramTypes),
+ origTarget));
+ } else {
+ return findMethod(origTarget, parent, name, paramTypes);
+ }
+ }
+
+ public R invoke(T target, Object... args) {
+ try {
+ Object result = method.invoke(target, args);
+ return returnType.cast(result);
+ } catch (InvocationTargetException e) {
+ Throwable cause = e.getCause();
+ if (cause instanceof RuntimeException) {
+ throw (RuntimeException) cause;
+ }
+ throw new GradleException(String.format("Could not call %s.%s() on %s", method.getDeclaringClass().getSimpleName(), method.getName(), target), cause);
+ } catch (Exception e) {
+ throw new GradleException(String.format("Could not call %s.%s() on %s", method.getDeclaringClass().getSimpleName(), method.getName(), target), e);
+ }
+ }
+
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/util/hash/HashUtil.java b/subprojects/base-services/src/main/java/org/gradle/util/hash/HashUtil.java
similarity index 100%
rename from subprojects/core/src/main/groovy/org/gradle/util/hash/HashUtil.java
rename to subprojects/base-services/src/main/java/org/gradle/util/hash/HashUtil.java
diff --git a/subprojects/core/src/main/groovy/org/gradle/util/hash/HashValue.java b/subprojects/base-services/src/main/java/org/gradle/util/hash/HashValue.java
similarity index 100%
rename from subprojects/core/src/main/groovy/org/gradle/util/hash/HashValue.java
rename to subprojects/base-services/src/main/java/org/gradle/util/hash/HashValue.java
diff --git a/subprojects/base-services/src/test/groovy/org/gradle/api/internal/TransformersTest.groovy b/subprojects/base-services/src/test/groovy/org/gradle/api/internal/TransformersTest.groovy
index 6a95706..93e4102 100644
--- a/subprojects/base-services/src/test/groovy/org/gradle/api/internal/TransformersTest.groovy
+++ b/subprojects/base-services/src/test/groovy/org/gradle/api/internal/TransformersTest.groovy
@@ -16,6 +16,7 @@
package org.gradle.api.internal
+import org.gradle.api.Action
import org.gradle.api.Named
import org.gradle.api.Namer
import spock.lang.Specification
@@ -49,6 +50,11 @@ class TransformersTest extends Specification {
asString().transform(null) == null
}
+ def "to URL"() {
+ expect:
+ toURL().transform(new URI("http://localhost:80/path")) == new URL("http://localhost:80/path")
+ }
+
def "naming"() {
expect:
name().transform(named("foo")) == "foo"
@@ -64,6 +70,24 @@ class TransformersTest extends Specification {
name(namer).transform(3) == "3"
}
+ def "by type"() {
+ expect:
+ type().transform("foo") == String
+ }
+
+ def "action as transformer"() {
+ def action = Mock(Action)
+
+ when:
+ def result = toTransformer(action).transform("original")
+
+ then:
+ 1 * action.execute("original")
+
+ and:
+ result == null
+ }
+
Named named(String name) {
new Named() {
String getName() {
diff --git a/subprojects/base-services/src/test/groovy/org/gradle/internal/LazyIterableTest.groovy b/subprojects/base-services/src/test/groovy/org/gradle/internal/LazyIterableTest.groovy
deleted file mode 100644
index 717b5ad..0000000
--- a/subprojects/base-services/src/test/groovy/org/gradle/internal/LazyIterableTest.groovy
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.internal
-
-import spock.lang.Specification
-
-class LazyIterableTest extends Specification {
-
- def "laziness"() {
- given:
- def l = [1]
- def i = new LazyIterable({ l } as Factory)
-
- expect:
- i.collect() == [1]
-
- when:
- l << 2
-
- then:
- i.collect() == [1, 2]
- }
-}
diff --git a/subprojects/base-services/src/test/groovy/org/gradle/internal/classloader/CachingClassLoaderTest.groovy b/subprojects/base-services/src/test/groovy/org/gradle/internal/classloader/CachingClassLoaderTest.groovy
new file mode 100644
index 0000000..53991c6
--- /dev/null
+++ b/subprojects/base-services/src/test/groovy/org/gradle/internal/classloader/CachingClassLoaderTest.groovy
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.classloader
+
+import spock.lang.Specification
+
+class CachingClassLoaderTest extends Specification {
+ final parent = Mock(ClassLoader, useObjenesis: false)
+ final classLoader = new CachingClassLoader(parent)
+
+ def "loads class once and caches result"() {
+ when:
+ def cl = classLoader.loadClass("someClass")
+
+ then:
+ cl == String.class
+
+ and:
+ 1 * parent.loadClass("someClass", false) >> String.class
+ 0 * parent._
+
+ when:
+ cl = classLoader.loadClass("someClass")
+
+ then:
+ cl == String.class
+
+ and:
+ 0 * parent._
+ }
+
+ def "caches missing classes"() {
+ when:
+ classLoader.loadClass("someClass")
+
+ then:
+ thrown(ClassNotFoundException)
+
+ and:
+ 1 * parent.loadClass("someClass", false) >> { throw new ClassNotFoundException("broken") }
+ 0 * parent._
+
+ when:
+ classLoader.loadClass("someClass")
+
+ then:
+ thrown(ClassNotFoundException)
+
+ and:
+ 0 * parent._
+ }
+
+ def "visits self and parent"() {
+ def visitor = Mock(ClassLoaderVisitor)
+
+ when:
+ classLoader.visit(visitor)
+
+ then:
+ 1 * visitor.visitSpec({it instanceof CachingClassLoader.Spec})
+ 1 * visitor.visitParent(parent)
+ 0 * visitor._
+ }
+}
diff --git a/subprojects/base-services/src/test/groovy/org/gradle/internal/classloader/DefaultClassLoaderFactoryTest.groovy b/subprojects/base-services/src/test/groovy/org/gradle/internal/classloader/DefaultClassLoaderFactoryTest.groovy
new file mode 100644
index 0000000..13248fa
--- /dev/null
+++ b/subprojects/base-services/src/test/groovy/org/gradle/internal/classloader/DefaultClassLoaderFactoryTest.groovy
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.classloader
+
+import spock.lang.Specification
+
+class DefaultClassLoaderFactoryTest extends Specification {
+ final DefaultClassLoaderFactory factory = new DefaultClassLoaderFactory()
+ ClassLoader original
+
+ def setup() {
+ original = Thread.currentThread().contextClassLoader
+ }
+
+ def cleanup() {
+ Thread.currentThread().contextClassLoader = original
+ }
+
+ def "classes from specified URLs are visible in isolated ClassLoader"() {
+ when:
+ def cl = factory.createIsolatedClassLoader(classpath)
+ def c = cl.loadClass(DefaultClassLoaderFactoryTestHelper.name)
+
+ then:
+ c.name == DefaultClassLoaderFactoryTestHelper.name
+ c != DefaultClassLoaderFactoryTestHelper
+ }
+
+ def "application classes are not visible in isolated ClassLoader"() {
+ when:
+ def cl = factory.createIsolatedClassLoader(classpath)
+ cl.loadClass(Closure.name)
+
+ then:
+ thrown(ClassNotFoundException)
+ }
+
+ def "can use XML APIs from isolated ClassLoader when application classes include an XML provider"() {
+ assert ClassLoader.getSystemResource("META-INF/services/javax.xml.parsers.SAXParserFactory")
+
+ when:
+ def cl = factory.createIsolatedClassLoader(classpath)
+ def c = cl.loadClass(DefaultClassLoaderFactoryTestHelper.name)
+
+ then:
+ c != DefaultClassLoaderFactoryTestHelper
+
+ when:
+ Thread.currentThread().contextClassLoader = cl
+ c.newInstance().doStuff()
+
+ then:
+ notThrown()
+ }
+
+ def "can use XML APIs from filtering ClassLoader when application classes include an XML provider"() {
+ assert ClassLoader.getSystemResource("META-INF/services/javax.xml.parsers.SAXParserFactory")
+
+ when:
+ def cl = new URLClassLoader(classpath.collect { it.toURL() } as URL[], factory.createFilteringClassLoader(getClass().classLoader))
+ def c = cl.loadClass(DefaultClassLoaderFactoryTestHelper.name)
+
+ then:
+ c != DefaultClassLoaderFactoryTestHelper
+
+ when:
+ Thread.currentThread().contextClassLoader = cl
+ c.newInstance().doStuff()
+
+ then:
+ notThrown()
+ }
+
+ def getClasspath() {
+ return [ClasspathUtil.getClasspathForClass(DefaultClassLoaderFactoryTestHelper)].collect { it.toURI() }
+ }
+}
+
diff --git a/subprojects/base-services/src/test/groovy/org/gradle/internal/classloader/DefaultClassLoaderFactoryTestHelper.java b/subprojects/base-services/src/test/groovy/org/gradle/internal/classloader/DefaultClassLoaderFactoryTestHelper.java
new file mode 100644
index 0000000..d1d4ee0
--- /dev/null
+++ b/subprojects/base-services/src/test/groovy/org/gradle/internal/classloader/DefaultClassLoaderFactoryTestHelper.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.classloader;
+
+import javax.xml.XMLConstants;
+import javax.xml.datatype.DatatypeFactory;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.validation.SchemaFactory;
+import javax.xml.xpath.XPathFactory;
+
+public class DefaultClassLoaderFactoryTestHelper {
+ public void doStuff() throws Exception {
+ SAXParserFactory.newInstance().newSAXParser();
+ DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ DatatypeFactory.newInstance().newXMLGregorianCalendar();
+ TransformerFactory.newInstance().newTransformer();
+ SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+ XPathFactory.newInstance().newXPath();
+ }
+}
diff --git a/subprojects/base-services/src/test/groovy/org/gradle/internal/classloader/FilteringClassLoaderTest.groovy b/subprojects/base-services/src/test/groovy/org/gradle/internal/classloader/FilteringClassLoaderTest.groovy
new file mode 100644
index 0000000..9a7d5e8
--- /dev/null
+++ b/subprojects/base-services/src/test/groovy/org/gradle/internal/classloader/FilteringClassLoaderTest.groovy
@@ -0,0 +1,235 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.classloader
+
+import org.junit.Before
+import org.junit.Test
+import org.junit.runners.BlockJUnit4ClassRunner
+import spock.lang.Specification
+
+import static org.junit.Assert.fail
+
+class FilteringClassLoaderTest extends Specification {
+ private final FilteringClassLoader classLoader = new FilteringClassLoader(FilteringClassLoaderTest.class.getClassLoader())
+
+ void passesThroughSystemClasses() {
+ expect:
+ canLoadClass(String)
+ }
+
+ void passesThroughSystemPackages() {
+ expect:
+ canSeePackage('java.lang')
+ }
+
+ void passesThroughSystemResources() {
+ expect:
+ canSeeResource('com/sun/jndi/ldap/jndiprovider.properties')
+ }
+
+ void filtersClassesByDefault() {
+ given:
+ classLoader.parent.loadClass(Test.class.name)
+
+ when:
+ classLoader.loadClass(Test.class.name, false)
+
+ then:
+ ClassNotFoundException e = thrown()
+ e.message == "$Test.name not found."
+
+ when:
+ classLoader.loadClass(Test.class.name)
+
+ then:
+ ClassNotFoundException e2 = thrown()
+ e2.message == "$Test.name not found."
+ }
+
+ void filtersPackagesByDefault() {
+ given:
+ assert classLoader.parent.getPackage('org.junit') != null
+
+ expect:
+ cannotSeePackage('org.junit')
+ }
+
+ void filtersResourcesByDefault() {
+ given:
+ assert classLoader.parent.getResource('org/gradle/util/ClassLoaderTest.txt') != null
+
+ expect:
+ cannotSeeResource('org/gradle/util/ClassLoaderTest.txt')
+ }
+
+ void passesThroughClassesInSpecifiedPackagesAndSubPackages() {
+ given:
+ cannotLoadClass(Test)
+ cannotLoadClass(BlockJUnit4ClassRunner)
+
+ and:
+ classLoader.allowPackage('org.junit')
+
+ expect:
+ canLoadClass(Test)
+ canLoadClass(Before)
+ canLoadClass(BlockJUnit4ClassRunner)
+ }
+
+ void passesThroughSpecifiedClasses() {
+ given:
+ cannotLoadClass(Test)
+
+ and:
+ classLoader.allowClass(Test.class)
+
+ expect:
+ canLoadClass(Test)
+ cannotLoadClass(Before)
+ }
+
+ void filtersSpecifiedClasses() {
+ given:
+ cannotLoadClass(Test)
+ cannotLoadClass(Before)
+
+ and:
+ classLoader.allowPackage("org.junit")
+ classLoader.disallowClass("org.junit.Test")
+
+ expect:
+ canLoadClass(Before)
+ cannotLoadClass(Test)
+ }
+
+ void disallowClassWinsOverAllowClass() {
+ given:
+ classLoader.allowClass(Test)
+ classLoader.disallowClass(Test.name)
+
+ expect:
+ cannotLoadClass(Test)
+ }
+
+ void passesThroughSpecifiedPackagesAndSubPackages() {
+ given:
+ cannotSeePackage('org.junit')
+ cannotSeePackage('org.junit.runner')
+
+ and:
+ classLoader.allowPackage('org.junit')
+
+ expect:
+ canSeePackage('org.junit')
+ canSeePackage('org.junit.runner')
+ }
+
+ void passesThroughResourcesInSpecifiedPackages() {
+ given:
+ cannotSeeResource('org/gradle/util/ClassLoaderTest.txt')
+
+ classLoader.allowPackage('org.gradle')
+
+ expect:
+ canSeeResource('org/gradle/util/ClassLoaderTest.txt')
+ }
+
+ void passesThroughResourcesWithSpecifiedPrefix() {
+ given:
+ cannotSeeResource('org/gradle/util/ClassLoaderTest.txt')
+
+ and:
+ classLoader.allowResources('org/gradle')
+
+ expect:
+ canSeeResource('org/gradle/util/ClassLoaderTest.txt')
+ }
+
+ void passesThroughSpecifiedResources() {
+ given:
+ cannotSeeResource('org/gradle/util/ClassLoaderTest.txt')
+
+ and:
+ classLoader.allowResource('org/gradle/util/ClassLoaderTest.txt')
+
+ expect:
+ canSeeResource('org/gradle/util/ClassLoaderTest.txt')
+ }
+
+ void "visits self and parent"() {
+ def visitor = Mock(ClassLoaderVisitor)
+ given:
+ classLoader.allowClass(Test)
+ classLoader.allowPackage("org.junit")
+ classLoader.allowResource("a/b/c")
+ classLoader.disallowClass(Before.name)
+
+ when:
+ classLoader.visit(visitor)
+
+ then:
+ 1 * visitor.visitSpec({it instanceof FilteringClassLoader.Spec}) >> { FilteringClassLoader.Spec spec ->
+ spec.classNames == [Test.name]
+ spec.disallowedClassNames == [Before.name]
+ spec.packageNames == ["org.junit"]
+ spec.packagePrefixes == ["org.junit."]
+ spec.resourceNames == ["a/b/c"]
+ spec.resourcePrefixes == ["org/junit/"]
+ }
+ 1 * visitor.visitParent(classLoader.parent)
+ 0 * visitor._
+ }
+
+ void cannotSeeResource(String name) {
+ assert classLoader.getResource(name) == null
+ assert classLoader.getResourceAsStream(name) == null
+ assert !classLoader.getResources(name).hasMoreElements()
+ }
+
+ void canSeeResource(String name) {
+ assert classLoader.getResource(name) != null
+ def instr = classLoader.getResourceAsStream(name)
+ assert instr != null
+ instr.close()
+ assert classLoader.getResources(name).hasMoreElements()
+ }
+
+ void canSeePackage(String name) {
+ assert classLoader.getPackage(name) != null
+ assert classLoader.packages.any { it.name == name }
+ }
+
+ void cannotSeePackage(String name) {
+ assert classLoader.getPackage(name) == null
+ assert !classLoader.packages.any { it.name == name }
+ }
+
+ void canLoadClass(Class<?> clazz) {
+ assert classLoader.loadClass(clazz.name, false).is(clazz)
+ assert classLoader.loadClass(clazz.name).is(clazz)
+ }
+
+ void cannotLoadClass(Class<?> clazz) {
+ try {
+ classLoader.loadClass(clazz.name, false)
+ fail()
+ } catch (ClassNotFoundException expected) {}
+ try {
+ classLoader.loadClass(clazz.name)
+ fail()
+ } catch (ClassNotFoundException expected) {}
+ }
+}
diff --git a/subprojects/base-services/src/test/groovy/org/gradle/internal/classloader/MultiParentClassLoaderTest.groovy b/subprojects/base-services/src/test/groovy/org/gradle/internal/classloader/MultiParentClassLoaderTest.groovy
new file mode 100644
index 0000000..0faa891
--- /dev/null
+++ b/subprojects/base-services/src/test/groovy/org/gradle/internal/classloader/MultiParentClassLoaderTest.groovy
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.classloader
+
+import spock.lang.Specification
+
+class MultiParentClassLoaderTest extends Specification {
+ private ClassLoader parent1 = Mock()
+ private ClassLoader parent2 = Mock()
+ private MultiParentClassLoader loader = new MultiParentClassLoader(parent1, parent2)
+
+ public void parentsAreNotVisibleViaSuperClass() {
+ expect:
+ loader.parent == null
+ }
+
+ public void loadsClassFromParentsInOrderSpecified() {
+ given:
+ _ * parent1.loadClass('string') >> String
+ _ * parent1.loadClass('integer') >> { throw new ClassNotFoundException() }
+ _ * parent2.loadClass('integer') >> Integer
+
+ expect:
+ loader.loadClass('string') == String
+ loader.loadClass('string', true) == String
+ loader.loadClass('integer') == Integer
+ loader.loadClass('integer', true) == Integer
+ }
+
+ public void throwsCNFExceptionWhenClassNotFound() {
+ given:
+ _ * parent1.loadClass('string') >> { throw new ClassNotFoundException() }
+ _ * parent2.loadClass('string') >> { throw new ClassNotFoundException() }
+
+ when:
+ loader.loadClass('string')
+
+ then:
+ ClassNotFoundException e = thrown()
+ e.message == 'string not found.'
+ }
+
+ public void loadsPackageFromParentsInOrderSpecified() {
+ def stringPackage = String.class.getPackage()
+ def listPackage = List.class.getPackage()
+
+ given:
+ _ * parent1.getPackage('string') >> stringPackage
+ _ * parent1.getPackage('list') >> null
+ _ * parent2.getPackage('list') >> listPackage
+
+ expect:
+ loader.getPackage('string') == stringPackage
+ loader.getPackage('list') == listPackage
+ }
+
+ public void containsUnionOfPackagesFromAllParents() {
+ def package1 = Stub(Package)
+ def package2 = Stub(Package)
+ def package3 = Stub(Package)
+
+ given:
+ _ * parent1.getPackages() >> ([package1] as Package[])
+ _ * parent2.getPackages() >> ([package1, package2, package3] as Package[])
+
+ expect:
+ loader.getPackages() == [package1, package2, package3] as Package[]
+ }
+
+ public void loadsResourceFromParentsInOrderSpecified() {
+ URL resource1 = new File('res1').toURI().toURL()
+ URL resource2 = new File('res2').toURI().toURL()
+
+ given:
+ _ * parent1.getResource('resource1') >> resource1
+ _ * parent1.getResource('resource2') >> null
+ _ * parent2.getResource('resource2') >> resource2
+
+ expect:
+ loader.getResource('resource1') == resource1
+ loader.getResource('resource2') == resource2
+ }
+
+ public void containsUnionOfResourcesFromAllParents() {
+ URL resource1 = new File('res1').toURI().toURL()
+ URL resource2 = new File('res2').toURI().toURL()
+ URL resource3 = new File('res3').toURI().toURL()
+
+ given:
+ _ * parent1.getResources('resource') >> { return Collections.enumeration([resource1, resource2]) }
+ _ * parent2.getResources('resource') >> { return Collections.enumeration([resource1, resource3]) }
+
+ expect:
+ def resources = loader.getResources('resource').collect { it }
+ resources == [resource1, resource2, resource3]
+ }
+
+ public void visitsSelfAndParents() {
+ def visitor = Mock(ClassLoaderVisitor)
+
+ when:
+ loader.visit(visitor)
+
+ then:
+ 1 * visitor.visitSpec({it instanceof MultiParentClassLoader.Spec})
+ 1 * visitor.visitParent(parent1)
+ 1 * visitor.visitParent(parent2)
+ 0 * visitor._
+ }
+}
diff --git a/subprojects/base-services/src/test/groovy/org/gradle/internal/classloader/MutableURLClassLoaderTest.groovy b/subprojects/base-services/src/test/groovy/org/gradle/internal/classloader/MutableURLClassLoaderTest.groovy
new file mode 100644
index 0000000..5c04a80
--- /dev/null
+++ b/subprojects/base-services/src/test/groovy/org/gradle/internal/classloader/MutableURLClassLoaderTest.groovy
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.classloader
+
+import spock.lang.Specification
+
+class MutableURLClassLoaderTest extends Specification {
+ def "visits self and parent"() {
+ def visitor = Mock(ClassLoaderVisitor)
+ def parent = new ClassLoader(null) { }
+ def classPath = [new File("a").toURI().toURL(), new File("b").toURI().toURL()]
+ def cl = new MutableURLClassLoader(parent, classPath)
+
+ when:
+ cl.visit(visitor)
+
+ then:
+ 1 * visitor.visitSpec({it instanceof MutableURLClassLoader.Spec}) >> { MutableURLClassLoader.Spec spec ->
+ assert spec.classpath == classPath
+ }
+ 1 * visitor.visitClassPath(classPath)
+ 1 * visitor.visitParent(parent)
+ 0 * visitor._
+ }
+}
diff --git a/subprojects/base-services/src/test/groovy/org/gradle/internal/concurrent/ServiceLifecycleTest.groovy b/subprojects/base-services/src/test/groovy/org/gradle/internal/concurrent/ServiceLifecycleTest.groovy
new file mode 100644
index 0000000..c25ec4d
--- /dev/null
+++ b/subprojects/base-services/src/test/groovy/org/gradle/internal/concurrent/ServiceLifecycleTest.groovy
@@ -0,0 +1,203 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.concurrent
+
+import org.gradle.test.fixtures.concurrent.ConcurrentSpec
+
+class ServiceLifecycleTest extends ConcurrentSpec {
+ def lifecycle = new ServiceLifecycle("[service]")
+
+ def "can use service when not stopped"() {
+ def action = Mock(Runnable)
+
+ when:
+ lifecycle.use(action)
+
+ then:
+ 1 * action.run()
+ 0 * _._
+ }
+
+ def "can use service concurrently from multiple threads"() {
+ given:
+ def action1 = {
+ instant.action1Started
+ thread.blockUntil.action2Done
+ instant.action1Done
+ }
+ def action2 = {
+ thread.blockUntil.action1Started
+ instant.action2Done
+ }
+
+ when:
+ async {
+ start {
+ lifecycle.use(action1)
+ }
+ start {
+ lifecycle.use(action2)
+ }
+ }
+
+ then:
+ instant.action1Done > instant.action2Done
+ }
+
+ def "can stop multiple times"() {
+ when:
+ lifecycle.stop()
+ lifecycle.stop()
+ lifecycle.requestStop()
+ lifecycle.requestStop()
+ lifecycle.stop()
+
+ then:
+ noExceptionThrown()
+ }
+
+ def "throws exception when attempting to use service after it has stopped"() {
+ when:
+ lifecycle.stop()
+ lifecycle.use { }
+
+ then:
+ IllegalStateException e = thrown()
+ e.message == 'Cannot use [service] as it has been stopped.'
+ }
+
+ def "throws exception when attempting to use service after stop has been requested"() {
+ when:
+ lifecycle.requestStop()
+ lifecycle.use { }
+
+ then:
+ IllegalStateException e = thrown()
+ e.message == 'Cannot use [service] as it has been stopped.'
+ }
+
+ def "throws exception when attempting to use service while it is stopping"() {
+ when:
+ async {
+ start {
+ lifecycle.use {
+ lifecycle.requestStop()
+ instant.stopRequested
+ thread.block()
+ }
+ }
+ thread.blockUntil.stopRequested
+ lifecycle.use {}
+ }
+
+ then:
+ IllegalStateException e = thrown()
+ e.message == 'Cannot use [service] as it is currently stopping.'
+ }
+
+ def "stop() blocks while service is in use"() {
+ when:
+ async {
+ start {
+ lifecycle.use {
+ instant.running
+ thread.block()
+ instant.finished
+ }
+ }
+ thread.blockUntil.running
+ lifecycle.stop()
+ instant.stopped
+ }
+
+ then:
+ instant.finished < instant.stopped
+ }
+
+ def "requestStop() does not block while service is in use"() {
+ when:
+ async {
+ start {
+ lifecycle.use {
+ instant.running
+ thread.blockUntil.requested
+ instant.finished
+ }
+ }
+ thread.blockUntil.running
+ lifecycle.requestStop()
+ instant.requested
+ }
+
+ then:
+ instant.requested < instant.finished
+ }
+
+ def "cannot call stop() from thread that is using service"() {
+ when:
+ lifecycle.use {
+ lifecycle.stop()
+ }
+
+ then:
+ IllegalStateException e = thrown()
+ e.message == 'Cannot stop [service] from a thread that is using it.'
+ }
+
+ def "usage is re-entrant"() {
+ when:
+ async {
+ start {
+ lifecycle.use {
+ instant.running
+ lifecycle.use {
+ lifecycle.use { }
+ thread.block()
+ }
+ instant.finished
+ }
+ }
+ thread.blockUntil.running
+ lifecycle.stop()
+ instant.stopped
+ }
+
+ then:
+ instant.finished < instant.stopped
+ }
+
+ def "can call requestStop() from thread that is using service"() {
+ when:
+ async {
+ start {
+ lifecycle.use {
+ lifecycle.requestStop()
+ instant.stopRequested
+ thread.block()
+ instant.finished
+ }
+ }
+
+ thread.blockUntil.stopRequested
+ lifecycle.stop()
+ instant.stopped
+ }
+
+ then:
+ instant.finished < instant.stopped
+ }
+}
diff --git a/subprojects/base-services/src/test/groovy/org/gradle/internal/jvm/JvmTest.groovy b/subprojects/base-services/src/test/groovy/org/gradle/internal/jvm/JvmTest.groovy
index 91f81b2..8f9ca5b 100644
--- a/subprojects/base-services/src/test/groovy/org/gradle/internal/jvm/JvmTest.groovy
+++ b/subprojects/base-services/src/test/groovy/org/gradle/internal/jvm/JvmTest.groovy
@@ -26,7 +26,11 @@ import spock.lang.Specification
class JvmTest extends Specification {
@Rule TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider()
@Rule SetSystemProperties sysProp = new SetSystemProperties()
- OperatingSystem os = Mock()
+ OperatingSystem os = Mock() {
+ getExecutableName(_) >> { String name ->
+ return "${name}.exe"
+ }
+ }
OperatingSystem theOs = OperatingSystem.current()
Jvm getJvm() {
@@ -48,104 +52,213 @@ class JvmTest extends Specification {
7 | 5 | 6
}
- def "looks for runtime Jar in Java home directory"() {
- TestFile javaHomeDir = tmpDir.createDir('jdk')
- TestFile runtimeJar = javaHomeDir.file('lib/rt.jar').createFile()
- System.properties['java.home'] = javaHomeDir.absolutePath
-
- expect:
- jvm.javaHome == javaHomeDir
- jvm.runtimeJar == runtimeJar
- }
+ def "locates JDK and JRE installs when java.home points to a typical JRE installation embedded in a JDK installation"() {
+ given:
+ TestFile software = tmpDir.createDir('software')
+ software.create {
+ jdk {
+ lib {
+ file 'tools.jar'
+ }
+ bin {
+ file 'java.exe'
+ file 'javac.exe'
+ file 'javadoc.exe'
+ }
+ jre {
+ lib { file 'rt.jar' }
+ bin { file 'java.exe' }
+ }
+ }
+ }
- def "looks for tools Jar in Java home directory"() {
- TestFile javaHomeDir = tmpDir.createDir('jdk')
- TestFile toolsJar = javaHomeDir.file('lib/tools.jar').createFile()
- System.properties['java.home'] = javaHomeDir.absolutePath
+ when:
+ System.properties['java.home'] = software.file('jdk/jre').absolutePath
- expect:
- jvm.javaHome == javaHomeDir
- jvm.toolsJar == toolsJar
+ then:
+ jvm.javaHome == software.file('jdk')
+ jvm.runtimeJar == software.file('jdk/jre/lib/rt.jar')
+ jvm.toolsJar == software.file('jdk/lib/tools.jar')
+ jvm.javaExecutable == software.file('jdk/bin/java.exe')
+ jvm.javacExecutable == software.file('jdk/bin/javac.exe')
+ jvm.javadocExecutable == software.file('jdk/bin/javadoc.exe')
+ jvm.jre.homeDir == software.file('jdk/jre')
+ jvm.standaloneJre == null
}
- def "provides information when typical jdk installed"() {
+ def "locates JDK and JRE installs when java.home points to a typical JDK installation"() {
given:
TestFile software = tmpDir.createDir('software')
software.create {
jdk {
- jre { lib { file 'rt.jar' }}
- lib { file 'tools.jar'}
+ lib {
+ file 'tools.jar'
+ }
+ bin {
+ file 'java.exe'
+ file 'javac.exe'
+ file 'javadoc.exe'
+ }
+ jre {
+ lib { file 'rt.jar' }
+ bin { file 'java.exe' }
+ }
}
}
when:
- System.properties['java.home'] = software.file('jdk/jre').absolutePath
+ System.properties['java.home'] = software.file('jdk').absolutePath
then:
- jvm.javaHome.absolutePath == software.file('jdk').absolutePath
+ jvm.javaHome == software.file('jdk')
jvm.runtimeJar == software.file('jdk/jre/lib/rt.jar')
jvm.toolsJar == software.file('jdk/lib/tools.jar')
+ jvm.javaExecutable == software.file('jdk/bin/java.exe')
+ jvm.javacExecutable == software.file('jdk/bin/javac.exe')
+ jvm.javadocExecutable == software.file('jdk/bin/javadoc.exe')
+ jvm.jre.homeDir == software.file('jdk/jre')
+ jvm.standaloneJre == null
}
- def "provides information when typical jre installed"() {
+ def "locates JDK and JRE installs when java.home points to a typical standalone JRE installation"() {
given:
TestFile software = tmpDir.createDir('software')
software.create {
- jre { lib { file 'rt.jar' }}
+ jre {
+ bin { file 'java.exe' }
+ lib { file 'rt.jar' }
+ }
}
when:
System.properties['java.home'] = software.file('jre').absolutePath
then:
- jvm.javaHome.absolutePath == software.file('jre').absolutePath
+ jvm.javaHome == software.file('jre')
jvm.runtimeJar == software.file('jre/lib/rt.jar')
jvm.toolsJar == null
+ jvm.javaExecutable == software.file('jre/bin/java.exe')
+ jvm.javacExecutable == new File('javac.exe')
+ jvm.javadocExecutable == new File('javadoc.exe')
+ jvm.jre.homeDir == software.file('jre')
+ jvm.standaloneJre.homeDir == software.file('jre')
}
- def "looks for tools Jar in parent of JRE's Java home directory"() {
- TestFile javaHomeDir = tmpDir.createDir('jdk')
- TestFile toolsJar = javaHomeDir.file('lib/tools.jar').createFile()
- System.properties['java.home'] = javaHomeDir.file('jre').absolutePath
+ def "locates JDK and JRE installs when java.home points to a typical standalone JRE installation on Windows"() {
+ given:
+ TestFile software = tmpDir.createDir('software')
+ software.create {
+ "${jreDirName}" {
+ bin { file 'java.exe' }
+ lib { file 'rt.jar' }
+ }
+ "${jdkDirName}" {
+ bin {
+ file 'java.exe'
+ file 'javac.exe'
+ file 'javadoc.exe'
+ }
+ lib { file 'tools.jar' }
+ }
+ }
+ def jreDir = software.file(jreDirName)
+ def jdkDir = software.file(jdkDirName)
+
+ and:
+ _ * os.windows >> true
- expect:
- def jvm = new Jvm(os)
- jvm.javaHome == javaHomeDir
- jvm.toolsJar == toolsJar
+ when:
+ System.properties['java.home'] = jreDir.absolutePath
+ System.properties['java.version'] = version
+
+ then:
+ jvm.javaHome == jdkDir
+ jvm.runtimeJar == jreDir.file("lib/rt.jar")
+ jvm.toolsJar == jdkDir.file("lib/tools.jar")
+ jvm.javaExecutable == jdkDir.file('bin/java.exe')
+ jvm.javacExecutable == jdkDir.file('bin/javac.exe')
+ jvm.javadocExecutable == jdkDir.file('bin/javadoc.exe')
+ jvm.jre.homeDir == jreDir
+ jvm.standaloneJre.homeDir == jreDir
+
+ where:
+ version | jreDirName | jdkDirName
+ '1.6.0' | 'jre6' | 'jdk1.6.0'
+ '1.5.0_22' | 'jre1.5.0_22' | 'jdk1.5.0_22'
}
- def "looks for tools Jar in sibling of JRE's Java home directory on Windows"() {
- TestFile javaHomeDir = tmpDir.createDir('jdk1.6.0')
- TestFile toolsJar = javaHomeDir.file('lib/tools.jar').createFile()
- System.properties['java.home'] = tmpDir.createDir('jre6').absolutePath
- System.properties['java.version'] = '1.6.0'
+ def "locates JDK and JRE installs when java.home points to a typical JDK installation on Windows"() {
+ given:
+ TestFile software = tmpDir.createDir('software')
+ software.create {
+ "${jreDirName}" {
+ bin { file 'java.exe' }
+ lib {
+ file 'rt.jar'
+ }
+ }
+ "${jdkDirName}" {
+ bin {
+ file 'java.exe'
+ file 'javac.exe'
+ file 'javadoc.exe'
+ }
+ jre {
+ lib {
+ file 'rt.jar'
+ }
+ }
+ lib {
+ file 'tools.jar'
+ }
+ }
+ }
+ def jreDir = software.file(jreDirName)
+ def jdkDir = software.file(jdkDirName)
+
+ and:
_ * os.windows >> true
- expect:
- jvm.javaHome == javaHomeDir
- jvm.toolsJar == toolsJar
+ when:
+ System.properties['java.home'] = jdkDir.absolutePath
+ System.properties['java.version'] = version
+
+ then:
+ jvm.javaHome == jdkDir
+ jvm.runtimeJar == jdkDir.file("jre/lib/rt.jar")
+ jvm.toolsJar == jdkDir.file("lib/tools.jar")
+ jvm.javaExecutable == jdkDir.file('bin/java.exe')
+ jvm.javacExecutable == jdkDir.file('bin/javac.exe')
+ jvm.javadocExecutable == jdkDir.file('bin/javadoc.exe')
+ jvm.jre.homeDir == jdkDir.file('jre')
+ jvm.standaloneJre.homeDir == jreDir
+
+ where:
+ version | jreDirName | jdkDirName
+ '1.6.0' | 'jre6' | 'jdk1.6.0'
+ '1.5.0_22' | 'jre1.5.0_22' | 'jdk1.5.0_22'
}
- def "uses system property to locate Java home directory when tools Jar not found"() {
- TestFile javaHomeDir = tmpDir.createDir('jdk')
- System.properties['java.home'] = javaHomeDir.absolutePath
+ def "uses system property to determine if Sun/Oracle JVM"() {
+ when:
+ System.properties['java.vm.vendor'] = 'Sun'
+ def jvm = Jvm.create(null)
- expect:
- jvm.javaHome == javaHomeDir
- jvm.toolsJar == null
+ then:
+ jvm.getClass() == Jvm
}
def "uses system property to determine if Apple JVM"() {
when:
System.properties['java.vm.vendor'] = 'Apple Inc.'
- def jvm = Jvm.current()
+ def jvm = Jvm.create(null)
then:
jvm.getClass() == Jvm.AppleJvm
when:
System.properties['java.vm.vendor'] = 'Sun'
- jvm = Jvm.current()
+ jvm = Jvm.create(null)
then:
jvm.getClass() == Jvm
@@ -154,13 +267,13 @@ class JvmTest extends Specification {
def "uses system property to determine if IBM JVM"() {
when:
System.properties['java.vm.vendor'] = 'IBM Corporation'
- def jvm = Jvm.current()
+ def jvm = Jvm.create(null)
then:
jvm.getClass() == Jvm.IbmJvm
}
- def "finds executable if for java home supplied"() {
+ def "finds executable for java home supplied"() {
System.properties['java.vm.vendor'] = 'Sun'
when:
@@ -176,7 +289,7 @@ class JvmTest extends Specification {
then:
home.file(theOs.getExecutableName("jre/bin/javadoc")).absolutePath ==
- Jvm.forHome(home.file("jre")).getExecutable("javadoc").absolutePath
+ Jvm.forHome(home.file("jre")).getExecutable("javadoc").absolutePath
}
def "finds tools.jar if java home supplied"() {
@@ -193,7 +306,7 @@ class JvmTest extends Specification {
then:
home.file("jdk/lib/tools.jar").absolutePath ==
- Jvm.forHome(home.file("jdk")).toolsJar.absolutePath
+ Jvm.forHome(home.file("jdk")).toolsJar.absolutePath
}
def "provides decent feedback if executable not found"() {
@@ -215,8 +328,7 @@ class JvmTest extends Specification {
given:
def home = tmpDir.createDir("home")
System.properties['java.home'] = home.absolutePath
- 1 * os.getExecutableName(_ as String) >> "foobar.exe"
- 1 * os.findInPath("foobar") >> new File('/path/foobar.exe')
+ _ * os.findInPath("foobar") >> new File('/path/foobar.exe')
when:
def exec = jvm.getExecutable("foobar")
@@ -259,7 +371,7 @@ class JvmTest extends Specification {
then:
thrown(IllegalArgumentException)
}
-
+
def "describes accurately when created for supplied java home"() {
when:
def jvm = new Jvm(theOs, new File('dummyFolder'))
diff --git a/subprojects/base-services/src/test/groovy/org/gradle/internal/os/OperatingSystemTest.groovy b/subprojects/base-services/src/test/groovy/org/gradle/internal/os/OperatingSystemTest.groovy
index 71e41da..c9adf6a 100644
--- a/subprojects/base-services/src/test/groovy/org/gradle/internal/os/OperatingSystemTest.groovy
+++ b/subprojects/base-services/src/test/groovy/org/gradle/internal/os/OperatingSystemTest.groovy
@@ -61,6 +61,9 @@ class OperatingSystemTest extends Specification {
os.getScriptName("a.bat") == "a.bat"
os.getScriptName("a.BAT") == "a.BAT"
os.getScriptName("a") == "a.bat"
+ os.getScriptName("a.exe") == "a.bat"
+ os.getScriptName("a.b/c") == "a.b/c.bat"
+ os.getScriptName("a.b\\c") == "a.b\\c.bat"
}
def "windows transforms executable names"() {
@@ -70,6 +73,9 @@ class OperatingSystemTest extends Specification {
os.getExecutableName("a.exe") == "a.exe"
os.getExecutableName("a.EXE") == "a.EXE"
os.getExecutableName("a") == "a.exe"
+ os.getExecutableName("a.bat") == "a.exe"
+ os.getExecutableName("a.b/c") == "a.b/c.exe"
+ os.getExecutableName("a.b\\c") == "a.b\\c.exe"
}
def "windows transforms shared library names"() {
@@ -79,6 +85,21 @@ class OperatingSystemTest extends Specification {
os.getSharedLibraryName("a.dll") == "a.dll"
os.getSharedLibraryName("a.DLL") == "a.DLL"
os.getSharedLibraryName("a") == "a.dll"
+ os.getSharedLibraryName("a.lib") == "a.dll"
+ os.getSharedLibraryName("a.b/c") == "a.b/c.dll"
+ os.getSharedLibraryName("a.b\\c") == "a.b\\c.dll"
+ }
+
+ def "windows transforms static library names"() {
+ def os = new OperatingSystem.Windows()
+
+ expect:
+ os.getStaticLibraryName("a.lib") == "a.lib"
+ os.getStaticLibraryName("a.LIB") == "a.LIB"
+ os.getStaticLibraryName("a") == "a.lib"
+ os.getStaticLibraryName("a.dll") == "a.lib"
+ os.getStaticLibraryName("a.b/c") == "a.b/c.lib"
+ os.getStaticLibraryName("a.b\\c") == "a.b\\c.lib"
}
def "windows searches for executable in path"() {
@@ -178,6 +199,18 @@ class OperatingSystemTest extends Specification {
os.getSharedLibraryName("path/a") == "path/liba.so"
}
+ def "UNIX transforms static library names"() {
+ def os = new OperatingSystem.Unix()
+
+ expect:
+ os.getStaticLibraryName("a.a") == "a.a"
+ os.getStaticLibraryName("liba.a") == "liba.a"
+ os.getStaticLibraryName("a") == "liba.a"
+ os.getStaticLibraryName("lib1") == "liblib1.a"
+ os.getStaticLibraryName("path/liba.a") == "path/liba.a"
+ os.getStaticLibraryName("path/a") == "path/liba.a"
+ }
+
def "UNIX searches for executable in path"() {
def exe = tmpDir.createFile("bin/a")
tmpDir.createFile("bin2/a")
diff --git a/subprojects/base-services/src/test/groovy/org/gradle/internal/reflect/JavaReflectionUtilTest.groovy b/subprojects/base-services/src/test/groovy/org/gradle/internal/reflect/JavaReflectionUtilTest.groovy
index 94995e5..0740a60 100644
--- a/subprojects/base-services/src/test/groovy/org/gradle/internal/reflect/JavaReflectionUtilTest.groovy
+++ b/subprojects/base-services/src/test/groovy/org/gradle/internal/reflect/JavaReflectionUtilTest.groovy
@@ -14,67 +14,261 @@
* limitations under the License.
*/
-package org.gradle.internal.reflect;
+package org.gradle.internal.reflect
-import spock.lang.Specification
+import org.gradle.api.specs.Spec
import org.gradle.internal.UncheckedException
+import spock.lang.Specification
+
+import java.lang.annotation.Inherited
+import java.lang.annotation.Retention
+import java.lang.annotation.RetentionPolicy
+
+import static org.gradle.internal.reflect.JavaReflectionUtil.*
class JavaReflectionUtilTest extends Specification {
- def myProperties = new MyProperties()
+ JavaTestSubject myProperties = new JavaTestSubject()
+
+ def "read field"() {
+ expect:
+ readField(new JavaTestSubject(), boolean.class, "myBooleanProp")
+ readField(new JavaTestSubject(), String.class, "myProp") == "myValue"
+ readField(new JavaTestSubjectSubclass(), boolean.class, "myBooleanProp")
+ readField(new JavaTestSubjectSubclass(), String.class, "myProp") == "subclass"
+
+ when:
+ readField(new JavaTestSubject(), String.class, "myBooleanProp")
+
+ then:
+ def e = thrown UncheckedException
+ e.cause instanceof NoSuchFieldException
+
+ when:
+ readField(new JavaTestSubject(), String.class, "non existent")
+
+ then:
+ e = thrown UncheckedException
+ e.cause instanceof NoSuchFieldException
+
+ when:
+ readField(new JavaTestSubjectSubclass(), String.class, "non existent")
+
+ then:
+ e = thrown UncheckedException
+ e.cause instanceof NoSuchFieldException
+ }
+
+ def "property exists"() {
+ expect:
+ propertyExists(new JavaTestSubject(), "myBooleanProperty")
+ propertyExists(new JavaTestSubject(), "myProperty")
+ propertyExists(new JavaTestSubject(), "publicField")
+ !propertyExists(new JavaTestSubject(), "myBooleanProp")
+ !propertyExists(new JavaTestSubject(), "protectedProperty")
+ !propertyExists(new JavaTestSubject(), "privateProperty")
+
+ and:
+ propertyExists(new JavaTestSubjectSubclass(), "myBooleanProperty")
+ propertyExists(new JavaTestSubjectSubclass(), "myProperty")
+ propertyExists(new JavaTestSubjectSubclass(), "publicField")
+ !propertyExists(new JavaTestSubjectSubclass(), "myBooleanProp")
+ !propertyExists(new JavaTestSubjectSubclass(), "protectedProperty")
+ !propertyExists(new JavaTestSubjectSubclass(), "privateProperty")
+
+ and:
+ propertyExists(new JavaTestSubjectSubclass(), "subclassBoolean")
+ }
+
+ def "readable properties"() {
+ expect:
+ def properties = readableProperties(JavaTestSubjectSubclass)
+ properties.size() == 5
+ properties.class
+ properties.myProperty
+ properties.myBooleanProperty
+ properties.myOtherBooleanProperty
+ properties.subclassBoolean
+ }
def "read property"() {
expect:
- JavaReflectionUtil.readProperty(myProperties, "myProperty") == "myValue"
+ readableProperty(JavaTestSubject, "myProperty").getValue(myProperties) == "myValue"
}
def "write property"() {
when:
- JavaReflectionUtil.writeProperty(myProperties, "myProperty", "otherValue")
+ writeableProperty(JavaTestSubject, "myProperty").setValue(myProperties, "otherValue")
then:
- JavaReflectionUtil.readProperty(myProperties, "myProperty") == "otherValue"
+ readableProperty(JavaTestSubject, "myProperty").getValue(myProperties) == "otherValue"
}
def "read boolean property"() {
expect:
- JavaReflectionUtil.readProperty(myProperties, "myBooleanProperty") == true
+ readableProperty(JavaTestSubject, "myBooleanProperty").getValue(myProperties) == true
}
def "write boolean property"() {
when:
- JavaReflectionUtil.writeProperty(myProperties, "myBooleanProperty", false)
+ writeableProperty(JavaTestSubject, "myBooleanProperty").setValue(myProperties, false)
+
+ then:
+ readableProperty(JavaTestSubject, "myBooleanProperty").getValue(myProperties) == false
+ }
+
+ def "read property that doesn't have a well formed getter"() {
+ when:
+ readableProperty(JavaTestSubject, property)
+
+ then:
+ NoSuchPropertyException e = thrown()
+ e.message == "Could not find getter method for property '${property}' on class JavaTestSubject."
+
+ where:
+ property | _
+ "doesNotExist" | _
+ "notABooleanProperty" | _
+ "staticProperty" | _
+ "paramProperty" | _
+ "voidProperty" | _
+ "writeOnly" | _
+ }
+
+ def "read property that is not public"() {
+ when:
+ readableProperty(JavaTestSubject, property)
then:
- JavaReflectionUtil.readProperty(myProperties, "myBooleanProperty") == false
+ NoSuchPropertyException e = thrown()
+ e.message == "Could not find getter method for property '${property}' on class JavaTestSubject."
+
+ where:
+ property | _
+ "privateProperty" | _
+ "protectedProperty" | _
}
- def "read property that doesn't exist"() {
+ def "write property that doesn't have a well formed setter"() {
when:
- JavaReflectionUtil.readProperty(myProperties, "unexisting")
+ writeableProperty(JavaTestSubject, property)
then:
- UncheckedException e = thrown()
- e.cause instanceof NoSuchMethodException
+ NoSuchPropertyException e = thrown()
+ e.message == "Could not find setter method for property '${property}' on class JavaTestSubject."
+
+ where:
+ property | _
+ "doesNotExist" | _
+ "myOtherBooleanProperty" | _
+ "staticProperty" | _
+ "paramProperty" | _
}
- def "write property that doesn't exist"() {
+ def "write property that is not public"() {
when:
- JavaReflectionUtil.writeProperty(myProperties, "unexisting", "someValue")
+ writeableProperty(JavaTestSubject, property)
then:
- UncheckedException e = thrown()
- e.cause instanceof NoSuchMethodException
+ NoSuchPropertyException e = thrown()
+ e.message == "Could not find setter method for property '${property}' on class JavaTestSubject."
+
+ where:
+ property | _
+ "privateProperty" | _
+ "protectedProperty" | _
}
- static class MyProperties {
- private String myProp = "myValue"
- private boolean myBooleanProp = true
+ def "call methods successfully reflectively"() {
+ expect:
+ method(myProperties.class, String, "getMyProperty").invoke(myProperties) == myProperties.myProp
- String getMyProperty() { myProp }
- void setMyProperty(String value) { myProp = value }
+ when:
+ method(myProperties.class, Void, "setMyProperty", String).invoke(myProperties, "foo")
- boolean isMyBooleanProperty() { myBooleanProp }
- void setMyBooleanProperty(boolean value) { myBooleanProp = value }
+ then:
+ method(myProperties.class, String, "getMyProperty").invoke(myProperties) == "foo"
}
+
+ def "call failing methods reflectively"() {
+ when:
+ method(myProperties.class, Void, "throwsException").invoke(myProperties)
+
+ then:
+ thrown IllegalStateException
+ }
+
+ def "call declared method that may not be public"() {
+ expect:
+ method(JavaTestSubjectSubclass, String, "protectedMethod").invoke(new JavaTestSubjectSubclass()) == "parent"
+ method(JavaTestSubjectSubclass, String, "overridden").invoke(new JavaTestSubjectSubclass()) == "subclass"
+ }
+
+ def "find method"() {
+ expect:
+ findMethod(String, { it.name == "toString" } as Spec) == String.declaredMethods.find { it.name == "toString" }
+ findMethod(String, { it.name == "getClass" } as Spec) == Object.declaredMethods.find { it.name == "getClass" }
+ }
+
+ def "get annotation"() {
+ expect:
+ getAnnotation(Root, InheritedAnnotation).value() == "default"
+ getAnnotation(Subclass, InheritedAnnotation).value() == "default"
+ getAnnotation(RootInterface, InheritedAnnotation).value() == "default"
+ getAnnotation(SubInterface, InheritedAnnotation).value() == "default"
+
+ getAnnotation(Root, NotInheritedAnnotation).value() == "default"
+ getAnnotation(Subclass, NotInheritedAnnotation) == null
+ getAnnotation(RootInterface, NotInheritedAnnotation).value() == "default"
+ getAnnotation(SubInterface, NotInheritedAnnotation) == null
+
+ getAnnotation(ImplementsRootInterface, InheritedAnnotation).value() == "default"
+ getAnnotation(ImplementsRootInterface, NotInheritedAnnotation) == null
+ getAnnotation(ImplementsSubInterface, InheritedAnnotation).value() == "default"
+ getAnnotation(ImplementsSubInterface, NotInheritedAnnotation) == null
+ getAnnotation(ImplementsBoth, InheritedAnnotation).value() == "default"
+ getAnnotation(ImplementsBoth, NotInheritedAnnotation) == null
+
+ getAnnotation(OverrideFirst, InheritedAnnotation).value() == "HasAnnotations"
+ getAnnotation(OverrideLast, InheritedAnnotation).value() == "default"
+
+ getAnnotation(InheritsInterface, InheritedAnnotation).value() == "default"
+ getAnnotation(InheritsInterface, NotInheritedAnnotation) == null
+ }
+
+}
+
+ at Retention(RetentionPolicy.RUNTIME)
+ at Inherited
+ at interface InheritedAnnotation {
+ String value() default "default"
}
+ at Retention(RetentionPolicy.RUNTIME)
+ at interface NotInheritedAnnotation {
+ String value() default "default"
+}
+
+ at InheritedAnnotation
+ at NotInheritedAnnotation
+class Root {}
+
+class Subclass extends Root {}
+
+ at InheritedAnnotation
+ at NotInheritedAnnotation
+interface RootInterface {}
+
+interface SubInterface extends RootInterface {}
+
+class ImplementsRootInterface implements RootInterface {}
+class ImplementsSubInterface implements SubInterface {}
+class ImplementsBoth implements RootInterface, SubInterface {}
+
+ at InheritedAnnotation(value = "HasAnnotations")
+interface HasAnnotations {}
+
+class OverrideFirst implements HasAnnotations, RootInterface, SubInterface {}
+class OverrideLast implements RootInterface, SubInterface, HasAnnotations {}
+
+class SuperWithInterface implements RootInterface {}
+class InheritsInterface extends SuperWithInterface {}
\ No newline at end of file
diff --git a/subprojects/base-services/src/test/groovy/org/gradle/internal/reflect/JavaTestSubject.java b/subprojects/base-services/src/test/groovy/org/gradle/internal/reflect/JavaTestSubject.java
new file mode 100644
index 0000000..27eb899
--- /dev/null
+++ b/subprojects/base-services/src/test/groovy/org/gradle/internal/reflect/JavaTestSubject.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.reflect;
+
+ at SuppressWarnings("UnusedDeclaration")
+public class JavaTestSubject {
+
+ private String myProp = "myValue";
+ private boolean myBooleanProp = true;
+
+ public int publicField;
+
+ public String getMyProperty() {
+ return myProp;
+ }
+
+ public void setMyProperty(String value) {
+ myProp = value;
+ }
+
+ public boolean isMyBooleanProperty() {
+ return myBooleanProp;
+ }
+
+ public void setMyBooleanProperty(boolean value) {
+ myBooleanProp = value;
+ }
+
+ public boolean getMyOtherBooleanProperty() {
+ return true;
+ }
+
+ public String isNotABooleanProperty() {
+ return null;
+ }
+
+ public static String getStaticProperty() {
+ return null;
+ }
+
+ public static void setStaticProperty(String value) {
+ }
+
+ public void getVoidProperty() {
+ }
+
+ public String getParamProperty(String param) {
+ return null;
+ }
+
+ public void setParamProperty() {
+ }
+
+ public void setParamProperty(String param, String someOther) {
+ }
+
+ public void setWriteOnly(String param) {
+ }
+
+ public void throwsException() {
+ throw new IllegalStateException();
+ }
+
+ protected String protectedMethod() {
+ return "parent";
+ }
+
+ protected String overridden() {
+ return "parent";
+ }
+
+ protected String getProtectedProperty() {
+ return null;
+ }
+
+ protected void setProtectedProperty(String value) {
+ }
+
+ private String getPrivateProperty() {
+ return null;
+ }
+
+ private void setPrivateProperty(String value) {
+ }
+}
diff --git a/subprojects/base-services/src/test/groovy/org/gradle/internal/reflect/JavaTestSubjectSubclass.java b/subprojects/base-services/src/test/groovy/org/gradle/internal/reflect/JavaTestSubjectSubclass.java
new file mode 100644
index 0000000..f035d2f
--- /dev/null
+++ b/subprojects/base-services/src/test/groovy/org/gradle/internal/reflect/JavaTestSubjectSubclass.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.reflect;
+
+public class JavaTestSubjectSubclass extends JavaTestSubject {
+
+ private String myProp = "subclass";
+
+ @Override
+ protected String overridden() {
+ return "subclass";
+ }
+
+ public boolean getSubclassBoolean() {
+ return false;
+ }
+}
diff --git a/subprojects/base-services/src/test/groovy/org/gradle/internal/service/ServiceLocatorTest.groovy b/subprojects/base-services/src/test/groovy/org/gradle/internal/service/ServiceLocatorTest.groovy
index 0b91e05..da0c5ec 100644
--- a/subprojects/base-services/src/test/groovy/org/gradle/internal/service/ServiceLocatorTest.groovy
+++ b/subprojects/base-services/src/test/groovy/org/gradle/internal/service/ServiceLocatorTest.groovy
@@ -25,21 +25,21 @@ class ServiceLocatorTest extends Specification {
def serviceFile = stream('org.gradle.ImplClass')
when:
- def result = serviceLocator.findServiceImplementationClass(String.class)
+ def result = serviceLocator.findFactory(String.class).create()
then:
- result == String
- 1 * classLoader.getResource("META-INF/services/java.lang.String") >> serviceFile
+ result instanceof String
+ 1 * classLoader.getResources("META-INF/services/java.lang.String") >> Collections.enumeration([serviceFile])
1 * classLoader.loadClass('org.gradle.ImplClass') >> String
}
- def "findServiceImplementationClass() returns null when no service meta data resource available"() {
+ def "findFactory() returns null when no service meta data resource available"() {
when:
- def result = serviceLocator.findServiceImplementationClass(String.class)
+ def result = serviceLocator.findFactory(String.class)
then:
result == null
- 1 * classLoader.getResource("META-INF/services/java.lang.String") >> null
+ 1 * classLoader.getResources("META-INF/services/java.lang.String") >> Collections.enumeration([])
}
def "wraps implementation class load failure"() {
@@ -47,13 +47,13 @@ class ServiceLocatorTest extends Specification {
def failure = new ClassNotFoundException()
when:
- serviceLocator.findServiceImplementationClass(String.class)
+ serviceLocator.findFactory(String.class)
then:
RuntimeException e = thrown()
- e.message == "Could not load implementation class 'org.gradle.ImplClass' for service 'java.lang.String'."
+ e.message == "Could not load implementation class 'org.gradle.ImplClass' for service 'java.lang.String' specified in resource '${serviceFile}'."
e.cause == failure
- 1 * classLoader.getResource("META-INF/services/java.lang.String") >> serviceFile
+ 1 * classLoader.getResources("META-INF/services/java.lang.String") >> Collections.enumeration([serviceFile])
1 * classLoader.loadClass('org.gradle.ImplClass') >> { throw failure }
}
@@ -64,37 +64,51 @@ class ServiceLocatorTest extends Specification {
''')
when:
- def result = serviceLocator.findServiceImplementationClass(String.class)
+ def result = serviceLocator.findFactory(String.class).create()
then:
- result == String
- 1 * classLoader.getResource("META-INF/services/java.lang.String") >> serviceFile
+ result instanceof String
+ 1 * classLoader.getResources("META-INF/services/java.lang.String") >> Collections.enumeration([serviceFile])
1 * classLoader.loadClass('org.gradle.ImplClass') >> String
}
- def "findServiceImplementationClass() fails when no implementation class specified in service meta data resource"() {
+ def "can locate multiple service implementations from one resource file"() {
+ def serviceFile = stream("""org.gradle.ImplClass1
+org.gradle.ImplClass2""")
+
+ when:
+ def result = serviceLocator.getAll(String.class)
+
+ then:
+ result.size() == 2
+ 1 * classLoader.getResources("META-INF/services/java.lang.String") >> Collections.enumeration([serviceFile])
+ 1 * classLoader.loadClass('org.gradle.ImplClass1') >> String
+ 1 * classLoader.loadClass('org.gradle.ImplClass2') >> String
+ }
+
+ def "findFactory() fails when no implementation class specified in service meta data resource"() {
def serviceFile = stream('#empty!')
when:
- serviceLocator.findServiceImplementationClass(String.class)
+ serviceLocator.findFactory(String.class)
then:
RuntimeException e = thrown()
- e.message == "Could not determine implementation class for service 'java.lang.String'."
- e.cause.message == "No implementation class for service 'java.lang.String' specified in resource '${serviceFile}'."
- 1 * classLoader.getResource("META-INF/services/java.lang.String") >> serviceFile
+ e.message == "Could not determine implementation class for service 'java.lang.String' specified in resource '${serviceFile}'."
+ e.cause.message == "No implementation class for service 'java.lang.String' specified."
+ 1 * classLoader.getResources("META-INF/services/java.lang.String") >> Collections.enumeration([serviceFile])
}
- def "findServiceImplementationClass() fails when implementation class specified in service meta data resource is not assignable to service type"() {
+ def "findFactory() fails when implementation class specified in service meta data resource is not assignable to service type"() {
given:
implementationDeclared(String, Integer)
when:
- serviceLocator.findServiceImplementationClass(String)
+ serviceLocator.findFactory(String)
then:
RuntimeException e = thrown()
- e.message == "Could not load implementation class 'java.lang.Integer' for service 'java.lang.String'."
+ e.message.startsWith("Could not load implementation class 'java.lang.Integer' for service 'java.lang.String' specified in resource '")
e.cause.message == "Implementation class 'java.lang.Integer' is not assignable to service class 'java.lang.String'."
}
@@ -128,6 +142,7 @@ class ServiceLocatorTest extends Specification {
then:
UnknownServiceException e = thrown()
e.message == "Could not find meta-data resource 'META-INF/services/java.lang.CharSequence' for service 'java.lang.CharSequence'."
+ 1 * classLoader.getResources("META-INF/services/java.lang.CharSequence") >> Collections.enumeration([])
}
def "getFactory() returns a factory which creates instances of implementation class"() {
@@ -152,15 +167,7 @@ class ServiceLocatorTest extends Specification {
then:
UnknownServiceException e = thrown()
e.message == "Could not find meta-data resource 'META-INF/services/java.lang.CharSequence' for service 'java.lang.CharSequence'."
- }
-
- def stream(String contents) {
- URLStreamHandler handler = Mock()
- URLConnection connection = Mock()
- URL url = new URL("custom", "host", 12, "file", handler)
- _ * handler.openConnection(url) >> connection
- _ * connection.getInputStream() >> new ByteArrayInputStream(contents.bytes)
- return url
+ 1 * classLoader.getResources("META-INF/services/java.lang.CharSequence") >> Collections.enumeration([])
}
def "newInstance() creates instances of implementation class"() {
@@ -173,10 +180,77 @@ class ServiceLocatorTest extends Specification {
then:
result instanceof String
}
-
+
+ def "getAll() returns an instance of each declared implementation"() {
+ def impl1 = stream("org.gradle.Impl1")
+ def impl2 = stream("org.gradle.Impl2")
+
+ when:
+ def result = serviceLocator.getAll(CharSequence)
+
+ then:
+ result.size() == 2
+ result[0] instanceof String
+ result[1] instanceof StringBuilder
+ 1 * classLoader.getResources("META-INF/services/java.lang.CharSequence") >> Collections.enumeration([impl1, impl2])
+ 1 * classLoader.loadClass("org.gradle.Impl1") >> String
+ 1 * classLoader.loadClass("org.gradle.Impl2") >> StringBuilder
+ }
+
+ def "getAll() ignores duplicate implementation classes"() {
+ def impl1 = stream("org.gradle.Impl1")
+ def impl2 = stream("org.gradle.Impl2")
+ def impl3 = stream("org.gradle.Impl1")
+
+ when:
+ def result = serviceLocator.getAll(CharSequence)
+
+ then:
+ result.size() == 2
+ result[0] instanceof String
+ result[1] instanceof StringBuilder
+ 1 * classLoader.getResources("META-INF/services/java.lang.CharSequence") >> Collections.enumeration([impl1, impl2, impl3])
+ 1 * classLoader.loadClass("org.gradle.Impl1") >> String
+ 1 * classLoader.loadClass("org.gradle.Impl2") >> StringBuilder
+ }
+
+ def "getAll() returns empty collection no meta-data file found for service type"() {
+ when:
+ def result = serviceLocator.getAll(CharSequence)
+
+ then:
+ result.empty
+ 1 * classLoader.getResources("META-INF/services/java.lang.CharSequence") >> Collections.enumeration([])
+ }
+
+ def "servicelocator uses utf-8 encoding for reading serviceFile"() {
+ def serviceFile = stream(className)
+
+ when:
+ def result = serviceLocator.get(String.class)
+
+ then:
+ result instanceof String
+ 1 * classLoader.getResources("META-INF/services/java.lang.String") >> Collections.enumeration([serviceFile])
+ 1 * classLoader.loadClass(className) >> String
+
+ where:
+ className << ['org.gradle.κόσμε']
+ }
+
+
+ def stream(String contents) {
+ URLStreamHandler handler = Mock()
+ URLConnection connection = Mock()
+ URL url = new URL("custom", "host", 12, "file", handler)
+ _ * handler.openConnection(url) >> connection
+ _ * connection.getInputStream() >> new ByteArrayInputStream(contents.getBytes("UTF-8"))
+ return url
+ }
+
def implementationDeclared(Class<?> serviceType, Class<?> implementationType) {
def serviceFile = stream(implementationType.name)
- _ * classLoader.getResource("META-INF/services/${serviceType.name}") >> serviceFile
+ _ * classLoader.getResources("META-INF/services/${serviceType.name}") >> Collections.enumeration([serviceFile])
_ * classLoader.loadClass(implementationType.name) >> implementationType
}
}
diff --git a/subprojects/base-services/src/test/groovy/org/gradle/internal/service/SynchronizedServiceRegistryTest.groovy b/subprojects/base-services/src/test/groovy/org/gradle/internal/service/SynchronizedServiceRegistryTest.groovy
index 3623ccc..27427b5 100644
--- a/subprojects/base-services/src/test/groovy/org/gradle/internal/service/SynchronizedServiceRegistryTest.groovy
+++ b/subprojects/base-services/src/test/groovy/org/gradle/internal/service/SynchronizedServiceRegistryTest.groovy
@@ -19,9 +19,6 @@ package org.gradle.internal.service;
import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 11/24/11
- */
public class SynchronizedServiceRegistryTest extends Specification {
def delegate = Mock(ServiceRegistry)
diff --git a/subprojects/base-services/src/test/groovy/org/gradle/util/CollectionUtilsTest.groovy b/subprojects/base-services/src/test/groovy/org/gradle/util/CollectionUtilsTest.groovy
index d9b96e2..84a2d52 100644
--- a/subprojects/base-services/src/test/groovy/org/gradle/util/CollectionUtilsTest.groovy
+++ b/subprojects/base-services/src/test/groovy/org/gradle/util/CollectionUtilsTest.groovy
@@ -94,6 +94,11 @@ class CollectionUtilsTest extends Specification {
collect([1, 2, 3] as Object[], transformer { it * 2 }) == [2, 4, 6]
}
+ def "collect iterable"() {
+ expect:
+ collect([1, 2, 3] as Iterable, transformer { it * 2 }) == [2, 4, 6]
+ }
+
def "list stringize"() {
expect:
stringize([1, 2, 3]) == ["1", "2", "3"]
diff --git a/subprojects/base-services/src/test/groovy/org/gradle/util/JavaMethodTest.java b/subprojects/base-services/src/test/groovy/org/gradle/util/JavaMethodTest.java
new file mode 100644
index 0000000..225103b
--- /dev/null
+++ b/subprojects/base-services/src/test/groovy/org/gradle/util/JavaMethodTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.util;
+
+import org.gradle.internal.reflect.JavaReflectionUtil;
+import org.jmock.Expectations;
+import org.jmock.integration.junit4.JMock;
+import org.jmock.integration.junit4.JUnit4Mockery;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.sameInstance;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+ at RunWith(JMock.class)
+public class JavaMethodTest {
+ private final JUnit4Mockery context = new JUnit4Mockery();
+
+ @Test
+ public void invokesMethodOnObject() {
+ JavaMethod<CharSequence, CharSequence> method = JavaReflectionUtil.method(CharSequence.class, CharSequence.class, "subSequence", int.class, int.class);
+ assertThat(method.invoke("string", 0, 3), equalTo((CharSequence) "str"));
+ }
+
+ @Test
+ public void propagatesExceptionThrownByMethod() {
+ final CharSequence mock = context.mock(CharSequence.class);
+ final RuntimeException failure = new RuntimeException();
+ context.checking(new Expectations() {{
+ one(mock).subSequence(0, 3);
+ will(throwException(failure));
+ }});
+
+ JavaMethod<CharSequence, CharSequence> method = JavaReflectionUtil.method(CharSequence.class, CharSequence.class, "subSequence", int.class, int.class);
+ try {
+ method.invoke(mock, 0, 3);
+ fail();
+ } catch (RuntimeException e) {
+ assertThat(e, sameInstance(failure));
+ }
+ }
+
+ @Test
+ public void canAccessProtectedMethod() {
+ final Package[] packages = new Package[0];
+ ClassLoader classLoader = new ClassLoader() {
+ @Override
+ protected Package[] getPackages() {
+ return packages;
+ }
+ };
+
+ JavaMethod<ClassLoader, Package[]> method = JavaReflectionUtil.method(ClassLoader.class, Package[].class, "getPackages");
+ assertThat(method.invoke(classLoader), sameInstance(packages));
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/util/hash/HashValueTest.groovy b/subprojects/base-services/src/test/groovy/org/gradle/util/hash/HashValueTest.groovy
similarity index 100%
rename from subprojects/core/src/test/groovy/org/gradle/util/hash/HashValueTest.groovy
rename to subprojects/base-services/src/test/groovy/org/gradle/util/hash/HashValueTest.groovy
diff --git a/subprojects/core/src/test/resources/org/gradle/util/ClassLoaderTest.txt b/subprojects/base-services/src/test/resources/org/gradle/util/ClassLoaderTest.txt
similarity index 100%
rename from subprojects/core/src/test/resources/org/gradle/util/ClassLoaderTest.txt
rename to subprojects/base-services/src/test/resources/org/gradle/util/ClassLoaderTest.txt
diff --git a/subprojects/build-comparison/build-comparison.gradle b/subprojects/build-comparison/build-comparison.gradle
index 9dd01ef..7e80092 100644
--- a/subprojects/build-comparison/build-comparison.gradle
+++ b/subprojects/build-comparison/build-comparison.gradle
@@ -15,12 +15,14 @@
*/
dependencies {
- groovy libraries.groovy
+ compile libraries.groovy
+ compile project(":resources")
compile project(":core")
compile project(":toolingApi")
compile project(":reporting")
- compile project(":ide") // for FileOutcomeIdentifier enum
+ compile project(':plugins')
+ compile project(':ear')
compile libraries.guava
compile libraries.slf4j_api
diff --git a/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/gradle/CompareGradleBuilds.java b/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/gradle/CompareGradleBuilds.java
index c3f8da8..ede1389 100644
--- a/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/gradle/CompareGradleBuilds.java
+++ b/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/gradle/CompareGradleBuilds.java
@@ -18,7 +18,7 @@ package org.gradle.api.plugins.buildcomparison.gradle;
import org.gradle.api.*;
import org.gradle.api.internal.file.FileResolver;
-import org.gradle.api.internal.filestore.FileStore;
+import org.gradle.internal.filestore.FileStore;
import org.gradle.api.internal.filestore.PathNormalisingKeyFileStore;
import org.gradle.api.logging.Logger;
import org.gradle.api.plugins.buildcomparison.compare.internal.BuildComparisonResult;
diff --git a/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/gradle/internal/ComparableGradleBuildExecuter.java b/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/gradle/internal/ComparableGradleBuildExecuter.java
index b60d456..a969718 100644
--- a/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/gradle/internal/ComparableGradleBuildExecuter.java
+++ b/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/gradle/internal/ComparableGradleBuildExecuter.java
@@ -57,7 +57,7 @@ public class ComparableGradleBuildExecuter {
return true;
} else {
// Special handling for snapshots/RCs of the minimum version
- return version.getVersionBase().equals(PROJECT_OUTCOMES_MINIMUM_VERSION.getVersionBase());
+ return version.getBaseVersion().equals(PROJECT_OUTCOMES_MINIMUM_VERSION);
}
}
diff --git a/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/gradle/internal/DefaultGradleBuildInvocationSpec.java b/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/gradle/internal/DefaultGradleBuildInvocationSpec.java
index 8face84..77f76a4 100644
--- a/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/gradle/internal/DefaultGradleBuildInvocationSpec.java
+++ b/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/gradle/internal/DefaultGradleBuildInvocationSpec.java
@@ -59,9 +59,6 @@ public class DefaultGradleBuildInvocationSpec implements GradleBuildInvocationSp
throw new IllegalArgumentException("gradleVersion cannot be null");
}
GradleVersion version = GradleVersion.version(gradleVersion);
- if (!version.isValid()) {
- throw new IllegalArgumentException(String.format("%s is not a valid Gradle version string (examples: '1.0', 1.0-rc-1'", gradleVersion));
- }
this.gradleVersion = version.getVersion();
}
diff --git a/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/gradle/internal/GradleBuildComparison.java b/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/gradle/internal/GradleBuildComparison.java
index af75bac..7afc9ba 100644
--- a/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/gradle/internal/GradleBuildComparison.java
+++ b/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/gradle/internal/GradleBuildComparison.java
@@ -20,7 +20,7 @@ import org.gradle.api.Action;
import org.gradle.api.GradleException;
import org.gradle.api.Transformer;
import org.gradle.api.internal.IoActions;
-import org.gradle.api.internal.filestore.FileStore;
+import org.gradle.internal.filestore.FileStore;
import org.gradle.api.invocation.Gradle;
import org.gradle.api.logging.Logger;
import org.gradle.api.plugins.buildcomparison.compare.internal.*;
diff --git a/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/gradle/internal/GradleBuildOutcomeSetInferrer.java b/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/gradle/internal/GradleBuildOutcomeSetInferrer.java
index 3b15fd3..98b320a 100644
--- a/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/gradle/internal/GradleBuildOutcomeSetInferrer.java
+++ b/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/gradle/internal/GradleBuildOutcomeSetInferrer.java
@@ -17,11 +17,11 @@
package org.gradle.api.plugins.buildcomparison.gradle.internal;
import org.gradle.api.Transformer;
-import org.gradle.api.internal.filestore.FileStore;
-import org.gradle.api.internal.filestore.FileStoreEntry;
+import org.gradle.internal.filestore.FileStore;
import org.gradle.api.plugins.buildcomparison.outcome.internal.BuildOutcome;
import org.gradle.api.plugins.buildcomparison.outcome.internal.archive.GeneratedArchiveBuildOutcome;
import org.gradle.api.plugins.buildcomparison.outcome.internal.unknown.UnknownBuildOutcome;
+import org.gradle.internal.resource.local.LocallyAvailableResource;
import org.gradle.util.CollectionUtils;
import java.io.File;
@@ -59,13 +59,13 @@ public class GradleBuildOutcomeSetInferrer implements Transformer<Set<BuildOutco
// TODO - we are relying on knowledge that the name of the outcome is the task path
String taskPath = outcome.getName();
- FileStoreEntry fileStoreEntry = null;
+ LocallyAvailableResource resource = null;
if (file.exists()) {
String filestoreDestination = String.format("%s/%s/%s", fileStorePrefix, taskPath, file.getName());
- fileStoreEntry = fileStore.move(filestoreDestination, file);
+ resource = fileStore.move(filestoreDestination, file);
}
- return new GeneratedArchiveBuildOutcome(outcome.getName(), outcome.getDescription(), fileStoreEntry, rootRelativePath);
+ return new GeneratedArchiveBuildOutcome(outcome.getName(), outcome.getDescription(), resource, rootRelativePath);
} else {
throw new IllegalStateException(String.format("Unhandled build outcome type: %s", outcome.getClass().getName()));
}
diff --git a/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/gradle/internal/GradleBuildOutcomeSetTransformer.java b/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/gradle/internal/GradleBuildOutcomeSetTransformer.java
index d4b3933..20765cc 100644
--- a/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/gradle/internal/GradleBuildOutcomeSetTransformer.java
+++ b/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/gradle/internal/GradleBuildOutcomeSetTransformer.java
@@ -17,12 +17,12 @@
package org.gradle.api.plugins.buildcomparison.gradle.internal;
import org.gradle.api.Transformer;
-import org.gradle.api.internal.filestore.FileStore;
-import org.gradle.api.internal.filestore.FileStoreEntry;
+import org.gradle.internal.filestore.FileStore;
import org.gradle.api.plugins.buildcomparison.outcome.internal.BuildOutcome;
import org.gradle.api.plugins.buildcomparison.outcome.internal.archive.GeneratedArchiveBuildOutcome;
import org.gradle.api.plugins.buildcomparison.outcome.internal.unknown.UnknownBuildOutcome;
-import org.gradle.tooling.internal.provider.FileOutcomeIdentifier;
+import org.gradle.api.plugins.buildcomparison.outcome.internal.FileOutcomeIdentifier;
+import org.gradle.internal.resource.local.LocallyAvailableResource;
import org.gradle.tooling.model.internal.outcomes.GradleFileBuildOutcome;
import org.gradle.tooling.model.internal.outcomes.GradleBuildOutcome;
import org.gradle.tooling.model.internal.outcomes.ProjectOutcomes;
@@ -79,13 +79,13 @@ public class GradleBuildOutcomeSetTransformer implements Transformer<Set<BuildOu
File originalFile = outcome.getFile();
String relativePath = GFileUtils.relativePath(rootProject.getProjectDirectory(), originalFile);
- FileStoreEntry fileStoreEntry = null;
+ LocallyAvailableResource resource = null;
if (originalFile.exists()) {
String filestoreDestination = String.format("%s/%s/%s", fileStorePrefix, outcome.getTaskPath(), originalFile.getName());
- fileStoreEntry = fileStore.move(filestoreDestination, originalFile);
+ resource = fileStore.move(filestoreDestination, originalFile);
}
- BuildOutcome buildOutcome = new GeneratedArchiveBuildOutcome(outcome.getTaskPath(), outcome.getDescription(), fileStoreEntry, relativePath);
+ BuildOutcome buildOutcome = new GeneratedArchiveBuildOutcome(outcome.getTaskPath(), outcome.getDescription(), resource, relativePath);
translatedOutcomes.add(buildOutcome);
} else {
translatedOutcomes.add(new UnknownBuildOutcome(outcome.getTaskPath(), outcome.getDescription()));
diff --git a/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/outcome/internal/FileOutcomeIdentifier.java b/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/outcome/internal/FileOutcomeIdentifier.java
new file mode 100644
index 0000000..b8a38e7
--- /dev/null
+++ b/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/outcome/internal/FileOutcomeIdentifier.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.plugins.buildcomparison.outcome.internal;
+
+/**
+ * This should not be used as a type in the model. It's just a container for known
+ * {@link org.gradle.tooling.model.internal.outcomes.GradleFileBuildOutcome#getTypeIdentifier()} values.
+ */
+public enum FileOutcomeIdentifier {
+ ZIP_ARTIFACT("artifact.zip"),
+ JAR_ARTIFACT("artifact.jar"),
+ WAR_ARTIFACT("artifact.war"),
+ EAR_ARTIFACT("artifact.ear"),
+ TAR_ARTIFACT("artifact.tar"),
+ ARCHIVE_ARTIFACT("artifact.archive"), // We know it's an archive, but not what kind of archive
+ UNKNOWN_ARTIFACT("artifact.unknown"); // We know it's an artifact, but that's all we know for sure
+
+ private String typeIdentifier;
+
+ FileOutcomeIdentifier(String typeIdentifier) {
+ this.typeIdentifier = typeIdentifier;
+ }
+
+ public String getTypeIdentifier() {
+ return typeIdentifier;
+ }
+}
diff --git a/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/outcome/internal/archive/GeneratedArchiveBuildOutcome.java b/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/outcome/internal/archive/GeneratedArchiveBuildOutcome.java
index 357f8cd..2b6fc4b 100644
--- a/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/outcome/internal/archive/GeneratedArchiveBuildOutcome.java
+++ b/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/outcome/internal/archive/GeneratedArchiveBuildOutcome.java
@@ -16,19 +16,19 @@
package org.gradle.api.plugins.buildcomparison.outcome.internal.archive;
-import org.gradle.api.internal.filestore.FileStoreEntry;
import org.gradle.api.plugins.buildcomparison.outcome.internal.BuildOutcomeSupport;
+import org.gradle.internal.resource.local.LocallyAvailableResource;
import java.io.File;
public class GeneratedArchiveBuildOutcome extends BuildOutcomeSupport {
- private final FileStoreEntry fileStoreEntry;
+ private final LocallyAvailableResource resource;
private final String rootRelativePath;
- public GeneratedArchiveBuildOutcome(String name, String description, FileStoreEntry fileStoreEntry, String rootRelativePath) {
+ public GeneratedArchiveBuildOutcome(String name, String description, LocallyAvailableResource resource, String rootRelativePath) {
super(name, description);
- this.fileStoreEntry = fileStoreEntry;
+ this.resource = resource;
this.rootRelativePath = rootRelativePath;
}
@@ -40,7 +40,7 @@ public class GeneratedArchiveBuildOutcome extends BuildOutcomeSupport {
* @return The generated archive, or null if no archive was generated.
*/
public File getArchiveFile() {
- return fileStoreEntry == null ? null : fileStoreEntry.getFile();
+ return resource == null ? null : resource.getFile();
}
/**
diff --git a/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/outcome/internal/tooling/DefaultGradleBuildOutcome.java b/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/outcome/internal/tooling/DefaultGradleBuildOutcome.java
new file mode 100644
index 0000000..28edf41
--- /dev/null
+++ b/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/outcome/internal/tooling/DefaultGradleBuildOutcome.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.plugins.buildcomparison.outcome.internal.tooling;
+
+import org.gradle.tooling.model.internal.outcomes.GradleBuildOutcome;
+
+import java.io.Serializable;
+
+public class DefaultGradleBuildOutcome implements GradleBuildOutcome, Serializable {
+
+ private final String id;
+ private final String description;
+ private final String taskPath;
+
+ public DefaultGradleBuildOutcome(String id, String description, String taskPath) {
+ this.id = id;
+ this.description = description;
+ this.taskPath = taskPath;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public String getTaskPath() {
+ return taskPath;
+ }
+}
diff --git a/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/outcome/internal/tooling/DefaultGradleFileBuildOutcome.java b/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/outcome/internal/tooling/DefaultGradleFileBuildOutcome.java
new file mode 100644
index 0000000..1a09506
--- /dev/null
+++ b/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/outcome/internal/tooling/DefaultGradleFileBuildOutcome.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.plugins.buildcomparison.outcome.internal.tooling;
+
+import org.gradle.tooling.model.internal.outcomes.GradleFileBuildOutcome;
+
+import java.io.File;
+
+public class DefaultGradleFileBuildOutcome extends DefaultGradleBuildOutcome implements GradleFileBuildOutcome {
+
+ private final File file;
+ private final String typeIdentifier;
+
+ public DefaultGradleFileBuildOutcome(String id, String description, String taskPath, File file, String typeIdentifier) {
+ super(id, description, taskPath);
+ this.file = file;
+ this.typeIdentifier = typeIdentifier;
+ }
+
+ public File getFile() {
+ return file;
+ }
+
+ public String getTypeIdentifier() {
+ return typeIdentifier;
+ }
+
+}
diff --git a/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/outcome/internal/tooling/DefaultProjectOutcomes.java b/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/outcome/internal/tooling/DefaultProjectOutcomes.java
new file mode 100644
index 0000000..7e5d6fc
--- /dev/null
+++ b/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/outcome/internal/tooling/DefaultProjectOutcomes.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.plugins.buildcomparison.outcome.internal.tooling;
+
+import com.google.common.collect.Lists;
+import org.gradle.tooling.model.DomainObjectSet;
+import org.gradle.tooling.model.internal.ImmutableDomainObjectSet;
+import org.gradle.tooling.model.internal.outcomes.GradleBuildOutcome;
+import org.gradle.tooling.model.internal.outcomes.ProjectOutcomes;
+
+import java.io.File;
+import java.io.Serializable;
+import java.util.List;
+
+public class DefaultProjectOutcomes implements ProjectOutcomes, Serializable {
+ private final String name;
+ private final String projectPath;
+ private final String description;
+ private final File projectDirectory;
+ private final DomainObjectSet<? extends GradleBuildOutcome> outcomes;
+ private final ProjectOutcomes parent;
+ private final List<ProjectOutcomes> children = Lists.newArrayList();
+
+ public DefaultProjectOutcomes(String name, String projectPath, String description, File projectDirectory,
+ DomainObjectSet<? extends GradleBuildOutcome> outcomes, ProjectOutcomes parent) {
+ this.name = name;
+ this.projectPath = projectPath;
+ this.description = description;
+ this.projectDirectory = projectDirectory;
+ this.outcomes = outcomes;
+ this.parent = parent;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getPath() {
+ return projectPath;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public File getProjectDirectory() {
+ return projectDirectory;
+ }
+
+ public DomainObjectSet<? extends GradleBuildOutcome> getOutcomes() {
+ return outcomes;
+ }
+
+ public ProjectOutcomes getParent() {
+ return parent;
+ }
+
+ public DomainObjectSet<ProjectOutcomes> getChildren() {
+ return new ImmutableDomainObjectSet<ProjectOutcomes>(children);
+ }
+
+ public void addChild(ProjectOutcomes child) {
+ children.add(child);
+ }
+}
diff --git a/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/outcome/internal/tooling/ProjectOutcomesModelBuilder.java b/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/outcome/internal/tooling/ProjectOutcomesModelBuilder.java
new file mode 100644
index 0000000..15e9481
--- /dev/null
+++ b/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/outcome/internal/tooling/ProjectOutcomesModelBuilder.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.plugins.buildcomparison.outcome.internal.tooling;
+
+import com.google.common.collect.Lists;
+import org.gradle.api.Project;
+import org.gradle.api.artifacts.Configuration;
+import org.gradle.api.artifacts.PublishArtifact;
+import org.gradle.tooling.model.DomainObjectSet;
+import org.gradle.tooling.model.internal.ImmutableDomainObjectSet;
+import org.gradle.tooling.model.internal.outcomes.GradleFileBuildOutcome;
+import org.gradle.tooling.model.internal.outcomes.ProjectOutcomes;
+import org.gradle.tooling.provider.model.ToolingModelBuilder;
+
+import java.util.List;
+
+public class ProjectOutcomesModelBuilder implements ToolingModelBuilder {
+ private final PublishArtifactToFileBuildOutcomeTransformer artifactTransformer = new PublishArtifactToFileBuildOutcomeTransformer();
+
+ public boolean canBuild(String modelName) {
+ return modelName.equals("org.gradle.tooling.model.outcomes.ProjectOutcomes");
+ }
+
+ public Object buildAll(String modelName, Project project) {
+ return buildProjectOutput(project.getRootProject(), null);
+ }
+
+ private DefaultProjectOutcomes buildProjectOutput(Project project, ProjectOutcomes parent) {
+ DefaultProjectOutcomes projectOutput = new DefaultProjectOutcomes(project.getName(), project.getPath(),
+ project.getDescription(), project.getProjectDir(), getFileOutcomes(project), parent);
+ for (Project child : project.getChildProjects().values()) {
+ projectOutput.addChild(buildProjectOutput(child, projectOutput));
+ }
+ return projectOutput;
+ }
+
+ private DomainObjectSet<GradleFileBuildOutcome> getFileOutcomes(Project project) {
+ List<GradleFileBuildOutcome> fileBuildOutcomes = Lists.newArrayList();
+ addArtifacts(project, fileBuildOutcomes);
+ return new ImmutableDomainObjectSet<GradleFileBuildOutcome>(fileBuildOutcomes);
+ }
+
+ private void addArtifacts(Project project, List<GradleFileBuildOutcome> outcomes) {
+ Configuration configuration = project.getConfigurations().findByName("archives");
+ if (configuration != null) {
+ for (PublishArtifact artifact : configuration.getArtifacts()) {
+ GradleFileBuildOutcome outcome = artifactTransformer.transform(artifact, project);
+ outcomes.add(outcome);
+ }
+ }
+ }
+
+}
diff --git a/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/outcome/internal/tooling/PublishArtifactToFileBuildOutcomeTransformer.java b/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/outcome/internal/tooling/PublishArtifactToFileBuildOutcomeTransformer.java
new file mode 100644
index 0000000..b853a6e
--- /dev/null
+++ b/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/outcome/internal/tooling/PublishArtifactToFileBuildOutcomeTransformer.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.plugins.buildcomparison.outcome.internal.tooling;
+
+import org.gradle.api.Project;
+import org.gradle.api.Task;
+import org.gradle.api.artifacts.PublishArtifact;
+import org.gradle.api.internal.artifacts.publish.ArchivePublishArtifact;
+import org.gradle.api.tasks.bundling.*;
+import org.gradle.plugins.ear.Ear;
+import org.gradle.tooling.model.internal.outcomes.GradleFileBuildOutcome;
+
+import java.net.URI;
+import java.util.Set;
+
+import static org.gradle.api.plugins.buildcomparison.outcome.internal.FileOutcomeIdentifier.*;
+
+public class PublishArtifactToFileBuildOutcomeTransformer {
+
+ public GradleFileBuildOutcome transform(PublishArtifact artifact, Project project) {
+ String id = getId(artifact, project);
+ String taskPath = getTaskPath(artifact);
+ String description = getDescription(artifact);
+ String typeIdentifier = getTypeIdentifier(artifact);
+
+ return new DefaultGradleFileBuildOutcome(id, description, taskPath, artifact.getFile(), typeIdentifier);
+ }
+
+ private String getId(PublishArtifact artifact, Project project) {
+ // Assume that each artifact points to a unique file, and use the relative path from the project as the id
+ URI artifactUri = artifact.getFile().toURI();
+ URI projectDirUri = project.getProjectDir().toURI();
+ URI relativeUri = projectDirUri.relativize(artifactUri);
+ return relativeUri.getPath();
+ }
+
+ private String getDescription(PublishArtifact artifact) {
+ return String.format("Publish artifact '%s'", artifact.toString());
+ }
+
+ private String getTypeIdentifier(PublishArtifact artifact) {
+ if (artifact instanceof ArchivePublishArtifact) {
+ ArchivePublishArtifact publishArtifact = (ArchivePublishArtifact) artifact;
+ AbstractArchiveTask task = publishArtifact.getArchiveTask();
+
+ // There is an inheritance hierarchy in play here, so the order
+ // of the clauses is very important.
+
+ if (task instanceof War) {
+ return WAR_ARTIFACT.getTypeIdentifier();
+ } else if (task instanceof Ear) {
+ return EAR_ARTIFACT.getTypeIdentifier();
+ } else if (task instanceof Jar) {
+ return JAR_ARTIFACT.getTypeIdentifier();
+ } else if (task instanceof Zip) {
+ return ZIP_ARTIFACT.getTypeIdentifier();
+ } else if (task instanceof Tar) {
+ return TAR_ARTIFACT.getTypeIdentifier();
+ } else {
+ // we don't know about this kind of archive task
+ return ARCHIVE_ARTIFACT.getTypeIdentifier();
+ }
+ } else {
+ // This could very well be a zip (or something else we understand), but we can't know for sure.
+ // The client may try to infer from the file extension.
+ return UNKNOWN_ARTIFACT.getTypeIdentifier();
+ }
+ }
+
+ private String getTaskPath(PublishArtifact artifact) {
+ if (artifact instanceof ArchivePublishArtifact) {
+ return ((ArchivePublishArtifact) artifact).getArchiveTask().getPath();
+ } else {
+ String taskPath = null;
+ Set<? extends Task> tasks = artifact.getBuildDependencies().getDependencies(null);
+ if (!tasks.isEmpty()) {
+ taskPath = tasks.iterator().next().getPath();
+ }
+ return taskPath;
+ }
+ }
+
+}
diff --git a/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/outcome/internal/tooling/ToolingRegistrationAction.java b/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/outcome/internal/tooling/ToolingRegistrationAction.java
new file mode 100644
index 0000000..59add9a
--- /dev/null
+++ b/subprojects/build-comparison/src/main/groovy/org/gradle/api/plugins/buildcomparison/outcome/internal/tooling/ToolingRegistrationAction.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.plugins.buildcomparison.outcome.internal.tooling;
+
+import org.gradle.api.internal.project.ProjectInternal;
+import org.gradle.configuration.project.ProjectConfigureAction;
+import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry;
+
+public class ToolingRegistrationAction implements ProjectConfigureAction {
+ public void execute(ProjectInternal project) {
+ project.getServices().get(ToolingModelBuilderRegistry.class).register(new ProjectOutcomesModelBuilder());
+ }
+}
diff --git a/subprojects/build-comparison/src/main/resources/META-INF/services/org.gradle.configuration.project.ProjectConfigureAction b/subprojects/build-comparison/src/main/resources/META-INF/services/org.gradle.configuration.project.ProjectConfigureAction
new file mode 100644
index 0000000..a2789fd
--- /dev/null
+++ b/subprojects/build-comparison/src/main/resources/META-INF/services/org.gradle.configuration.project.ProjectConfigureAction
@@ -0,0 +1 @@
+org.gradle.api.plugins.buildcomparison.outcome.internal.tooling.ToolingRegistrationAction
\ No newline at end of file
diff --git a/subprojects/build-comparison/src/test/groovy/org/gradle/api/plugins/buildcomparison/gradle/internal/DefaultGradleBuildInvocationSpecTest.groovy b/subprojects/build-comparison/src/test/groovy/org/gradle/api/plugins/buildcomparison/gradle/internal/DefaultGradleBuildInvocationSpecTest.groovy
index e64df57..4d5c4bd 100644
--- a/subprojects/build-comparison/src/test/groovy/org/gradle/api/plugins/buildcomparison/gradle/internal/DefaultGradleBuildInvocationSpecTest.groovy
+++ b/subprojects/build-comparison/src/test/groovy/org/gradle/api/plugins/buildcomparison/gradle/internal/DefaultGradleBuildInvocationSpecTest.groovy
@@ -17,12 +17,12 @@
package org.gradle.api.plugins.buildcomparison.gradle.internal
import org.gradle.api.internal.file.FileResolver
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import spock.lang.Specification
class DefaultGradleBuildInvocationSpecTest extends Specification {
- FileResolver fileResolver = HelperUtil.createRootProject().fileResolver
+ FileResolver fileResolver = TestUtil.createRootProject().fileResolver
def "equals and hashCode"() {
given:
diff --git a/subprojects/build-comparison/src/test/groovy/org/gradle/api/plugins/buildcomparison/gradle/internal/GradleBuildOutcomeSetInferrerTest.groovy b/subprojects/build-comparison/src/test/groovy/org/gradle/api/plugins/buildcomparison/gradle/internal/GradleBuildOutcomeSetInferrerTest.groovy
index 19ceb76..665f6ec 100644
--- a/subprojects/build-comparison/src/test/groovy/org/gradle/api/plugins/buildcomparison/gradle/internal/GradleBuildOutcomeSetInferrerTest.groovy
+++ b/subprojects/build-comparison/src/test/groovy/org/gradle/api/plugins/buildcomparison/gradle/internal/GradleBuildOutcomeSetInferrerTest.groovy
@@ -28,7 +28,7 @@ import org.gradle.tooling.model.internal.outcomes.ProjectOutcomes
import org.junit.Rule
import spock.lang.Specification
-import static org.gradle.tooling.internal.provider.FileOutcomeIdentifier.*
+import static org.gradle.api.plugins.buildcomparison.outcome.internal.FileOutcomeIdentifier.*
class GradleBuildOutcomeSetInferrerTest extends Specification {
diff --git a/subprojects/build-comparison/src/test/groovy/org/gradle/api/plugins/buildcomparison/gradle/internal/GradleBuildOutcomeSetTransformerTest.groovy b/subprojects/build-comparison/src/test/groovy/org/gradle/api/plugins/buildcomparison/gradle/internal/GradleBuildOutcomeSetTransformerTest.groovy
index 84529dd..b01fb24 100644
--- a/subprojects/build-comparison/src/test/groovy/org/gradle/api/plugins/buildcomparison/gradle/internal/GradleBuildOutcomeSetTransformerTest.groovy
+++ b/subprojects/build-comparison/src/test/groovy/org/gradle/api/plugins/buildcomparison/gradle/internal/GradleBuildOutcomeSetTransformerTest.groovy
@@ -17,12 +17,12 @@
package org.gradle.api.plugins.buildcomparison.gradle.internal
import org.gradle.api.Action
-import org.gradle.api.internal.filestore.AbstractFileStoreEntry
-import org.gradle.api.internal.filestore.FileStore
-import org.gradle.api.internal.filestore.FileStoreEntry
+import org.gradle.internal.filestore.FileStore
import org.gradle.api.plugins.buildcomparison.fixtures.ProjectOutcomesBuilder
import org.gradle.api.plugins.buildcomparison.outcome.internal.archive.GeneratedArchiveBuildOutcome
import org.gradle.api.plugins.buildcomparison.outcome.internal.unknown.UnknownBuildOutcome
+import org.gradle.internal.resource.local.DefaultLocallyAvailableResource
+import org.gradle.internal.resource.local.LocallyAvailableResource
import org.gradle.test.fixtures.file.TestFile
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
import org.gradle.tooling.model.internal.outcomes.GradleBuildOutcome
@@ -31,32 +31,24 @@ import org.gradle.tooling.model.internal.outcomes.ProjectOutcomes
import org.junit.Rule
import spock.lang.Specification
-import static org.gradle.tooling.internal.provider.FileOutcomeIdentifier.*
+import static org.gradle.api.plugins.buildcomparison.outcome.internal.FileOutcomeIdentifier.*
class GradleBuildOutcomeSetTransformerTest extends Specification {
def store = new FileStore<String>() {
- FileStoreEntry move(String key, File source) {
- new AbstractFileStoreEntry() {
- File getFile() {
- source
- }
- }
+ LocallyAvailableResource move(String key, File source) {
+ new DefaultLocallyAvailableResource(source)
}
- FileStoreEntry copy(String key, File source) {
- new AbstractFileStoreEntry() {
- File getFile() {
- source
- }
- }
+ LocallyAvailableResource copy(String key, File source) {
+ new DefaultLocallyAvailableResource(source)
}
void moveFilestore(File destination) {
throw new UnsupportedOperationException()
}
- FileStoreEntry add(String key, Action<File> addAction) {
+ LocallyAvailableResource add(String key, Action<File> addAction) {
throw new UnsupportedOperationException()
}
}
diff --git a/subprojects/build-comparison/src/test/groovy/org/gradle/api/plugins/buildcomparison/outcome/internal/archive/GeneratedArchiveBuildOutcomeComparatorTest.groovy b/subprojects/build-comparison/src/test/groovy/org/gradle/api/plugins/buildcomparison/outcome/internal/archive/GeneratedArchiveBuildOutcomeComparatorTest.groovy
index b5a71bc..0eaa388 100644
--- a/subprojects/build-comparison/src/test/groovy/org/gradle/api/plugins/buildcomparison/outcome/internal/archive/GeneratedArchiveBuildOutcomeComparatorTest.groovy
+++ b/subprojects/build-comparison/src/test/groovy/org/gradle/api/plugins/buildcomparison/outcome/internal/archive/GeneratedArchiveBuildOutcomeComparatorTest.groovy
@@ -17,10 +17,10 @@
package org.gradle.api.plugins.buildcomparison.outcome.internal.archive
import org.gradle.api.Transformer
-import org.gradle.api.internal.filestore.AbstractFileStoreEntry
import org.gradle.api.plugins.buildcomparison.outcome.internal.DefaultBuildOutcomeAssociation
import org.gradle.api.plugins.buildcomparison.outcome.internal.archive.entry.ArchiveEntry
import org.gradle.api.plugins.buildcomparison.outcome.internal.archive.entry.ArchiveEntryComparison
+import org.gradle.internal.resource.local.DefaultLocallyAvailableResource
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
import org.junit.Rule
import spock.lang.Specification
@@ -121,9 +121,7 @@ class GeneratedArchiveBuildOutcomeComparatorTest extends Specification {
}
GeneratedArchiveBuildOutcome outcome(String name, File file = dir.createFile(name)) {
- def fileStoreEntry = new AbstractFileStoreEntry() {
- File getFile() { file }
- }
- new GeneratedArchiveBuildOutcome(name, name, fileStoreEntry, name)
+ def resource = new DefaultLocallyAvailableResource(file)
+ new GeneratedArchiveBuildOutcome(name, name, resource, name)
}
}
diff --git a/subprojects/build-comparison/src/test/groovy/org/gradle/api/plugins/buildcomparison/outcome/internal/tooling/PublishArtifactToFileBuildOutcomeTransformerTest.groovy b/subprojects/build-comparison/src/test/groovy/org/gradle/api/plugins/buildcomparison/outcome/internal/tooling/PublishArtifactToFileBuildOutcomeTransformerTest.groovy
new file mode 100644
index 0000000..ad74474
--- /dev/null
+++ b/subprojects/build-comparison/src/test/groovy/org/gradle/api/plugins/buildcomparison/outcome/internal/tooling/PublishArtifactToFileBuildOutcomeTransformerTest.groovy
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.plugins.buildcomparison.outcome.internal.tooling
+
+import org.gradle.api.Task
+import org.gradle.api.artifacts.PublishArtifact
+import org.gradle.api.internal.artifacts.publish.ArchivePublishArtifact
+import org.gradle.api.plugins.buildcomparison.outcome.internal.FileOutcomeIdentifier
+import org.gradle.api.tasks.TaskDependency
+import org.gradle.plugins.ear.Ear
+import org.gradle.tooling.model.internal.outcomes.GradleFileBuildOutcome
+import spock.lang.Specification
+import spock.lang.Unroll
+import org.gradle.api.tasks.bundling.*
+
+import static org.gradle.api.plugins.buildcomparison.outcome.internal.FileOutcomeIdentifier.*
+import org.gradle.util.TestUtil
+import org.gradle.api.Project
+
+class PublishArtifactToFileBuildOutcomeTransformerTest extends Specification {
+
+ def transformer = new PublishArtifactToFileBuildOutcomeTransformer()
+
+ Project project = TestUtil.createRootProject()
+
+ @Unroll
+ "can create outcome for #taskClass archive artifact"(Class<? extends AbstractArchiveTask> taskClass, FileOutcomeIdentifier typeIdentifier) {
+ given:
+ AbstractArchiveTask task = Mock(taskClass)
+ PublishArtifact artifact = new ArchivePublishArtifact(task)
+
+ and:
+ _ * task.getArchivePath() >> project.file("file")
+
+ when:
+ GradleFileBuildOutcome outcome = transformer.transform(artifact, project)
+
+ then:
+ outcome.typeIdentifier == typeIdentifier.typeIdentifier
+ outcome.id == "file"
+
+ where:
+ taskClass | typeIdentifier
+ Zip | ZIP_ARTIFACT
+ Jar | JAR_ARTIFACT
+ Ear | EAR_ARTIFACT
+ Tar | TAR_ARTIFACT
+ War | WAR_ARTIFACT
+ AbstractArchiveTask | ARCHIVE_ARTIFACT
+ }
+
+ def "can handle generic publish artifact"() {
+ given:
+ def task = Mock(Task)
+ def taskDependency = Mock(TaskDependency)
+ def artifact = Mock(PublishArtifact)
+
+ 1 * taskDependency.getDependencies(null) >>> [[task] as Set]
+ 1 * task.getPath() >> "path"
+ _ * artifact.getFile() >> project.file("file")
+ 1 * artifact.getBuildDependencies() >> taskDependency
+
+ when:
+ def outcome = transformer.transform(artifact, project)
+
+ then:
+ outcome.typeIdentifier == UNKNOWN_ARTIFACT.typeIdentifier
+ outcome.taskPath == "path"
+ outcome.id == "file"
+ }
+
+
+}
diff --git a/subprojects/build-setup/build-setup.gradle b/subprojects/build-setup/build-setup.gradle
new file mode 100644
index 0000000..8095d3f
--- /dev/null
+++ b/subprojects/build-setup/build-setup.gradle
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+dependencies {
+ compile libraries.groovy
+ compile project(':core')
+ compile project(':plugins')
+ compile project(':wrapper')
+ integTestRuntime project(':maven')
+}
+
+useTestFixtures()
+useClassycle()
diff --git a/subprojects/build-setup/src/integTest/groovy/org/gradle/buildsetup/plugins/BuildSetupPluginIntegrationTest.groovy b/subprojects/build-setup/src/integTest/groovy/org/gradle/buildsetup/plugins/BuildSetupPluginIntegrationTest.groovy
new file mode 100644
index 0000000..023c8b5
--- /dev/null
+++ b/subprojects/build-setup/src/integTest/groovy/org/gradle/buildsetup/plugins/BuildSetupPluginIntegrationTest.groovy
@@ -0,0 +1,204 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.buildsetup.plugins
+
+import org.gradle.buildsetup.plugins.fixtures.WrapperTestFixture
+import org.gradle.integtests.fixtures.WellBehavedPluginTest
+import org.gradle.test.fixtures.file.TestFile
+import org.hamcrest.Matcher
+
+import static org.hamcrest.Matchers.containsString
+import static org.hamcrest.Matchers.not
+
+class BuildSetupPluginIntegrationTest extends WellBehavedPluginTest {
+ final wrapper = new WrapperTestFixture(testDirectory)
+
+ @Override
+ String getMainTask() {
+ return "setupBuild"
+ }
+
+ @Override
+ String getPluginId() {
+ "build-setup"
+ }
+
+ def "setupBuild shows up on tasks overview "() {
+ when:
+ run 'tasks'
+
+ then:
+ result.output.contains "setupBuild - Initializes a new Gradle build."
+ }
+
+ def "creates a simple project when no pom file present and no type specified"() {
+ given:
+ assert !buildFile.exists()
+ assert !settingsFile.exists()
+
+ when:
+ run 'setupBuild'
+
+ then:
+ wrapper.generated()
+ buildFile.exists()
+ settingsFile.exists()
+
+ expect:
+ succeeds 'tasks'
+ }
+
+ def "build file generation is skipped when build file already exists"() {
+ given:
+ buildFile.createFile()
+
+ when:
+ run('setupBuild')
+
+ then:
+ result.assertTasksExecuted(":setupBuild")
+ result.output.contains("The build file 'build.gradle' already exists. Skipping build initialization.")
+
+ and:
+ !settingsFile.exists()
+ wrapper.notGenerated()
+ }
+
+ def "build file generation is skipped when settings file already exists"() {
+ given:
+ settingsFile.createFile()
+
+ when:
+ run('setupBuild')
+
+ then:
+ result.assertTasksExecuted(":setupBuild")
+ result.output.contains("The settings file 'settings.gradle' already exists. Skipping build initialization.")
+
+ and:
+ !buildFile.exists()
+ wrapper.notGenerated()
+ }
+
+ def "build file generation is skipped when custom build file exists"() {
+ given:
+ def customBuildScript = testDirectory.file("customBuild.gradle").createFile()
+
+ when:
+ executer.usingBuildScript(customBuildScript)
+ run('setupBuild')
+
+ then:
+ result.assertTasksExecuted(":setupBuild")
+ result.output.contains("The build file 'customBuild.gradle' already exists. Skipping build initialization.")
+
+ and:
+ !buildFile.exists()
+ !settingsFile.exists()
+ wrapper.notGenerated()
+ }
+
+ def "build file generation is skipped when part of a multi-project build with non-standard settings file location"() {
+ given:
+ def customSettings = testDirectory.file("customSettings.gradle")
+ customSettings << """
+include 'child'
+"""
+
+ when:
+ executer.usingSettingsFile(customSettings)
+ run('setupBuild')
+
+ then:
+ result.assertTasksExecuted(":setupBuild")
+ result.output.contains("This Gradle project appears to be part of an existing multi-project Gradle build. Skipping build initialization.")
+
+ and:
+ !buildFile.exists()
+ !settingsFile.exists()
+ wrapper.notGenerated()
+ }
+
+ def "pom conversion is triggered when pom and no gradle file found"() {
+ given:
+ pom()
+
+ when:
+ run('setupBuild')
+
+ then:
+ pomValuesUsed()
+ }
+
+ def "pom conversion not triggered when build type is specified"() {
+ given:
+ pom()
+
+ when:
+ succeeds('setupBuild', '--type', 'java-library')
+
+ then:
+ pomValuesNotUsed()
+ }
+
+ def "gives decent error message when triggered with unknown setupBuild-type"() {
+ when:
+ fails('setupBuild', '--type', 'some-unknown-library')
+
+ then:
+ failure.assertHasCause("The requested build setup type 'some-unknown-library' is not supported.")
+ }
+
+ private TestFile pom() {
+ file("pom.xml") << """
+ <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>util</groupId>
+ <artifactId>util</artifactId>
+ <version>2.5</version>
+ <packaging>jar</packaging>
+ </project>"""
+ }
+
+ private pomValuesUsed() {
+ buildFile.assertContents(containsPomGroup())
+ buildFile.assertContents(containsPomVersion())
+ settingsFile.assertContents(containsPomArtifactId())
+ }
+
+ private pomValuesNotUsed() {
+ buildFile.assertContents(not(containsPomGroup()))
+ buildFile.assertContents(not(containsPomVersion()))
+ settingsFile.assertContents(not(containsPomArtifactId()))
+ }
+
+ private Matcher<String> containsPomGroup() {
+ containsString("group = 'util'")
+ }
+
+ private Matcher<String> containsPomVersion() {
+ containsString("version = '2.5'")
+ }
+
+ private Matcher<String> containsPomArtifactId() {
+ containsString("rootProject.name = 'util'")
+ }
+
+}
diff --git a/subprojects/build-setup/src/integTest/groovy/org/gradle/buildsetup/plugins/JavaLibrarySetupIntegrationTest.groovy b/subprojects/build-setup/src/integTest/groovy/org/gradle/buildsetup/plugins/JavaLibrarySetupIntegrationTest.groovy
new file mode 100644
index 0000000..304097e
--- /dev/null
+++ b/subprojects/build-setup/src/integTest/groovy/org/gradle/buildsetup/plugins/JavaLibrarySetupIntegrationTest.groovy
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.buildsetup.plugins
+
+import org.gradle.buildsetup.plugins.fixtures.WrapperTestFixture
+import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+import org.gradle.integtests.fixtures.DefaultTestExecutionResult
+import org.gradle.integtests.fixtures.TestExecutionResult
+
+
+class JavaLibrarySetupIntegrationTest extends AbstractIntegrationSpec {
+
+ public static final String SAMPLE_LIBRARY_CLASS = "src/main/java/Library.java"
+ public static final String SAMPLE_LIBRARY_TEST_CLASS = "src/test/java/LibraryTest.java"
+
+ final wrapper = new WrapperTestFixture(testDirectory)
+
+ def "creates sample source if no source present"() {
+ when:
+ succeeds('setupBuild', '--type', 'java-library')
+
+ then:
+ file(SAMPLE_LIBRARY_CLASS).exists()
+ file(SAMPLE_LIBRARY_TEST_CLASS).exists()
+ buildFile.exists()
+ settingsFile.exists()
+ wrapper.generated()
+
+ when:
+ succeeds("build")
+
+ then:
+ TestExecutionResult testResult = new DefaultTestExecutionResult(testDirectory)
+ testResult.assertTestClassesExecuted("LibraryTest")
+ testResult.testClass("LibraryTest").assertTestPassed("testSomeLibraryMethod")
+ }
+
+ def "setupProjectLayout is skipped when sources detected"() {
+ setup:
+ file("src/main/java/org/acme/SampleMain.java") << """
+ package org.acme;
+
+ public class SampleMain{
+ }
+"""
+ file("src/test/java/org/acme/SampleMainTest.java") << """
+ package org.acme;
+
+ public class SampleMain{
+ }
+ """
+ when:
+ succeeds('setupBuild', '--type', 'java-library')
+
+ then:
+ !file(SAMPLE_LIBRARY_CLASS).exists()
+ !file(SAMPLE_LIBRARY_TEST_CLASS).exists()
+ buildFile.exists()
+ settingsFile.exists()
+ wrapper.generated()
+ }
+}
diff --git a/subprojects/build-setup/src/integTest/groovy/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest.groovy b/subprojects/build-setup/src/integTest/groovy/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest.groovy
new file mode 100644
index 0000000..58d0446
--- /dev/null
+++ b/subprojects/build-setup/src/integTest/groovy/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest.groovy
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.buildsetup.plugins
+
+import org.gradle.buildsetup.plugins.fixtures.WrapperTestFixture
+import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+import org.gradle.integtests.fixtures.DefaultTestExecutionResult
+import org.gradle.integtests.fixtures.TestResources
+import org.gradle.test.fixtures.file.TestFile
+import org.junit.Rule
+
+import static org.gradle.util.TextUtil.toPlatformLineSeparators
+
+class MavenConversionIntegrationTest extends AbstractIntegrationSpec {
+
+ @Rule
+ public final TestResources resources = new TestResources(temporaryFolder)
+
+ def "multiModule"() {
+ when:
+ run 'setupBuild'
+
+ then:
+ settingsFile.exists()
+ buildFile.exists()
+ wrapperFilesGenerated()
+
+ when:
+ run 'clean', 'build'
+
+ then: //smoke test the build artifacts
+ file("webinar-api/build/libs/webinar-api-1.0-SNAPSHOT.jar").exists()
+ file("webinar-impl/build/libs/webinar-impl-1.0-SNAPSHOT.jar").exists()
+ file("webinar-war/build/libs/webinar-war-1.0-SNAPSHOT.war").exists()
+
+ new DefaultTestExecutionResult(file("webinar-impl")).assertTestClassesExecuted('webinar.WebinarTest')
+
+ when:
+ run 'projects'
+
+ then:
+ output.contains(toPlatformLineSeparators("""
+Root project 'webinar-parent'
++--- Project ':webinar-api' - Webinar APIs
++--- Project ':webinar-impl' - Webinar implementation
+\\--- Project ':webinar-war' - Webinar web application
+"""))
+ }
+
+ def "flatmultimodule"() {
+ when:
+ executer.inDirectory(file("webinar-parent"))
+ run 'setupBuild'
+
+ then:
+ file("webinar-parent/settings.gradle").exists()
+ file("webinar-parent/build.gradle").exists()
+ wrapperFilesGenerated(file("webinar-parent"))
+
+ when:
+ executer.inDirectory(file("webinar-parent"))
+ run 'clean', 'build'
+
+ then: //smoke test the build artifacts
+ file("webinar-api/build/libs/webinar-api-1.0-SNAPSHOT.jar").exists()
+ file("webinar-impl/build/libs/webinar-impl-1.0-SNAPSHOT.jar").exists()
+ file("webinar-war/build/libs/webinar-war-1.0-SNAPSHOT.war").exists()
+
+ new DefaultTestExecutionResult(file("webinar-impl")).assertTestClassesExecuted('webinar.WebinarTest')
+
+ when:
+ executer.inDirectory(file("webinar-parent"))
+ run 'projects'
+
+ then:
+ output.contains(toPlatformLineSeparators("""
+Root project 'webinar-parent'
++--- Project ':webinar-api' - Webinar APIs
++--- Project ':webinar-impl' - Webinar implementation
+\\--- Project ':webinar-war' - Webinar web application
+"""))
+ }
+
+ def "singleModule"() {
+ when:
+ run 'setupBuild'
+
+ then:
+ buildFile.exists()
+ settingsFile.exists()
+ wrapperFilesGenerated()
+
+ when:
+ //TODO this build should fail because the TestNG test is failing
+ //however the plugin does not generate testNG for single module project atm (bug)
+ //def failure = runAndFail('clean', 'build') //assert if fails for the right reason
+ run 'clean', 'build'
+
+ then:
+ file("build/libs/util-2.5.jar").exists()
+ }
+
+ def "testjar"() {
+ when:
+ run 'setupBuild'
+
+ then:
+ settingsFile.exists()
+ settingsFile.exists()
+ wrapperFilesGenerated()
+
+ when:
+ run 'clean', 'build'
+
+ then:
+ file("build/libs/testjar-2.5.jar").exists()
+ file("build/libs/testjar-2.5-tests.jar").exists()
+ }
+
+ def "enforcerplugin"() {
+ when:
+ run 'setupBuild'
+
+ then:
+ settingsFile.exists()
+ buildFile.exists()
+ wrapperFilesGenerated()
+
+ and:
+ buildFile.text.contains("""configurations.all {
+it.exclude group: 'org.apache.maven'
+it.exclude group: 'org.apache.maven', module: 'badArtifact'
+it.exclude group: '*', module: 'badArtifact'
+}""")
+ when:
+ run 'clean', 'build'
+
+ then:
+ file("build/libs/enforcerExample-1.0.jar").exists()
+ }
+
+ def "providedNotWar"() {
+ when:
+ run 'setupBuild'
+
+ then:
+ settingsFile.exists()
+ buildFile.exists()
+ wrapperFilesGenerated()
+
+ when:
+ run 'clean', 'build'
+
+ then:
+ file("build/libs/myThing-0.0.1-SNAPSHOT.jar").exists()
+ }
+
+ def "provides decent error message when POM is invalid"() {
+ setup:
+ def pom = file("pom.xml")
+ pom << "<project>someInvalid pom content</project>"
+
+ when:
+ fails 'setupBuild'
+
+ then:
+ failure.assertHasCause("Could not convert Maven POM $pom to a Gradle build.")
+ }
+
+ def "mavenExtensions"() {
+ when:
+ run 'setupBuild'
+ then:
+ settingsFile.exists()
+ buildFile.exists()
+ wrapperFilesGenerated()
+
+ when:
+ run 'clean', 'build'
+
+ then:
+ file("build/libs/testApp-1.0.jar").exists()
+ }
+
+ void wrapperFilesGenerated(TestFile parentFolder = file(".")) {
+ new WrapperTestFixture(parentFolder).generated()
+ }
+}
\ No newline at end of file
diff --git a/subprojects/build-setup/src/integTest/groovy/org/gradle/buildsetup/plugins/WrapperPluginIntegrationTest.groovy b/subprojects/build-setup/src/integTest/groovy/org/gradle/buildsetup/plugins/WrapperPluginIntegrationTest.groovy
new file mode 100644
index 0000000..757229a
--- /dev/null
+++ b/subprojects/build-setup/src/integTest/groovy/org/gradle/buildsetup/plugins/WrapperPluginIntegrationTest.groovy
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.buildsetup.plugins
+
+import org.gradle.buildsetup.plugins.fixtures.WrapperTestFixture
+import org.gradle.integtests.fixtures.WellBehavedPluginTest
+
+class WrapperPluginIntegrationTest extends WellBehavedPluginTest {
+ @Override
+ String getMainTask() {
+ return "wrapper"
+ }
+
+ def "wrapper task generates wrapper files"() {
+ when:
+ run 'wrapper'
+
+ then:
+ new WrapperTestFixture(testDirectory).generated()
+ }
+}
\ No newline at end of file
diff --git a/subprojects/build-setup/src/integTest/groovy/org/gradle/buildsetup/plugins/fixtures/WrapperTestFixture.groovy b/subprojects/build-setup/src/integTest/groovy/org/gradle/buildsetup/plugins/fixtures/WrapperTestFixture.groovy
new file mode 100644
index 0000000..03731f9
--- /dev/null
+++ b/subprojects/build-setup/src/integTest/groovy/org/gradle/buildsetup/plugins/fixtures/WrapperTestFixture.groovy
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.buildsetup.plugins.fixtures
+
+import org.gradle.test.fixtures.file.TestFile
+import org.gradle.util.GradleVersion
+
+
+class WrapperTestFixture {
+
+ public static final String GRADLEW_BASH_SCRIPT = "gradlew"
+ public static final String GRADLEW_BATCH_SCRIPT = "gradlew.bat"
+ public static final String GRADLEW_WRAPPER_JAR = "gradle/wrapper/gradle-wrapper.jar"
+ public static final String GRADLEW_PROPERTY_FILE = "gradle/wrapper/gradle-wrapper.properties"
+
+ private final TestFile projectDirectory
+
+ WrapperTestFixture(TestFile projectdirectory) {
+ this.projectDirectory = projectdirectory
+ }
+
+ public void generated(String version = GradleVersion.current().version) {
+ projectDirectory.file(GRADLEW_BASH_SCRIPT).assertExists()
+ projectDirectory.file(GRADLEW_BATCH_SCRIPT).assertExists()
+ projectDirectory.file(GRADLEW_WRAPPER_JAR).assertExists()
+ projectDirectory.file(GRADLEW_PROPERTY_FILE).assertExists()
+ projectDirectory.file(GRADLEW_PROPERTY_FILE).text.contains("gradle-${version}-bin.zip")
+ }
+
+ public void notGenerated() {
+ projectDirectory.file(GRADLEW_BASH_SCRIPT).assertDoesNotExist()
+ projectDirectory.file(GRADLEW_BATCH_SCRIPT).assertDoesNotExist()
+ projectDirectory.file(GRADLEW_WRAPPER_JAR).assertDoesNotExist()
+ projectDirectory.file(GRADLEW_PROPERTY_FILE).assertDoesNotExist()
+ }
+}
diff --git a/subprojects/build-setup/src/integTest/groovy/org/gradle/buildsetup/plugins/internal/WrapperPluginAutoApplyActionIntegTest.groovy b/subprojects/build-setup/src/integTest/groovy/org/gradle/buildsetup/plugins/internal/WrapperPluginAutoApplyActionIntegTest.groovy
new file mode 100644
index 0000000..0117dda
--- /dev/null
+++ b/subprojects/build-setup/src/integTest/groovy/org/gradle/buildsetup/plugins/internal/WrapperPluginAutoApplyActionIntegTest.groovy
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.buildsetup.plugins.internal
+
+import org.gradle.buildsetup.plugins.fixtures.WrapperTestFixture
+import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+import org.gradle.test.fixtures.file.TestFile
+
+class WrapperPluginAutoApplyActionIntegTest extends AbstractIntegrationSpec {
+ final wrapper = new WrapperTestFixture(testDirectory)
+
+ def "can apply wrapper plugin dynamically"() {
+ when:
+ run 'tasks'
+ then:
+ output.contains("wrapper - Generates Gradle wrapper files.")
+
+ when:
+ run 'wrapper'
+ then:
+ wrapper.generated()
+ }
+
+ def "can use camel-case for dynamically applied wrapper plugin "() {
+ when:
+ run taskName
+ then:
+ wrapper.generated()
+ where:
+ taskName << ["wrapp"]//, "wrap", "w"]
+ }
+
+ def "wrapper plugin not applied on subprojects"() {
+ setup:
+ settingsFile << "include 'moduleA'"
+ TestFile subprojectsDir = file("moduleA").createDir()
+
+ when:
+ executer.inDirectory(subprojectsDir)
+ run 'tasks'
+ then:
+ !output.contains("wrapper - Generates Gradle wrapper files.")
+
+ when:
+ executer.inDirectory(subprojectsDir)
+ then:
+ fails("wrapper")
+ }
+
+ def "can reference dynamic applied wrapper plugin"() {
+ when:
+ buildFile << """
+ wrapper{
+ gradleVersion = '12.34'
+ }
+ """
+ run 'wrapper'
+ then:
+ wrapper.generated("12.34")
+ }
+
+ def "can depend on dynamic applied wrapper task"() {
+ when:
+ buildFile << """
+ task myTask(dependsOn:wrapper)
+ """
+ run 'myTask'
+ then:
+ wrapper.generated()
+ }
+
+ def "manually declared wrapper task is preferred"() {
+ when:
+ buildFile << """
+
+ task wrapper << {
+ println "running custom wrapper task"
+ }
+ """
+ run 'wrapper'
+ then:
+ output.contains("running custom wrapper task")
+ wrapper.notGenerated()
+ }
+}
diff --git a/subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/enforcerplugin/pom.xml b/subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/enforcerplugin/pom.xml
similarity index 100%
rename from subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/enforcerplugin/pom.xml
rename to subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/enforcerplugin/pom.xml
diff --git a/subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/enforcerplugin/src/main/java/Foo.java b/subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/enforcerplugin/src/main/java/Foo.java
similarity index 100%
rename from subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/enforcerplugin/src/main/java/Foo.java
rename to subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/enforcerplugin/src/main/java/Foo.java
diff --git a/subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/flatmultimodule/webinar-api/pom.xml b/subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/flatmultimodule/webinar-api/pom.xml
similarity index 100%
rename from subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/flatmultimodule/webinar-api/pom.xml
rename to subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/flatmultimodule/webinar-api/pom.xml
diff --git a/subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/flatmultimodule/webinar-api/src/main/java/webinar/Demoable.java b/subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/flatmultimodule/webinar-api/src/main/java/webinar/Demoable.java
similarity index 100%
rename from subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/flatmultimodule/webinar-api/src/main/java/webinar/Demoable.java
rename to subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/flatmultimodule/webinar-api/src/main/java/webinar/Demoable.java
diff --git a/subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/flatmultimodule/webinar-impl/pom.xml b/subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/flatmultimodule/webinar-impl/pom.xml
similarity index 100%
rename from subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/flatmultimodule/webinar-impl/pom.xml
rename to subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/flatmultimodule/webinar-impl/pom.xml
diff --git a/subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/flatmultimodule/webinar-impl/src/main/java/webinar/Webinar.java b/subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/flatmultimodule/webinar-impl/src/main/java/webinar/Webinar.java
similarity index 100%
rename from subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/flatmultimodule/webinar-impl/src/main/java/webinar/Webinar.java
rename to subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/flatmultimodule/webinar-impl/src/main/java/webinar/Webinar.java
diff --git a/subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/flatmultimodule/webinar-impl/src/test/java/webinar/WebinarTest.java b/subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/flatmultimodule/webinar-impl/src/test/java/webinar/WebinarTest.java
similarity index 100%
rename from subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/flatmultimodule/webinar-impl/src/test/java/webinar/WebinarTest.java
rename to subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/flatmultimodule/webinar-impl/src/test/java/webinar/WebinarTest.java
diff --git a/subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/flatmultimodule/webinar-parent/pom.xml b/subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/flatmultimodule/webinar-parent/pom.xml
similarity index 100%
rename from subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/flatmultimodule/webinar-parent/pom.xml
rename to subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/flatmultimodule/webinar-parent/pom.xml
diff --git a/subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/flatmultimodule/webinar-war/pom.xml b/subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/flatmultimodule/webinar-war/pom.xml
similarity index 100%
rename from subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/flatmultimodule/webinar-war/pom.xml
rename to subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/flatmultimodule/webinar-war/pom.xml
diff --git a/subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/flatmultimodule/webinar-war/src/main/webapp/WEB-INF/web.xml b/subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/flatmultimodule/webinar-war/src/main/webapp/WEB-INF/web.xml
similarity index 100%
rename from subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/flatmultimodule/webinar-war/src/main/webapp/WEB-INF/web.xml
rename to subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/flatmultimodule/webinar-war/src/main/webapp/WEB-INF/web.xml
diff --git a/subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/flatmultimodule/webinar-war/src/main/webapp/index.jsp b/subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/flatmultimodule/webinar-war/src/main/webapp/index.jsp
similarity index 100%
rename from subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/flatmultimodule/webinar-war/src/main/webapp/index.jsp
rename to subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/flatmultimodule/webinar-war/src/main/webapp/index.jsp
diff --git a/subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/mavenExtensions/pom.xml b/subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/mavenExtensions/pom.xml
new file mode 100644
index 0000000..d4aa30d
--- /dev/null
+++ b/subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/mavenExtensions/pom.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ This is the base POM for all dependent and inherited POMS of the DPJW application
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.test</groupId>
+ <artifactId>testApp</artifactId>
+ <version>1.0</version>
+ <packaging>pom</packaging>
+ <name>A Test Project</name>
+ <description>Some Test project</description>
+ <build>
+ <plugins>
+ <!-- set this project compiler to jdk version 1.6 -->
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.6</source>
+ <target>1.6</target>
+ </configuration>
+
+ </plugin>
+ <!-- the test plugin -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <excludes>
+ <exclude>**/HistoryConfigurationTest.java</exclude>
+ <exclude>**/TestDataFactory.java</exclude>
+ </excludes>
+ <forkMode>once</forkMode>
+ <reportFormat>xml</reportFormat>
+ </configuration>
+ </plugin>
+ </plugins>
+ <extensions>
+ <extension>
+ <groupId>mysql</groupId>
+ <artifactId>mysql-connector-java</artifactId>
+ <version>5.0.7</version>
+ </extension>
+ </extensions>
+ </build>
+</project>
\ No newline at end of file
diff --git a/subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/mavenExtensions/test-core/pom.xml b/subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/mavenExtensions/test-core/pom.xml
new file mode 100755
index 0000000..45f4d9c
--- /dev/null
+++ b/subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/mavenExtensions/test-core/pom.xml
@@ -0,0 +1,22 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.test</groupId>
+ <artifactId>testApp</artifactId>
+ <version>1.0</version>
+ </parent>
+
+ <artifactId>test-core</artifactId>
+ <name>test-core</name>
+ <packaging>jar</packaging>
+ <build>
+ <extensions>
+ <extension>
+ <groupId>mysql</groupId>
+ <artifactId>mysql-connector-java</artifactId>
+ <version>5.0.7</version>
+ </extension>
+ </extensions>
+ </build>
+</project>
diff --git a/subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/multiModule/pom.xml b/subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/multiModule/pom.xml
similarity index 100%
rename from subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/multiModule/pom.xml
rename to subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/multiModule/pom.xml
diff --git a/subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/multiModule/webinar-api/pom.xml b/subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/multiModule/webinar-api/pom.xml
similarity index 100%
rename from subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/multiModule/webinar-api/pom.xml
rename to subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/multiModule/webinar-api/pom.xml
diff --git a/subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/multiModule/webinar-api/src/main/java/webinar/Demoable.java b/subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/multiModule/webinar-api/src/main/java/webinar/Demoable.java
similarity index 100%
rename from subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/multiModule/webinar-api/src/main/java/webinar/Demoable.java
rename to subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/multiModule/webinar-api/src/main/java/webinar/Demoable.java
diff --git a/subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/multiModule/webinar-impl/pom.xml b/subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/multiModule/webinar-impl/pom.xml
similarity index 100%
rename from subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/multiModule/webinar-impl/pom.xml
rename to subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/multiModule/webinar-impl/pom.xml
diff --git a/subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/multiModule/webinar-impl/src/main/java/webinar/Webinar.java b/subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/multiModule/webinar-impl/src/main/java/webinar/Webinar.java
similarity index 100%
rename from subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/multiModule/webinar-impl/src/main/java/webinar/Webinar.java
rename to subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/multiModule/webinar-impl/src/main/java/webinar/Webinar.java
diff --git a/subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/multiModule/webinar-impl/src/test/java/webinar/WebinarTest.java b/subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/multiModule/webinar-impl/src/test/java/webinar/WebinarTest.java
similarity index 100%
rename from subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/multiModule/webinar-impl/src/test/java/webinar/WebinarTest.java
rename to subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/multiModule/webinar-impl/src/test/java/webinar/WebinarTest.java
diff --git a/subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/multiModule/webinar-war/pom.xml b/subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/multiModule/webinar-war/pom.xml
similarity index 100%
rename from subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/multiModule/webinar-war/pom.xml
rename to subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/multiModule/webinar-war/pom.xml
diff --git a/subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/multiModule/webinar-war/src/main/webapp/WEB-INF/web.xml b/subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/multiModule/webinar-war/src/main/webapp/WEB-INF/web.xml
similarity index 100%
rename from subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/multiModule/webinar-war/src/main/webapp/WEB-INF/web.xml
rename to subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/multiModule/webinar-war/src/main/webapp/WEB-INF/web.xml
diff --git a/subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/multiModule/webinar-war/src/main/webapp/index.jsp b/subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/multiModule/webinar-war/src/main/webapp/index.jsp
similarity index 100%
rename from subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/multiModule/webinar-war/src/main/webapp/index.jsp
rename to subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/multiModule/webinar-war/src/main/webapp/index.jsp
diff --git a/subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/providedNotWar/pom.xml b/subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/providedNotWar/pom.xml
new file mode 100644
index 0000000..911e15d
--- /dev/null
+++ b/subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/providedNotWar/pom.xml
@@ -0,0 +1,30 @@
+<!--
+ ~ Copyright 2013 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ 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.
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>myGroup</groupId>
+ <artifactId>myThing</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.10</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+</project>
\ No newline at end of file
diff --git a/subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/singleModule/pom.xml b/subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/singleModule/pom.xml
similarity index 100%
rename from subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/singleModule/pom.xml
rename to subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/singleModule/pom.xml
diff --git a/subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/singleModule/src/main/java/Foo.java b/subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/singleModule/src/main/java/Foo.java
similarity index 100%
rename from subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/singleModule/src/main/java/Foo.java
rename to subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/singleModule/src/main/java/Foo.java
diff --git a/subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/singleModule/src/test/java/FooTest.java b/subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/singleModule/src/test/java/FooTest.java
similarity index 100%
rename from subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/singleModule/src/test/java/FooTest.java
rename to subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/singleModule/src/test/java/FooTest.java
diff --git a/subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/testjar/pom.xml b/subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/testjar/pom.xml
similarity index 100%
rename from subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/testjar/pom.xml
rename to subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/testjar/pom.xml
diff --git a/subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/testjar/src/main/java/Foo.java b/subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/testjar/src/main/java/Foo.java
similarity index 100%
rename from subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/testjar/src/main/java/Foo.java
rename to subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/testjar/src/main/java/Foo.java
diff --git a/subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/testjar/src/test/java/FooTest.java b/subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/testjar/src/test/java/FooTest.java
similarity index 100%
rename from subprojects/maven/src/integTest/resources/org/gradle/api/plugins/maven/MavenConversionIntegrationTest/testjar/src/test/java/FooTest.java
rename to subprojects/build-setup/src/integTest/resources/org/gradle/buildsetup/plugins/MavenConversionIntegrationTest/testjar/src/test/java/FooTest.java
diff --git a/subprojects/build-setup/src/main/groovy/org/gradle/api/tasks/wrapper/Wrapper.java b/subprojects/build-setup/src/main/groovy/org/gradle/api/tasks/wrapper/Wrapper.java
new file mode 100644
index 0000000..68097ba
--- /dev/null
+++ b/subprojects/build-setup/src/main/groovy/org/gradle/api/tasks/wrapper/Wrapper.java
@@ -0,0 +1,278 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.tasks.wrapper;
+
+import org.gradle.api.DefaultTask;
+import org.gradle.api.GradleException;
+import org.gradle.api.internal.file.FileResolver;
+import org.gradle.api.internal.plugins.StartScriptGenerator;
+import org.gradle.api.tasks.Input;
+import org.gradle.api.tasks.OutputFile;
+import org.gradle.api.tasks.TaskAction;
+import org.gradle.util.*;
+import org.gradle.wrapper.GradleWrapperMain;
+import org.gradle.wrapper.Install;
+import org.gradle.wrapper.WrapperExecutor;
+
+import java.io.File;
+import java.net.URL;
+import java.util.Properties;
+
+/**
+ * <p>Generates scripts (for *nix and windows) which allow you to build your project with Gradle, without having to
+ * install Gradle.
+ *
+ * <p>When a user executes a wrapper script the first time, the script downloads and installs the appropriate Gradle
+ * distribution and runs the build against this downloaded distribution. Any installed Gradle distribution is ignored
+ * when using the wrapper scripts.
+ *
+ * <p>The scripts generated by this task are intended to be committed to your version control system. This task also
+ * generates a small {@code gradle-wrapper.jar} bootstrap JAR file and properties file which should also be committed to
+ * your VCS. The scripts delegates to this JAR.
+ */
+public class Wrapper extends DefaultTask {
+ public static final String DEFAULT_DISTRIBUTION_PARENT_NAME = Install.DEFAULT_DISTRIBUTION_PATH;
+
+ private String distributionUrl;
+
+ /**
+ * Specifies how the wrapper path should be interpreted.
+ */
+ public enum PathBase {
+ PROJECT, GRADLE_USER_HOME
+ }
+
+ private Object scriptFile;
+ private Object jarFile;
+
+ @Input
+ private String distributionPath;
+
+ @Input
+ private PathBase distributionBase = PathBase.GRADLE_USER_HOME;
+
+ private GradleVersion gradleVersion;
+
+ @Input
+ private String archivePath;
+
+ @Input
+ private PathBase archiveBase = PathBase.GRADLE_USER_HOME;
+
+ private final DistributionLocator locator = new DistributionLocator();
+
+ public Wrapper() {
+ scriptFile = "gradlew";
+ jarFile = "gradle/wrapper/gradle-wrapper.jar";
+ distributionPath = DEFAULT_DISTRIBUTION_PARENT_NAME;
+ archivePath = DEFAULT_DISTRIBUTION_PARENT_NAME;
+ gradleVersion = GradleVersion.current();
+ }
+
+ @TaskAction
+ void generate() {
+ File jarFileDestination = getJarFile();
+ File unixScript = getScriptFile();
+ FileResolver resolver = getServices().get(FileResolver.class).withBaseDir(unixScript.getParentFile());
+ String jarFileRelativePath = resolver.resolveAsRelativePath(jarFileDestination);
+
+ writeProperties(getPropertiesFile());
+
+ URL jarFileSource = Wrapper.class.getResource("/gradle-wrapper.jar");
+ if (jarFileSource == null) {
+ throw new GradleException("Cannot locate wrapper JAR resource.");
+ }
+ GFileUtils.copyURLToFile(jarFileSource, jarFileDestination);
+
+ StartScriptGenerator generator = new StartScriptGenerator();
+ generator.setApplicationName("Gradle");
+ generator.setMainClassName(GradleWrapperMain.class.getName());
+ generator.setClasspath(WrapUtil.toList(jarFileRelativePath));
+ generator.setOptsEnvironmentVar("GRADLE_OPTS");
+ generator.setExitEnvironmentVar("GRADLE_EXIT_CONSOLE");
+ generator.setAppNameSystemProperty("org.gradle.appname");
+ generator.setScriptRelPath(unixScript.getName());
+ generator.generateUnixScript(unixScript);
+ generator.generateWindowsScript(getBatchScript());
+ }
+
+ private void writeProperties(File propertiesFileDestination) {
+ Properties wrapperProperties = new Properties();
+ wrapperProperties.put(WrapperExecutor.DISTRIBUTION_URL_PROPERTY, getDistributionUrl());
+ wrapperProperties.put(WrapperExecutor.DISTRIBUTION_BASE_PROPERTY, distributionBase.toString());
+ wrapperProperties.put(WrapperExecutor.DISTRIBUTION_PATH_PROPERTY, distributionPath);
+ wrapperProperties.put(WrapperExecutor.ZIP_STORE_BASE_PROPERTY, archiveBase.toString());
+ wrapperProperties.put(WrapperExecutor.ZIP_STORE_PATH_PROPERTY, archivePath);
+ GUtil.saveProperties(wrapperProperties, propertiesFileDestination);
+ }
+
+ /**
+ * Returns the file to write the wrapper script to.
+ */
+ @OutputFile
+ public File getScriptFile() {
+ return getProject().file(scriptFile);
+ }
+
+ public void setScriptFile(Object scriptFile) {
+ this.scriptFile = scriptFile;
+ }
+
+ /**
+ * Returns the file to write the wrapper batch script to.
+ */
+ @OutputFile
+ public File getBatchScript() {
+ File scriptFile = getScriptFile();
+ return new File(scriptFile.getParentFile(), scriptFile.getName().replaceFirst("(\\.[^\\.]+)?$", ".bat"));
+ }
+
+ /**
+ * Returns the file to write the wrapper jar file to.
+ */
+ @OutputFile
+ public File getJarFile() {
+ return getProject().file(jarFile);
+ }
+
+ public void setJarFile(Object jarFile) {
+ this.jarFile = jarFile;
+ }
+
+ /**
+ * Returns the file to write the wrapper properties to.
+ */
+ @OutputFile
+ public File getPropertiesFile() {
+ File jarFileDestination = getJarFile();
+ return new File(jarFileDestination.getParentFile(), jarFileDestination.getName().replaceAll("\\.jar$",
+ ".properties"));
+ }
+
+ /**
+ * Returns the path where the gradle distributions needed by the wrapper are unzipped. The path is relative to the
+ * distribution base directory
+ *
+ * @see #setDistributionPath(String)
+ */
+ public String getDistributionPath() {
+ return distributionPath;
+ }
+
+ /**
+ * Sets the path where the gradle distributions needed by the wrapper are unzipped. The path is relative to the
+ * distribution base directory
+ *
+ * @see #setDistributionPath(String)
+ */
+ public void setDistributionPath(String distributionPath) {
+ this.distributionPath = distributionPath;
+ }
+
+ /**
+ * Returns the gradle version for the wrapper.
+ *
+ * @see #setGradleVersion(String)
+ */
+ public String getGradleVersion() {
+ return gradleVersion.getVersion();
+ }
+
+ /**
+ * The version of the gradle distribution required by the wrapper. This is usually the same version of Gradle you
+ * use for building your project.
+ */
+ public void setGradleVersion(String gradleVersion) {
+ this.gradleVersion = GradleVersion.version(gradleVersion);
+ }
+
+ /**
+ * The URL to download the gradle distribution from.
+ *
+ * <p>If not set, the download URL is the default for the specified {@link #getGradleVersion()}.
+ *
+ * <p>If {@link #getGradleVersion()} is not set, will return null.
+ *
+ * <p>The wrapper downloads a certain distribution only once and caches it. If your distribution base is the
+ * project, you might submit the distribution to your version control system. That way no download is necessary at
+ * all. This might be in particular interesting, if you provide a custom gradle snapshot to the wrapper, because you
+ * don't need to provide a download server then.
+ */
+ @Input
+ public String getDistributionUrl() {
+ if (distributionUrl != null) {
+ return distributionUrl;
+ } else if (gradleVersion != null) {
+ return locator.getDistributionFor(gradleVersion).toString();
+ } else {
+ return null;
+ }
+ }
+
+ public void setDistributionUrl(String url) {
+ this.distributionUrl = url;
+ }
+
+ /**
+ * The distribution base specifies whether the unpacked wrapper distribution should be stored in the project or in
+ * the gradle user home dir.
+ */
+ public PathBase getDistributionBase() {
+ return distributionBase;
+ }
+
+ /**
+ * The distribution base specifies whether the unpacked wrapper distribution should be stored in the project or in
+ * the gradle user home dir.
+ */
+ public void setDistributionBase(PathBase distributionBase) {
+ this.distributionBase = distributionBase;
+ }
+
+ /**
+ * Returns the path where the gradle distributions archive should be saved (i.e. the parent dir). The path is
+ * relative to the archive base directory.
+ */
+ public String getArchivePath() {
+ return archivePath;
+ }
+
+ /**
+ * Set's the path where the gradle distributions archive should be saved (i.e. the parent dir). The path is relative
+ * to the parent dir specified with {@link #getArchiveBase()}.
+ */
+ public void setArchivePath(String archivePath) {
+ this.archivePath = archivePath;
+ }
+
+ /**
+ * The archive base specifies whether the unpacked wrapper distribution should be stored in the project or in the
+ * gradle user home dir.
+ */
+ public PathBase getArchiveBase() {
+ return archiveBase;
+ }
+
+ /**
+ * The archive base specifies whether the unpacked wrapper distribution should be stored in the project or in the
+ * gradle user home dir.
+ */
+ public void setArchiveBase(PathBase archiveBase) {
+ this.archiveBase = archiveBase;
+ }
+
+}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/wrapper/package-info.java b/subprojects/build-setup/src/main/groovy/org/gradle/api/tasks/wrapper/package-info.java
similarity index 100%
rename from subprojects/plugins/src/main/groovy/org/gradle/api/tasks/wrapper/package-info.java
rename to subprojects/build-setup/src/main/groovy/org/gradle/api/tasks/wrapper/package-info.java
diff --git a/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/BuildSetupPlugin.groovy b/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/BuildSetupPlugin.groovy
new file mode 100644
index 0000000..283fe7d
--- /dev/null
+++ b/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/BuildSetupPlugin.groovy
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.buildsetup.plugins
+
+import org.gradle.api.Incubating
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.api.Task
+import org.gradle.api.internal.DocumentationRegistry
+import org.gradle.api.internal.artifacts.DependencyManagementServices
+import org.gradle.api.internal.artifacts.mvnsettings.MavenSettingsProvider
+import org.gradle.api.internal.file.FileResolver
+import org.gradle.buildsetup.plugins.internal.ProjectLayoutSetupRegistry
+import org.gradle.buildsetup.plugins.internal.ProjectLayoutSetupRegistryFactory
+import org.gradle.buildsetup.tasks.SetupBuild
+
+import javax.inject.Inject
+
+ at Incubating
+class BuildSetupPlugin implements Plugin<Project> {
+ public static final String SETUP_BUILD_TASK_NAME = "setupBuild"
+ public static final String GROUP = 'Build Setup'
+
+ private final MavenSettingsProvider mavenSettingsProvider
+ private final DocumentationRegistry documentationRegistry
+ private final FileResolver fileResolver
+
+ @Inject
+ BuildSetupPlugin(DependencyManagementServices dependencyManagementServices, DocumentationRegistry documentationRegistry, FileResolver fileResolver) {
+ this.fileResolver = fileResolver
+ this.documentationRegistry = documentationRegistry
+ this.mavenSettingsProvider = dependencyManagementServices.get(MavenSettingsProvider)
+ }
+
+ void apply(Project project) {
+ ProjectLayoutSetupRegistryFactory projectLayoutRegistryFactory = new ProjectLayoutSetupRegistryFactory(mavenSettingsProvider,
+ documentationRegistry,
+ fileResolver);
+
+ Task setupBuild = project.getTasks().create(SETUP_BUILD_TASK_NAME, SetupBuild);
+ ProjectLayoutSetupRegistry projectLayoutRegistry = projectLayoutRegistryFactory.createProjectLayoutSetupRegistry()
+ setupBuild.projectLayoutRegistry = projectLayoutRegistry
+ setupBuild.group = GROUP
+ setupBuild.description = "Initializes a new Gradle build. [incubating]"
+ Closure setupCanBeSkipped = {
+ if (project.file("build.gradle").exists()) {
+ return ("The build file 'build.gradle' already exists. Skipping build initialization.")
+ }
+ if (project.buildFile?.exists()) {
+ return ("The build file '$project.buildFile.name' already exists. Skipping build initialization.")
+ }
+ if (project.file("settings.gradle").exists()) {
+ return ("The settings file 'settings.gradle' already exists. Skipping build initialization.")
+ }
+ if (project.subprojects.size() > 0) {
+ return ("This Gradle project appears to be part of an existing multi-project Gradle build. Skipping build initialization.")
+ }
+ return null
+ }
+ setupBuild.onlyIf {
+ def skippedMsg = setupCanBeSkipped()
+ if (skippedMsg) {
+ project.logger.warn skippedMsg
+ return false
+ }
+ return true
+ }
+
+ if (!setupCanBeSkipped()) {
+ setupBuild.dependsOn("wrapper")
+ }
+ }
+}
\ No newline at end of file
diff --git a/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/WrapperPlugin.groovy b/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/WrapperPlugin.groovy
new file mode 100644
index 0000000..682890a
--- /dev/null
+++ b/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/WrapperPlugin.groovy
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.buildsetup.plugins
+
+import org.gradle.api.Incubating
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.api.Task
+import org.gradle.api.tasks.wrapper.Wrapper
+
+ at Incubating
+class WrapperPlugin implements Plugin<Project> {
+ void apply(Project project) {
+ Task wrapper = project.tasks.create("wrapper", Wrapper)
+ wrapper.group = BuildSetupPlugin.GROUP
+ wrapper.description = "Generates Gradle wrapper files. [incubating]"
+ }
+}
diff --git a/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/BasicProjectSetupDescriptor.groovy b/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/BasicProjectSetupDescriptor.groovy
new file mode 100644
index 0000000..62178b5
--- /dev/null
+++ b/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/BasicProjectSetupDescriptor.groovy
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.buildsetup.plugins.internal
+
+import org.gradle.api.internal.DocumentationRegistry
+import org.gradle.api.internal.file.FileResolver
+
+class BasicProjectSetupDescriptor extends TemplateBasedProjectSetupDescriptor {
+
+ public BasicProjectSetupDescriptor(FileResolver fileResolver, DocumentationRegistry documentationRegistry) {
+ super(fileResolver, documentationRegistry)
+ }
+
+ String getId() {
+ BuildSetupTypeIds.BASIC
+ }
+
+ @Override
+ URL getBuildFileTemplate() {
+ return BasicProjectSetupDescriptor.class.getResource("/org/gradle/buildsetup/tasks/templates/build.gradle.template");
+ }
+
+ @Override
+ URL getSettingsTemplate() {
+ return BasicProjectSetupDescriptor.class.getResource("/org/gradle/buildsetup/tasks/templates/settings.gradle.template")
+ }
+}
diff --git a/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/BuildSetupAutoApplyAction.java b/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/BuildSetupAutoApplyAction.java
new file mode 100644
index 0000000..0fa2b0d
--- /dev/null
+++ b/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/BuildSetupAutoApplyAction.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.buildsetup.plugins.internal;
+
+import org.gradle.api.internal.project.ProjectInternal;
+import org.gradle.configuration.project.ProjectConfigureAction;
+
+public class BuildSetupAutoApplyAction implements ProjectConfigureAction {
+
+ public void execute(final ProjectInternal projectInternal) {
+ if (projectInternal.getParent() == null) {
+ projectInternal.getTasks().addPlaceholderAction("setupBuild", new Runnable() {
+ public void run() {
+ projectInternal.getPlugins().apply("build-setup");
+ }
+ });
+ }
+ }
+}
diff --git a/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/BuildSetupTypeIds.java b/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/BuildSetupTypeIds.java
new file mode 100644
index 0000000..8f3bd58
--- /dev/null
+++ b/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/BuildSetupTypeIds.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.buildsetup.plugins.internal;
+
+public abstract class BuildSetupTypeIds {
+
+ private BuildSetupTypeIds() {}
+
+ public static final String BASIC = "basic";
+ public static final String POM = "pom";
+ public static final String JAVA_LIBRARY = "java-library";
+
+}
diff --git a/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/JavaLibraryProjectSetupDescriptor.groovy b/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/JavaLibraryProjectSetupDescriptor.groovy
new file mode 100644
index 0000000..01e9be7
--- /dev/null
+++ b/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/JavaLibraryProjectSetupDescriptor.groovy
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.buildsetup.plugins.internal
+
+import org.gradle.api.internal.DocumentationRegistry
+import org.gradle.api.internal.file.FileResolver
+
+class JavaLibraryProjectSetupDescriptor extends TemplateBasedProjectSetupDescriptor {
+
+ private final FileResolver fileResolver
+
+ public JavaLibraryProjectSetupDescriptor(FileResolver fileResolver, DocumentationRegistry documentationRegistry) {
+ super(fileResolver, documentationRegistry);
+ this.fileResolver = fileResolver;
+ }
+
+ String getId() {
+ BuildSetupTypeIds.JAVA_LIBRARY
+ }
+
+ URL getBuildFileTemplate() {
+ return JavaLibraryProjectSetupDescriptor.class.getResource("/org/gradle/buildsetup/tasks/templates/java-library-build.gradle.template");
+ }
+
+ URL getSettingsTemplate() {
+ return JavaLibraryProjectSetupDescriptor.class.getResource("/org/gradle/buildsetup/tasks/templates/settings.gradle.template")
+ }
+
+ void generateProjectSources() {
+ if (fileResolver.resolveFilesAsTree("src/main/java").empty || fileResolver.resolveFilesAsTree("src/test/java").empty) {
+ generateClass("src/main/java", "Library.java")
+ generateClass("src/test/java", "LibraryTest.java")
+ }
+ }
+
+ def generateClass(String sourceRoot, String clazzFileName) {
+ File sourceRootFolder = fileResolver.resolve(sourceRoot)
+ sourceRootFolder.mkdirs()
+ File clazzFile = new File(sourceRootFolder, clazzFileName)
+ URL productionClazzFileTemplate = JavaLibraryProjectSetupDescriptor.class.getResource("/org/gradle/buildsetup/tasks/templates/${clazzFileName}.template");
+ generateFileFromTemplate(productionClazzFileTemplate, clazzFile, [:])
+ }
+}
\ No newline at end of file
diff --git a/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/PomProjectSetupDescriptor.groovy b/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/PomProjectSetupDescriptor.groovy
new file mode 100644
index 0000000..0c4302a
--- /dev/null
+++ b/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/PomProjectSetupDescriptor.groovy
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.buildsetup.plugins.internal
+
+import org.gradle.api.internal.artifacts.mvnsettings.MavenSettingsProvider
+import org.gradle.api.internal.file.FileResolver
+import org.gradle.buildsetup.plugins.internal.maven.Maven2Gradle
+import org.gradle.buildsetup.plugins.internal.maven.MavenConversionException
+import org.gradle.buildsetup.plugins.internal.maven.MavenProjectsCreator
+import org.gradle.util.SingleMessageLogger
+
+class PomProjectSetupDescriptor implements ProjectSetupDescriptor {
+ private final MavenSettingsProvider settingsProvider
+ private final FileResolver fileResolver
+
+
+ PomProjectSetupDescriptor(FileResolver fileResolver, MavenSettingsProvider mavenSettingsProvider) {
+ this.fileResolver = fileResolver
+ this.settingsProvider = mavenSettingsProvider
+ }
+
+ String getId() {
+ BuildSetupTypeIds.POM
+ }
+
+ void generateProject() {
+ SingleMessageLogger.incubatingFeatureUsed("Maven to Gradle conversion")
+ def pom = fileResolver.resolve("pom.xml")
+ try {
+ def settings = settingsProvider.buildSettings()
+ def mavenProjects = new MavenProjectsCreator().create(settings, pom)
+ new Maven2Gradle(mavenProjects).convert()
+ } catch (Exception exception) {
+ throw new MavenConversionException("Could not convert Maven POM $pom to a Gradle build.", exception)
+ }
+ }
+}
diff --git a/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/ProjectLayoutSetupRegistry.groovy b/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/ProjectLayoutSetupRegistry.groovy
new file mode 100644
index 0000000..dacc465
--- /dev/null
+++ b/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/ProjectLayoutSetupRegistry.groovy
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.buildsetup.plugins.internal
+
+import org.gradle.api.GradleException
+import org.gradle.api.logging.Logger
+import org.gradle.api.logging.Logging
+
+class ProjectLayoutSetupRegistry {
+
+ private final Logger logger = Logging.getLogger(ProjectLayoutSetupRegistry.class);
+ private final Map<String, ProjectSetupDescriptor> registeredProjectDescriptors = new HashMap<String, ProjectSetupDescriptor>();
+
+ void add(ProjectSetupDescriptor descriptor) {
+ if (registeredProjectDescriptors.containsKey(descriptor.id)) {
+ throw new GradleException("ProjectDescriptor with ID '${descriptor.id}' already registered.")
+ }
+ registeredProjectDescriptors.put(descriptor.id, descriptor)
+ logger.debug("registered setupDescriptor {}", descriptor.id)
+ }
+
+ ProjectSetupDescriptor get(String type) {
+ return registeredProjectDescriptors.get(type)
+ }
+
+ List<ProjectSetupDescriptor> getAll() {
+ return Arrays.asList(registeredProjectDescriptors.values())
+ }
+
+ boolean supports(String type) {
+ return get(type) != null
+ }
+}
diff --git a/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/ProjectLayoutSetupRegistryFactory.groovy b/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/ProjectLayoutSetupRegistryFactory.groovy
new file mode 100644
index 0000000..6647bdb
--- /dev/null
+++ b/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/ProjectLayoutSetupRegistryFactory.groovy
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.buildsetup.plugins.internal
+
+import org.gradle.api.internal.DocumentationRegistry
+import org.gradle.api.internal.artifacts.mvnsettings.MavenSettingsProvider
+import org.gradle.api.internal.file.FileResolver
+
+class ProjectLayoutSetupRegistryFactory {
+ private final DocumentationRegistry documentationRegistry
+ private final MavenSettingsProvider mavenSettingsProvider
+ private final FileResolver fileResolver
+
+ public ProjectLayoutSetupRegistryFactory(MavenSettingsProvider mavenSettingsProvider,
+ DocumentationRegistry documentationRegistry,
+ FileResolver fileResolver) {
+ this.mavenSettingsProvider = mavenSettingsProvider
+ this.documentationRegistry = documentationRegistry
+ this.fileResolver = fileResolver
+ }
+
+ ProjectLayoutSetupRegistry createProjectLayoutSetupRegistry() {
+ ProjectLayoutSetupRegistry registry = new ProjectLayoutSetupRegistry()
+
+ // TODO maybe referencing the implementation class here is enough and instantiation
+ // should be defererred when descriptor is requested.
+ registry.add(new BasicProjectSetupDescriptor(fileResolver, documentationRegistry));
+ registry.add(new JavaLibraryProjectSetupDescriptor(fileResolver, documentationRegistry));
+ registry.add(new PomProjectSetupDescriptor(fileResolver, mavenSettingsProvider))
+ return registry
+ }
+
+}
diff --git a/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/ProjectSetupDescriptor.groovy b/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/ProjectSetupDescriptor.groovy
new file mode 100644
index 0000000..9edb334
--- /dev/null
+++ b/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/ProjectSetupDescriptor.groovy
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.buildsetup.plugins.internal
+
+interface ProjectSetupDescriptor {
+
+ String getId()
+
+ void generateProject()
+
+}
diff --git a/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/TemplateBasedProjectSetupDescriptor.groovy b/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/TemplateBasedProjectSetupDescriptor.groovy
new file mode 100644
index 0000000..e5e35cb
--- /dev/null
+++ b/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/TemplateBasedProjectSetupDescriptor.groovy
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.buildsetup.plugins.internal
+
+import groovy.text.SimpleTemplateEngine
+import groovy.text.Template
+import org.gradle.api.internal.DocumentationRegistry
+import org.gradle.api.internal.file.FileResolver
+import org.gradle.util.GradleVersion
+
+import java.text.DateFormat
+
+abstract class TemplateBasedProjectSetupDescriptor implements ProjectSetupDescriptor {
+
+ private final DocumentationRegistry documentationRegistry
+ private final FileResolver fileResolver
+
+ TemplateBasedProjectSetupDescriptor(FileResolver fileResolver, DocumentationRegistry documentationRegistry) {
+ this.fileResolver = fileResolver
+ this.documentationRegistry = documentationRegistry
+ }
+
+ abstract URL getBuildFileTemplate()
+
+ abstract URL getSettingsTemplate()
+
+ void generateProject() {
+ generateGradleFiles()
+ generateProjectSources()
+ }
+
+ void generateProjectSources() {
+ }
+
+ def generateGradleFiles() {
+ generateFileFromTemplate(getBuildFileTemplate(), fileResolver.resolve("build.gradle"), getAdditionalBuildFileTemplateBindings())
+ generateFileFromTemplate(getSettingsTemplate(), fileResolver.resolve("settings.gradle"), getAdditionalSettingsFileTemplateBindings())
+ }
+
+ protected Map getAdditionalBuildFileTemplateBindings() {
+ return [ref_userguide_java_tutorial: documentationRegistry.getDocumentationFor("tutorial_java_projects")]
+ }
+
+ protected Map getAdditionalSettingsFileTemplateBindings() {
+ return [ref_userguide_multiproject: documentationRegistry.getDocumentationFor("multi_project_builds"), rootProjectName: fileResolver.resolve(".").name]
+ }
+
+ protected generateFileFromTemplate(URL templateURL, File targetFile, Map additionalBindings) {
+ SimpleTemplateEngine templateEngine = new SimpleTemplateEngine()
+ String now = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT).format(new Date())
+ def bindings = [genDate: now, genUser: System.getProperty("user.name"), genGradleVersion: GradleVersion.current().toString()]
+ bindings += additionalBindings
+ Template template = templateEngine.createTemplate(templateURL.text)
+ Map wrappedBindings = bindings.collectEntries { key, value -> [key, new TemplateValue(value.toString())] }
+ targetFile.withWriter("utf-8") { writer ->
+ template.make(wrappedBindings).writeTo(writer)
+ }
+ }
+}
diff --git a/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/TemplateValue.java b/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/TemplateValue.java
new file mode 100644
index 0000000..9e05f53
--- /dev/null
+++ b/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/TemplateValue.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.buildsetup.plugins.internal;
+
+public class TemplateValue {
+ private final String value;
+
+ public TemplateValue(String value) {
+ this.value = value;
+ }
+
+ public String getGroovyComment() {
+ return value.replace("\\", "\\\\");
+ }
+
+ public String getGroovyString() {
+ StringBuilder result = new StringBuilder();
+ for (int i = 0; i < value.length(); i++) {
+ char ch = value.charAt(i);
+ switch (ch) {
+ case '\\':
+ result.append('\\').append('\\');
+ break;
+ case '\'':
+ result.append('\\').append('\'');
+ break;
+ case '\n':
+ result.append('\\').append('n');
+ break;
+ case '\r':
+ result.append('\\').append('r');
+ break;
+ case '\t':
+ result.append('\\').append('t');
+ break;
+ case '\f':
+ result.append('\\').append('f');
+ break;
+ case '\b':
+ result.append('\\').append('b');
+ break;
+ default:
+ result.append(ch);
+ }
+ }
+ return result.toString();
+ }
+
+ @Override
+ public String toString() {
+ return String.format(">>>%s<<<", value);
+ }
+}
diff --git a/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/WrapperPluginAutoApplyAction.groovy b/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/WrapperPluginAutoApplyAction.groovy
new file mode 100644
index 0000000..570e3d4
--- /dev/null
+++ b/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/WrapperPluginAutoApplyAction.groovy
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.buildsetup.plugins.internal
+
+import org.gradle.api.internal.project.ProjectInternal
+import org.gradle.configuration.project.ProjectConfigureAction
+
+class WrapperPluginAutoApplyAction implements ProjectConfigureAction {
+ void execute(ProjectInternal projectInternal) {
+ if (projectInternal.getParent() == null) {
+ projectInternal.tasks.addPlaceholderAction("wrapper", new Runnable() {
+ void run() {
+ projectInternal.getPlugins().apply("wrapper")
+ }
+ })
+ }
+ }
+}
diff --git a/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/maven/Maven2Gradle.groovy b/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/maven/Maven2Gradle.groovy
new file mode 100644
index 0000000..55a108c
--- /dev/null
+++ b/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/maven/Maven2Gradle.groovy
@@ -0,0 +1,514 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.buildsetup.plugins.internal.maven
+
+import org.gradle.mvn3.org.apache.maven.project.MavenProject
+import org.gradle.util.GFileUtils
+
+/**
+ * This script obtains the effective POM of the current project, reads its dependencies
+ * and generates build.gradle scripts. It also generates settings.gradle for multimodule builds. <br/>
+ *
+ * It currently supports both single-module and multi-module POMs, inheritance, dependency management, properties - everything.
+ */
+class Maven2Gradle {
+
+ def dependentWars = []
+ def qualifiedNames
+ def workingDir
+ def effectivePom
+
+ private Set<MavenProject> mavenProjects
+
+ Maven2Gradle(Set<MavenProject> mavenProjects) {
+ assert !mavenProjects.empty: "No Maven projects provided."
+ this.mavenProjects = mavenProjects
+ }
+
+ def convert() {
+ workingDir = new File('.').canonicalFile
+
+ //For now we're building the effective POM XML from the model
+ //and then we parse the XML using slurper.
+ //This way we don't have to rewrite the Maven2Gradle just yet.
+ //Maven2Gradle should be rewritten (with coverage) so that feeds of the maven object model, not XML.
+ def effectivePom = new MavenProjectXmlWriter().toXml(mavenProjects)
+ //use the Groovy XmlSlurper library to parse the text string
+ this.effectivePom = new XmlSlurper().parseText(effectivePom)
+
+ String build
+ def multimodule = this.effectivePom.name() == "projects"
+
+ if (multimodule) {
+ def allProjects = this.effectivePom.project
+ qualifiedNames = generateSettings(workingDir.getName(), allProjects[0].artifactId, allProjects);
+ def dependencies = [:];
+ allProjects.each { project ->
+ dependencies[project.artifactId.text()] = getDependencies(project, allProjects)
+ }
+
+ def commonDeps = dependencies.get(allProjects[0].artifactId.text())
+ build = """allprojects {
+ apply plugin: 'maven'
+
+ ${getArtifactData(allProjects[0])}
+}
+
+subprojects {
+ apply plugin: 'java'
+ ${compilerSettings(allProjects[0], " ")}
+ ${packageSources(allProjects[0])}
+ ${getRepositoriesForProjects(allProjects)}
+ ${globalExclusions(allProjects[0])}
+ ${commonDeps}
+ ${testNg(commonDeps)}
+}
+"""
+ modules(allProjects, false).each { module ->
+ def id = module.artifactId.text()
+ String moduleDependencies = dependencies.get(id)
+ boolean warPack = module.packaging.text().equals("war")
+ def hasDependencies = !(moduleDependencies == null || moduleDependencies.length() == 0)
+ File submoduleBuildFile = new File(projectDir(module), 'build.gradle')
+ def group = ''
+ if (module.groupId != allProjects[0].groupId) {
+ group = "group = '${module.groupId}'"
+ }
+ String moduleBuild = """
+${group}
+description = '${module.name}'
+
+"""
+ if (warPack) {
+ moduleBuild += """apply plugin: 'war'
+
+"""
+ if (dependentWars.any { project ->
+ project.groupId.text() == module.groupId.text() &&
+ project.artifactId.text() == id
+ }) {
+ moduleBuild += """jar.enabled = true
+"""
+ }
+ }
+ if (hasDependencies) {
+ moduleBuild += moduleDependencies
+ }
+
+ moduleBuild += testNg(moduleDependencies)
+
+ if (submoduleBuildFile.exists()) {
+ submoduleBuildFile.renameTo(new File("build.gradle.bak"))
+ }
+ def packageTests = packageTests(module);
+ if (packageTests) {
+ moduleBuild += packageTests;
+ }
+ submoduleBuildFile.text = moduleBuild
+ }
+ //TODO deployment
+ } else {//simple
+ build = """apply plugin: 'java'
+apply plugin: 'maven'
+
+${getArtifactData(this.effectivePom)}
+
+description = \"""${this.effectivePom.name}\"""
+
+${compilerSettings(this.effectivePom, "")}
+${globalExclusions(this.effectivePom)}
+
+"""
+
+ Set<String> repoSet = new LinkedHashSet<String>();
+ getRepositoriesForModule(this.effectivePom, repoSet)
+ String repos = """repositories {
+ $localRepoUri
+"""
+ repoSet.each {
+ repos = "${repos} ${it}\n"
+ }
+ build += "${repos}}\n"
+ String dependencies = getDependencies(this.effectivePom, null)
+ build += dependencies
+
+ String packageTests = packageTests(this.effectivePom);
+ if (packageTests) {
+ build += '//packaging tests'
+ build += packageTests;
+ }
+ generateSettings(workingDir.getName(), this.effectivePom.artifactId, null);
+ }
+ def buildFile = new File("build.gradle")
+ if (buildFile.exists()) {
+ buildFile.renameTo(new File("build.gradle.bak"))
+ }
+ buildFile.text = build
+ }
+
+ def globalExclusions = { project ->
+ def exclusions = ''
+ def enforcerPlugin = plugin('maven-enforcer-plugin', project)
+ def enforceGoal = pluginGoal('enforce', enforcerPlugin)
+ if (enforceGoal) {
+ exclusions += 'configurations.all {\n'
+ enforceGoal.configuration.rules.bannedDependencies.excludes.childNodes().each {
+ def tokens = it.text().tokenize(':')
+ exclusions += "it.exclude group: '${tokens[0]}'"
+ if (tokens.size() > 1 && tokens[1] != '*') {
+ exclusions += ", module: '${tokens[1]}'"
+ }
+ exclusions += '\n'
+ }
+ }
+ exclusions = exclusions ? exclusions += '}' : exclusions
+ exclusions
+ }
+
+ def testNg = { moduleDependencies ->
+ if (moduleDependencies.contains('testng')) {
+ """test.useTestNG()
+"""
+ } else {
+ ''
+ }
+ }
+
+ def modules = { allProjects, incReactors ->
+ return allProjects.findAll { project ->
+ project.parent.text().length() > 0 && (incReactors || project.packaging.text() != 'pom')
+ }
+ }
+
+ def fqn = { project, allProjects ->
+ def buffer = new StringBuilder()
+ generateFqn(project, allProjects, buffer)
+ return buffer.toString()
+ }
+
+ private generateFqn(def project, def allProjects, StringBuilder buffer) {
+ def artifactId = project.artifactId.text()
+ buffer.insert(0, ":${artifactId}")
+ //we don't need the top-level parent in gradle, so we stop on it
+ if (project.parent.artifactId.text() != allProjects[0].artifactId.text()) {
+ generateFqn(allProjects.find { fullProject ->
+ fullProject.artifactId.text() == project.parent.artifactId.text()
+ }, allProjects, buffer)
+ }
+ }
+
+
+ def localRepoUri = {
+ """mavenLocal()
+ """
+ }
+
+ private String getArtifactData(project) {
+ return """group = '$project.groupId'
+version = '$project.version'""";
+ }
+
+ private String getRepositoriesForProjects(projects) {
+ String repos = """repositories {
+ ${localRepoUri()}
+"""
+ def repoSet = new LinkedHashSet<String>();
+ projects.each {
+ getRepositoriesForModule(it, repoSet)
+ }
+ repoSet.each {
+ repos = "${repos}${it}\n"
+ }
+ repos = "${repos} }\n"
+ return repos
+ }
+
+ private void getRepositoriesForModule(module, repoSet) {
+ module.repositories.repository.each {
+ repoSet.add(" maven { url \"${it.url}\" }")
+ }
+ //No need to include plugin repos - who cares about maven plugins?
+ }
+
+ private String getDependencies(project, allProjects) {
+ // use GPath to navigate the object hierarchy and retrieve the collection of dependency nodes.
+ def dependencies = project.dependencies.dependency
+ def war = project.packaging == "war"
+
+ def compileTimeScope = []
+ def runTimeScope = []
+ def testScope = []
+ def providedScope = []
+ def systemScope = []
+
+ //cleanup duplicates from parent
+
+// using Groovy Looping and mapping a Groovy Closure to each element, we collect together all
+// the dependency nodes into corresponding collections depending on their scope value.
+ dependencies.each() {
+ if (!duplicateDependency(it, project, allProjects)) {
+ def scope = (elementHasText(it.scope)) ? it.scope : "compile"
+ switch (scope) {
+ case "compile":
+ compileTimeScope.add(it)
+ break
+ case "test":
+ testScope.add(it)
+ break
+ case "provided":
+ providedScope.add(it)
+ break
+ case "runtime":
+ runTimeScope.add(it)
+ break
+ case "system":
+ systemScope.add(it)
+ break
+ }
+ }
+ }
+
+ /**
+ * print function then checks the exclusions node to see if it exists, if
+ * so it branches off, otherwise we call our simple print function
+ */
+ def createGradleDep = { String scope, StringBuilder sb, mavenDependency ->
+ def projectDep = allProjects.find { prj ->
+ return prj.artifactId.text() == mavenDependency.artifactId.text() && prj.groupId.text() == mavenDependency.groupId.text()
+ }
+
+ if (projectDep) {
+ createProjectDependency(projectDep, sb, scope, allProjects)
+ } else {
+ def providedMessage = "";
+ if (!war && scope == 'providedCompile') {
+ scope = 'compile'
+ providedMessage = '''\
+ /* This dependency was originally in the Maven provided scope, but the project was not of type war.
+ This behavior is not yet supported by Gradle, so this dependency has been converted to a compile dependency.
+ Please review and delete this closure when resolved. */
+ '''.stripIndent(16)
+ }
+ def exclusions = mavenDependency.exclusions.exclusion
+ if (exclusions.size() > 0 || providedMessage != "") {
+ createComplexDependency(mavenDependency, sb, scope, providedMessage)
+ } else {
+ createBasicDependency(mavenDependency, sb, scope)
+ }
+ }
+ }
+
+
+ StringBuilder build = new StringBuilder()
+ if (!compileTimeScope.isEmpty() || !runTimeScope.isEmpty() || !testScope.isEmpty() || !providedScope.isEmpty() || !systemScope.isEmpty()) {
+ build.append("dependencies {").append("\n")
+// for each collection, one at a time, we take each element and call our print function
+ if (!compileTimeScope.isEmpty()) {
+ compileTimeScope.each() { createGradleDep("compile", build, it) }
+ }
+ if (!runTimeScope.isEmpty()) {
+ runTimeScope.each() { createGradleDep("runtime", build, it) }
+ }
+ if (!testScope.isEmpty()) {
+ testScope.each() { createGradleDep("testCompile", build, it) }
+ }
+ if (!providedScope.isEmpty()) {
+ providedScope.each() { createGradleDep("providedCompile", build, it) }
+ }
+ if (!systemScope.isEmpty()) {
+ systemScope.each() { createGradleDep("system", build, it) }
+ }
+ build.append("}\n")
+ }
+ return build.toString();
+ }
+
+ def compilerSettings = { project, indent ->
+ def configuration = plugin('maven-compiler-plugin', project).configuration
+ return "sourceCompatibility = ${configuration.source.text() ?: '1.5'}\n${indent}targetCompatibility = ${configuration.target.text() ?: '1.5'}\n"
+ }
+
+ def plugin = { artifactId, project ->
+ project.build.plugins.plugin.find { pluginTag ->
+ pluginTag.artifactId.text() == artifactId
+ }
+ }
+
+ def pluginGoal = { goalName, plugin ->
+ plugin.executions.execution.find { exec ->
+ exec.goals.goal.find { gl ->
+ gl.text().startsWith(goalName)
+ }
+ }
+ }
+
+ def packSources = { sourceSets ->
+ def sourceSetStr = ''
+ if (!sourceSets.empty) {
+ sourceSetStr = """task packageSources(type: Jar) {
+classifier = 'sources'
+"""
+ sourceSets.each { sourceSet ->
+ sourceSetStr += """from sourceSets.${sourceSet}.allSource
+"""
+ }
+ sourceSetStr += """
+}
+artifacts.archives packageSources"""
+ }
+ sourceSetStr
+ }
+
+
+ def packageTests = { project ->
+ def jarPlugin = plugin('maven-jar-plugin', project)
+ pluginGoal('test-jar', jarPlugin) ? """
+task packageTests(type: Jar) {
+ from sourceSets.test.output
+ classifier = 'tests'
+}
+artifacts.archives packageTests
+""" : ''
+ }
+
+ def packageSources = { project ->
+ def sourcePlugin = plugin('maven-source-plugin', project)
+ def sourceSets = []
+ if (sourcePlugin) {
+ if (pluginGoal('jar', sourcePlugin)) {
+ sourceSets += 'main'
+ } else if (pluginGoal('test-jar', sourcePlugin)) {
+ sourceSets += 'test'
+ }
+ }
+ packSources(sourceSets)
+ }
+
+ private boolean duplicateDependency(dependency, project, allProjects) {
+ def parentTag = project.parent
+ if (allProjects == null || parentTag.isEmpty()) {//simple project or no parent
+ return false;
+ } else {
+ def parent = allProjects.find {
+ it.groupId.equals(parentTag.groupId) && it.artifactId.equals(parentTag.artifactId)
+ }
+ def duplicate = parent.dependencies.dependency.any {
+ it.groupId.equals(dependency.groupId) && it.artifactId.equals(dependency.artifactId)
+ }
+ if (duplicate) {
+ return true;
+ } else {
+ duplicateDependency(dependency, parent, allProjects)
+ }
+ }
+ }
+
+ def artifactId = { File dir ->
+ return new XmlSlurper().parse(new File(dir, 'pom.xml')).artifactId.text()
+ }
+
+ def projectDir = { project ->
+ return new File(project.build.directory.text()).parentFile
+ }
+
+ private def generateSettings(def dirName, def mvnProjectName, def projects) {
+ def qualifiedNames = [:]
+ def projectName = "";
+ if (dirName != mvnProjectName) {
+ projectName = """rootProject.name = '${mvnProjectName}'
+"""
+ }
+ def modulePoms = modules(projects, true)
+
+ def modules = new StringBuilder();
+ def artifactIdToDir = [:]
+ if (projects) {
+ modulePoms.each { project ->
+ def fqn = fqn(project, projects)
+ artifactIdToDir[fqn] = GFileUtils.relativePath(workingDir, projectDir(project))
+ modules.append("'${fqn}', ")
+ }
+ def strLength = modules.length()
+ if (strLength > 2) {
+ modules.delete(strLength - 2, strLength)
+ }
+ }
+ File settingsFile = new File("settings.gradle")
+ if (settingsFile.exists()) {
+ settingsFile.renameTo(new File("settings.gradle.bak"))
+ }
+ def settingsText = "${projectName}${modules.length() > 0 ? "include ${modules.toString()}" : ''}\n"
+ artifactIdToDir.each { entry ->
+ settingsText += """
+project('$entry.key').projectDir = """ + '"$rootDir/' + "${entry.value}" + '" as File'
+ }
+ settingsFile.text = settingsText
+ return qualifiedNames
+ }
+
+/**
+ * complex print statement does one extra task which is
+ * iterate over each <exclusion> node and print out the artifact id.
+ * It also provides review comments for the user.
+ */
+ private def createComplexDependency(it, build, scope, providedMessage) {
+ build.append(" ${scope}(${contructSignature(it)}) {\n")
+ it.exclusions.exclusion.each() {
+ build.append("exclude(module: '${it.artifactId}')\n")
+ }
+ if (providedMessage) {
+ build.append(providedMessage)
+ }
+ build.append(" }\n")
+ }
+
+/**
+ * Print out the basic form og gradle dependency
+ */
+ private def createBasicDependency(mavenDependency, build, String scope) {
+ def classifier = contructSignature(mavenDependency)
+ build.append(" ${scope} ${classifier}\n")
+ }
+/**
+ * Print out the basic form of gradle dependency
+ */
+ private def createProjectDependency(projectDep, build, String scope, allProjects) {
+ if (projectDep.packaging.text() == 'war') {
+ dependentWars += projectDep
+ }
+ build.append(" ${scope} project('${fqn(projectDep, allProjects)}')\n")
+ }
+
+/**
+ * Construct and return the signature of a dependency, including its version and
+ * classifier if it exists
+ */
+ private def contructSignature(mavenDependency) {
+ def gradelDep = "group: '${mavenDependency.groupId.text()}', name: '${mavenDependency.artifactId.text()}', version:'${mavenDependency?.version?.text()}'"
+ def classifier = elementHasText(mavenDependency.classifier) ? gradelDep + ", classifier:'" + mavenDependency.classifier.text().trim() + "'" : gradelDep
+ return classifier
+ }
+
+/**
+ * Check to see if the selected node has content
+ */
+ private boolean elementHasText(it) {
+ return it.text().length() != 0
+ }
+}
\ No newline at end of file
diff --git a/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/maven/MavenConversionException.java b/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/maven/MavenConversionException.java
new file mode 100644
index 0000000..aaf741b
--- /dev/null
+++ b/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/maven/MavenConversionException.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.buildsetup.plugins.internal.maven;
+import org.gradle.api.internal.Contextual;
+
+ at Contextual
+public class MavenConversionException extends RuntimeException {
+ public MavenConversionException(String message) {
+ super(message);
+ }
+
+ public MavenConversionException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/maven/MavenProjectXmlWriter.java b/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/maven/MavenProjectXmlWriter.java
new file mode 100644
index 0000000..e0620a3
--- /dev/null
+++ b/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/maven/MavenProjectXmlWriter.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.buildsetup.plugins.internal.maven;
+
+import org.gradle.mvn3.org.apache.maven.model.io.xpp3.MavenXpp3Writer;
+import org.gradle.mvn3.org.apache.maven.project.MavenProject;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Set;
+
+public class MavenProjectXmlWriter {
+
+ //TODO this class attempts to mimic the behavior of the output of mvn help:effective-pom
+ //instead of this class we should walk the maven project object model (instead of parsing the xml!)
+
+ String toXml(Set<MavenProject> projects) {
+ assert !projects.isEmpty() : "Cannot prepare the Maven projects effective XML because provided projects set is empty.";
+
+ if (projects.size() == 1) {
+ return toXml(projects.iterator().next());
+ }
+
+ StringBuilder out = new StringBuilder("<projects>");
+ for (MavenProject project : projects) {
+ out.append(toXml(project));
+ }
+ return out.append("</projects>").toString();
+ }
+
+ private String toXml(MavenProject project) {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ try {
+ new MavenXpp3Writer().write(out, project.getModel());
+ } catch (IOException e) {
+ throw new RuntimeException("Unable to serialize Maven model to XML. Maven project: " + project, e);
+ }
+ return prepareXml(out.toString());
+ }
+
+ String prepareXml(String xml) {
+ return xml.replaceFirst("^<\\?xml.+?\\?>", "");
+ }
+}
diff --git a/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/maven/MavenProjectsCreator.java b/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/maven/MavenProjectsCreator.java
new file mode 100644
index 0000000..1fd32e5
--- /dev/null
+++ b/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/plugins/internal/maven/MavenProjectsCreator.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.buildsetup.plugins.internal.maven;
+
+import com.google.common.collect.ImmutableList;
+import org.gradle.api.Transformer;
+import org.gradle.mvn3.org.apache.maven.execution.*;
+import org.gradle.mvn3.org.apache.maven.project.*;
+import org.gradle.mvn3.org.apache.maven.settings.Settings;
+import org.gradle.mvn3.org.codehaus.plexus.ContainerConfiguration;
+import org.gradle.mvn3.org.codehaus.plexus.DefaultContainerConfiguration;
+import org.gradle.mvn3.org.codehaus.plexus.DefaultPlexusContainer;
+import org.gradle.mvn3.org.codehaus.plexus.PlexusContainerException;
+import org.gradle.mvn3.org.codehaus.plexus.classworlds.ClassWorld;
+import org.gradle.mvn3.org.codehaus.plexus.component.repository.exception.ComponentLookupException;
+import org.gradle.mvn3.org.codehaus.plexus.configuration.PlexusConfigurationException;
+import org.gradle.mvn3.org.sonatype.aether.RepositorySystemSession;
+import org.gradle.mvn3.org.sonatype.aether.util.DefaultRepositorySystemSession;
+import org.gradle.util.CollectionUtils;
+
+import java.io.File;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+public class MavenProjectsCreator {
+
+ public Set<MavenProject> create(Settings mavenSettings, File pomFile) {
+ if (!pomFile.exists()) {
+ throw new MavenConversionException(String.format("Unable to create Maven project model. The POM file %s does not exist.", pomFile));
+ }
+ try {
+ return createNow(mavenSettings, pomFile);
+ } catch (Exception e) {
+ throw new MavenConversionException(String.format("Unable to create Maven project model using POM %s.", pomFile), e);
+ }
+ }
+
+ private Set<MavenProject> createNow(Settings settings, File pomFile) throws PlexusContainerException, PlexusConfigurationException, ComponentLookupException, MavenExecutionRequestPopulationException, ProjectBuildingException {
+ //using jarjar for maven3 classes affects the contents of the effective pom
+ //references to certain Maven standard plugins contain jarjar in the fqn
+ //not sure if this is a problem.
+ ContainerConfiguration containerConfiguration = new DefaultContainerConfiguration()
+ .setClassWorld(new ClassWorld("plexus.core", ClassWorld.class.getClassLoader()))
+ .setName("mavenCore");
+
+ DefaultPlexusContainer container = new DefaultPlexusContainer(containerConfiguration);
+ ProjectBuilder builder = container.lookup(ProjectBuilder.class);
+ MavenExecutionRequest executionRequest = new DefaultMavenExecutionRequest();
+ MavenExecutionRequestPopulator populator = container.lookup(MavenExecutionRequestPopulator.class);
+ populator.populateFromSettings(executionRequest, settings);
+ populator.populateDefaults(executionRequest);
+ ProjectBuildingRequest buildingRequest = executionRequest.getProjectBuildingRequest();
+ buildingRequest.setProcessPlugins(false);
+ MavenProject mavenProject = builder.build(pomFile, buildingRequest).getProject();
+ Set<MavenProject> reactorProjects = new LinkedHashSet<MavenProject>();
+
+ //TODO adding the parent project first because the converter needs it this way ATM. This is oversimplified.
+ //the converter should not depend on the order of reactor projects.
+ //we should add coverage for nested multi-project builds with multiple parents.
+ reactorProjects.add(mavenProject);
+
+ List<ProjectBuildingResult> allProjects = builder.build(ImmutableList.of(pomFile), true, buildingRequest);
+ CollectionUtils.collect(allProjects, reactorProjects, new Transformer<MavenProject, ProjectBuildingResult>() {
+ public MavenProject transform(ProjectBuildingResult original) {
+ return original.getProject();
+ }
+ });
+
+ MavenExecutionResult result = new DefaultMavenExecutionResult();
+ result.setProject(mavenProject);
+ RepositorySystemSession repoSession = new DefaultRepositorySystemSession();
+ MavenSession session = new MavenSession(container, repoSession, executionRequest, result);
+ session.setCurrentProject(mavenProject);
+
+ return reactorProjects;
+ }
+}
diff --git a/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/tasks/SetupBuild.groovy b/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/tasks/SetupBuild.groovy
new file mode 100644
index 0000000..b27e649
--- /dev/null
+++ b/subprojects/build-setup/src/main/groovy/org/gradle/buildsetup/tasks/SetupBuild.groovy
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.buildsetup.tasks
+
+import org.gradle.api.DefaultTask
+import org.gradle.api.GradleException
+import org.gradle.api.Incubating
+import org.gradle.api.internal.tasks.CommandLineOption
+import org.gradle.api.tasks.TaskAction
+import org.gradle.buildsetup.plugins.internal.BuildSetupTypeIds
+import org.gradle.buildsetup.plugins.internal.ProjectLayoutSetupRegistry
+
+/**
+ * Generates a Gradle project structure.
+ */
+ at Incubating
+class SetupBuild extends DefaultTask {
+ private String type
+
+ ProjectLayoutSetupRegistry projectLayoutRegistry
+
+ /**
+ * The desired type of build to create, defaults to {@value BuildSetupTypeIds#POM} if 'pom.xml' is found in project root
+ * if no pom.xml is found, it defaults to {@value BuildSetupTypeIds#BASIC}.
+ *
+ * This property can be set via command-line option '--type'.
+ */
+ String getType() {
+ type ?: project.file("pom.xml").exists() ? BuildSetupTypeIds.POM : BuildSetupTypeIds.BASIC
+ }
+
+ @TaskAction
+ void setupProjectLayout() {
+ def type = getType()
+ if (!projectLayoutRegistry.supports(type)) {
+ throw new GradleException("The requested build setup type '${type}' is not supported. Supported types: ${projectLayoutRegistry.all.collect { "'${it.id}'" }.join(", ")}.")
+ }
+ projectLayoutRegistry.get(type).generateProject()
+ }
+
+ @CommandLineOption(options = "type", description = "Set type of build to create.")
+ public void setType(String type) {
+ this.type = type;
+ }
+}
diff --git a/subprojects/build-setup/src/main/resources/META-INF/gradle-plugins/build-setup.properties b/subprojects/build-setup/src/main/resources/META-INF/gradle-plugins/build-setup.properties
new file mode 100644
index 0000000..bb78f47
--- /dev/null
+++ b/subprojects/build-setup/src/main/resources/META-INF/gradle-plugins/build-setup.properties
@@ -0,0 +1 @@
+implementation-class=org.gradle.buildsetup.plugins.BuildSetupPlugin
diff --git a/subprojects/build-setup/src/main/resources/META-INF/gradle-plugins/wrapper.properties b/subprojects/build-setup/src/main/resources/META-INF/gradle-plugins/wrapper.properties
new file mode 100644
index 0000000..5468281
--- /dev/null
+++ b/subprojects/build-setup/src/main/resources/META-INF/gradle-plugins/wrapper.properties
@@ -0,0 +1,17 @@
+#
+# Copyright 2013 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# 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.
+#
+
+implementation-class=org.gradle.buildsetup.plugins.WrapperPlugin
diff --git a/subprojects/build-setup/src/main/resources/META-INF/services/org.gradle.configuration.project.ProjectConfigureAction b/subprojects/build-setup/src/main/resources/META-INF/services/org.gradle.configuration.project.ProjectConfigureAction
new file mode 100644
index 0000000..be1a2c0
--- /dev/null
+++ b/subprojects/build-setup/src/main/resources/META-INF/services/org.gradle.configuration.project.ProjectConfigureAction
@@ -0,0 +1,2 @@
+org.gradle.buildsetup.plugins.internal.BuildSetupAutoApplyAction
+org.gradle.buildsetup.plugins.internal.WrapperPluginAutoApplyAction
diff --git a/subprojects/build-setup/src/main/resources/org/gradle/buildsetup/tasks/templates/Library.java.template b/subprojects/build-setup/src/main/resources/org/gradle/buildsetup/tasks/templates/Library.java.template
new file mode 100644
index 0000000..9e451aa
--- /dev/null
+++ b/subprojects/build-setup/src/main/resources/org/gradle/buildsetup/tasks/templates/Library.java.template
@@ -0,0 +1,11 @@
+/*
+ * This Java source file was auto generated by running 'gradle buildSetup --type java-library'
+ * by '${genUser.groovyComment}' at '${genDate.groovyComment}' with ${genGradleVersion.groovyComment}
+ *
+ * @author ${genUser.groovyComment}, @date ${genDate.groovyComment}
+ */
+public class Library {
+ public boolean someLibraryMethod() {
+ return true;
+ }
+}
diff --git a/subprojects/build-setup/src/main/resources/org/gradle/buildsetup/tasks/templates/LibraryTest.java.template b/subprojects/build-setup/src/main/resources/org/gradle/buildsetup/tasks/templates/LibraryTest.java.template
new file mode 100644
index 0000000..17ed8f5
--- /dev/null
+++ b/subprojects/build-setup/src/main/resources/org/gradle/buildsetup/tasks/templates/LibraryTest.java.template
@@ -0,0 +1,15 @@
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/*
+ * This Java source file was auto generated by running 'gradle buildSetup --type java-library'
+ * by '${genUser.groovyComment}' at '${genDate.groovyComment}' with ${genGradleVersion.groovyComment}
+ *
+ * @author ${genUser.groovyComment}, @date ${genDate.groovyComment}
+ */
+public class LibraryTest {
+ @Test public void testSomeLibraryMethod() {
+ Library classUnderTest = new Library();
+ assertTrue("someLibraryMethod should return 'true'", classUnderTest.someLibraryMethod());
+ }
+}
diff --git a/subprojects/build-setup/src/main/resources/org/gradle/buildsetup/tasks/templates/build.gradle.template b/subprojects/build-setup/src/main/resources/org/gradle/buildsetup/tasks/templates/build.gradle.template
new file mode 100644
index 0000000..7bcd658
--- /dev/null
+++ b/subprojects/build-setup/src/main/resources/org/gradle/buildsetup/tasks/templates/build.gradle.template
@@ -0,0 +1,32 @@
+/*
+ * This build file was auto generated by running the Gradle 'buildSetup' task
+ * by '${genUser.groovyComment}' at '${genDate.groovyComment}' with ${genGradleVersion.groovyComment}
+ *
+ * This generated file contains a commented-out sample Java project to get you started.
+ * For more details take a look at the Java Quickstart chapter in the Gradle
+ * user guide available at ${ref_userguide_java_tutorial.groovyComment}
+ */
+
+/*
+// Apply the java plugin to add support for Java
+apply plugin: 'java'
+
+// In this section you declare where to find the dependencies of your project
+repositories {
+ // Use 'maven central' for resolving your dependencies.
+ // You can declare any Maven/Ivy/file repository here.
+ mavenCentral()
+}
+
+// In this section you declare the dependencies for your production and test code
+dependencies {
+ // The production code uses the SLF4J logging API at compile time
+ compile 'org.slf4j:slf4j-api:1.7.5'
+
+ // Declare the dependency for your favourite test framework you want to use in your tests.
+ // TestNG is also supported by the Gradle Test task. Just change the
+ // testCompile dependency to testCompile 'org.testng:testng:6.8.1' and add
+ // 'test.useTestNG()' to your build script.
+ testCompile "junit:junit:4.11"
+}
+*/
diff --git a/subprojects/build-setup/src/main/resources/org/gradle/buildsetup/tasks/templates/java-library-build.gradle.template b/subprojects/build-setup/src/main/resources/org/gradle/buildsetup/tasks/templates/java-library-build.gradle.template
new file mode 100644
index 0000000..74f2e4b
--- /dev/null
+++ b/subprojects/build-setup/src/main/resources/org/gradle/buildsetup/tasks/templates/java-library-build.gradle.template
@@ -0,0 +1,30 @@
+/*
+ * This build file was auto generated by running the Gradle 'buildSetup' task
+ * by '${genUser.groovyComment}' at '${genDate.groovyComment}' with ${genGradleVersion.groovyComment}
+ *
+ * This generated file contains a sample Java project to get you started.
+ * For more details take a look at the Java Quickstart chapter in the Gradle
+ * user guide available at ${ref_userguide_java_tutorial.groovyComment}
+ */
+
+// Apply the java plugin to add support for Java
+apply plugin: 'java'
+
+// In this section you declare where to find the dependencies of your project
+repositories {
+ // Use 'maven central' for resolving your dependencies.
+ // You can declare any Maven/Ivy/file repository here.
+ mavenCentral()
+}
+
+// In this section you declare the dependencies for your production and test code
+dependencies {
+ // The production code uses the SLF4J logging API at compile time
+ compile 'org.slf4j:slf4j-api:1.7.5'
+
+ // Declare the dependency for your favourite test framework you want to use in your tests.
+ // TestNG is also supported by the Gradle Test task. Just change the
+ // testCompile dependency to testCompile 'org.testng:testng:6.8.1' and add
+ // 'test.useTestNG()' to your build script.
+ testCompile "junit:junit:4.11"
+}
diff --git a/subprojects/build-setup/src/main/resources/org/gradle/buildsetup/tasks/templates/settings.gradle.template b/subprojects/build-setup/src/main/resources/org/gradle/buildsetup/tasks/templates/settings.gradle.template
new file mode 100644
index 0000000..1dd3b47
--- /dev/null
+++ b/subprojects/build-setup/src/main/resources/org/gradle/buildsetup/tasks/templates/settings.gradle.template
@@ -0,0 +1,19 @@
+/*
+ * This settings file was auto generated by the Gradle buildSetup task
+ * by '${genUser.groovyComment}' at '${genDate.groovyComment}' with ${genGradleVersion.groovyComment}
+ *
+ * The settings file is used to specify which projects to include in your build.
+ * In a single project build this file can be empty or even removed.
+ *
+ * Detailed information about configuring a multi-project build in Gradle can be found
+ * in the user guide at ${ref_userguide_multiproject.groovyComment}
+ */
+
+/*
+// To declare projects as part of a multi-project build use the 'include' method
+include 'shared'
+include 'api'
+include 'services:webservice'
+*/
+
+rootProject.name = '${rootProjectName.groovyString}'
diff --git a/subprojects/build-setup/src/test/groovy/org/gradle/api/tasks/wrapper/WrapperTest.java b/subprojects/build-setup/src/test/groovy/org/gradle/api/tasks/wrapper/WrapperTest.java
new file mode 100644
index 0000000..bf46f0c
--- /dev/null
+++ b/subprojects/build-setup/src/test/groovy/org/gradle/api/tasks/wrapper/WrapperTest.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.tasks.wrapper;
+
+import org.gradle.api.internal.AbstractTask;
+import org.gradle.api.tasks.AbstractTaskTest;
+import org.gradle.test.fixtures.file.TestFile;
+import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider;
+import org.gradle.util.GUtil;
+import org.gradle.util.GradleVersion;
+import org.gradle.util.WrapUtil;
+import org.gradle.wrapper.GradleWrapperMain;
+import org.gradle.wrapper.WrapperExecutor;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Properties;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.junit.Assert.*;
+
+public class WrapperTest extends AbstractTaskTest {
+
+ private Wrapper wrapper;
+ private String targetWrapperJarPath;
+ private TestFile expectedTargetWrapperJar;
+ private File expectedTargetWrapperProperties;
+ @Rule
+ public TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider();
+
+ @Before
+ public void setUp() {
+ wrapper = createTask(Wrapper.class);
+ wrapper.setGradleVersion("1.0");
+ targetWrapperJarPath = "gradle/wrapper";
+ expectedTargetWrapperJar = new TestFile(getProject().getProjectDir(),
+ targetWrapperJarPath + "/gradle-wrapper.jar");
+ expectedTargetWrapperProperties = new File(getProject().getProjectDir(),
+ targetWrapperJarPath + "/gradle-wrapper.properties");
+ new File(getProject().getProjectDir(), targetWrapperJarPath).mkdirs();
+ wrapper.setDistributionPath("somepath");
+ }
+
+ public AbstractTask getTask() {
+ return wrapper;
+ }
+
+ @Test
+ public void testWrapperDefaults() {
+ wrapper = createTask(Wrapper.class);
+ assertEquals(new File(getProject().getProjectDir(), "gradle/wrapper/gradle-wrapper.jar"), wrapper.getJarFile());
+ assertEquals(new File(getProject().getProjectDir(), "gradlew"), wrapper.getScriptFile());
+ assertEquals(new File(getProject().getProjectDir(), "gradlew.bat"), wrapper.getBatchScript());
+ assertEquals(GradleVersion.current().getVersion(), wrapper.getGradleVersion());
+ assertEquals(Wrapper.DEFAULT_DISTRIBUTION_PARENT_NAME, wrapper.getDistributionPath());
+ assertEquals(Wrapper.DEFAULT_DISTRIBUTION_PARENT_NAME, wrapper.getArchivePath());
+ assertEquals(Wrapper.PathBase.GRADLE_USER_HOME, wrapper.getDistributionBase());
+ assertEquals(Wrapper.PathBase.GRADLE_USER_HOME, wrapper.getArchiveBase());
+ assertNotNull(wrapper.getDistributionUrl());
+ }
+
+ @Test
+ public void testDeterminesWindowsScriptPathFromUnixScriptPath() {
+ wrapper.setScriptFile("build/gradle.sh");
+ assertEquals(getProject().file("build/gradle.bat"), wrapper.getBatchScript());
+
+ wrapper.setScriptFile("build/gradle-wrapper");
+ assertEquals(getProject().file("build/gradle-wrapper.bat"), wrapper.getBatchScript());
+ }
+
+ @Test
+ public void testDeterminesPropertiesFilePathFromJarPath() {
+ wrapper.setJarFile("build/gradle-wrapper.jar");
+ assertEquals(getProject().file("build/gradle-wrapper.properties"), wrapper.getPropertiesFile());
+ }
+
+ @Test
+ public void testDownloadsFromReleaseRepositoryForReleaseVersions() {
+ wrapper.setGradleVersion("0.9.1");
+ assertEquals("http://services.gradle.org/distributions/gradle-0.9.1-bin.zip", wrapper.getDistributionUrl());
+ }
+
+ @Test
+ public void testDownloadsFromReleaseRepositoryForPreviewReleaseVersions() {
+ wrapper.setGradleVersion("1.0-milestone-1");
+ assertEquals("http://services.gradle.org/distributions/gradle-1.0-milestone-1-bin.zip", wrapper.getDistributionUrl());
+ }
+
+ @Test
+ public void testDownloadsFromSnapshotRepositoryForSnapshotVersions() {
+ wrapper.setGradleVersion("0.9.1-20101224110000+1100");
+ assertEquals("http://services.gradle.org/distributions-snapshots/gradle-0.9.1-20101224110000+1100-bin.zip", wrapper.getDistributionUrl());
+ }
+
+ @Test
+ public void testUsesExplicitlyDefinedDistributionUrl() {
+ wrapper.setGradleVersion("0.9");
+ wrapper.setDistributionUrl("http://some-url");
+ assertEquals("http://some-url", wrapper.getDistributionUrl());
+ }
+
+ @Test
+ public void testExecuteWithNonExistingWrapperJarParentDir() throws IOException {
+ checkExecute();
+ }
+
+ @Test
+ public void testCheckInputs() throws IOException {
+ assertThat(wrapper.getInputs().getProperties().keySet(),
+ equalTo(WrapUtil.toSet("distributionBase", "distributionPath", "distributionUrl", "archiveBase", "archivePath")));
+ }
+
+ @Test
+ public void testExecuteWithExistingWrapperJarParentDirAndExistingWrapperJar() throws IOException {
+ File jarDir = new File(getProject().getProjectDir(), "lib");
+ jarDir.mkdirs();
+ File wrapperJar = new File(getProject().getProjectDir(), targetWrapperJarPath);
+ File parentFile = expectedTargetWrapperJar.getParentFile();
+ assertTrue(parentFile.isDirectory() || parentFile.mkdirs());
+ try {
+ assertTrue(expectedTargetWrapperJar.createNewFile());
+ } catch (IOException e) {
+ throw new RuntimeException(String.format("Could not create %s.", wrapperJar), e);
+ }
+ checkExecute();
+ }
+
+ private void checkExecute() throws IOException {
+ wrapper.execute();
+ TestFile unjarDir = tmpDir.createDir("unjar");
+ expectedTargetWrapperJar.unzipTo(unjarDir);
+ unjarDir.file(GradleWrapperMain.class.getName().replace(".", "/") + ".class").assertIsFile();
+ Properties properties = GUtil.loadProperties(expectedTargetWrapperProperties);
+ assertEquals(properties.getProperty(WrapperExecutor.DISTRIBUTION_URL_PROPERTY), wrapper.getDistributionUrl());
+ assertEquals(properties.getProperty(WrapperExecutor.DISTRIBUTION_BASE_PROPERTY), wrapper.getDistributionBase().toString());
+ assertEquals(properties.getProperty(WrapperExecutor.DISTRIBUTION_PATH_PROPERTY), wrapper.getDistributionPath());
+ assertEquals(properties.getProperty(WrapperExecutor.ZIP_STORE_BASE_PROPERTY), wrapper.getArchiveBase().toString());
+ assertEquals(properties.getProperty(WrapperExecutor.ZIP_STORE_PATH_PROPERTY), wrapper.getArchivePath());
+ }
+
+ private String toNative(String s) {
+ return s.replace("/", File.separator);
+ }
+}
diff --git a/subprojects/build-setup/src/test/groovy/org/gradle/buildsetup/plugins/BuildSetupPluginSpec.groovy b/subprojects/build-setup/src/test/groovy/org/gradle/buildsetup/plugins/BuildSetupPluginSpec.groovy
new file mode 100644
index 0000000..18fbbb4
--- /dev/null
+++ b/subprojects/build-setup/src/test/groovy/org/gradle/buildsetup/plugins/BuildSetupPluginSpec.groovy
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.buildsetup.plugins
+
+import org.gradle.api.internal.file.TemporaryFileProvider
+import org.gradle.api.internal.file.TmpDirTemporaryFileProvider
+import org.gradle.api.tasks.wrapper.Wrapper
+import org.gradle.util.TestUtil
+import org.gradle.util.Matchers
+import spock.lang.Specification
+
+class BuildSetupPluginSpec extends Specification {
+ def project = TestUtil.createRootProject()
+
+ def "applies plugin"() {
+ when:
+ project.plugins.apply BuildSetupPlugin
+ and:
+ project.evaluate()
+ then:
+ project.tasks.wrapper instanceof Wrapper
+ Matchers.dependsOn("wrapper").matches(project.tasks.setupBuild)
+ }
+
+ def "no wrapper task configured if build file already exists"() {
+ setup:
+ TemporaryFileProvider temporaryFileProvider = new TmpDirTemporaryFileProvider();
+ File projectDir = temporaryFileProvider.createTemporaryDirectory("gradle", "projectDir");
+ def buildFile = new File(projectDir, "build.gradle") << '// an empty build'
+ buildFile << '// an empty build'
+ project = TestUtil.builder().withProjectDir(projectDir).build()
+ when:
+ project.plugins.apply BuildSetupPlugin
+
+ then:
+ project.setupBuild != null
+ project.tasks.collect { it.name } == ["setupBuild"]
+ }
+
+ def "no build file generation if settings file already exists"() {
+ setup:
+ project.file("settings.gradle") << '// an empty file'
+
+ when:
+ project.plugins.apply BuildSetupPlugin
+
+ then:
+ project.setupBuild != null
+ project.tasks.collect { it.name } == ["setupBuild"]
+ }
+
+ def "no build file generation when part of multi-project build"() {
+ setup:
+ TestUtil.createChildProject(project, 'child')
+
+ when:
+ project.plugins.apply BuildSetupPlugin
+
+ then:
+ project.setupBuild != null
+ project.tasks.collect { it.name } == ["setupBuild"]
+ }
+}
diff --git a/subprojects/build-setup/src/test/groovy/org/gradle/buildsetup/plugins/WrapperPluginSpec.groovy b/subprojects/build-setup/src/test/groovy/org/gradle/buildsetup/plugins/WrapperPluginSpec.groovy
new file mode 100644
index 0000000..91dfeab
--- /dev/null
+++ b/subprojects/build-setup/src/test/groovy/org/gradle/buildsetup/plugins/WrapperPluginSpec.groovy
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.buildsetup.plugins
+
+import org.gradle.api.tasks.wrapper.Wrapper
+import org.gradle.util.TestUtil
+import spock.lang.Specification
+
+class WrapperPluginSpec extends Specification {
+ def project = TestUtil.createRootProject()
+
+ def "adds 'wrapper' task"() {
+ when:
+ project.plugins.apply WrapperPlugin
+
+ then:
+ project.tasks.wrapper instanceof Wrapper
+ project.tasks.wrapper.group == BuildSetupPlugin.GROUP
+ }
+}
diff --git a/subprojects/build-setup/src/test/groovy/org/gradle/buildsetup/plugins/internal/BuildSetupAutoApplyActionSpec.groovy b/subprojects/build-setup/src/test/groovy/org/gradle/buildsetup/plugins/internal/BuildSetupAutoApplyActionSpec.groovy
new file mode 100644
index 0000000..b7fcc74
--- /dev/null
+++ b/subprojects/build-setup/src/test/groovy/org/gradle/buildsetup/plugins/internal/BuildSetupAutoApplyActionSpec.groovy
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.buildsetup.plugins.internal
+
+import org.gradle.api.internal.project.ProjectInternal
+import org.gradle.api.internal.tasks.TaskContainerInternal
+import org.gradle.api.plugins.PluginContainer
+import org.gradle.test.fixtures.file.TestFile
+import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
+import org.junit.Rule
+import spock.lang.Specification
+
+class BuildSetupAutoApplyActionSpec extends Specification {
+
+ @Rule
+ final TestNameTestDirectoryProvider temporaryFolder = new TestNameTestDirectoryProvider()
+ TestFile buildFile
+ ProjectInternal projectInternal
+ PluginContainer pluginContainer
+ TaskContainerInternal taskContainerInternal
+
+ public void setup() {
+ projectInternal = Mock(ProjectInternal)
+ pluginContainer = Mock(PluginContainer)
+ taskContainerInternal = Mock(TaskContainerInternal)
+ _ * projectInternal.getTasks() >> taskContainerInternal
+
+ }
+
+ def "applies placeholder action for setupBuild on taskcontainer"() {
+ when:
+ new BuildSetupAutoApplyAction().execute(projectInternal)
+ then:
+ 1 * taskContainerInternal.addPlaceholderAction("setupBuild", _) >> {args -> args[1].run()}
+ 1 * projectInternal.getParent() >> null
+ 1 * projectInternal.getPlugins() >> pluginContainer
+ 1 * pluginContainer.apply("build-setup")
+ }
+
+ def "is not applied on non rootprojects"() {
+ given:
+ isNotRootProject()
+ when:
+ new BuildSetupAutoApplyAction().execute(projectInternal)
+ then:
+ 0 * taskContainerInternal.addPlaceholderAction("setupBuild", _)
+ 0 * projectInternal.getPlugins() >> pluginContainer
+ 0 * pluginContainer.apply("build-setup")
+ }
+
+ def isNotRootProject() {
+ projectInternal.getParent() >> Mock(ProjectInternal)
+ }
+
+ void noChildprojects() {
+ projectInternal.subprojects >> []
+ }
+}
diff --git a/subprojects/build-setup/src/test/groovy/org/gradle/buildsetup/plugins/internal/ProjectLayoutSetupRegistryFactoryTest.groovy b/subprojects/build-setup/src/test/groovy/org/gradle/buildsetup/plugins/internal/ProjectLayoutSetupRegistryFactoryTest.groovy
new file mode 100644
index 0000000..4efbaa9
--- /dev/null
+++ b/subprojects/build-setup/src/test/groovy/org/gradle/buildsetup/plugins/internal/ProjectLayoutSetupRegistryFactoryTest.groovy
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.buildsetup.plugins.internal
+
+import org.gradle.api.internal.DocumentationRegistry
+import org.gradle.api.internal.artifacts.mvnsettings.MavenSettingsProvider
+import org.gradle.api.internal.file.FileResolver
+import spock.lang.Specification
+import spock.lang.Unroll
+
+class ProjectLayoutSetupRegistryFactoryTest extends Specification {
+
+ ProjectLayoutSetupRegistryFactory projectLayoutSetupRegistry
+ DocumentationRegistry documentationRegistry
+ MavenSettingsProvider mavenSettingsProvider
+ FileResolver fileResolver
+
+ def setup() {
+ fileResolver = Mock()
+ projectLayoutSetupRegistry = new ProjectLayoutSetupRegistryFactory(mavenSettingsProvider, documentationRegistry, fileResolver);
+ }
+
+ @Unroll
+ def "supports '#type' project descriptor type"() {
+ when:
+ ProjectSetupDescriptor descriptor = projectLayoutSetupRegistry.createProjectLayoutSetupRegistry().get(type)
+
+ then:
+ descriptor != null
+ descriptor.class == clazz
+
+ where:
+ type | clazz
+ BuildSetupTypeIds.POM | PomProjectSetupDescriptor.class
+ BuildSetupTypeIds.BASIC | BasicProjectSetupDescriptor.class
+ BuildSetupTypeIds.JAVA_LIBRARY | JavaLibraryProjectSetupDescriptor.class
+ }
+}
diff --git a/subprojects/build-setup/src/test/groovy/org/gradle/buildsetup/plugins/internal/ProjectLayoutSetupRegistrySpec.groovy b/subprojects/build-setup/src/test/groovy/org/gradle/buildsetup/plugins/internal/ProjectLayoutSetupRegistrySpec.groovy
new file mode 100644
index 0000000..ff44192
--- /dev/null
+++ b/subprojects/build-setup/src/test/groovy/org/gradle/buildsetup/plugins/internal/ProjectLayoutSetupRegistrySpec.groovy
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.buildsetup.plugins.internal
+
+import org.gradle.api.GradleException
+import spock.lang.Specification
+
+
+class ProjectLayoutSetupRegistrySpec extends Specification {
+
+
+ ProjectLayoutSetupRegistry registry = new ProjectLayoutSetupRegistry()
+
+ def "can add multiple projectlayoutdescriptors"() {
+ when:
+ registry.add(descriptor("desc1"))
+ registry.add(descriptor("desc2"))
+ registry.add(descriptor("desc3"))
+ then:
+ registry.supports("desc1")
+ registry.get("desc1") != null
+
+ registry.supports("desc2")
+ registry.get("desc2") != null
+
+ registry.supports("desc3")
+ registry.get("desc3") != null
+ }
+
+ def "cannot add multiple descriptors with same id"() {
+ when:
+ registry.add(descriptor("desc1"))
+ registry.add(descriptor("desc1"))
+ then:
+ def e = thrown(GradleException)
+ e.message == "ProjectDescriptor with ID 'desc1' already registered."
+ }
+
+ ProjectSetupDescriptor descriptor(String descrName) {
+ ProjectSetupDescriptor descriptor = Mock()
+ _ * descriptor.id >> descrName
+ descriptor
+ }
+}
diff --git a/subprojects/build-setup/src/test/groovy/org/gradle/buildsetup/plugins/internal/TemplateBasedProjectSetupDescriptorSpec.groovy b/subprojects/build-setup/src/test/groovy/org/gradle/buildsetup/plugins/internal/TemplateBasedProjectSetupDescriptorSpec.groovy
new file mode 100644
index 0000000..804ab88
--- /dev/null
+++ b/subprojects/build-setup/src/test/groovy/org/gradle/buildsetup/plugins/internal/TemplateBasedProjectSetupDescriptorSpec.groovy
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.buildsetup.plugins.internal
+
+import org.gradle.api.internal.DocumentationRegistry
+import org.gradle.api.internal.file.FileResolver
+import org.gradle.test.fixtures.encoding.Identifier
+import org.gradle.test.fixtures.file.TestFile
+import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
+import org.junit.Rule
+import spock.lang.Specification
+
+class TemplateBasedProjectSetupDescriptorSpec extends Specification {
+
+ private TestTemplateBasedProjectSetupDescriptor descriptor
+ private DocumentationRegistry documentationRegistry
+ private FileResolver fileResolver
+ private TestFile buildTemplateFile
+ private TestFile settingsTemplateFile
+ private URL buildFileTemplateURL
+ private URL settingsTemplateURL
+ @Rule
+ final TestNameTestDirectoryProvider temporaryFolder = new TestNameTestDirectoryProvider()
+
+ def setup() {
+ buildTemplateFile = temporaryFolder.createFile("build.gradle.template")
+ buildFileTemplateURL = buildTemplateFile.toURI().toURL()
+
+ settingsTemplateFile = temporaryFolder.createFile("settings.gradle.template")
+ settingsTemplateFile << 'root'
+ settingsTemplateURL = settingsTemplateFile.toURI().toURL()
+
+ documentationRegistry = Mock(DocumentationRegistry)
+
+ fileResolver = Mock(FileResolver)
+ _ * fileResolver.resolve(_) >> {
+ temporaryFolder.file(it[0])
+ }
+
+ descriptor = new TestTemplateBasedProjectSetupDescriptor(fileResolver, documentationRegistry)
+ }
+
+ def "can generate build and settings file via templates"() {
+ when:
+ descriptor.generateProject()
+ then:
+ temporaryFolder.file("build.gradle").exists()
+ temporaryFolder.file("settings.gradle").exists()
+ }
+
+ def "escapes strings and encodes contents using UTF-8"() {
+ setup:
+ buildTemplateFile.text = '${somePath.groovyComment}'
+ settingsTemplateFile.text = '${someValue.groovyString}'
+ when:
+ descriptor.generateProject()
+ then:
+ temporaryFolder.file("build.gradle").getText('utf-8') == /C:\\Programe Files\\gradle/
+ temporaryFolder.file("settings.gradle").getText('utf-8') == new Identifier(/a\'b\\c/).withNonAscii().toString()
+ }
+
+ class TestTemplateBasedProjectSetupDescriptor extends TemplateBasedProjectSetupDescriptor {
+
+ public TestTemplateBasedProjectSetupDescriptor(FileResolver fileResolver, DocumentationRegistry documentationRegistry) {
+ super(fileResolver, documentationRegistry)
+ }
+
+ @Override
+ URL getBuildFileTemplate() {
+ return buildFileTemplateURL
+ }
+
+ @Override
+ URL getSettingsTemplate() {
+ return settingsTemplateURL
+ }
+
+ @Override
+ protected Map getAdditionalBuildFileTemplateBindings() {
+ return [somePath: "C:\\Programe Files\\gradle"]
+ }
+
+ protected Map getAdditionalSettingsFileTemplateBindings() {
+ return [someValue: new Identifier("a\'b\\c").withNonAscii().toString()]
+ }
+
+ String getId() {
+ return "test-ID"
+ }
+ }
+}
diff --git a/subprojects/build-setup/src/test/groovy/org/gradle/buildsetup/plugins/internal/TemplateValueTest.groovy b/subprojects/build-setup/src/test/groovy/org/gradle/buildsetup/plugins/internal/TemplateValueTest.groovy
new file mode 100644
index 0000000..32f9241
--- /dev/null
+++ b/subprojects/build-setup/src/test/groovy/org/gradle/buildsetup/plugins/internal/TemplateValueTest.groovy
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.buildsetup.plugins.internal
+
+import spock.lang.Specification
+
+class TemplateValueTest extends Specification {
+ def "escapes value for inclusion in a comment"() {
+ expect:
+ new TemplateValue(value).groovyComment == escaped
+
+ where:
+ value | escaped
+ '' | ''
+ 'abc' | 'abc'
+ 'a\n\t' | 'a\n\t'
+ /a\b/ | /a\\b/
+ }
+
+ def "escapes value for inclusion in a string"() {
+ expect:
+ new TemplateValue(value).groovyString == escaped
+
+ where:
+ value | escaped
+ '' | ''
+ 'abc' | 'abc'
+ 'a\n\t\r\b\f' | /a\n\t\r\b\f/
+ /a\b/ | /a\\b/
+ /'/ | /\'/
+ /"/ | /"/
+ /\'/ | /\\\'/
+ }
+}
diff --git a/subprojects/build-setup/src/test/groovy/org/gradle/buildsetup/plugins/internal/maven/MavenProjectXmlWriterTest.groovy b/subprojects/build-setup/src/test/groovy/org/gradle/buildsetup/plugins/internal/maven/MavenProjectXmlWriterTest.groovy
new file mode 100644
index 0000000..93b918b
--- /dev/null
+++ b/subprojects/build-setup/src/test/groovy/org/gradle/buildsetup/plugins/internal/maven/MavenProjectXmlWriterTest.groovy
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.buildsetup.plugins.internal.maven
+
+import spock.lang.Specification
+
+class MavenProjectXmlWriterTest extends Specification {
+
+ def writer = new MavenProjectXmlWriter()
+
+ def "removes xml element"() {
+ expect:
+ writer.prepareXml('<?xml encoding="UTF-8"?><project/>') == "<project/>"
+ writer.prepareXml('<?xml version="1.0" encoding="UTF-8"?><project/>') == "<project/>"
+ writer.prepareXml('<?xml version="1.0" encoding="UTF-8" ?><project/>') == "<project/>"
+ }
+}
diff --git a/subprojects/build-setup/src/test/groovy/org/gradle/buildsetup/plugins/internal/maven/MavenProjectsCreatorSpec.groovy b/subprojects/build-setup/src/test/groovy/org/gradle/buildsetup/plugins/internal/maven/MavenProjectsCreatorSpec.groovy
new file mode 100644
index 0000000..412d090
--- /dev/null
+++ b/subprojects/build-setup/src/test/groovy/org/gradle/buildsetup/plugins/internal/maven/MavenProjectsCreatorSpec.groovy
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.buildsetup.plugins.internal.maven
+
+import org.gradle.api.internal.artifacts.mvnsettings.DefaultMavenSettingsProvider
+import org.gradle.api.internal.artifacts.mvnsettings.MavenFileLocations
+import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
+import org.junit.Rule
+import spock.lang.Specification
+
+class MavenProjectsCreatorSpec extends Specification {
+
+ @Rule TestNameTestDirectoryProvider temp
+ private settings = new DefaultMavenSettingsProvider({} as MavenFileLocations)
+ private creator = new MavenProjectsCreator()
+
+ def "creates single module project"() {
+ given:
+ def pom = temp.file("pom.xml")
+ pom.text = """<project>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>util</groupId>
+ <artifactId>util</artifactId>
+ <version>2.5</version>
+ <packaging>jar</packaging>
+</project>"""
+
+ when:
+ def mavenProjects = creator.create(settings.buildSettings(), pom) as List
+
+ then:
+ mavenProjects.size() == 1
+ mavenProjects[0].name == 'util'
+ }
+
+ def "creates multi module project"() {
+ given:
+ def parentPom = temp.file("pom.xml")
+ parentPom.text = """<project>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.gradle.webinar</groupId>
+ <artifactId>webinar-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <modules>
+ <module>webinar-api</module>
+ </modules>
+</project>
+"""
+
+ temp.createDir("webinar-api")
+ temp.file("webinar-api/pom.xml").text = """<project>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>webinar-api</artifactId>
+ <packaging>jar</packaging>
+
+ <parent>
+ <groupId>org.gradle.webinar</groupId>
+ <artifactId>webinar-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+</project>
+"""
+
+ when:
+ def mavenProjects = creator.create(settings.buildSettings(), parentPom) as List
+
+ then:
+ mavenProjects.size() == 2
+ mavenProjects[0].name == 'webinar-parent'
+ mavenProjects[1].name == 'webinar-api'
+ }
+
+ def "fails with decent exception if pom is incorrect"() {
+ given:
+ def pom = temp.file("pom.xml")
+ pom.text = """<project>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>util</artifactId>
+ <version>2.5</version>
+ <packaging>jar</packaging>
+</project>"""
+
+ when:
+ creator.create(settings.buildSettings(), pom) as List
+
+ then:
+ def ex = thrown(MavenConversionException)
+ ex.message == "Unable to create Maven project model using POM $pom."
+ }
+
+ def "fails with decent exception if pom does not exist"() {
+ def pom = temp.file("pom.xml")
+
+ when:
+ creator.create(settings.buildSettings(), pom) as List
+
+ then:
+ def ex = thrown(MavenConversionException)
+ ex.message == "Unable to create Maven project model. The POM file $pom does not exist."
+ }
+}
diff --git a/subprojects/build-setup/src/test/groovy/org/gradle/buildsetup/tasks/SetupBuildSpec.groovy b/subprojects/build-setup/src/test/groovy/org/gradle/buildsetup/tasks/SetupBuildSpec.groovy
new file mode 100644
index 0000000..2adbde9
--- /dev/null
+++ b/subprojects/build-setup/src/test/groovy/org/gradle/buildsetup/tasks/SetupBuildSpec.groovy
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.buildsetup.tasks
+
+import org.gradle.api.GradleException
+import org.gradle.buildsetup.plugins.internal.BuildSetupTypeIds
+import org.gradle.buildsetup.plugins.internal.ProjectLayoutSetupRegistry
+import org.gradle.buildsetup.plugins.internal.ProjectSetupDescriptor
+import org.gradle.util.TestUtil
+import spock.lang.Specification
+
+class SetupBuildSpec extends Specification {
+
+ SetupBuild setupBuild;
+
+ ProjectLayoutSetupRegistry projectLayoutRegistry;
+
+ ProjectSetupDescriptor projectSetupDescriptor1
+ ProjectSetupDescriptor projectSetupDescriptor2
+ ProjectSetupDescriptor projectSetupDescriptor3
+
+ def setup() {
+ setupBuild = TestUtil.builder().build().tasks.create("setupBuild", SetupBuild)
+ projectLayoutRegistry = Mock()
+ projectSetupDescriptor1 = Mock()
+ projectSetupDescriptor2 = Mock()
+ projectSetupDescriptor3 = Mock()
+ _ * projectSetupDescriptor2.id >> "supported-type"
+ _ * projectSetupDescriptor3.id >> "another-supported-type"
+ setupBuild.projectLayoutRegistry = projectLayoutRegistry
+ }
+
+ def "throws GradleException if requested setupDescriptor not supported"() {
+ setup:
+ _ * projectLayoutRegistry.get("aType") >> null
+ _ * projectLayoutRegistry.all >> [projectSetupDescriptor2, projectSetupDescriptor3]
+ when:
+ setupBuild.type = "aType"
+ setupBuild.setupProjectLayout()
+ then:
+ def e = thrown(GradleException)
+ e.message == "The requested build setup type 'aType' is not supported. Supported types: 'supported-type', 'another-supported-type'."
+
+ }
+
+ def "delegates task action to referenced setupDescriptor"() {
+ setup:
+ 1 * projectLayoutRegistry.supports(BuildSetupTypeIds.BASIC) >> true
+ 1 * projectLayoutRegistry.get(BuildSetupTypeIds.BASIC) >> projectSetupDescriptor1
+ when:
+ setupBuild.setupProjectLayout()
+ then:
+ 1 * projectSetupDescriptor1.generateProject()
+ }
+}
diff --git a/subprojects/cli/cli.gradle b/subprojects/cli/cli.gradle
index 68118d9..46b1219 100644
--- a/subprojects/cli/cli.gradle
+++ b/subprojects/cli/cli.gradle
@@ -21,7 +21,7 @@
It has no dependencies, and should never have any.
*/
dependencies {
- groovy libraries.groovy
+ testCompile libraries.groovy
}
useClassycle()
\ No newline at end of file
diff --git a/subprojects/cli/src/main/java/org/gradle/cli/CommandLineArgumentException.java b/subprojects/cli/src/main/java/org/gradle/cli/CommandLineArgumentException.java
index 82a5ff3..b34d668 100644
--- a/subprojects/cli/src/main/java/org/gradle/cli/CommandLineArgumentException.java
+++ b/subprojects/cli/src/main/java/org/gradle/cli/CommandLineArgumentException.java
@@ -17,8 +17,6 @@ package org.gradle.cli;
/**
* A {@code CommandLineArgumentException} is thrown when command-line arguments cannot be parsed.
- *
- * @author Hans Dockter
*/
public class CommandLineArgumentException extends RuntimeException {
public CommandLineArgumentException(String message) {
diff --git a/subprojects/cli/src/main/java/org/gradle/cli/CommandLineConverter.java b/subprojects/cli/src/main/java/org/gradle/cli/CommandLineConverter.java
index bc9bac4..bfc2627 100644
--- a/subprojects/cli/src/main/java/org/gradle/cli/CommandLineConverter.java
+++ b/subprojects/cli/src/main/java/org/gradle/cli/CommandLineConverter.java
@@ -15,9 +15,6 @@
*/
package org.gradle.cli;
-/**
- * @author Hans Dockter
- */
public interface CommandLineConverter<T> {
T convert(Iterable<String> args) throws CommandLineArgumentException;
diff --git a/subprojects/cli/src/main/java/org/gradle/cli/CommandLineOption.java b/subprojects/cli/src/main/java/org/gradle/cli/CommandLineOption.java
index 8520081..96d36c8 100644
--- a/subprojects/cli/src/main/java/org/gradle/cli/CommandLineOption.java
+++ b/subprojects/cli/src/main/java/org/gradle/cli/CommandLineOption.java
@@ -23,9 +23,9 @@ public class CommandLineOption {
private final Set<String> options = new HashSet<String>();
private Class<?> argumentType = Void.TYPE;
private String description;
- private String subcommand;
private String deprecationWarning;
private boolean incubating;
+ private final Set<CommandLineOption> groupWith = new HashSet<CommandLineOption>();
public CommandLineOption(Iterable<String> options) {
for (String option : options) {
@@ -47,15 +47,6 @@ public class CommandLineOption {
return this;
}
- public String getSubcommand() {
- return subcommand;
- }
-
- public CommandLineOption mapsToSubcommand(String command) {
- this.subcommand = command;
- return this;
- }
-
public String getDescription() {
StringBuilder result = new StringBuilder();
if (description != null) {
@@ -104,4 +95,13 @@ public class CommandLineOption {
public String getDeprecationWarning() {
return deprecationWarning;
}
+
+ Set<CommandLineOption> getGroupWith() {
+ return groupWith;
+ }
+
+ void groupWith(Set<CommandLineOption> options) {
+ this.groupWith.addAll(options);
+ this.groupWith.remove(this);
+ }
}
diff --git a/subprojects/cli/src/main/java/org/gradle/cli/CommandLineParser.java b/subprojects/cli/src/main/java/org/gradle/cli/CommandLineParser.java
index c238506..20ed20d 100644
--- a/subprojects/cli/src/main/java/org/gradle/cli/CommandLineParser.java
+++ b/subprojects/cli/src/main/java/org/gradle/cli/CommandLineParser.java
@@ -156,6 +156,21 @@ public class CommandLineParser {
}
/**
+ * Specifies that the given set of options are mutually-exclusive. Only one of the given options will be selected.
+ * The parser ignores all but the last of these options.
+ */
+ public CommandLineParser allowOneOf(String... options) {
+ Set<CommandLineOption> commandLineOptions = new HashSet<CommandLineOption>();
+ for (String option : options) {
+ commandLineOptions.add(optionsByString.get(option));
+ }
+ for (CommandLineOption commandLineOption : commandLineOptions) {
+ commandLineOption.groupWith(commandLineOptions);
+ }
+ return this;
+ }
+
+ /**
* Prints a usage message to the given stream.
*
* @param out The output stream to write to.
@@ -234,7 +249,7 @@ public class CommandLineParser {
}
CommandLineOption option = new CommandLineOption(Arrays.asList(options));
for (String optionStr : option.getOptions()) {
- this.optionsByString.put(optionStr, option);
+ optionsByString.put(optionStr, option);
}
return option;
}
@@ -444,8 +459,9 @@ public class CommandLineParser {
if (option.getDeprecationWarning() != null) {
deprecationPrinter.println("The " + optionString + " option is deprecated - " + option.getDeprecationWarning());
}
- if (option.getSubcommand() != null) {
- return state.onNonOption(option.getSubcommand());
+
+ for (CommandLineOption otherOption : option.getGroupWith()) {
+ commandLine.removeOption(otherOption);
}
return state;
diff --git a/subprojects/cli/src/main/java/org/gradle/cli/ParsedCommandLine.java b/subprojects/cli/src/main/java/org/gradle/cli/ParsedCommandLine.java
index 8179d31..3134649 100644
--- a/subprojects/cli/src/main/java/org/gradle/cli/ParsedCommandLine.java
+++ b/subprojects/cli/src/main/java/org/gradle/cli/ParsedCommandLine.java
@@ -104,4 +104,8 @@ public class ParsedCommandLine {
presentOptions.addAll(option.getOptions());
return parsedOption;
}
+
+ void removeOption(CommandLineOption option) {
+ presentOptions.removeAll(option.getOptions());
+ }
}
diff --git a/subprojects/cli/src/test/groovy/org/gradle/cli/CommandLineParserTest.groovy b/subprojects/cli/src/test/groovy/org/gradle/cli/CommandLineParserTest.groovy
index d44dbac..2859eaa 100644
--- a/subprojects/cli/src/test/groovy/org/gradle/cli/CommandLineParserTest.groovy
+++ b/subprojects/cli/src/test/groovy/org/gradle/cli/CommandLineParserTest.groovy
@@ -265,51 +265,49 @@ class CommandLineParserTest extends Specification {
result.extraArguments == ['a', '--option', 'b']
}
- def canMapOptionToSubcommand() {
- parser.option('a').mapsToSubcommand('subcmd')
-
- expect:
- def result = parser.parse(['-a', '--option', 'b'])
- result.extraArguments == ['subcmd', '--option', 'b']
- result.hasOption('a')
- }
-
def canCombineSubcommandShortOptionWithOtherShortOptions() {
- parser.option('a').mapsToSubcommand('subcmd')
parser.option('b')
+ parser.allowMixedSubcommandsAndOptions()
when:
- def result = parser.parse(['-abc', '--option', 'b'])
+ def result = parser.parse(['cmd', '-b', '-a'])
then:
- result.extraArguments == ['subcmd', '-b', '-c', '--option', 'b']
- result.hasOption('a')
- !result.hasOption('b')
+ result.extraArguments == ['cmd', '-a']
+ result.hasOption('b')
when:
- result = parser.parse(['-bac', '--option', 'b'])
+ result = parser.parse(['cmd', '-ba'])
then:
- result.extraArguments == ['subcmd', '-c', '--option', 'b']
- result.hasOption('a')
+ result.extraArguments == ['cmd', '-a']
result.hasOption('b')
+ }
+
+ def returnsLastMutuallyExclusiveOptionThatIsPresent() {
+ parser.option("a")
+ parser.option("b")
+ parser.option("c", "long-option")
+ parser.option("d")
+ parser.allowOneOf("a", "b", "c")
when:
- parser.allowMixedSubcommandsAndOptions()
- result = parser.parse(['-abc', '--option', 'b'])
+ def result = parser.parse(['-a', '-b', '-c'])
then:
- result.extraArguments == ['subcmd', '-c', '--option', 'b']
- result.hasOption('a')
- result.hasOption('b')
+ !result.hasOption('a')
+ !result.hasOption('b')
+ result.hasOption('c')
+ result.hasOption('long-option')
when:
- result = parser.parse(['-bac', '--option', 'b'])
+ result = parser.parse(['-a', '-b', '--long-option'])
then:
- result.extraArguments == ['subcmd', '-c', '--option', 'b']
- result.hasOption('a')
- result.hasOption('b')
+ !result.hasOption('a')
+ !result.hasOption('b')
+ result.hasOption('c')
+ result.hasOption('long-option')
}
def singleDashIsNotConsideredAnOption() {
diff --git a/subprojects/cli/src/test/groovy/org/gradle/cli/ParsedCommandLineOptionSpec.groovy b/subprojects/cli/src/test/groovy/org/gradle/cli/ParsedCommandLineOptionSpec.groovy
index 224a638..bb0bba1 100644
--- a/subprojects/cli/src/test/groovy/org/gradle/cli/ParsedCommandLineOptionSpec.groovy
+++ b/subprojects/cli/src/test/groovy/org/gradle/cli/ParsedCommandLineOptionSpec.groovy
@@ -18,9 +18,6 @@ package org.gradle.cli
import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 9/5/12
- */
class ParsedCommandLineOptionSpec extends Specification {
final option = new ParsedCommandLineOption();
diff --git a/subprojects/cli/src/test/groovy/org/gradle/cli/ParsedCommandLineTest.groovy b/subprojects/cli/src/test/groovy/org/gradle/cli/ParsedCommandLineTest.groovy
index 1e3f52e..22851fe 100644
--- a/subprojects/cli/src/test/groovy/org/gradle/cli/ParsedCommandLineTest.groovy
+++ b/subprojects/cli/src/test/groovy/org/gradle/cli/ParsedCommandLineTest.groovy
@@ -18,9 +18,6 @@ package org.gradle.cli
import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 4/16/12
- */
class ParsedCommandLineTest extends Specification {
def "knows if contains an option"() {
diff --git a/subprojects/code-quality/code-quality.gradle b/subprojects/code-quality/code-quality.gradle
index 90640da..0ecaff2 100644
--- a/subprojects/code-quality/code-quality.gradle
+++ b/subprojects/code-quality/code-quality.gradle
@@ -16,7 +16,7 @@
apply from: "$rootDir/gradle/providedConfiguration.gradle"
dependencies {
- groovy libraries.groovy
+ compile libraries.groovy
compile project(':core')
compile project(':plugins')
diff --git a/subprojects/code-quality/src/integTest/groovy/org/gradle/api/plugins/quality/CheckstylePluginIntegrationTest.groovy b/subprojects/code-quality/src/integTest/groovy/org/gradle/api/plugins/quality/CheckstylePluginIntegrationTest.groovy
index 2d8d517..8d7eb85 100644
--- a/subprojects/code-quality/src/integTest/groovy/org/gradle/api/plugins/quality/CheckstylePluginIntegrationTest.groovy
+++ b/subprojects/code-quality/src/integTest/groovy/org/gradle/api/plugins/quality/CheckstylePluginIntegrationTest.groovy
@@ -49,7 +49,7 @@ class CheckstylePluginIntegrationTest extends WellBehavedPluginTest {
expect:
fails("check")
- failure.assertHasDescription("Execution failed for task ':checkstyleMain'")
+ failure.assertHasDescription("Execution failed for task ':checkstyleMain'.")
failure.assertThatCause(startsWith("Checkstyle rule violations were found. See the report at:"))
failure.error.contains("Name 'class1' must match pattern")
file("build/reports/checkstyle/main.xml").assertContents(containsClass("org.gradle.class1"))
@@ -65,7 +65,7 @@ class CheckstylePluginIntegrationTest extends WellBehavedPluginTest {
then:
fails("check")
- failure.assertHasDescription("Execution failed for task ':checkstyleMain'")
+ failure.assertHasDescription("Execution failed for task ':checkstyleMain'.")
failure.assertThatCause(startsWith("Checkstyle rule violations were found. See the report at:"))
!failure.error.contains("Name 'class1' must match pattern")
file("build/reports/checkstyle/main.xml").assertContents(containsClass("org.gradle.class1"))
@@ -144,7 +144,7 @@ repositories {
}
dependencies {
- groovy localGroovy()
+ compile localGroovy()
}
"""
}
diff --git a/subprojects/code-quality/src/integTest/groovy/org/gradle/api/plugins/quality/CodeNarcPluginIntegrationTest.groovy b/subprojects/code-quality/src/integTest/groovy/org/gradle/api/plugins/quality/CodeNarcPluginIntegrationTest.groovy
index 162f9d9..b93799d 100644
--- a/subprojects/code-quality/src/integTest/groovy/org/gradle/api/plugins/quality/CodeNarcPluginIntegrationTest.groovy
+++ b/subprojects/code-quality/src/integTest/groovy/org/gradle/api/plugins/quality/CodeNarcPluginIntegrationTest.groovy
@@ -78,7 +78,7 @@ class CodeNarcPluginIntegrationTest extends WellBehavedPluginTest {
expect:
fails("check")
- failure.assertHasDescription("Execution failed for task ':codenarcTest'")
+ failure.assertHasDescription("Execution failed for task ':codenarcTest'.")
failure.assertThatCause(startsWith("CodeNarc rule violations were found. See the report at:"))
!file("build/reports/codenarc/main.html").text.contains("Class2")
file("build/reports/codenarc/test.html").text.contains("testclass2")
@@ -100,6 +100,20 @@ class CodeNarcPluginIntegrationTest extends WellBehavedPluginTest {
}
+ def "can configure max violations"() {
+ badCode()
+ buildFile << """
+ codenarcTest {
+ maxPriority2Violations = 1
+ }
+ """
+
+ expect:
+ succeeds("check")
+ !output.contains("CodeNarc rule violations were found. See the report at:")
+ file("build/reports/codenarc/test.html").text.contains("testclass2")
+ }
+
private goodCode() {
file("src/main/groovy/org/gradle/class1.java") << "package org.gradle; class class1 { }"
file("src/test/groovy/org/gradle/testclass1.java") << "package org.gradle; class testclass1 { }"
@@ -124,7 +138,7 @@ repositories {
}
dependencies {
- groovy localGroovy()
+ compile localGroovy()
}
"""
}
diff --git a/subprojects/code-quality/src/integTest/groovy/org/gradle/api/plugins/quality/CodeQualityPluginIntegrationTest.groovy b/subprojects/code-quality/src/integTest/groovy/org/gradle/api/plugins/quality/CodeQualityPluginIntegrationTest.groovy
index 3ef3675..265fd0f 100644
--- a/subprojects/code-quality/src/integTest/groovy/org/gradle/api/plugins/quality/CodeQualityPluginIntegrationTest.groovy
+++ b/subprojects/code-quality/src/integTest/groovy/org/gradle/api/plugins/quality/CodeQualityPluginIntegrationTest.groovy
@@ -37,7 +37,7 @@ apply plugin: 'groovy'
apply plugin: 'java'
apply plugin: 'code-quality'
repositories { mavenCentral() }
-dependencies { groovy localGroovy() }
+dependencies { compile localGroovy() }
'''
inTestDirectory().withTasks('check').run()
}
@@ -66,7 +66,7 @@ repositories { mavenCentral() }
apply plugin: 'groovy'
apply plugin: 'code-quality'
repositories { mavenCentral() }
-dependencies { groovy localGroovy() }
+dependencies { compile localGroovy() }
'''
writeCheckstyleConfig()
@@ -89,7 +89,7 @@ dependencies { groovy localGroovy() }
apply plugin: 'groovy'
apply plugin: 'code-quality'
repositories { mavenCentral() }
-dependencies { groovy localGroovy() }
+dependencies { compile localGroovy() }
'''
writeCheckstyleConfig()
@@ -109,7 +109,7 @@ dependencies { groovy localGroovy() }
apply plugin: 'groovy'
apply plugin: 'code-quality'
repositories { mavenCentral() }
-dependencies { groovy localGroovy() }
+dependencies { compile localGroovy() }
'''
writeCheckstyleConfig()
@@ -117,7 +117,7 @@ dependencies { groovy localGroovy() }
testFile('src/main/groovy/org/gradle/class2.java') << 'package org.gradle; class class2 { }'
ExecutionFailure failure = inTestDirectory().withTasks('check').runWithFailure()
- failure.assertHasDescription('Execution failed for task \':checkstyleMain\'')
+ failure.assertHasDescription('Execution failed for task \':checkstyleMain\'.')
failure.assertThatCause(startsWith('Checkstyle rule violations were found. See the report at'))
testFile('build/checkstyle/main.xml').assertExists()
@@ -129,7 +129,7 @@ dependencies { groovy localGroovy() }
apply plugin: 'groovy'
apply plugin: 'code-quality'
repositories { mavenCentral() }
-dependencies { groovy localGroovy() }
+dependencies { compile localGroovy() }
'''
writeCodeNarcConfigFile()
@@ -148,7 +148,7 @@ dependencies { groovy localGroovy() }
apply plugin: 'groovy'
apply plugin: 'code-quality'
repositories { mavenCentral() }
-dependencies { groovy localGroovy() }
+dependencies { compile localGroovy() }
'''
writeCodeNarcConfigFile()
@@ -167,7 +167,7 @@ dependencies { groovy localGroovy() }
apply plugin: 'groovy'
apply plugin: 'code-quality'
repositories { mavenCentral() }
-dependencies { groovy localGroovy() }
+dependencies { compile localGroovy() }
'''
writeCodeNarcConfigFile()
@@ -175,7 +175,7 @@ dependencies { groovy localGroovy() }
testFile('src/main/groovy/org/gradle/class1.groovy') << 'package org.gradle; class class1 { }'
ExecutionFailure failure = inTestDirectory().withTasks('check').runWithFailure()
- failure.assertHasDescription('Execution failed for task \':codenarcMain\'')
+ failure.assertHasDescription('Execution failed for task \':codenarcMain\'.')
failure.assertThatCause(startsWith('CodeNarc rule violations were found. See the report at:'))
testFile('build/reports/codenarc/main.html').assertExists()
diff --git a/subprojects/code-quality/src/integTest/groovy/org/gradle/api/plugins/quality/FindBugsPluginIntegrationTest.groovy b/subprojects/code-quality/src/integTest/groovy/org/gradle/api/plugins/quality/FindBugsPluginIntegrationTest.groovy
index 913f3a5..238fea7 100644
--- a/subprojects/code-quality/src/integTest/groovy/org/gradle/api/plugins/quality/FindBugsPluginIntegrationTest.groovy
+++ b/subprojects/code-quality/src/integTest/groovy/org/gradle/api/plugins/quality/FindBugsPluginIntegrationTest.groovy
@@ -45,7 +45,7 @@ class FindBugsPluginIntegrationTest extends WellBehavedPluginTest {
expect:
fails("check")
- failure.assertHasDescription("Execution failed for task ':findbugsMain'")
+ failure.assertHasDescription("Execution failed for task ':findbugsMain'.")
failure.assertThatCause(startsWith("FindBugs rule violations were found. See the report at:"))
file("build/reports/findbugs/main.xml").assertContents(containsClass("org.gradle.BadClass"))
}
diff --git a/subprojects/code-quality/src/integTest/groovy/org/gradle/api/plugins/quality/PmdPluginIntegrationTest.groovy b/subprojects/code-quality/src/integTest/groovy/org/gradle/api/plugins/quality/PmdPluginIntegrationTest.groovy
index dd47625..1c1f3dd 100644
--- a/subprojects/code-quality/src/integTest/groovy/org/gradle/api/plugins/quality/PmdPluginIntegrationTest.groovy
+++ b/subprojects/code-quality/src/integTest/groovy/org/gradle/api/plugins/quality/PmdPluginIntegrationTest.groovy
@@ -46,7 +46,7 @@ class PmdPluginIntegrationTest extends WellBehavedPluginTest {
expect:
fails("check")
- failure.assertHasDescription("Execution failed for task ':pmdTest'")
+ failure.assertHasDescription("Execution failed for task ':pmdTest'.")
failure.assertThatCause(containsString("2 PMD rule violations were found. See the report at:"))
file("build/reports/pmd/main.xml").assertContents(not(containsClass("org.gradle.Class1")))
file("build/reports/pmd/test.xml").assertContents(containsClass("org.gradle.Class1Test"))
@@ -112,7 +112,7 @@ class PmdPluginIntegrationTest extends WellBehavedPluginTest {
expect:
fails("pmdMain")
- failure.assertHasDescription("Execution failed for task ':pmdMain'")
+ failure.assertHasDescription("Execution failed for task ':pmdMain'.")
failure.assertThatCause(containsString("1 PMD rule violations were found. See the report at:"))
file("build/reports/pmd/main.xml").assertContents(not(containsClass("org.gradle.Class1")))
file("build/reports/pmd/main.xml").assertContents(containsClass("org.gradle.Class2"))
diff --git a/subprojects/code-quality/src/integTest/groovy/org/gradle/api/plugins/quality/PmdPluginVersionIntegrationTest.groovy b/subprojects/code-quality/src/integTest/groovy/org/gradle/api/plugins/quality/PmdPluginVersionIntegrationTest.groovy
index 5ca45d1..784bebd 100644
--- a/subprojects/code-quality/src/integTest/groovy/org/gradle/api/plugins/quality/PmdPluginVersionIntegrationTest.groovy
+++ b/subprojects/code-quality/src/integTest/groovy/org/gradle/api/plugins/quality/PmdPluginVersionIntegrationTest.groovy
@@ -23,7 +23,7 @@ import static org.gradle.util.Matchers.containsLine
import static org.hamcrest.Matchers.containsString
import static org.hamcrest.Matchers.not
- at TargetVersions(['4.3', '5.0.2'])
+ at TargetVersions(['4.3', '5.0.4'])
class PmdPluginVersionIntegrationTest extends MultiVersionIntegrationSpec {
def "can use different PMD versions"() {
given:
@@ -43,7 +43,7 @@ class PmdPluginVersionIntegrationTest extends MultiVersionIntegrationSpec {
expect:
fails("check")
- failure.assertHasDescription("Execution failed for task ':pmdTest'")
+ failure.assertHasDescription("Execution failed for task ':pmdTest'.")
failure.assertThatCause(containsString("2 PMD rule violations were found. See the report at:"))
file("build/reports/pmd/main.xml").assertContents(not(containsClass("org.gradle.Class1")))
file("build/reports/pmd/test.xml").assertContents(containsClass("org.gradle.Class1Test"))
diff --git a/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/CheckstyleReports.java b/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/CheckstyleReports.java
index 2c8307a..d4d493a 100644
--- a/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/CheckstyleReports.java
+++ b/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/CheckstyleReports.java
@@ -20,15 +20,14 @@ import org.gradle.api.reporting.ReportContainer;
import org.gradle.api.reporting.SingleFileReport;
/**
- * The reporting configuration for the the {@link Checkstyle} test.
+ * The reporting configuration for the {@link Checkstyle} test.
*/
public interface CheckstyleReports extends ReportContainer<SingleFileReport> {
/**
- * The checkstyle xml report
+ * The checkstyle XML report
*
- * @return The checkstyle xml report
+ * @return The checkstyle XML report
*/
SingleFileReport getXml();
-
}
diff --git a/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/CodeNarc.groovy b/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/CodeNarc.groovy
index 4c95f83..60d26e0 100644
--- a/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/CodeNarc.groovy
+++ b/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/CodeNarc.groovy
@@ -46,6 +46,24 @@ class CodeNarc extends SourceTask implements VerificationTask, Reporting<CodeNar
File configFile
/**
+ * The maximum number of priority 1 violations allowed before failing the build.
+ */
+ @Input
+ int maxPriority1Violations
+
+ /**
+ * The maximum number of priority 2 violations allowed before failing the build.
+ */
+ @Input
+ int maxPriority2Violations
+
+ /**
+ * The maximum number of priority 3 violations allowed before failing the build.
+ */
+ @Input
+ int maxPriority3Violations
+
+ /**
* The format type of the CodeNarc report.
*
* @deprecated Use {@code reports.<report-type>.enabled} instead.
@@ -109,7 +127,7 @@ class CodeNarc extends SourceTask implements VerificationTask, Reporting<CodeNar
antBuilder.withClasspath(getCodenarcClasspath()).execute {
ant.taskdef(name: 'codenarc', classname: 'org.codenarc.ant.CodeNarcTask')
try {
- ant.codenarc(ruleSetFiles: "file:${getConfigFile()}", maxPriority1Violations: 0, maxPriority2Violations: 0, maxPriority3Violations: 0) {
+ ant.codenarc(ruleSetFiles: "file:${getConfigFile()}", maxPriority1Violations: getMaxPriority1Violations(), maxPriority2Violations: getMaxPriority2Violations(), maxPriority3Violations: getMaxPriority3Violations()) {
reports.enabled.each { Report r ->
report(type: r.name) {
option(name: 'outputFile', value: r.destination)
@@ -150,6 +168,4 @@ class CodeNarc extends SourceTask implements VerificationTask, Reporting<CodeNar
CodeNarcReports reports(Closure closure) {
reports.configure(closure)
}
-
-
}
diff --git a/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/CodeNarcExtension.groovy b/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/CodeNarcExtension.groovy
index 86d2e57..f0af5e5 100644
--- a/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/CodeNarcExtension.groovy
+++ b/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/CodeNarcExtension.groovy
@@ -24,6 +24,21 @@ class CodeNarcExtension extends CodeQualityExtension {
File configFile
/**
+ * The maximum number of priority 1 violations allowed before failing the build.
+ */
+ int maxPriority1Violations
+
+ /**
+ * The maximum number of priority 2 violations allowed before failing the build.
+ */
+ int maxPriority2Violations
+
+ /**
+ * The maximum number of priority 3 violations allowed before failing the build.
+ */
+ int maxPriority3Violations
+
+ /**
* The format type of the CodeNarc report. One of <tt>html</tt>, <tt>xml</tt>, <tt>text</tt>, <tt>console</tt>.
*/
String reportFormat
diff --git a/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/CodeNarcPlugin.groovy b/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/CodeNarcPlugin.groovy
index fc3cc73..7eeb27b 100644
--- a/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/CodeNarcPlugin.groovy
+++ b/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/CodeNarcPlugin.groovy
@@ -43,6 +43,9 @@ class CodeNarcPlugin extends AbstractCodeQualityPlugin<CodeNarc> {
extension.with {
toolVersion = "0.18"
configFile = project.rootProject.file("config/codenarc/codenarc.xml")
+ maxPriority1Violations = 0
+ maxPriority2Violations = 0
+ maxPriority3Violations = 0
reportFormat = "html"
}
return extension
@@ -61,6 +64,9 @@ class CodeNarcPlugin extends AbstractCodeQualityPlugin<CodeNarc> {
config
}
configFile = { extension.configFile }
+ maxPriority1Violations = { extension.maxPriority1Violations }
+ maxPriority2Violations = { extension.maxPriority2Violations }
+ maxPriority3Violations = { extension.maxPriority3Violations }
ignoreFailures = { extension.ignoreFailures }
}
@@ -80,6 +86,6 @@ class CodeNarcPlugin extends AbstractCodeQualityPlugin<CodeNarc> {
task.with {
description = "Run CodeNarc analysis for $sourceSet.name classes"
}
- task.setSource( sourceSet.allGroovy )
+ task.setSource(sourceSet.allGroovy)
}
}
diff --git a/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/CodeNarcReports.java b/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/CodeNarcReports.java
index 808dda9..db62ea8 100644
--- a/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/CodeNarcReports.java
+++ b/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/CodeNarcReports.java
@@ -20,21 +20,21 @@ import org.gradle.api.reporting.ReportContainer;
import org.gradle.api.reporting.SingleFileReport;
/**
- * The reporting configuration for the the {@link CodeNarc} test.
+ * The reporting configuration for the {@link CodeNarc} test.
*/
public interface CodeNarcReports extends ReportContainer<SingleFileReport> {
/**
- * The codenarc xml report
+ * The codenarc XML report
*
- * @return The codenarc xml report
+ * @return The codenarc XML report
*/
SingleFileReport getXml();
/**
- * The codenarc html report
+ * The codenarc HTML report
*
- * @return The codenarc html report
+ * @return The codenarc HTML report
*/
SingleFileReport getHtml();
@@ -44,5 +44,4 @@ public interface CodeNarcReports extends ReportContainer<SingleFileReport> {
* @return The codenarc text report
*/
SingleFileReport getText();
-
}
diff --git a/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/FindBugsPlugin.groovy b/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/FindBugsPlugin.groovy
index b38df0a..ca805f5 100644
--- a/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/FindBugsPlugin.groovy
+++ b/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/FindBugsPlugin.groovy
@@ -52,7 +52,7 @@ class FindBugsPlugin extends AbstractCodeQualityPlugin<FindBugs> {
}
private configureFindBugsConfigurations() {
- project.configurations.add('findbugsPlugins').with {
+ project.configurations.create('findbugsPlugins').with {
visible = false
transitive = true
description = 'The FindBugs plugins to be used for this project.'
diff --git a/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/FindBugsReports.java b/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/FindBugsReports.java
index 6c0a28c..5e213c1 100644
--- a/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/FindBugsReports.java
+++ b/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/FindBugsReports.java
@@ -20,25 +20,24 @@ import org.gradle.api.reporting.ReportContainer;
import org.gradle.api.reporting.SingleFileReport;
/**
- * The reporting configuration for the the {@link FindBugs} task.
+ * The reporting configuration for the {@link FindBugs} task.
*
- * Only one of the xml or html reports can be enabled when the task executes. If more than one is enabled, an {@link org.gradle.api.InvalidUserDataException}
+ * Only one of the XML or HTML reports can be enabled when the task executes. If more than one is enabled, an {@link org.gradle.api.InvalidUserDataException}
* will be thrown.
*/
public interface FindBugsReports extends ReportContainer<SingleFileReport> {
/**
- * The findbugs xml report
+ * The findbugs XML report
*
- * @return The findbugs xml report
+ * @return The findbugs XML report
*/
SingleFileReport getXml();
/**
- * The findbugs html report
+ * The findbugs HTML report
*
- * @return The findbugs html report
+ * @return The findbugs HTML report
*/
SingleFileReport getHtml();
-
}
diff --git a/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/JDepend.groovy b/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/JDepend.groovy
index e20f8a7..b493c44 100644
--- a/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/JDepend.groovy
+++ b/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/JDepend.groovy
@@ -42,7 +42,7 @@ class JDepend extends DefaultTask implements Reporting<JDependReports> {
@InputDirectory
File classesDir
- // workaround for GRADLE-2020
+ // workaround for GRADLE-2026
/**
* Returns the directory containing the classes to be analyzed.
*/
diff --git a/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/JDependReports.java b/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/JDependReports.java
index e6d038d..a40c6f6 100644
--- a/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/JDependReports.java
+++ b/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/JDependReports.java
@@ -20,17 +20,17 @@ import org.gradle.api.reporting.ReportContainer;
import org.gradle.api.reporting.SingleFileReport;
/**
- * The reporting configuration for the the {@link JDepend} task.
+ * The reporting configuration for the {@link JDepend} task.
*
- * Exactly one of the xml or html reports can be enabled when the task executes. If more than one or none is enabled, an {@link org.gradle.api.InvalidUserDataException}
+ * Exactly one of the XML or HTML reports can be enabled when the task executes. If more than one or none is enabled, an {@link org.gradle.api.InvalidUserDataException}
* will be thrown.
*/
public interface JDependReports extends ReportContainer<SingleFileReport> {
/**
- * The jdepend xml report
+ * The jdepend XML report
*
- * @return The jdepend xml report
+ * @return The jdepend XML report
*/
SingleFileReport getXml();
@@ -40,5 +40,4 @@ public interface JDependReports extends ReportContainer<SingleFileReport> {
* @return The jdepend text report
*/
SingleFileReport getText();
-
}
diff --git a/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/PmdExtension.groovy b/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/PmdExtension.groovy
index 1af0df5..d36d82e 100644
--- a/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/PmdExtension.groovy
+++ b/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/PmdExtension.groovy
@@ -51,6 +51,7 @@ class PmdExtension extends CodeQualityExtension {
void setTargetJdk(def value) {
targetJdk = TargetJdk.toVersion(value)
}
+
/**
* Convenience method for adding rule sets.
*
diff --git a/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/PmdReports.java b/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/PmdReports.java
index 3307f0b..fe2adda 100644
--- a/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/PmdReports.java
+++ b/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/PmdReports.java
@@ -20,21 +20,21 @@ import org.gradle.api.reporting.ReportContainer;
import org.gradle.api.reporting.SingleFileReport;
/**
- * The reporting configuration for the the {@link Pmd} task.
+ * The reporting configuration for the {@link Pmd} task.
*/
public interface PmdReports extends ReportContainer<SingleFileReport> {
/**
- * The pmd (single file) html report
+ * The pmd (single file) HTML report
*
- * @return The pmd (single file) html report
+ * @return The pmd (single file) HTML report
*/
SingleFileReport getHtml();
/**
- * The pmd (single file) xml report
+ * The pmd (single file) XML report
*
- * @return The pmd (single file) xml report
+ * @return The pmd (single file) XML report
*/
SingleFileReport getXml();
}
diff --git a/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/internal/AbstractCodeQualityPlugin.groovy b/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/internal/AbstractCodeQualityPlugin.groovy
index 23aef56..7a7b4f8 100644
--- a/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/internal/AbstractCodeQualityPlugin.groovy
+++ b/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/internal/AbstractCodeQualityPlugin.groovy
@@ -64,7 +64,7 @@ abstract class AbstractCodeQualityPlugin<T> implements Plugin<ProjectInternal> {
}
protected void createConfigurations() {
- project.configurations.add(configurationName).with {
+ project.configurations.create(configurationName).with {
visible = false
transitive = true
description = "The ${toolName} libraries to be used for this project."
@@ -109,7 +109,7 @@ abstract class AbstractCodeQualityPlugin<T> implements Plugin<ProjectInternal> {
private void configureSourceSetRule() {
project.plugins.withType(basePlugin) {
project.sourceSets.all { SourceSet sourceSet ->
- T task = project.tasks.add(sourceSet.getTaskName(taskBaseName, null), taskType)
+ T task = project.tasks.create(sourceSet.getTaskName(taskBaseName, null), taskType)
configureForSourceSet(sourceSet, task)
}
}
diff --git a/subprojects/code-quality/src/test/groovy/org/gradle/api/plugins/quality/CheckstylePluginTest.groovy b/subprojects/code-quality/src/test/groovy/org/gradle/api/plugins/quality/CheckstylePluginTest.groovy
index afadcfd..07edfff 100644
--- a/subprojects/code-quality/src/test/groovy/org/gradle/api/plugins/quality/CheckstylePluginTest.groovy
+++ b/subprojects/code-quality/src/test/groovy/org/gradle/api/plugins/quality/CheckstylePluginTest.groovy
@@ -18,7 +18,7 @@ package org.gradle.api.plugins.quality
import org.gradle.api.Project
import org.gradle.api.plugins.ReportingBasePlugin
import org.gradle.api.tasks.SourceSet
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import org.gradle.api.plugins.JavaBasePlugin
import spock.lang.Specification
@@ -28,7 +28,7 @@ import static org.hamcrest.Matchers.*
import static spock.util.matcher.HamcrestSupport.that
class CheckstylePluginTest extends Specification {
- Project project = HelperUtil.createRootProject()
+ Project project = TestUtil.createRootProject()
def setup() {
project.plugins.apply(CheckstylePlugin)
@@ -88,7 +88,7 @@ class CheckstylePluginTest extends Specification {
}
def "configures any additional checkstyle tasks"() {
- def task = project.tasks.add("checkstyleCustom", Checkstyle)
+ def task = project.tasks.create("checkstyleCustom", Checkstyle)
expect:
task.description == null
@@ -153,7 +153,7 @@ class CheckstylePluginTest extends Specification {
}
def "can customize any additional checkstyle tasks via extension"() {
- def task = project.tasks.add("checkstyleCustom", Checkstyle)
+ def task = project.tasks.create("checkstyleCustom", Checkstyle)
project.checkstyle {
configFile = project.file("checkstyle-config")
configProperties = [foo: "foo"]
diff --git a/subprojects/code-quality/src/test/groovy/org/gradle/api/plugins/quality/CheckstyleTest.groovy b/subprojects/code-quality/src/test/groovy/org/gradle/api/plugins/quality/CheckstyleTest.groovy
index 6b72fd4..c53f5e8 100644
--- a/subprojects/code-quality/src/test/groovy/org/gradle/api/plugins/quality/CheckstyleTest.groovy
+++ b/subprojects/code-quality/src/test/groovy/org/gradle/api/plugins/quality/CheckstyleTest.groovy
@@ -23,7 +23,7 @@ import spock.lang.Specification
class CheckstyleTest extends Specification {
def "default configuration"() {
def project = ProjectBuilder.builder().build()
- def checkstyle = project.tasks.add("checkstyle", Checkstyle)
+ def checkstyle = project.tasks.create("checkstyle", Checkstyle)
expect:
with(checkstyle) {
diff --git a/subprojects/code-quality/src/test/groovy/org/gradle/api/plugins/quality/CodeNarcPluginTest.groovy b/subprojects/code-quality/src/test/groovy/org/gradle/api/plugins/quality/CodeNarcPluginTest.groovy
index 17ac7b4..134958b 100644
--- a/subprojects/code-quality/src/test/groovy/org/gradle/api/plugins/quality/CodeNarcPluginTest.groovy
+++ b/subprojects/code-quality/src/test/groovy/org/gradle/api/plugins/quality/CodeNarcPluginTest.groovy
@@ -18,7 +18,7 @@ package org.gradle.api.plugins.quality
import org.gradle.api.Project
import org.gradle.api.plugins.GroovyBasePlugin
import org.gradle.api.tasks.SourceSet
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import spock.lang.Specification
import static org.gradle.util.Matchers.dependsOn
import static org.hamcrest.Matchers.hasItems
@@ -26,7 +26,7 @@ import static spock.util.matcher.HamcrestSupport.that
import org.gradle.api.plugins.ReportingBasePlugin
class CodeNarcPluginTest extends Specification {
- Project project = HelperUtil.createRootProject()
+ Project project = TestUtil.createRootProject()
def setup() {
project.plugins.apply(CodeNarcPlugin)
@@ -51,6 +51,9 @@ class CodeNarcPluginTest extends Specification {
expect:
CodeNarcExtension codenarc = project.extensions.codenarc
codenarc.configFile == project.file("config/codenarc/codenarc.xml")
+ codenarc.maxPriority1Violations == 0
+ codenarc.maxPriority2Violations == 0
+ codenarc.maxPriority3Violations == 0
codenarc.reportFormat == "html"
codenarc.reportsDir == project.file("build/reports/codenarc")
codenarc.sourceSets == []
@@ -79,6 +82,9 @@ class CodeNarcPluginTest extends Specification {
assert source as List == sourceSet.allGroovy as List
assert codenarcClasspath == project.configurations.codenarc
assert configFile == project.file("config/codenarc/codenarc.xml")
+ assert maxPriority1Violations == 0
+ assert maxPriority2Violations == 0
+ assert maxPriority3Violations == 0
assert reportFormat == "html"
assert reportFile == project.file("build/reports/codenarc/${sourceSet.name}.html")
assert ignoreFailures == false
@@ -96,6 +102,9 @@ class CodeNarcPluginTest extends Specification {
project.codenarc {
checkTasks = ["codenarcMain"]
configFile = project.file("codenarc-config")
+ maxPriority1Violations = 10
+ maxPriority2Violations = 50
+ maxPriority3Violations = 200
reportFormat = "xml"
reportsDir = project.file("codenarc-reports")
ignoreFailures = true
@@ -115,6 +124,9 @@ class CodeNarcPluginTest extends Specification {
assert source as List == sourceSet.allGroovy as List
assert codenarcClasspath == project.configurations.codenarc
assert configFile == project.file("codenarc-config")
+ assert maxPriority1Violations == 10
+ assert maxPriority2Violations == 50
+ assert maxPriority3Violations == 200
assert reportFormat == "xml"
assert reportFile == project.file("codenarc-reports/${sourceSet.name}.xml")
assert ignoreFailures == true
@@ -122,23 +134,29 @@ class CodeNarcPluginTest extends Specification {
}
def "configures any additional codenarc tasks"() {
- def task = project.tasks.add("codenarcCustom", CodeNarc)
+ def task = project.tasks.create("codenarcCustom", CodeNarc)
expect:
task.description == null
task.source.isEmpty()
task.codenarcClasspath == project.configurations.codenarc
task.configFile == project.file("config/codenarc/codenarc.xml")
+ task.maxPriority1Violations == 0
+ task.maxPriority2Violations == 0
+ task.maxPriority3Violations == 0
task.reportFormat == "html"
task.reportFile == project.file("build/reports/codenarc/custom.html")
task.ignoreFailures == false
}
def "can customize additional tasks via extension"() {
- def task = project.tasks.add("codenarcCustom", CodeNarc)
+ def task = project.tasks.create("codenarcCustom", CodeNarc)
project.codenarc {
configFile = project.file("codenarc-config")
+ maxPriority1Violations = 10
+ maxPriority2Violations = 50
+ maxPriority3Violations = 200
reportFormat = "xml"
reportsDir = project.file("codenarc-reports")
ignoreFailures = true
@@ -149,6 +167,9 @@ class CodeNarcPluginTest extends Specification {
task.source.isEmpty()
task.codenarcClasspath == project.configurations.codenarc
task.configFile == project.file("codenarc-config")
+ task.maxPriority1Violations == 10
+ task.maxPriority2Violations == 50
+ task.maxPriority3Violations == 200
task.reportFormat == "xml"
task.reportFile == project.file("codenarc-reports/custom.xml")
task.ignoreFailures == true
@@ -162,7 +183,7 @@ class CodeNarcPluginTest extends Specification {
other
}
- project.tasks.add("codenarcCustom", CodeNarc)
+ project.tasks.create("codenarcCustom", CodeNarc)
expect:
that(project.check, dependsOn(hasItems("codenarcMain", "codenarcTest", "codenarcOther")))
@@ -176,7 +197,7 @@ class CodeNarcPluginTest extends Specification {
other
}
- project.tasks.add("codenarcCustom", CodeNarc)
+ project.tasks.create("codenarcCustom", CodeNarc)
project.codenarc {
sourceSets = [project.sourceSets.main]
@@ -187,7 +208,7 @@ class CodeNarcPluginTest extends Specification {
}
def "can customize task directly"() {
- CodeNarc task = project.tasks.add("codenarcCustom", CodeNarc)
+ CodeNarc task = project.tasks.create("codenarcCustom", CodeNarc)
task.reports.xml {
enabled true
diff --git a/subprojects/code-quality/src/test/groovy/org/gradle/api/plugins/quality/CodeQualityPluginTest.groovy b/subprojects/code-quality/src/test/groovy/org/gradle/api/plugins/quality/CodeQualityPluginTest.groovy
index 147bd99..b07f03c 100644
--- a/subprojects/code-quality/src/test/groovy/org/gradle/api/plugins/quality/CodeQualityPluginTest.groovy
+++ b/subprojects/code-quality/src/test/groovy/org/gradle/api/plugins/quality/CodeQualityPluginTest.groovy
@@ -19,7 +19,7 @@ import org.gradle.api.Project
import org.gradle.api.plugins.GroovyPlugin
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.plugins.ReportingBasePlugin
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import org.junit.Test
import static org.gradle.util.Matchers.*
import static org.hamcrest.Matchers.*
@@ -28,7 +28,7 @@ import org.gradle.api.plugins.JavaBasePlugin
import org.gradle.api.plugins.GroovyBasePlugin
class CodeQualityPluginTest {
- private final Project project = HelperUtil.createRootProject()
+ private final Project project = TestUtil.createRootProject()
private final CodeQualityPlugin plugin = new CodeQualityPlugin()
@Test public void appliesCheckstyleAndCodeNarcPlugins() {
@@ -78,7 +78,7 @@ class CodeQualityPluginTest {
assertThat(task.properties, equalTo(project.checkstyleProperties))
assertThat(task, dependsOn(JavaPlugin.TEST_CLASSES_TASK_NAME))
- project.sourceSets.add('custom')
+ project.sourceSets.create('custom')
task = project.tasks['checkstyleCustom']
assertThat(task, instanceOf(Checkstyle))
assertThat(task.source as List, equalTo(project.sourceSets.custom.allJava as List))
@@ -114,7 +114,7 @@ class CodeQualityPluginTest {
assertThat(task.reportFile, equalTo(project.file("build/reports/codenarc/test.html")))
assertThat(task, dependsOn())
- project.sourceSets.add('custom')
+ project.sourceSets.create('custom')
task = project.tasks['codenarcCustom']
assertThat(task, instanceOf(CodeNarc))
assertThat(task.source as List, equalTo(project.sourceSets.custom.allGroovy as List))
@@ -135,7 +135,7 @@ class CodeQualityPluginTest {
project.checkstyleProperties.someProp = 'someValue'
- def task = project.tasks.add('checkstyleApi', Checkstyle)
+ def task = project.tasks.create('checkstyleApi', Checkstyle)
assertThat(task.source, isEmpty())
assertThat(task.checkstyleClasspath, equalTo(project.configurations.checkstyle))
assertThat(task.configFile, equalTo(project.checkstyleConfigFile))
@@ -148,7 +148,7 @@ class CodeQualityPluginTest {
project.checkstyleProperties.someProp = 'someValue'
- def task = project.tasks.add('codenarcApi', CodeNarc)
+ def task = project.tasks.create('codenarcApi', CodeNarc)
assertThat(task.source, isEmpty())
assertThat(task.codenarcClasspath, equalTo(project.configurations.codenarc))
assertThat(task.configFile, equalTo(project.codeNarcConfigFile))
diff --git a/subprojects/code-quality/src/test/groovy/org/gradle/api/plugins/quality/FindBugsPluginTest.groovy b/subprojects/code-quality/src/test/groovy/org/gradle/api/plugins/quality/FindBugsPluginTest.groovy
index e7640cd..05ccfe8 100644
--- a/subprojects/code-quality/src/test/groovy/org/gradle/api/plugins/quality/FindBugsPluginTest.groovy
+++ b/subprojects/code-quality/src/test/groovy/org/gradle/api/plugins/quality/FindBugsPluginTest.groovy
@@ -19,8 +19,7 @@ import org.gradle.api.Project
import org.gradle.api.plugins.JavaBasePlugin
import org.gradle.api.plugins.ReportingBasePlugin
import org.gradle.api.tasks.SourceSet
-import org.gradle.util.HelperUtil
-
+import org.gradle.util.TestUtil
import spock.lang.Specification
import static org.gradle.util.Matchers.dependsOn
@@ -28,7 +27,7 @@ import static org.hamcrest.Matchers.*
import static spock.util.matcher.HamcrestSupport.that
class FindBugsPluginTest extends Specification {
- Project project = HelperUtil.createRootProject()
+ Project project = TestUtil.createRootProject()
def setup() {
project.plugins.apply(FindBugsPlugin)
@@ -96,7 +95,7 @@ class FindBugsPluginTest extends Specification {
}
def "configures any additional FindBugs tasks"() {
- def task = project.tasks.add("findbugsCustom", FindBugs)
+ def task = project.tasks.create("findbugsCustom", FindBugs)
expect:
with(task) {
@@ -176,7 +175,7 @@ class FindBugsPluginTest extends Specification {
}
def "can customize any additional FindBugs tasks via extension"() {
- def task = project.tasks.add("findbugsCustom", FindBugs)
+ def task = project.tasks.create("findbugsCustom", FindBugs)
project.findbugs {
reportsDir = project.file("findbugs-reports")
ignoreFailures = true
diff --git a/subprojects/code-quality/src/test/groovy/org/gradle/api/plugins/quality/FindBugsTest.groovy b/subprojects/code-quality/src/test/groovy/org/gradle/api/plugins/quality/FindBugsTest.groovy
index 1c3077e..3a9d1d9 100644
--- a/subprojects/code-quality/src/test/groovy/org/gradle/api/plugins/quality/FindBugsTest.groovy
+++ b/subprojects/code-quality/src/test/groovy/org/gradle/api/plugins/quality/FindBugsTest.groovy
@@ -27,7 +27,7 @@ class FindBugsTest extends Specification {
def setup() {
def project = ProjectBuilder.builder().build()
- findbugs = project.tasks.add("findbugs", FindBugs)
+ findbugs = project.tasks.create("findbugs", FindBugs)
}
def "fails when errorCount greater than zero"() {
diff --git a/subprojects/code-quality/src/test/groovy/org/gradle/api/plugins/quality/JDependPluginTest.groovy b/subprojects/code-quality/src/test/groovy/org/gradle/api/plugins/quality/JDependPluginTest.groovy
index 424a8eb..62c2b0e 100644
--- a/subprojects/code-quality/src/test/groovy/org/gradle/api/plugins/quality/JDependPluginTest.groovy
+++ b/subprojects/code-quality/src/test/groovy/org/gradle/api/plugins/quality/JDependPluginTest.groovy
@@ -19,14 +19,14 @@ import org.gradle.api.Project
import org.gradle.api.plugins.JavaBasePlugin
import org.gradle.api.plugins.ReportingBasePlugin
import org.gradle.api.tasks.SourceSet
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import spock.lang.Specification
import static org.gradle.util.Matchers.dependsOn
import static org.hamcrest.Matchers.*
import static spock.util.matcher.HamcrestSupport.that
class JDependPluginTest extends Specification {
- Project project = HelperUtil.createRootProject()
+ Project project = TestUtil.createRootProject()
def setup() {
project.plugins.apply(JDependPlugin)
@@ -80,7 +80,7 @@ class JDependPluginTest extends Specification {
}
def "configures any additional JDepend tasks"() {
- def task = project.tasks.add("jdependCustom", JDepend)
+ def task = project.tasks.create("jdependCustom", JDepend)
expect:
task.description == null
@@ -124,7 +124,7 @@ class JDependPluginTest extends Specification {
}
def "can customize any additional JDepend tasks via extension"() {
- def task = project.tasks.add("jdependCustom", JDepend)
+ def task = project.tasks.create("jdependCustom", JDepend)
project.jdepend {
reportsDir = project.file("jdepend-reports")
}
diff --git a/subprojects/code-quality/src/test/groovy/org/gradle/api/plugins/quality/PmdPluginTest.groovy b/subprojects/code-quality/src/test/groovy/org/gradle/api/plugins/quality/PmdPluginTest.groovy
index b708011..6b0544e 100644
--- a/subprojects/code-quality/src/test/groovy/org/gradle/api/plugins/quality/PmdPluginTest.groovy
+++ b/subprojects/code-quality/src/test/groovy/org/gradle/api/plugins/quality/PmdPluginTest.groovy
@@ -19,7 +19,7 @@ import org.gradle.api.Project
import org.gradle.api.plugins.JavaBasePlugin
import org.gradle.api.plugins.ReportingBasePlugin
import org.gradle.api.tasks.SourceSet
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import spock.lang.Specification
import static org.gradle.util.Matchers.dependsOn
@@ -27,7 +27,7 @@ import static org.hamcrest.Matchers.*
import static spock.util.matcher.HamcrestSupport.that
class PmdPluginTest extends Specification {
- Project project = HelperUtil.createRootProject()
+ Project project = TestUtil.createRootProject()
def setup() {
project.plugins.apply(PmdPlugin)
@@ -110,7 +110,7 @@ class PmdPluginTest extends Specification {
}
def "configures any additional PMD tasks"() {
- def task = project.tasks.add("pmdCustom", Pmd)
+ def task = project.tasks.create("pmdCustom", Pmd)
expect:
task.description == null
@@ -175,7 +175,7 @@ class PmdPluginTest extends Specification {
}
def "can customize any additional PMD tasks via extension"() {
- def task = project.tasks.add("pmdCustom", Pmd)
+ def task = project.tasks.create("pmdCustom", Pmd)
project.pmd {
ruleSets = ["braces", "unusedcode"]
ruleSetFiles = project.files("my-ruleset.xml")
diff --git a/subprojects/core-impl/core-impl.gradle b/subprojects/core-impl/core-impl.gradle
index 495307e..7962bae 100644
--- a/subprojects/core-impl/core-impl.gradle
+++ b/subprojects/core-impl/core-impl.gradle
@@ -7,8 +7,6 @@ configurations {
}
dependencies {
- groovy libraries.groovy
-
compile project(":core")
compile libraries.commons_httpclient
@@ -26,6 +24,8 @@ dependencies {
mvn3Input libraries.maven3
+ testCompile libraries.groovy
+
//this dependency is necessary to run IvySFtpResolverIntegrationTest on ibm jdk
integTestRuntime "org.bouncycastle:bcprov-jdk15:1.46 at jar"
}
@@ -51,6 +51,7 @@ def allJarJars = tasks.withType(JarJar)
ideaModule.dependsOn allJarJars
eclipseClasspath.dependsOn allJarJars
useTestFixtures()
+useTestFixtures(project: ":messaging")
def avoidConflictingPlexusComponents(JarJar task) {
//DefaultSecDispatcher component is configured in 2 different jars (META-INF/plexus/components.xml).
diff --git a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ArtifactDependenciesIntegrationTest.groovy b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ArtifactDependenciesIntegrationTest.groovy
index 89a69ea..441b8c2 100644
--- a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ArtifactDependenciesIntegrationTest.groovy
+++ b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ArtifactDependenciesIntegrationTest.groovy
@@ -165,6 +165,36 @@ project(':b') {
}
@Test
+ public void artifactFilesPreserveFixedOrder() {
+ repo.module('org', 'leaf1').publish()
+ repo.module('org', 'leaf2').publish()
+ repo.module('org', 'leaf3').publish()
+ repo.module('org', 'leaf4').publish()
+
+ repo.module('org', 'middle1').dependsOn("leaf1", "leaf2").publish()
+ repo.module('org', 'middle2').dependsOn("leaf3", "leaf4").publish()
+
+ repo.module('org', 'top').dependsOn("middle1", "middle2").publish()
+
+ testFile('build.gradle') << """
+ repositories {
+ maven { url '${repo.uri}' }
+ }
+ configurations {
+ compile
+ }
+ dependencies {
+ compile "org:middle2:1.0", "org:middle1:1.0"
+ }
+ task test << {
+ assert configurations.compile.files.collect { it.name } == ['middle2-1.0.jar', 'middle1-1.0.jar', 'leaf3-1.0.jar', 'leaf4-1.0.jar', 'leaf1-1.0.jar', 'leaf2-1.0.jar']
+ }
+ """
+
+ executer.withTasks("test").run()
+ }
+
+ @Test
public void exposesMetaDataAboutResolvedArtifactsInAFixedOrder() {
def module = repo.module('org.gradle.test', 'lib', '1.0')
module.artifact(type: 'zip')
@@ -186,7 +216,7 @@ dependencies {
compile "org.gradle.test:dist:1.0"
}
task test << {
- assert configurations.compile.files.collect { it.name } == ['lib-1.0.jar', 'lib-1.0.zip', 'lib-1.0-classifier.jar', 'dist-1.0.zip']
+ assert configurations.compile.files.collect { it.name } == ['lib-1.0.jar', 'lib-1.0-classifier.jar', 'lib-1.0.zip', 'dist-1.0.zip']
def artifacts = configurations.compile.resolvedConfiguration.resolvedArtifacts as List
assert artifacts.size() == 4
assert artifacts[0].name == 'lib'
@@ -611,7 +641,7 @@ task test << {
failure
.assertHasFileName("Build file '" + buildFile.getPath() + "'")
- .assertHasDescription("Execution failed for task ':listJars'");
+ .assertHasDescription("Execution failed for task ':listJars'.");
failure.assertResolutionFailure(':compile')
.assertHasCause("Could not find test:unknownProjectA:1.2.")
@@ -622,7 +652,7 @@ task test << {
public void projectCanDependOnItself() {
TestFile buildFile = testFile("build.gradle");
buildFile << '''
- configurations { compile; add('default') }
+ configurations { compile; create('default') }
dependencies { compile project(':') }
task jar1(type: Jar) { destinationDir = buildDir; baseName = '1' }
task jar2(type: Jar) { destinationDir = buildDir; baseName = '2' }
diff --git a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ClientModuleDependenciesResolveIntegrationTest.groovy b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ClientModuleDependenciesResolveIntegrationTest.groovy
index b347c86..5529aaf 100644
--- a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ClientModuleDependenciesResolveIntegrationTest.groovy
+++ b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ClientModuleDependenciesResolveIntegrationTest.groovy
@@ -18,9 +18,6 @@ package org.gradle.integtests.resolve
import org.gradle.integtests.fixtures.AbstractDependencyResolutionTest
import org.junit.Test
-/**
- * @author Hans Dockter
- */
public class ClientModuleDependenciesResolveIntegrationTest extends AbstractDependencyResolutionTest {
@Test
public void "uses metadata from Client Module and looks up artifact in declared repositories"() {
diff --git a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/DependencyNotationIntegrationSpec.groovy b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/DependencyNotationIntegrationSpec.groovy
index f2c2a12..445dfb1 100644
--- a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/DependencyNotationIntegrationSpec.groovy
+++ b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/DependencyNotationIntegrationSpec.groovy
@@ -19,9 +19,6 @@ package org.gradle.integtests.resolve
import org.gradle.integtests.fixtures.AbstractIntegrationSpec
import org.hamcrest.Matchers
-/**
- * by Szczepan Faber, created at: 11/9/11
- */
class DependencyNotationIntegrationSpec extends AbstractIntegrationSpec {
def "understands dependency notations"() {
diff --git a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/DependencyResolveRulesIntegrationTest.groovy b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/DependencyResolveRulesIntegrationTest.groovy
index df3c85f..f83563f 100644
--- a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/DependencyResolveRulesIntegrationTest.groovy
+++ b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/DependencyResolveRulesIntegrationTest.groovy
@@ -21,9 +21,6 @@ import org.gradle.integtests.fixtures.AbstractIntegrationSpec
import static org.gradle.util.TextUtil.toPlatformLineSeparators
-/**
- * @author Szczepan Faber, @date 03.03.11
- */
class DependencyResolveRulesIntegrationTest extends AbstractIntegrationSpec {
void "forces multiple modules by rule"()
@@ -717,6 +714,39 @@ class DependencyResolveRulesIntegrationTest extends AbstractIntegrationSpec {
failure.assertResolutionFailure(":conf").assertHasCause("Invalid format: 'foobar'")
}
+ def "substituted module version participates in conflict resolution"()
+ {
+ mavenRepo.module("org", "a", "2.0").dependsOn("org", "b", "2.0").publish()
+ mavenRepo.module("org", "b", "2.0").dependsOn("org", "c", "2.0").publish()
+ mavenRepo.module("org", "c", "2.0").publish()
+
+ buildFile << """
+ $common
+
+ dependencies {
+ conf 'org:a:1.0', 'org:a:2.0'
+ }
+
+ configurations.conf.resolutionStrategy.eachDependency {
+ if (it.requested.name == 'a' && it.requested.version == '1.0') {
+ it.useTarget group: 'org', name: 'c', version: '1.1'
+ }
+ }
+"""
+
+ when:
+ run("dependencies")
+
+ then:
+ output.contains(toPlatformLineSeparators("""
+conf
++--- org:a:1.0 -> org:c:2.0
+\\--- org:a:2.0
+ \\--- org:b:2.0
+ \\--- org:c:2.0
+"""))
+ }
+
def "module selected by conflict resolution can be selected again in a another pass of conflict resolution"()
{
mavenRepo.module("org", "a", "1.0").publish()
diff --git a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/DetachedConfigurationsIntegrationTest.groovy b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/DetachedConfigurationsIntegrationTest.groovy
new file mode 100644
index 0000000..f3570f8
--- /dev/null
+++ b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/DetachedConfigurationsIntegrationTest.groovy
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests.resolve
+
+import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+import spock.lang.Issue
+
+class DetachedConfigurationsIntegrationTest extends AbstractIntegrationSpec {
+
+ @Issue("GRADLE-2889")
+ def "detached configurations may have separate dependencies"() {
+ settingsFile << "include 'a', 'b'"
+ mavenRepo.module("org", "foo").publish()
+ mavenRepo.module("org", "bar").publish()
+
+ buildFile << """
+ allprojects {
+ configurations {
+ foo
+ }
+ repositories {
+ maven { url "${mavenRepo.uri}" }
+ }
+ task checkDependencies() << {
+ configurations.each { conf ->
+ def declared = conf.dependencies
+ def detached = project.configurations.detachedConfiguration(declared as Dependency[])
+ def resolved = detached.resolvedConfiguration.getFirstLevelModuleDependencies()
+ assert declared*.name == resolved*.moduleName
+ }
+ }
+ }
+ project(":a") {
+ dependencies {
+ foo "org:foo:1.0"
+ }
+ }
+ project(":b") {
+ dependencies {
+ foo "org:bar:1.0"
+ }
+ }
+ """
+
+ expect:
+ run "checkDependencies"
+ }
+}
diff --git a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ExtendingConfigurationsIntegrationTest.groovy b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ExtendingConfigurationsIntegrationTest.groovy
new file mode 100644
index 0000000..9dd235e
--- /dev/null
+++ b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ExtendingConfigurationsIntegrationTest.groovy
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests.resolve;
+
+import org.gradle.integtests.fixtures.AbstractDependencyResolutionTest
+import spock.lang.Issue;
+
+public class ExtendingConfigurationsIntegrationTest extends AbstractDependencyResolutionTest {
+
+ @Issue("GRADLE-2873")
+ def "may replace configuration extension targets"() {
+ mavenRepo.module("org", "foo").publish()
+ mavenRepo.module("org", "bar").publish()
+
+ buildFile << """
+ configurations {
+ fooConf
+ barConf
+ conf
+ }
+
+ dependencies {
+ fooConf 'org:foo:1.0'
+ barConf 'org:bar:1.0'
+ }
+
+ task check << {
+ configurations.conf.extendsFrom(configurations.fooConf)
+ assert configurations.conf.allDependencies*.name == ['foo']
+
+ //purposefully again:
+ configurations.conf.extendsFrom(configurations.fooConf)
+ assert configurations.conf.allDependencies*.name == ['foo']
+
+ //replace:
+ configurations.conf.extendsFrom = [configurations.barConf] as Set
+ assert configurations.conf.allDependencies*.name == ['bar']
+ }
+ """
+
+ when:
+ run "check"
+
+ then:
+ noExceptionThrown()
+ }
+}
diff --git a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ForcedModulesIntegrationTest.groovy b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ForcedModulesIntegrationTest.groovy
index 94bebef..d68511d 100644
--- a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ForcedModulesIntegrationTest.groovy
+++ b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ForcedModulesIntegrationTest.groovy
@@ -17,10 +17,7 @@ package org.gradle.integtests.resolve
import org.gradle.integtests.fixtures.AbstractIntegrationSpec
-/**
- * @author Szczepan Faber, @date 03.03.11
- */
-class ForcedModulesIntegrationTest extends AbstractIntegrationSpec {
+public class ForcedModulesIntegrationTest extends AbstractIntegrationSpec {
void "can force the version of a particular module"() {
mavenRepo.module("org", "foo", '1.3.3').publish()
diff --git a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ProjectDependenciesIntegrationTest.groovy b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ProjectDependenciesIntegrationTest.groovy
index 23e3602..7c231ce 100644
--- a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ProjectDependenciesIntegrationTest.groovy
+++ b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ProjectDependenciesIntegrationTest.groovy
@@ -21,9 +21,6 @@ package org.gradle.integtests.resolve
import org.gradle.integtests.fixtures.AbstractDependencyResolutionTest
import spock.lang.Issue
-/**
- * by Szczepan Faber, created at: 11/21/12
- */
class ProjectDependenciesIntegrationTest extends AbstractDependencyResolutionTest {
@Issue("GRADLE-2477") //this is a feature on its own but also covers one of the reported issues
@@ -59,7 +56,7 @@ class ProjectDependenciesIntegrationTest extends AbstractDependencyResolutionTes
def "configuring project dependencies by map is validated"() {
settingsFile << "include 'impl'"
buildFile << """
- allprojects { configurations.add('conf') }
+ allprojects { configurations.create('conf') }
task extraKey << {
def dep = dependencies.project(path: ":impl", configuration: ":conf", foo: "bar")
assert dep.foo == "bar"
diff --git a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ProjectDependencyResolveIntegrationTest.groovy b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ProjectDependencyResolveIntegrationTest.groovy
index a7f7f2c..597c97e 100644
--- a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ProjectDependencyResolveIntegrationTest.groovy
+++ b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ProjectDependencyResolveIntegrationTest.groovy
@@ -148,17 +148,18 @@ allprojects {
project(":a") {
configurations { 'default' {} }
dependencies { 'default' 'group:externalA:1.5' }
- task aJar(type: Jar) { }
- artifacts { 'default' aJar }
+ task aJar(type: Jar) { baseName='a' }
+ task bJar(type: Jar) { baseName='b' }
+ artifacts { 'default' aJar, bJar }
}
project(":b") {
configurations { compile }
- dependencies { compile(project(':a')) { artifact { name = 'a'; type = 'jar' } } }
+ dependencies { compile(project(':a')) { artifact { name = 'b'; type = 'jar' } } }
task test {
inputs.files configurations.compile
doFirst {
- assert configurations.compile.files.collect { it.name } == ['a.jar', 'externalA-1.5.jar']
+ assert configurations.compile.files.collect { it.name } == ['b.jar', 'externalA-1.5.jar']
}
}
}
@@ -168,6 +169,38 @@ project(":b") {
succeeds 'test'
}
+ public void "reports project dependency that refers to an unknown artifact"() {
+ given:
+ file('settings.gradle') << """
+include 'a', 'b'
+"""
+
+ and:
+ buildFile << """
+allprojects { group = 'test' }
+project(":a") {
+ configurations { 'default' {} }
+}
+
+project(":b") {
+ configurations { compile }
+ dependencies { compile(project(':a')) { artifact { name = 'b'; type = 'jar' } } }
+ task test {
+ inputs.files configurations.compile
+ doFirst {
+ assert configurations.compile.files.collect { it.name } == ['a-b.jar', 'externalA-1.5.jar']
+ }
+ }
+}
+"""
+
+ expect:
+ fails 'test'
+
+ and:
+ failure.assertResolutionFailure(":b:compile").assertHasCause("Artifact 'test:a:unspecified at jar' not found.")
+ }
+
public void "non-transitive project dependency includes only the artifacts of the target configuration"() {
given:
mavenRepo.module("group", "externalA", 1.5).publish()
diff --git a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ResolutionResultApiIntegrationTest.groovy b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ResolutionResultApiIntegrationTest.groovy
new file mode 100644
index 0000000..dd2403a
--- /dev/null
+++ b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ResolutionResultApiIntegrationTest.groovy
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests.resolve
+
+import org.gradle.integtests.fixtures.AbstractDependencyResolutionTest
+
+import static org.gradle.util.TextUtil.toPlatformLineSeparators
+
+class ResolutionResultApiIntegrationTest extends AbstractDependencyResolutionTest {
+
+ /*
+ The ResolutionResult API is also covered by the dependency report integration tests.
+ */
+
+ def "selection reasons are described"() {
+ given:
+ mavenRepo.module("org", "leaf", 1.0).publish()
+ mavenRepo.module("org", "leaf", 2.0).publish()
+ mavenRepo.module("org", "foo", 0.5).publish()
+
+ mavenRepo.module("org", "foo", 1.0).dependsOn('org', 'leaf', '1.0').publish()
+ mavenRepo.module("org", "bar", 1.0).dependsOn('org', 'leaf', '2.0').publish()
+ mavenRepo.module("org", "baz", 1.0).dependsOn('org', 'foo', '1.0').publish()
+
+ file("settings.gradle") << "rootProject.name = 'cool-project'"
+
+ file("build.gradle") << """
+ version = '5.0'
+ repositories {
+ maven { url "${mavenRepo.uri}" }
+ }
+ configurations {
+ conf
+ }
+ configurations.conf.resolutionStrategy.force 'org:leaf:2.0'
+ dependencies {
+ conf 'org:foo:0.5', 'org:bar:1.0', 'org:baz:1.0'
+ }
+ task resolutionResult << {
+ def result = configurations.conf.incoming.resolutionResult
+ result.allModuleVersions {
+ println it.id.name + ":" + it.id.version + " " + it.selectionReason.description
+ }
+ }
+ """
+
+ when:
+ run "resolutionResult"
+
+ then:
+ output.contains(toPlatformLineSeparators("""
+cool-project:5.0 root
+foo:1.0 conflict resolution
+leaf:2.0 forced
+bar:1.0 requested
+baz:1.0 requested
+"""))
+ }
+}
diff --git a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ResolutionStrategySamplesIntegrationTest.groovy b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ResolutionStrategySamplesIntegrationTest.groovy
index aae6410..81885f3 100644
--- a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ResolutionStrategySamplesIntegrationTest.groovy
+++ b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ResolutionStrategySamplesIntegrationTest.groovy
@@ -20,10 +20,7 @@ import org.gradle.integtests.fixtures.AbstractIntegrationSpec
import org.gradle.integtests.fixtures.Sample
import org.junit.Rule
-/**
- * @author Szczepan Faber, @date 03.03.11
- */
-class ResolutionStrategySamplesIntegrationTest extends AbstractIntegrationSpec {
+public class ResolutionStrategySamplesIntegrationTest extends AbstractIntegrationSpec {
@Rule public final Sample sample = new Sample(temporaryFolder, 'userguide/artifacts/resolutionStrategy')
diff --git a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ResolveCrossVersionIntegrationTest.groovy b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ResolveCrossVersionIntegrationTest.groovy
index 6883df0..81d178b 100644
--- a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ResolveCrossVersionIntegrationTest.groovy
+++ b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ResolveCrossVersionIntegrationTest.groovy
@@ -16,14 +16,26 @@
package org.gradle.integtests.resolve
import org.gradle.integtests.fixtures.CrossVersionIntegrationSpec
+import org.gradle.test.fixtures.server.http.HttpServer
+import org.junit.Rule
class ResolveCrossVersionIntegrationTest extends CrossVersionIntegrationSpec {
+ @Rule HttpServer server = new HttpServer()
def "can upgrade and downgrade Gradle version"() {
given:
+ mavenRepo.module("test", "io", "1.4").publish()
+ mavenRepo.module("test", "lang", "2.4").publish()
+ mavenRepo.module("test", "lang", "2.6").publish()
+
+ and:
+ server.start()
+ server.allowGetOrHead("/repo", mavenRepo.rootDir)
+
+ and:
buildFile << """
repositories {
- mavenCentral()
+ mavenRepo urls: "http://localhost:${server.port}/repo"
}
configurations {
@@ -31,12 +43,12 @@ configurations {
}
dependencies {
- compile 'commons-io:commons-io:1.4'
- compile 'commons-lang:commons-lang:2.+'
+ compile 'test:io:1.4'
+ compile 'test:lang:2.+'
}
task check << {
- assert configurations.compile*.name as Set == ['commons-io-1.4.jar', 'commons-lang-2.6.jar'] as Set
+ assert configurations.compile*.name as Set == ['io-1.4.jar', 'lang-2.6.jar'] as Set
}
"""
diff --git a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ResolvedConfigurationIntegrationTest.groovy b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ResolvedConfigurationIntegrationTest.groovy
index 8c1b112..4fbb47a 100644
--- a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ResolvedConfigurationIntegrationTest.groovy
+++ b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ResolvedConfigurationIntegrationTest.groovy
@@ -20,13 +20,13 @@ import org.gradle.api.artifacts.LenientConfiguration
import org.gradle.api.internal.project.DefaultProject
import org.gradle.api.specs.Specs
import org.gradle.integtests.fixtures.AbstractIntegrationTest
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import org.junit.Before
import org.junit.Test
public class ResolvedConfigurationIntegrationTest extends AbstractIntegrationTest {
- def DefaultProject project = HelperUtil.createRootProject()
- def Project childProject = HelperUtil.createChildProject(project, "child", new File("."))
+ def DefaultProject project = TestUtil.createRootProject()
+ def Project childProject = TestUtil.createChildProject(project, "child", new File("."))
@Before
public void boringSetup() {
diff --git a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/VersionConflictResolutionIntegrationTest.groovy b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/VersionConflictResolutionIntegrationTest.groovy
index 0d4da25..e249531 100644
--- a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/VersionConflictResolutionIntegrationTest.groovy
+++ b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/VersionConflictResolutionIntegrationTest.groovy
@@ -21,10 +21,7 @@ import spock.lang.Issue
import static org.gradle.util.TextUtil.toPlatformLineSeparators
import static org.hamcrest.Matchers.containsString
-/**
- * @author Szczepan Faber, @date 03.03.11
- */
-class VersionConflictResolutionIntegrationTest extends AbstractIntegrationSpec {
+public class VersionConflictResolutionIntegrationTest extends AbstractIntegrationSpec {
void "strict conflict resolution should fail due to conflict"() {
mavenRepo.module("org", "foo", '1.3.3').publish()
@@ -172,6 +169,37 @@ task checkDeps << {
run("checkDeps")
}
+ @Issue("GRADLE-2890")
+ void "selects latest from multiple conflicts"() {
+ mavenRepo.module("org", "child", '1').publish()
+ mavenRepo.module("org", "child", '2').publish()
+ mavenRepo.module("org", "parent", '1').dependsOn("org", "child", "1").publish()
+ mavenRepo.module("org", "parent", '2').dependsOn("org", "child", "2").publish()
+ mavenRepo.module("org", "dep", '2').dependsOn("org", "parent", "2").publish()
+
+ buildFile << """
+repositories {
+ maven { url "${mavenRepo.uri}" }
+}
+configurations {
+ compile
+}
+dependencies {
+ compile 'org:parent:1'
+ compile 'org:child:2'
+ compile 'org:dep:2'
+}
+task checkDeps(dependsOn: configurations.compile) << {
+ assert configurations.compile*.name == ['child-2.jar', 'dep-2.jar', 'parent-2.jar']
+ configurations.compile.resolvedConfiguration.firstLevelModuleDependencies*.name
+ configurations.compile.incoming.resolutionResult.allModuleVersions*.id
+}
+"""
+
+ expect:
+ run("checkDeps")
+ }
+
void "resolves dynamic dependency before resolving conflict"() {
mavenRepo.module("org", "external", "1.2").publish()
mavenRepo.module("org", "external", "1.4").publish()
@@ -445,7 +473,7 @@ task checkDeps << {
}
task checkDeps << {
- assert configurations.conf*.name == ['a-1.0.jar', 'b-1.0.jar', 'target-child-1.0.jar', 'target-1.0.jar', 'in-conflict-2.0.jar', 'b-child-1.0.jar']
+ assert configurations.conf*.name == ['a-1.0.jar', 'b-1.0.jar', 'b-child-1.0.jar', 'target-1.0.jar', 'in-conflict-2.0.jar', 'target-child-1.0.jar']
def result = configurations.conf.incoming.resolutionResult
assert result.allModuleVersions.size() == 7
def a = result.allModuleVersions.find { it.id.name == 'a' }
@@ -506,7 +534,6 @@ task checkDeps << {
run("dependencies")
then:
- //TODO SF proper assertions
output.contains(toPlatformLineSeparators("""
childFirst
+--- org:d:1.0
@@ -530,4 +557,118 @@ parentFirst
\\--- org:f:1.0
\\--- org:x:2.0 FAILED"""))
}
+
+ @Issue("GRADLE-2752")
+ void "does not replace root module when earlier version of root module is requested"() {
+ mavenRepo.module("org", "test", "1.2").publish()
+ mavenRepo.module("org", "other", "1.7").dependsOn("org", "test", "1.2").publish()
+
+ settingsFile << "rootProject.name= 'test'"
+
+ buildFile << """
+apply plugin: 'java'
+
+group "org"
+version "1.3"
+
+repositories {
+ maven { url "${mavenRepo.uri}" }
+}
+
+dependencies {
+ compile "org:other:1.7"
+}
+
+task checkDeps(dependsOn: configurations.compile) << {
+ assert configurations.compile*.name == ['other-1.7.jar', 'test-1.3.jar']
+
+ def result = configurations.compile.incoming.resolutionResult
+ assert result.allModuleVersions.size() == 2
+
+ def root = result.root
+ assert root.id.version == '1.3'
+ assert root.selectionReason.description == 'root'
+ assert !root.selectionReason.conflictResolution //current behavior, feels incorrect
+
+ def other = result.allModuleVersions.find { it.id.name == 'other' }
+
+ assert root.dependencies*.selected == [other]
+ assert other.dependencies*.selected == [root]
+}
+"""
+
+ expect:
+ run("checkDeps")
+ }
+
+ void "module is required only by selected conflicting version and in turn requires evicted conflicting version"() {
+ /*
+ a2 -> b1 -> c1
+ a1
+ c2
+ */
+ mavenRepo.module("org", "a", "1").publish()
+ mavenRepo.module("org", "a", "2").dependsOn("org", "b", "1").publish()
+ mavenRepo.module("org", "b", "1").dependsOn("org", "c", "1").publish()
+ mavenRepo.module("org", "c", "1").publish()
+ mavenRepo.module("org", "c", "2").publish()
+
+ settingsFile << "rootProject.name= 'test'"
+
+ buildFile << """
+repositories {
+ maven { url "${mavenRepo.uri}" }
+}
+configurations {
+ compile
+}
+dependencies {
+ compile "org:a:2"
+ compile "org:a:1"
+ compile "org:c:2"
+}
+
+task checkDeps(dependsOn: configurations.compile) << {
+ assert configurations.compile*.name == ['a-2.jar', 'c-2.jar', 'b-1.jar']
+ assert configurations.compile.incoming.resolutionResult.allModuleVersions.find { it.id.name == 'b' }.dependencies.size() == 1
+}
+"""
+
+ expect:
+ run("checkDeps")
+ }
+
+ @Issue("GRADLE-2738")
+ def "resolution fails when any selector cannot be resolved"() {
+ given:
+ //only 1.5 published:
+ mavenRepo.module("org", "leaf", "1.5").publish()
+
+ mavenRepo.module("org", "c", "1.0").dependsOn("org", "leaf", "2.0+").publish()
+ mavenRepo.module("org", "a", "1.0").dependsOn("org", "leaf", "1.0").publish()
+ mavenRepo.module("org", "b", "1.0").dependsOn("org", "leaf", "[1.5,1.9]").publish()
+
+ settingsFile << "rootProject.name = 'broken'"
+ buildFile << """
+ version = 12
+ repositories {
+ maven { url "${mavenRepo.uri}" }
+ }
+ configurations {
+ conf
+ }
+ dependencies {
+ conf 'org:a:1.0', 'org:b:1.0', 'org:c:1.0'
+ }
+ task resolve << {
+ configurations.conf.files
+ }
+ """
+
+ when:
+ runAndFail "resolve"
+
+ then:
+ failure.assertResolutionFailure(":conf").assertFailedDependencyRequiredBy(":broken:12 > org:c:1.0")
+ }
}
diff --git a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/artifactreuse/AbstractCacheReuseCrossVersionIntegrationTest.groovy b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/artifactreuse/AbstractCacheReuseCrossVersionIntegrationTest.groovy
index 285c1f5..0e2295d 100644
--- a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/artifactreuse/AbstractCacheReuseCrossVersionIntegrationTest.groovy
+++ b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/artifactreuse/AbstractCacheReuseCrossVersionIntegrationTest.groovy
@@ -22,9 +22,6 @@ import org.gradle.api.internal.artifacts.ivyservice.DefaultCacheLockingManager
import org.gradle.integtests.fixtures.CrossVersionIntegrationSpec
import org.gradle.integtests.fixtures.executer.UnderDevelopmentGradleDistribution
-/**
- * by Szczepan Faber, created at: 11/27/12
- */
abstract class AbstractCacheReuseCrossVersionIntegrationTest extends CrossVersionIntegrationSpec {
/**
diff --git a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/artifactreuse/AliasedArtifactResolutionIntegrationTest.groovy b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/artifactreuse/AliasedArtifactResolutionIntegrationTest.groovy
index 8adfc88..7859a85 100644
--- a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/artifactreuse/AliasedArtifactResolutionIntegrationTest.groovy
+++ b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/artifactreuse/AliasedArtifactResolutionIntegrationTest.groovy
@@ -64,11 +64,10 @@ class AliasedArtifactResolutionIntegrationTest extends AbstractDependencyResolut
when:
def projectBModuleRepo2 = mavenRepo2.module('org.name', 'projectB', '1.0').publish()
- def projectBArtifactRepo2 = projectBModuleRepo2.artifact
projectBModuleRepo2.pom.expectHead()
projectBModuleRepo2.pom.sha1.expectGet()
- projectBArtifactRepo2.expectHead()
- projectBArtifactRepo2.sha1.expectGet()
+ projectBModuleRepo2.artifact.expectHead()
+ projectBModuleRepo2.artifact.sha1.expectGet()
then:
succeedsWith 'mavenRepository2'
@@ -98,7 +97,7 @@ class AliasedArtifactResolutionIntegrationTest extends AbstractDependencyResolut
when:
def projectBRepo1 = mavenRepo1.module('org.name', 'projectB', '1.0').publish()
projectBRepo1.pom.expectGet()
- projectBRepo1.getArtifact().expectGet()
+ projectBRepo1.artifact.expectGet()
then:
succeedsWith 'mavenRepository1'
@@ -125,9 +124,8 @@ class AliasedArtifactResolutionIntegrationTest extends AbstractDependencyResolut
when:
def projectBRepo2 = mavenRepo1.module('org.name', 'projectB', '1.0').publish()
projectBRepo2.pom.expectGet()
- def projectBRepo2Artifact = projectBRepo2.artifact
- projectBRepo2Artifact.expectHead()
- projectBRepo2Artifact.sha1.expectGet()
+ projectBRepo2.artifact.expectHead()
+ projectBRepo2.artifact.sha1.expectGet()
then:
succeedsWith 'mavenRepository1'
@@ -153,7 +151,7 @@ class AliasedArtifactResolutionIntegrationTest extends AbstractDependencyResolut
when:
def projectBRepo1 = mavenRepo1.module('org.name', 'projectB', '1.0').publish()
projectBRepo1.pom.expectGet()
- projectBRepo1.getArtifact().expectGet()
+ projectBRepo1.artifact.expectGet()
then:
succeedsWith 'mavenRepository1'
@@ -175,7 +173,7 @@ class AliasedArtifactResolutionIntegrationTest extends AbstractDependencyResolut
when:
def projectBRepo1 = mavenRepo1.module('org.name', 'projectB', '1.0').publish()
projectBRepo1.pom.expectGet()
- projectBRepo1.getArtifact().expectGet()
+ projectBRepo1.artifact.expectGet()
then:
succeedsWith 'mavenRepository1'
@@ -186,10 +184,9 @@ class AliasedArtifactResolutionIntegrationTest extends AbstractDependencyResolut
projectBRepo2.pom.sha1.expectGet()
projectBRepo2.pom.expectGet()
- def projRepo2BArtifact = projectBRepo2.artifact
- projRepo2BArtifact.expectHead()
+ projectBRepo2.artifact.expectHead()
projectBRepo2.artifact.sha1.expectGet()
- projRepo2BArtifact.expectGet()
+ projectBRepo2.artifact.expectGet()
then:
succeedsWith 'mavenRepository2'
diff --git a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/caching/CachingDependencyMetadataInMemoryIntegrationTest.groovy b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/caching/CachingDependencyMetadataInMemoryIntegrationTest.groovy
new file mode 100644
index 0000000..f07bf0a
--- /dev/null
+++ b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/caching/CachingDependencyMetadataInMemoryIntegrationTest.groovy
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests.resolve.caching
+
+import org.gradle.integtests.fixtures.AbstractDependencyResolutionTest
+import org.gradle.test.fixtures.ivy.IvyFileRepository
+import spock.lang.Ignore
+
+class CachingDependencyMetadataInMemoryIntegrationTest extends AbstractDependencyResolutionTest {
+
+ def "descriptor and artifact is cached in memory"() {
+ given:
+ mavenRepo.module("org", "lib").publish()
+
+ file("build.gradle") << """
+ configurations {
+ one
+ two
+ }
+ repositories {
+ ivy { url "${mavenRepo.uri}" }
+ }
+ dependencies {
+ one 'org:lib:1.0'
+ two 'org:lib:1.0'
+ }
+ //runs first and resolves
+ task resolveOne << {
+ configurations.one.files
+ }
+ //runs second, purges repo
+ task purgeRepo(type: Delete, dependsOn: resolveOne) {
+ delete "${mavenRepo.uri}"
+ }
+ //runs last, still works even thoug local repo is empty
+ task resolveTwo(dependsOn: purgeRepo) << {
+ println "Resolved " + configurations.two.files*.name
+ }
+ """
+
+ when:
+ run "resolveTwo"
+
+ then:
+ output.contains 'Resolved [lib-1.0.jar]'
+ }
+
+ def "descriptors and artifacts are cached across projects and repositories"() {
+ given:
+ ivyRepo.module("org", "lib").publish()
+
+ file("settings.gradle") << "include 'impl'"
+
+ file("build.gradle") << """
+ allprojects {
+ configurations { conf }
+ repositories { ivy { url "${ivyRepo.uri}" } }
+ dependencies { conf 'org:lib:1.0' }
+ task resolveConf << { println path + " " + configurations.conf.files*.name }
+ }
+ task purgeRepo(type: Delete, dependsOn: ':impl:resolveConf') {
+ delete "${ivyRepo.uri}"
+ }
+ resolveConf.dependsOn purgeRepo
+ """
+
+ when:
+ run "resolveConf"
+
+ then:
+ output.contains ':impl:resolveConf [lib-1.0.jar]'
+ output.contains ':resolveConf [lib-1.0.jar]'
+ }
+
+ def "descriptors and artifacts are separated for different repositories"() {
+ given:
+ ivyRepo.module("org", "lib").publish()
+ def ivyRepo2 = new IvyFileRepository(file("ivy-repo2"))
+ ivyRepo2.module("org", "lib", "2.0").publish() //different version of lib
+
+ file("settings.gradle") << "include 'impl'"
+
+ file("build.gradle") << """
+ allprojects {
+ configurations { conf }
+ dependencies { conf 'org:lib:1.0' }
+ task resolveConf << { println "\$path " + configurations.conf.files*.name }
+ }
+ repositories { ivy { url "${ivyRepo.uri}" } }
+ project(":impl") {
+ repositories { ivy { url "${ivyRepo2.uri}" } }
+ tasks.resolveConf.dependsOn(":resolveConf")
+ }
+ """
+
+ when:
+ runAndFail ":impl:resolveConf"
+
+ then:
+ output.contains ':resolveConf [lib-1.0.jar]'
+ //uses different repo that does not contain this dependency
+ failure.assertResolutionFailure(":impl:conf").assertHasCause("Could not find org:lib:1.0")
+ }
+
+ @Ignore //TODO SF rework or remove this test
+ def "snapshot artifacts are only cached per build"() {
+ given:
+ file("provider/build.gradle") << """
+ apply plugin: 'java'
+ apply plugin: 'maven'
+ group = 'org'
+ archivesBaseName = 'provider'
+ version = '1.0-SNAPSHOT'
+ repositories { maven { url "$mavenRepo.uri" } }
+ """
+ file("provider/src/main/java/Name.java") << """public class Name {
+ public String toString() { return "foo"; }
+ }"""
+
+ when:
+ inDirectory "provider"; run "install"
+
+ then:
+ noExceptionThrown()
+
+ when:
+ file("consumer/build.gradle") << """
+ buildscript {
+ repositories { mavenLocal() }
+ dependencies { classpath 'org:provider:1.0-SNAPSHOT' }
+ }
+ task printName << { println "Name: " + new Name() }
+ """
+
+ inDirectory("consumer"); run "printName"
+
+ then:
+ output.contains "Name: foo"
+
+ when:
+ //change the class
+ file("provider/src/main/java/Name.java").text = """public class Name {
+ public String toString() { return "updated"; }
+ }"""
+
+ inDirectory("provider"); run "install"
+
+ and:
+ inDirectory("consumer"); run "printName"
+
+ then:
+ output.contains "Name: updated" //uses updated artifact
+ }
+
+ def "cache expires at the end of build"() {
+ given:
+ ivyRepo.module("org", "dependency").publish()
+ ivyRepo.module("org", "lib").publish()
+
+ file("build.gradle") << """
+ configurations {
+ configurations { conf }
+ repositories { ivy { url "${ivyRepo.uri}" } }
+ dependencies { conf 'org:lib:1.0' }
+ }
+ """
+
+ when:
+ run "dependencies", "--configuration", "conf"
+
+ then:
+ !output.contains("org:dependency:1.0")
+
+ when:
+ ivyRepo.module("org", "lib").dependsOn("org", "dependency", "1.0").publish()
+ run "dependencies", "--configuration", "conf"
+
+ then:
+ output.contains("org:dependency:1.0")
+ }
+}
diff --git a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/custom/FileSystemResolverIntegrationTest.groovy b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/custom/FileSystemResolverIntegrationTest.groovy
index 1a8b161..652edfe 100644
--- a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/custom/FileSystemResolverIntegrationTest.groovy
+++ b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/custom/FileSystemResolverIntegrationTest.groovy
@@ -19,9 +19,8 @@ package org.gradle.integtests.resolve.custom
import org.gradle.integtests.fixtures.AbstractIntegrationSpec
class FileSystemResolverIntegrationTest extends AbstractIntegrationSpec {
-
def "file system resolvers use item at source by default"() {
- when:
+ given:
def module = ivyRepo.module("group", "projectA", "1.2")
module.publish()
def jar = module.jarFile
@@ -45,16 +44,21 @@ class FileSystemResolverIntegrationTest extends AbstractIntegrationSpec {
}
"""
+ when:
+ executer.withDeprecationChecksDisabled()
+ run 'echoContent'
+
then:
- succeeds 'echoContent'
scrapeValue("content") == "1"
scrapeValue("path") == jar.canonicalPath
when:
jar.text = "2"
+ executer.withDeprecationChecksDisabled()
+ run 'echoContent'
+
then:
- succeeds 'echoContent'
scrapeValue("content") == "2"
scrapeValue("path") == jar.canonicalPath
}
diff --git a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/custom/IvySFtpResolverIntegrationTest.groovy b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/custom/IvySFtpResolverIntegrationTest.groovy
index 67e2a21..2aed311 100644
--- a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/custom/IvySFtpResolverIntegrationTest.groovy
+++ b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/custom/IvySFtpResolverIntegrationTest.groovy
@@ -28,7 +28,7 @@ class IvySFtpResolverIntegrationTest extends AbstractIntegrationSpec {
@Rule ProgressLoggingFixture progressLogging = new ProgressLoggingFixture(executer, temporaryFolder)
- def "setup"() {
+ def setup() {
requireOwnGradleUserHomeDir()
}
@@ -58,7 +58,8 @@ task listJars << {
}
"""
when:
- succeeds 'listJars'
+ executer.withDeprecationChecksDisabled()
+ run 'listJars'
then:
server.fileRequests == ["repos/libs/group/projectA/1.2/ivy-1.2.xml",
@@ -70,7 +71,8 @@ task listJars << {
when:
server.clearRequests()
- succeeds 'listJars'
+ executer.withDeprecationChecksDisabled()
+ run 'listJars'
then:
server.fileRequests.empty
diff --git a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/custom/IvyUrlResolverIntegrationTest.groovy b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/custom/IvyUrlResolverIntegrationTest.groovy
index f9d2964..5a07eac 100644
--- a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/custom/IvyUrlResolverIntegrationTest.groovy
+++ b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/custom/IvyUrlResolverIntegrationTest.groovy
@@ -24,7 +24,7 @@ class IvyUrlResolverIntegrationTest extends AbstractDependencyResolutionTest {
@Rule ProgressLoggingFixture progressLogging = new ProgressLoggingFixture(executer, temporaryFolder)
def setup() {
- server.expectUserAgent(null) // custom resolver uses apache/ivy as useragent strings
+ server.expectUserAgent(null) // custom resolver uses apache/ivy as user agent strings
}
public void "can resolve and cache dependencies from an HTTP Ivy repository"() {
@@ -52,6 +52,7 @@ task listJars << {
module.expectIvyGet()
module.expectJarHead()
module.expectJarGet()
+ executer.withDeprecationChecksDisabled()
then:
succeeds 'listJars'
@@ -62,6 +63,7 @@ task listJars << {
when:
server.resetExpectations()
+ executer.withDeprecationChecksDisabled()
// No extra calls for cached dependencies
then:
@@ -97,6 +99,7 @@ task retrieve(type: Sync) {
module.expectIvyGet()
module.expectJarHead()
module.expectJarGet()
+ executer.withDeprecationChecksDisabled()
run 'retrieve'
@@ -114,6 +117,7 @@ task retrieve(type: Sync) {
module.expectIvyGet()
module.expectJarHead()
module.expectJarGet()
+ executer.withDeprecationChecksDisabled()
run 'retrieve'
diff --git a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ivy/IvyBrokenRemoteResolveIntegrationTest.groovy b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ivy/IvyBrokenRemoteResolveIntegrationTest.groovy
index fca2690..1ee80e4 100644
--- a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ivy/IvyBrokenRemoteResolveIntegrationTest.groovy
+++ b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ivy/IvyBrokenRemoteResolveIntegrationTest.groovy
@@ -57,7 +57,7 @@ task showMissing << { println configurations.missing.files }
succeeds('showMissing')
}
- public void "reports and recovers from broken module"() {
+ public void "reports and recovers from failed Ivy descriptor download"() {
server.start()
given:
@@ -176,4 +176,35 @@ task retrieve(type: Sync) {
succeeds "retrieve"
file('libs').assertHasDescendants('projectA-1.2.jar')
}
+
+ public void "reports Ivy descriptor that cannot be parsed"() {
+ server.start()
+ given:
+ buildFile << """
+repositories {
+ ivy {
+ url "${ivyHttpRepo.uri}"
+ }
+}
+configurations { compile }
+dependencies {
+ compile 'group:projectA:1.2'
+}
+task showBroken << { println configurations.compile.files }
+"""
+
+ and:
+ def module = ivyHttpRepo.module('group', 'projectA', '1.2').publish()
+ module.ivyFile.text = "<ivy-module>"
+
+ when:
+ module.expectIvyGet()
+
+ then:
+ fails "showBroken"
+ failure
+ .assertResolutionFailure(":compile")
+ .assertHasCause("Could not parse Ivy file ${module.ivyFileUri}")
+ .assertHasCause("invalid version null")
+ }
}
diff --git a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ivy/IvyChangingModuleRemoteResolveIntegrationTest.groovy b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ivy/IvyChangingModuleRemoteResolveIntegrationTest.groovy
index 2bcdea5..0319d6e 100644
--- a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ivy/IvyChangingModuleRemoteResolveIntegrationTest.groovy
+++ b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ivy/IvyChangingModuleRemoteResolveIntegrationTest.groovy
@@ -70,7 +70,6 @@ task retrieve(type: Copy) {
module.expectIvySha1Get()
module.expectIvyGet()
module.expectJarHead()
- module.expectJarSha1Get()
module.expectArtifactGet('other')
moduleB.expectIvyGet()
moduleB.expectJarGet()
diff --git a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ivy/IvyComponentMetadataRulesIntegrationTest.groovy b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ivy/IvyComponentMetadataRulesIntegrationTest.groovy
new file mode 100644
index 0000000..65b2e0b
--- /dev/null
+++ b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ivy/IvyComponentMetadataRulesIntegrationTest.groovy
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests.resolve.ivy
+
+import org.gradle.integtests.fixtures.AbstractDependencyResolutionTest
+
+import static org.hamcrest.Matchers.containsString
+
+class IvyComponentMetadataRulesIntegrationTest extends AbstractDependencyResolutionTest {
+ def setup() {
+ buildFile <<
+"""
+repositories {
+ ivy {
+ url "${ivyRepo.uri}"
+ }
+}
+
+configurations { compile }
+
+dependencies {
+ compile 'org.test:projectA:1.0'
+}
+
+task resolve(type: Sync) {
+ from configurations.compile
+ into 'libs'
+}
+"""
+ }
+
+ def "rule is being passed correct, mutable metadata"() {
+ ivyRepo.module('org.test', 'projectA', '1.0').withStatus("release").publish()
+ buildFile <<
+"""
+dependencies {
+ components {
+ eachComponent { details ->
+ assert details.id.group == "org.test"
+ assert details.id.name == "projectA"
+ assert details.id.version == "1.0"
+ assert details.status == "release"
+ assert details.statusScheme == ["integration", "milestone", "release"]
+
+ details.status "silver" // verify that 'details' is enhanced
+ assert details.status == "silver"
+
+ details.statusScheme = ["bronze", "silver", "gold"]
+ assert details.statusScheme == ["bronze", "silver", "gold"]
+ }
+ }
+}
+"""
+
+ expect:
+ succeeds 'resolve'
+ }
+
+ def "module with custom status can be resolved by adapting status scheme"() {
+ ivyRepo.module('org.test', 'projectA', '1.0').withStatus("silver").publish()
+ buildFile <<
+"""
+dependencies {
+ components {
+ eachComponent { details ->
+ details.statusScheme = ["gold", "silver", "bronze"]
+ }
+ }
+}
+"""
+
+ expect:
+ succeeds 'resolve'
+ file('libs').assertHasDescendants('projectA-1.0.jar')
+ }
+
+ def "resolve fails if status doesn't match default status scheme"() {
+ ivyRepo.module('org.test', 'projectA', '1.0').withStatus("silver").publish()
+
+ expect:
+ fails 'resolve'
+ failure.assertThatCause(containsString("bad status: 'silver'"))
+ }
+
+ def "resolve fails if status doesn't match custom status scheme"() {
+ ivyRepo.module('org.test', 'projectA', '1.0').withStatus("silver").publish()
+ buildFile <<
+"""
+dependencies {
+ components {
+ eachComponent { details ->
+ details.statusScheme = ["gold", "bronze"]
+ }
+ }
+}
+"""
+
+ expect:
+ fails 'resolve'
+ failure.assertThatCause(containsString("bad status: 'silver'"))
+ }
+
+ def "rule can change status"() {
+ ivyRepo.module('org.test', 'projectA', '1.0').withStatus("silver").publish()
+ buildFile <<
+"""
+dependencies {
+ components {
+ eachComponent { details ->
+ details.status = "milestone"
+ }
+ }
+}
+"""
+
+ expect:
+ succeeds 'resolve'
+ }
+}
diff --git a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ivy/IvyCustomStatusLatestVersionIntegrationTest.groovy b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ivy/IvyCustomStatusLatestVersionIntegrationTest.groovy
new file mode 100644
index 0000000..0a4e444
--- /dev/null
+++ b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ivy/IvyCustomStatusLatestVersionIntegrationTest.groovy
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests.resolve.ivy
+
+import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+
+class IvyCustomStatusLatestVersionIntegrationTest extends AbstractIntegrationSpec {
+ def "latest.xyz selects highest version with given or higher status"() {
+ given:
+ buildFile << """
+repositories {
+ ivy {
+ url "${ivyRepo.uri}"
+ }
+}
+configurations { compile }
+dependencies {
+ compile 'org.test:projectA:latest.$status'
+ components {
+ eachComponent { details ->
+ details.statusScheme = ["bronze", "silver", "gold", "platin"]
+ }
+ }
+}
+
+task retrieve(type: Sync) {
+ from configurations.compile
+ into 'libs'
+}
+"""
+
+ when:
+ ivyRepo.module('org.test', 'projectA', '1.1').withStatus('bronze').publish()
+ ivyRepo.module('org.test', 'projectA', '1.3').withStatus('silver').publish()
+ ivyRepo.module('org.test', 'projectA', '1.2').withStatus('gold').publish()
+ ivyRepo.module('org.test', 'projectA', '1.0').withStatus('platin').publish()
+ run 'retrieve'
+
+ then:
+ file('libs').assertHasDescendants("projectA-${version}.jar")
+
+ where:
+ status | version
+ "bronze" | "1.3"
+ "silver" | "1.3"
+ "gold" | "1.2"
+ "platin" | "1.0"
+ }
+}
diff --git a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ivy/IvyDescriptorResolveIntegrationTest.groovy b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ivy/IvyDescriptorResolveIntegrationTest.groovy
index 858d735..9d1c180 100644
--- a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ivy/IvyDescriptorResolveIntegrationTest.groovy
+++ b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ivy/IvyDescriptorResolveIntegrationTest.groovy
@@ -14,7 +14,9 @@
* limitations under the License.
*/
package org.gradle.integtests.resolve.ivy
+
import org.gradle.integtests.fixtures.AbstractDependencyResolutionTest
+import spock.lang.Unroll
class IvyDescriptorResolveIntegrationTest extends AbstractDependencyResolutionTest {
def "substitutes system properties into ivy descriptor"() {
@@ -54,22 +56,23 @@ task check << {
def "merges values from included descriptor file"() {
given:
- final parentModule = ivyRepo.module("org.gradle.parent", "parent_module", "1.1").dependsOn("org.gradle.dep", "dep_module", "1.1").publish()
- ivyRepo.module("org.gradle.dep", "dep_module", "1.1").publish()
+ server.start()
+ final parentModule = ivyHttpRepo.module("org.gradle.parent", "parent_module", "1.1").dependsOn("org.gradle.dep", "dep_module", "1.1").publish()
+ final depModule = ivyHttpRepo.module("org.gradle.dep", "dep_module", "1.1").publish()
- final module = ivyRepo.module("org.gradle", "test", "1.45")
+ final module = ivyHttpRepo.module("org.gradle", "test", "1.45")
final extendAttributes = ["organisation": "org.gradle.parent", "module": "parent_module", "revision": "1.1"]
if (includeLocation) {
- extendAttributes["location"] = parentModule.ivyFile.absolutePath
+ extendAttributes["location"] = parentModule.ivyFile.toURI().toURL()
}
module.withXml {
asNode().info[0].appendNode("extends", extendAttributes)
}
module.publish()
- and:
+ when:
buildFile << """
-repositories { ivy { url "${ivyRepo.uri}" } }
+repositories { ivy { url "${ivyHttpRepo.uri}" } }
configurations { compile }
dependencies {
compile "org.gradle:test:1.45"
@@ -80,12 +83,131 @@ task check << {
}
"""
- expect:
+ and:
+ module.expectIvyGet()
+ if (!includeLocation) {
+ parentModule.expectIvyGet()
+ }
+ depModule.expectIvyGet()
+ module.expectJarGet()
+ depModule.expectJarGet()
+
+ then:
+ executer.withArgument("--debug")
+ succeeds "check"
+
+ when:
+ server.resetExpectations()
+
+ then:
+ executer.withArgument("--debug")
succeeds "check"
where:
- name | includeLocation
- "with explicit location" | true
+ name | includeLocation
+ "with explicit location" | true
"without explicit location" | false
}
+
+ @Unroll
+ def "excludes transitive dependencies when ivy.xml has dependency declared with #name"() {
+ given:
+
+ ivyRepo.module("org.gradle.dep", "dep_module", "1.134")
+ .dependsOn("org.gradle.one", "mod_one", "1.1")
+ .dependsOn("org.gradle.two", "mod_one", "2.1")
+ .dependsOn("org.gradle.two", "mod_two", "2.2")
+ .publish()
+ ivyRepo.module("org.gradle.one", "mod_one", "1.1").artifact([:]).artifact([type: 'war']).publish()
+ ivyRepo.module("org.gradle.two", "mod_one", "2.1").publish()
+ ivyRepo.module("org.gradle.two", "mod_two", "2.2").publish()
+
+ ivyRepo.module("org.gradle.test", "test_exclude", "1.134")
+ .dependsOn("org.gradle.dep", "dep_module", "1.134")
+ .withXml({
+ asNode().dependencies[0].dependency[0].appendNode("exclude", excludeAttributes)
+ })
+ .publish()
+
+ and:
+ buildFile << """
+repositories { ivy { url "${ivyRepo.uri}" } }
+configurations { compile }
+dependencies {
+ compile "org.gradle.test:test_exclude:1.134"
+}
+
+task check(type: Sync) {
+ into "libs"
+ from configurations.compile
+}
+"""
+
+ when:
+ succeeds "check"
+
+ then:
+ def jars = ['test_exclude-1.134.jar', 'dep_module-1.134.jar'] + transitiveJars
+ file("libs").assertHasDescendants(jars.toArray(new String[0]))
+
+ where:
+ name | excludeAttributes | transitiveJars
+ "empty exclude" | [:] | []
+ "unmatched exclude" | [module: "different"] | ['mod_one-1.1.jar', 'mod_one-1.1.war', 'mod_one-2.1.jar', 'mod_two-2.2.jar']
+ "module exclude" | [module: "mod_one"] | ['mod_two-2.2.jar']
+ "org exclude" | [org: "org.gradle.two"] | ['mod_one-1.1.jar', 'mod_one-1.1.war']
+ "module and org exclude" | [org: "org.gradle.two", module: "mod_one"] | ['mod_one-1.1.jar', 'mod_one-1.1.war', 'mod_two-2.2.jar']
+ "regex module exclude" | [module: "mod.*"] | []
+ "matching config exclude" | [module: "mod_one", conf: "default,other"] | ['mod_two-2.2.jar']
+ "unmatched config exclude" | [module: "mod_one", conf: "other"] | ['mod_one-1.1.jar', 'mod_one-1.1.war', 'mod_one-2.1.jar', 'mod_two-2.2.jar']
+// GRADLE-2674
+// "type exclude" | [type: "war"] | ['mod_one-1.1.jar', 'mod_one-2.1.jar', 'mod_two-2.2.jar']
+ }
+
+ def "transitive dependencies are only excluded if excluded from each dependency declaration"() {
+// c -> d,e
+// a -> c (excludes 'd')
+// b -> c (excludes 'd', 'e')
+ given:
+ ivyRepo.module("d").publish()
+ ivyRepo.module("e").publish()
+ ivyRepo.module("c").dependsOn("d").dependsOn("e").publish()
+
+ ivyRepo.module("a")
+ .dependsOn("c")
+ .withXml({
+ asNode().dependencies[0].dependency[0].appendNode("exclude", [module: "d"])
+ })
+ .publish()
+ ivyRepo.module("b")
+ .dependsOn("c")
+ .withXml({
+ def dep = asNode().dependencies[0].dependency[0]
+ dep.appendNode("exclude", [module: "d"])
+ dep.appendNode("exclude", [module: "e"])
+ })
+ .publish()
+
+ and:
+ buildFile << """
+repositories { ivy { url "${ivyRepo.uri}" } }
+configurations {
+ merged
+}
+dependencies {
+ merged "org.gradle.test:a:1.0", "org.gradle.test:b:1.0"
+}
+
+task syncMerged(type: Sync) {
+ from configurations.merged
+ into "libs"
+}
+"""
+
+ when:
+ succeeds "syncMerged"
+
+ then:
+ file("libs").assertHasDescendants(['a-1.0.jar', 'b-1.0.jar', 'c-1.0.jar', 'e-1.0.jar'] as String[])
+ }
}
diff --git a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ivy/IvyDynamicRevisionRemoteResolveIntegrationTest.groovy b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ivy/IvyDynamicRevisionRemoteResolveIntegrationTest.groovy
index a4af2af..164b304 100644
--- a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ivy/IvyDynamicRevisionRemoteResolveIntegrationTest.groovy
+++ b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ivy/IvyDynamicRevisionRemoteResolveIntegrationTest.groovy
@@ -253,6 +253,49 @@ task retrieveMilestone(type: Sync) {
file('milestone').assertHasDescendants('projectA-1.1.jar')
}
+ def "can get latest version from repository with multiple ivyPatterns"() {
+ server.start()
+
+ given:
+ def repo1 = ivyHttpRepo("ivyRepo1")
+ repo1.module('org.test', 'projectA', '1.1').withStatus("integration").publish()
+ def repo1version2 = repo1.module('org.test', 'projectA', '1.2').withStatus("milestone").publish()
+ def repo2 = ivyHttpRepo("ivyRepo2")
+ def repo2version1 = repo2.module('org.test', 'projectA', '1.1').withStatus("milestone").publish()
+ def repo2version3 = repo2.module('org.test', 'projectA', '1.3').withStatus("integration").publish()
+
+ and:
+ buildFile << """
+repositories {
+ ivy {
+ url "${repo1.uri}"
+ ivyPattern "${repo2.uri}/[organisation]/[module]/[revision]/ivy-[revision].xml"
+ artifactPattern "${repo2.uri}/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]"
+ }
+}
+configurations { milestone }
+dependencies {
+ milestone 'org.test:projectA:latest.milestone'
+}
+task retrieveMilestone(type: Sync) {
+ from configurations.milestone
+ into 'milestone'
+}
+"""
+ when:
+ repo1.expectDirectoryListGet("org.test", "projectA")
+ repo2.expectDirectoryListGet("org.test", "projectA")
+ repo2version3.expectIvyGet()
+ repo1version2.expectIvyGet()
+ repo1version2.expectJarGet()
+
+ then:
+ succeeds 'retrieveMilestone'
+
+ and:
+ file('milestone').assertHasDescendants('projectA-1.2.jar')
+ }
+
def "checks new repositories before returning any cached value"() {
server.start()
def repo1 = ivyHttpRepo("repo1")
diff --git a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ivy/IvyDynamicRevisionResolveIntegrationTest.groovy b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ivy/IvyDynamicRevisionResolveIntegrationTest.groovy
index b3d4176..ed5974f 100644
--- a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ivy/IvyDynamicRevisionResolveIntegrationTest.groovy
+++ b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ivy/IvyDynamicRevisionResolveIntegrationTest.groovy
@@ -20,7 +20,6 @@ import spock.lang.Ignore
import spock.lang.Issue
class IvyDynamicRevisionResolveIntegrationTest extends AbstractDependencyResolutionTest {
- @Ignore
@Issue("GRADLE-2502")
def "latest.integration selects highest version regardless of status"() {
given:
@@ -44,7 +43,7 @@ class IvyDynamicRevisionResolveIntegrationTest extends AbstractDependencyResolut
runAndFail 'retrieve'
then:
- failureHasCause 'Could not find any version that matches group:group, module:projectA, version:latest.integration.'
+ failureHasCause 'Could not find any version that matches org.test:projectA:latest.integration.'
when:
ivyRepo.module('org.test', 'projectA', '1.0').withNoMetaData().publish()
@@ -67,8 +66,30 @@ class IvyDynamicRevisionResolveIntegrationTest extends AbstractDependencyResolut
then:
file('libs').assertHasDescendants('projectA-1.3.jar')
+ }
+
+ @Ignore
+ @Issue("GRADLE-2502")
+ def "latest.integration selects highest version regardless of status even if metadata is missing"() {
+ given:
+ buildFile << """
+ repositories {
+ ivy {
+ url "${ivyRepo.uri}"
+ }
+ }
+ configurations { compile }
+ dependencies {
+ compile 'org.test:projectA:latest.integration'
+ }
+ task retrieve(type: Sync) {
+ from configurations.compile
+ into 'libs'
+ }
+ """
when:
+ ivyRepo.module('org.test', 'projectA', '1.1').withStatus('integration').publish()
ivyRepo.module('org.test', 'projectA', '1.4').withNoMetaData().publish()
run 'retrieve'
@@ -179,7 +200,6 @@ class IvyDynamicRevisionResolveIntegrationTest extends AbstractDependencyResolut
file('libs').assertHasDescendants('projectA-1.1.jar')
}
- @Ignore
@Issue("GRADLE-2502")
def "version selector ending in + selects highest matching version"() {
given:
@@ -228,6 +248,30 @@ class IvyDynamicRevisionResolveIntegrationTest extends AbstractDependencyResolut
then:
file('libs').assertHasDescendants('projectA-1.2.9.jar')
+ }
+
+ @Ignore
+ @Issue("GRADLE-2502")
+ def "version selector ending in + selects highest matching version even if metadata is missing"() {
+ given:
+ buildFile << """
+ repositories {
+ ivy {
+ url "${ivyRepo.uri}"
+ }
+ }
+ configurations { compile }
+ dependencies {
+ compile 'org.test:projectA:1.2+'
+ }
+ task retrieve(type: Sync) {
+ from configurations.compile
+ into 'libs'
+ }
+ """
+ and:
+ ivyRepo.module('org.test', 'projectA', '1.2.1').publish()
+ ivyRepo.module('org.test', 'projectA', '2.0').publish()
when:
ivyRepo.module('org.test', 'projectA', '1.2.12').withNoMetaData().publish()
@@ -237,7 +281,6 @@ class IvyDynamicRevisionResolveIntegrationTest extends AbstractDependencyResolut
file('libs').assertHasDescendants('projectA-1.2.12.jar')
}
- @Ignore
@Issue("GRADLE-2502")
def "version range selects highest matching version"() {
given:
@@ -258,7 +301,7 @@ class IvyDynamicRevisionResolveIntegrationTest extends AbstractDependencyResolut
"""
and:
ivyRepo.module('org.test', 'projectA', '1.1.2').publish()
- ivyRepo.module('org.test', 'projectA', '2.0').publish()
+ ivyRepo.module('org.test', 'projectA', '2.1').publish()
when:
runAndFail 'retrieve'
@@ -286,6 +329,29 @@ class IvyDynamicRevisionResolveIntegrationTest extends AbstractDependencyResolut
then:
file('libs').assertHasDescendants('projectA-1.3.jar')
+ }
+
+ @Ignore
+ @Issue("GRADLE-2502")
+ def "version range selects highest matching version even if metadata is missing"() {
+ given:
+ buildFile << """
+ repositories {
+ ivy {
+ url "${ivyRepo.uri}"
+ }
+ }
+ configurations { compile }
+ dependencies {
+ compile 'org.test:projectA:[1.2,2.0]'
+ }
+ task retrieve(type: Sync) {
+ from configurations.compile
+ into 'libs'
+ }
+ """
+ and:
+ ivyRepo.module('org.test', 'projectA', '1.2.1').publish()
when:
ivyRepo.module('org.test', 'projectA', '1.3.12').withNoMetaData().publish()
@@ -330,4 +396,53 @@ class IvyDynamicRevisionResolveIntegrationTest extends AbstractDependencyResolut
then:
file('libs').assertHasDescendants('projectA-1.1.jar')
}
+
+ def "can resolve dynamic versions with multiple ivy patterns"() {
+ given:
+ def repo1 = ivyRepo("ivyRepo1")
+ repo1.module('org.test', 'projectA', '1.1').withStatus("integration").publish()
+ repo1.module('org.test', 'projectA', '1.2').withStatus("milestone").publish()
+ def repo2 = ivyRepo("ivyRepo2")
+ repo2.module('org.test', 'projectA', '1.1').withStatus("milestone").publish()
+ repo2.module('org.test', 'projectA', '1.3').withStatus("integration").publish()
+
+ and:
+ buildFile << """
+repositories {
+ ivy {
+ url "${repo1.uri}"
+ ivyPattern "${repo2.uri}/[organisation]/[module]/[revision]/ivy-[revision].xml"
+ artifactPattern "${repo2.uri}/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]"
+ }
+}
+configurations {
+ milestone
+ dynamic
+}
+dependencies {
+ milestone 'org.test:projectA:latest.milestone'
+ dynamic 'org.test:projectA:1.+'
+}
+task retrieveDynamic(type: Sync) {
+ from configurations.dynamic
+ into 'dynamic'
+}
+task retrieveMilestone(type: Sync) {
+ from configurations.milestone
+ into 'milestone'
+}
+"""
+
+ when:
+ run 'retrieveDynamic'
+
+ then:
+ file('dynamic').assertHasDescendants('projectA-1.3.jar')
+
+ when:
+ run 'retrieveMilestone'
+
+ then:
+ file('milestone').assertHasDescendants('projectA-1.2.jar')
+ }
}
diff --git a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ivy/IvyMetadataConsistencyIntegrationTest.groovy b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ivy/IvyMetadataConsistencyIntegrationTest.groovy
new file mode 100644
index 0000000..f67d7c3
--- /dev/null
+++ b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ivy/IvyMetadataConsistencyIntegrationTest.groovy
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests.resolve.ivy
+
+import org.gradle.integtests.fixtures.AbstractDependencyResolutionTest
+
+import static org.hamcrest.CoreMatchers.containsString
+
+class IvyMetadataConsistencyIntegrationTest extends AbstractDependencyResolutionTest {
+ def "latest.integration selects highest version regardless of status"() {
+ given:
+ buildFile << """
+ repositories {
+ ivy {
+ url "${ivyRepo.uri}"
+ }
+ }
+ configurations { compile }
+ dependencies {
+ compile 'org.test:projectA:[1.3,1.5]'
+ }
+ task resolve << {
+ configurations.compile.resolve()
+ }
+ """
+
+ def module = ivyRepo.module('org.test', 'projectA', '1.4')
+ module.publish()
+
+ expect:
+ succeeds 'resolve'
+
+ when:
+ module.ivyFile.setText(module.ivyFile.text.replace('revision="1.4"', 'revision="1.6"'), "utf-8")
+
+ then:
+ fails 'resolve'
+ failure.assertThatCause(containsString("bad version: expected='1.4' found='1.6'"))
+ }
+
+}
\ No newline at end of file
diff --git a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ivy/IvyModuleResolveIntegrationTest.groovy b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ivy/IvyModuleResolveIntegrationTest.groovy
new file mode 100644
index 0000000..ee15e89
--- /dev/null
+++ b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ivy/IvyModuleResolveIntegrationTest.groovy
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests.resolve.ivy
+
+import org.gradle.integtests.fixtures.AbstractDependencyResolutionTest
+import spock.lang.Unroll
+
+class IvyModuleResolveIntegrationTest extends AbstractDependencyResolutionTest {
+ def "wildcard on LHS of configuration mapping includes all public configurations of target module"() {
+ given:
+ buildFile << """
+configurations {
+ compile
+}
+dependencies {
+ repositories {
+ ivy { url "${ivyRepo.uri}" }
+ }
+ compile 'ivy.configuration:projectA:1.2'
+}
+task retrieve(type: Sync) {
+ from configurations.compile
+ into 'libs'
+}
+"""
+ when: "projectA uses a wildcard configuration mapping for dependency on projectB"
+ def moduleA = ivyRepo.module('ivy.configuration', 'projectA', '1.2')
+ .configuration('parent')
+ .artifact()
+ .dependsOn(organisation: 'ivy.configuration', module: 'projectB', revision: '1.5', conf: 'runtime->*')
+ .publish()
+
+ ivyRepo.module('ivy.configuration', 'projectB', '1.5')
+ .configuration('child')
+ .configuration('private', visibility: 'private')
+ .artifact()
+ .artifact([name: 'projectB', conf: 'runtime'])
+ .artifact([name: 'projectB-child', conf: 'child'])
+ .artifact([name: 'projectB-private', conf: 'private'])
+ .dependsOn(organisation: 'ivy.configuration', module: 'projectC', revision: '1.7', conf: 'child->*')
+ .dependsOn(organisation: 'ivy.configuration', module: 'projectD', revision: 'broken', conf: 'private->*')
+ .publish()
+
+ ivyRepo.module('ivy.configuration', 'projectC', '1.7')
+ .artifact()
+ .publish()
+
+ and:
+ succeeds 'retrieve'
+
+ then: "artifacts and dependencies from all configurations of projectB are included"
+ file('libs').assertHasDescendants('projectA-1.2.jar', 'projectB-1.5.jar', 'projectB-child-1.5.jar', 'projectC-1.7.jar')
+
+ when: "projectB-1.5 is replaced by conflict resolution with projectB-1.6 that has a different set of configurations"
+
+ ivyRepo.module('ivy.configuration', 'projectB', '1.6')
+ .configuration('other')
+ .artifact([name: 'projectB-other', conf: 'other'])
+ .publish()
+
+ ivyRepo.module('ivy.configuration', 'projectD', '1.0')
+ .dependsOn('ivy.configuration', 'projectB', '1.6')
+ .publish()
+
+ moduleA.dependsOn('ivy.configuration', 'projectD', '1.0').publish()
+
+ and:
+ succeeds 'retrieve'
+
+ then: "we resolve artifacts from projectB-1.6 only"
+ file('libs').assertHasDescendants('projectA-1.2.jar', 'projectB-other-1.6.jar', 'projectD-1.0.jar')
+ }
+
+ @Unroll
+ def "correctly handles configuration mapping rule '#rule'"() {
+ given:
+ buildFile << """
+configurations {
+ compile
+}
+dependencies {
+ repositories {
+ ivy { url "${ivyRepo.uri}" }
+ }
+ compile group: 'ivy.configuration', name: 'projectA', version: '1.2', configuration: 'a'
+}
+task retrieve(type: Sync) {
+ from configurations.compile
+ into 'libs'
+}
+"""
+ ivyRepo.module('ivy.configuration', 'projectA', '1.2')
+ .configuration("parent")
+ .configuration("a", extendsFrom: ["parent"])
+ .configuration("b")
+ .dependsOn(organisation: 'ivy.configuration', module: 'projectB', revision: '1.5', conf: rule)
+ .publish()
+
+ ivyRepo.module('ivy.configuration', 'projectB', '1.5')
+ .configuration('a')
+ .configuration('b')
+ .configuration('c')
+ .configuration('d', visibility: 'private')
+ .artifact([name: 'projectB-a', conf: 'a'])
+ .artifact([name: 'projectB-b', conf: 'b'])
+ .artifact([name: 'projectB-c', conf: 'c'])
+ .artifact([name: 'projectB-d', conf: 'd'])
+ .dependsOn(organisation: 'ivy.configuration', module: 'projectC', revision: '1.7', conf: 'a->default')
+ .dependsOn(organisation: 'ivy.configuration', module: 'projectD', revision: '1.7', conf: 'b->default')
+ .dependsOn(organisation: 'ivy.configuration', module: 'projectE', revision: '1.7', conf: 'd->default')
+ .publish()
+
+ ivyRepo.module('ivy.configuration', 'projectC', '1.7').publish()
+ ivyRepo.module('ivy.configuration', 'projectD', '1.7').publish()
+
+ when:
+ run 'retrieve'
+
+ then:
+ file('libs').assertHasDescendants(* (['projectA-1.2.jar'] + jars))
+
+ where:
+ rule | jars
+ "a" | ["projectB-a-1.5.jar", "projectC-1.7.jar"]
+ "a->b" | ["projectB-b-1.5.jar", "projectD-1.7.jar"]
+ "a,b->b" | ["projectB-b-1.5.jar", "projectD-1.7.jar"]
+ "parent->a" | ["projectB-a-1.5.jar", "projectC-1.7.jar"]
+ "a,parent->a" | ["projectB-a-1.5.jar", "projectC-1.7.jar"]
+ "a->a,b" | ["projectB-a-1.5.jar", "projectB-b-1.5.jar", "projectC-1.7.jar", "projectD-1.7.jar"]
+ "a;a->b" | ["projectB-a-1.5.jar", "projectB-b-1.5.jar", "projectC-1.7.jar", "projectD-1.7.jar"]
+ "*->a" | ["projectB-a-1.5.jar", "projectC-1.7.jar"]
+ "*->*" | ["projectB-a-1.5.jar", "projectB-b-1.5.jar", "projectB-c-1.5.jar", "projectC-1.7.jar", "projectD-1.7.jar"]
+ "*->@" | ["projectB-a-1.5.jar", "projectC-1.7.jar"]
+ "a,b->@" | ["projectB-a-1.5.jar", "projectC-1.7.jar"]
+ "runtime->unknown;%->@" | ["projectB-a-1.5.jar", "projectC-1.7.jar"]
+ "a->a;%->b" | ["projectB-a-1.5.jar", "projectC-1.7.jar"]
+ "*,!b->b" | ["projectB-b-1.5.jar", "projectD-1.7.jar"]
+ "b" | []
+ "*,!a->a" | []
+ "a->#" | ["projectB-a-1.5.jar", "projectC-1.7.jar"]
+ "parent->#" | ["projectB-a-1.5.jar", "projectC-1.7.jar"]
+ "*->#" | ["projectB-a-1.5.jar", "projectC-1.7.jar"]
+ "*->unknown(a)" | ["projectB-a-1.5.jar", "projectC-1.7.jar"]
+ "a->unknown(*)" | ["projectB-a-1.5.jar", "projectB-b-1.5.jar", "projectB-c-1.5.jar", "projectC-1.7.jar", "projectD-1.7.jar"]
+ "a->a(*),b(*);b->b(*)" | ["projectB-a-1.5.jar", "projectB-b-1.5.jar", "projectC-1.7.jar", "projectD-1.7.jar"]
+ }
+
+ def "prefers revConstraint over rev when dynamic resolve mode is used"() {
+ given:
+ buildFile << """
+configurations {
+ compile
+}
+dependencies {
+ repositories {
+ ivy {
+ url "${ivyRepo.uri}"
+ resolve.dynamicMode = project.hasProperty('useDynamicResolve')
+ }
+ }
+ compile 'org:projectA:1.2'
+}
+task retrieve(type: Sync) {
+ from configurations.compile
+ into 'libs'
+}
+"""
+ ivyRepo.module('org', 'projectA', '1.2')
+ .dependsOn(organisation: 'org', module: 'projectB', revision: '1.5', revConstraint: '1.6')
+ .dependsOn(organisation: 'org', module: 'projectC', revision: 'alpha-12')
+ .publish()
+
+ ivyRepo.module('org', 'projectB', '1.5')
+ .publish()
+
+ ivyRepo.module('org', 'projectB', '1.6')
+ .publish()
+
+ ivyRepo.module('org', 'projectC', 'alpha-12')
+ .publish()
+
+ when:
+ executer.withArguments("-PuseDynamicResolve=true")
+ run 'retrieve'
+
+ then:
+ file('libs').assertHasDescendants('projectA-1.2.jar', 'projectB-1.6.jar', 'projectC-alpha-12.jar')
+
+ when:
+ run 'retrieve'
+
+ then:
+ file('libs').assertHasDescendants('projectA-1.2.jar', 'projectB-1.5.jar', 'projectC-alpha-12.jar')
+ }
+}
diff --git a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ivy/IvyResolveIntegrationTest.groovy b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ivy/IvyResolveIntegrationTest.groovy
index 5197a3b..a8e52f7 100644
--- a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ivy/IvyResolveIntegrationTest.groovy
+++ b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/ivy/IvyResolveIntegrationTest.groovy
@@ -22,6 +22,7 @@ class IvyResolveIntegrationTest extends AbstractDependencyResolutionTest {
given:
ivyRepo.module("org.gradle", "test", "1.45")
.dependsOn("org.gradle", "other", "preview-1")
+ .artifact()
.artifact(classifier: "classifier")
.artifact(name: "test-extra")
.publish()
@@ -137,111 +138,4 @@ task check << {
expect:
succeeds "check"
}
-
- def "correctly handles wildcard configuration mapping in transitive dependencies"() {
- given:
- buildFile << """
-configurations {
- compile
-}
-dependencies {
- repositories {
- ivy { url "${ivyRepo.uri}" }
- }
- compile 'ivy.configuration:projectA:1.2'
-}
-task retrieve(type: Sync) {
- from configurations.compile
- into 'libs'
-}
-"""
- when: "projectA uses a wildcard configuration mapping for dependency on projectB"
- def moduleA = ivyRepo.module('ivy.configuration', 'projectA', '1.2')
- .configuration('parent')
- .artifact([:])
- .dependsOn(organisation: 'ivy.configuration', module: 'projectB', revision: '1.5', conf: 'runtime->*')
- .publish()
-
- ivyRepo.module('ivy.configuration', 'projectB', '1.5')
- .configuration('child')
- .artifact([name: 'projectB', conf: 'runtime'])
- .artifact([name: 'projectB-child', conf: 'child'])
- .dependsOn(organisation: 'ivy.configuration', module: 'projectC', revision: '1.7', conf: 'child->*')
- .publish()
-
- ivyRepo.module('ivy.configuration', 'projectC', '1.7').artifact([:]).publish()
-
- and:
- succeeds 'retrieve'
-
- then: "artifacts and dependencies from all configurations of projectB are included"
- file('libs').assertHasDescendants('projectA-1.2.jar', 'projectB-1.5.jar', 'projectB-child-1.5.jar', 'projectC-1.7.jar')
-
- when: "projectB-1.5 is replaced by conflict resolution with projectB-1.6 that has a different set of configurations"
-
- ivyRepo.module('ivy.configuration', 'projectB', '1.6')
- .configuration('other')
- .artifact([name: 'projectB-other', conf: 'other'])
- .publish()
-
- ivyRepo.module('ivy.configuration', 'projectD', '1.0')
- .dependsOn('ivy.configuration', 'projectB', '1.6')
- .publish()
-
- moduleA.dependsOn('ivy.configuration', 'projectD', '1.0').publish()
-
- and:
- succeeds 'retrieve'
-
- then: "we resolve artifacts from projectB-1.6 only"
- file('libs').assertHasDescendants('projectA-1.2.jar', 'projectB-1.6.jar', 'projectB-other-1.6.jar', 'projectD-1.0.jar')
- }
-
- def "prefers revConstraint over rev when dynamic resolve mode is used"() {
- given:
- buildFile << """
-configurations {
- compile
-}
-dependencies {
- repositories {
- ivy {
- url "${ivyRepo.uri}"
- resolve.dynamicMode = project.hasProperty('useDynamicResolve')
- }
- }
- compile 'org:projectA:1.2'
-}
-task retrieve(type: Sync) {
- from configurations.compile
- into 'libs'
-}
-"""
- ivyRepo.module('org', 'projectA', '1.2')
- .dependsOn(organisation: 'org', module: 'projectB', revision: '1.5', revConstraint: '1.6')
- .dependsOn(organisation: 'org', module: 'projectC', revision: 'alpha-12')
- .publish()
-
- ivyRepo.module('org', 'projectB', '1.5')
- .publish()
-
- ivyRepo.module('org', 'projectB', '1.6')
- .publish()
-
- ivyRepo.module('org', 'projectC', 'alpha-12')
- .publish()
-
- when:
- executer.withArguments("-PuseDynamicResolve=true")
- run 'retrieve'
-
- then:
- file('libs').assertHasDescendants('projectA-1.2.jar', 'projectB-1.6.jar', 'projectC-alpha-12.jar')
-
- when:
- run 'retrieve'
-
- then:
- file('libs').assertHasDescendants('projectA-1.2.jar', 'projectB-1.5.jar', 'projectC-alpha-12.jar')
- }
}
diff --git a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/maven/BadPomFileResolveIntegrationTest.groovy b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/maven/BadPomFileResolveIntegrationTest.groovy
index c871a5d..bf98795 100644
--- a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/maven/BadPomFileResolveIntegrationTest.groovy
+++ b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/maven/BadPomFileResolveIntegrationTest.groovy
@@ -16,16 +16,13 @@
package org.gradle.integtests.resolve.maven
import org.gradle.integtests.fixtures.AbstractDependencyResolutionTest
+import spock.lang.Ignore
import spock.lang.Issue
class BadPomFileResolveIntegrationTest extends AbstractDependencyResolutionTest {
-
@Issue("http://issues.gradle.org/browse/GRADLE-1005")
def "can handle self referencing dependency"() {
given:
- file("settings.gradle") << "include 'client'"
-
- and:
mavenRepo().module('group', 'artifact', '1.0').dependsOn('group', 'artifact', '1.0').publish()
and:
@@ -43,4 +40,49 @@ class BadPomFileResolveIntegrationTest extends AbstractDependencyResolutionTest
expect:
succeeds ":libs"
}
+
+ @Issue("http://issues.gradle.org/browse/GRADLE-2861")
+ @Ignore
+ def "can handle pom with placeholders in dependency management"() {
+ given:
+ server.start()
+
+ def parent = mavenHttpRepo.module('group', 'parent', '1.0').publish()
+ parent.pomFile.text = parent.pomFile.text.replace("</project>", """
+<dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>\${some.group}</groupId>
+ <artifactId>\${some.artifact}</artifactId>
+ <version>\${some.version}</version>
+ </dependency>
+ </dependencies>
+</dependencyManagement>
+</project>
+""")
+
+ def module = mavenHttpRepo.module('group', 'artifact', '1.0').parent('group', 'parent', '1.0').publish()
+
+ and:
+ buildFile << """
+ repositories {
+ maven { url "${mavenHttpRepo.uri}" }
+ }
+ configurations { compile }
+ dependencies {
+ compile "group:artifact:1.0"
+ }
+ task libs << { assert configurations.compile.files.collect {it.name} == ['artifact-1.0.jar'] }
+ """
+
+ and:
+ parent.pom.expectGet()
+ module.pom.expectGet()
+ module.artifact.expectGet()
+
+ expect:
+ // have to run twice to trigger the failure, to parse the descriptor from the cache
+ succeeds ":libs"
+ succeeds ":libs"
+ }
}
\ No newline at end of file
diff --git a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/maven/LegacyMavenRepoResolveIntegrationTest.groovy b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/maven/LegacyMavenRepoResolveIntegrationTest.groovy
index 9d9470d..00ffd20 100644
--- a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/maven/LegacyMavenRepoResolveIntegrationTest.groovy
+++ b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/maven/LegacyMavenRepoResolveIntegrationTest.groovy
@@ -49,6 +49,7 @@ task check << {
module.artifact.expectGet()
module.artifact.sha1.expectGetMissing()
module.artifact.md5.expectGet()
+ executer.withDeprecationChecksDisabled()
expect:
succeeds 'check'
@@ -68,6 +69,7 @@ task check << {
module.artifact.expectGet()
// TODO - shouldn't get checksum twice
module.artifact.sha1.expectGet()
+ executer.withDeprecationChecksDisabled()
then:
executer.withArguments("--refresh-dependencies")
@@ -102,12 +104,17 @@ task check << {
module.pom.sha1.expectGet()
module.artifact.expectGet()
module.artifact.sha1.expectGet()
+
and:
module.artifact.sha1.file.text = '1234'
+
+ and:
+ executer.withDeprecationChecksDisabled()
+
expect:
fails 'check'
failureHasCause("Could not download artifact 'group:module:1.2 at jar'")
- failureHasCause("invalid sha1: expected=1234 computed=5b253435f362abf1a12197966e332df7d2b153f5")
+ failureHasCause("invalid sha1: expected=1234 computed=2ee22701c9bd9af023ed20917897da5ce77336bc")
}
def "can configure resolver to fail when descriptor is not present"() {
@@ -137,6 +144,9 @@ task check << {
and:
module.pom.expectGetMissing()
+ and:
+ executer.withDeprecationChecksDisabled()
+
expect:
fails 'check'
failureHasCause("Could not find group:module:1.2.")
@@ -171,6 +181,9 @@ task check << {
module.artifact.expectHead()
module.artifact.expectGet()
+ and:
+ executer.withDeprecationChecksDisabled()
+
expect:
succeeds "check"
}
@@ -203,8 +216,10 @@ task check << {
module.pom.expectGet()
module.artifact.expectGet()
- expect:
+ and:
executer.withDeprecationChecksDisabled()
+
+ expect:
succeeds "check"
}
}
diff --git a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenBrokenRemoteResolveIntegrationTest.groovy b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenBrokenRemoteResolveIntegrationTest.groovy
new file mode 100644
index 0000000..ba47d3f
--- /dev/null
+++ b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenBrokenRemoteResolveIntegrationTest.groovy
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests.resolve.maven
+
+import org.gradle.integtests.fixtures.AbstractDependencyResolutionTest
+
+class MavenBrokenRemoteResolveIntegrationTest extends AbstractDependencyResolutionTest {
+ public void "reports POM that cannot be parsed"() {
+ server.start()
+ given:
+ buildFile << """
+repositories {
+ maven {
+ url "${mavenHttpRepo.uri}"
+ }
+}
+configurations { compile }
+dependencies {
+ compile 'group:projectA:1.2'
+}
+task showBroken << { println configurations.compile.files }
+"""
+
+ and:
+ def module = mavenHttpRepo.module('group', 'projectA', '1.2').publish()
+ module.pomFile.text = "<project>"
+
+ when:
+ module.pom.expectGet()
+
+ then:
+ fails "showBroken"
+ failure.assertResolutionFailure(":compile")
+ .assertHasCause("Could not parse POM ${module.pom.uri}")
+ }
+}
diff --git a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenComponentMetadataRulesIntegrationTest.groovy b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenComponentMetadataRulesIntegrationTest.groovy
new file mode 100644
index 0000000..d1047c4
--- /dev/null
+++ b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenComponentMetadataRulesIntegrationTest.groovy
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests.resolve.maven
+
+import org.gradle.integtests.fixtures.AbstractDependencyResolutionTest
+
+class MavenComponentMetadataRulesIntegrationTest extends AbstractDependencyResolutionTest {
+ def "rules are provided with correct metadata"() {
+ given:
+ mavenRepo().module('group1', 'projectA', '1.0').publish()
+ mavenRepo().module('group2', 'projectB', '2.0-SNAPSHOT').publish()
+
+ and:
+ buildFile << """
+configurations { compile }
+repositories { maven { url "${mavenRepo().uri}" } }
+def allDetails = []
+dependencies {
+ compile 'group1:projectA:1.0'
+ compile 'group2:projectB:2.0-SNAPSHOT'
+ components {
+ eachComponent { allDetails << it }
+ }
+}
+
+task verify {
+ configurations.compile.resolve()
+
+ def projectA = allDetails.find { it.id.name == 'projectA' }
+ assert projectA != null
+ assert projectA.id.group == 'group1'
+ assert projectA.id.version == '1.0'
+ assert projectA.status == 'release'
+ assert projectA.statusScheme == ['integration', 'milestone', 'release']
+
+ def projectB = allDetails.find { it.id.name == 'projectB' }
+ assert projectB != null
+ assert projectB.id.group == 'group2'
+ assert projectB.id.version == '2.0-SNAPSHOT'
+ assert projectB.status == 'integration'
+ assert projectB.statusScheme == ['integration', 'milestone', 'release']
+}
+"""
+
+ expect:
+ succeeds 'verify'
+ }
+}
diff --git a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenDependencyResolveIntegrationTest.groovy b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenDependencyResolveIntegrationTest.groovy
index 0cc4101..ba8e950 100644
--- a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenDependencyResolveIntegrationTest.groovy
+++ b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenDependencyResolveIntegrationTest.groovy
@@ -16,6 +16,8 @@
package org.gradle.integtests.resolve.maven
import org.gradle.integtests.fixtures.AbstractDependencyResolutionTest
+import org.gradle.util.Requires
+import org.gradle.util.TestPrecondition
class MavenDependencyResolveIntegrationTest extends AbstractDependencyResolutionTest {
def "dependency includes main artifact and runtime dependencies of referenced module"() {
@@ -100,6 +102,7 @@ task check << {
succeeds "check"
}
+ @Requires(TestPrecondition.ONLINE)
def "resolves dependencies on real projects"() {
// Hibernate core brings in conflicts, exclusions and parent poms
// Add a direct dependency on an earlier version of commons-collection than required by hibernate core
diff --git a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenJcenterDependencyResolveIntegrationTest.groovy b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenJcenterDependencyResolveIntegrationTest.groovy
new file mode 100644
index 0000000..ed554ca
--- /dev/null
+++ b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenJcenterDependencyResolveIntegrationTest.groovy
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests.resolve.maven
+
+import org.gradle.integtests.fixtures.AbstractDependencyResolutionTest
+import org.gradle.util.Requires
+import org.gradle.util.TestPrecondition
+
+ at Requires(TestPrecondition.ONLINE)
+class MavenJcenterDependencyResolveIntegrationTest extends AbstractDependencyResolutionTest {
+ def "resolves a minimal dependency from bintray's jcenter"() {
+ given:
+ buildFile << """
+repositories {
+ jcenter()
+ jcenter { // just test this syntax works.
+ name = "otherJcenter"
+ }
+}
+
+configurations {
+ compile
+}
+
+dependencies {
+ compile "ch.qos.logback:logback-classic:1.0.13"
+}
+
+task check << {
+ def compile = configurations.compile
+ assert compile.resolvedConfiguration.firstLevelModuleDependencies.collect { it.name } == [
+ 'ch.qos.logback:logback-classic:1.0.13',
+ ]
+
+ assert compile.collect { it.name } == [
+ 'logback-classic-1.0.13.jar',
+ 'logback-core-1.0.13.jar',
+ 'slf4j-api-1.7.5.jar'
+ ]
+
+ assert compile.resolvedConfiguration.resolvedArtifacts.collect { it.file.name } == [
+ 'logback-classic-1.0.13.jar',
+ 'logback-core-1.0.13.jar',
+ 'slf4j-api-1.7.5.jar'
+ ]
+}
+
+task repoNames << {
+ println repositories*.name
+}
+"""
+
+ expect:
+ succeeds "check", "repoNames"
+
+ and:
+ output.contains(["BintrayJCenter", "otherJcenter"].toString())
+ }
+}
\ No newline at end of file
diff --git a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenLatestResolveIntegrationTest.groovy b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenLatestResolveIntegrationTest.groovy
new file mode 100644
index 0000000..61e3017
--- /dev/null
+++ b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenLatestResolveIntegrationTest.groovy
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests.resolve.maven
+
+import org.gradle.integtests.fixtures.AbstractDependencyResolutionTest
+
+class MavenLatestResolveIntegrationTest extends AbstractDependencyResolutionTest {
+ def "latest selector works correctly when (only) release versions are present"() {
+ given:
+ mavenRepo().module('group', 'projectA', '1.0').publish()
+ def highest = mavenRepo().module('group', 'projectA', '2.2').publish()
+ mavenRepo().module('group', 'projectA', '1.4').publish()
+
+ and:
+ buildFile << """
+configurations { compile }
+repositories { maven { url "${mavenRepo().uri}" } }
+dependencies { compile 'group:projectA:latest.$status' }
+task retrieve(type: Sync) {
+ from configurations.compile
+ into 'build'
+}
+"""
+
+ when:
+ run 'retrieve'
+
+ then:
+ def buildDir = file('build')
+ buildDir.assertHasDescendants(highest.artifactFile.name)
+
+ where:
+ status << ["integration", "milestone", "release"]
+ }
+
+ def "latest selector with unknown status leads to failure"() {
+ mavenRepo().module('group', 'projectA', '1.0').publish()
+
+ buildFile << """
+configurations { compile }
+repositories { maven { url "${mavenRepo().uri}" } }
+dependencies { compile 'group:projectA:latest.foo' }
+task retrieve(type: Sync) {
+ from configurations.compile
+ into 'build'
+}
+"""
+
+ expect:
+ fails 'retrieve'
+ // would be better if metadata validation failed (status not contained in status scheme)
+ failure.assertHasCause("Could not find any version that matches group:projectA:latest.foo.")
+ }
+
+ // describes the actual (not the desired) behavior
+ def "latest selector doesn't work correctly if highest version is snapshot"() {
+ given:
+ def moduleA = mavenRepo().module('group', 'projectA', '1.0').publish()
+ def moduleAA = mavenRepo().module('group', 'projectA', '1.2-SNAPSHOT').publish()
+
+ and:
+ buildFile << """
+configurations { compile }
+repositories { maven { url "${mavenRepo().uri}" } }
+dependencies { compile 'group:projectA:latest.release' }
+task retrieve(type: Sync) {
+ from configurations.compile
+ into 'build'
+}
+"""
+
+ when:
+ runAndFail("retrieve")
+
+ then:
+ failure.assertHasCause("Could not find any version that matches group:projectA:latest.release")
+ }
+}
diff --git a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenParentPomResolveIntegrationTest.groovy b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenParentPomResolveIntegrationTest.groovy
index 4e6841c..daeb983 100644
--- a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenParentPomResolveIntegrationTest.groovy
+++ b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenParentPomResolveIntegrationTest.groovy
@@ -69,6 +69,16 @@ task retrieve(type: Sync) {
then:
file('libs').assertHasDescendants('child-1.0.jar', 'parent_dep-1.2.jar', 'child_dep-1.7.jar')
+
+ when:
+ server.resetExpectations()
+ file('libs').deleteDir()
+
+ and:
+ run 'retrieve'
+
+ then:
+ file('libs').assertHasDescendants('child-1.0.jar', 'parent_dep-1.2.jar', 'child_dep-1.7.jar')
}
@Issue("GRADLE-2641")
@@ -160,4 +170,79 @@ task retrieve(type: Sync) {
then:
file('libs').assertHasDescendants('child-1.0.jar')
}
+
+ def "uses cached parent pom located in a different repository"() {
+ given:
+ server.start()
+
+ def repo1 = mavenHttpRepo("repo1")
+ def repo2 = mavenHttpRepo("repo2")
+
+ // Parent not found in repo1
+ def missingParent = repo1.module("org", "parent")
+ def parent = repo2.module("org", "parent", "1.0")
+ parent.dependsOn("org", "parent_dep", "1.2")
+ .hasPackaging('pom')
+ .publish()
+
+ def parentDep = repo1.module("org", "parent_dep", "1.2").publish()
+
+ def child1 = repo1.module("org", "child1", "1.0")
+ child1.parent("org", "parent", "1.0").publish()
+ def child2 = repo1.module("org", "child2", "1.0")
+ child2.parent("org", "parent", "1.0").publish()
+
+ buildFile << """
+repositories {
+ maven { url '${repo1.uri}' }
+ maven { url '${repo2.uri}' }
+}
+configurations {
+ child1
+ child2
+}
+dependencies {
+ child1 'org:child1:1.0'
+ child2 'org:child2:1.0'
+}
+task retrieveChild1(type: Sync) {
+ into 'libs/child1'
+ from configurations.child1
+}
+task retrieveChild2(type: Sync) {
+ into 'libs/child2'
+ from configurations.child2
+}
+"""
+
+ when:
+ child1.pom.expectGet()
+ missingParent.pom.expectGetMissing()
+ missingParent.artifact.expectHeadMissing()
+ parent.pom.expectGet()
+ parent.artifact.expectHeadMissing()
+
+ child1.artifact.expectGet()
+
+ parentDep.pom.expectGet()
+ parentDep.artifact.expectGet()
+
+
+ and:
+ run 'retrieveChild1'
+
+ then:
+ file('libs/child1').assertHasDescendants('child1-1.0.jar', 'parent_dep-1.2.jar')
+
+ when:
+ server.resetExpectations()
+ child2.pom.expectGet()
+ child2.artifact.expectGet()
+
+ and:
+ run 'retrieveChild2'
+
+ then:
+ file('libs/child2').assertHasDescendants('child2-1.0.jar', 'parent_dep-1.2.jar')
+ }
}
\ No newline at end of file
diff --git a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenSnapshotResolveIntegrationTest.groovy b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenSnapshotResolveIntegrationTest.groovy
index 6784b20..d3251fe 100644
--- a/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenSnapshotResolveIntegrationTest.groovy
+++ b/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenSnapshotResolveIntegrationTest.groovy
@@ -17,6 +17,7 @@ package org.gradle.integtests.resolve.maven
import org.gradle.integtests.fixtures.AbstractDependencyResolutionTest
import org.gradle.test.fixtures.maven.MavenHttpModule
+import spock.lang.Ignore
class MavenSnapshotResolveIntegrationTest extends AbstractDependencyResolutionTest {
@@ -348,6 +349,10 @@ allprojects {
from configurations.compile
}
}
+
+//imposing an artificial order so that the parallel build retrieves sequentially, GRADLE-2788
+retrieve.dependsOn ":a:retrieve"
+tasks.getByPath(":a:retrieve").dependsOn ":b:retrieve"
"""
when: "Module is requested once"
expectModuleServed(module)
@@ -361,6 +366,7 @@ allprojects {
file('b/build').assertHasDescendants('testproject-1.0-SNAPSHOT.jar')
}
+ @Ignore //TODO SF need to rework this test. First step might be turning off in-memory metadata caching for this test.
def "can update snapshot artifact during build even if it is locked earlier in build"() {
server.start()
given:
@@ -517,10 +523,9 @@ project('second') {
module.pom.expectHead()
module.pom.sha1.expectGet()
module.pom.expectGet()
- def artifact = module.artifact
- artifact.expectHead()
- artifact.sha1.expectGet()
- artifact.expectGet()
+ module.artifact.expectHead()
+ module.artifact.sha1.expectGet()
+ module.artifact.expectGet()
}
private expectChangedArtifactServed(MavenHttpModule module) {
diff --git a/subprojects/core-impl/src/integTest/resources/org/gradle/integtests/resolve/ArtifactDependenciesIntegrationTest/canNestModules/projectWithNestedModules.gradle b/subprojects/core-impl/src/integTest/resources/org/gradle/integtests/resolve/ArtifactDependenciesIntegrationTest/canNestModules/projectWithNestedModules.gradle
index d104d48..df5cea3 100644
--- a/subprojects/core-impl/src/integTest/resources/org/gradle/integtests/resolve/ArtifactDependenciesIntegrationTest/canNestModules/projectWithNestedModules.gradle
+++ b/subprojects/core-impl/src/integTest/resources/org/gradle/integtests/resolve/ArtifactDependenciesIntegrationTest/canNestModules/projectWithNestedModules.gradle
@@ -22,5 +22,5 @@ file("projectC-2.0.jar").text = ''
task listJars << {
List jars = configurations.compile.collect { it.name }
- assert jars == ['projectA-1.2.jar', 'projectC-2.0.jar', 'projectB-1.5.jar']
+ assert jars == ['projectA-1.2.jar', 'projectB-1.5.jar', 'projectC-2.0.jar']
}
diff --git a/subprojects/core-impl/src/integTest/resources/org/gradle/integtests/resolve/ArtifactDependenciesIntegrationTest/dependencyReportWithConflicts/projectWithConflicts.gradle b/subprojects/core-impl/src/integTest/resources/org/gradle/integtests/resolve/ArtifactDependenciesIntegrationTest/dependencyReportWithConflicts/projectWithConflicts.gradle
index 0deaf43..47b508d 100644
--- a/subprojects/core-impl/src/integTest/resources/org/gradle/integtests/resolve/ArtifactDependenciesIntegrationTest/dependencyReportWithConflicts/projectWithConflicts.gradle
+++ b/subprojects/core-impl/src/integTest/resources/org/gradle/integtests/resolve/ArtifactDependenciesIntegrationTest/dependencyReportWithConflicts/projectWithConflicts.gradle
@@ -3,7 +3,7 @@ allprojects {
evictedTransitive
evictedDirect
multiProject
- add('default')
+ create('default')
}
dependencies {
repositories {
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ArtifactDependencyResolver.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ArtifactDependencyResolver.java
index 7b5dae9..b94fd63 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ArtifactDependencyResolver.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ArtifactDependencyResolver.java
@@ -21,9 +21,6 @@ import org.gradle.api.internal.artifacts.repositories.ResolutionAwareRepository;
import java.util.List;
-/**
- * @author Hans Dockter
- */
public interface ArtifactDependencyResolver {
ResolverResults resolve(ConfigurationInternal configuration, List<? extends ResolutionAwareRepository> repositories) throws ResolveException;
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/BuildableModuleVersionPublishMetaData.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/BuildableModuleVersionPublishMetaData.java
new file mode 100644
index 0000000..093fcad
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/BuildableModuleVersionPublishMetaData.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts;
+
+import org.apache.ivy.core.module.descriptor.Artifact;
+import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor;
+
+import java.io.File;
+
+public interface BuildableModuleVersionPublishMetaData extends ModuleVersionPublishMetaData {
+ DefaultModuleDescriptor getModuleDescriptor();
+
+ void addArtifact(Artifact artifact, File file);
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ConfigurationResolver.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ConfigurationResolver.java
index 501959b..0751e90 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ConfigurationResolver.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ConfigurationResolver.java
@@ -18,9 +18,6 @@ package org.gradle.api.internal.artifacts;
import org.gradle.api.artifacts.ResolveException;
import org.gradle.api.internal.artifacts.configurations.ConfigurationInternal;
-/**
- * @author Hans Dockter
- */
public interface ConfigurationResolver {
ResolverResults resolve(ConfigurationInternal configuration) throws ResolveException;
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/DefaultArtifactIdentifier.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/DefaultArtifactIdentifier.java
new file mode 100644
index 0000000..8f91951
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/DefaultArtifactIdentifier.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts;
+
+import org.apache.ivy.core.module.descriptor.Artifact;
+import org.apache.ivy.core.module.descriptor.DefaultArtifact;
+import org.apache.ivy.core.module.id.ModuleRevisionId;
+import org.gradle.api.artifacts.ArtifactIdentifier;
+import org.gradle.api.artifacts.ModuleVersionIdentifier;
+
+import java.util.Collections;
+import java.util.Map;
+
+import static org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier.newId;
+
+public class DefaultArtifactIdentifier implements ArtifactIdentifier {
+ private final ModuleVersionIdentifier moduleVersionIdentifier;
+ private final String name;
+ private final String type;
+ private final String extension;
+ private final String classifier;
+
+ public DefaultArtifactIdentifier(ModuleVersionIdentifier moduleVersionIdentifier, String name, String type, String extension, String classifier) {
+ this.moduleVersionIdentifier = moduleVersionIdentifier;
+ this.name = name;
+ this.type = type;
+ this.extension = extension;
+ this.classifier = classifier;
+ }
+
+ public DefaultArtifactIdentifier(Artifact artifact) {
+ this(newId(artifact.getModuleRevisionId()), artifact.getName(), artifact.getType(), artifact.getExt(), artifact.getExtraAttribute("classifier"));
+ }
+
+ public static Artifact toArtifact(ArtifactIdentifier artifactIdentifier) {
+ ModuleVersionIdentifier moduleVersionIdentifier = artifactIdentifier.getModuleVersionIdentifier();
+ Map<String, String> extraAttributes = artifactIdentifier.getClassifier() == null ? Collections.<String, String>emptyMap() : Collections.singletonMap("classifier", artifactIdentifier.getClassifier());
+ ModuleRevisionId moduleRevisionId = ModuleRevisionId.newInstance(moduleVersionIdentifier.getGroup(), moduleVersionIdentifier.getName(), moduleVersionIdentifier.getVersion());
+ return new DefaultArtifact(moduleRevisionId, null, artifactIdentifier.getName(), artifactIdentifier.getType(), artifactIdentifier.getExtension(), extraAttributes);
+ }
+
+ public ModuleVersionIdentifier getModuleVersionIdentifier() {
+ return moduleVersionIdentifier;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public String getExtension() {
+ return extension;
+ }
+
+ public String getClassifier() {
+ return classifier;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("module: %s, name: %s, ext: %s, classifier: %s", moduleVersionIdentifier, name, extension, classifier);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof DefaultArtifactIdentifier)) {
+ return false;
+ }
+
+ DefaultArtifactIdentifier that = (DefaultArtifactIdentifier) o;
+
+ if (classifier != null ? !classifier.equals(that.classifier) : that.classifier != null) {
+ return false;
+ }
+ if (extension != null ? !extension.equals(that.extension) : that.extension != null) {
+ return false;
+ }
+ if (moduleVersionIdentifier != null ? !moduleVersionIdentifier.equals(that.moduleVersionIdentifier) : that.moduleVersionIdentifier != null) {
+ return false;
+ }
+ if (name != null ? !name.equals(that.name) : that.name != null) {
+ return false;
+ }
+ if (type != null ? !type.equals(that.type) : that.type != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = moduleVersionIdentifier != null ? moduleVersionIdentifier.hashCode() : 0;
+ result = 31 * result + (name != null ? name.hashCode() : 0);
+ result = 31 * result + (type != null ? type.hashCode() : 0);
+ result = 31 * result + (extension != null ? extension.hashCode() : 0);
+ result = 31 * result + (classifier != null ? classifier.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/DefaultDependencyFactory.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/DefaultDependencyFactory.java
index 69e7831..e46766f 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/DefaultDependencyFactory.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/DefaultDependencyFactory.java
@@ -28,9 +28,6 @@ import org.gradle.api.internal.notations.api.NotationParser;
import java.util.Map;
-/**
- * @author Hans Dockter
- */
public class DefaultDependencyFactory implements DependencyFactory {
private final NotationParser<Dependency> dependencyNotationParser;
private final NotationParser<ClientModule> clientModuleNotationParser;
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java
index 59e2b1a..45d1241 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java
@@ -28,6 +28,7 @@ import org.gradle.api.internal.artifacts.configurations.DefaultConfigurationCont
import org.gradle.api.internal.artifacts.configurations.DependencyMetaDataProvider;
import org.gradle.api.internal.artifacts.dependencies.DefaultExternalModuleDependency;
import org.gradle.api.internal.artifacts.dsl.DefaultArtifactHandler;
+import org.gradle.api.internal.artifacts.dsl.DefaultComponentMetadataHandler;
import org.gradle.api.internal.artifacts.dsl.DefaultRepositoryHandler;
import org.gradle.api.internal.artifacts.dsl.PublishArtifactNotationParserFactory;
import org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler;
@@ -38,23 +39,30 @@ import org.gradle.api.internal.artifacts.ivyservice.dynamicversions.ModuleResolu
import org.gradle.api.internal.artifacts.ivyservice.dynamicversions.SingleFileBackedModuleResolutionCache;
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ResolveIvyFactory;
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.StartParameterResolutionOverride;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.memcache.InMemoryDependencyMetadataCache;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.DefaultMetaDataParser;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.ParserRegistry;
import org.gradle.api.internal.artifacts.ivyservice.modulecache.DefaultModuleDescriptorCache;
import org.gradle.api.internal.artifacts.ivyservice.modulecache.ModuleDescriptorCache;
import org.gradle.api.internal.artifacts.ivyservice.moduleconverter.*;
import org.gradle.api.internal.artifacts.ivyservice.moduleconverter.dependencies.*;
import org.gradle.api.internal.artifacts.ivyservice.projectmodule.DefaultProjectModuleRegistry;
import org.gradle.api.internal.artifacts.ivyservice.resolveengine.DefaultDependencyResolver;
+import org.gradle.api.internal.artifacts.ivyservice.resolveengine.store.ResolutionResultsStoreFactory;
import org.gradle.api.internal.artifacts.mvnsettings.*;
import org.gradle.api.internal.artifacts.repositories.DefaultBaseRepositoryFactory;
-import org.gradle.api.internal.artifacts.repositories.cachemanager.DownloadingRepositoryCacheManager;
-import org.gradle.api.internal.artifacts.repositories.cachemanager.LocalFileRepositoryCacheManager;
+import org.gradle.api.internal.artifacts.repositories.cachemanager.DownloadingRepositoryArtifactCache;
+import org.gradle.api.internal.artifacts.repositories.legacy.CustomIvyResolverRepositoryFactory;
+import org.gradle.api.internal.artifacts.repositories.legacy.DownloadingRepositoryCacheManager;
+import org.gradle.api.internal.artifacts.repositories.cachemanager.LocalFileRepositoryArtifactCache;
+import org.gradle.api.internal.artifacts.repositories.legacy.LegacyDependencyResolverRepositoryFactory;
+import org.gradle.api.internal.artifacts.repositories.legacy.LocalFileRepositoryCacheManager;
import org.gradle.api.internal.artifacts.repositories.transport.RepositoryTransportFactory;
import org.gradle.api.internal.externalresource.cached.ByUrlCachedExternalResourceIndex;
import org.gradle.api.internal.externalresource.ivy.ArtifactAtRepositoryCachedArtifactIndex;
import org.gradle.api.internal.externalresource.local.LocallyAvailableResourceFinder;
import org.gradle.api.internal.externalresource.local.ivy.LocallyAvailableResourceFinderFactory;
import org.gradle.api.internal.file.FileResolver;
-import org.gradle.api.internal.file.IdentityFileResolver;
import org.gradle.api.internal.file.TmpDirTemporaryFileProvider;
import org.gradle.api.internal.filestore.PathKeyFileStore;
import org.gradle.api.internal.filestore.UniquePathKeyFileStore;
@@ -85,10 +93,13 @@ public class DefaultDependencyManagementServices extends DefaultServiceRegistry
return new DefaultDependencyResolutionServices(this, resolver, dependencyMetaDataProvider, projectFinder, domainObjectContext);
}
+ protected InMemoryDependencyMetadataCache createInMemoryDependencyMetadataCache() {
+ return new InMemoryDependencyMetadataCache();
+ }
+
protected ResolveModuleDescriptorConverter createResolveModuleDescriptorConverter() {
return new ResolveModuleDescriptorConverter(
get(ModuleDescriptorFactory.class),
- get(DependencyDescriptorFactory.class),
get(ConfigurationsToModuleDescriptorConverter.class),
new DefaultDependenciesToModuleDescriptorConverter(
get(DependencyDescriptorFactory.class),
@@ -99,11 +110,11 @@ public class DefaultDependencyManagementServices extends DefaultServiceRegistry
protected PublishModuleDescriptorConverter createPublishModuleDescriptorConverter() {
return new PublishModuleDescriptorConverter(
get(ResolveModuleDescriptorConverter.class),
- new DefaultArtifactsToModuleDescriptorConverter(DefaultArtifactsToModuleDescriptorConverter.RESOLVE_STRATEGY));
+ new DefaultArtifactsToModuleDescriptorConverter());
}
protected ModuleDescriptorFactory createModuleDescriptorFactory() {
- return new DefaultModuleDescriptorFactory(get(IvyFactory.class), get(SettingsConverter.class));
+ return new DefaultModuleDescriptorFactory();
}
protected ExcludeRuleConverter createExcludeRuleConverter() {
@@ -150,7 +161,7 @@ public class DefaultDependencyManagementServices extends DefaultServiceRegistry
moduleMapParser,
selfResolvingDependencyFactory,
projParser,
- new DependencyClassPathNotationParser(instantiator, get(ClassPathRegistry.class), new IdentityFileResolver()));
+ new DependencyClassPathNotationParser(instantiator, get(ClassPathRegistry.class), get(FileResolver.class).withNoBaseDir()));
return new DefaultDependencyFactory(
new DependencyNotationParser(notationParsers),
@@ -207,16 +218,8 @@ public class DefaultDependencyManagementServices extends DefaultServiceRegistry
return new ArtifactRevisionIdFileStore(get(PathKeyFileStore.class), new TmpDirTemporaryFileProvider());
}
- protected SettingsConverter createSettingsConverter() {
- return new DefaultSettingsConverter(
- new IvySettingsFactory(
- get(ArtifactCacheMetaData.class)
- )
- );
- }
-
- protected IvyFactory createIvyFactory() {
- return new DefaultIvyFactory();
+ protected IvyContextManager createIvyContextManager() {
+ return new DefaultIvyContextManager();
}
protected MavenSettingsProvider createMavenSettingsProvider() {
@@ -234,20 +237,33 @@ public class DefaultDependencyManagementServices extends DefaultServiceRegistry
return finderFactory.create();
}
- protected LocalFileRepositoryCacheManager createLocalRepositoryCacheManager() {
- return new LocalFileRepositoryCacheManager("local");
+ protected LegacyDependencyResolverRepositoryFactory createCustomerResolverRepositoryFactory() {
+ return new CustomIvyResolverRepositoryFactory(
+ get(ProgressLoggerFactory.class),
+ new LocalFileRepositoryCacheManager("local"),
+ new DownloadingRepositoryCacheManager(
+ "downloading",
+ get(ArtifactRevisionIdFileStore.class),
+ new TmpDirTemporaryFileProvider(),
+ get(CacheLockingManager.class)
+ )
+ );
+ }
+
+ protected LocalFileRepositoryArtifactCache createLocalRepositoryArtifactCache() {
+ return new LocalFileRepositoryArtifactCache();
}
- protected DownloadingRepositoryCacheManager createDownloadingRepositoryCacheManager() {
- return new DownloadingRepositoryCacheManager("downloading", get(ArtifactRevisionIdFileStore.class), get(ByUrlCachedExternalResourceIndex.class),
+ protected DownloadingRepositoryArtifactCache createDownloadingRepositoryArtifactCache() {
+ return new DownloadingRepositoryArtifactCache(get(ArtifactRevisionIdFileStore.class), get(ByUrlCachedExternalResourceIndex.class),
new TmpDirTemporaryFileProvider(), get(CacheLockingManager.class));
}
protected RepositoryTransportFactory createRepositoryTransportFactory() {
return new RepositoryTransportFactory(
get(ProgressLoggerFactory.class),
- get(LocalFileRepositoryCacheManager.class),
- get(DownloadingRepositoryCacheManager.class),
+ get(LocalFileRepositoryArtifactCache.class),
+ get(DownloadingRepositoryArtifactCache.class),
new TmpDirTemporaryFileProvider(),
get(ByUrlCachedExternalResourceIndex.class)
);
@@ -257,14 +273,13 @@ public class DefaultDependencyManagementServices extends DefaultServiceRegistry
StartParameter startParameter = get(StartParameter.class);
StartParameterResolutionOverride startParameterResolutionOverride = new StartParameterResolutionOverride(startParameter);
return new ResolveIvyFactory(
- get(IvyFactory.class),
- get(SettingsConverter.class),
get(ModuleResolutionCache.class),
get(ModuleDescriptorCache.class),
get(ArtifactAtRepositoryCachedArtifactIndex.class),
get(CacheLockingManager.class),
startParameterResolutionOverride,
- get(BuildCommencedTimeProvider.class));
+ get(BuildCommencedTimeProvider.class),
+ get(InMemoryDependencyMetadataCache.class));
}
protected ArtifactDependencyResolver createArtifactDependencyResolver() {
@@ -272,13 +287,14 @@ public class DefaultDependencyManagementServices extends DefaultServiceRegistry
get(ResolveIvyFactory.class),
get(PublishModuleDescriptorConverter.class),
new ResolvedArtifactFactory(
- get(CacheLockingManager.class)
+ get(CacheLockingManager.class),
+ get(IvyContextManager.class)
),
new DefaultProjectModuleRegistry(
get(PublishModuleDescriptorConverter.class)),
- get(ProjectAccessListener.class),
- get(CacheLockingManager.class)
- );
+ get(CacheLockingManager.class),
+ get(IvyContextManager.class),
+ get(ResolutionResultsStoreFactory.class));
return new ErrorHandlingArtifactDependencyResolver(
new ShortcircuitEmptyConfigsArtifactDependencyResolver(
new SelfResolvingDependencyResolver(
@@ -287,6 +303,10 @@ public class DefaultDependencyManagementServices extends DefaultServiceRegistry
resolver))));
}
+ protected ResolutionResultsStoreFactory createResolutionResultsStoreFactory() {
+ return new ResolutionResultsStoreFactory(new TmpDirTemporaryFileProvider());
+ }
+
private class DefaultDependencyResolutionServices implements DependencyResolutionServices {
private final ServiceRegistry parent;
private final FileResolver fileResolver;
@@ -296,6 +316,7 @@ public class DefaultDependencyManagementServices extends DefaultServiceRegistry
private DefaultRepositoryHandler repositoryHandler;
private ConfigurationContainerInternal configurationContainer;
private DependencyHandler dependencyHandler;
+ private DefaultComponentMetadataHandler componentMetadataHandler;
private DefaultArtifactHandler artifactHandler;
private BaseRepositoryFactory baseRepositoryFactory;
@@ -324,9 +345,9 @@ public class DefaultDependencyManagementServices extends DefaultServiceRegistry
instantiator,
get(RepositoryTransportFactory.class),
get(LocallyAvailableResourceFinder.class),
- get(ProgressLoggerFactory.class),
- get(LocalFileRepositoryCacheManager.class),
- get(DownloadingRepositoryCacheManager.class)
+ new DefaultMetaDataParser(new ParserRegistry()),
+ getComponentMetadataHandler(),
+ get(LegacyDependencyResolverRepositoryFactory.class)
);
}
@@ -351,11 +372,19 @@ public class DefaultDependencyManagementServices extends DefaultServiceRegistry
public DependencyHandler getDependencyHandler() {
if (dependencyHandler == null) {
- dependencyHandler = new DefaultDependencyHandler(getConfigurationContainer(), parent.get(DependencyFactory.class), projectFinder);
+ dependencyHandler = new DefaultDependencyHandler(getConfigurationContainer(), parent.get(DependencyFactory.class), projectFinder, getComponentMetadataHandler());
}
return dependencyHandler;
}
+ public DefaultComponentMetadataHandler getComponentMetadataHandler() {
+ if (componentMetadataHandler == null) {
+ Instantiator instantiator = parent.get(Instantiator.class);
+ componentMetadataHandler = instantiator.newInstance(DefaultComponentMetadataHandler.class, instantiator);
+ }
+ return componentMetadataHandler;
+ }
+
public ArtifactHandler getArtifactHandler() {
if (artifactHandler == null) {
NotationParser<PublishArtifact> publishArtifactNotationParser = new PublishArtifactNotationParserFactory(get(Instantiator.class), dependencyMetaDataProvider).create();
@@ -376,13 +405,12 @@ public class DefaultDependencyManagementServices extends DefaultServiceRegistry
ArtifactPublisher createArtifactPublisher() {
return new IvyBackedArtifactPublisher(
- get(SettingsConverter.class),
get(PublishModuleDescriptorConverter.class),
- get(IvyFactory.class),
- new DefaultIvyDependencyPublisher()
+ get(IvyContextManager.class),
+ new DefaultIvyDependencyPublisher(),
+ new IvyXmlModuleDescriptorWriter()
);
}
-
}
private static class DefaultArtifactPublicationServices implements ArtifactPublicationServices {
@@ -396,16 +424,6 @@ public class DefaultDependencyManagementServices extends DefaultServiceRegistry
return dependencyResolutionServices.createRepositoryHandler();
}
- public ModuleDescriptorConverter getDescriptorFileModuleConverter() {
- return new PublishModuleDescriptorConverter(
- dependencyResolutionServices.parent.get(ResolveModuleDescriptorConverter.class),
- new DefaultArtifactsToModuleDescriptorConverter(DefaultArtifactsToModuleDescriptorConverter.IVY_FILE_STRATEGY));
- }
-
- public IvyModuleDescriptorWriter getIvyModuleDescriptorWriter() {
- return new IvyXmlModuleDescriptorWriter();
- }
-
public ArtifactPublisher createArtifactPublisher() {
return dependencyResolutionServices.createArtifactPublisher();
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/DefaultModuleVersionIdentifier.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/DefaultModuleVersionIdentifier.java
index 346f2be..2ab0961 100755
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/DefaultModuleVersionIdentifier.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/DefaultModuleVersionIdentifier.java
@@ -15,6 +15,7 @@
*/
package org.gradle.api.internal.artifacts;
+import org.apache.ivy.core.module.id.ModuleRevisionId;
import org.gradle.api.artifacts.Module;
import org.gradle.api.artifacts.ModuleIdentifier;
import org.gradle.api.artifacts.ModuleVersionIdentifier;
@@ -83,4 +84,8 @@ public class DefaultModuleVersionIdentifier implements ModuleVersionIdentifier {
public static ModuleVersionIdentifier newId(String group, String name, String version) {
return new DefaultModuleVersionIdentifier(group, name, version);
}
+
+ public static ModuleVersionIdentifier newId(ModuleRevisionId moduleRevisionId) {
+ return new DefaultModuleVersionIdentifier(moduleRevisionId.getOrganisation(), moduleRevisionId.getName(), moduleRevisionId.getRevision());
+ }
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/DefaultModuleVersionPublishMetaData.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/DefaultModuleVersionPublishMetaData.java
new file mode 100644
index 0000000..307bf02
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/DefaultModuleVersionPublishMetaData.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts;
+
+import org.apache.ivy.core.module.descriptor.Artifact;
+import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor;
+import org.gradle.api.artifacts.ModuleVersionIdentifier;
+
+import java.io.File;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+public class DefaultModuleVersionPublishMetaData implements BuildableModuleVersionPublishMetaData {
+ private final Map<Artifact, File> artifacts = new LinkedHashMap<Artifact, File>();
+ private final DefaultModuleDescriptor moduleDescriptor;
+ private final ModuleVersionIdentifier id;
+
+ public DefaultModuleVersionPublishMetaData(DefaultModuleDescriptor moduleDescriptor) {
+ this.moduleDescriptor = moduleDescriptor;
+ id = DefaultModuleVersionIdentifier.newId(moduleDescriptor.getModuleRevisionId());
+ }
+
+ public ModuleVersionIdentifier getId() {
+ return id;
+ }
+
+ public DefaultModuleDescriptor getModuleDescriptor() {
+ return moduleDescriptor;
+ }
+
+ public void addArtifact(Artifact artifact, File file) {
+ artifacts.put(artifact, file);
+ }
+
+ public Map<Artifact, File> getArtifacts() {
+ return artifacts;
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/DefaultModuleVersionSelector.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/DefaultModuleVersionSelector.java
index 17af643..b285c6f 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/DefaultModuleVersionSelector.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/DefaultModuleVersionSelector.java
@@ -16,12 +16,10 @@
package org.gradle.api.internal.artifacts;
+import org.apache.ivy.core.module.id.ModuleRevisionId;
import org.gradle.api.artifacts.ModuleVersionIdentifier;
import org.gradle.api.artifacts.ModuleVersionSelector;
-/**
- * by Szczepan Faber, created at: 11/13/11
- */
public class DefaultModuleVersionSelector implements ModuleVersionSelector {
private String group;
@@ -105,4 +103,8 @@ public class DefaultModuleVersionSelector implements ModuleVersionSelector {
public static ModuleVersionSelector newSelector(String group, String name, String version) {
return new DefaultModuleVersionSelector(group, name, version);
}
+
+ public static ModuleVersionSelector newSelector(ModuleRevisionId module) {
+ return newSelector(module.getOrganisation(), module.getName(), module.getRevision());
+ }
}
\ No newline at end of file
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/DefaultProjectDependencyFactory.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/DefaultProjectDependencyFactory.java
index bf9301b..62af822 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/DefaultProjectDependencyFactory.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/DefaultProjectDependencyFactory.java
@@ -23,9 +23,6 @@ import org.gradle.api.internal.project.ProjectInternal;
import org.gradle.initialization.ProjectAccessListener;
import org.gradle.internal.reflect.Instantiator;
-/**
- * by Szczepan Faber, created at: 2/5/13
- */
public class DefaultProjectDependencyFactory {
private final ProjectAccessListener projectAccessListener;
private final Instantiator instantiator;
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/DefaultResolvedArtifact.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/DefaultResolvedArtifact.java
index 02cea03..b034e65 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/DefaultResolvedArtifact.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/DefaultResolvedArtifact.java
@@ -27,20 +27,21 @@ import java.io.File;
import java.util.HashMap;
import java.util.Map;
-/**
- * @author Hans Dockter
- */
public class DefaultResolvedArtifact implements ResolvedArtifact {
- private final ResolvedDependency resolvedDependency;
private final Map<String, String> extraAttributes;
private final String name;
private final String type;
private final String ext;
+ private final ResolvedModuleVersion owner;
+ private long id;
+ private final Factory<ResolvedDependency> ownerSource;
private Factory<File> artifactSource;
private File file;
- public DefaultResolvedArtifact(ResolvedDependency resolvedDependency, Artifact artifact, Factory<File> artifactSource) {
- this.resolvedDependency = resolvedDependency;
+ public DefaultResolvedArtifact(ResolvedModuleVersion owner, Factory<ResolvedDependency> ownerSource, Artifact artifact, Factory<File> artifactSource, long id) {
+ this.ownerSource = ownerSource;
+ this.owner = owner;
+ this.id = id;
// Unpack the stuff that we're interested from the artifact and discard. The artifact instance drags in a whole pile of stuff that
// we don't want to retain references to.
this.name = artifact.getName();
@@ -50,21 +51,26 @@ public class DefaultResolvedArtifact implements ResolvedArtifact {
this.artifactSource = artifactSource;
}
+ public long getId() {
+ return id;
+ }
+
public ResolvedDependency getResolvedDependency() {
DeprecationLogger.nagUserOfDeprecated(
"ResolvedArtifact.getResolvedDependency()",
"For version info use ResolvedArtifact.getModuleVersion(), to access the dependency graph use ResolvedConfiguration.getFirstLevelModuleDependencies()"
);
- return resolvedDependency;
+ //resolvedDependency is expensive so lazily create it
+ return ownerSource.create();
}
public ResolvedModuleVersion getModuleVersion() {
- return resolvedDependency.getModule();
+ return owner;
}
@Override
public String toString() {
- return String.format("[ResolvedArtifact dependency:%s name:%s classifier:%s extension:%s type:%s]", resolvedDependency, getName(), getClassifier(), getExtension(), getType());
+ return String.format("[ResolvedArtifact dependency:%s name:%s classifier:%s extension:%s type:%s]", owner, getName(), getClassifier(), getExtension(), getType());
}
@Override
@@ -76,7 +82,7 @@ public class DefaultResolvedArtifact implements ResolvedArtifact {
return false;
}
DefaultResolvedArtifact other = (DefaultResolvedArtifact) obj;
- if (!other.resolvedDependency.getModule().getId().equals(resolvedDependency.getModule().getId())) {
+ if (!other.owner.getId().equals(owner.getId())) {
return false;
}
if (!other.getName().equals(getName())) {
@@ -96,7 +102,7 @@ public class DefaultResolvedArtifact implements ResolvedArtifact {
@Override
public int hashCode() {
- return resolvedDependency.getModule().getId().hashCode() ^ getName().hashCode() ^ getType().hashCode() ^ getExtension().hashCode() ^ extraAttributes.hashCode();
+ return owner.getId().hashCode() ^ getName().hashCode() ^ getType().hashCode() ^ getExtension().hashCode() ^ extraAttributes.hashCode();
}
public String getName() {
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/DefaultResolvedDependency.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/DefaultResolvedDependency.java
index 3c8d725..fd83484 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/DefaultResolvedDependency.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/DefaultResolvedDependency.java
@@ -25,9 +25,6 @@ import org.gradle.api.artifacts.ResolvedModuleVersion;
import java.util.*;
-/**
- * @author Hans Dockter
- */
public class DefaultResolvedDependency implements ResolvedDependency {
private final Set<ResolvedDependency> children = new LinkedHashSet<ResolvedDependency>();
private final Set<ResolvedDependency> parents = new LinkedHashSet<ResolvedDependency>();
@@ -38,16 +35,12 @@ public class DefaultResolvedDependency implements ResolvedDependency {
private final Map<ResolvedDependency, Set<ResolvedArtifact>> allArtifactsCache = new HashMap<ResolvedDependency, Set<ResolvedArtifact>>();
private Set<ResolvedArtifact> allModuleArtifactsCache;
- public DefaultResolvedDependency(String name, String moduleGroup, String moduleName, String moduleVersion, String configuration) {
- this.name = name;
- id = new ResolvedConfigurationIdentifier(moduleGroup, moduleName, moduleVersion, configuration);
+ public DefaultResolvedDependency(ModuleVersionIdentifier moduleVersionIdentifier, String configuration) {
+ this.name = String.format("%s:%s:%s", moduleVersionIdentifier.getGroup(), moduleVersionIdentifier.getName(), moduleVersionIdentifier.getVersion());
+ id = new ResolvedConfigurationIdentifier(moduleVersionIdentifier, configuration);
this.moduleArtifacts = new TreeSet<ResolvedArtifact>(new ResolvedArtifactComparator());
}
- public DefaultResolvedDependency(String moduleGroup, String moduleName, String moduleVersion, String configuration) {
- this(moduleGroup + ":" + moduleName + ":" + moduleVersion, moduleGroup, moduleName, moduleVersion, configuration);
- }
-
public String getName() {
return name;
}
@@ -75,7 +68,7 @@ public class DefaultResolvedDependency implements ResolvedDependency {
public ResolvedModuleVersion getModule() {
return new ResolvedModuleVersion() {
public ModuleVersionIdentifier getId() {
- return new DefaultModuleVersionIdentifier(id.getModuleGroup(), id.getModuleName(), id.getModuleVersion());
+ return id.getId();
}
};
}
@@ -102,7 +95,7 @@ public class DefaultResolvedDependency implements ResolvedDependency {
public Set<ResolvedArtifact> getParentArtifacts(ResolvedDependency parent) {
if (!parents.contains(parent)) {
- throw new InvalidUserDataException("Unknown Parent");
+ throw new InvalidUserDataException("Provided dependency (" + parent + ") must be a parent of: " + this);
}
Set<ResolvedArtifact> artifacts = parentArtifacts.get(parent);
return artifacts == null ? Collections.<ResolvedArtifact>emptySet() : artifacts;
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ModuleMetadataProcessor.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ModuleMetadataProcessor.java
new file mode 100644
index 0000000..65975cc
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ModuleMetadataProcessor.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts;
+
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ModuleVersionMetaData;
+
+public interface ModuleMetadataProcessor {
+ void process(ModuleVersionMetaData metadata);
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ModuleVersionIdentifierSerializer.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ModuleVersionIdentifierSerializer.java
index f27db28..4cd8137 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ModuleVersionIdentifierSerializer.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ModuleVersionIdentifierSerializer.java
@@ -17,25 +17,23 @@
package org.gradle.api.internal.artifacts;
import org.gradle.api.artifacts.ModuleVersionIdentifier;
-import org.gradle.messaging.serialize.DataStreamBackedSerializer;
+import org.gradle.messaging.serialize.Decoder;
+import org.gradle.messaging.serialize.Encoder;
+import org.gradle.messaging.serialize.Serializer;
-import java.io.DataInput;
-import java.io.DataOutput;
import java.io.IOException;
-public class ModuleVersionIdentifierSerializer extends DataStreamBackedSerializer<ModuleVersionIdentifier> {
- @Override
- public void write(DataOutput dataOutput, ModuleVersionIdentifier value) throws IOException {
- dataOutput.writeUTF(value.getGroup());
- dataOutput.writeUTF(value.getName());
- dataOutput.writeUTF(value.getVersion());
+public class ModuleVersionIdentifierSerializer implements Serializer<ModuleVersionIdentifier> {
+ public void write(Encoder encoder, ModuleVersionIdentifier value) throws IOException {
+ encoder.writeString(value.getGroup());
+ encoder.writeString(value.getName());
+ encoder.writeString(value.getVersion());
}
- @Override
- public ModuleVersionIdentifier read(DataInput dataInput) throws IOException {
- String group = dataInput.readUTF();
- String module = dataInput.readUTF();
- String version = dataInput.readUTF();
+ public ModuleVersionIdentifier read(Decoder decoder) throws IOException {
+ String group = decoder.readString();
+ String module = decoder.readString();
+ String version = decoder.readString();
return DefaultModuleVersionIdentifier.newId(group, module, version);
}
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ModuleVersionSelectorSerializer.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ModuleVersionSelectorSerializer.java
new file mode 100644
index 0000000..8e43bcf
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ModuleVersionSelectorSerializer.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts;
+
+import org.gradle.api.artifacts.ModuleVersionSelector;
+import org.gradle.messaging.serialize.Decoder;
+import org.gradle.messaging.serialize.Encoder;
+import org.gradle.messaging.serialize.Serializer;
+
+import java.io.IOException;
+
+import static org.gradle.api.internal.artifacts.DefaultModuleVersionSelector.newSelector;
+
+public class ModuleVersionSelectorSerializer implements Serializer<ModuleVersionSelector> {
+ public ModuleVersionSelector read(Decoder decoder) throws IOException {
+ String group = decoder.readString();
+ String name = decoder.readString();
+ String version = decoder.readString();
+ return newSelector(group, name, version);
+ }
+
+ public void write(Encoder encoder, ModuleVersionSelector value) throws IOException {
+ encoder.writeString(value.getGroup());
+ encoder.writeString(value.getName());
+ encoder.writeString(value.getVersion());
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/PlexusLoggerAdapter.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/PlexusLoggerAdapter.java
index 4bb5c77..e02ab3b 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/PlexusLoggerAdapter.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/PlexusLoggerAdapter.java
@@ -17,9 +17,6 @@ package org.gradle.api.internal.artifacts;
import org.codehaus.plexus.logging.Logger;
-/**
- * @author Hans Dockter
- */
public class PlexusLoggerAdapter implements Logger {
org.slf4j.Logger logger;
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ResolvedConfigurationIdentifier.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ResolvedConfigurationIdentifier.java
index a6710a6..1fbdb6f 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ResolvedConfigurationIdentifier.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ResolvedConfigurationIdentifier.java
@@ -22,9 +22,9 @@ public class ResolvedConfigurationIdentifier {
private final ModuleVersionIdentifier id;
private final String configuration;
- public ResolvedConfigurationIdentifier(String moduleGroup, String moduleName, String moduleVersion,
+ public ResolvedConfigurationIdentifier(ModuleVersionIdentifier moduleVersionIdentifier,
String configuration) {
- this.id = new DefaultModuleVersionIdentifier(moduleGroup, moduleName, moduleVersion);
+ this.id = moduleVersionIdentifier;
this.configuration = configuration;
}
@@ -50,7 +50,7 @@ public class ResolvedConfigurationIdentifier {
@Override
public String toString() {
- return String.format("%s:%s:%s:%s", getModuleGroup(), getModuleVersion(), getModuleName(), configuration);
+ return String.format("%s:%s:%s:%s", getModuleGroup(), getModuleName(), getModuleVersion(), configuration);
}
@Override
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ResolvedConfigurationIdentifierSerializer.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ResolvedConfigurationIdentifierSerializer.java
new file mode 100644
index 0000000..ed9accc
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ResolvedConfigurationIdentifierSerializer.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts;
+
+import org.gradle.api.artifacts.ModuleVersionIdentifier;
+import org.gradle.messaging.serialize.Decoder;
+import org.gradle.messaging.serialize.Encoder;
+import org.gradle.messaging.serialize.Serializer;
+
+import java.io.IOException;
+
+public class ResolvedConfigurationIdentifierSerializer implements Serializer<ResolvedConfigurationIdentifier> {
+ private final ModuleVersionIdentifierSerializer idSerializer = new ModuleVersionIdentifierSerializer();
+
+ public ResolvedConfigurationIdentifier read(Decoder decoder) throws IOException {
+ ModuleVersionIdentifier id = idSerializer.read(decoder);
+ String configuration = decoder.readString();
+ return new ResolvedConfigurationIdentifier(id, configuration);
+ }
+
+ public void write(Encoder encoder, ResolvedConfigurationIdentifier value) throws IOException {
+ idSerializer.write(encoder, value.getId());
+ encoder.writeString(value.getConfiguration());
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ResolverResults.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ResolverResults.java
index 6811040..4320f80 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ResolverResults.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ResolverResults.java
@@ -20,9 +20,6 @@ import org.gradle.api.artifacts.ResolveException;
import org.gradle.api.artifacts.ResolvedConfiguration;
import org.gradle.api.artifacts.result.ResolutionResult;
-/**
- * by Szczepan Faber, created at: 10/16/12
- */
public class ResolverResults {
private final ResolvedConfiguration resolvedConfiguration;
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/configurations/Configurations.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/configurations/Configurations.java
index c92b018..793c227 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/configurations/Configurations.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/configurations/Configurations.java
@@ -21,9 +21,6 @@ import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
-/**
- * @author Hans Dockter
- */
public class Configurations {
public static Set<String> getNames(Collection<? extends Configuration> configurations, boolean includeExtended) {
Set<Configuration> allConfigurations = new HashSet<Configuration>(configurations);
@@ -49,15 +46,10 @@ public class Configurations {
return allConfigurations;
}
- public static String uploadInternalTaskName(String configurationName) {
- return String.format("upload%sInternal", getCapitalName(configurationName));
- }
-
public static String uploadTaskName(String configurationName) {
return String.format("upload%s", getCapitalName(configurationName));
}
-
private static String getCapitalName(String configurationName) {
return configurationName.substring(0, 1).toUpperCase() + configurationName.substring(1);
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/configurations/ConfigurationsProvider.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/configurations/ConfigurationsProvider.java
index 15b95cc..85bce22 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/configurations/ConfigurationsProvider.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/configurations/ConfigurationsProvider.java
@@ -19,9 +19,6 @@ import org.gradle.api.artifacts.Configuration;
import java.util.Set;
-/**
- * @author Hans Dockter
- */
public interface ConfigurationsProvider {
Set<Configuration> getAll();
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/configurations/DefaultConfiguration.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/configurations/DefaultConfiguration.java
index 3042e4e..cad63b4 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/configurations/DefaultConfiguration.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/configurations/DefaultConfiguration.java
@@ -411,6 +411,10 @@ public class DefaultConfiguration extends AbstractFileCollection implements Conf
return resolutionStrategy;
}
+ public String getPath() {
+ return path;
+ }
+
public Configuration resolutionStrategy(Closure closure) {
ConfigureUtil.configure(closure, resolutionStrategy);
return this;
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/configurations/DefaultConfigurationContainer.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/configurations/DefaultConfigurationContainer.java
index 0a2eb49..363e8bf 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/configurations/DefaultConfigurationContainer.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/configurations/DefaultConfigurationContainer.java
@@ -27,14 +27,12 @@ import org.gradle.api.internal.artifacts.ConfigurationResolver;
import org.gradle.api.internal.artifacts.ivyservice.resolutionstrategy.DefaultResolutionStrategy;
import org.gradle.internal.reflect.Instantiator;
import org.gradle.listener.ListenerManager;
+import org.gradle.util.DeprecationLogger;
import java.util.Collection;
import java.util.Set;
-/**
- * @author Hans Dockter
- */
-public class DefaultConfigurationContainer extends AbstractNamedDomainObjectContainer<Configuration>
+public class DefaultConfigurationContainer extends AbstractNamedDomainObjectContainer<Configuration>
implements ConfigurationContainerInternal, ConfigurationsProvider {
public static final String DETACHED_CONFIGURATION_DEFAULT_NAME = "detachedConfiguration";
@@ -69,10 +67,12 @@ public class DefaultConfigurationContainer extends AbstractNamedDomainObjectCont
}
public Configuration add(String name) {
+ DeprecationLogger.nagUserOfReplacedMethod("ConfigurationContainer.add()", "create()");
return create(name);
}
public Configuration add(String name, Closure closure) {
+ DeprecationLogger.nagUserOfReplacedMethod("ConfigurationContainer.add()", "create()");
return create(name, closure);
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/configurations/DetachedConfigurationsProvider.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/configurations/DetachedConfigurationsProvider.java
index c8c83ff..7a61bae 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/configurations/DetachedConfigurationsProvider.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/configurations/DetachedConfigurationsProvider.java
@@ -20,9 +20,6 @@ import org.gradle.util.WrapUtil;
import java.util.Set;
-/**
- * @author Hans Dockter
-*/
class DetachedConfigurationsProvider implements ConfigurationsProvider {
private Configuration theOnlyConfiguration;
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/dsl/DefaultArtifactHandler.groovy b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/dsl/DefaultArtifactHandler.groovy
index 6fd0bb3..6a68287 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/dsl/DefaultArtifactHandler.groovy
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/dsl/DefaultArtifactHandler.groovy
@@ -20,13 +20,10 @@ import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.ConfigurationContainer
import org.gradle.api.artifacts.PublishArtifact
import org.gradle.api.artifacts.dsl.ArtifactHandler
+import org.gradle.api.internal.notations.api.NotationParser
import org.gradle.util.ConfigureUtil
import org.gradle.util.GUtil
-import org.gradle.api.internal.notations.api.NotationParser
-/**
- * @author Hans Dockter
- */
class DefaultArtifactHandler implements ArtifactHandler {
ConfigurationContainer configurationContainer
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/dsl/DefaultComponentMetadataHandler.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/dsl/DefaultComponentMetadataHandler.java
new file mode 100644
index 0000000..18fc28b
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/dsl/DefaultComponentMetadataHandler.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.dsl;
+
+import org.gradle.api.Action;
+import org.gradle.api.artifacts.ComponentMetadataDetails;
+import org.gradle.api.internal.artifacts.ModuleMetadataProcessor;
+import org.gradle.api.artifacts.dsl.ComponentMetadataHandler;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ModuleVersionMetaData;
+import org.gradle.api.internal.artifacts.repositories.resolver.ComponentMetadataDetailsAdapter;
+import org.gradle.internal.reflect.Instantiator;
+import org.gradle.listener.ActionBroadcast;
+
+public class DefaultComponentMetadataHandler implements ComponentMetadataHandler, ModuleMetadataProcessor {
+ private final Instantiator instantiator;
+ private final ActionBroadcast<ComponentMetadataDetails> moduleRules = new ActionBroadcast<ComponentMetadataDetails>();
+
+ public DefaultComponentMetadataHandler(Instantiator instantiator) {
+ this.instantiator = instantiator;
+ }
+
+ public void eachComponent(Action<? super ComponentMetadataDetails> rule) {
+ moduleRules.add(rule);
+ }
+
+ public void process(ModuleVersionMetaData metadata) {
+ ComponentMetadataDetails details = instantiator.newInstance(ComponentMetadataDetailsAdapter.class, metadata);
+ moduleRules.execute(details);
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/dsl/ModuleVersionSelectorParsers.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/dsl/ModuleVersionSelectorParsers.java
index d852d60..2fa896a 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/dsl/ModuleVersionSelectorParsers.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/dsl/ModuleVersionSelectorParsers.java
@@ -30,9 +30,6 @@ import java.util.Set;
import static org.gradle.api.internal.artifacts.DefaultModuleVersionSelector.newSelector;
-/**
- * by Szczepan Faber, created at: 10/11/11
- */
public class ModuleVersionSelectorParsers {
public static NotationParser<Set<ModuleVersionSelector>> multiParser() {
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/dsl/ParsedModuleStringNotation.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/dsl/ParsedModuleStringNotation.java
index cb31a95..de16d59 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/dsl/ParsedModuleStringNotation.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/dsl/ParsedModuleStringNotation.java
@@ -18,9 +18,6 @@ package org.gradle.api.internal.artifacts.dsl;
import org.gradle.api.IllegalDependencyNotation;
import org.gradle.util.GUtil;
-/**
- * @author Hans Dockter
- */
public class ParsedModuleStringNotation {
private String group;
private String name;
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/dsl/PublishArtifactNotationParserFactory.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/dsl/PublishArtifactNotationParserFactory.java
index 0064e2d..c80157e 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/dsl/PublishArtifactNotationParserFactory.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/dsl/PublishArtifactNotationParserFactory.java
@@ -34,9 +34,6 @@ import org.gradle.internal.reflect.Instantiator;
import java.io.File;
import java.util.Collection;
-/**
- * @author Hans Dockter
- */
public class PublishArtifactNotationParserFactory implements Factory<NotationParser<PublishArtifact>> {
private final Instantiator instantiator;
private final DependencyMetaDataProvider metaDataProvider;
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/BuildableArtifactResolveResult.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/BuildableArtifactResolveResult.java
index dd43274..4ea37c1 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/BuildableArtifactResolveResult.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/BuildableArtifactResolveResult.java
@@ -16,7 +16,7 @@
package org.gradle.api.internal.artifacts.ivyservice;
-import org.apache.ivy.core.module.descriptor.Artifact;
+import org.gradle.api.artifacts.ArtifactIdentifier;
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ArtifactResolveException;
import java.io.File;
@@ -33,7 +33,7 @@ public interface BuildableArtifactResolveResult extends ArtifactResolveResult {
void failed(ArtifactResolveException failure);
/**
- * Marks the module version as not found.
+ * Marks the artifact as not found.
*/
- void notFound(Artifact artifact);
+ void notFound(ArtifactIdentifier artifact);
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultBuildableArtifactResolveResult.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultBuildableArtifactResolveResult.java
index 9e1d486..099f2db 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultBuildableArtifactResolveResult.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultBuildableArtifactResolveResult.java
@@ -16,7 +16,7 @@
package org.gradle.api.internal.artifacts.ivyservice;
-import org.apache.ivy.core.module.descriptor.Artifact;
+import org.gradle.api.artifacts.ArtifactIdentifier;
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ArtifactNotFoundException;
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ArtifactResolveException;
@@ -34,7 +34,7 @@ public class DefaultBuildableArtifactResolveResult implements BuildableArtifactR
this.file = file;
}
- public void notFound(Artifact artifact) {
+ public void notFound(ArtifactIdentifier artifact) {
failed(new ArtifactNotFoundException(artifact));
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultBuildableModuleVersionResolveResult.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultBuildableModuleVersionResolveResult.java
index 4410d69..7606036 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultBuildableModuleVersionResolveResult.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultBuildableModuleVersionResolveResult.java
@@ -19,7 +19,7 @@ package org.gradle.api.internal.artifacts.ivyservice;
import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
import org.gradle.api.artifacts.ModuleVersionIdentifier;
import org.gradle.api.artifacts.ModuleVersionSelector;
-import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.DefaultBuildableModuleVersionMetaData;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.DefaultBuildableModuleVersionMetaDataResolveResult;
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ModuleVersionMetaData;
public class DefaultBuildableModuleVersionResolveResult implements BuildableModuleVersionResolveResult {
@@ -38,7 +38,7 @@ public class DefaultBuildableModuleVersionResolveResult implements BuildableModu
}
public void resolved(ModuleVersionIdentifier moduleVersionId, ModuleDescriptor descriptor, ArtifactResolver artifactResolver) {
- DefaultBuildableModuleVersionMetaData metaData = new DefaultBuildableModuleVersionMetaData();
+ DefaultBuildableModuleVersionMetaDataResolveResult metaData = new DefaultBuildableModuleVersionMetaDataResolveResult();
metaData.resolved(moduleVersionId, descriptor, false, null);
resolved(metaData, artifactResolver);
}
@@ -50,7 +50,7 @@ public class DefaultBuildableModuleVersionResolveResult implements BuildableModu
public void setMetaData(ModuleDescriptor descriptor) {
assertResolved();
- DefaultBuildableModuleVersionMetaData newMetaData = new DefaultBuildableModuleVersionMetaData();
+ DefaultBuildableModuleVersionMetaDataResolveResult newMetaData = new DefaultBuildableModuleVersionMetaDataResolveResult();
newMetaData.resolved(metaData.getId(), descriptor, metaData.isChanging(), null);
this.metaData = newMetaData;
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultCacheLockingManager.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultCacheLockingManager.java
index 8928b3e..3f9b73c 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultCacheLockingManager.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultCacheLockingManager.java
@@ -28,7 +28,8 @@ import java.io.File;
public class DefaultCacheLockingManager implements CacheLockingManager {
// If you update this, also update DefaultGradleDistribution.getArtifactCacheLayoutVersion() (which is the historical record)
- public static final int CACHE_LAYOUT_VERSION = 23;
+ // You should also update LocallyAvailableResourceFinderFactory
+ public static final int CACHE_LAYOUT_VERSION = 26;
private final PersistentCache cache;
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultDependencyResolveDetails.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultDependencyResolveDetails.java
index b8fa9f1..20e7af0 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultDependencyResolveDetails.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultDependencyResolveDetails.java
@@ -24,9 +24,6 @@ import org.gradle.api.internal.artifacts.ivyservice.resolveengine.result.Version
import static org.gradle.api.internal.artifacts.DefaultModuleVersionSelector.newSelector;
-/**
-* by Szczepan Faber, created at: 11/29/12
-*/
public class DefaultDependencyResolveDetails implements DependencyResolveDetailsInternal {
private final ModuleVersionSelector requested;
private ModuleVersionSelectionReason selectionReason;
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultIvyContextManager.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultIvyContextManager.java
new file mode 100644
index 0000000..4d8df3b
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultIvyContextManager.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice;
+
+import org.apache.ivy.Ivy;
+import org.apache.ivy.core.IvyContext;
+import org.apache.ivy.core.settings.IvySettings;
+import org.apache.ivy.util.Message;
+import org.gradle.api.Action;
+import org.gradle.api.Transformer;
+import org.gradle.api.internal.Transformers;
+
+import java.util.LinkedList;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+public class DefaultIvyContextManager implements IvyContextManager {
+ private static final int MAX_CACHED_IVY_INSTANCES = 4;
+ private final Lock lock = new ReentrantLock();
+ private boolean messageAdapterAttached;
+ private final LinkedList<Ivy> cached = new LinkedList<Ivy>();
+ private final ThreadLocal<Integer> depth = new ThreadLocal<Integer>();
+
+ public void withIvy(final Action<? super Ivy> action) {
+ withIvy(Transformers.toTransformer(action));
+ }
+
+ public <T> T withIvy(Transformer<? extends T, ? super Ivy> action) {
+ Integer currentDepth = depth.get();
+
+ if (currentDepth != null) {
+ depth.set(currentDepth + 1);
+ try {
+ return action.transform(IvyContext.getContext().getIvy());
+ } finally {
+ depth.set(currentDepth);
+ }
+ }
+
+ IvyContext.pushNewContext();
+ try {
+ depth.set(1);
+ try {
+ Ivy ivy = getIvy();
+ try {
+ IvyContext.getContext().setIvy(ivy);
+ return action.transform(ivy);
+ } finally {
+ releaseIvy(ivy);
+ }
+ } finally {
+ depth.set(null);
+ }
+ } finally {
+ IvyContext.popContext();
+ }
+ }
+
+ private Ivy getIvy() {
+ lock.lock();
+ try {
+ if (!cached.isEmpty()) {
+ return cached.removeFirst();
+ }
+ if (!messageAdapterAttached) {
+ Message.setDefaultLogger(new IvyLoggingAdaper());
+ messageAdapterAttached = true;
+ }
+ } finally {
+ lock.unlock();
+ }
+ return Ivy.newInstance(new IvySettings());
+ }
+
+ private void releaseIvy(Ivy ivy) {
+ // cleanup
+ ivy.getSettings().getResolvers().clear();
+ ivy.getSettings().setDefaultResolver(null);
+
+ lock.lock();
+ try {
+ if (cached.size() < MAX_CACHED_IVY_INSTANCES) {
+ cached.add(ivy);
+ }
+ // else, throw it away
+ } finally {
+ lock.unlock();
+ }
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultIvyDependencyPublisher.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultIvyDependencyPublisher.java
index 6b78236..3f3fd50 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultIvyDependencyPublisher.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultIvyDependencyPublisher.java
@@ -15,146 +15,82 @@
*/
package org.gradle.api.internal.artifacts.ivyservice;
-import org.apache.ivy.core.IvyContext;
-import org.apache.ivy.core.event.EventManager;
-import org.apache.ivy.core.event.publish.EndArtifactPublishEvent;
-import org.apache.ivy.core.event.publish.StartArtifactPublishEvent;
import org.apache.ivy.core.module.descriptor.Artifact;
+import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor;
import org.apache.ivy.core.module.descriptor.MDArtifact;
-import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
-import org.apache.ivy.plugins.resolver.DependencyResolver;
-import org.apache.ivy.util.ConfigurationUtils;
import org.gradle.api.UncheckedIOException;
+import org.gradle.api.internal.artifacts.DefaultModuleVersionPublishMetaData;
+import org.gradle.api.internal.artifacts.ModuleVersionPublishMetaData;
+import org.gradle.api.internal.artifacts.ModuleVersionPublisher;
import org.gradle.util.DeprecationLogger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
-import java.util.*;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
-/**
- * @author Hans Dockter
- */
public class DefaultIvyDependencyPublisher implements IvyDependencyPublisher {
- public static final String FILE_ABSOLUTE_PATH_EXTRA_ATTRIBUTE = "filePath";
-
private static Logger logger = LoggerFactory.getLogger(DefaultIvyDependencyPublisher.class);
public void publish(Set<String> configurations,
- List<DependencyResolver> publishResolvers,
- ModuleDescriptor moduleDescriptor,
- File descriptorDestination,
- EventManager eventManager) {
+ List<ModuleVersionPublisher> publishResolvers,
+ ModuleVersionPublishMetaData publishMetaData,
+ File descriptorDestination) {
try {
- Publication publication = new Publication(moduleDescriptor, eventManager, configurations, descriptorDestination);
-
- for (DependencyResolver resolver : publishResolvers) {
- logger.info("Publishing to repository {}", resolver);
- publication.publishTo(resolver);
+ Publication publication = new Publication(publishMetaData, descriptorDestination);
+ for (ModuleVersionPublisher publisher : publishResolvers) {
+ logger.info("Publishing to {}", publisher);
+ publisher.publish(publication);
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
- private static class Publication {
- private final ModuleDescriptor moduleDescriptor;
- private final Set<String> configurations;
+ private static class Publication extends DefaultModuleVersionPublishMetaData {
private final File descriptorFile;
- private final EventManager eventManager;
-
- private Publication(ModuleDescriptor moduleDescriptor, EventManager eventManager, Set<String> configurations, File descriptorFile) {
- this.moduleDescriptor = moduleDescriptor;
- this.eventManager = eventManager;
- this.configurations = configurations;
+ private Publication(ModuleVersionPublishMetaData metaData, File descriptorFile) {
+ super((DefaultModuleDescriptor) metaData.getModuleDescriptor());
this.descriptorFile = descriptorFile;
- }
-
- public void publishTo(DependencyResolver resolver) throws IOException {
- Set<Artifact> allArtifacts = getAllArtifacts(moduleDescriptor);
-
- Map<Artifact, File> artifactsFiles = new LinkedHashMap<Artifact, File>();
- for (Artifact artifact : allArtifacts) {
- addPublishedArtifact(artifact, artifactsFiles);
+ for (Map.Entry<Artifact, File> entry : metaData.getArtifacts().entrySet()) {
+ addPublishedArtifact(entry.getKey(), entry.getValue());
}
if (descriptorFile != null) {
- addPublishedDescriptor(artifactsFiles);
- }
-
- boolean successfullyPublished = false;
- try {
- resolver.beginPublishTransaction(moduleDescriptor.getModuleRevisionId(), true);
- // for each declared published artifact in this descriptor, do:
- for (Map.Entry<Artifact, File> entry : artifactsFiles.entrySet()) {
- Artifact artifact = entry.getKey();
- File artifactFile = entry.getValue();
- publish(artifact, artifactFile, resolver, true);
- }
- resolver.commitPublishTransaction();
- successfullyPublished = true;
- } finally {
- if (!successfullyPublished) {
- resolver.abortPublishTransaction();
- }
+ addPublishedDescriptor();
}
}
- private void addPublishedDescriptor(Map<Artifact, File> artifactsFiles) {
- Artifact artifact = MDArtifact.newIvyArtifact(moduleDescriptor);
- checkArtifactFileExists(artifact, descriptorFile);
- artifactsFiles.put(artifact, descriptorFile);
+ private void addPublishedDescriptor() {
+ Artifact artifact = MDArtifact.newIvyArtifact(getModuleDescriptor());
+ if (checkArtifactFileExists(artifact, descriptorFile)) {
+ addArtifact(artifact, descriptorFile);
+ }
}
- private void addPublishedArtifact(Artifact artifact, Map<Artifact, File> artifactsFiles) {
- File artifactFile = new File(artifact.getExtraAttribute(FILE_ABSOLUTE_PATH_EXTRA_ATTRIBUTE));
- checkArtifactFileExists(artifact, artifactFile);
- artifactsFiles.put(artifact, artifactFile);
+ private void addPublishedArtifact(Artifact artifact, File artifactFile) {
+ if (checkArtifactFileExists(artifact, artifactFile)) {
+ addArtifact(artifact, artifactFile);
+ }
}
- private void checkArtifactFileExists(Artifact artifact, File artifactFile) {
- if (!artifactFile.exists()) {
- // TODO:DAZ This hack is required so that we don't log a warning when the Signing plugin is used. We need to allow conditional configurations so we can remove this.
- if (isSigningArtifact(artifact)) {
- return;
- }
+ private boolean checkArtifactFileExists(Artifact artifact, File artifactFile) {
+ if (artifactFile.exists()) {
+ return true;
+ }
+ // TODO:DAZ This hack is required so that we don't log a warning when the Signing plugin is used. We need to allow conditional configurations so we can remove this.
+ if (!isSigningArtifact(artifact)) {
String message = String.format("Attempted to publish an artifact '%s' that does not exist '%s'", artifact.getModuleRevisionId(), artifactFile);
DeprecationLogger.nagUserOfDeprecatedBehaviour(message);
}
+ return false;
}
private boolean isSigningArtifact(Artifact artifact) {
return artifact.getType().endsWith(".asc") || artifact.getType().endsWith(".sig");
}
-
- private Set<Artifact> getAllArtifacts(ModuleDescriptor moduleDescriptor) {
- Set<Artifact> allArtifacts = new LinkedHashSet<Artifact>();
- String[] trueConfigurations = ConfigurationUtils.replaceWildcards(configurations.toArray(new String[configurations.size()]), moduleDescriptor);
- for (String configuration : trueConfigurations) {
- Collections.addAll(allArtifacts, moduleDescriptor.getArtifacts(configuration));
- }
- return allArtifacts;
- }
-
- private void publish(Artifact artifact, File src,
- DependencyResolver resolver, boolean overwrite) throws IOException {
- IvyContext.getContext().checkInterrupted();
- //notify triggers that an artifact is about to be published
- eventManager.fireIvyEvent(
- new StartArtifactPublishEvent(resolver, artifact, src, overwrite));
- boolean successful = false; //set to true once the publish succeeds
- try {
- if (src.exists()) {
- resolver.publish(artifact, src, overwrite);
- successful = true;
- }
- } finally {
- //notify triggers that the publish is finished, successfully or not.
- eventManager.fireIvyEvent(
- new EndArtifactPublishEvent(resolver, artifact, src, overwrite, successful));
- }
- }
}
-
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultIvyFactory.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultIvyFactory.java
deleted file mode 100644
index 7d42d31..0000000
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultIvyFactory.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 2007-2008 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.artifacts.ivyservice;
-
-import org.apache.ivy.Ivy;
-import org.apache.ivy.core.settings.IvySettings;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * @author Hans Dockter
- */
-public class DefaultIvyFactory implements IvyFactory {
- private final Map<IvySettings, Ivy> instanceCache = new HashMap<IvySettings, Ivy>();
-
- public Ivy createIvy(IvySettings ivySettings) {
- Ivy ivy = instanceCache.get(ivySettings);
- if (ivy == null) {
- ivy = Ivy.newInstance(ivySettings);
- instanceCache.put(ivySettings, ivy);
- }
- return ivy;
- }
-}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultLenientConfiguration.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultLenientConfiguration.java
index 1cf335d..e296b08 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultLenientConfiguration.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultLenientConfiguration.java
@@ -16,37 +16,37 @@
package org.gradle.api.internal.artifacts.ivyservice;
import org.gradle.api.artifacts.*;
-import org.gradle.api.internal.CachingDirectedGraphWalker;
-import org.gradle.api.internal.DirectedGraphWithEdgeValues;
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ArtifactResolveException;
+import org.gradle.api.internal.artifacts.ivyservice.resolveengine.oldresult.ResolvedConfigurationResults;
import org.gradle.api.specs.Spec;
+import org.gradle.api.specs.Specs;
+import org.gradle.internal.Factory;
+import org.gradle.internal.graph.CachingDirectedGraphWalker;
+import org.gradle.internal.graph.DirectedGraphWithEdgeValues;
import org.gradle.util.CollectionUtils;
import java.io.File;
import java.util.*;
-public class DefaultLenientConfiguration implements ResolvedConfigurationBuilder, LenientConfiguration {
- private final ResolvedDependency root;
+public class DefaultLenientConfiguration implements LenientConfiguration {
+ private CacheLockingManager cacheLockingManager;
private final Configuration configuration;
- private final Map<ModuleDependency, ResolvedDependency> firstLevelDependencies = new LinkedHashMap<ModuleDependency, ResolvedDependency>();
- private final Set<ResolvedArtifact> artifacts = new LinkedHashSet<ResolvedArtifact>();
- private final Set<UnresolvedDependency> unresolvedDependencies = new LinkedHashSet<UnresolvedDependency>();
- private final CachingDirectedGraphWalker<ResolvedDependency, ResolvedArtifact> walker
- = new CachingDirectedGraphWalker<ResolvedDependency, ResolvedArtifact>(new ResolvedDependencyArtifactsGraph());
+ private ResolvedConfigurationResults results;
- public DefaultLenientConfiguration(Configuration configuration, ResolvedDependency root) {
+ public DefaultLenientConfiguration(Configuration configuration, ResolvedConfigurationResults results, CacheLockingManager cacheLockingManager) {
this.configuration = configuration;
- this.root = root;
+ this.results = results;
+ this.cacheLockingManager = cacheLockingManager;
}
public boolean hasError() {
- return !unresolvedDependencies.isEmpty();
+ return results.hasError();
}
public void rethrowFailure() throws ResolveException {
- if (!unresolvedDependencies.isEmpty()) {
+ if (hasError()) {
List<Throwable> failures = new ArrayList<Throwable>();
- for (UnresolvedDependency unresolvedDependency : unresolvedDependencies) {
+ for (UnresolvedDependency unresolvedDependency : results.getUnresolvedDependencies()) {
failures.add(unresolvedDependency.getProblem());
}
throw new ResolveException(configuration, failures);
@@ -54,36 +54,16 @@ public class DefaultLenientConfiguration implements ResolvedConfigurationBuilder
}
public Set<UnresolvedDependency> getUnresolvedModuleDependencies() {
- return unresolvedDependencies;
+ return results.getUnresolvedDependencies();
}
public Set<ResolvedArtifact> getResolvedArtifacts() throws ResolveException {
- return artifacts;
- }
-
- public ResolvedDependency getRoot() {
- return root;
- }
-
- public void addFirstLevelDependency(ModuleDependency moduleDependency, ResolvedDependency refersTo) {
- firstLevelDependencies.put(moduleDependency, refersTo);
- }
-
- public void addArtifact(ResolvedArtifact artifact) {
- artifacts.add(artifact);
- }
-
- public void addUnresolvedDependency(UnresolvedDependency unresolvedDependency) {
- unresolvedDependencies.add(unresolvedDependency);
- }
-
- public Set<ResolvedDependency> getFirstLevelModuleDependencies() {
- return root.getChildren();
+ return results.getArtifacts();
}
public Set<ResolvedDependency> getFirstLevelModuleDependencies(Spec<? super Dependency> dependencySpec) {
Set<ResolvedDependency> matches = new LinkedHashSet<ResolvedDependency>();
- for (Map.Entry<ModuleDependency, ResolvedDependency> entry : firstLevelDependencies.entrySet()) {
+ for (Map.Entry<ModuleDependency, ResolvedDependency> entry : results.more().getFirstLevelDependencies().entrySet()) {
if (dependencySpec.isSatisfiedBy(entry.getKey())) {
matches.add(entry.getValue());
}
@@ -107,27 +87,35 @@ public class DefaultLenientConfiguration implements ResolvedConfigurationBuilder
* @param dependencySpec dependency spec
*/
public Set<ResolvedArtifact> getArtifacts(Spec<? super Dependency> dependencySpec) {
- Set<ResolvedArtifact> allArtifacts = getAllArtifacts(dependencySpec);
- return CollectionUtils.filter(allArtifacts, new Spec<ResolvedArtifact>() {
- public boolean isSatisfiedBy(ResolvedArtifact element) {
- try {
- File file = element.getFile();
- return file != null;
- } catch (ArtifactResolveException e) {
- return false;
- }
+ final Set<ResolvedArtifact> allArtifacts = getAllArtifacts(dependencySpec);
+ return cacheLockingManager.useCache("retrieve artifacts from " + configuration, new Factory<Set<ResolvedArtifact>>() {
+ public Set<ResolvedArtifact> create() {
+ return CollectionUtils.filter(allArtifacts, new Spec<ResolvedArtifact>() {
+ public boolean isSatisfiedBy(ResolvedArtifact element) {
+ try {
+ File file = element.getFile();
+ return file != null;
+ } catch (ArtifactResolveException e) {
+ return false;
+ }
+ }
+ });
}
});
}
- private Set<File> getFiles(Set<ResolvedArtifact> artifacts) {
- Set<File> files = new LinkedHashSet<File>();
- for (ResolvedArtifact artifact : artifacts) {
- File depFile = artifact.getFile();
- if (depFile != null) {
- files.add(depFile);
+ private Set<File> getFiles(final Set<ResolvedArtifact> artifacts) {
+ final Set<File> files = new LinkedHashSet<File>();
+ cacheLockingManager.useCache("resolve files from " + configuration, new Runnable() {
+ public void run() {
+ for (ResolvedArtifact artifact : artifacts) {
+ File depFile = artifact.getFile();
+ if (depFile != null) {
+ files.add(depFile);
+ }
+ }
}
- }
+ });
return files;
}
@@ -137,12 +125,21 @@ public class DefaultLenientConfiguration implements ResolvedConfigurationBuilder
* @param dependencySpec dependency spec
*/
public Set<ResolvedArtifact> getAllArtifacts(Spec<? super Dependency> dependencySpec) {
+ //this is not very nice might be good enough until we get rid of ResolvedConfiguration and friends
+ //avoid traversing the graph causing the full ResolvedDependency graph to be loaded for the most typical scenario
+ if (dependencySpec == Specs.SATISFIES_ALL) {
+ return results.getArtifacts();
+ }
+
+ CachingDirectedGraphWalker<ResolvedDependency, ResolvedArtifact> walker
+ = new CachingDirectedGraphWalker<ResolvedDependency, ResolvedArtifact>(new ResolvedDependencyArtifactsGraph());
+
Set<ResolvedDependency> firstLevelModuleDependencies = getFirstLevelModuleDependencies(dependencySpec);
Set<ResolvedArtifact> artifacts = new LinkedHashSet<ResolvedArtifact>();
for (ResolvedDependency resolvedDependency : firstLevelModuleDependencies) {
- artifacts.addAll(resolvedDependency.getParentArtifacts(root));
+ artifacts.addAll(resolvedDependency.getParentArtifacts(results.more().getRoot()));
walker.add(resolvedDependency);
}
@@ -154,9 +151,13 @@ public class DefaultLenientConfiguration implements ResolvedConfigurationBuilder
return configuration;
}
+ public Set<ResolvedDependency> getFirstLevelModuleDependencies() {
+ return results.more().getRoot().getChildren();
+ }
+
private static class ResolvedDependencyArtifactsGraph implements DirectedGraphWithEdgeValues<ResolvedDependency, ResolvedArtifact> {
- public void getNodeValues(ResolvedDependency node, Collection<ResolvedArtifact> values,
- Collection<ResolvedDependency> connectedNodes) {
+ public void getNodeValues(ResolvedDependency node, Collection<? super ResolvedArtifact> values,
+ Collection<? super ResolvedDependency> connectedNodes) {
connectedNodes.addAll(node.getChildren());
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultResolvedConfiguration.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultResolvedConfiguration.java
index a0869af..146ccbe 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultResolvedConfiguration.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultResolvedConfiguration.java
@@ -17,20 +17,15 @@ package org.gradle.api.internal.artifacts.ivyservice;
import org.gradle.api.artifacts.*;
import org.gradle.api.specs.Spec;
-import org.gradle.internal.Factory;
import java.io.File;
import java.util.Set;
-import static java.lang.String.format;
-
public class DefaultResolvedConfiguration implements ResolvedConfiguration {
private final DefaultLenientConfiguration configuration;
- private final CacheLockingManager cacheLockingManager;
- public DefaultResolvedConfiguration(DefaultLenientConfiguration configuration, CacheLockingManager cacheLockingManager) {
+ public DefaultResolvedConfiguration(DefaultLenientConfiguration configuration) {
this.configuration = configuration;
- this.cacheLockingManager = cacheLockingManager;
}
public boolean hasError() {
@@ -47,11 +42,7 @@ public class DefaultResolvedConfiguration implements ResolvedConfiguration {
public Set<File> getFiles(final Spec<? super Dependency> dependencySpec) throws ResolveException {
rethrowFailure();
- return cacheLockingManager.useCache(format("resolving files from %s", configuration.getConfiguration()), new Factory<Set<File>>() {
- public Set<File> create() {
- return configuration.getFilesStrict(dependencySpec);
- }
- });
+ return configuration.getFilesStrict(dependencySpec);
}
public Set<ResolvedDependency> getFirstLevelModuleDependencies() throws ResolveException {
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultSettingsConverter.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultSettingsConverter.java
deleted file mode 100644
index 4c37d0b..0000000
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultSettingsConverter.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.artifacts.ivyservice;
-
-import org.apache.ivy.core.settings.IvySettings;
-import org.apache.ivy.plugins.resolver.DependencyResolver;
-import org.apache.ivy.util.Message;
-import org.gradle.internal.Factory;
-
-import java.util.List;
-
-/**
- * @author Hans Dockter
- */
-public class DefaultSettingsConverter implements SettingsConverter {
- private final Factory<IvySettings> settingsFactory;
- private IvySettings publishSettings;
- private IvySettings resolveSettings;
-
- public DefaultSettingsConverter(Factory<IvySettings> settingsFactory) {
- this.settingsFactory = settingsFactory;
- Message.setDefaultLogger(new IvyLoggingAdaper());
- }
-
- public IvySettings convertForPublish(List<DependencyResolver> publishResolvers) {
- if (publishSettings == null) {
- publishSettings = settingsFactory.create();
- } else {
- publishSettings.getResolvers().clear();
- }
- for (DependencyResolver dependencyResolver : publishResolvers) {
- dependencyResolver.setSettings(publishSettings);
- }
- return publishSettings;
- }
-
- public IvySettings convertForResolve(DependencyResolver defaultResolver) {
- if (resolveSettings == null) {
- resolveSettings = settingsFactory.create();
- } else {
- resolveSettings.getResolvers().clear();
- }
-
- resolveSettings.addResolver(defaultResolver);
- resolveSettings.setDefaultResolver(defaultResolver.getName());
-
- return resolveSettings;
- }
-
- public IvySettings getForResolve() {
- if (resolveSettings == null) {
- resolveSettings = settingsFactory.create();
- }
- return resolveSettings;
- }
-}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DependencyToModuleResolver.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DependencyToModuleResolver.java
deleted file mode 100755
index 73b9c3d..0000000
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DependencyToModuleResolver.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.artifacts.ivyservice;
-
-import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.DependencyMetaData;
-
-/**
- * Resolves a dependency to the meta-data for a module.
- */
-public interface DependencyToModuleResolver {
- /**
- * Resolves the given dependency to a module version id. Failures are packaged up in the returned result.
- */
- void resolve(DependencyMetaData dependency, BuildableModuleVersionResolveResult result);
-}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DependencyToModuleVersionResolver.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DependencyToModuleVersionResolver.java
new file mode 100755
index 0000000..d4fc489
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/DependencyToModuleVersionResolver.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice;
+
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.DependencyMetaData;
+
+/**
+ * Resolves a dependency to the meta-data for a module.
+ */
+public interface DependencyToModuleVersionResolver {
+ /**
+ * Resolves the given dependency to a module version id. Failures are packaged up in the returned result.
+ */
+ void resolve(DependencyMetaData dependency, BuildableModuleVersionResolveResult result);
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ErrorHandlingArtifactDependencyResolver.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ErrorHandlingArtifactDependencyResolver.java
index 444809a..915315f 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ErrorHandlingArtifactDependencyResolver.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ErrorHandlingArtifactDependencyResolver.java
@@ -15,7 +15,12 @@
*/
package org.gradle.api.internal.artifacts.ivyservice;
+import groovy.lang.Closure;
+import org.gradle.api.Action;
import org.gradle.api.artifacts.*;
+import org.gradle.api.artifacts.result.DependencyResult;
+import org.gradle.api.artifacts.result.ResolutionResult;
+import org.gradle.api.artifacts.result.ResolvedModuleVersionResult;
import org.gradle.api.internal.artifacts.ArtifactDependencyResolver;
import org.gradle.api.internal.artifacts.ResolverResults;
import org.gradle.api.internal.artifacts.configurations.ConfigurationInternal;
@@ -40,8 +45,9 @@ public class ErrorHandlingArtifactDependencyResolver implements ArtifactDependen
} catch (final Throwable e) {
return new ResolverResults(new BrokenResolvedConfiguration(e, configuration), wrapException(e, configuration));
}
- ResolvedConfiguration withErrorHandling = new ErrorHandlingResolvedConfiguration(results.getResolvedConfiguration(), configuration);
- return results.withResolvedConfiguration(withErrorHandling);
+ ResolvedConfiguration wrappedConfiguration = new ErrorHandlingResolvedConfiguration(results.getResolvedConfiguration(), configuration);
+ ResolutionResult wrappedResult = new ErrorHandlingResolutionResult(results.getResolutionResult(), configuration);
+ return new ResolverResults(wrappedConfiguration, wrappedResult);
}
private static ResolveException wrapException(Throwable e, Configuration configuration) {
@@ -51,6 +57,98 @@ public class ErrorHandlingArtifactDependencyResolver implements ArtifactDependen
return new ResolveException(configuration, e);
}
+ private static class ErrorHandlingLenientConfiguration implements LenientConfiguration {
+ private final LenientConfiguration lenientConfiguration;
+ private final Configuration configuration;
+
+ private ErrorHandlingLenientConfiguration(LenientConfiguration lenientConfiguration, Configuration configuration) {
+ this.lenientConfiguration = lenientConfiguration;
+ this.configuration = configuration;
+ }
+
+ public Set<ResolvedArtifact> getArtifacts(Spec<? super Dependency> dependencySpec) {
+ try {
+ return lenientConfiguration.getArtifacts(dependencySpec);
+ } catch (Throwable e) {
+ throw wrapException(e, configuration);
+ }
+ }
+
+ public Set<ResolvedDependency> getFirstLevelModuleDependencies(Spec<? super Dependency> dependencySpec) {
+ try {
+ return lenientConfiguration.getFirstLevelModuleDependencies(dependencySpec);
+ } catch (Throwable e) {
+ throw wrapException(e, configuration);
+ }
+ }
+
+ public Set<UnresolvedDependency> getUnresolvedModuleDependencies() {
+ try {
+ return lenientConfiguration.getUnresolvedModuleDependencies();
+ } catch (Throwable e) {
+ throw wrapException(e, configuration);
+ }
+ }
+
+ public Set<File> getFiles(Spec<? super Dependency> dependencySpec) {
+ try {
+ return lenientConfiguration.getFiles(dependencySpec);
+ } catch (Throwable e) {
+ throw wrapException(e, configuration);
+ }
+ }
+ }
+
+ private static class ErrorHandlingResolutionResult implements ResolutionResult {
+ private final ResolutionResult resolutionResult;
+ private final Configuration configuration;
+
+ public ErrorHandlingResolutionResult(ResolutionResult resolutionResult, Configuration configuration) {
+ this.resolutionResult = resolutionResult;
+ this.configuration = configuration;
+ }
+
+ public ResolvedModuleVersionResult getRoot() {
+ try {
+ return resolutionResult.getRoot();
+ } catch (Throwable e) {
+ throw wrapException(e, configuration);
+ }
+ }
+
+ public void allDependencies(Action<? super DependencyResult> action) {
+ resolutionResult.allDependencies(action);
+ }
+
+ public Set<? extends DependencyResult> getAllDependencies() {
+ try {
+ return resolutionResult.getAllDependencies();
+ } catch (Throwable e) {
+ throw wrapException(e, configuration);
+ }
+ }
+
+ public void allDependencies(Closure closure) {
+ resolutionResult.allDependencies(closure);
+ }
+
+ public Set<ResolvedModuleVersionResult> getAllModuleVersions() {
+ try {
+ return resolutionResult.getAllModuleVersions();
+ } catch (Throwable e) {
+ throw wrapException(e, configuration);
+ }
+ }
+
+ public void allModuleVersions(Action<? super ResolvedModuleVersionResult> action) {
+ resolutionResult.allModuleVersions(action);
+ }
+
+ public void allModuleVersions(Closure closure) {
+ resolutionResult.allModuleVersions(closure);
+ }
+ }
+
private static class ErrorHandlingResolvedConfiguration implements ResolvedConfiguration {
private final ResolvedConfiguration resolvedConfiguration;
private final Configuration configuration;
@@ -66,7 +164,11 @@ public class ErrorHandlingArtifactDependencyResolver implements ArtifactDependen
}
public LenientConfiguration getLenientConfiguration() {
- return resolvedConfiguration.getLenientConfiguration();
+ try {
+ return new ErrorHandlingLenientConfiguration(resolvedConfiguration.getLenientConfiguration(), configuration);
+ } catch (Throwable e) {
+ throw wrapException(e, configuration);
+ }
}
public void rethrowFailure() throws ResolveException {
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/IvyBackedArtifactPublisher.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/IvyBackedArtifactPublisher.java
index f34fe63..82daa44 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/IvyBackedArtifactPublisher.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/IvyBackedArtifactPublisher.java
@@ -16,11 +16,14 @@
package org.gradle.api.internal.artifacts.ivyservice;
import org.apache.ivy.Ivy;
-import org.apache.ivy.plugins.resolver.DependencyResolver;
+import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
+import org.gradle.api.Action;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.Module;
import org.gradle.api.artifacts.PublishException;
import org.gradle.api.internal.artifacts.ArtifactPublisher;
+import org.gradle.api.internal.artifacts.ModuleVersionPublishMetaData;
+import org.gradle.api.internal.artifacts.ModuleVersionPublisher;
import org.gradle.api.internal.artifacts.configurations.Configurations;
import org.gradle.api.internal.artifacts.repositories.PublicationAwareRepository;
@@ -29,42 +32,47 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Set;
-/**
- * @author Hans Dockter
- */
public class IvyBackedArtifactPublisher implements ArtifactPublisher {
- private final SettingsConverter settingsConverter;
private final ModuleDescriptorConverter publishModuleDescriptorConverter;
- private final IvyFactory ivyFactory;
+ private final IvyContextManager ivyContextManager;
private final IvyDependencyPublisher dependencyPublisher;
+ private final IvyModuleDescriptorWriter ivyModuleDescriptorWriter;
- public IvyBackedArtifactPublisher(SettingsConverter settingsConverter,
- ModuleDescriptorConverter publishModuleDescriptorConverter,
- IvyFactory ivyFactory,
- IvyDependencyPublisher dependencyPublisher) {
- this.settingsConverter = settingsConverter;
+ public IvyBackedArtifactPublisher(ModuleDescriptorConverter publishModuleDescriptorConverter,
+ IvyContextManager ivyContextManager,
+ IvyDependencyPublisher dependencyPublisher,
+ IvyModuleDescriptorWriter ivyModuleDescriptorWriter) {
this.publishModuleDescriptorConverter = publishModuleDescriptorConverter;
- this.ivyFactory = ivyFactory;
+ this.ivyContextManager = ivyContextManager;
this.dependencyPublisher = dependencyPublisher;
+ this.ivyModuleDescriptorWriter = ivyModuleDescriptorWriter;
}
- private Ivy ivyForPublish(List<DependencyResolver> publishResolvers) {
- return ivyFactory.createIvy(settingsConverter.convertForPublish(publishResolvers));
- }
+ public void publish(final Iterable<? extends PublicationAwareRepository> repositories, final Module module, final Set<? extends Configuration> configurations, final File descriptor) throws PublishException {
+ ivyContextManager.withIvy(new Action<Ivy>() {
+ public void execute(Ivy ivy) {
+ Set<Configuration> allConfigurations = configurations.iterator().next().getAll();
+ ModuleVersionPublishMetaData publishMetaData = publishModuleDescriptorConverter.convert(allConfigurations, module);
+ if (descriptor != null) {
+ ModuleDescriptor moduleDescriptor = publishMetaData.getModuleDescriptor();
+ ivyModuleDescriptorWriter.write(moduleDescriptor, descriptor);
+ }
- public void publish(Iterable<? extends PublicationAwareRepository> repositories, Module module, Set<? extends Configuration> configurations, File descriptor) throws PublishException {
- List<DependencyResolver> publishResolvers = new ArrayList<DependencyResolver>();
- for (PublicationAwareRepository repository : repositories) {
- publishResolvers.add(repository.createPublisher());
- }
- Ivy ivy = ivyForPublish(publishResolvers);
- Set<String> confs = Configurations.getNames(configurations, false);
- dependencyPublisher.publish(
- confs,
- publishResolvers,
- publishModuleDescriptorConverter.convert(configurations, module),
- descriptor,
- ivy.getEventManager());
- }
+ List<ModuleVersionPublisher> publishResolvers = new ArrayList<ModuleVersionPublisher>();
+ for (PublicationAwareRepository repository : repositories) {
+ ModuleVersionPublisher publisher = repository.createPublisher();
+ publisher.setSettings(ivy.getSettings());
+ publishResolvers.add(publisher);
+ }
+ publishMetaData = publishModuleDescriptorConverter.convert(configurations, module);
+ Set<String> confs = Configurations.getNames(configurations, false);
+ dependencyPublisher.publish(
+ confs,
+ publishResolvers,
+ publishMetaData,
+ descriptor);
+ }
+ });
+ }
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/IvyContextManager.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/IvyContextManager.java
new file mode 100644
index 0000000..660f384
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/IvyContextManager.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice;
+
+import net.jcip.annotations.ThreadSafe;
+import org.apache.ivy.Ivy;
+import org.gradle.api.Action;
+import org.gradle.api.Transformer;
+
+ at ThreadSafe
+public interface IvyContextManager {
+ /**
+ * Executes the given action against an Ivy instance. Sets up the Ivy context before the action and cleans up at the end.
+ *
+ * <p>The Ivy instance of the calling thread is reused if the thread is already executing an action against an Ivy instance.
+ */
+ void withIvy(Action<? super Ivy> action);
+
+ /**
+ * Executes the given action against an Ivy instance and returns the result. Sets up the Ivy context before the action and cleans up at the end.
+ *
+ * <p>The Ivy instance of the calling thread is reused if the thread is already executing an action against an Ivy instance.
+ */
+ <T> T withIvy(Transformer<? extends T, ? super Ivy> action);
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/IvyDependencyPublisher.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/IvyDependencyPublisher.java
index 650127c..5618332 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/IvyDependencyPublisher.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/IvyDependencyPublisher.java
@@ -15,20 +15,16 @@
*/
package org.gradle.api.internal.artifacts.ivyservice;
-import org.apache.ivy.core.event.EventManager;
-import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
-import org.apache.ivy.plugins.resolver.DependencyResolver;
+import org.gradle.api.internal.artifacts.ModuleVersionPublishMetaData;
+import org.gradle.api.internal.artifacts.ModuleVersionPublisher;
import java.io.File;
import java.util.List;
import java.util.Set;
-/**
- * @author Hans Dockter
- */
public interface IvyDependencyPublisher {
void publish(Set<String> configurations,
- List<DependencyResolver> publishResolvers,
- ModuleDescriptor moduleDescriptor,
- File descriptorDestination, EventManager eventManager);
+ List<ModuleVersionPublisher> publishResolvers,
+ ModuleVersionPublishMetaData publishMetaData,
+ File descriptorDestination);
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/IvyFactory.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/IvyFactory.java
deleted file mode 100644
index 4dfc079..0000000
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/IvyFactory.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2007-2008 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.artifacts.ivyservice;
-
-import org.apache.ivy.Ivy;
-import org.apache.ivy.core.settings.IvySettings;
-
-/**
- * @author Hans Dockter
- */
-public interface IvyFactory {
- public Ivy createIvy(IvySettings ivySettings);
-}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/IvyLoggingAdaper.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/IvyLoggingAdaper.java
index 3daaaff..d072a42 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/IvyLoggingAdaper.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/IvyLoggingAdaper.java
@@ -24,8 +24,6 @@ import org.gradle.api.logging.Logging;
* logback. This would be bad for embedded usage. We only want one on slf4j. But slf4j has no constants for log levels.
* As we want to avoid the execution of if statements for each Ivy request, we use Map which delegates Ivy log
* statements to Sl4j action classes.
- *
- * @author Hans Dockter
*/
public class IvyLoggingAdaper extends AbstractMessageLogger {
private final Logger logger = Logging.getLogger(IvyLoggingAdaper.class);
@@ -38,6 +36,22 @@ public class IvyLoggingAdaper extends AbstractMessageLogger {
log(msg, level);
}
+ /**
+ * Overrides the default implementation, which doesn't delegate to {@link #log(String, int)}.
+ */
+ @Override
+ public void warn(String msg) {
+ logger.warn(msg);
+ }
+
+ /**
+ * Overrides the default implementation, which doesn't delegate to {@link #log(String, int)}.
+ */
+ @Override
+ public void error(String msg) {
+ logger.error(msg);
+ }
+
public void doProgress() {
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/IvyModuleDescriptorWriter.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/IvyModuleDescriptorWriter.java
similarity index 100%
rename from subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/IvyModuleDescriptorWriter.java
rename to subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/IvyModuleDescriptorWriter.java
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/IvyResolverBackedModuleVersionPublisher.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/IvyResolverBackedModuleVersionPublisher.java
new file mode 100644
index 0000000..0bc8126
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/IvyResolverBackedModuleVersionPublisher.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice;
+
+import org.apache.ivy.core.module.descriptor.Artifact;
+import org.apache.ivy.core.module.id.ModuleRevisionId;
+import org.apache.ivy.core.settings.IvySettings;
+import org.apache.ivy.plugins.resolver.DependencyResolver;
+import org.gradle.api.artifacts.ModuleVersionIdentifier;
+import org.gradle.api.internal.artifacts.ModuleVersionPublishMetaData;
+import org.gradle.api.internal.artifacts.ModuleVersionPublisher;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Map;
+
+public class IvyResolverBackedModuleVersionPublisher implements ModuleVersionPublisher {
+ private final DependencyResolver resolver;
+
+ public IvyResolverBackedModuleVersionPublisher(DependencyResolver resolver) {
+ this.resolver = resolver;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("repository '%s'", resolver.getName());
+ }
+
+ public void setSettings(IvySettings settings) {
+ settings.addResolver(resolver);
+ }
+
+ public void publish(ModuleVersionPublishMetaData moduleVersion) throws IOException {
+ boolean successfullyPublished = false;
+ try {
+ ModuleVersionIdentifier id = moduleVersion.getId();
+ ModuleRevisionId ivyId = ModuleRevisionId.newInstance(id.getGroup(), id.getName(), id.getVersion());
+ resolver.beginPublishTransaction(ivyId, true);
+ for (Map.Entry<Artifact, File> entry : moduleVersion.getArtifacts().entrySet()) {
+ Artifact artifact = entry.getKey();
+ File artifactFile = entry.getValue();
+ resolver.publish(artifact, artifactFile, true);
+ }
+ resolver.commitPublishTransaction();
+ successfullyPublished = true;
+ } finally {
+ if (!successfullyPublished) {
+ resolver.abortPublishTransaction();
+ }
+ }
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/IvySettingsFactory.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/IvySettingsFactory.java
deleted file mode 100644
index 11f49c3..0000000
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/IvySettingsFactory.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.artifacts.ivyservice;
-
-import org.apache.ivy.core.settings.IvySettings;
-import org.gradle.api.artifacts.ArtifactRepositoryContainer;
-import org.gradle.internal.Factory;
-
-import java.io.File;
-
-public class IvySettingsFactory implements Factory<IvySettings> {
- private final ArtifactCacheMetaData cacheMetaData;
-
- public IvySettingsFactory(ArtifactCacheMetaData cacheMetaData) {
- this.cacheMetaData = cacheMetaData;
- }
-
- public IvySettings create() {
- IvySettings ivySettings = new IvySettings();
- ivySettings.setDefaultCache(new File(cacheMetaData.getCacheDir(), "ivy"));
- ivySettings.setDefaultCacheIvyPattern(ArtifactRepositoryContainer.DEFAULT_CACHE_IVY_PATTERN);
- ivySettings.setDefaultCacheArtifactPattern(ArtifactRepositoryContainer.DEFAULT_CACHE_ARTIFACT_PATTERN);
- ivySettings.setVariable("ivy.log.modules.in.use", "false");
-
- return ivySettings;
- }
-}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/IvyUtil.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/IvyUtil.java
index 856cd82..3ae7cc2 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/IvyUtil.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/IvyUtil.java
@@ -23,9 +23,6 @@ import org.gradle.util.GUtil;
import java.util.HashMap;
import java.util.Map;
-/**
- * @author Hans Dockter
- */
public class IvyUtil {
public static ModuleRevisionId createModuleRevisionId(Module module) {
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/IvyXmlModuleDescriptorWriter.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/IvyXmlModuleDescriptorWriter.java
index 50bcbf7..66bf56c 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/IvyXmlModuleDescriptorWriter.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/IvyXmlModuleDescriptorWriter.java
@@ -20,7 +20,6 @@ import org.apache.ivy.core.IvyPatternHelper;
import org.apache.ivy.core.module.descriptor.*;
import org.apache.ivy.core.module.id.ModuleRevisionId;
import org.apache.ivy.plugins.matcher.MapMatcher;
-import org.apache.ivy.util.Message;
import org.apache.ivy.util.StringUtils;
import org.apache.ivy.util.XMLHelper;
import org.apache.ivy.util.extendable.ExtendableItem;
@@ -28,6 +27,8 @@ import org.gradle.api.Action;
import org.gradle.api.internal.ErroringAction;
import org.gradle.api.internal.IoActions;
import org.gradle.util.TextUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
@@ -38,6 +39,7 @@ import java.util.Iterator;
import java.util.Map;
public class IvyXmlModuleDescriptorWriter implements IvyModuleDescriptorWriter {
+ private static final Logger LOGGER = LoggerFactory.getLogger(IvyXmlModuleDescriptorWriter.class);
public static final String IVY_DATE_PATTERN = "yyyyMMddHHmmss";
@@ -205,8 +207,7 @@ public class IvyXmlModuleDescriptorWriter implements IvyModuleDescriptorWriter {
writer.write("/>");
writer.write(TextUtil.getPlatformLineSeparator());
} else {
- Message.verbose("ignoring unhandled DependencyDescriptorMediator: "
- + mediator.getClass());
+ LOGGER.debug("Ignoring unhandled DependencyDescriptorMediator: {}", mediator.getClass());
}
}
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ModuleDescriptorConverter.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ModuleDescriptorConverter.java
new file mode 100644
index 0000000..d2bcb49
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ModuleDescriptorConverter.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2007-2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice;
+
+import org.gradle.api.artifacts.Configuration;
+import org.gradle.api.artifacts.Module;
+import org.gradle.api.internal.artifacts.ModuleVersionPublishMetaData;
+
+import java.util.Set;
+
+public interface ModuleDescriptorConverter {
+ ModuleVersionPublishMetaData convert(Set<? extends Configuration> configurations, Module module);
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ModuleToModuleVersionResolver.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ModuleToModuleVersionResolver.java
new file mode 100755
index 0000000..c492d04
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ModuleToModuleVersionResolver.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice;
+
+import org.gradle.api.artifacts.Configuration;
+import org.gradle.api.artifacts.Module;
+
+import java.util.Set;
+
+/**
+ * Resolves a module to the meta-data for a module.
+ */
+public interface ModuleToModuleVersionResolver {
+ void resolve(Module module, Set<? extends Configuration> configurations, BuildableModuleVersionResolveResult result);
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ModuleVersionResolveException.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ModuleVersionResolveException.java
index a6a78c9..b991555 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ModuleVersionResolveException.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ModuleVersionResolveException.java
@@ -30,7 +30,7 @@ import java.util.List;
@Contextual
public class ModuleVersionResolveException extends AbstractMultiCauseException {
- private final List<List<ModuleRevisionId>> paths = new ArrayList<List<ModuleRevisionId>>();
+ private final List<List<ModuleVersionIdentifier>> paths = new ArrayList<List<ModuleVersionIdentifier>>();
private final String messageFormat;
private final ModuleVersionSelector selector;
@@ -81,7 +81,7 @@ public class ModuleVersionResolveException extends AbstractMultiCauseException {
/**
* Creates a copy of this exception, with the given incoming paths.
*/
- public ModuleVersionResolveException withIncomingPaths(Collection<? extends List<ModuleRevisionId>> paths) {
+ public ModuleVersionResolveException withIncomingPaths(Collection<? extends List<ModuleVersionIdentifier>> paths) {
ModuleVersionResolveException copy = createCopy();
copy.paths.addAll(paths);
copy.initCauses(getCauses());
@@ -96,7 +96,7 @@ public class ModuleVersionResolveException extends AbstractMultiCauseException {
}
Formatter formatter = new Formatter();
formatter.format("%s%nRequired by:", super.getMessage());
- for (List<ModuleRevisionId> path : paths) {
+ for (List<ModuleVersionIdentifier> path : paths) {
formatter.format("%n %s", toString(path.get(0)));
for (int i = 1; i < path.size(); i++) {
formatter.format(" > %s", toString(path.get(i)));
@@ -105,8 +105,8 @@ public class ModuleVersionResolveException extends AbstractMultiCauseException {
return formatter.toString();
}
- private String toString(ModuleRevisionId moduleRevisionId) {
- return String.format("%s:%s:%s", moduleRevisionId.getOrganisation(), moduleRevisionId.getName(), moduleRevisionId.getRevision());
+ private String toString(ModuleVersionIdentifier identifier) {
+ return identifier.toString();
}
protected ModuleVersionResolveException createCopy() {
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ResolvedArtifactFactory.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ResolvedArtifactFactory.java
index 5b5b951..4f49714 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ResolvedArtifactFactory.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ResolvedArtifactFactory.java
@@ -15,32 +15,38 @@
*/
package org.gradle.api.internal.artifacts.ivyservice;
+import org.apache.ivy.Ivy;
import org.apache.ivy.core.module.descriptor.Artifact;
-import org.gradle.api.artifacts.ResolvedArtifact;
-import org.gradle.api.artifacts.ResolvedDependency;
-import org.gradle.api.internal.artifacts.DefaultResolvedArtifact;
+import org.gradle.api.Transformer;
import org.gradle.internal.Factory;
import java.io.File;
+//TODO SF rename
public class ResolvedArtifactFactory {
private final CacheLockingManager lockingManager;
+ private final IvyContextManager ivyContextManager;
- public ResolvedArtifactFactory(CacheLockingManager lockingManager) {
+ public ResolvedArtifactFactory(CacheLockingManager lockingManager, IvyContextManager ivyContextManager) {
this.lockingManager = lockingManager;
+ this.ivyContextManager = ivyContextManager;
}
- public ResolvedArtifact create(ResolvedDependency owner, final Artifact artifact, final ArtifactResolver resolver) {
- return new DefaultResolvedArtifact(owner, artifact, new Factory<File>() {
+ public Factory<File> artifactSource(final Artifact artifact, final ArtifactResolver resolver) {
+ return new Factory<File>() {
public File create() {
- return lockingManager.useCache(String.format("download %s", artifact), new Factory<File>() {
+ return lockingManager.useCache(String.format("resolve %s", artifact), new Factory<File>() {
public File create() {
- DefaultBuildableArtifactResolveResult result = new DefaultBuildableArtifactResolveResult();
- resolver.resolve(artifact, result);
- return result.getFile();
+ return ivyContextManager.withIvy(new Transformer<File, Ivy>() {
+ public File transform(Ivy original) {
+ DefaultBuildableArtifactResolveResult result = new DefaultBuildableArtifactResolveResult();
+ resolver.resolve(artifact, result);
+ return result.getFile();
+ }
+ });
}
});
}
- });
+ };
}
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ResolvedConfigurationBuilder.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ResolvedConfigurationBuilder.java
deleted file mode 100644
index 1ecee6c..0000000
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ResolvedConfigurationBuilder.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.artifacts.ivyservice;
-
-import org.gradle.api.artifacts.ModuleDependency;
-import org.gradle.api.artifacts.ResolvedArtifact;
-import org.gradle.api.artifacts.ResolvedDependency;
-import org.gradle.api.artifacts.UnresolvedDependency;
-
-public interface ResolvedConfigurationBuilder {
- void addArtifact(ResolvedArtifact artifact);
-
- void addFirstLevelDependency(ModuleDependency moduleDependency, ResolvedDependency dependency);
-
- void addUnresolvedDependency(UnresolvedDependency unresolvedDependency);
-
- ResolvedDependency getRoot();
-}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/SettingsConverter.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/SettingsConverter.java
deleted file mode 100644
index 877ffde..0000000
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/SettingsConverter.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2007-2008 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.artifacts.ivyservice;
-
-import org.apache.ivy.core.settings.IvySettings;
-import org.apache.ivy.plugins.resolver.DependencyResolver;
-
-import java.util.List;
-
-/**
- * @author Hans Dockter
- */
-public interface SettingsConverter {
- String LOOPBACK_RESOLVER_NAME = "main";
-
- IvySettings convertForPublish(List<DependencyResolver> publishResolvers);
-
- IvySettings convertForResolve(DependencyResolver defaultResolver);
-
- IvySettings getForResolve();
-}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ShortcircuitEmptyConfigsArtifactDependencyResolver.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ShortcircuitEmptyConfigsArtifactDependencyResolver.java
index f7820c0..622d18b 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ShortcircuitEmptyConfigsArtifactDependencyResolver.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ShortcircuitEmptyConfigsArtifactDependencyResolver.java
@@ -16,13 +16,13 @@
package org.gradle.api.internal.artifacts.ivyservice;
import org.gradle.api.artifacts.*;
+import org.gradle.api.artifacts.result.ResolutionResult;
import org.gradle.api.internal.artifacts.ArtifactDependencyResolver;
import org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier;
import org.gradle.api.internal.artifacts.ResolverResults;
import org.gradle.api.internal.artifacts.configurations.ConfigurationInternal;
import org.gradle.api.internal.artifacts.ivyservice.resolveengine.result.ResolutionResultBuilder;
import org.gradle.api.internal.artifacts.repositories.ResolutionAwareRepository;
-import org.gradle.api.internal.artifacts.result.DefaultResolutionResult;
import org.gradle.api.specs.Spec;
import java.io.File;
@@ -40,7 +40,7 @@ public class ShortcircuitEmptyConfigsArtifactDependencyResolver implements Artif
public ResolverResults resolve(ConfigurationInternal configuration, List<? extends ResolutionAwareRepository> repositories) throws ResolveException {
if (configuration.getAllDependencies().isEmpty()) {
ModuleVersionIdentifier id = DefaultModuleVersionIdentifier.newId(configuration.getModule());
- DefaultResolutionResult emptyResult = new ResolutionResultBuilder().start(id).getResult();
+ ResolutionResult emptyResult = new ResolutionResultBuilder().start(id).complete();
return new ResolverResults(new EmptyResolvedConfiguration(), emptyResult);
}
return dependencyResolver.resolve(configuration, repositories);
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/SubstitutedModuleVersionIdResolveResult.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/SubstitutedModuleVersionIdResolveResult.java
index 8971b89..9e49c53 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/SubstitutedModuleVersionIdResolveResult.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/SubstitutedModuleVersionIdResolveResult.java
@@ -19,9 +19,6 @@ package org.gradle.api.internal.artifacts.ivyservice;
import org.gradle.api.artifacts.ModuleVersionIdentifier;
import org.gradle.api.artifacts.result.ModuleVersionSelectionReason;
-/**
- * by Szczepan Faber, created at: 8/29/12
- */
class SubstitutedModuleVersionIdResolveResult implements ModuleVersionIdResolveResult {
final ModuleVersionIdResolveResult result;
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/clientmodule/ClientModuleResolver.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/clientmodule/ClientModuleResolver.java
index cbf202d..999b705 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/clientmodule/ClientModuleResolver.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/clientmodule/ClientModuleResolver.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2009 the original author or authors.
+ * Copyright 2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,17 +19,14 @@ package org.gradle.api.internal.artifacts.ivyservice.clientmodule;
import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
import org.gradle.api.internal.artifacts.ivyservice.BuildableModuleVersionResolveResult;
-import org.gradle.api.internal.artifacts.ivyservice.DependencyToModuleResolver;
+import org.gradle.api.internal.artifacts.ivyservice.DependencyToModuleVersionResolver;
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.DependencyMetaData;
import org.gradle.api.internal.artifacts.ivyservice.moduleconverter.dependencies.ClientModuleDependencyDescriptor;
-/**
- * @author Hans Dockter
- */
-public class ClientModuleResolver implements DependencyToModuleResolver {
- private final DependencyToModuleResolver resolver;
+public class ClientModuleResolver implements DependencyToModuleVersionResolver {
+ private final DependencyToModuleVersionResolver resolver;
- public ClientModuleResolver(DependencyToModuleResolver resolver) {
+ public ClientModuleResolver(DependencyToModuleVersionResolver resolver) {
this.resolver = resolver;
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/dynamicversions/DefaultCachedModuleResolution.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/dynamicversions/DefaultCachedModuleResolution.java
index 2a3f3da..661e4d1 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/dynamicversions/DefaultCachedModuleResolution.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/dynamicversions/DefaultCachedModuleResolution.java
@@ -15,18 +15,17 @@
*/
package org.gradle.api.internal.artifacts.ivyservice.dynamicversions;
-import org.apache.ivy.core.module.id.ModuleRevisionId;
import org.gradle.api.artifacts.ModuleVersionIdentifier;
-import org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier;
+import org.gradle.api.artifacts.ModuleVersionSelector;
import org.gradle.internal.TimeProvider;
class DefaultCachedModuleResolution implements ModuleResolutionCache.CachedModuleResolution {
- private final ModuleVersionIdentifier requestedVersion;
+ private final ModuleVersionSelector requestedVersion;
private final ModuleVersionIdentifier resolvedVersion;
private final long ageMillis;
- public DefaultCachedModuleResolution(ModuleRevisionId requestedVersion, ModuleResolutionCacheEntry entry, TimeProvider timeProvider) {
- this.requestedVersion = new DefaultModuleVersionIdentifier(requestedVersion.getOrganisation(), requestedVersion.getName(), requestedVersion.getRevision());
+ public DefaultCachedModuleResolution(ModuleVersionSelector requestedVersion, ModuleResolutionCacheEntry entry, TimeProvider timeProvider) {
+ this.requestedVersion = requestedVersion;
this.resolvedVersion = entry.moduleVersionIdentifier;
ageMillis = timeProvider.getCurrentTime() - entry.createTimestamp;
}
@@ -40,6 +39,6 @@ class DefaultCachedModuleResolution implements ModuleResolutionCache.CachedModul
}
public boolean isDynamicVersion() {
- return !requestedVersion.equals(resolvedVersion);
+ return !requestedVersion.matchesStrictly(resolvedVersion);
}
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/dynamicversions/DefaultResolvedModuleVersion.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/dynamicversions/DefaultResolvedModuleVersion.java
index 706f4a1..30068d4 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/dynamicversions/DefaultResolvedModuleVersion.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/dynamicversions/DefaultResolvedModuleVersion.java
@@ -15,19 +15,17 @@
*/
package org.gradle.api.internal.artifacts.ivyservice.dynamicversions;
-import org.apache.ivy.core.module.id.ModuleRevisionId;
import org.gradle.api.artifacts.ModuleVersionIdentifier;
import org.gradle.api.artifacts.ResolvedModuleVersion;
-import org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier;
public class DefaultResolvedModuleVersion implements ResolvedModuleVersion {
- private final ModuleRevisionId moduleRevisionId;
+ private final ModuleVersionIdentifier identifier;
- public DefaultResolvedModuleVersion(ModuleRevisionId moduleRevisionId) {
- this.moduleRevisionId = moduleRevisionId;
+ public DefaultResolvedModuleVersion(ModuleVersionIdentifier identifier) {
+ this.identifier = identifier;
}
public ModuleVersionIdentifier getId() {
- return new DefaultModuleVersionIdentifier(moduleRevisionId.getOrganisation(), moduleRevisionId.getName(), moduleRevisionId.getRevision());
+ return identifier;
}
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/dynamicversions/ModuleResolutionCache.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/dynamicversions/ModuleResolutionCache.java
index ed9717f..b5eb4a6 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/dynamicversions/ModuleResolutionCache.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/dynamicversions/ModuleResolutionCache.java
@@ -15,15 +15,15 @@
*/
package org.gradle.api.internal.artifacts.ivyservice.dynamicversions;
-import org.apache.ivy.core.module.id.ModuleRevisionId;
import org.gradle.api.artifacts.ModuleVersionIdentifier;
+import org.gradle.api.artifacts.ModuleVersionSelector;
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ModuleVersionRepository;
public interface ModuleResolutionCache {
- void cacheModuleResolution(ModuleVersionRepository repository, ModuleRevisionId dynamicVersion, ModuleVersionIdentifier moduleVersionIdentifier);
+ void cacheModuleResolution(ModuleVersionRepository repository, ModuleVersionSelector requestedVersion, ModuleVersionIdentifier resolvedVersion);
- CachedModuleResolution getCachedModuleResolution(ModuleVersionRepository repository, ModuleRevisionId dynamicVersion);
+ CachedModuleResolution getCachedModuleResolution(ModuleVersionRepository repository, ModuleVersionSelector requestedVersion);
interface CachedModuleResolution {
ModuleVersionIdentifier getResolvedVersion();
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/dynamicversions/SingleFileBackedModuleResolutionCache.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/dynamicversions/SingleFileBackedModuleResolutionCache.java
index 5aa0bac..064ad09 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/dynamicversions/SingleFileBackedModuleResolutionCache.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/dynamicversions/SingleFileBackedModuleResolutionCache.java
@@ -15,19 +15,22 @@
*/
package org.gradle.api.internal.artifacts.ivyservice.dynamicversions;
-import org.apache.ivy.core.module.id.ModuleRevisionId;
import org.gradle.api.artifacts.ModuleVersionIdentifier;
+import org.gradle.api.artifacts.ModuleVersionSelector;
+import org.gradle.api.internal.artifacts.DefaultModuleVersionSelector;
import org.gradle.api.internal.artifacts.ModuleVersionIdentifierSerializer;
import org.gradle.api.internal.artifacts.ivyservice.ArtifactCacheMetaData;
import org.gradle.api.internal.artifacts.ivyservice.CacheLockingManager;
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ModuleVersionRepository;
import org.gradle.cache.PersistentIndexedCache;
import org.gradle.internal.TimeProvider;
-import org.gradle.messaging.serialize.DataStreamBackedSerializer;
+import org.gradle.messaging.serialize.Decoder;
+import org.gradle.messaging.serialize.Encoder;
+import org.gradle.messaging.serialize.Serializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.*;
+import java.io.File;
public class SingleFileBackedModuleResolutionCache implements ModuleResolutionCache {
private static final Logger LOGGER = LoggerFactory.getLogger(SingleFileBackedModuleResolutionCache.class);
@@ -55,25 +58,25 @@ public class SingleFileBackedModuleResolutionCache implements ModuleResolutionCa
return cacheLockingManager.createCache(dynamicRevisionsFile, new RevisionKeySerializer(), new ModuleResolutionCacheEntrySerializer());
}
- public void cacheModuleResolution(ModuleVersionRepository repository, ModuleRevisionId requestedVersion, ModuleVersionIdentifier moduleVersionIdentifier) {
- if (requestedVersion.equals(moduleVersionIdentifier)) {
+ public void cacheModuleResolution(ModuleVersionRepository repository, ModuleVersionSelector requestedVersion, ModuleVersionIdentifier resolvedVersion) {
+ if (requestedVersion.matchesStrictly(resolvedVersion)) {
return;
}
- LOGGER.debug("Caching resolved revision in dynamic revision cache: Will use '{}' for '{}'", moduleVersionIdentifier, requestedVersion);
- getCache().put(createKey(repository, requestedVersion), createEntry(moduleVersionIdentifier));
+ LOGGER.debug("Caching resolved revision in dynamic revision cache: Will use '{}' for '{}'", resolvedVersion, requestedVersion);
+ getCache().put(createKey(repository, requestedVersion), createEntry(resolvedVersion));
}
- public CachedModuleResolution getCachedModuleResolution(ModuleVersionRepository repository, ModuleRevisionId moduleId) {
- ModuleResolutionCacheEntry moduleResolutionCacheEntry = getCache().get(createKey(repository, moduleId));
+ public CachedModuleResolution getCachedModuleResolution(ModuleVersionRepository repository, ModuleVersionSelector requestedVersion) {
+ ModuleResolutionCacheEntry moduleResolutionCacheEntry = getCache().get(createKey(repository, requestedVersion));
if (moduleResolutionCacheEntry == null) {
return null;
}
- return new DefaultCachedModuleResolution(moduleId, moduleResolutionCacheEntry, timeProvider);
+ return new DefaultCachedModuleResolution(requestedVersion, moduleResolutionCacheEntry, timeProvider);
}
- private RevisionKey createKey(ModuleVersionRepository repository, ModuleRevisionId revisionId) {
- return new RevisionKey(repository.getId(), revisionId.encodeToString());
+ private RevisionKey createKey(ModuleVersionRepository repository, ModuleVersionSelector requestedVersion) {
+ return new RevisionKey(repository.getId(), requestedVersion);
}
private ModuleResolutionCacheEntry createEntry(ModuleVersionIdentifier moduleVersionIdentifier) {
@@ -82,11 +85,11 @@ public class SingleFileBackedModuleResolutionCache implements ModuleResolutionCa
private static class RevisionKey {
private final String repositoryId;
- private final String revisionId;
+ private final ModuleVersionSelector requestedVersion;
- private RevisionKey(String repositoryId, String revisionId) {
+ private RevisionKey(String repositoryId, ModuleVersionSelector requestedVersion) {
this.repositoryId = repositoryId;
- this.revisionId = revisionId;
+ this.requestedVersion = requestedVersion;
}
@Override
@@ -95,43 +98,43 @@ public class SingleFileBackedModuleResolutionCache implements ModuleResolutionCa
return false;
}
RevisionKey other = (RevisionKey) o;
- return repositoryId.equals(other.repositoryId) && revisionId.equals(other.revisionId);
+ return repositoryId.equals(other.repositoryId) && requestedVersion.equals(other.requestedVersion);
}
@Override
public int hashCode() {
- return repositoryId.hashCode() ^ revisionId.hashCode();
+ return repositoryId.hashCode() ^ requestedVersion.hashCode();
}
}
- private static class RevisionKeySerializer extends DataStreamBackedSerializer<RevisionKey> {
- @Override
- public void write(DataOutput dataOutput, RevisionKey value) throws IOException {
- dataOutput.writeUTF(value.repositoryId);
- dataOutput.writeUTF(value.revisionId);
+ private static class RevisionKeySerializer implements Serializer<RevisionKey> {
+ public void write(Encoder encoder, RevisionKey value) throws Exception {
+ encoder.writeString(value.repositoryId);
+ encoder.writeString(value.requestedVersion.getGroup());
+ encoder.writeString(value.requestedVersion.getName());
+ encoder.writeString(value.requestedVersion.getVersion());
}
- @Override
- public RevisionKey read(DataInput dataInput) throws IOException {
- String resolverId = dataInput.readUTF();
- String revisionId = dataInput.readUTF();
- return new RevisionKey(resolverId, revisionId);
+ public RevisionKey read(Decoder decoder) throws Exception {
+ String resolverId = decoder.readString();
+ String group = decoder.readString();
+ String module = decoder.readString();
+ String version = decoder.readString();
+ return new RevisionKey(resolverId, DefaultModuleVersionSelector.newSelector(group, module, version));
}
}
- private static class ModuleResolutionCacheEntrySerializer extends DataStreamBackedSerializer<ModuleResolutionCacheEntry> {
+ private static class ModuleResolutionCacheEntrySerializer implements Serializer<ModuleResolutionCacheEntry> {
private final ModuleVersionIdentifierSerializer identifierSerializer = new ModuleVersionIdentifierSerializer();
- @Override
- public void write(DataOutput dataOutput, ModuleResolutionCacheEntry value) throws IOException {
- identifierSerializer.write(dataOutput, value.moduleVersionIdentifier);
- dataOutput.writeLong(value.createTimestamp);
+ public void write(Encoder encoder, ModuleResolutionCacheEntry value) throws Exception {
+ identifierSerializer.write(encoder, value.moduleVersionIdentifier);
+ encoder.writeLong(value.createTimestamp);
}
- @Override
- public ModuleResolutionCacheEntry read(DataInput dataInput) throws IOException {
- ModuleVersionIdentifier identifier = identifierSerializer.read(dataInput);
- long createTimestamp = dataInput.readLong();
+ public ModuleResolutionCacheEntry read(Decoder decoder) throws Exception {
+ ModuleVersionIdentifier identifier = identifierSerializer.read(decoder);
+ long createTimestamp = decoder.readLong();
return new ModuleResolutionCacheEntry(identifier, createTimestamp);
}
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/AbstractDependencyResolverAdapter.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/AbstractDependencyResolverAdapter.java
deleted file mode 100644
index 9280823..0000000
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/AbstractDependencyResolverAdapter.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve;
-
-import org.apache.ivy.core.settings.IvySettings;
-import org.apache.ivy.plugins.resolver.DependencyResolver;
-import org.gradle.api.internal.artifacts.repositories.cachemanager.LocalFileRepositoryCacheManager;
-
-public abstract class AbstractDependencyResolverAdapter implements IvyAwareModuleVersionRepository {
- private final DependencyResolverIdentifier identifier;
- protected final DependencyResolver resolver;
-
- public AbstractDependencyResolverAdapter(DependencyResolver resolver) {
- this.identifier = new DependencyResolverIdentifier(resolver);
- this.resolver = resolver;
- }
-
- public String getId() {
- return identifier.getUniqueId();
- }
-
- public String getName() {
- return identifier.getName();
- }
-
- @Override
- public String toString() {
- return String.format("Repository '%s'", resolver.getName());
- }
-
- public void setSettings(IvySettings settings) {
- settings.addResolver(resolver);
- }
-
- public boolean isDynamicResolveMode() {
- return false;
- }
-
- public boolean isLocal() {
- return resolver.getRepositoryCacheManager() instanceof LocalFileRepositoryCacheManager;
- }
-}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/ArtifactNotFoundException.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/ArtifactNotFoundException.java
index 902334b..76ed48b 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/ArtifactNotFoundException.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/ArtifactNotFoundException.java
@@ -15,14 +15,14 @@
*/
package org.gradle.api.internal.artifacts.ivyservice.ivyresolve;
-import org.apache.ivy.core.module.descriptor.Artifact;
+import org.gradle.api.artifacts.ArtifactIdentifier;
public class ArtifactNotFoundException extends ArtifactResolveException {
- public ArtifactNotFoundException(Artifact artifact) {
+ public ArtifactNotFoundException(ArtifactIdentifier artifact) {
super(format(artifact));
}
- private static String format(Artifact artifact) {
+ private static String format(ArtifactIdentifier artifact) {
StringBuilder builder = new StringBuilder();
builder.append("Artifact '");
formatTo(artifact, builder);
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/ArtifactResolveException.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/ArtifactResolveException.java
index 778e9a7..5e36a52 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/ArtifactResolveException.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/ArtifactResolveException.java
@@ -16,9 +16,11 @@
package org.gradle.api.internal.artifacts.ivyservice.ivyresolve;
import org.apache.ivy.core.module.descriptor.Artifact;
-import org.apache.ivy.core.module.id.ModuleRevisionId;
import org.gradle.api.GradleException;
+import org.gradle.api.artifacts.ArtifactIdentifier;
+import org.gradle.api.artifacts.ModuleVersionIdentifier;
import org.gradle.api.internal.Contextual;
+import org.gradle.api.internal.artifacts.DefaultArtifactIdentifier;
import org.gradle.util.GUtil;
@Contextual
@@ -28,14 +30,18 @@ public class ArtifactResolveException extends GradleException {
}
public ArtifactResolveException(Artifact artifact, Throwable cause) {
+ this(new DefaultArtifactIdentifier(artifact), cause);
+ }
+
+ public ArtifactResolveException(ArtifactIdentifier artifact, Throwable cause) {
super(format(artifact, ""), cause);
}
- public ArtifactResolveException(Artifact artifact, String message) {
+ public ArtifactResolveException(ArtifactIdentifier artifact, String message) {
super(format(artifact, message));
}
- private static String format(Artifact artifact, String message) {
+ private static String format(ArtifactIdentifier artifact, String message) {
StringBuilder builder = new StringBuilder();
builder.append("Could not download artifact '");
formatTo(artifact, builder);
@@ -47,15 +53,15 @@ public class ArtifactResolveException extends GradleException {
return builder.toString();
}
- protected static void formatTo(Artifact artifact, StringBuilder builder) {
- ModuleRevisionId moduleRevisionId = artifact.getModuleRevisionId();
- builder.append(moduleRevisionId.getOrganisation())
- .append(":").append(moduleRevisionId.getName())
- .append(":").append(moduleRevisionId.getRevision());
- String classifier = artifact.getExtraAttribute("classifier");
+ protected static void formatTo(ArtifactIdentifier artifact, StringBuilder builder) {
+ ModuleVersionIdentifier moduleVersion = artifact.getModuleVersionIdentifier();
+ builder.append(moduleVersion.getGroup())
+ .append(":").append(moduleVersion.getName())
+ .append(":").append(moduleVersion.getVersion());
+ String classifier = artifact.getClassifier();
if (GUtil.isTrue(classifier)) {
builder.append(":").append(classifier);
}
- builder.append("@").append(artifact.getExt());
+ builder.append("@").append(artifact.getExtension());
}
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/BuildableModuleVersionMetaData.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/BuildableModuleVersionMetaData.java
deleted file mode 100644
index f731d7d..0000000
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/BuildableModuleVersionMetaData.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve;
-
-import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
-import org.gradle.api.Nullable;
-import org.gradle.api.artifacts.ModuleVersionIdentifier;
-import org.gradle.api.internal.artifacts.ivyservice.ModuleVersionResolveException;
-
-/**
- * The result of attempting to resolve a dependency descriptor to the meta-data for a module version.
- *
- * TODO - detach this from ModuleVersionMetaData, so that it has-a instead of is-a.
- */
-public interface BuildableModuleVersionMetaData extends ModuleVersionMetaData {
- enum State {
- Resolved, Missing, Failed, ProbablyMissing, Unknown
- }
-
- /**
- * Returns the current state of this descriptor.
- */
- State getState();
-
- @Nullable
- ModuleVersionResolveException getFailure();
-
- /**
- * Marks the module version as resolved, with the given meta-data.
- */
- void resolved(ModuleDescriptor descriptor, boolean changing, ModuleSource moduleSource);
-
- /**
- * Marks the module version as resolved, with the given meta-data.
- */
- void resolved(ModuleVersionIdentifier id, ModuleDescriptor descriptor, boolean changing, ModuleSource moduleSource);
-
- /**
- * Marks the resolve as failed with the given exception.
- */
- void failed(ModuleVersionResolveException failure);
-
- /**
- * Marks the module version as definitely missing.
- */
- void missing();
-
- /**
- * Marks the module version as probably missing.
- */
- void probablyMissing();
-
- /**
- * The repository-specific source for this module version.
- */
- public ModuleSource getModuleSource();
-
- void setModuleSource(ModuleSource moduleSource);
-
- /**
- * Replaces the dependencies of this module version.
- */
- void setDependencies(Iterable<? extends DependencyMetaData> dependencies);
-}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/BuildableModuleVersionMetaDataResolveResult.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/BuildableModuleVersionMetaDataResolveResult.java
new file mode 100644
index 0000000..c2ae2a1
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/BuildableModuleVersionMetaDataResolveResult.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve;
+
+import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
+import org.gradle.api.Nullable;
+import org.gradle.api.artifacts.ModuleVersionIdentifier;
+import org.gradle.api.internal.artifacts.ivyservice.ModuleVersionResolveException;
+
+/**
+ * The result of attempting to resolve a dependency descriptor to the meta-data for a module version.
+ */
+public interface BuildableModuleVersionMetaDataResolveResult {
+ static enum State {
+ Resolved, Missing, Failed, ProbablyMissing, Unknown
+ }
+
+ /**
+ * Returns the current state of this descriptor.
+ */
+ State getState();
+
+ /**
+ * Returns the meta-data.
+ *
+ * @throws ModuleVersionResolveException If the resolution was not successful.
+ */
+ ModuleVersionMetaData getMetaData() throws ModuleVersionResolveException;
+
+ @Nullable
+ ModuleVersionResolveException getFailure();
+
+ /**
+ * Marks the module version as resolved, with the given meta-data.
+ */
+ void resolved(ModuleDescriptor descriptor, boolean changing, ModuleSource moduleSource);
+
+ /**
+ * Marks the module version as resolved, with the given meta-data.
+ */
+ void resolved(ModuleVersionIdentifier id, ModuleDescriptor descriptor, boolean changing, ModuleSource moduleSource);
+
+ /**
+ * Marks the resolve as failed with the given exception.
+ */
+ void failed(ModuleVersionResolveException failure);
+
+ /**
+ * Marks the module version as definitely missing.
+ */
+ void missing();
+
+ /**
+ * Marks the module version as probably missing.
+ */
+ void probablyMissing();
+
+ /**
+ * The repository-specific source for this module version.
+ */
+ public ModuleSource getModuleSource();
+
+ void setModuleSource(ModuleSource moduleSource);
+
+ /**
+ * Replaces the dependencies of this module version.
+ */
+ void setDependencies(Iterable<? extends DependencyMetaData> dependencies);
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/CacheLockingModuleVersionRepository.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/CacheLockingModuleVersionRepository.java
index 514cced..d392459 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/CacheLockingModuleVersionRepository.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/CacheLockingModuleVersionRepository.java
@@ -15,7 +15,7 @@
*/
package org.gradle.api.internal.artifacts.ivyservice.ivyresolve;
-import org.apache.ivy.core.module.descriptor.Artifact;
+import org.gradle.api.artifacts.ArtifactIdentifier;
import org.gradle.api.internal.artifacts.ivyservice.BuildableArtifactResolveResult;
import org.gradle.api.internal.artifacts.ivyservice.CacheLockingManager;
@@ -39,7 +39,7 @@ public class CacheLockingModuleVersionRepository implements ModuleVersionReposit
return repository.getName();
}
- public void getDependency(final DependencyMetaData dependency, final BuildableModuleVersionMetaData result) {
+ public void getDependency(final DependencyMetaData dependency, final BuildableModuleVersionMetaDataResolveResult result) {
cacheLockingManager.longRunningOperation(String.format("Resolve %s using repository %s", dependency, getId()), new Runnable() {
public void run() {
repository.getDependency(dependency, result);
@@ -47,7 +47,7 @@ public class CacheLockingModuleVersionRepository implements ModuleVersionReposit
});
}
- public void resolve(final Artifact artifact, final BuildableArtifactResolveResult result, final ModuleSource moduleSource) {
+ public void resolve(final ArtifactIdentifier artifact, final BuildableArtifactResolveResult result, final ModuleSource moduleSource) {
cacheLockingManager.longRunningOperation(String.format("Download %s using repository %s", artifact, getId()), new Runnable() {
public void run() {
repository.resolve(artifact, result, moduleSource);
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/CachingModuleVersionRepository.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/CachingModuleVersionRepository.java
index 8b82cb5..37bccb6 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/CachingModuleVersionRepository.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/CachingModuleVersionRepository.java
@@ -15,16 +15,15 @@
*/
package org.gradle.api.internal.artifacts.ivyservice.ivyresolve;
-import org.apache.ivy.core.module.descriptor.Artifact;
import org.apache.ivy.core.module.id.ModuleRevisionId;
import org.gradle.api.artifacts.ArtifactIdentifier;
import org.gradle.api.artifacts.ModuleVersionIdentifier;
import org.gradle.api.artifacts.ModuleVersionSelector;
-import org.gradle.api.internal.artifacts.DefaultArtifactIdentifier;
import org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier;
import org.gradle.api.internal.artifacts.DefaultModuleVersionSelector;
import org.gradle.api.internal.artifacts.configurations.dynamicversion.CachePolicy;
import org.gradle.api.internal.artifacts.ivyservice.BuildableArtifactResolveResult;
+import org.gradle.api.internal.artifacts.ivyservice.DependencyToModuleVersionResolver;
import org.gradle.api.internal.artifacts.ivyservice.dynamicversions.ModuleResolutionCache;
import org.gradle.api.internal.artifacts.ivyservice.modulecache.ModuleDescriptorCache;
import org.gradle.api.internal.externalresource.cached.CachedArtifact;
@@ -37,12 +36,15 @@ import org.slf4j.LoggerFactory;
import java.io.File;
import java.math.BigInteger;
+import static org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier.newId;
+
public class CachingModuleVersionRepository implements LocalAwareModuleVersionRepository {
private static final Logger LOGGER = LoggerFactory.getLogger(CachingModuleVersionRepository.class);
private final ModuleResolutionCache moduleResolutionCache;
private final ModuleDescriptorCache moduleDescriptorCache;
private final CachedArtifactIndex artifactAtRepositoryCachedResolutionIndex;
+ private final DependencyToModuleVersionResolver resolver;
private final CachePolicy cachePolicy;
@@ -51,11 +53,13 @@ public class CachingModuleVersionRepository implements LocalAwareModuleVersionRe
public CachingModuleVersionRepository(ModuleVersionRepository delegate, ModuleResolutionCache moduleResolutionCache, ModuleDescriptorCache moduleDescriptorCache,
CachedArtifactIndex artifactAtRepositoryCachedResolutionIndex,
+ DependencyToModuleVersionResolver resolver,
CachePolicy cachePolicy, TimeProvider timeProvider) {
this.delegate = delegate;
this.moduleDescriptorCache = moduleDescriptorCache;
this.moduleResolutionCache = moduleResolutionCache;
this.artifactAtRepositoryCachedResolutionIndex = artifactAtRepositoryCachedResolutionIndex;
+ this.resolver = resolver;
this.timeProvider = timeProvider;
this.cachePolicy = cachePolicy;
}
@@ -73,24 +77,25 @@ public class CachingModuleVersionRepository implements LocalAwareModuleVersionRe
return "Caching " + delegate.toString();
}
- public void getLocalDependency(DependencyMetaData dependency, BuildableModuleVersionMetaData result) {
+ public void getLocalDependency(DependencyMetaData dependency, BuildableModuleVersionMetaDataResolveResult result) {
DependencyMetaData resolvedDependency = maybeUseCachedDynamicVersion(delegate, dependency);
lookupModuleInCache(delegate, resolvedDependency, result);
}
- public void getDependency(DependencyMetaData dependency, BuildableModuleVersionMetaData result) {
+ public void getDependency(DependencyMetaData dependency, BuildableModuleVersionMetaDataResolveResult result) {
DependencyMetaData forced = dependency.withChanging();
delegate.getDependency(forced, result);
switch (result.getState()) {
case Missing:
final ModuleRevisionId dependencyRevisionId = dependency.getDescriptor().getDependencyRevisionId();
- final DefaultModuleVersionIdentifier moduleVersionIdentifier = new DefaultModuleVersionIdentifier(dependencyRevisionId.getOrganisation(), dependencyRevisionId.getName(), dependencyRevisionId.getRevision());
+ final ModuleVersionIdentifier moduleVersionIdentifier = DefaultModuleVersionIdentifier.newId(dependencyRevisionId);
moduleDescriptorCache.cacheModuleDescriptor(delegate, moduleVersionIdentifier, null, null, dependency.isChanging());
break;
case Resolved:
- moduleResolutionCache.cacheModuleResolution(delegate, dependency.getDescriptor().getDependencyRevisionId(), result.getId());
+ ModuleVersionMetaData metaData = result.getMetaData();
+ moduleResolutionCache.cacheModuleResolution(delegate, dependency.getRequested(), metaData.getId());
final ModuleSource moduleSource = result.getModuleSource();
- final ModuleDescriptorCache.CachedModuleDescriptor cachedModuleDescriptor = moduleDescriptorCache.cacheModuleDescriptor(delegate, result.getId(), result.getDescriptor(), moduleSource, isChangingDependency(dependency, result));
+ final ModuleDescriptorCache.CachedModuleDescriptor cachedModuleDescriptor = moduleDescriptorCache.cacheModuleDescriptor(delegate, metaData.getId(), metaData.getDescriptor(), moduleSource, isChangingDependency(dependency, metaData));
result.setModuleSource(new CachingModuleSource(cachedModuleDescriptor.getDescriptorHash(), cachedModuleDescriptor.isChangingModule(), moduleSource));
break;
case Failed:
@@ -101,26 +106,25 @@ public class CachingModuleVersionRepository implements LocalAwareModuleVersionRe
}
private DependencyMetaData maybeUseCachedDynamicVersion(ModuleVersionRepository repository, DependencyMetaData original) {
- ModuleRevisionId originalId = original.getDescriptor().getDependencyRevisionId();
- ModuleResolutionCache.CachedModuleResolution cachedModuleResolution = moduleResolutionCache.getCachedModuleResolution(repository, originalId);
+ ModuleVersionSelector requested = original.getRequested();
+ ModuleResolutionCache.CachedModuleResolution cachedModuleResolution = moduleResolutionCache.getCachedModuleResolution(repository, requested);
if (cachedModuleResolution != null && cachedModuleResolution.isDynamicVersion()) {
- ModuleVersionSelector selector = createModuleVersionSelector(originalId);
ModuleVersionIdentifier resolvedVersion = cachedModuleResolution.getResolvedVersion();
- if (cachePolicy.mustRefreshDynamicVersion(selector, resolvedVersion, cachedModuleResolution.getAgeMillis())) {
- LOGGER.debug("Resolved revision in dynamic revision cache is expired: will perform fresh resolve of '{}' in '{}'", selector, repository.getName());
+ if (cachePolicy.mustRefreshDynamicVersion(requested, resolvedVersion, cachedModuleResolution.getAgeMillis())) {
+ LOGGER.debug("Resolved revision in dynamic revision cache is expired: will perform fresh resolve of '{}' in '{}'", requested, repository.getName());
return original;
} else {
- LOGGER.debug("Found resolved revision in dynamic revision cache of '{}': Using '{}' for '{}'", repository.getName(), cachedModuleResolution.getResolvedVersion(), originalId);
+ LOGGER.debug("Found resolved revision in dynamic revision cache of '{}': Using '{}' for '{}'", repository.getName(), cachedModuleResolution.getResolvedVersion(), requested);
return original.withRequestedVersion(DefaultModuleVersionSelector.newSelector(resolvedVersion.getGroup(), resolvedVersion.getName(), resolvedVersion.getVersion()));
}
}
return original;
}
- public void lookupModuleInCache(ModuleVersionRepository repository, DependencyMetaData dependency, BuildableModuleVersionMetaData result) {
+ public void lookupModuleInCache(ModuleVersionRepository repository, DependencyMetaData dependency, BuildableModuleVersionMetaDataResolveResult result) {
ModuleRevisionId resolvedModuleVersionId = dependency.getDescriptor().getDependencyRevisionId();
- ModuleVersionIdentifier moduleVersionIdentifier = createModuleVersionIdentifier(resolvedModuleVersionId);
- ModuleDescriptorCache.CachedModuleDescriptor cachedModuleDescriptor = moduleDescriptorCache.getCachedModuleDescriptor(repository, moduleVersionIdentifier);
+ ModuleVersionIdentifier moduleVersionIdentifier = newId(resolvedModuleVersionId);
+ ModuleDescriptorCache.CachedModuleDescriptor cachedModuleDescriptor = moduleDescriptorCache.getCachedModuleDescriptor(repository, moduleVersionIdentifier, resolver);
if (cachedModuleDescriptor == null) {
return;
}
@@ -163,26 +167,25 @@ public class CachingModuleVersionRepository implements LocalAwareModuleVersionRe
return downloadedModule.isChanging();
}
- public void resolve(Artifact artifact, BuildableArtifactResolveResult result, ModuleSource moduleSource) {
- ArtifactAtRepositoryKey resolutionCacheIndexKey = new ArtifactAtRepositoryKey(delegate, artifact.getId());
+ public void resolve(ArtifactIdentifier artifact, BuildableArtifactResolveResult result, ModuleSource moduleSource) {
+ ArtifactAtRepositoryKey resolutionCacheIndexKey = new ArtifactAtRepositoryKey(delegate.getId(), artifact);
// Look in the cache for this resolver
CachedArtifact cached = artifactAtRepositoryCachedResolutionIndex.lookup(resolutionCacheIndexKey);
final CachingModuleSource cachedModuleSource = (CachingModuleSource) moduleSource;
final BigInteger descriptorHash = cachedModuleSource.getDescriptorHash();
if (cached != null) {
- ArtifactIdentifier artifactIdentifier = createArtifactIdentifier(artifact);
long age = timeProvider.getCurrentTime() - cached.getCachedAt();
final boolean isChangingModule = cachedModuleSource.isChangingModule();
if (cached.isMissing()) {
- if (!cachePolicy.mustRefreshArtifact(artifactIdentifier, null, age, isChangingModule, descriptorHash.equals(cached.getDescriptorHash()))) {
- LOGGER.debug("Detected non-existence of artifact '{}' in resolver cache", artifact.getId());
+ if (!cachePolicy.mustRefreshArtifact(artifact, null, age, isChangingModule, descriptorHash.equals(cached.getDescriptorHash()))) {
+ LOGGER.debug("Detected non-existence of artifact '{}' in resolver cache", artifact);
result.notFound(artifact);
return;
}
} else {
File cachedArtifactFile = cached.getCachedFile();
- if (!cachePolicy.mustRefreshArtifact(artifactIdentifier, cachedArtifactFile, age, isChangingModule, descriptorHash.equals(cached.getDescriptorHash()))) {
- LOGGER.debug("Found artifact '{}' in resolver cache: {}", artifact.getId(), cachedArtifactFile);
+ if (!cachePolicy.mustRefreshArtifact(artifact, cachedArtifactFile, age, isChangingModule, descriptorHash.equals(cached.getDescriptorHash()))) {
+ LOGGER.debug("Found artifact '{}' in resolver cache: {}", artifact, cachedArtifactFile);
result.resolved(cachedArtifactFile);
return;
}
@@ -190,7 +193,7 @@ public class CachingModuleVersionRepository implements LocalAwareModuleVersionRe
}
delegate.resolve(artifact, result, cachedModuleSource.getDelegate());
- LOGGER.debug("Downloaded artifact '{}' from resolver: {}", artifact.getId(), delegate);
+ LOGGER.debug("Downloaded artifact '{}' from resolver: {}", artifact, delegate.getName());
if (result.getFailure() instanceof ArtifactNotFoundException) {
artifactAtRepositoryCachedResolutionIndex.storeMissing(resolutionCacheIndexKey, descriptorHash);
@@ -199,19 +202,6 @@ public class CachingModuleVersionRepository implements LocalAwareModuleVersionRe
}
}
- private ModuleVersionSelector createModuleVersionSelector(ModuleRevisionId moduleRevisionId) {
- return new DefaultModuleVersionSelector(moduleRevisionId.getOrganisation(), moduleRevisionId.getName(), moduleRevisionId.getRevision());
- }
-
- private ModuleVersionIdentifier createModuleVersionIdentifier(ModuleRevisionId moduleRevisionId) {
- return new DefaultModuleVersionIdentifier(moduleRevisionId.getOrganisation(), moduleRevisionId.getName(), moduleRevisionId.getRevision());
- }
-
- private ArtifactIdentifier createArtifactIdentifier(Artifact artifact) {
- ModuleVersionIdentifier moduleVersionIdentifier = createModuleVersionIdentifier(artifact.getModuleRevisionId());
- return new DefaultArtifactIdentifier(moduleVersionIdentifier, artifact.getName(), artifact.getType(), artifact.getExt(), artifact.getExtraAttribute("classifier"));
- }
-
static class CachingModuleSource implements ModuleSource {
private final BigInteger descriptorHash;
private final boolean changingModule;
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/ConfigurationMetaData.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/ConfigurationMetaData.java
new file mode 100644
index 0000000..5e04a64
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/ConfigurationMetaData.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve;
+
+import org.apache.ivy.core.module.descriptor.Artifact;
+import org.apache.ivy.core.module.descriptor.ExcludeRule;
+
+import java.util.List;
+import java.util.Set;
+
+public interface ConfigurationMetaData {
+ /**
+ * The set of configurations that this configuration extends. Includes this configuration.
+ */
+ Set<String> getHierarchy();
+
+ String getName();
+
+ ModuleVersionMetaData getModuleVersion();
+
+ List<DependencyMetaData> getDependencies();
+
+ Set<Artifact> getArtifacts();
+
+ Set<ExcludeRule> getExcludeRules();
+
+ boolean isTransitive();
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/ConfiguredModuleVersionRepository.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/ConfiguredModuleVersionRepository.java
new file mode 100644
index 0000000..57cdd62
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/ConfiguredModuleVersionRepository.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve;
+
+public interface ConfiguredModuleVersionRepository extends ModuleVersionRepository {
+ boolean isDynamicResolveMode();
+
+ boolean isLocal();
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/DefaultBuildableModuleVersionMetaData.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/DefaultBuildableModuleVersionMetaData.java
deleted file mode 100644
index ec67ca1..0000000
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/DefaultBuildableModuleVersionMetaData.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve;
-
-import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
-import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
-import org.apache.ivy.core.module.id.ModuleRevisionId;
-import org.gradle.api.artifacts.ModuleVersionIdentifier;
-import org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier;
-import org.gradle.api.internal.artifacts.ivyservice.ModuleVersionResolveException;
-import org.gradle.util.CollectionUtils;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class DefaultBuildableModuleVersionMetaData implements BuildableModuleVersionMetaData {
- private ModuleDescriptor moduleDescriptor;
- private boolean changing;
- private State state = State.Unknown;
- private ModuleSource moduleSource;
- private List<DependencyMetaData> dependencies;
- private ModuleVersionResolveException failure;
- private ModuleVersionIdentifier moduleVersionIdentifier;
-
- public void reset(State state) {
- this.state = state;
- moduleDescriptor = null;
- changing = false;
- failure = null;
- }
-
- public void resolved(ModuleDescriptor descriptor, boolean changing, ModuleSource moduleSource) {
- ModuleRevisionId moduleRevisionId = descriptor.getModuleRevisionId();
- DefaultModuleVersionIdentifier id = new DefaultModuleVersionIdentifier(moduleRevisionId.getOrganisation(), moduleRevisionId.getName(), moduleRevisionId.getRevision());
- resolved(id, descriptor, changing, moduleSource);
- }
-
- public void resolved(ModuleVersionIdentifier id, ModuleDescriptor descriptor, boolean changing, ModuleSource moduleSource) {
- reset(State.Resolved);
- this.moduleVersionIdentifier = id;
- this.moduleDescriptor = descriptor;
- this.changing = changing;
- this.moduleSource = moduleSource;
- }
-
- public void missing() {
- reset(State.Missing);
- }
-
- public void probablyMissing() {
- reset(State.ProbablyMissing);
- }
-
- public void failed(ModuleVersionResolveException failure) {
- reset(State.Failed);
- this.failure = failure;
- }
-
- public State getState() {
- return state;
- }
-
- public ModuleVersionResolveException getFailure() {
- assertHasResult();
- return failure;
- }
-
- private void assertHasResult() {
- if (state == State.Unknown) {
- throw new IllegalStateException("No result has been specified.");
- }
- }
-
- private void assertResolved() {
- if (state == State.Failed) {
- throw failure;
- }
- if (state != State.Resolved) {
- throw new IllegalStateException("This module has not been resolved.");
- }
- }
-
- public ModuleVersionIdentifier getId() {
- assertResolved();
- return moduleVersionIdentifier;
- }
-
- public ModuleDescriptor getDescriptor() {
- assertResolved();
- return moduleDescriptor;
- }
-
- public List<DependencyMetaData> getDependencies() {
- assertResolved();
- if (dependencies == null) {
- dependencies = new ArrayList<DependencyMetaData>();
- for (final DependencyDescriptor dependencyDescriptor : moduleDescriptor.getDependencies()) {
- dependencies.add(new DefaultDependencyMetaData(dependencyDescriptor));
- }
- }
- return dependencies;
- }
-
- public void setDependencies(Iterable<? extends DependencyMetaData> dependencies) {
- assertResolved();
- this.dependencies = CollectionUtils.toList(dependencies);
- }
-
- public boolean isChanging() {
- assertResolved();
- return changing;
- }
-
- public ModuleSource getModuleSource() {
- assertResolved();
- return moduleSource;
- }
-
- public void setModuleSource(ModuleSource moduleSource) {
- assertResolved();
- this.moduleSource = moduleSource;
- }
-
-}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/DefaultBuildableModuleVersionMetaDataResolveResult.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/DefaultBuildableModuleVersionMetaDataResolveResult.java
new file mode 100644
index 0000000..61c8a01
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/DefaultBuildableModuleVersionMetaDataResolveResult.java
@@ -0,0 +1,286 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve;
+
+import org.apache.ivy.core.module.descriptor.*;
+import org.apache.ivy.core.module.id.ModuleRevisionId;
+import org.gradle.api.artifacts.ModuleVersionIdentifier;
+import org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier;
+import org.gradle.api.internal.artifacts.ivyservice.ModuleVersionResolveException;
+import org.gradle.util.CollectionUtils;
+
+import java.util.*;
+
+// TODO - split out a buildable ModuleVersionMetaData implementation
+public class DefaultBuildableModuleVersionMetaDataResolveResult implements BuildableModuleVersionMetaDataResolveResult, MutableModuleVersionMetaData {
+ private static final List<String> DEFAULT_STATUS_SCHEME = Arrays.asList("integration", "milestone", "release");
+
+ private ModuleDescriptor moduleDescriptor;
+ private boolean changing;
+ private State state = State.Unknown;
+ private ModuleSource moduleSource;
+ private List<DependencyMetaData> dependencies;
+ private Map<String, DefaultConfigurationMetaData> configurations = new HashMap<String, DefaultConfigurationMetaData>();
+ private ModuleVersionResolveException failure;
+ private ModuleVersionIdentifier moduleVersionIdentifier;
+ private String status;
+ private List<String> statusScheme = DEFAULT_STATUS_SCHEME;
+
+ public void reset(State state) {
+ this.state = state;
+ moduleDescriptor = null;
+ changing = false;
+ failure = null;
+ status = null;
+ statusScheme = DEFAULT_STATUS_SCHEME;
+ }
+
+ public void resolved(ModuleDescriptor descriptor, boolean changing, ModuleSource moduleSource) {
+ ModuleRevisionId moduleRevisionId = descriptor.getModuleRevisionId();
+ ModuleVersionIdentifier id = DefaultModuleVersionIdentifier.newId(moduleRevisionId);
+ resolved(id, descriptor, changing, moduleSource);
+ }
+
+ public void resolved(ModuleVersionIdentifier id, ModuleDescriptor descriptor, boolean changing, ModuleSource moduleSource) {
+ reset(State.Resolved);
+ this.moduleVersionIdentifier = id;
+ this.moduleDescriptor = descriptor;
+ this.changing = changing;
+ this.moduleSource = moduleSource;
+ this.status = moduleDescriptor.getStatus();
+ }
+
+ public void missing() {
+ reset(State.Missing);
+ }
+
+ public void probablyMissing() {
+ reset(State.ProbablyMissing);
+ }
+
+ public void failed(ModuleVersionResolveException failure) {
+ reset(State.Failed);
+ this.failure = failure;
+ }
+
+ public State getState() {
+ return state;
+ }
+
+ public ModuleVersionResolveException getFailure() {
+ assertHasResult();
+ return failure;
+ }
+
+ public MutableModuleVersionMetaData getMetaData() throws ModuleVersionResolveException {
+ assertResolved();
+ return this;
+ }
+
+ private void assertHasResult() {
+ if (state == State.Unknown) {
+ throw new IllegalStateException("No result has been specified.");
+ }
+ }
+
+ private void assertResolved() {
+ if (state == State.Failed) {
+ throw failure;
+ }
+ if (state != State.Resolved) {
+ throw new IllegalStateException("This module has not been resolved.");
+ }
+ }
+
+ public ModuleVersionIdentifier getId() {
+ assertResolved();
+ return moduleVersionIdentifier;
+ }
+
+ public ModuleDescriptor getDescriptor() {
+ assertResolved();
+ return moduleDescriptor;
+ }
+
+ public List<DependencyMetaData> getDependencies() {
+ assertResolved();
+ if (dependencies == null) {
+ dependencies = new ArrayList<DependencyMetaData>();
+ for (final DependencyDescriptor dependencyDescriptor : moduleDescriptor.getDependencies()) {
+ dependencies.add(new DefaultDependencyMetaData(dependencyDescriptor));
+ }
+ }
+ return dependencies;
+ }
+
+ public void setDependencies(Iterable<? extends DependencyMetaData> dependencies) {
+ assertResolved();
+ this.dependencies = CollectionUtils.toList(dependencies);
+ for (DefaultConfigurationMetaData configuration : configurations.values()) {
+ configuration.dependencies = null;
+ }
+ }
+
+ public DefaultConfigurationMetaData getConfiguration(final String name) {
+ assertResolved();
+ DefaultConfigurationMetaData configuration = configurations.get(name);
+ if (configuration == null) {
+ Configuration descriptor = moduleDescriptor.getConfiguration(name);
+ if (descriptor == null) {
+ return null;
+ }
+ Set<String> hierarchy = new LinkedHashSet<String>();
+ hierarchy.add(name);
+ for (String parent : descriptor.getExtends()) {
+ hierarchy.addAll(getConfiguration(parent).hierarchy);
+ }
+ configuration = new DefaultConfigurationMetaData(descriptor, hierarchy);
+ configurations.put(name, configuration);
+ }
+ return configuration;
+ }
+
+ public boolean isChanging() {
+ assertResolved();
+ return changing;
+ }
+
+ public ModuleSource getModuleSource() {
+ assertResolved();
+ return moduleSource;
+ }
+
+ public void setModuleSource(ModuleSource moduleSource) {
+ assertResolved();
+ this.moduleSource = moduleSource;
+ }
+
+ public String getStatus() {
+ assertResolved();
+ return status;
+ }
+
+ public List<String> getStatusScheme() {
+ assertResolved();
+ return statusScheme;
+ }
+
+ public void setChanging(boolean changing) {
+ assertResolved();
+ this.changing = changing;
+ }
+
+ public void setStatus(String status) {
+ assertResolved();
+ this.status = status;
+ }
+
+ public void setStatusScheme(List<String> statusScheme) {
+ assertResolved();
+ this.statusScheme = statusScheme;
+ }
+
+ private class DefaultConfigurationMetaData implements ConfigurationMetaData {
+ private final Configuration descriptor;
+ private final Set<String> hierarchy;
+ private List<DependencyMetaData> dependencies;
+ private Set<Artifact> artifacts;
+ private LinkedHashSet<ExcludeRule> excludeRules;
+
+ private DefaultConfigurationMetaData(Configuration descriptor, Set<String> hierarchy) {
+ this.descriptor = descriptor;
+ this.hierarchy = hierarchy;
+ }
+
+ public ModuleVersionMetaData getModuleVersion() {
+ return DefaultBuildableModuleVersionMetaDataResolveResult.this;
+ }
+
+ public String getName() {
+ return descriptor.getName();
+ }
+
+ public Set<String> getHierarchy() {
+ return hierarchy;
+ }
+
+ public boolean isTransitive() {
+ return descriptor.isTransitive();
+ }
+
+ public List<DependencyMetaData> getDependencies() {
+ if (dependencies == null) {
+ dependencies = new ArrayList<DependencyMetaData>();
+ for (DependencyMetaData dependency : DefaultBuildableModuleVersionMetaDataResolveResult.this.getDependencies()) {
+ if (include(dependency)) {
+ dependencies.add(dependency);
+ }
+ }
+ }
+ return dependencies;
+ }
+
+ private boolean include(DependencyMetaData dependency) {
+ String[] moduleConfigurations = dependency.getDescriptor().getModuleConfigurations();
+ for (int i = 0; i < moduleConfigurations.length; i++) {
+ String moduleConfiguration = moduleConfigurations[i];
+ if (moduleConfiguration.equals("%") || hierarchy.contains(moduleConfiguration)) {
+ return true;
+ }
+ if (moduleConfiguration.equals("*")) {
+ boolean include = true;
+ for (int j = i + 1; j < moduleConfigurations.length && moduleConfigurations[j].startsWith("!"); j++) {
+ if (moduleConfigurations[j].substring(1).equals(getName())) {
+ include = false;
+ break;
+ }
+ }
+ if (include) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public Set<ExcludeRule> getExcludeRules() {
+ if (excludeRules == null) {
+ excludeRules = new LinkedHashSet<ExcludeRule>();
+ for (ExcludeRule excludeRule : moduleDescriptor.getAllExcludeRules()) {
+ for (String config : excludeRule.getConfigurations()) {
+ if (hierarchy.contains(config)) {
+ excludeRules.add(excludeRule);
+ break;
+ }
+ }
+ }
+ }
+ return excludeRules;
+ }
+
+ public Set<Artifact> getArtifacts() {
+ if (artifacts == null) {
+ artifacts = new LinkedHashSet<Artifact>();
+ for (String ancestor : hierarchy) {
+ for (Artifact artifact : moduleDescriptor.getArtifacts(ancestor)) {
+ artifacts.add(artifact);
+ }
+ }
+ }
+ return artifacts;
+ }
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/DefaultDependencyMetaData.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/DefaultDependencyMetaData.java
index b442e75..9965fe3 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/DefaultDependencyMetaData.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/DefaultDependencyMetaData.java
@@ -26,9 +26,9 @@ import org.gradle.internal.UncheckedException;
import java.lang.reflect.Field;
-class DefaultDependencyMetaData implements DependencyMetaData {
+public class DefaultDependencyMetaData implements DependencyMetaData {
private final DependencyDescriptor dependencyDescriptor;
- private DefaultModuleVersionSelector requested;
+ private final DefaultModuleVersionSelector requested;
public DefaultDependencyMetaData(DependencyDescriptor dependencyDescriptor) {
this.dependencyDescriptor = dependencyDescriptor;
@@ -49,6 +49,10 @@ class DefaultDependencyMetaData implements DependencyMetaData {
return dependencyDescriptor.isChanging();
}
+ public boolean isTransitive() {
+ return dependencyDescriptor.isTransitive();
+ }
+
public DependencyDescriptor getDescriptor() {
return dependencyDescriptor;
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/DefaultIvyAdapter.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/DefaultIvyAdapter.java
index 41e97ce..52cb316 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/DefaultIvyAdapter.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/DefaultIvyAdapter.java
@@ -15,23 +15,30 @@
*/
package org.gradle.api.internal.artifacts.ivyservice.ivyresolve;
-import org.apache.ivy.core.resolve.ResolveData;
-import org.gradle.api.internal.artifacts.ivyservice.DependencyToModuleResolver;
+import org.gradle.api.internal.artifacts.ivyservice.DependencyToModuleVersionResolver;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.LatestStrategy;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.VersionMatcher;
class DefaultIvyAdapter implements IvyAdapter {
- private final ResolveData resolveData;
- private final DependencyToModuleResolver userResolver;
+ private final VersionMatcher versionMatcher;
+ private final LatestStrategy latestStrategy;
+ private final DependencyToModuleVersionResolver userResolver;
- public DefaultIvyAdapter(ResolveData resolveData, DependencyToModuleResolver userResolverChain) {
- this.resolveData = resolveData;
+ public DefaultIvyAdapter(VersionMatcher versionMatcher, LatestStrategy latestStrategy, DependencyToModuleVersionResolver userResolverChain) {
+ this.versionMatcher = versionMatcher;
+ this.latestStrategy = latestStrategy;
userResolver = userResolverChain;
}
- public ResolveData getResolveData() {
- return resolveData;
+ public LatestStrategy getLatestStrategy() {
+ return latestStrategy;
}
- public DependencyToModuleResolver getDependencyToModuleResolver() {
+ public VersionMatcher getVersionMatcher() {
+ return versionMatcher;
+ }
+
+ public DependencyToModuleVersionResolver getDependencyToModuleResolver() {
return userResolver;
}
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/DelegatingDependencyResolver.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/DelegatingDependencyResolver.java
deleted file mode 100644
index c40b50a..0000000
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/DelegatingDependencyResolver.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve;
-
-import org.apache.ivy.core.cache.ArtifactOrigin;
-import org.apache.ivy.core.cache.RepositoryCacheManager;
-import org.apache.ivy.core.module.descriptor.Artifact;
-import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
-import org.apache.ivy.core.module.id.ModuleRevisionId;
-import org.apache.ivy.core.report.ArtifactDownloadReport;
-import org.apache.ivy.core.report.DownloadReport;
-import org.apache.ivy.core.resolve.DownloadOptions;
-import org.apache.ivy.core.resolve.ResolveData;
-import org.apache.ivy.core.resolve.ResolvedModuleRevision;
-import org.apache.ivy.core.search.ModuleEntry;
-import org.apache.ivy.core.search.OrganisationEntry;
-import org.apache.ivy.core.search.RevisionEntry;
-import org.apache.ivy.plugins.namespace.Namespace;
-import org.apache.ivy.plugins.resolver.DependencyResolver;
-import org.apache.ivy.plugins.resolver.ResolverSettings;
-import org.apache.ivy.plugins.resolver.util.ResolvedResource;
-
-import java.io.File;
-import java.io.IOException;
-import java.text.ParseException;
-import java.util.Map;
-
-abstract class DelegatingDependencyResolver implements DependencyResolver {
- private final DependencyResolver resolver;
- private ResolverSettings settings;
-
- public DelegatingDependencyResolver(DependencyResolver resolver) {
- this.resolver = resolver;
- }
-
- public DependencyResolver getResolver() {
- return resolver;
- }
-
- public String getName() {
- return resolver.getName();
- }
-
- public ResolverSettings getSettings() {
- return settings;
- }
-
- public void setSettings(ResolverSettings settings) {
- this.settings = settings;
- resolver.setSettings(settings);
- }
-
- public Namespace getNamespace() {
- return resolver.getNamespace();
- }
-
- public RepositoryCacheManager getRepositoryCacheManager() {
- return resolver.getRepositoryCacheManager();
- }
-
- public ModuleEntry[] listModules(OrganisationEntry org) {
- return resolver.listModules(org);
- }
-
- public OrganisationEntry[] listOrganisations() {
- return resolver.listOrganisations();
- }
-
- public RevisionEntry[] listRevisions(ModuleEntry module) {
- return resolver.listRevisions(module);
- }
-
- public String[] listTokenValues(String token, Map otherTokenValues) {
- return resolver.listTokenValues(token, otherTokenValues);
- }
-
- public Map[] listTokenValues(String[] tokens, Map criteria) {
- return resolver.listTokenValues(tokens, criteria);
- }
-
- public ArtifactOrigin locate(Artifact artifact) {
- return resolver.locate(artifact);
- }
-
- public ResolvedModuleRevision getDependency(DependencyDescriptor dd, ResolveData data) throws ParseException {
- return resolver.getDependency(dd, data);
- }
-
- public ResolvedResource findIvyFileRef(DependencyDescriptor dd, ResolveData data) {
- return resolver.findIvyFileRef(dd, data);
- }
-
- public boolean exists(Artifact artifact) {
- return resolver.exists(artifact);
- }
-
- public DownloadReport download(Artifact[] artifacts, DownloadOptions options) {
- return resolver.download(artifacts, options);
- }
-
- public ArtifactDownloadReport download(ArtifactOrigin artifact, DownloadOptions options) {
- return resolver.download(artifact, options);
- }
-
- public void abortPublishTransaction() throws IOException {
- throw new UnsupportedOperationException();
- }
-
- public void setName(String name) {
- throw new UnsupportedOperationException();
- }
-
- public void publish(Artifact artifact, File src, boolean overwrite) throws IOException {
- throw new UnsupportedOperationException();
- }
-
- public void beginPublishTransaction(ModuleRevisionId module, boolean overwrite) throws IOException {
- throw new UnsupportedOperationException();
- }
-
- public void commitPublishTransaction() throws IOException {
- throw new UnsupportedOperationException();
- }
-
- public void reportFailure() {
- throw new UnsupportedOperationException();
- }
-
- public void reportFailure(Artifact art) {
- throw new UnsupportedOperationException();
- }
-
- public void dumpSettings() {
- throw new UnsupportedOperationException();
- }
-}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/DependencyMetaData.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/DependencyMetaData.java
index 889998e..fb3eaeb 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/DependencyMetaData.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/DependencyMetaData.java
@@ -26,6 +26,8 @@ public interface DependencyMetaData {
boolean isChanging();
+ boolean isTransitive();
+
/**
* Returns a copy of this dependency with the given requested version.
*/
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/DependencyResolverIdentifier.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/DependencyResolverIdentifier.java
index d7e03a4..1950cfc 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/DependencyResolverIdentifier.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/DependencyResolverIdentifier.java
@@ -25,22 +25,10 @@ import java.util.ArrayList;
import java.util.List;
public class DependencyResolverIdentifier {
- private final String resolverId;
- private final String resolverName;
-
- public DependencyResolverIdentifier(DependencyResolver resolver) {
- resolverName = resolver.getName();
-
+ public static String forIvyResolver(DependencyResolver resolver) {
List<String> parts = new ArrayList<String>();
parts.add(resolver.getClass().getName());
- if (resolver instanceof ExternalResourceResolver) {
- ExternalResourceResolver externalResourceResolver = (ExternalResourceResolver) resolver;
- parts.add(joinPatterns(externalResourceResolver.getIvyPatterns()));
- parts.add(joinPatterns(externalResourceResolver.getArtifactPatterns()));
- if (externalResourceResolver.isM2compatible()) {
- parts.add("m2compatible");
- }
- } else if (resolver instanceof AbstractPatternsBasedResolver) {
+ if (resolver instanceof AbstractPatternsBasedResolver) {
AbstractPatternsBasedResolver patternsBasedResolver = (AbstractPatternsBasedResolver) resolver;
parts.add(joinPatterns(patternsBasedResolver.getIvyPatterns()));
parts.add(joinPatterns(patternsBasedResolver.getArtifactPatterns()));
@@ -52,23 +40,27 @@ public class DependencyResolverIdentifier {
// TODO We should not be assuming equality between resolvers here based on name...
}
- resolverId = calculateId(parts);
+ return calculateId(parts);
}
- private String joinPatterns(List<String> patterns) {
+ // TODO: Move this logic into ExternalResourceResolver, and add some transport-specific information (bumping the cache version)
+ public static String forExternalResourceResolver(ExternalResourceResolver resolver) {
+ List<String> parts = new ArrayList<String>();
+ parts.add(resolver.getClass().getName());
+ parts.add(joinPatterns(resolver.getIvyPatterns()));
+ parts.add(joinPatterns(resolver.getArtifactPatterns()));
+ if (resolver.isM2compatible()) {
+ parts.add("m2compatible");
+ }
+ return calculateId(parts);
+ }
+
+ private static String joinPatterns(List<String> patterns) {
return CollectionUtils.join(",", patterns);
}
- private String calculateId(List<String> parts) {
+ private static String calculateId(List<String> parts) {
String idString = CollectionUtils.join("::", parts);
return HashUtil.createHash(idString, "MD5").asHexString();
}
-
- public String getUniqueId() {
- return resolverId;
- }
-
- public String getName() {
- return resolverName;
- }
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/ExternalResourceResolverAdapter.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/ExternalResourceResolverAdapter.java
deleted file mode 100644
index e634fa2..0000000
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/ExternalResourceResolverAdapter.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve;
-
-import org.apache.ivy.core.module.descriptor.Artifact;
-import org.gradle.api.internal.artifacts.ivyservice.BuildableArtifactResolveResult;
-import org.gradle.api.internal.artifacts.repositories.resolver.ExternalResourceResolver;
-
-/**
- * A {@link ModuleVersionRepository} wrapper around an {@link ExternalResourceResolver}.
- */
-public class ExternalResourceResolverAdapter extends AbstractDependencyResolverAdapter {
- private final ExternalResourceResolver resolver;
- private final boolean dynamicResolve;
-
- public ExternalResourceResolverAdapter(ExternalResourceResolver resolver, boolean dynamicResolve) {
- super(resolver);
- this.resolver = resolver;
- this.dynamicResolve = dynamicResolve;
- }
-
- @Override
- public boolean isDynamicResolveMode() {
- return dynamicResolve;
- }
-
- public void getDependency(DependencyMetaData dependency, BuildableModuleVersionMetaData result) {
- resolver.getDependency(dependency.getDescriptor(), result);
- }
-
- public void resolve(Artifact artifact, BuildableArtifactResolveResult result, ModuleSource moduleSource) {
- resolver.resolve(artifact, result, moduleSource);
- }
-}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/IvyAdapter.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/IvyAdapter.java
index 824b41b..8cd985f 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/IvyAdapter.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/IvyAdapter.java
@@ -15,11 +15,14 @@
*/
package org.gradle.api.internal.artifacts.ivyservice.ivyresolve;
-import org.apache.ivy.core.resolve.ResolveData;
-import org.gradle.api.internal.artifacts.ivyservice.DependencyToModuleResolver;
+import org.gradle.api.internal.artifacts.ivyservice.DependencyToModuleVersionResolver;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.LatestStrategy;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.VersionMatcher;
public interface IvyAdapter {
- ResolveData getResolveData();
+ VersionMatcher getVersionMatcher();
- DependencyToModuleResolver getDependencyToModuleResolver();
+ LatestStrategy getLatestStrategy();
+
+ DependencyToModuleVersionResolver getDependencyToModuleResolver();
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/IvyAwareModuleVersionRepository.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/IvyAwareModuleVersionRepository.java
index b999020..1b66ddc 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/IvyAwareModuleVersionRepository.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/IvyAwareModuleVersionRepository.java
@@ -16,13 +16,11 @@
package org.gradle.api.internal.artifacts.ivyservice.ivyresolve;
+import org.apache.ivy.core.resolve.ResolveData;
import org.apache.ivy.core.settings.IvySettings;
public interface IvyAwareModuleVersionRepository extends ModuleVersionRepository {
void setSettings(IvySettings settings);
- // TODO - move this
- boolean isDynamicResolveMode();
-
- boolean isLocal();
+ void setResolveData(ResolveData resolveData);
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/IvyContextualiser.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/IvyContextualiser.java
index b92dafb..f4c7a63 100755
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/IvyContextualiser.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/IvyContextualiser.java
@@ -15,46 +15,12 @@
*/
package org.gradle.api.internal.artifacts.ivyservice.ivyresolve;
-import org.apache.ivy.Ivy;
import org.apache.ivy.core.IvyContext;
-import org.apache.ivy.core.resolve.ResolveData;
-import org.gradle.internal.UncheckedException;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
public class IvyContextualiser {
- private final Ivy ivy;
- private final ResolveData resolveData;
-
- public IvyContextualiser(Ivy ivy, ResolveData resolveData) {
- this.ivy = ivy;
- this.resolveData = resolveData;
- }
-
- public <T> T contextualise(Class<T> type, final T delegate) {
- Object proxy = Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{type}, new InvocationHandler() {
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- IvyContext context = IvyContext.pushNewCopyContext();
- try {
- context.setIvy(ivy);
- context.setResolveData(resolveData);
- return method.invoke(delegate, args);
- } catch (InvocationTargetException e) {
- throw UncheckedException.throwAsUncheckedException(e.getTargetException());
- } finally {
- IvyContext.popContext();
- }
- }
- });
- return type.cast(proxy);
- }
-
public static IvyContext getIvyContext() {
IvyContext context = IvyContext.getContext();
- if (context.peekIvy() == null || context.getResolveData() == null) {
+ if (context.peekIvy() == null) {
throw new IllegalStateException("Ivy context not established");
}
return context;
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/IvyDependencyResolverAdapter.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/IvyDependencyResolverAdapter.java
index e4fe31b..bf20aef 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/IvyDependencyResolverAdapter.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/IvyDependencyResolverAdapter.java
@@ -15,15 +15,20 @@
*/
package org.gradle.api.internal.artifacts.ivyservice.ivyresolve;
+import org.apache.ivy.core.IvyContext;
import org.apache.ivy.core.module.descriptor.Artifact;
import org.apache.ivy.core.report.ArtifactDownloadReport;
import org.apache.ivy.core.report.DownloadStatus;
import org.apache.ivy.core.resolve.DownloadOptions;
import org.apache.ivy.core.resolve.ResolveData;
import org.apache.ivy.core.resolve.ResolvedModuleRevision;
+import org.apache.ivy.core.settings.IvySettings;
import org.apache.ivy.plugins.resolver.DependencyResolver;
+import org.gradle.api.artifacts.ArtifactIdentifier;
+import org.gradle.api.internal.artifacts.DefaultArtifactIdentifier;
import org.gradle.api.internal.artifacts.ivyservice.BuildableArtifactResolveResult;
-import org.gradle.api.internal.artifacts.repositories.cachemanager.EnhancedArtifactDownloadReport;
+import org.gradle.api.internal.artifacts.repositories.legacy.EnhancedArtifactDownloadReport;
+import org.gradle.api.internal.artifacts.repositories.legacy.LocalFileRepositoryCacheManager;
import org.gradle.internal.UncheckedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -34,16 +39,49 @@ import java.text.ParseException;
/**
* A {@link ModuleVersionRepository} wrapper around an Ivy {@link DependencyResolver}.
*/
-public class IvyDependencyResolverAdapter extends AbstractDependencyResolverAdapter {
+public class IvyDependencyResolverAdapter implements ConfiguredModuleVersionRepository, IvyAwareModuleVersionRepository {
private static final Logger LOGGER = LoggerFactory.getLogger(IvyDependencyResolverAdapter.class);
private final DownloadOptions downloadOptions = new DownloadOptions();
+ private final String identifier;
+ private final DependencyResolver resolver;
+ private ResolveData resolveData;
public IvyDependencyResolverAdapter(DependencyResolver resolver) {
- super(resolver);
+ this.resolver = resolver;
+ identifier = DependencyResolverIdentifier.forIvyResolver(resolver);
}
- public void getDependency(DependencyMetaData dependency, BuildableModuleVersionMetaData result) {
- ResolveData resolveData = IvyContextualiser.getIvyContext().getResolveData();
+ public String getId() {
+ return identifier;
+ }
+
+ public String getName() {
+ return resolver.getName();
+ }
+
+ @Override
+ public String toString() {
+ return String.format("Repository '%s'", resolver.getName());
+ }
+
+ public boolean isLocal() {
+ return resolver.getRepositoryCacheManager() instanceof LocalFileRepositoryCacheManager;
+ }
+
+ public void setSettings(IvySettings settings) {
+ settings.addResolver(resolver);
+ }
+
+ public void setResolveData(ResolveData resolveData) {
+ this.resolveData = resolveData;
+ }
+
+ public boolean isDynamicResolveMode() {
+ return false;
+ }
+
+ public void getDependency(DependencyMetaData dependency, BuildableModuleVersionMetaDataResolveResult result) {
+ IvyContext.getContext().setResolveData(resolveData);
try {
ResolvedModuleRevision revision = resolver.getDependency(dependency.getDescriptor(), resolveData);
if (revision == null) {
@@ -58,14 +96,15 @@ public class IvyDependencyResolverAdapter extends AbstractDependencyResolverAdap
}
}
- public void resolve(Artifact artifact, BuildableArtifactResolveResult result, ModuleSource moduleSource) {
- ArtifactDownloadReport artifactDownloadReport = resolver.download(new Artifact[]{artifact}, downloadOptions).getArtifactReport(artifact);
+ public void resolve(ArtifactIdentifier artifact, BuildableArtifactResolveResult result, ModuleSource moduleSource) {
+ Artifact ivyArtifact = DefaultArtifactIdentifier.toArtifact(artifact);
+ ArtifactDownloadReport artifactDownloadReport = resolver.download(new Artifact[]{ivyArtifact}, downloadOptions).getArtifactReport(ivyArtifact);
if (downloadFailed(artifactDownloadReport)) {
if (artifactDownloadReport instanceof EnhancedArtifactDownloadReport) {
EnhancedArtifactDownloadReport enhancedReport = (EnhancedArtifactDownloadReport) artifactDownloadReport;
- result.failed(new ArtifactResolveException(artifactDownloadReport.getArtifact(), enhancedReport.getFailure()));
+ result.failed(new ArtifactResolveException(artifact, enhancedReport.getFailure()));
} else {
- result.failed(new ArtifactResolveException(artifactDownloadReport.getArtifact(), artifactDownloadReport.getDownloadDetails()));
+ result.failed(new ArtifactResolveException(artifact, artifactDownloadReport.getDownloadDetails()));
}
return;
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/IvyDynamicResolveModuleVersionRepository.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/IvyDynamicResolveModuleVersionRepository.java
index 821e0d8..d061381 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/IvyDynamicResolveModuleVersionRepository.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/IvyDynamicResolveModuleVersionRepository.java
@@ -16,7 +16,7 @@
package org.gradle.api.internal.artifacts.ivyservice.ivyresolve;
-import org.apache.ivy.core.module.descriptor.Artifact;
+import org.gradle.api.artifacts.ArtifactIdentifier;
import org.gradle.api.internal.artifacts.ivyservice.BuildableArtifactResolveResult;
import java.util.ArrayList;
@@ -37,29 +37,29 @@ public class IvyDynamicResolveModuleVersionRepository implements LocalAwareModul
return repository.getName();
}
- public void getLocalDependency(DependencyMetaData dependency, BuildableModuleVersionMetaData result) {
+ public void getLocalDependency(DependencyMetaData dependency, BuildableModuleVersionMetaDataResolveResult result) {
repository.getLocalDependency(dependency, result);
- if (result.getState() == BuildableModuleVersionMetaData.State.Resolved) {
+ if (result.getState() == BuildableModuleVersionMetaDataResolveResult.State.Resolved) {
transformDependencies(result);
}
}
- public void getDependency(DependencyMetaData dependency, BuildableModuleVersionMetaData result) {
+ public void getDependency(DependencyMetaData dependency, BuildableModuleVersionMetaDataResolveResult result) {
repository.getDependency(dependency, result);
- if (result.getState() == BuildableModuleVersionMetaData.State.Resolved) {
+ if (result.getState() == BuildableModuleVersionMetaDataResolveResult.State.Resolved) {
transformDependencies(result);
}
}
- private void transformDependencies(BuildableModuleVersionMetaData result) {
+ private void transformDependencies(BuildableModuleVersionMetaDataResolveResult result) {
List<DependencyMetaData> transformed = new ArrayList<DependencyMetaData>();
- for (DependencyMetaData dependency : result.getDependencies()) {
+ for (DependencyMetaData dependency : result.getMetaData().getDependencies()) {
transformed.add(dependency.withRequestedVersion(dependency.getDescriptor().getDynamicConstraintDependencyRevisionId().getRevision()));
}
result.setDependencies(transformed);
}
- public void resolve(Artifact artifact, BuildableArtifactResolveResult result, ModuleSource moduleSource) {
+ public void resolve(ArtifactIdentifier artifact, BuildableArtifactResolveResult result, ModuleSource moduleSource) {
repository.resolve(artifact, result, moduleSource);
}
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/LazyDependencyToModuleResolver.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/LazyDependencyToModuleResolver.java
index 637cb5b..5c53c8f 100755
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/LazyDependencyToModuleResolver.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/LazyDependencyToModuleResolver.java
@@ -18,12 +18,12 @@ package org.gradle.api.internal.artifacts.ivyservice.ivyresolve;
import org.apache.ivy.core.module.descriptor.Artifact;
import org.apache.ivy.core.module.descriptor.Configuration;
import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
-import org.apache.ivy.plugins.version.VersionMatcher;
import org.gradle.api.artifacts.ModuleVersionIdentifier;
import org.gradle.api.artifacts.ModuleVersionSelector;
import org.gradle.api.artifacts.result.ModuleVersionSelectionReason;
import org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier;
import org.gradle.api.internal.artifacts.ivyservice.*;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.VersionMatcher;
import org.gradle.api.internal.artifacts.ivyservice.resolveengine.result.VersionSelectionReasons;
/**
@@ -31,16 +31,16 @@ import org.gradle.api.internal.artifacts.ivyservice.resolveengine.result.Version
* required.
*/
public class LazyDependencyToModuleResolver implements DependencyToModuleVersionIdResolver {
- private final DependencyToModuleResolver dependencyResolver;
+ private final DependencyToModuleVersionResolver dependencyResolver;
private final VersionMatcher versionMatcher;
- public LazyDependencyToModuleResolver(DependencyToModuleResolver dependencyResolver, VersionMatcher versionMatcher) {
+ public LazyDependencyToModuleResolver(DependencyToModuleVersionResolver dependencyResolver, VersionMatcher versionMatcher) {
this.dependencyResolver = dependencyResolver;
this.versionMatcher = versionMatcher;
}
public ModuleVersionIdResolveResult resolve(DependencyMetaData dependency) {
- if (versionMatcher.isDynamic(dependency.getDescriptor().getDependencyRevisionId())) {
+ if (versionMatcher.isDynamic(dependency.getRequested().getVersion())) {
DynamicVersionResolveResult result = new DynamicVersionResolveResult(dependency);
result.resolve();
return result;
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/LocalAwareModuleVersionRepository.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/LocalAwareModuleVersionRepository.java
index 2066cb0..b81524a 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/LocalAwareModuleVersionRepository.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/LocalAwareModuleVersionRepository.java
@@ -20,10 +20,10 @@ public interface LocalAwareModuleVersionRepository extends ModuleVersionReposito
/**
* Locates the given dependency, using only local resources.
*/
- void getLocalDependency(DependencyMetaData dependency, BuildableModuleVersionMetaData result);
+ void getLocalDependency(DependencyMetaData dependency, BuildableModuleVersionMetaDataResolveResult result);
/**
- * Locates the given dependency, using whichever resources are appropriate. Always called after {@link #getLocalDependency(DependencyMetaData, BuildableModuleVersionMetaData)}.
+ * Locates the given dependency, using whichever resources are appropriate. Always called after {@link #getLocalDependency(DependencyMetaData, BuildableModuleVersionMetaDataResolveResult)}.
*/
- void getDependency(DependencyMetaData dependency, BuildableModuleVersionMetaData result);
+ void getDependency(DependencyMetaData dependency, BuildableModuleVersionMetaDataResolveResult result);
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/LocalModuleVersionRepository.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/LocalModuleVersionRepository.java
index 93268b6..034d03d 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/LocalModuleVersionRepository.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/LocalModuleVersionRepository.java
@@ -16,7 +16,7 @@
package org.gradle.api.internal.artifacts.ivyservice.ivyresolve;
-import org.apache.ivy.core.module.descriptor.Artifact;
+import org.gradle.api.artifacts.ArtifactIdentifier;
import org.gradle.api.internal.artifacts.ivyservice.BuildableArtifactResolveResult;
public class LocalModuleVersionRepository implements LocalAwareModuleVersionRepository {
@@ -26,15 +26,15 @@ public class LocalModuleVersionRepository implements LocalAwareModuleVersionRepo
this.delegate = delegate;
}
- public void resolve(Artifact artifact, BuildableArtifactResolveResult result, ModuleSource moduleSource) {
+ public void resolve(ArtifactIdentifier artifact, BuildableArtifactResolveResult result, ModuleSource moduleSource) {
delegate.resolve(artifact, result, moduleSource);
}
- public void getLocalDependency(DependencyMetaData dependency, BuildableModuleVersionMetaData result) {
+ public void getLocalDependency(DependencyMetaData dependency, BuildableModuleVersionMetaDataResolveResult result) {
delegate.getDependency(dependency, result);
}
- public void getDependency(DependencyMetaData dependency, BuildableModuleVersionMetaData result) {
+ public void getDependency(DependencyMetaData dependency, BuildableModuleVersionMetaDataResolveResult result) {
result.missing();
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/LoopbackDependencyResolver.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/LoopbackDependencyResolver.java
index 38f1308..2b5d3ec 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/LoopbackDependencyResolver.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/LoopbackDependencyResolver.java
@@ -17,13 +17,23 @@ package org.gradle.api.internal.artifacts.ivyservice.ivyresolve;
import org.apache.ivy.core.IvyContext;
import org.apache.ivy.core.cache.ArtifactOrigin;
+import org.apache.ivy.core.cache.RepositoryCacheManager;
import org.apache.ivy.core.module.descriptor.Artifact;
import org.apache.ivy.core.module.descriptor.DefaultDependencyDescriptor;
import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
+import org.apache.ivy.core.module.id.ModuleRevisionId;
+import org.apache.ivy.core.report.ArtifactDownloadReport;
+import org.apache.ivy.core.report.DownloadReport;
+import org.apache.ivy.core.resolve.DownloadOptions;
import org.apache.ivy.core.resolve.ResolveData;
import org.apache.ivy.core.resolve.ResolvedModuleRevision;
+import org.apache.ivy.core.search.ModuleEntry;
+import org.apache.ivy.core.search.OrganisationEntry;
+import org.apache.ivy.core.search.RevisionEntry;
+import org.apache.ivy.plugins.namespace.Namespace;
import org.apache.ivy.plugins.resolver.DependencyResolver;
import org.apache.ivy.plugins.resolver.ResolverSettings;
+import org.apache.ivy.plugins.resolver.util.ResolvedResource;
import org.gradle.api.internal.artifacts.ivyservice.CacheLockingManager;
import org.gradle.api.internal.artifacts.ivyservice.DefaultBuildableArtifactResolveResult;
import org.gradle.api.internal.artifacts.ivyservice.DefaultBuildableModuleVersionResolveResult;
@@ -31,12 +41,14 @@ import org.gradle.api.internal.artifacts.ivyservice.ModuleVersionNotFoundExcepti
import org.gradle.internal.Factory;
import java.io.File;
+import java.io.IOException;
import java.text.ParseException;
+import java.util.Map;
/**
* The main entry point for a {@link DependencyResolver} to call back into the dependency resolution mechanism.
*/
-public class LoopbackDependencyResolver extends RestrictedDependencyResolver {
+public class LoopbackDependencyResolver implements DependencyResolver {
private final String name;
private final UserResolverChain userResolverChain;
private final CacheLockingManager cacheLockingManager;
@@ -47,17 +59,14 @@ public class LoopbackDependencyResolver extends RestrictedDependencyResolver {
this.cacheLockingManager = cacheLockingManager;
}
- @Override
public String getName() {
return name;
}
- @Override
public void setSettings(ResolverSettings settings) {
// don't care
}
- @Override
public ResolvedModuleRevision getDependency(final DependencyDescriptor dd, final ResolveData data) throws ParseException {
final DependencyResolver loopback = this;
return cacheLockingManager.useCache(String.format("Resolve %s", dd), new Factory<ResolvedModuleRevision>() {
@@ -76,7 +85,6 @@ public class LoopbackDependencyResolver extends RestrictedDependencyResolver {
});
}
- @Override
public ArtifactOrigin locate(final Artifact artifact) {
return cacheLockingManager.useCache(String.format("Locate %s", artifact), new Factory<ArtifactOrigin>() {
public ArtifactOrigin create() {
@@ -97,4 +105,80 @@ public class LoopbackDependencyResolver extends RestrictedDependencyResolver {
}
});
}
+
+ public void setName(String name) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void abortPublishTransaction() throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ public ResolvedResource findIvyFileRef(DependencyDescriptor dd, ResolveData data) {
+ throw new UnsupportedOperationException();
+ }
+
+ public DownloadReport download(Artifact[] artifacts, DownloadOptions options) {
+ throw new UnsupportedOperationException();
+ }
+
+ public ArtifactDownloadReport download(ArtifactOrigin artifact, DownloadOptions options) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean exists(Artifact artifact) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void publish(Artifact artifact, File src, boolean overwrite) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void beginPublishTransaction(ModuleRevisionId module, boolean overwrite) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void commitPublishTransaction() throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void reportFailure() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void reportFailure(Artifact art) {
+ throw new UnsupportedOperationException();
+ }
+
+ public String[] listTokenValues(String token, Map otherTokenValues) {
+ throw new UnsupportedOperationException();
+ }
+
+ public Map[] listTokenValues(String[] tokens, Map criteria) {
+ throw new UnsupportedOperationException();
+ }
+
+ public OrganisationEntry[] listOrganisations() {
+ throw new UnsupportedOperationException();
+ }
+
+ public ModuleEntry[] listModules(OrganisationEntry org) {
+ throw new UnsupportedOperationException();
+ }
+
+ public RevisionEntry[] listRevisions(ModuleEntry module) {
+ throw new UnsupportedOperationException();
+ }
+
+ public Namespace getNamespace() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void dumpSettings() {
+ throw new UnsupportedOperationException();
+ }
+
+ public RepositoryCacheManager getRepositoryCacheManager() {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/ModuleSource.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/ModuleSource.java
index 61e2285..a2a980b 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/ModuleSource.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/ModuleSource.java
@@ -18,7 +18,11 @@ package org.gradle.api.internal.artifacts.ivyservice.ivyresolve;
import java.io.Serializable;
+/**
+ * A memento for any resolution state that is relevant to locate the artifacts of a resolved module version.
+ *
+ * Implementations must retain as little state as possible and must be able to be serialized. Also note that
+ * a given instance may be passed to multiple repository instances.
+ */
public interface ModuleSource extends Serializable {
}
-
-
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/ModuleVersionMetaData.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/ModuleVersionMetaData.java
index db1ad9c..d2a24c6 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/ModuleVersionMetaData.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/ModuleVersionMetaData.java
@@ -16,12 +16,13 @@
package org.gradle.api.internal.artifacts.ivyservice.ivyresolve;
import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
+import org.gradle.api.Nullable;
import org.gradle.api.artifacts.ModuleVersionIdentifier;
import java.util.List;
/**
- * The meta-data for a module version.
+ * The meta-data for a module version required during dependency resolution.
*/
public interface ModuleVersionMetaData {
ModuleVersionIdentifier getId();
@@ -30,5 +31,12 @@ public interface ModuleVersionMetaData {
List<DependencyMetaData> getDependencies();
+ @Nullable
+ ConfigurationMetaData getConfiguration(String name);
+
boolean isChanging();
+
+ String getStatus();
+
+ List<String> getStatusScheme();
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/ModuleVersionRepository.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/ModuleVersionRepository.java
index 8b6df7d..41be712 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/ModuleVersionRepository.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/ModuleVersionRepository.java
@@ -15,23 +15,27 @@
*/
package org.gradle.api.internal.artifacts.ivyservice.ivyresolve;
-import org.apache.ivy.core.module.descriptor.Artifact;
+import org.gradle.api.artifacts.ArtifactIdentifier;
import org.gradle.api.internal.artifacts.ivyservice.BuildableArtifactResolveResult;
/**
* A repository of module versions.
*
- * The plan is to sync this with {@link org.gradle.api.internal.artifacts.ivyservice.DependencyToModuleResolver}
+ * The plan is to sync this with {@link org.gradle.api.internal.artifacts.ivyservice.DependencyToModuleVersionResolver} and rename it
+ * to have 'resolver' instead of 'repository' in its name.
*/
public interface ModuleVersionRepository {
String getId();
String getName();
- void getDependency(DependencyMetaData dependency, BuildableModuleVersionMetaData result);
+ /**
+ * Resolves the given dependency to the corresponding module version meta-data.
+ */
+ void getDependency(DependencyMetaData dependency, BuildableModuleVersionMetaDataResolveResult result);
/**
- * Downloads the given artifact. Any failures are packaged up in the result.
+ * Resolves the given artifact. Any failures are packaged up in the result.
*/
- void resolve(Artifact artifact, BuildableArtifactResolveResult result, ModuleSource moduleSource);
+ void resolve(ArtifactIdentifier artifact, BuildableArtifactResolveResult result, ModuleSource moduleSource);
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/MutableModuleVersionMetaData.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/MutableModuleVersionMetaData.java
new file mode 100644
index 0000000..350ca34
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/MutableModuleVersionMetaData.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve;
+
+import java.util.List;
+
+public interface MutableModuleVersionMetaData extends ModuleVersionMetaData {
+ void setChanging(boolean changing);
+ void setStatus(String status);
+ void setStatusScheme(List<String> statusScheme);
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/ResolveIvyFactory.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/ResolveIvyFactory.java
index e672c0e..6174231 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/ResolveIvyFactory.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/ResolveIvyFactory.java
@@ -16,63 +16,69 @@
package org.gradle.api.internal.artifacts.ivyservice.ivyresolve;
import org.apache.ivy.Ivy;
+import org.apache.ivy.core.IvyContext;
import org.apache.ivy.core.resolve.ResolveData;
import org.apache.ivy.core.resolve.ResolveOptions;
import org.apache.ivy.core.settings.IvySettings;
import org.gradle.api.artifacts.cache.ResolutionRules;
import org.gradle.api.internal.artifacts.configurations.ConfigurationInternal;
+import org.gradle.api.internal.artifacts.ivyservice.BuildableModuleVersionResolveResult;
import org.gradle.api.internal.artifacts.ivyservice.CacheLockingManager;
-import org.gradle.api.internal.artifacts.ivyservice.IvyFactory;
-import org.gradle.api.internal.artifacts.ivyservice.SettingsConverter;
+import org.gradle.api.internal.artifacts.ivyservice.DependencyToModuleVersionResolver;
import org.gradle.api.internal.artifacts.ivyservice.dynamicversions.ModuleResolutionCache;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.memcache.InMemoryDependencyMetadataCache;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.LatestStrategy;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.ResolverStrategy;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.VersionMatcher;
import org.gradle.api.internal.artifacts.ivyservice.modulecache.ModuleDescriptorCache;
import org.gradle.api.internal.artifacts.repositories.ResolutionAwareRepository;
+import org.gradle.api.internal.artifacts.repositories.resolver.ExternalResourceResolver;
import org.gradle.api.internal.externalresource.cached.CachedArtifactIndex;
import org.gradle.internal.TimeProvider;
import org.gradle.util.WrapUtil;
public class ResolveIvyFactory {
- private final IvyFactory ivyFactory;
- private final SettingsConverter settingsConverter;
private final ModuleResolutionCache moduleResolutionCache;
private final ModuleDescriptorCache moduleDescriptorCache;
private final CachedArtifactIndex artifactAtRepositoryCachedResolutionIndex;
private final CacheLockingManager cacheLockingManager;
private final StartParameterResolutionOverride startParameterResolutionOverride;
private final TimeProvider timeProvider;
+ private InMemoryDependencyMetadataCache inMemoryCache;
- public ResolveIvyFactory(IvyFactory ivyFactory, SettingsConverter settingsConverter,
- ModuleResolutionCache moduleResolutionCache, ModuleDescriptorCache moduleDescriptorCache,
+ public ResolveIvyFactory(ModuleResolutionCache moduleResolutionCache, ModuleDescriptorCache moduleDescriptorCache,
CachedArtifactIndex artifactAtRepositoryCachedResolutionIndex,
CacheLockingManager cacheLockingManager, StartParameterResolutionOverride startParameterResolutionOverride,
- TimeProvider timeProvider) {
- this.ivyFactory = ivyFactory;
- this.settingsConverter = settingsConverter;
+ TimeProvider timeProvider, InMemoryDependencyMetadataCache inMemoryCache) {
this.moduleResolutionCache = moduleResolutionCache;
this.moduleDescriptorCache = moduleDescriptorCache;
this.artifactAtRepositoryCachedResolutionIndex = artifactAtRepositoryCachedResolutionIndex;
this.cacheLockingManager = cacheLockingManager;
this.startParameterResolutionOverride = startParameterResolutionOverride;
this.timeProvider = timeProvider;
+ this.inMemoryCache = inMemoryCache;
}
public IvyAdapter create(ConfigurationInternal configuration, Iterable<? extends ResolutionAwareRepository> repositories) {
- UserResolverChain userResolverChain = new UserResolverChain();
ResolutionRules resolutionRules = configuration.getResolutionStrategy().getResolutionRules();
startParameterResolutionOverride.addResolutionRules(resolutionRules);
- LoopbackDependencyResolver loopbackDependencyResolver = new LoopbackDependencyResolver(SettingsConverter.LOOPBACK_RESOLVER_NAME, userResolverChain, cacheLockingManager);
+ VersionMatcher versionMatcher = ResolverStrategy.INSTANCE.getVersionMatcher();
+ LatestStrategy comparatorLatestStrategy = ResolverStrategy.INSTANCE.getLatestStrategy();
- IvySettings ivySettings = settingsConverter.convertForResolve(loopbackDependencyResolver);
- userResolverChain.setSettings(ivySettings);
-
- Ivy ivy = ivyFactory.createIvy(ivySettings);
- ResolveData resolveData = createResolveData(ivy, configuration.getName());
- IvyContextualiser contextualiser = new IvyContextualiser(ivy, resolveData);
+ UserResolverChain userResolverChain = new UserResolverChain(versionMatcher, comparatorLatestStrategy);
+ DependencyToModuleVersionResolver parentLookupResolver = new ParentModuleLookupResolver(userResolverChain, cacheLockingManager);
for (ResolutionAwareRepository repository : repositories) {
- IvyAwareModuleVersionRepository moduleVersionRepository = repository.createResolver();
- moduleVersionRepository.setSettings(ivySettings);
+ ConfiguredModuleVersionRepository moduleVersionRepository = repository.createResolver();
+
+ if (moduleVersionRepository instanceof IvyAwareModuleVersionRepository) {
+ ivyContextualize((IvyAwareModuleVersionRepository) moduleVersionRepository, userResolverChain, configuration.getName());
+ }
+ if (moduleVersionRepository instanceof ExternalResourceResolver) {
+ // TODO:DAZ Should have type for this
+ ((ExternalResourceResolver) moduleVersionRepository).setResolver(parentLookupResolver);
+ }
LocalAwareModuleVersionRepository localAwareRepository;
if (moduleVersionRepository.isLocal()) {
@@ -81,16 +87,28 @@ public class ResolveIvyFactory {
ModuleVersionRepository wrapperRepository = new CacheLockingModuleVersionRepository(moduleVersionRepository, cacheLockingManager);
wrapperRepository = startParameterResolutionOverride.overrideModuleVersionRepository(wrapperRepository);
localAwareRepository = new CachingModuleVersionRepository(wrapperRepository, moduleResolutionCache, moduleDescriptorCache, artifactAtRepositoryCachedResolutionIndex,
- configuration.getResolutionStrategy().getCachePolicy(), timeProvider);
+ parentLookupResolver, configuration.getResolutionStrategy().getCachePolicy(), timeProvider);
}
if (moduleVersionRepository.isDynamicResolveMode()) {
localAwareRepository = new IvyDynamicResolveModuleVersionRepository(localAwareRepository);
}
- localAwareRepository = contextualiser.contextualise(LocalAwareModuleVersionRepository.class, localAwareRepository);
+ localAwareRepository = inMemoryCache.cached(localAwareRepository);
userResolverChain.add(localAwareRepository);
}
- return new DefaultIvyAdapter(resolveData, userResolverChain);
+ return new DefaultIvyAdapter(versionMatcher, comparatorLatestStrategy, userResolverChain);
+ }
+
+ private void ivyContextualize(IvyAwareModuleVersionRepository ivyAwareRepository, UserResolverChain userResolverChain, String configurationName) {
+ Ivy ivy = IvyContext.getContext().getIvy();
+ IvySettings ivySettings = ivy.getSettings();
+ LoopbackDependencyResolver loopbackDependencyResolver = new LoopbackDependencyResolver("main", userResolverChain, cacheLockingManager);
+ ivySettings.addResolver(loopbackDependencyResolver);
+ ivySettings.setDefaultResolver(loopbackDependencyResolver.getName());
+
+ ResolveData resolveData = createResolveData(ivy, configurationName);
+ ivyAwareRepository.setSettings(ivySettings);
+ ivyAwareRepository.setResolveData(resolveData);
}
private ResolveData createResolveData(Ivy ivy, String configurationName) {
@@ -99,4 +117,25 @@ public class ResolveIvyFactory {
options.setConfs(WrapUtil.toArray(configurationName));
return new ResolveData(ivy.getResolveEngine(), options);
}
+
+ /**
+ * Provides access to the top-level resolver chain for looking up parent modules when parsing module descriptor files.
+ */
+ private static class ParentModuleLookupResolver implements DependencyToModuleVersionResolver {
+ private final UserResolverChain delegate;
+ private final CacheLockingManager cacheLockingManager;
+
+ public ParentModuleLookupResolver(UserResolverChain delegate, CacheLockingManager cacheLockingManager) {
+ this.delegate = delegate;
+ this.cacheLockingManager = cacheLockingManager;
+ }
+
+ public void resolve(final DependencyMetaData dependency, final BuildableModuleVersionResolveResult result) {
+ cacheLockingManager.useCache(String.format("Resolve %s", dependency), new Runnable() {
+ public void run() {
+ delegate.resolve(dependency, result);
+ }
+ });
+ }
+ }
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/RestrictedDependencyResolver.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/RestrictedDependencyResolver.java
deleted file mode 100644
index fc308e2..0000000
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/RestrictedDependencyResolver.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve;
-
-import org.apache.ivy.plugins.resolver.DependencyResolver;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-
-public abstract class RestrictedDependencyResolver extends DelegatingDependencyResolver {
- protected RestrictedDependencyResolver() {
- super(createAngryDelegate());
- }
-
- private static DependencyResolver createAngryDelegate() {
- return (DependencyResolver) Proxy.newProxyInstance(RestrictedDependencyResolver.class.getClassLoader(), new Class<?>[]{DependencyResolver.class}, new InvocationHandler() {
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- throw new UnsupportedOperationException();
- }
- });
- }
-}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/StartParameterResolutionOverride.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/StartParameterResolutionOverride.java
index b75aeec..ba82e2f 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/StartParameterResolutionOverride.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/StartParameterResolutionOverride.java
@@ -15,9 +15,9 @@
*/
package org.gradle.api.internal.artifacts.ivyservice.ivyresolve;
-import org.apache.ivy.core.module.descriptor.Artifact;
import org.gradle.StartParameter;
import org.gradle.api.Action;
+import org.gradle.api.artifacts.ArtifactIdentifier;
import org.gradle.api.artifacts.cache.ArtifactResolutionControl;
import org.gradle.api.artifacts.cache.DependencyResolutionControl;
import org.gradle.api.artifacts.cache.ModuleResolutionControl;
@@ -96,11 +96,11 @@ public class StartParameterResolutionOverride {
return false;
}
- public void getDependency(DependencyMetaData dependency, BuildableModuleVersionMetaData result) {
+ public void getDependency(DependencyMetaData dependency, BuildableModuleVersionMetaDataResolveResult result) {
result.failed(new ModuleVersionResolveException(dependency.getRequested(), "No cached version of %s available for offline mode."));
}
- public void resolve(Artifact artifact, BuildableArtifactResolveResult result, ModuleSource moduleSource) {
+ public void resolve(ArtifactIdentifier artifact, BuildableArtifactResolveResult result, ModuleSource moduleSource) {
result.failed(new ArtifactResolveException(artifact, "No cached version available for offline mode"));
}
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/UserResolverChain.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/UserResolverChain.java
index 0364650..1507018 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/UserResolverChain.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/UserResolverChain.java
@@ -17,25 +17,30 @@
package org.gradle.api.internal.artifacts.ivyservice.ivyresolve;
import org.apache.ivy.core.module.descriptor.Artifact;
-import org.apache.ivy.plugins.latest.ArtifactInfo;
-import org.apache.ivy.plugins.latest.ComparatorLatestStrategy;
-import org.apache.ivy.plugins.resolver.ResolverSettings;
import org.gradle.api.artifacts.ModuleVersionSelector;
+import org.gradle.api.internal.artifacts.DefaultArtifactIdentifier;
import org.gradle.api.internal.artifacts.ivyservice.*;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.LatestStrategy;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.VersionMatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
-public class UserResolverChain implements DependencyToModuleResolver {
+public class UserResolverChain implements DependencyToModuleVersionResolver {
private static final Logger LOGGER = LoggerFactory.getLogger(UserResolverChain.class);
private final List<LocalAwareModuleVersionRepository> moduleVersionRepositories = new ArrayList<LocalAwareModuleVersionRepository>();
private final List<String> moduleVersionRepositoryNames = new ArrayList<String>();
- private ResolverSettings settings;
+ private final VersionMatcher versionMatcher;
+ private final LatestStrategy latestStrategy;
- public void setSettings(ResolverSettings settings) {
- this.settings = settings;
+ public UserResolverChain(VersionMatcher versionMatcher, LatestStrategy latestStrategy) {
+ this.versionMatcher = versionMatcher;
+ this.latestStrategy = latestStrategy;
}
public void add(LocalAwareModuleVersionRepository repository) {
@@ -84,7 +89,7 @@ public class UserResolverChain implements DependencyToModuleResolver {
}
private ModuleResolution findLatestModule(DependencyMetaData dependency, LinkedList<RepositoryResolveState> queue, Collection<Throwable> failures, Collection<RepositoryResolveState> missing) {
- boolean isStaticVersion = !settings.getVersionMatcher().isDynamic(dependency.getDescriptor().getDependencyRevisionId());
+ boolean isStaticVersion = !versionMatcher.isDynamic(dependency.getRequested().getVersion());
ModuleResolution best = null;
while (!queue.isEmpty()) {
RepositoryResolveState request = queue.removeFirst();
@@ -110,7 +115,7 @@ public class UserResolverChain implements DependencyToModuleResolver {
}
break;
case Resolved:
- ModuleResolution moduleResolution = new ModuleResolution(request.repository, request.descriptor, request.descriptor.getModuleSource());
+ ModuleResolution moduleResolution = new ModuleResolution(request.repository, request.descriptor.getMetaData(), request.descriptor.getModuleSource());
if (isStaticVersion && !moduleResolution.isGeneratedModuleDescriptor()) {
return moduleResolution;
}
@@ -132,9 +137,7 @@ public class UserResolverChain implements DependencyToModuleResolver {
return two.module == null ? one : two;
}
- ComparatorLatestStrategy latestStrategy = (ComparatorLatestStrategy) settings.getDefaultLatestStrategy();
- Comparator<ArtifactInfo> comparator = latestStrategy.getComparator();
- int comparison = comparator.compare(one, two);
+ int comparison = latestStrategy.compare(one, two);
if (comparison == 0) {
if (one.isGeneratedModuleDescriptor() && !two.isGeneratedModuleDescriptor()) {
@@ -156,13 +159,13 @@ public class UserResolverChain implements DependencyToModuleResolver {
}
public void resolve(Artifact artifact, BuildableArtifactResolveResult result) {
- delegate.resolve(artifact, result, moduleSource);
+ delegate.resolve(new DefaultArtifactIdentifier(artifact), result, moduleSource);
}
}
private static class RepositoryResolveState {
final LocalAwareModuleVersionRepository repository;
- final DefaultBuildableModuleVersionMetaData descriptor = new DefaultBuildableModuleVersionMetaData();
+ final DefaultBuildableModuleVersionMetaDataResolveResult descriptor = new DefaultBuildableModuleVersionMetaDataResolveResult();
boolean searchedLocally;
boolean searchedRemotely;
@@ -179,7 +182,7 @@ public class UserResolverChain implements DependencyToModuleResolver {
searchedRemotely = true;
repository.getDependency(dependency, descriptor);
}
- if (descriptor.getState() == BuildableModuleVersionMetaData.State.Failed) {
+ if (descriptor.getState() == BuildableModuleVersionMetaDataResolveResult.State.Failed) {
throw descriptor.getFailure();
}
}
@@ -189,7 +192,7 @@ public class UserResolverChain implements DependencyToModuleResolver {
}
}
- private static class ModuleResolution implements ArtifactInfo {
+ private static class ModuleResolution implements Versioned {
public final ModuleVersionRepository repository;
public final ModuleVersionMetaData module;
public final ModuleSource moduleSource;
@@ -204,11 +207,7 @@ public class UserResolverChain implements DependencyToModuleResolver {
return module.getDescriptor().isDefault();
}
- public long getLastModified() {
- return module.getDescriptor().getResolvedPublicationDate().getTime();
- }
-
- public String getRevision() {
+ public String getVersion() {
return module.getId().getVersion();
}
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/VersionInfo.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/VersionInfo.java
new file mode 100644
index 0000000..8ba0d75
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/VersionInfo.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve;
+
+public class VersionInfo implements Versioned {
+ private final String version;
+
+ public VersionInfo(String version) {
+ this.version = version;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public boolean equals(Object other) {
+ if (!(other instanceof VersionInfo)) {
+ return false;
+ }
+ return version.equals(((VersionInfo) other).getVersion());
+ }
+
+ public int hashCode() {
+ return version.hashCode();
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/Versioned.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/Versioned.java
new file mode 100644
index 0000000..7a4e207
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/Versioned.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve;
+
+public interface Versioned {
+ String getVersion();
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/memcache/CachedModuleVersionResult.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/memcache/CachedModuleVersionResult.java
new file mode 100644
index 0000000..d239657
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/memcache/CachedModuleVersionResult.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve.memcache;
+
+import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
+import org.gradle.api.artifacts.ModuleVersionIdentifier;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.BuildableModuleVersionMetaDataResolveResult;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ModuleSource;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ModuleVersionMetaData;
+
+import static org.gradle.api.internal.artifacts.ivyservice.ivyresolve.BuildableModuleVersionMetaDataResolveResult.State.*;
+
+class CachedModuleVersionResult {
+ private final BuildableModuleVersionMetaDataResolveResult.State state;
+ private final ModuleDescriptor moduleDescriptor;
+ private final boolean isChanging;
+ private final ModuleSource moduleSource;
+ private final ModuleVersionIdentifier id;
+
+ public CachedModuleVersionResult(BuildableModuleVersionMetaDataResolveResult result) {
+ this.state = result.getState();
+ if (state == Resolved) {
+ ModuleVersionMetaData metaData = result.getMetaData();
+ this.id = metaData.getId();
+ this.moduleDescriptor = metaData.getDescriptor();
+ this.isChanging = metaData.isChanging();
+ this.moduleSource = result.getModuleSource();
+ } else {
+ this.id = null;
+ this.moduleDescriptor = null;
+ this.isChanging = false;
+ this.moduleSource = null;
+ }
+ }
+
+ public boolean isCacheable() {
+ return state == Missing || state == ProbablyMissing || state == Resolved;
+ }
+
+ public void supply(BuildableModuleVersionMetaDataResolveResult result) {
+ assert isCacheable() : "Results are not cacheable, cannot supply the results.";
+ if (state == Resolved) {
+ result.resolved(id, moduleDescriptor, isChanging, moduleSource);
+ } else if (state == Missing) {
+ result.missing();
+ } else if (state == ProbablyMissing) {
+ result.probablyMissing();
+ }
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/memcache/CachedRepository.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/memcache/CachedRepository.java
new file mode 100644
index 0000000..1e45b2e
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/memcache/CachedRepository.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve.memcache;
+
+import org.gradle.api.artifacts.ArtifactIdentifier;
+import org.gradle.api.internal.artifacts.ivyservice.BuildableArtifactResolveResult;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.BuildableModuleVersionMetaDataResolveResult;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.DependencyMetaData;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.LocalAwareModuleVersionRepository;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ModuleSource;
+
+class CachedRepository implements LocalAwareModuleVersionRepository {
+ final DependencyMetadataCache cache;
+ final LocalAwareModuleVersionRepository delegate;
+ final DependencyMetadataCacheStats stats;
+
+ public CachedRepository(DependencyMetadataCache cache, LocalAwareModuleVersionRepository delegate, DependencyMetadataCacheStats stats) {
+ this.cache = cache;
+ this.delegate = delegate;
+ this.stats = stats;
+ }
+
+ public String getId() {
+ return delegate.getId();
+ }
+
+ public String getName() {
+ return delegate.getName();
+ }
+
+ public void getLocalDependency(DependencyMetaData dependency, BuildableModuleVersionMetaDataResolveResult result) {
+ if(!cache.supplyLocalMetaData(dependency.getRequested(), result)) {
+ delegate.getLocalDependency(dependency, result);
+ cache.newLocalDependencyResult(dependency.getRequested(), result);
+ }
+ }
+
+ public void getDependency(DependencyMetaData dependency, BuildableModuleVersionMetaDataResolveResult result) {
+ if(!cache.supplyMetaData(dependency.getRequested(), result)) {
+ delegate.getDependency(dependency, result);
+ cache.newDependencyResult(dependency.getRequested(), result);
+ }
+ }
+
+ public void resolve(ArtifactIdentifier artifact, BuildableArtifactResolveResult result, ModuleSource moduleSource) {
+ if(!cache.supplyArtifact(artifact, result)) {
+ delegate.resolve(artifact, result, moduleSource);
+ cache.newArtifact(artifact, result);
+ }
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/memcache/DependencyMetadataCache.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/memcache/DependencyMetadataCache.java
new file mode 100644
index 0000000..bed91f9
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/memcache/DependencyMetadataCache.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve.memcache;
+
+import org.gradle.api.artifacts.ArtifactIdentifier;
+import org.gradle.api.artifacts.ModuleVersionSelector;
+import org.gradle.api.internal.artifacts.ivyservice.BuildableArtifactResolveResult;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.BuildableModuleVersionMetaDataResolveResult;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+
+class DependencyMetadataCache {
+ private final Map<ModuleVersionSelector, CachedModuleVersionResult> localMetaData = new HashMap<ModuleVersionSelector, CachedModuleVersionResult>();
+ private final Map<ModuleVersionSelector, CachedModuleVersionResult> metaData = new HashMap<ModuleVersionSelector, CachedModuleVersionResult>();
+ private final Map<ArtifactIdentifier, File> artifacts = new HashMap<ArtifactIdentifier, File>();
+ private DependencyMetadataCacheStats stats;
+
+ DependencyMetadataCache(DependencyMetadataCacheStats stats) {
+ this.stats = stats;
+ }
+
+ boolean supplyLocalMetaData(ModuleVersionSelector requested, BuildableModuleVersionMetaDataResolveResult result) {
+ return supply(requested, result, localMetaData, stats);
+ }
+
+ boolean supplyMetaData(ModuleVersionSelector requested, BuildableModuleVersionMetaDataResolveResult result) {
+ return supply(requested, result, metaData, stats);
+ }
+
+ private static boolean supply(ModuleVersionSelector requested, BuildableModuleVersionMetaDataResolveResult result, Map<ModuleVersionSelector, CachedModuleVersionResult> map, DependencyMetadataCacheStats stats) {
+ CachedModuleVersionResult fromCache = map.get(requested);
+ if (fromCache == null) {
+ return false;
+ }
+ fromCache.supply(result);
+ stats.metadataServed++;
+ return true;
+ }
+
+ void newLocalDependencyResult(ModuleVersionSelector requested, BuildableModuleVersionMetaDataResolveResult result) {
+ newResult(requested, result, localMetaData);
+ }
+
+ void newDependencyResult(ModuleVersionSelector requested, BuildableModuleVersionMetaDataResolveResult result) {
+ newResult(requested, result, metaData);
+ }
+
+ private static void newResult(ModuleVersionSelector requested, BuildableModuleVersionMetaDataResolveResult result, Map<ModuleVersionSelector, CachedModuleVersionResult> map) {
+ CachedModuleVersionResult cachedResult = new CachedModuleVersionResult(result);
+ if (cachedResult.isCacheable()) {
+ map.put(requested, cachedResult);
+ }
+ }
+
+ public boolean supplyArtifact(ArtifactIdentifier id, BuildableArtifactResolveResult result) {
+ File fromCache = artifacts.get(id);
+ if (fromCache != null) {
+ result.resolved(fromCache);
+ stats.artifactsServed++;
+ return true;
+ }
+ return false;
+ }
+
+ public void newArtifact(ArtifactIdentifier id, BuildableArtifactResolveResult result) {
+ artifacts.put(id, result.getFile());
+ }
+}
\ No newline at end of file
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/memcache/DependencyMetadataCacheStats.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/memcache/DependencyMetadataCacheStats.java
new file mode 100644
index 0000000..127d5e6
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/memcache/DependencyMetadataCacheStats.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve.memcache;
+
+class DependencyMetadataCacheStats {
+ int cacheInstances;
+ int reposWrapped;
+ int metadataServed;
+ int artifactsServed;
+ public String toString() {
+ return String.format(
+ "Repos cached: %s, cache instances: %s, modules served from cache: %s, artifacts: %s",
+ reposWrapped, cacheInstances, metadataServed, artifactsServed);
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/memcache/InMemoryDependencyMetadataCache.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/memcache/InMemoryDependencyMetadataCache.java
new file mode 100644
index 0000000..120d6e1
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/memcache/InMemoryDependencyMetadataCache.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve.memcache;
+
+import com.google.common.collect.MapMaker;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.LocalAwareModuleVersionRepository;
+import org.gradle.api.logging.Logger;
+import org.gradle.api.logging.Logging;
+import org.gradle.internal.Stoppable;
+
+import java.util.Map;
+
+/**
+ * Caches the dependency metadata (descriptors, artifact files) in memory. Uses soft maps to reduce heap pressure.
+ */
+public class InMemoryDependencyMetadataCache implements Stoppable {
+
+ public final static String TOGGLE_PROPERTY = "org.gradle.resolution.memorycache";
+
+ private final static Logger LOG = Logging.getLogger(InMemoryDependencyMetadataCache.class);
+
+ Map<String, DependencyMetadataCache> cachePerRepo = new MapMaker().softValues().makeMap();
+
+ final DependencyMetadataCacheStats stats = new DependencyMetadataCacheStats();
+
+ public LocalAwareModuleVersionRepository cached(LocalAwareModuleVersionRepository input) {
+ if ("false".equalsIgnoreCase(System.getProperty(TOGGLE_PROPERTY))) {
+ return input;
+ }
+
+ DependencyMetadataCache dataCache = cachePerRepo.get(input.getId());
+ stats.reposWrapped++;
+ if (dataCache == null) {
+ LOG.debug("Creating new in-memory cache for repo '{}' [{}].", input.getName(), input.getId());
+ dataCache = new DependencyMetadataCache(stats);
+ stats.cacheInstances++;
+ cachePerRepo.put(input.getId(), dataCache);
+ } else {
+ LOG.debug("Reusing in-memory cache for repo '{}' [{}].", input.getName(), input.getId());
+ }
+ return new CachedRepository(dataCache, input, stats);
+ }
+
+ public void stop() {
+ cachePerRepo.clear();
+ LOG.debug("In-memory dependency metadata cache closed. {}", stats);
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/AbstractDescriptorParseContext.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/AbstractDescriptorParseContext.java
new file mode 100644
index 0000000..e0b97eb
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/AbstractDescriptorParseContext.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser;
+
+import org.apache.ivy.core.IvyPatternHelper;
+import org.apache.ivy.plugins.matcher.PatternMatcher;
+import org.gradle.api.Transformer;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.ResolverStrategy;
+import org.gradle.util.CollectionUtils;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+public abstract class AbstractDescriptorParseContext implements DescriptorParseContext {
+ protected final String defaultStatus;
+ private final Map<String, String> properties = new HashMap<String, String>();
+
+ public AbstractDescriptorParseContext(String defaultStatus) {
+ this.defaultStatus = defaultStatus;
+ populateProperties();
+ }
+
+ private void populateProperties() {
+ String baseDir = new File(".").getAbsolutePath();
+ properties.put("ivy.default.settings.dir", baseDir);
+ properties.put("ivy.basedir", baseDir);
+
+ Set<String> propertyNames = CollectionUtils.collect(System.getProperties().entrySet(), new Transformer<String, Map.Entry<Object, Object>>() {
+ public String transform(Map.Entry<Object, Object> entry) {
+ return entry.getKey().toString();
+ }
+ });
+
+ for (String property : propertyNames) {
+ properties.put(property, System.getProperty(property));
+ }
+ }
+
+ public String substitute(String value) {
+ return IvyPatternHelper.substituteVariables(value, properties);
+ }
+
+ public PatternMatcher getMatcher(String matcherName) {
+ return ResolverStrategy.INSTANCE.getPatternMatcher(matcherName);
+ }
+
+ public String getDefaultStatus() {
+ return defaultStatus;
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/AbstractModuleDescriptorParser.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/AbstractModuleDescriptorParser.java
new file mode 100644
index 0000000..3e59d0f
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/AbstractModuleDescriptorParser.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser;
+
+import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor;
+import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
+import org.gradle.api.internal.externalresource.DefaultLocallyAvailableExternalResource;
+import org.gradle.api.internal.externalresource.LocallyAvailableExternalResource;
+import org.gradle.internal.resource.local.DefaultLocallyAvailableResource;
+import org.gradle.internal.resource.local.LocallyAvailableResource;
+
+import java.io.File;
+
+public abstract class AbstractModuleDescriptorParser implements ModuleDescriptorParser {
+ public ModuleDescriptor parseDescriptor(DescriptorParseContext ivySettings, File descriptorFile, boolean validate) throws MetaDataParseException {
+ LocallyAvailableResource localResource = new DefaultLocallyAvailableResource(descriptorFile);
+ LocallyAvailableExternalResource resource = new DefaultLocallyAvailableExternalResource(descriptorFile.toURI().toString(), localResource);
+ return parseDescriptor(ivySettings, resource, validate);
+ }
+
+ public DefaultModuleDescriptor parseDescriptor(DescriptorParseContext ivySettings, LocallyAvailableExternalResource resource, boolean validate) throws MetaDataParseException {
+ try {
+ return doParseDescriptor(ivySettings, resource, validate);
+ } catch (MetaDataParseException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new MetaDataParseException(getTypeName(), resource, e);
+ }
+ }
+
+ protected abstract String getTypeName();
+
+ protected abstract DefaultModuleDescriptor doParseDescriptor(DescriptorParseContext ivySettings, LocallyAvailableExternalResource resource, boolean validate) throws Exception;
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/DefaultMetaDataParser.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/DefaultMetaDataParser.java
new file mode 100644
index 0000000..b350a05
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/DefaultMetaDataParser.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser;
+
+import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.MutableModuleVersionMetaData;
+import org.gradle.api.internal.externalresource.LocallyAvailableExternalResource;
+
+public class DefaultMetaDataParser implements MetaDataParser {
+ private final ParserRegistry parserRegistry;
+
+ public DefaultMetaDataParser(ParserRegistry parserRegistry) {
+ this.parserRegistry = parserRegistry;
+ }
+
+ public MutableModuleVersionMetaData parseModuleMetaData(LocallyAvailableExternalResource resource, DescriptorParseContext context) throws MetaDataParseException {
+ ModuleDescriptorParser parser = parserRegistry.forResource(resource);
+ ModuleDescriptor moduleDescriptor = parser.parseDescriptor(context, resource, true);
+ return new ModuleDescriptorAdapter(moduleDescriptor.getModuleRevisionId(), moduleDescriptor);
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/DescriptorParseContext.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/DescriptorParseContext.java
new file mode 100644
index 0000000..475fc91
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/DescriptorParseContext.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser;
+
+import org.apache.ivy.core.module.descriptor.Artifact;
+import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
+import org.apache.ivy.core.module.id.ModuleRevisionId;
+import org.apache.ivy.plugins.matcher.PatternMatcher;
+
+public interface DescriptorParseContext {
+
+ String substitute(String value);
+
+ PatternMatcher getMatcher(String matcherName);
+
+ String getDefaultStatus();
+
+ ModuleDescriptor getModuleDescriptor(ModuleRevisionId mRevId);
+
+ boolean artifactExists(Artifact artifact);
+
+ ModuleRevisionId getCurrentRevisionId();
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/DisconnectedDescriptorParseContext.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/DisconnectedDescriptorParseContext.java
new file mode 100644
index 0000000..2c96c10
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/DisconnectedDescriptorParseContext.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser;
+
+import org.apache.ivy.core.module.descriptor.Artifact;
+import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor;
+import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
+import org.apache.ivy.core.module.id.ModuleRevisionId;
+
+import java.util.Date;
+
+/**
+ * An implementation of {@link DescriptorParseContext} that is useful for parsing an ivy.xml file without attempting to download
+ * other resources from a DependencyResolver.
+ */
+public class DisconnectedDescriptorParseContext extends AbstractDescriptorParseContext {
+ public DisconnectedDescriptorParseContext() {
+ super("integration");
+ }
+
+ public ModuleDescriptor getModuleDescriptor(ModuleRevisionId mRevId) {
+ return new DefaultModuleDescriptor(mRevId, "release", new Date());
+ }
+
+ public boolean artifactExists(Artifact artifact) {
+ return false;
+ }
+
+ public ModuleRevisionId getCurrentRevisionId() {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/DisconnectedParserSettings.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/DisconnectedParserSettings.java
deleted file mode 100644
index 67fc733..0000000
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/DisconnectedParserSettings.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright 2013 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser;
-
-import org.apache.ivy.core.RelativeUrlResolver;
-import org.apache.ivy.core.cache.ResolutionCacheManager;
-import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor;
-import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
-import org.apache.ivy.core.module.id.ModuleId;
-import org.apache.ivy.core.module.id.ModuleRevisionId;
-import org.apache.ivy.core.module.status.StatusManager;
-import org.apache.ivy.core.resolve.ResolveData;
-import org.apache.ivy.core.resolve.ResolvedModuleRevision;
-import org.apache.ivy.core.settings.IvySettings;
-import org.apache.ivy.plugins.conflict.ConflictManager;
-import org.apache.ivy.plugins.matcher.PatternMatcher;
-import org.apache.ivy.plugins.namespace.Namespace;
-import org.apache.ivy.plugins.parser.ParserSettings;
-import org.apache.ivy.plugins.resolver.DependencyResolver;
-import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.RestrictedDependencyResolver;
-
-import java.io.File;
-import java.text.ParseException;
-import java.util.Date;
-import java.util.Map;
-
-/**
- * An implementation of {@link ParserSettings} that is useful for parsing an ivy.xml file without attempting to download
- * other resources from a DependencyResolver.
- */
-public class DisconnectedParserSettings implements ParserSettings {
- private final IvySettings ivySettings = new IvySettings();
-
- /**
- * This implementation will not attempt to download any parent modules.
- * TODO:DAZ Work out how to do the actual download if we want to do more validation when publishing.
- */
- public DependencyResolver getResolver(final ModuleRevisionId mRevId) {
- return new RestrictedDependencyResolver() {
- @Override
- public ResolvedModuleRevision getDependency(DependencyDescriptor dd, ResolveData data) throws ParseException {
- return new ResolvedModuleRevision(null, null, new DefaultModuleDescriptor(mRevId, "release", new Date()), null);
- }
- };
- }
-
- public String substitute(String value) {
- return ivySettings.substitute(value);
- }
-
- public PatternMatcher getMatcher(String matcherName) {
- return ivySettings.getMatcher(matcherName);
- }
-
- public StatusManager getStatusManager() {
- return ivySettings.getStatusManager();
- }
-
- public ConflictManager getConflictManager(String name) {
- return ivySettings.getConflictManager(name);
- }
-
- public Namespace getNamespace(String namespace) {
- return ivySettings.getNamespace(namespace);
- }
-
- public Namespace getContextNamespace() {
- return ivySettings.getContextNamespace();
- }
-
- // The reset of the methods are not used when parsing an ivy.xml
- public Map substitute(Map strings) {
- throw unsupported();
- }
-
- public ResolutionCacheManager getResolutionCacheManager() {
- throw unsupported();
- }
-
- public RelativeUrlResolver getRelativeUrlResolver() {
- throw unsupported();
- }
-
- public File resolveFile(String filename) {
- throw unsupported();
- }
-
- public String getDefaultBranch(ModuleId moduleId) {
- throw unsupported();
- }
-
- private UnsupportedOperationException unsupported() {
- return new UnsupportedOperationException();
- }
-
-}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/DownloadedIvyModuleDescriptorParser.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/DownloadedIvyModuleDescriptorParser.java
index f1758d3..3c28fe4 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/DownloadedIvyModuleDescriptorParser.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/DownloadedIvyModuleDescriptorParser.java
@@ -17,17 +17,12 @@
package org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser;
import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor;
-import org.apache.ivy.plugins.parser.ParserSettings;
-import org.apache.ivy.plugins.repository.Resource;
-
-import java.io.IOException;
-import java.net.URL;
-import java.text.ParseException;
+import org.gradle.api.internal.externalresource.LocallyAvailableExternalResource;
public class DownloadedIvyModuleDescriptorParser extends IvyXmlModuleDescriptorParser {
@Override
- public DefaultModuleDescriptor parseDescriptor(ParserSettings ivySettings, URL xmlURL, Resource res, boolean validate) throws ParseException, IOException {
- DefaultModuleDescriptor descriptor = super.parseDescriptor(ivySettings, xmlURL, res, validate);
+ public DefaultModuleDescriptor parseDescriptor(DescriptorParseContext ivySettings, LocallyAvailableExternalResource resource, boolean validate) throws MetaDataParseException {
+ DefaultModuleDescriptor descriptor = super.parseDescriptor(ivySettings, resource, validate);
descriptor.setDefault(false);
return descriptor;
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/GradlePomModuleDescriptorBuilder.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/GradlePomModuleDescriptorBuilder.java
index f7b3517..66cf7cb 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/GradlePomModuleDescriptorBuilder.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/GradlePomModuleDescriptorBuilder.java
@@ -16,7 +16,6 @@
package org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser;
import org.apache.ivy.Ivy;
-import org.apache.ivy.core.cache.ArtifactOrigin;
import org.apache.ivy.core.module.descriptor.*;
import org.apache.ivy.core.module.descriptor.Configuration.Visibility;
import org.apache.ivy.core.module.id.ArtifactId;
@@ -24,15 +23,13 @@ import org.apache.ivy.core.module.id.ModuleId;
import org.apache.ivy.core.module.id.ModuleRevisionId;
import org.apache.ivy.plugins.matcher.ExactPatternMatcher;
import org.apache.ivy.plugins.matcher.PatternMatcher;
-import org.apache.ivy.plugins.parser.ModuleDescriptorParser;
-import org.apache.ivy.plugins.parser.ParserSettings;
import org.apache.ivy.plugins.parser.m2.DefaultPomDependencyMgt;
import org.apache.ivy.plugins.parser.m2.PomDependencyMgt;
-import org.apache.ivy.plugins.parser.m2.PomReader.PomDependencyData;
-import org.apache.ivy.plugins.repository.Resource;
-import org.apache.ivy.plugins.resolver.DependencyResolver;
-import org.apache.ivy.util.Message;
+import org.apache.ivy.plugins.parser.xml.XmlModuleDescriptorParser;
+import org.gradle.api.internal.externalresource.ExternalResource;
import org.gradle.util.DeprecationLogger;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.util.*;
import java.util.Map.Entry;
@@ -43,6 +40,7 @@ import java.util.Map.Entry;
* classifiers)
*/
public class GradlePomModuleDescriptorBuilder {
+ private static final Logger LOGGER = LoggerFactory.getLogger(GradlePomModuleDescriptorBuilder.class);
private static final int DEPENDENCY_MANAGEMENT_KEY_PARTS_COUNT = 4;
@@ -164,15 +162,10 @@ public class GradlePomModuleDescriptorBuilder {
private ModuleRevisionId mrid;
- private ParserSettings parserSettings;
+ private DescriptorParseContext parserSettings;
- private static final String WRONG_NUMBER_OF_PARTS_MSG = "what seemed to be a dependency "
- + "management extra info exclusion had the wrong number of parts (should have 2) ";
-
-
- public GradlePomModuleDescriptorBuilder(
- ModuleDescriptorParser parser, Resource res, ParserSettings ivySettings) {
- ivyModuleDescriptor = new DefaultModuleDescriptor(parser, res);
+ public GradlePomModuleDescriptorBuilder(ExternalResource res, DescriptorParseContext ivySettings) {
+ ivyModuleDescriptor = new DefaultModuleDescriptor(XmlModuleDescriptorParser.getInstance(), null);
ivyModuleDescriptor.setResolvedPublicationDate(new Date(res.getLastModified()));
for (Configuration maven2Configuration : MAVEN2_CONFIGURATIONS) {
ivyModuleDescriptor.addConfiguration(maven2Configuration);
@@ -182,7 +175,7 @@ public class GradlePomModuleDescriptorBuilder {
parserSettings = ivySettings;
}
- public ModuleDescriptor getModuleDescriptor() {
+ public DefaultModuleDescriptor getModuleDescriptor() {
return ivyModuleDescriptor;
}
@@ -213,34 +206,22 @@ public class GradlePomModuleDescriptorBuilder {
public void addMainArtifact(String artifactId, String packaging) {
if ("pom".equals(packaging)) {
- // no artifact defined! Add the default artifact only if it exists
- DependencyResolver resolver = parserSettings.getResolver(mrid);
-
- if (resolver != null) {
- DefaultArtifact artifact = new DefaultArtifact(mrid, new Date(), artifactId, "jar", "jar");
-
- if (!ArtifactOrigin.isUnknown(resolver.locate(artifact))) {
- ivyModuleDescriptor.addArtifact("master", artifact);
- }
+ DefaultArtifact artifact = new DefaultArtifact(mrid, new Date(), artifactId, "jar", "jar");
+ if (parserSettings.artifactExists(artifact)) {
+ ivyModuleDescriptor.addArtifact("master", artifact);
}
return;
}
if (!isKnownJarPackaging(packaging)) {
- // Look for an artifact with extension = packaging. This is deprecated.
- DependencyResolver resolver = parserSettings.getResolver(mrid);
-
- if (resolver != null) {
- DefaultArtifact artifact = new DefaultArtifact(mrid, new Date(), artifactId, packaging, packaging);
+ DefaultArtifact artifact = new DefaultArtifact(mrid, new Date(), artifactId, packaging, packaging);
- if (!ArtifactOrigin.isUnknown(resolver.locate(artifact))) {
- ivyModuleDescriptor.addArtifact("master", artifact);
+ if (parserSettings.artifactExists(artifact)) {
+ ivyModuleDescriptor.addArtifact("master", artifact);
- DeprecationLogger.nagUserOfDeprecated("Relying on packaging to define the extension of the main artifact");
-
- return;
- }
+ DeprecationLogger.nagUserOfDeprecated("Relying on packaging to define the extension of the main artifact");
+ return;
}
}
@@ -251,7 +232,7 @@ public class GradlePomModuleDescriptorBuilder {
return "jar".equals(packaging) || JAR_PACKAGINGS.contains(packaging);
}
- public void addDependency(PomDependencyData dep) {
+ public void addDependency(PomReader.PomDependencyData dep) {
String scope = dep.getScope();
if ((scope != null) && (scope.length() > 0) && !MAVEN2_CONF_MAPPING.containsKey(scope)) {
// unknown scope, defaulting to 'compile'
@@ -328,7 +309,7 @@ public class GradlePomModuleDescriptorBuilder {
}
public void addDependency(DependencyDescriptor descriptor) {
- // Some POMs depend on theirselfves through their parent pom, don't add this dependency
+ // Some POMs depend on theirselfves through their parent POM, don't add this dependency
// since Ivy doesn't allow this!
// Example: http://repo2.maven.org/maven2/com/atomikos/atomikos-util/3.6.4/atomikos-util-3.6.4.pom
ModuleId dependencyId = descriptor.getDependencyId();
@@ -424,12 +405,12 @@ public class GradlePomModuleDescriptorBuilder {
}
}
- private String getDefaultVersion(PomDependencyData dep) {
+ private String getDefaultVersion(PomReader.PomDependencyData dep) {
String key = getDependencyMgtExtraInfoKeyForVersion(dep.getGroupId(), dep.getArtifactId());
return (String) ivyModuleDescriptor.getExtraInfo().get(key);
}
- private String getDefaultScope(PomDependencyData dep) {
+ private String getDefaultScope(PomReader.PomDependencyData dep) {
String key = getDependencyMgtExtraInfoKeyForScope(dep.getGroupId(), dep.getArtifactId());
String result = (String) ivyModuleDescriptor.getExtraInfo().get(key);
if ((result == null) || !MAVEN2_CONF_MAPPING.containsKey(result)) {
@@ -469,8 +450,8 @@ public class GradlePomModuleDescriptorBuilder {
String fullExclusion = entry.getValue();
String[] exclusionParts = fullExclusion.split(EXTRA_INFO_DELIMITER);
if (exclusionParts.length != 2) {
- Message.error(WRONG_NUMBER_OF_PARTS_MSG + exclusionParts.length + " : "
- + fullExclusion);
+ LOGGER.error("Wrong number of parts for dependency management extra info exclusion: expect 2, found {}: {}",
+ exclusionParts.length, fullExclusion);
continue;
}
exclusionIds.add(ModuleId.newInstance(exclusionParts[0], exclusionParts[1]));
@@ -489,7 +470,7 @@ public class GradlePomModuleDescriptorBuilder {
if (key.startsWith(DEPENDENCY_MANAGEMENT)) {
String[] parts = key.split(EXTRA_INFO_DELIMITER);
if (parts.length != DEPENDENCY_MANAGEMENT_KEY_PARTS_COUNT) {
- Message.warn("what seem to be a dependency management extra info doesn't match expected pattern: " + key);
+ LOGGER.warn("Dependency management extra info doesn't match expected pattern: {}", key);
} else {
String versionKey = DEPENDENCY_MANAGEMENT + EXTRA_INFO_DELIMITER + parts[1]
+ EXTRA_INFO_DELIMITER + parts[2]
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/GradlePomModuleDescriptorParser.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/GradlePomModuleDescriptorParser.java
index e9209fd..f814e1b 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/GradlePomModuleDescriptorParser.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/GradlePomModuleDescriptorParser.java
@@ -15,36 +15,18 @@
*/
package org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser;
-import org.apache.ivy.core.IvyContext;
import org.apache.ivy.core.module.descriptor.*;
import org.apache.ivy.core.module.descriptor.Configuration.Visibility;
import org.apache.ivy.core.module.id.ModuleRevisionId;
-import org.apache.ivy.core.resolve.ResolveData;
-import org.apache.ivy.core.resolve.ResolveEngine;
-import org.apache.ivy.core.resolve.ResolveOptions;
-import org.apache.ivy.core.resolve.ResolvedModuleRevision;
-import org.apache.ivy.plugins.namespace.NameSpaceHelper;
-import org.apache.ivy.plugins.parser.ModuleDescriptorParser;
-import org.apache.ivy.plugins.parser.ParserSettings;
import org.apache.ivy.plugins.parser.m2.PomDependencyMgt;
-import org.apache.ivy.plugins.parser.m2.PomReader;
-import org.apache.ivy.plugins.repository.Resource;
-import org.apache.ivy.plugins.repository.url.URLResource;
-import org.apache.ivy.plugins.resolver.DependencyResolver;
-import org.apache.ivy.util.Message;
-import org.gradle.internal.UncheckedException;
+import org.gradle.api.internal.externalresource.ExternalResource;
+import org.gradle.api.internal.externalresource.LocallyAvailableExternalResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException;
-import java.io.File;
import java.io.IOException;
-import java.io.InputStream;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import java.net.URL;
import java.text.ParseException;
-import java.util.Date;
import java.util.List;
import java.util.Map;
@@ -52,245 +34,177 @@ import java.util.Map;
* This a straight copy of org.apache.ivy.plugins.parser.m2.PomModuleDescriptorParser, with one change: we do NOT attempt to retrieve source and javadoc artifacts when parsing the POM. This cuts the
* number of remote call in half to resolve a module.
*/
-public final class GradlePomModuleDescriptorParser implements ModuleDescriptorParser {
- public void toIvyFile(InputStream is, Resource res, File destFile, ModuleDescriptor md)
- throws ParseException, IOException {
- throw new UnsupportedOperationException();
- }
+public final class GradlePomModuleDescriptorParser extends AbstractModuleDescriptorParser {
+ private static final Logger LOGGER = LoggerFactory.getLogger(GradlePomModuleDescriptorParser.class);
- public boolean accept(Resource res) {
+ public boolean accept(ExternalResource res) {
return res.getName().endsWith(".pom") || res.getName().endsWith("pom.xml")
|| res.getName().endsWith("project.xml");
}
- public String toString() {
- return "gradle pom parser";
- }
-
- public Artifact getMetadataArtifact(ModuleRevisionId mrid, Resource res) {
- return DefaultArtifact.newPomArtifact(mrid, new Date(res.getLastModified()));
- }
-
- public String getType() {
- return "pom";
+ @Override
+ protected String getTypeName() {
+ return "POM";
}
- public ModuleDescriptor parseDescriptor(ParserSettings ivySettings, URL descriptorURL,
- boolean validate) throws ParseException, IOException {
- URLResource resource = new URLResource(descriptorURL);
- return parseDescriptor(ivySettings, descriptorURL, resource, validate);
+ public String toString() {
+ return "gradle pom parser";
}
- public ModuleDescriptor parseDescriptor(ParserSettings ivySettings, URL descriptorURL,
- Resource resource, boolean validate) throws ParseException, IOException {
+ protected DefaultModuleDescriptor doParseDescriptor(DescriptorParseContext parserSettings, LocallyAvailableExternalResource resource, boolean validate) throws IOException, ParseException, SAXException {
+ GradlePomModuleDescriptorBuilder mdBuilder = new GradlePomModuleDescriptorBuilder(resource, parserSettings);
- Resource res = encodedUrlResource(resource, descriptorURL);
- GradlePomModuleDescriptorBuilder mdBuilder = new GradlePomModuleDescriptorBuilder(this, res, ivySettings);
+ PomReader pomReader = new PomReader(resource);
+ pomReader.setProperty("parent.version", pomReader.getParentVersion());
+ pomReader.setProperty("parent.groupId", pomReader.getParentGroupId());
+ pomReader.setProperty("project.parent.version", pomReader.getParentVersion());
+ pomReader.setProperty("project.parent.groupId", pomReader.getParentGroupId());
- try {
- PomReader domReader = new PomReader(descriptorURL, res);
- domReader.setProperty("parent.version", domReader.getParentVersion());
- domReader.setProperty("parent.groupId", domReader.getParentGroupId());
- domReader.setProperty("project.parent.version", domReader.getParentVersion());
- domReader.setProperty("project.parent.groupId", domReader.getParentGroupId());
+ Map pomProperties = pomReader.getPomProperties();
+ for (Object o : pomProperties.entrySet()) {
+ Map.Entry prop = (Map.Entry) o;
+ pomReader.setProperty((String) prop.getKey(), (String) prop.getValue());
+ mdBuilder.addProperty((String) prop.getKey(), (String) prop.getValue());
+ }
- Map pomProperties = domReader.getPomProperties();
- for (Object o : pomProperties.entrySet()) {
- Map.Entry prop = (Map.Entry) o;
- domReader.setProperty((String) prop.getKey(), (String) prop.getValue());
- mdBuilder.addProperty((String) prop.getKey(), (String) prop.getValue());
+ ModuleDescriptor parentDescr = null;
+ if (pomReader.hasParent()) {
+ //Is there any other parent properties?
+
+ ModuleRevisionId parentModRevID = ModuleRevisionId.newInstance(
+ pomReader.getParentGroupId(),
+ pomReader.getParentArtifactId(),
+ pomReader.getParentVersion());
+ parentDescr = parseOtherPom(parserSettings, parentModRevID);
+ if (parentDescr == null) {
+ throw new IOException("Impossible to load parent for " + resource.getName() + ". Parent=" + parentModRevID);
}
-
- ModuleDescriptor parentDescr = null;
- if (domReader.hasParent()) {
- //Is there any other parent properties?
-
- ModuleRevisionId parentModRevID = ModuleRevisionId.newInstance(
- domReader.getParentGroupId(),
- domReader.getParentArtifactId(),
- domReader.getParentVersion());
- ResolvedModuleRevision parentModule = parseOtherPom(ivySettings, parentModRevID);
- if (parentModule != null) {
- parentDescr = parentModule.getDescriptor();
- } else {
- throw new IOException("Impossible to load parent for " + res.getName() + ". Parent=" + parentModRevID);
- }
- if (parentDescr != null) {
- Map parentPomProps = GradlePomModuleDescriptorBuilder.extractPomProperties(parentDescr.getExtraInfo());
- for (Object o : parentPomProps.entrySet()) {
- Map.Entry prop = (Map.Entry) o;
- domReader.setProperty((String) prop.getKey(), (String) prop.getValue());
- }
- }
+ Map parentPomProps = GradlePomModuleDescriptorBuilder.extractPomProperties(parentDescr.getExtraInfo());
+ for (Object o : parentPomProps.entrySet()) {
+ Map.Entry prop = (Map.Entry) o;
+ pomReader.setProperty((String) prop.getKey(), (String) prop.getValue());
}
+ }
- String groupId = domReader.getGroupId();
- String artifactId = domReader.getArtifactId();
- String version = domReader.getVersion();
- ModuleScopedParserSettings scopedSettings = (ModuleScopedParserSettings) ivySettings;
- mdBuilder.setModuleRevId(scopedSettings.getCurrentRevisionId(), groupId, artifactId, version);
-
- mdBuilder.setHomePage(domReader.getHomePage());
- mdBuilder.setDescription(domReader.getDescription());
- mdBuilder.setLicenses(domReader.getLicenses());
-
- ModuleRevisionId relocation = domReader.getRelocation();
-
- if (relocation != null) {
- if (groupId != null && artifactId != null
- && artifactId.equals(relocation.getName())
- && groupId.equals(relocation.getOrganisation())) {
- Message.error("Relocation to an other version number not supported in ivy : "
+ String groupId = pomReader.getGroupId();
+ String artifactId = pomReader.getArtifactId();
+ String version = pomReader.getVersion();
+ mdBuilder.setModuleRevId(parserSettings.getCurrentRevisionId(), groupId, artifactId, version);
+
+ mdBuilder.setHomePage(pomReader.getHomePage());
+ mdBuilder.setDescription(pomReader.getDescription());
+ mdBuilder.setLicenses(pomReader.getLicenses());
+
+ ModuleRevisionId relocation = pomReader.getRelocation();
+
+ if (relocation != null) {
+ if (groupId != null && artifactId != null
+ && artifactId.equals(relocation.getName())
+ && groupId.equals(relocation.getOrganisation())) {
+ LOGGER.error("POM relocation to an other version number is not fully supported in Gradle : {} relocated to {}.",
+ mdBuilder.getModuleDescriptor().getModuleRevisionId(), relocation);
+ LOGGER.warn("Please update your dependency to directly use the correct version '{}'.", relocation);
+ LOGGER.warn("Resolution will only pick dependencies of the relocated element. Artifacts and other metadata will be ignored.");
+ ModuleDescriptor relocatedModule = parseOtherPom(parserSettings, relocation);
+ if (relocatedModule == null) {
+ throw new ParseException("impossible to load module "
+ + relocation + " to which "
+ mdBuilder.getModuleDescriptor().getModuleRevisionId()
- + " relocated to " + relocation
- + ". Please update your dependency to directly use the right version.");
- Message.warn("Resolution will only pick dependencies of the relocated element."
- + " Artefact and other metadata will be ignored.");
- ResolvedModuleRevision relocatedModule = parseOtherPom(ivySettings, relocation);
- if (relocatedModule == null) {
- throw new ParseException("impossible to load module "
- + relocation + " to which "
- + mdBuilder.getModuleDescriptor().getModuleRevisionId()
- + " has been relocated", 0);
- }
- DependencyDescriptor[] dds = relocatedModule.getDescriptor().getDependencies();
- for (DependencyDescriptor dd : dds) {
- mdBuilder.addDependency(dd);
- }
- } else {
- Message.info(mdBuilder.getModuleDescriptor().getModuleRevisionId()
- + " is relocated to " + relocation
- + ". Please update your dependencies.");
- Message.verbose("Relocated module will be considered as a dependency");
- DefaultDependencyDescriptor dd = new DefaultDependencyDescriptor(mdBuilder.getModuleDescriptor(), relocation, true, false, true);
- /* Map all public dependencies */
- Configuration[] m2Confs = GradlePomModuleDescriptorBuilder.MAVEN2_CONFIGURATIONS;
- for (Configuration m2Conf : m2Confs) {
- if (Visibility.PUBLIC.equals(m2Conf.getVisibility())) {
- dd.addDependencyConfiguration(m2Conf.getName(), m2Conf.getName());
- }
- }
+ + " has been relocated", 0);
+ }
+ DependencyDescriptor[] dds = relocatedModule.getDependencies();
+ for (DependencyDescriptor dd : dds) {
mdBuilder.addDependency(dd);
}
} else {
- domReader.setProperty("project.groupId", groupId);
- domReader.setProperty("pom.groupId", groupId);
- domReader.setProperty("groupId", groupId);
- domReader.setProperty("project.artifactId", artifactId);
- domReader.setProperty("pom.artifactId", artifactId);
- domReader.setProperty("artifactId", artifactId);
- domReader.setProperty("project.version", version);
- domReader.setProperty("pom.version", version);
- domReader.setProperty("version", version);
-
- if (parentDescr != null) {
- mdBuilder.addExtraInfos(parentDescr.getExtraInfo());
-
- // add dependency management info from parent
- List depMgt = GradlePomModuleDescriptorBuilder.getDependencyManagements(parentDescr);
- for (Object aDepMgt : depMgt) {
- mdBuilder.addDependencyMgt((PomDependencyMgt) aDepMgt);
- }
-
- // add plugins from parent
- List /*<PomDependencyMgt>*/ plugins = GradlePomModuleDescriptorBuilder.getPlugins(parentDescr);
- for (Object plugin : plugins) {
- mdBuilder.addPlugin((PomDependencyMgt) plugin);
+ LOGGER.info(mdBuilder.getModuleDescriptor().getModuleRevisionId()
+ + " is relocated to " + relocation
+ + ". Please update your dependencies.");
+ LOGGER.debug("Relocated module will be considered as a dependency");
+ DefaultDependencyDescriptor dd = new DefaultDependencyDescriptor(mdBuilder.getModuleDescriptor(), relocation, true, false, true);
+ /* Map all public dependencies */
+ Configuration[] m2Confs = GradlePomModuleDescriptorBuilder.MAVEN2_CONFIGURATIONS;
+ for (Configuration m2Conf : m2Confs) {
+ if (Visibility.PUBLIC.equals(m2Conf.getVisibility())) {
+ dd.addDependencyConfiguration(m2Conf.getName(), m2Conf.getName());
}
}
-
- for (Object o : domReader.getDependencyMgt()) {
- PomDependencyMgt dep = (PomDependencyMgt) o;
- if ("import".equals(dep.getScope())) {
- ModuleRevisionId importModRevID = ModuleRevisionId.newInstance(
- dep.getGroupId(),
- dep.getArtifactId(),
- dep.getVersion());
- ResolvedModuleRevision importModule = parseOtherPom(ivySettings, importModRevID);
- if (importModule != null) {
- ModuleDescriptor importDescr = importModule.getDescriptor();
-
- // add dependency management info from imported module
- List depMgt = GradlePomModuleDescriptorBuilder.getDependencyManagements(importDescr);
- for (Object aDepMgt : depMgt) {
- mdBuilder.addDependencyMgt((PomDependencyMgt) aDepMgt);
- }
- } else {
- throw new IOException("Impossible to import module for " + res.getName() + "."
- + " Import=" + importModRevID);
- }
-
- } else {
- mdBuilder.addDependencyMgt(dep);
- }
+ mdBuilder.addDependency(dd);
+ }
+ } else {
+ pomReader.setProperty("project.groupId", groupId);
+ pomReader.setProperty("pom.groupId", groupId);
+ pomReader.setProperty("groupId", groupId);
+ pomReader.setProperty("project.artifactId", artifactId);
+ pomReader.setProperty("pom.artifactId", artifactId);
+ pomReader.setProperty("artifactId", artifactId);
+ pomReader.setProperty("project.version", version);
+ pomReader.setProperty("pom.version", version);
+ pomReader.setProperty("version", version);
+
+ if (parentDescr != null) {
+ mdBuilder.addExtraInfos(parentDescr.getExtraInfo());
+
+ // add dependency management info from parent
+ List depMgt = GradlePomModuleDescriptorBuilder.getDependencyManagements(parentDescr);
+ for (Object aDepMgt : depMgt) {
+ mdBuilder.addDependencyMgt((PomDependencyMgt) aDepMgt);
}
- for (Object o : domReader.getDependencies()) {
- PomReader.PomDependencyData dep = (PomReader.PomDependencyData) o;
- mdBuilder.addDependency(dep);
+ // add plugins from parent
+ List /*<PomDependencyMgt>*/ plugins = GradlePomModuleDescriptorBuilder.getPlugins(parentDescr);
+ for (Object plugin : plugins) {
+ mdBuilder.addPlugin((PomDependencyMgt) plugin);
}
+ }
- if (parentDescr != null) {
- for (int i = 0; i < parentDescr.getDependencies().length; i++) {
- mdBuilder.addDependency(parentDescr.getDependencies()[i]);
+ for (Object o : pomReader.getDependencyMgt()) {
+ PomDependencyMgt dep = (PomDependencyMgt) o;
+ if ("import".equals(dep.getScope())) {
+ ModuleRevisionId importModRevID = ModuleRevisionId.newInstance(
+ dep.getGroupId(),
+ dep.getArtifactId(),
+ dep.getVersion());
+ ModuleDescriptor importDescr = parseOtherPom(parserSettings, importModRevID);
+ if (importDescr == null) {
+ throw new IOException("Impossible to import module for " + resource.getName() + "."
+ + " Import=" + importModRevID);
+ }
+ // add dependency management info from imported module
+ List depMgt = GradlePomModuleDescriptorBuilder.getDependencyManagements(importDescr);
+ for (Object aDepMgt : depMgt) {
+ mdBuilder.addDependencyMgt((PomDependencyMgt) aDepMgt);
}
- }
- for (Object o : domReader.getPlugins()) {
- PomReader.PomPluginElement plugin = (PomReader.PomPluginElement) o;
- mdBuilder.addPlugin(plugin);
+ } else {
+ mdBuilder.addDependencyMgt(dep);
}
+ }
- mdBuilder.addMainArtifact(artifactId, domReader.getPackaging());
+ for (Object o : pomReader.getDependencies()) {
+ PomReader.PomDependencyData dep = (PomReader.PomDependencyData) o;
+ mdBuilder.addDependency(dep);
}
- } catch (SAXException e) {
- throw newParserException(e);
- }
- return mdBuilder.getModuleDescriptor();
- }
+ if (parentDescr != null) {
+ for (int i = 0; i < parentDescr.getDependencies().length; i++) {
+ mdBuilder.addDependency(parentDescr.getDependencies()[i]);
+ }
+ }
- private ResolvedModuleRevision parseOtherPom(ParserSettings ivySettings,
- ModuleRevisionId parentModRevID) throws ParseException {
- DependencyDescriptor dd = new DefaultDependencyDescriptor(parentModRevID, true);
- ResolveData data = IvyContext.getContext().getResolveData();
- if (data == null) {
- ResolveEngine engine = IvyContext.getContext().getIvy().getResolveEngine();
- ResolveOptions options = new ResolveOptions();
- options.setDownload(false);
- data = new ResolveData(engine, options);
- }
+ for (Object o : pomReader.getPlugins()) {
+ PomReader.PomPluginElement plugin = (PomReader.PomPluginElement) o;
+ mdBuilder.addPlugin(plugin);
+ }
- DependencyResolver resolver = ivySettings.getResolver(parentModRevID);
- if (resolver == null) {
- // TODO: Throw exception here?
- return null;
- } else {
- dd = NameSpaceHelper.toSystem(dd, ivySettings.getContextNamespace());
- return resolver.getDependency(dd, data);
+ mdBuilder.addMainArtifact(artifactId, pomReader.getPackaging());
}
- }
- private ParseException newParserException(Exception e) {
- Message.error(e.getMessage());
- ParseException pe = new ParseException(e.getMessage(), 0);
- pe.initCause(e);
- return pe;
+ return mdBuilder.getModuleDescriptor();
}
- private Resource encodedUrlResource(final Resource base, final URL url) {
- Object proxy = Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{Resource.class}, new InvocationHandler() {
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- if ("getName".equals(method.getName())) {
- return url.toString();
- }
- try {
- return method.invoke(base, args);
- } catch (InvocationTargetException e) {
- throw UncheckedException.throwAsUncheckedException(e.getTargetException());
- }
- }
- });
- return (Resource) proxy;
+ private ModuleDescriptor parseOtherPom(DescriptorParseContext ivySettings,
+ ModuleRevisionId parentModRevID) throws ParseException {
+ return ivySettings.getModuleDescriptor(parentModRevID);
}
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/IvyXmlModuleDescriptorParser.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/IvyXmlModuleDescriptorParser.java
index 4476247..45135bf 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/IvyXmlModuleDescriptorParser.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/IvyXmlModuleDescriptorParser.java
@@ -16,51 +16,43 @@
package org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser;
-import org.apache.ivy.core.IvyContext;
+import com.google.common.base.Joiner;
import org.apache.ivy.core.NormalRelativeUrlResolver;
import org.apache.ivy.core.RelativeUrlResolver;
import org.apache.ivy.core.module.descriptor.*;
import org.apache.ivy.core.module.id.ArtifactId;
import org.apache.ivy.core.module.id.ModuleId;
import org.apache.ivy.core.module.id.ModuleRevisionId;
-import org.apache.ivy.core.resolve.ResolveData;
-import org.apache.ivy.core.resolve.ResolveEngine;
-import org.apache.ivy.core.resolve.ResolveOptions;
-import org.apache.ivy.core.resolve.ResolvedModuleRevision;
import org.apache.ivy.plugins.matcher.PatternMatcher;
-import org.apache.ivy.plugins.namespace.NameSpaceHelper;
import org.apache.ivy.plugins.namespace.Namespace;
-import org.apache.ivy.plugins.parser.AbstractModuleDescriptorParser;
-import org.apache.ivy.plugins.parser.ModuleDescriptorParser;
-import org.apache.ivy.plugins.parser.ParserSettings;
-import org.apache.ivy.plugins.repository.Resource;
-import org.apache.ivy.plugins.repository.url.URLResource;
-import org.apache.ivy.plugins.resolver.DependencyResolver;
+import org.apache.ivy.plugins.parser.xml.XmlModuleDescriptorParser;
import org.apache.ivy.util.XMLHelper;
import org.apache.ivy.util.extendable.DefaultExtendableItem;
-import org.apache.ivy.util.extendable.ExtendableItemHelper;
+import org.gradle.api.Action;
+import org.gradle.api.internal.externalresource.ExternalResource;
+import org.gradle.api.internal.externalresource.LocallyAvailableExternalResource;
+import org.gradle.api.internal.externalresource.UrlExternalResource;
import org.gradle.util.DeprecationLogger;
+import org.gradle.util.TextUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.ParserConfigurationException;
-import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.ParseException;
import java.text.SimpleDateFormat;
-import java.util.Arrays;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
/**
- * Copied from org.apache.ivy.plugins.parser.xml.XmlModuleDescriptorParser into gradle codebase to make
- * it thread-safe.
+ * Copied from org.apache.ivy.plugins.parser.xml.XmlModuleDescriptorParser into Gradle codebase.
*/
public class IvyXmlModuleDescriptorParser extends AbstractModuleDescriptorParser {
static final String[] DEPENDENCY_REGULAR_ATTRIBUTES =
@@ -70,25 +62,315 @@ public class IvyXmlModuleDescriptorParser extends AbstractModuleDescriptorParser
private static final Logger LOGGER = LoggerFactory.getLogger(IvyXmlModuleDescriptorParser.class);
- public DefaultModuleDescriptor parseDescriptor(ParserSettings ivySettings, URL xmlURL, Resource res, boolean validate) throws ParseException, IOException {
- Parser parser = new Parser(this, ivySettings, res);
+ protected DefaultModuleDescriptor doParseDescriptor(DescriptorParseContext ivySettings, LocallyAvailableExternalResource resource, boolean validate) throws IOException, ParseException {
+ Parser parser = new Parser(this, ivySettings, resource, resource.getLocalResource().getFile().toURI().toURL());
parser.setValidate(validate);
- parser.setInput(xmlURL);
parser.parse();
- return (DefaultModuleDescriptor) parser.getModuleDescriptor();
+ return parser.getModuleDescriptor();
}
- public ModuleDescriptor parseDescriptor(ParserSettings ivySettings, URL descriptorURL, boolean validate) throws ParseException, IOException {
- return parseDescriptor(ivySettings, descriptorURL, new URLResource(descriptorURL), validate);
+ @Override
+ protected String getTypeName() {
+ return "Ivy file";
}
- public boolean accept(Resource res) {
+ public boolean accept(ExternalResource res) {
return true; // this the default parser, it thus accepts all resources
}
- public void toIvyFile(InputStream is, Resource res, File destFile, ModuleDescriptor md)
- throws IOException, ParseException {
- throw new UnsupportedOperationException();
+ protected abstract static class AbstractParser extends DefaultHandler {
+ private static final String DEFAULT_CONF_MAPPING = "*->*";
+
+ private String defaultConf; // used only as defaultconf, not used for
+
+ // guessing right side part of a mapping
+ private String defaultConfMapping; // same as default conf but is used
+
+ // for guessing right side part of a mapping
+ private DefaultDependencyDescriptor defaultConfMappingDescriptor;
+
+ private final ExternalResource res;
+
+ private final List<String> errors = new ArrayList<String>();
+
+ private final DefaultModuleDescriptor md;
+
+ private final IvyXmlModuleDescriptorParser parser;
+
+ protected AbstractParser(IvyXmlModuleDescriptorParser parser, ExternalResource resource) {
+ this.parser = parser;
+ this.res = resource; // used for log and date only
+ md = new DefaultModuleDescriptor(XmlModuleDescriptorParser.getInstance(), null);
+ md.setLastModified(res.getLastModified());
+ }
+
+ public IvyXmlModuleDescriptorParser getModuleDescriptorParser() {
+ return parser;
+ }
+
+ protected void checkErrors() throws ParseException {
+ if (!errors.isEmpty()) {
+ throw new ParseException(Joiner.on(TextUtil.getPlatformLineSeparator()).join(errors), 0);
+ }
+ }
+
+ protected ExternalResource getResource() {
+ return res;
+ }
+
+ protected String getDefaultConfMapping() {
+ return defaultConfMapping;
+ }
+
+ protected void setDefaultConfMapping(String defaultConf) {
+ defaultConfMapping = defaultConf;
+ }
+
+ protected void parseDepsConfs(String confs, DefaultDependencyDescriptor dd) {
+ parseDepsConfs(confs, dd, defaultConfMapping != null);
+ }
+
+ protected void parseDepsConfs(String confs, DefaultDependencyDescriptor dd,
+ boolean useDefaultMappingToGuessRightOperande) {
+ parseDepsConfs(confs, dd, useDefaultMappingToGuessRightOperande, true);
+ }
+
+ protected void parseDepsConfs(String confs, DefaultDependencyDescriptor dd,
+ boolean useDefaultMappingToGuessRightOperande, boolean evaluateConditions) {
+ if (confs == null) {
+ return;
+ }
+
+ String[] conf = confs.split(";");
+ parseDepsConfs(conf, dd, useDefaultMappingToGuessRightOperande, evaluateConditions);
+ }
+
+ protected void parseDepsConfs(String[] conf, DefaultDependencyDescriptor dd,
+ boolean useDefaultMappingToGuessRightOperande) {
+ parseDepsConfs(conf, dd, useDefaultMappingToGuessRightOperande, true);
+ }
+
+ protected void parseDepsConfs(String[] conf, DefaultDependencyDescriptor dd,
+ boolean useDefaultMappingToGuessRightOperande, boolean evaluateConditions) {
+ replaceConfigurationWildcards(md);
+ for (int i = 0; i < conf.length; i++) {
+ String[] ops = conf[i].split("->");
+ if (ops.length == 1) {
+ String[] modConfs = ops[0].split(",");
+ if (!useDefaultMappingToGuessRightOperande) {
+ for (int j = 0; j < modConfs.length; j++) {
+ dd.addDependencyConfiguration(modConfs[j].trim(), modConfs[j].trim());
+ }
+ } else {
+ for (int j = 0; j < modConfs.length; j++) {
+ String[] depConfs = getDefaultConfMappingDescriptor()
+ .getDependencyConfigurations(modConfs[j]);
+ if (depConfs.length > 0) {
+ for (int k = 0; k < depConfs.length; k++) {
+ String mappedDependency = evaluateConditions
+ ? evaluateCondition(depConfs[k].trim(), dd)
+ : depConfs[k].trim();
+ if (mappedDependency != null) {
+ dd.addDependencyConfiguration(modConfs[j].trim(),
+ mappedDependency);
+ }
+ }
+ } else {
+ // no default mapping found for this configuration, map
+ // configuration to itself
+ dd.addDependencyConfiguration(modConfs[j].trim(), modConfs[j]
+ .trim());
+ }
+ }
+ }
+ } else if (ops.length == 2) {
+ String[] modConfs = ops[0].split(",");
+ String[] depConfs = ops[1].split(",");
+ for (int j = 0; j < modConfs.length; j++) {
+ for (int k = 0; k < depConfs.length; k++) {
+ String mappedDependency = evaluateConditions ? evaluateCondition(
+ depConfs[k].trim(), dd) : depConfs[k].trim();
+ if (mappedDependency != null) {
+ dd.addDependencyConfiguration(modConfs[j].trim(), mappedDependency);
+ }
+ }
+ }
+ } else {
+ addError("invalid conf " + conf[i] + " for " + dd);
+ }
+ }
+
+ if (md.isMappingOverride()) {
+ addExtendingConfigurations(conf, dd, useDefaultMappingToGuessRightOperande);
+ }
+ }
+
+ /**
+ * Evaluate the optional condition in the given configuration, like "[org=MYORG]confX". If
+ * the condition evaluates to true, the configuration is returned, if the condition
+ * evaluatate to false, null is returned. If there are no conditions, the configuration
+ * itself is returned.
+ *
+ * @param conf
+ * the configuration to evaluate
+ * @param dd
+ * the dependencydescriptor to which the configuration will be added
+ * @return the evaluated condition
+ */
+ private String evaluateCondition(String conf, DefaultDependencyDescriptor dd) {
+ if (conf.charAt(0) != '[') {
+ return conf;
+ }
+
+ int endConditionIndex = conf.indexOf(']');
+ if (endConditionIndex == -1) {
+ addError("invalid conf " + conf + " for " + dd);
+ return null;
+ }
+
+ String condition = conf.substring(1, endConditionIndex);
+
+ int notEqualIndex = condition.indexOf("!=");
+ if (notEqualIndex == -1) {
+ int equalIndex = condition.indexOf('=');
+ if (equalIndex == -1) {
+ addError("invalid conf " + conf + " for " + dd.getDependencyRevisionId());
+ return null;
+ }
+
+ String leftOp = condition.substring(0, equalIndex).trim();
+ String rightOp = condition.substring(equalIndex + 1).trim();
+
+ // allow organisation synonyms, like 'org' or 'organization'
+ if (leftOp.equals("org") || leftOp.equals("organization")) {
+ leftOp = "organisation";
+ }
+
+ String attrValue = dd.getAttribute(leftOp);
+ if (!rightOp.equals(attrValue)) {
+ return null;
+ }
+ } else {
+ String leftOp = condition.substring(0, notEqualIndex).trim();
+ String rightOp = condition.substring(notEqualIndex + 2).trim();
+
+ // allow organisation synonyms, like 'org' or 'organization'
+ if (leftOp.equals("org") || leftOp.equals("organization")) {
+ leftOp = "organisation";
+ }
+
+ String attrValue = dd.getAttribute(leftOp);
+ if (rightOp.equals(attrValue)) {
+ return null;
+ }
+ }
+
+ return conf.substring(endConditionIndex + 1);
+ }
+
+ private void addExtendingConfigurations(String[] confs, DefaultDependencyDescriptor dd,
+ boolean useDefaultMappingToGuessRightOperande) {
+ for (int i = 0; i < confs.length; i++) {
+ addExtendingConfigurations(confs[i], dd, useDefaultMappingToGuessRightOperande);
+ }
+ }
+
+ private void addExtendingConfigurations(String conf, DefaultDependencyDescriptor dd,
+ boolean useDefaultMappingToGuessRightOperande) {
+ Set configsToAdd = new HashSet();
+ Configuration[] configs = md.getConfigurations();
+ for (int i = 0; i < configs.length; i++) {
+ String[] ext = configs[i].getExtends();
+ for (int j = 0; j < ext.length; j++) {
+ if (conf.equals(ext[j])) {
+ String configName = configs[i].getName();
+ configsToAdd.add(configName);
+ addExtendingConfigurations(configName, dd,
+ useDefaultMappingToGuessRightOperande);
+ }
+ }
+ }
+
+ String[] confs = (String[]) configsToAdd.toArray(new String[configsToAdd.size()]);
+ parseDepsConfs(confs, dd, useDefaultMappingToGuessRightOperande);
+ }
+
+ protected DependencyDescriptor getDefaultConfMappingDescriptor() {
+ if (defaultConfMappingDescriptor == null) {
+ defaultConfMappingDescriptor = new DefaultDependencyDescriptor(ModuleRevisionId
+ .newInstance("", "", ""), false);
+ parseDepsConfs(defaultConfMapping, defaultConfMappingDescriptor, false, false);
+ }
+ return defaultConfMappingDescriptor;
+ }
+
+ protected void addError(String msg) {
+ errors.add(msg + " in " + res.getName());
+ }
+
+ public void warning(SAXParseException ex) {
+ LOGGER.warn("xml parsing: " + getLocationString(ex) + ": " + ex.getMessage());
+ }
+
+ public void error(SAXParseException ex) {
+ addError("xml parsing: " + getLocationString(ex) + ": " + ex.getMessage());
+ }
+
+ public void fatalError(SAXParseException ex) throws SAXException {
+ addError("[Fatal Error] " + getLocationString(ex) + ": " + ex.getMessage());
+ }
+
+ /** Returns a string of the location. */
+ private String getLocationString(SAXParseException ex) {
+ StringBuffer str = new StringBuffer();
+
+ String systemId = ex.getSystemId();
+ if (systemId != null) {
+ int index = systemId.lastIndexOf('/');
+ if (index != -1) {
+ systemId = systemId.substring(index + 1);
+ }
+ str.append(systemId);
+ } else {
+ str.append(getResource().getName());
+ }
+ str.append(':');
+ str.append(ex.getLineNumber());
+ str.append(':');
+ str.append(ex.getColumnNumber());
+
+ return str.toString();
+
+ } // getLocationString(SAXParseException):String
+
+ protected String getDefaultConf() {
+ return defaultConf != null ? defaultConf
+ : (defaultConfMapping != null ? defaultConfMapping : DEFAULT_CONF_MAPPING);
+ }
+
+ protected void setDefaultConf(String defaultConf) {
+ this.defaultConf = defaultConf;
+ }
+
+ public DefaultModuleDescriptor getModuleDescriptor() throws ParseException {
+ checkErrors();
+ return md;
+ }
+
+ protected Date getDefaultPubDate() {
+ return new Date(md.getLastModified());
+ }
+
+ private void replaceConfigurationWildcards(ModuleDescriptor md) {
+ Configuration[] configs = md.getConfigurations();
+ for (int i = 0; i < configs.length; i++) {
+ configs[i].replaceWildcards(md);
+ }
+ }
+
+ protected DefaultModuleDescriptor getMd() {
+ return md;
+ }
}
public static class Parser extends AbstractParser {
@@ -126,12 +408,10 @@ public class IvyXmlModuleDescriptorParser extends AbstractModuleDescriptorParser
private static final List ALLOWED_VERSIONS = Arrays.asList("1.0", "1.1", "1.2", "1.3", "1.4", "2.0", "2.1", "2.2");
/* how and what do we have to parse */
- private ParserSettings parserSettings;
+ private final DescriptorParseContext parserSettings;
private final RelativeUrlResolver relativeUrlResolver = new NormalRelativeUrlResolver();
+ private final URL descriptorURL;
private boolean validate = true;
- private URL descriptorURL;
- private InputStream descriptorInput;
-
/* Parsing state */
private int state = State.NONE;
@@ -145,59 +425,47 @@ public class IvyXmlModuleDescriptorParser extends AbstractModuleDescriptorParser
private String descriptorVersion;
private String[] publicationsDefaultConf;
- public Parser(ModuleDescriptorParser moduleDescriptorParser, ParserSettings ivySettings, Resource res) {
- super(moduleDescriptorParser);
+ public Parser(IvyXmlModuleDescriptorParser moduleDescriptorParser, DescriptorParseContext ivySettings, ExternalResource res, URL descriptorURL) {
+ super(moduleDescriptorParser, res);
parserSettings = ivySettings;
- setResource(res);
+ this.descriptorURL = descriptorURL;
}
- public Parser newParser(Resource res) {
- Parser parser = new Parser(getModuleDescriptorParser(), parserSettings, res);
+ public Parser newParser(ExternalResource res, URL descriptorURL) {
+ Parser parser = new Parser(getModuleDescriptorParser(), parserSettings, res, descriptorURL);
parser.setValidate(validate);
return parser;
}
- public void setInput(InputStream descriptorInput) {
- this.descriptorInput = descriptorInput;
- }
-
- public void setInput(URL descriptorURL) {
- this.descriptorURL = descriptorURL;
- }
-
public void setValidate(boolean validate) {
this.validate = validate;
}
- public void parse() throws ParseException,
- IOException {
- try {
- URL schemaURL = validate ? getSchemaURL() : null;
- if (descriptorURL != null) {
- XMLHelper.parse(descriptorURL, schemaURL, this);
- } else {
- XMLHelper.parse(descriptorInput, schemaURL, this, null);
- }
- checkConfigurations();
- replaceConfigurationWildcards();
- getMd().setModuleArtifact(DefaultArtifact.newIvyArtifact(getMd().getResolvedModuleRevisionId(), getMd().getPublicationDate()));
- if (!artifactsDeclared) {
- String[] configurationNames = getMd().getConfigurationsNames();
- for (String configurationName : configurationNames) {
- getMd().addArtifact(configurationName, new MDArtifact(getMd(), getMd().getModuleRevisionId().getName(), "jar", "jar"));
+ public void parse() throws ParseException, IOException {
+ getResource().withContent(new Action<InputStream>() {
+ public void execute(InputStream inputStream) {
+ URL schemaURL = validate ? getSchemaURL() : null;
+ InputSource inSrc = new InputSource(inputStream);
+ inSrc.setSystemId(descriptorURL.toExternalForm());
+ try {
+ XMLHelper.parse(inSrc, schemaURL, Parser.this, null);
+ } catch (Exception e) {
+ throw new MetaDataParseException("Ivy file", getResource(), e);
}
}
- getMd().check();
- } catch (ParserConfigurationException ex) {
- IllegalStateException ise = new IllegalStateException(ex.getMessage() + " in " + descriptorURL);
- ise.initCause(ex);
- throw ise;
- } catch (Exception ex) {
- checkErrors();
- ParseException pe = new ParseException(ex.getMessage() + " in " + descriptorURL, 0);
- pe.initCause(ex);
- throw pe;
+ });
+ checkErrors();
+ checkConfigurations();
+ replaceConfigurationWildcards();
+ getMd().setModuleArtifact(DefaultArtifact.newIvyArtifact(getMd().getResolvedModuleRevisionId(), getMd().getPublicationDate()));
+ if (!artifactsDeclared) {
+ String[] configurationNames = getMd().getConfigurationsNames();
+ for (String configurationName : configurationNames) {
+ getMd().addArtifact(configurationName, new MDArtifact(getMd(), getMd().getModuleRevisionId().getName(), "jar", "jar"));
+ }
}
+ checkErrors();
+ getMd().check();
}
public void startElement(String uri, String localName, String qName, Attributes attributes)
@@ -214,7 +482,11 @@ public class IvyXmlModuleDescriptorParser extends AbstractModuleDescriptorParser
extendsStarted(attributes);
} else if (state == State.INFO && "license".equals(qName)) {
getMd().addLicense(new License(substitute(attributes.getValue("name")), substitute(attributes.getValue("url"))));
- } else if (state == State.INFO && "description".equals(qName)) {
+ } /* CHECKSTYLE:OFF */ else if (state == State.INFO && "ivyauthor".equals(qName)) {
+ // nothing to do, we don't store this
+ } else if (state == State.INFO && "repository".equals(qName)) {
+ // nothing to do, we don't store this
+ } /* CHECKSTYLE:ON */ else if (state == State.INFO && "description".equals(qName)) {
getMd().setHomePage(substitute(attributes.getValue("homepage")));
state = State.DESCRIPTION;
buffer = new StringBuffer();
@@ -229,7 +501,7 @@ public class IvyXmlModuleDescriptorParser extends AbstractModuleDescriptorParser
dependenciesStarted(attributes);
} else if ("conflicts".equals(qName)) {
if (!descriptorVersion.startsWith("1.")) {
- DeprecationLogger.nagUserWith("Using conflicts section in ivy.xml is deprecated: please use hints section instead. Ivy file URL: " + descriptorURL);
+ DeprecationLogger.nagUserWith("Using conflicts section in ivy.xml is deprecated: please use hints section instead. Ivy file: " + getResource().getName());
}
state = State.CONFLICT;
checkConfigurations();
@@ -348,7 +620,6 @@ public class IvyXmlModuleDescriptorParser extends AbstractModuleDescriptorParser
mergeDescription(parent.getDescription());
}
}
-
}
private void mergeAll(ModuleDescriptor parent) {
@@ -422,7 +693,7 @@ public class IvyXmlModuleDescriptorParser extends AbstractModuleDescriptorParser
throws ParseException, IOException {
URL url = relativeUrlResolver.getURL(descriptorURL, location);
LOGGER.debug("Trying to load included ivy file from " + url.toString());
- Parser parser = newParser(new URLResource(url));
+ Parser parser = newParser(new UrlExternalResource(url), url);
parser.parse();
return parser.getModuleDescriptor();
}
@@ -432,27 +703,7 @@ public class IvyXmlModuleDescriptorParser extends AbstractModuleDescriptorParser
ModuleId parentModuleId = new ModuleId(parentOrganisation, parentModule);
ModuleRevisionId parentMrid = new ModuleRevisionId(parentModuleId, parentRevision);
- DependencyDescriptor dd = new DefaultDependencyDescriptor(parentMrid, true);
- ResolveData data = IvyContext.getContext().getResolveData();
- if (data == null) {
- ResolveEngine engine = IvyContext.getContext().getIvy().getResolveEngine();
- ResolveOptions options = new ResolveOptions();
- options.setDownload(false);
- data = new ResolveData(engine, options);
- }
-
- DependencyResolver resolver = parserSettings.getResolver(parentMrid);
- if (resolver == null) {
- // TODO: Throw exception here?
- return null;
- } else {
- dd = NameSpaceHelper.toSystem(dd, parserSettings.getContextNamespace());
- ResolvedModuleRevision otherModule = resolver.getDependency(dd, data);
- if (otherModule == null) {
- throw new ParseException("Unable to find " + parentMrid.toString(), 0);
- }
- return otherModule.getDescriptor();
- }
+ return parserSettings.getModuleDescriptor(parentMrid);
}
private void publicationsStarted(Attributes attributes) {
@@ -478,8 +729,7 @@ public class IvyXmlModuleDescriptorParser extends AbstractModuleDescriptorParser
// create a new temporary parser to read the configurations from
// the specified file.
- Parser parser = newParser(new URLResource(url));
- parser.setInput(url);
+ Parser parser = newParser(new UrlExternalResource(url), url);
XMLHelper.parse(url , null, parser);
// add the configurations from this temporary parser to this module descriptor
@@ -636,7 +886,7 @@ public class IvyXmlModuleDescriptorParser extends AbstractModuleDescriptorParser
setDefaultConf(defaultConf);
}
String defaultConfMapping = substitute(attributes.getValue("defaultconfmapping"));
- if (defaultConf != null) {
+ if (defaultConfMapping != null) {
setDefaultConfMapping(defaultConfMapping);
}
String confMappingOverride = substitute(attributes.getValue("confmappingoverride"));
@@ -662,17 +912,7 @@ public class IvyXmlModuleDescriptorParser extends AbstractModuleDescriptorParser
Map extraAttributes = getExtraAttributes(attributes, new String[]{"organisation", "module", "revision", "status", "publication", "branch", "namespace", "default", "resolver"});
getMd().setModuleRevisionId(ModuleRevisionId.newInstance(org, module, branch, revision, extraAttributes));
- String namespace = substitute(attributes.getValue("namespace"));
- if (namespace != null) {
- Namespace ns = parserSettings.getNamespace(namespace);
- if (ns == null) {
- LOGGER.warn("namespace not found for " + getMd().getModuleRevisionId() + ": " + namespace);
- } else {
- getMd().setNamespace(ns);
- }
- }
-
- getMd().setStatus(elvis(substitute(attributes.getValue("status")), parserSettings.getStatusManager().getDefaultStatus()));
+ getMd().setStatus(elvis(substitute(attributes.getValue("status")), parserSettings.getDefaultStatus()));
getMd().setDefault(Boolean.valueOf(substitute(attributes.getValue("default"))));
String pubDate = substitute(attributes.getValue("publication"));
if (pubDate != null && pubDate.length() > 0) {
@@ -893,7 +1133,9 @@ public class IvyXmlModuleDescriptorParser extends AbstractModuleDescriptorParser
}
private URL getSchemaURL() {
- return getClass().getResource("ivy.xsd");
+ URL resource = getClass().getClassLoader().getResource("org/apache/ivy/plugins/parser/xml/ivy.xsd");
+ assert resource != null;
+ return resource;
}
private String elvis(String value, String defaultValue) {
@@ -905,7 +1147,19 @@ public class IvyXmlModuleDescriptorParser extends AbstractModuleDescriptorParser
}
private Map getExtraAttributes(Attributes attributes, String[] ignoredAttributeNames) {
- return ExtendableItemHelper.getExtraAttributes(parserSettings, attributes, ignoredAttributeNames);
+ return getExtraAttributes(parserSettings, attributes, ignoredAttributeNames);
+ }
+
+ public static Map getExtraAttributes(
+ DescriptorParseContext settings, Attributes attributes, String[] ignoredAttNames) {
+ Map ret = new HashMap();
+ Collection ignored = Arrays.asList(ignoredAttNames);
+ for (int i = 0; i < attributes.getLength(); i++) {
+ if (!ignored.contains(attributes.getQName(i))) {
+ ret.put(attributes.getQName(i), settings.substitute(attributes.getValue(i)));
+ }
+ }
+ return ret;
}
private void fillExtraAttributes(DefaultExtendableItem item, Attributes attributes, String[] ignoredAttNames) {
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/MetaDataParseException.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/MetaDataParseException.java
new file mode 100644
index 0000000..f849117
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/MetaDataParseException.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser;
+
+import org.gradle.api.GradleException;
+import org.gradle.api.internal.Contextual;
+import org.gradle.api.internal.externalresource.ExternalResource;
+
+ at Contextual
+public class MetaDataParseException extends GradleException {
+ public MetaDataParseException(String message) {
+ super(message);
+ }
+
+ public MetaDataParseException(String typeName, ExternalResource resource, Throwable cause) {
+ super(String.format("Could not parse %s %s", typeName, resource.getName()), cause);
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/MetaDataParser.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/MetaDataParser.java
new file mode 100644
index 0000000..b23ac04
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/MetaDataParser.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser;
+
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.MutableModuleVersionMetaData;
+import org.gradle.api.internal.externalresource.LocallyAvailableExternalResource;
+
+public interface MetaDataParser {
+ MutableModuleVersionMetaData parseModuleMetaData(LocallyAvailableExternalResource resource, DescriptorParseContext context) throws MetaDataParseException;
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/ModuleDescriptorAdapter.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/ModuleDescriptorAdapter.java
new file mode 100644
index 0000000..5580268
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/ModuleDescriptorAdapter.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser;
+
+import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
+import org.apache.ivy.core.module.id.ModuleRevisionId;
+import org.gradle.api.artifacts.ModuleVersionIdentifier;
+import org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ConfigurationMetaData;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.DependencyMetaData;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.MutableModuleVersionMetaData;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class ModuleDescriptorAdapter implements MutableModuleVersionMetaData {
+ private static final List<String> DEFAULT_STATUS_SCHEME = Arrays.asList("integration", "milestone", "release");
+
+ private final ModuleVersionIdentifier moduleVersionIdentifier;
+ private final ModuleDescriptor moduleDescriptor;
+ private boolean changing;
+ private String status;
+ private List<String> statusScheme = DEFAULT_STATUS_SCHEME;
+
+ public ModuleDescriptorAdapter(ModuleRevisionId moduleRevisionId, ModuleDescriptor moduleDescriptor) {
+ this.moduleVersionIdentifier = DefaultModuleVersionIdentifier.newId(moduleRevisionId);
+ this.moduleDescriptor = moduleDescriptor;
+ status = moduleDescriptor.getStatus();
+ }
+
+ public ModuleVersionIdentifier getId() {
+ return moduleVersionIdentifier;
+ }
+
+ public ModuleDescriptor getDescriptor() {
+ return moduleDescriptor;
+ }
+
+ public boolean isChanging() {
+ return changing;
+ }
+
+ public String getStatus() {
+ return status;
+ }
+
+ public List<String> getStatusScheme() {
+ return statusScheme;
+ }
+
+ public void setChanging(boolean changing) {
+ this.changing = changing;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
+ public void setStatusScheme(List<String> statusScheme) {
+ this.statusScheme = statusScheme;
+ }
+
+ // The methods will require implementing when we stop handing around ModuleDescriptor and make ModuleVersionMetaData our key internal API.
+ public List<DependencyMetaData> getDependencies() {
+ // TODO:DAZ
+ throw new UnsupportedOperationException();
+ }
+
+ public ConfigurationMetaData getConfiguration(String name) {
+ // TODO:DAZ
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/ModuleDescriptorParser.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/ModuleDescriptorParser.java
new file mode 100644
index 0000000..2d5549c
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/ModuleDescriptorParser.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser;
+
+import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
+import org.gradle.api.internal.externalresource.ExternalResource;
+import org.gradle.api.internal.externalresource.LocallyAvailableExternalResource;
+
+import java.io.File;
+
+public interface ModuleDescriptorParser {
+ public ModuleDescriptor parseDescriptor(DescriptorParseContext ivySettings, File descriptorFile, boolean validate) throws MetaDataParseException;
+
+ public ModuleDescriptor parseDescriptor(DescriptorParseContext ivySettings, LocallyAvailableExternalResource resource, boolean validate) throws MetaDataParseException;
+
+ public boolean accept(ExternalResource res);
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/ModuleScopedParserSettings.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/ModuleScopedParserSettings.java
deleted file mode 100644
index 82905c7..0000000
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/ModuleScopedParserSettings.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser;
-
-import org.apache.ivy.core.RelativeUrlResolver;
-import org.apache.ivy.core.cache.ResolutionCacheManager;
-import org.apache.ivy.core.module.id.ModuleId;
-import org.apache.ivy.core.module.id.ModuleRevisionId;
-import org.apache.ivy.core.module.status.StatusManager;
-import org.apache.ivy.plugins.conflict.ConflictManager;
-import org.apache.ivy.plugins.matcher.PatternMatcher;
-import org.apache.ivy.plugins.namespace.Namespace;
-import org.apache.ivy.plugins.parser.ParserSettings;
-import org.apache.ivy.plugins.resolver.DependencyResolver;
-
-import java.io.File;
-import java.util.Map;
-
-/**
- * ParserSettings that control the scope of searches carried out during parsing.
- * If the parser asks for a resolver for the currently resolving revision, the resolver scope is only the repository where the module was resolved.
- * If the parser asks for a resolver for a different revision, the resolver scope is all repositories.
- */
-public class ModuleScopedParserSettings implements ParserSettings {
- private final ParserSettings settings;
- private final DependencyResolver currentResolver;
- private final ModuleRevisionId currentRevisionId;
-
- public ModuleScopedParserSettings(ParserSettings settings, DependencyResolver currentResolver, ModuleRevisionId currentRevisionId) {
- this.settings = settings;
- this.currentResolver = currentResolver;
- this.currentRevisionId = currentRevisionId;
- }
-
- public ModuleRevisionId getCurrentRevisionId() {
- return currentRevisionId;
- }
-
- public DependencyResolver getResolver(ModuleRevisionId mRevId) {
- if (mRevId.equals(currentRevisionId)) {
- return currentResolver;
- }
- return settings.getResolver(mRevId);
- }
-
- public ConflictManager getConflictManager(String name) {
- return settings.getConflictManager(name);
- }
-
- public String substitute(String value) {
- return settings.substitute(value);
- }
-
- public Map substitute(Map strings) {
- return settings.substitute(strings);
- }
-
- public ResolutionCacheManager getResolutionCacheManager() {
- return settings.getResolutionCacheManager();
- }
-
- public PatternMatcher getMatcher(String matcherName) {
- return settings.getMatcher(matcherName);
- }
-
- public Namespace getNamespace(String namespace) {
- return settings.getNamespace(namespace);
- }
-
- public StatusManager getStatusManager() {
- return settings.getStatusManager();
- }
-
- public RelativeUrlResolver getRelativeUrlResolver() {
- return settings.getRelativeUrlResolver();
- }
-
- public File resolveFile(String filename) {
- return settings.resolveFile(filename);
- }
-
- public String getDefaultBranch(ModuleId moduleId) {
- return settings.getDefaultBranch(moduleId);
- }
-
- public Namespace getContextNamespace() {
- return settings.getContextNamespace();
- }
-}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/ParserRegistry.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/ParserRegistry.java
index efd9040..5e9d444 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/ParserRegistry.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/ParserRegistry.java
@@ -15,8 +15,7 @@
*/
package org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser;
-import org.apache.ivy.plugins.parser.ModuleDescriptorParser;
-import org.apache.ivy.plugins.repository.Resource;
+import org.gradle.api.internal.externalresource.ExternalResource;
import java.util.ArrayList;
import java.util.List;
@@ -29,7 +28,7 @@ public class ParserRegistry {
parsers.add(new DownloadedIvyModuleDescriptorParser());
}
- public ModuleDescriptorParser forResource(Resource resource) {
+ public ModuleDescriptorParser forResource(ExternalResource resource) {
for (ModuleDescriptorParser parser : parsers) {
if (parser.accept(resource)) {
return parser;
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/PomReader.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/PomReader.java
new file mode 100644
index 0000000..53c7e59
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/PomReader.java
@@ -0,0 +1,577 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser;
+
+import org.apache.ivy.core.IvyPatternHelper;
+import org.apache.ivy.core.module.descriptor.License;
+import org.apache.ivy.core.module.id.ModuleId;
+import org.apache.ivy.core.module.id.ModuleRevisionId;
+import org.apache.ivy.plugins.parser.m2.PomDependencyMgt;
+import org.apache.ivy.util.XMLHelper;
+import org.gradle.api.Transformer;
+import org.gradle.api.internal.externalresource.LocallyAvailableExternalResource;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+import javax.xml.parsers.DocumentBuilder;
+import java.io.*;
+import java.util.*;
+
+
+/**
+ * Copied from org.apache.ivy.plugins.parser.m2.PomReader.
+ */
+public class PomReader {
+
+ private static final String PACKAGING = "packaging";
+ private static final String DEPENDENCY = "dependency";
+ private static final String DEPENDENCIES = "dependencies";
+ private static final String DEPENDENCY_MGT = "dependencyManagement";
+ private static final String PROJECT = "project";
+ private static final String MODEL = "model";
+ private static final String GROUP_ID = "groupId";
+ private static final String ARTIFACT_ID = "artifactId";
+ private static final String VERSION = "version";
+ private static final String DESCRIPTION = "description";
+ private static final String HOMEPAGE = "url";
+ private static final String LICENSES = "licenses";
+ private static final String LICENSE = "license";
+ private static final String LICENSE_NAME = "name";
+ private static final String LICENSE_URL = "url";
+ private static final String PARENT = "parent";
+ private static final String SCOPE = "scope";
+ private static final String CLASSIFIER = "classifier";
+ private static final String OPTIONAL = "optional";
+ private static final String EXCLUSIONS = "exclusions";
+ private static final String EXCLUSION = "exclusion";
+ private static final String DISTRIBUTION_MGT = "distributionManagement";
+ private static final String RELOCATION = "relocation";
+ private static final String PROPERTIES = "properties";
+ private static final String PLUGINS = "plugins";
+ private static final String PLUGIN = "plugin";
+ private static final String TYPE = "type";
+
+ private Map<String, String> properties = new HashMap<String, String>();
+
+ private final Element projectElement;
+ private final Element parentElement;
+
+ public PomReader(final LocallyAvailableExternalResource resource) throws IOException, SAXException {
+ final String systemId = resource.getLocalResource().getFile().toURI().toASCIIString();
+ Document pomDomDoc = resource.withContent(new Transformer<Document, InputStream>() {
+ public Document transform(InputStream inputStream) {
+ try {
+ return parseToDom(inputStream, systemId);
+ } catch (Exception e) {
+ throw new MetaDataParseException("POM", resource, e);
+ }
+ }
+ });
+ projectElement = pomDomDoc.getDocumentElement();
+ if (!PROJECT.equals(projectElement.getNodeName()) && !MODEL.equals(projectElement.getNodeName())) {
+ throw new SAXParseException("project must be the root tag", systemId, systemId, 0, 0);
+ }
+ parentElement = getFirstChildElement(projectElement, PARENT);
+ }
+
+ public static Document parseToDom(InputStream stream, String systemId) throws IOException, SAXException {
+ EntityResolver entityResolver = new EntityResolver() {
+ public InputSource resolveEntity(String publicId, String systemId)
+ throws SAXException, IOException {
+ if ((systemId != null) && systemId.endsWith("m2-entities.ent")) {
+ return new InputSource(org.apache.ivy.plugins.parser.m2.PomReader.class.getResourceAsStream("m2-entities.ent"));
+ }
+ return null;
+ }
+ };
+ InputStream dtdStream = new AddDTDFilterInputStream(stream);
+ DocumentBuilder docBuilder = XMLHelper.getDocBuilder(entityResolver);
+ return docBuilder.parse(dtdStream, systemId);
+ }
+
+ public boolean hasParent() {
+ return parentElement != null;
+ }
+
+ /**
+ * Add a property if not yet set and value is not null.
+ * This garantee that property keep the first value that is put on it and that the properties
+ * are never null.
+ */
+ public void setProperty(String prop, String val) {
+ if (!properties.containsKey(prop) && val != null) {
+ properties.put(prop, val);
+ }
+ }
+
+
+ public String getGroupId() {
+ String groupId = getFirstChildText(projectElement , GROUP_ID);
+ if (groupId == null) {
+ groupId = getFirstChildText(parentElement, GROUP_ID);
+ }
+ return replaceProps(groupId);
+
+ }
+
+ public String getParentGroupId() {
+ String groupId = getFirstChildText(parentElement , GROUP_ID);
+ if (groupId == null) {
+ groupId = getFirstChildText(projectElement, GROUP_ID);
+ }
+ return replaceProps(groupId);
+ }
+
+
+
+ public String getArtifactId() {
+ String val = getFirstChildText(projectElement , ARTIFACT_ID);
+ if (val == null) {
+ val = getFirstChildText(parentElement, ARTIFACT_ID);
+ }
+ return replaceProps(val);
+ }
+
+ public String getParentArtifactId() {
+ String val = getFirstChildText(parentElement , ARTIFACT_ID);
+ if (val == null) {
+ val = getFirstChildText(projectElement, ARTIFACT_ID);
+ }
+ return replaceProps(val);
+ }
+
+
+ public String getVersion() {
+ String val = getFirstChildText(projectElement , VERSION);
+ if (val == null) {
+ val = getFirstChildText(parentElement, VERSION);
+ }
+ return replaceProps(val);
+ }
+
+ public String getParentVersion() {
+ String val = getFirstChildText(parentElement , VERSION);
+ if (val == null) {
+ val = getFirstChildText(projectElement, VERSION);
+ }
+ return replaceProps(val);
+ }
+
+
+ public String getPackaging() {
+ String val = getFirstChildText(projectElement , PACKAGING);
+ if (val == null) {
+ val = "jar";
+ }
+ return val;
+ }
+
+ public String getHomePage() {
+ String val = getFirstChildText(projectElement , HOMEPAGE);
+ if (val == null) {
+ val = "";
+ }
+ return val;
+ }
+
+ public String getDescription() {
+ String val = getFirstChildText(projectElement , DESCRIPTION);
+ if (val == null) {
+ val = "";
+ }
+ return val.trim();
+ }
+
+ public License[] getLicenses() {
+ Element licenses = getFirstChildElement(projectElement, LICENSES);
+ if (licenses == null) {
+ return new License[0];
+ }
+ licenses.normalize();
+ List<License> lics = new ArrayList<License>();
+ for (Element license : getAllChilds(licenses)) {
+ if (LICENSE.equals(license.getNodeName())) {
+ String name = getFirstChildText(license, LICENSE_NAME);
+ String url = getFirstChildText(license, LICENSE_URL);
+
+ if ((name == null) && (url == null)) {
+ // move to next license
+ continue;
+ }
+
+ if (name == null) {
+ // The license name is required in Ivy but not in a POM!
+ name = "Unknown License";
+ }
+
+ lics.add(new License(name, url));
+ }
+ }
+ return lics.toArray(new License[lics.size()]);
+ }
+
+
+ public ModuleRevisionId getRelocation() {
+ Element distrMgt = getFirstChildElement(projectElement, DISTRIBUTION_MGT);
+ Element relocation = getFirstChildElement(distrMgt , RELOCATION);
+ if (relocation == null) {
+ return null;
+ } else {
+ String relocGroupId = getFirstChildText(relocation, GROUP_ID);
+ String relocArtId = getFirstChildText(relocation, ARTIFACT_ID);
+ String relocVersion = getFirstChildText(relocation, VERSION);
+ relocGroupId = relocGroupId == null ? getGroupId() : relocGroupId;
+ relocArtId = relocArtId == null ? getArtifactId() : relocArtId;
+ relocVersion = relocVersion == null ? getVersion() : relocVersion;
+ return ModuleRevisionId.newInstance(relocGroupId, relocArtId, relocVersion);
+ }
+ }
+
+ public List<PomDependencyData> getDependencies() {
+ Element dependenciesElement = getFirstChildElement(projectElement, DEPENDENCIES);
+ List<PomDependencyData> dependencies = new LinkedList<PomDependencyData>();
+ if (dependenciesElement != null) {
+ NodeList childs = dependenciesElement.getChildNodes();
+ for (int i = 0; i < childs.getLength(); i++) {
+ Node node = childs.item(i);
+ if (node instanceof Element && DEPENDENCY.equals(node.getNodeName())) {
+ dependencies.add(new PomDependencyData((Element) node));
+ }
+ }
+ }
+ return dependencies;
+ }
+
+
+ public List<PomDependencyMgt> getDependencyMgt() {
+ Element dependenciesElement = getFirstChildElement(projectElement, DEPENDENCY_MGT);
+ dependenciesElement = getFirstChildElement(dependenciesElement, DEPENDENCIES);
+ List<PomDependencyMgt> dependencies = new LinkedList<PomDependencyMgt>();
+ if (dependenciesElement != null) {
+ NodeList childs = dependenciesElement.getChildNodes();
+ for (int i = 0; i < childs.getLength(); i++) {
+ Node node = childs.item(i);
+ if (node instanceof Element && DEPENDENCY.equals(node.getNodeName())) {
+ dependencies.add(new PomDependencyMgtElement((Element) node));
+ }
+ }
+ }
+ return dependencies;
+ }
+
+ public class PomDependencyMgtElement implements PomDependencyMgt {
+ private final Element depElement;
+
+ PomDependencyMgtElement(Element depElement) {
+ this.depElement = depElement;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.ivy.plugins.parser.m2.PomDependencyMgt#getGroupId()
+ */
+ public String getGroupId() {
+ String val = getFirstChildText(depElement , GROUP_ID);
+ return replaceProps(val);
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.ivy.plugins.parser.m2.PomDependencyMgt#getArtifaceId()
+ */
+ public String getArtifactId() {
+ String val = getFirstChildText(depElement , ARTIFACT_ID);
+ return replaceProps(val);
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.ivy.plugins.parser.m2.PomDependencyMgt#getVersion()
+ */
+ public String getVersion() {
+ String val = getFirstChildText(depElement , VERSION);
+ return replaceProps(val);
+ }
+
+ public String getScope() {
+ String val = getFirstChildText(depElement , SCOPE);
+ return replaceProps(val);
+ }
+
+ public List<ModuleId> getExcludedModules() {
+ Element exclusionsElement = getFirstChildElement(depElement, EXCLUSIONS);
+ List<ModuleId> exclusions = new LinkedList<ModuleId>();
+ if (exclusionsElement != null) {
+ NodeList childs = exclusionsElement.getChildNodes();
+ for (int i = 0; i < childs.getLength(); i++) {
+ Node node = childs.item(i);
+ if (node instanceof Element && EXCLUSION.equals(node.getNodeName())) {
+ String groupId = getFirstChildText((Element) node, GROUP_ID);
+ String artifactId = getFirstChildText((Element) node, ARTIFACT_ID);
+ if ((groupId != null) && (artifactId != null)) {
+ exclusions.add(ModuleId.newInstance(groupId, artifactId));
+ }
+ }
+ }
+ }
+ return exclusions;
+ }
+ }
+
+ public List<PomPluginElement> getPlugins() {
+ List<PomPluginElement> plugins = new LinkedList<PomPluginElement>();
+
+ Element buildElement = getFirstChildElement(projectElement, "build");
+ if (buildElement == null) {
+ return plugins;
+ }
+
+ Element pluginsElement = getFirstChildElement(buildElement, PLUGINS);
+ if (pluginsElement != null) {
+ NodeList childs = pluginsElement.getChildNodes();
+ for (int i = 0; i < childs.getLength(); i++) {
+ Node node = childs.item(i);
+ if (node instanceof Element && PLUGIN.equals(node.getNodeName())) {
+ plugins.add(new PomPluginElement((Element) node));
+ }
+ }
+ }
+ return plugins;
+ }
+
+ public class PomPluginElement implements PomDependencyMgt {
+ private Element pluginElement;
+
+ PomPluginElement(Element pluginElement) {
+ this.pluginElement = pluginElement;
+ }
+
+ public String getGroupId() {
+ String val = getFirstChildText(pluginElement , GROUP_ID);
+ return replaceProps(val);
+ }
+
+ public String getArtifactId() {
+ String val = getFirstChildText(pluginElement , ARTIFACT_ID);
+ return replaceProps(val);
+ }
+
+ public String getVersion() {
+ String val = getFirstChildText(pluginElement , VERSION);
+ return replaceProps(val);
+ }
+
+ public String getScope() {
+ return null; // not used
+ }
+
+ public List<ModuleId> getExcludedModules() {
+ return Collections.emptyList(); // probably not used?
+ }
+ }
+
+
+ public class PomDependencyData extends PomDependencyMgtElement {
+ private final Element depElement;
+ PomDependencyData(Element depElement) {
+ super(depElement);
+ this.depElement = depElement;
+ }
+
+ public String getScope() {
+ String val = getFirstChildText(depElement , SCOPE);
+ return replaceProps(val);
+ }
+
+ public String getClassifier() {
+ String val = getFirstChildText(depElement , CLASSIFIER);
+ return replaceProps(val);
+ }
+
+ public String getType() {
+ String val = getFirstChildText(depElement, TYPE);
+ return replaceProps(val);
+ }
+
+ public boolean isOptional() {
+ Element e = getFirstChildElement(depElement, OPTIONAL);
+ return (e != null) && "true".equalsIgnoreCase(getTextContent(e));
+ }
+ }
+
+ /**
+ * @return the content of the properties tag into the pom.
+ */
+ public Map<String, String> getPomProperties() {
+ Map<String, String> pomProperties = new HashMap<String, String>();
+ Element propsEl = getFirstChildElement(projectElement, PROPERTIES);
+ if (propsEl != null) {
+ propsEl.normalize();
+ }
+ for (Element prop : getAllChilds(propsEl)) {
+ pomProperties.put(prop.getNodeName(), getTextContent(prop));
+ }
+ return pomProperties;
+ }
+
+ private String replaceProps(String val) {
+ if (val == null) {
+ return null;
+ } else {
+ return IvyPatternHelper.substituteVariables(val, properties).trim();
+ }
+ }
+
+ private static String getTextContent(Element element) {
+ StringBuilder result = new StringBuilder();
+
+ NodeList childNodes = element.getChildNodes();
+ for (int i = 0; i < childNodes.getLength(); i++) {
+ Node child = childNodes.item(i);
+
+ switch (child.getNodeType()) {
+ case Node.CDATA_SECTION_NODE:
+ case Node.TEXT_NODE:
+ result.append(child.getNodeValue());
+ break;
+ default:
+ break;
+ }
+ }
+
+ return result.toString();
+ }
+
+ private static String getFirstChildText(Element parentElem, String name) {
+ Element node = getFirstChildElement(parentElem, name);
+ if (node != null) {
+ return getTextContent(node);
+ } else {
+ return null;
+ }
+ }
+
+ private static Element getFirstChildElement(Element parentElem, String name) {
+ if (parentElem == null) {
+ return null;
+ }
+ NodeList childs = parentElem.getChildNodes();
+ for (int i = 0; i < childs.getLength(); i++) {
+ Node node = childs.item(i);
+ if (node instanceof Element && name.equals(node.getNodeName())) {
+ return (Element) node;
+ }
+ }
+ return null;
+ }
+
+ private static List<Element> getAllChilds(Element parent) {
+ List<Element> r = new LinkedList<Element>();
+ if (parent != null) {
+ NodeList childs = parent.getChildNodes();
+ for (int i = 0; i < childs.getLength(); i++) {
+ Node node = childs.item(i);
+ if (node instanceof Element) {
+ r.add((Element) node);
+ }
+ }
+ }
+ return r;
+ }
+
+ private static final class AddDTDFilterInputStream extends FilterInputStream {
+ private static final int MARK = 10000;
+ private static final String DOCTYPE = "<!DOCTYPE project SYSTEM \"m2-entities.ent\">\n";
+
+ private int count;
+ private byte[] prefix = DOCTYPE.getBytes();
+
+ private AddDTDFilterInputStream(InputStream in) throws IOException {
+ super(new BufferedInputStream(in));
+
+ this.in.mark(MARK);
+
+ // TODO: we should really find a better solution for this...
+ // maybe we could use a FilterReader instead of a FilterInputStream?
+ int byte1 = this.in.read();
+ int byte2 = this.in.read();
+ int byte3 = this.in.read();
+
+ if (byte1 == 239 && byte2 == 187 && byte3 == 191) {
+ // skip the UTF-8 BOM
+ this.in.mark(MARK);
+ } else {
+ this.in.reset();
+ }
+
+ int bytesToSkip = 0;
+ LineNumberReader reader = new LineNumberReader(new InputStreamReader(this.in, "UTF-8"), 100);
+ String firstLine = reader.readLine();
+ if (firstLine != null) {
+ String trimmed = firstLine.trim();
+ if (trimmed.startsWith("<?xml ")) {
+ int endIndex = trimmed.indexOf("?>");
+ String xmlDecl = trimmed.substring(0, endIndex + 2);
+ prefix = (xmlDecl + "\n" + DOCTYPE).getBytes();
+ bytesToSkip = xmlDecl.getBytes().length;
+ }
+ }
+
+ this.in.reset();
+ for (int i = 0; i < bytesToSkip; i++) {
+ this.in.read();
+ }
+ }
+
+ public int read() throws IOException {
+ if (count < prefix.length) {
+ return prefix[count++];
+ }
+
+ return super.read();
+ }
+
+ public int read(byte[] b, int off, int len) throws IOException {
+ if (b == null) {
+ throw new NullPointerException();
+ } else if ((off < 0) || (off > b.length) || (len < 0)
+ || ((off + len) > b.length) || ((off + len) < 0)) {
+ throw new IndexOutOfBoundsException();
+ } else if (len == 0) {
+ return 0;
+ }
+
+ int nbrBytesCopied = 0;
+
+ if (count < prefix.length) {
+ int nbrBytesFromPrefix = Math.min(prefix.length - count, len);
+ System.arraycopy(prefix, count, b, off, nbrBytesFromPrefix);
+ nbrBytesCopied = nbrBytesFromPrefix;
+ }
+
+ if (nbrBytesCopied < len) {
+ nbrBytesCopied += in.read(b, off + nbrBytesCopied, len - nbrBytesCopied);
+ }
+
+ count += nbrBytesCopied;
+ return nbrBytesCopied;
+ }
+ }
+
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/ChainVersionMatcher.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/ChainVersionMatcher.java
new file mode 100644
index 0000000..eb5f2c1
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/ChainVersionMatcher.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy;
+
+import com.google.common.collect.Lists;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ModuleVersionMetaData;
+
+import java.util.*;
+
+public class ChainVersionMatcher implements VersionMatcher {
+ private final List<VersionMatcher> matchers = Lists.newArrayList();
+
+ public void add(VersionMatcher matcher) {
+ matchers.add(matcher);
+ }
+
+ public boolean canHandle(String selector) {
+ // not expected to be called
+ throw new UnsupportedOperationException("canHandle");
+ }
+
+ public boolean isDynamic(String selector) {
+ return getCompatibleMatcher(selector).isDynamic(selector);
+ }
+
+ public boolean needModuleMetadata(String selector, String candidate) {
+ return getCompatibleMatcher(selector).needModuleMetadata(selector, candidate);
+ }
+
+ public boolean accept(String selector, String candidate) {
+ return getCompatibleMatcher(selector).accept(selector, candidate);
+ }
+
+ public boolean accept(String selector, ModuleVersionMetaData candidate) {
+ return getCompatibleMatcher(selector).accept(selector, candidate);
+ }
+
+ public int compare(String selector, String candidate) {
+ return getCompatibleMatcher(selector).compare(selector, candidate);
+ }
+
+ private VersionMatcher getCompatibleMatcher(String selector) {
+ for (VersionMatcher matcher : matchers) {
+ if (matcher.canHandle(selector)) {
+ return matcher;
+ }
+ }
+ throw new IllegalArgumentException("Invalid version selector: " + selector);
+ }
+}
+
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/ExactVersionMatcher.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/ExactVersionMatcher.java
new file mode 100644
index 0000000..76fb959
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/ExactVersionMatcher.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy;
+
+import com.google.common.collect.ImmutableMap;
+
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ModuleVersionMetaData;
+
+import java.util.Locale;
+import java.util.Map;
+
+/**
+ * Version matcher for "static" version selectors (1.0, 1.2.3, etc.).
+ */
+public class ExactVersionMatcher implements VersionMatcher {
+ private static final Map<String, Integer> SPECIAL_MEANINGS =
+ ImmutableMap.of("dev", new Integer(-1), "rc", new Integer(1), "final", new Integer(2));
+
+ public boolean canHandle(String selector) {
+ return true;
+ }
+
+ public boolean isDynamic(String selector) {
+ return false;
+ }
+
+ public boolean needModuleMetadata(String selector, String candidate) {
+ return false;
+ }
+
+ public boolean accept(String selector, String candidate) {
+ return selector.equals(candidate);
+ }
+
+ public boolean accept(String selector, ModuleVersionMetaData candidate) {
+ return accept(selector, candidate.getId().getVersion());
+ }
+
+ /**
+ * Compares a static selector with a candidate version. Algorithm is inspired
+ * by PHP version_compare one.
+ *
+ * TODO: compare() is inconsistent with accept(), because not everything
+ * that compares equal is accepted (e.g. 1.0 vs. 1_0). Can this cause problems?
+ */
+ public int compare(String selector, String candidate) {
+ if (selector.equals(candidate)) {
+ return 0;
+ }
+
+ selector = selector.replaceAll("([a-zA-Z])(\\d)", "$1.$2");
+ selector = selector.replaceAll("(\\d)([a-zA-Z])", "$1.$2");
+ candidate = candidate.replaceAll("([a-zA-Z])(\\d)", "$1.$2");
+ candidate = candidate.replaceAll("(\\d)([a-zA-Z])", "$1.$2");
+
+ String[] parts1 = selector.split("[\\._\\-\\+]");
+ String[] parts2 = candidate.split("[\\._\\-\\+]");
+
+ int i = 0;
+ for (; i < parts1.length && i < parts2.length; i++) {
+ if (parts1[i].equals(parts2[i])) {
+ continue;
+ }
+ boolean is1Number = isNumber(parts1[i]);
+ boolean is2Number = isNumber(parts2[i]);
+ if (is1Number && !is2Number) {
+ return 1;
+ }
+ if (is2Number && !is1Number) {
+ return -1;
+ }
+ if (is1Number && is2Number) {
+ return Long.valueOf(parts1[i]).compareTo(Long.valueOf(parts2[i]));
+ }
+ // both are strings, we compare them taking into account special meaning
+ Integer sm1 = SPECIAL_MEANINGS.get(parts1[i].toLowerCase(Locale.US));
+ Integer sm2 = SPECIAL_MEANINGS.get(parts2[i].toLowerCase(Locale.US));
+ if (sm1 != null) {
+ sm2 = sm2 == null ? 0 : sm2;
+ return sm1 - sm2;
+ }
+ if (sm2 != null) {
+ return -sm2;
+ }
+ return parts1[i].compareTo(parts2[i]);
+ }
+ if (i < parts1.length) {
+ return isNumber(parts1[i]) ? 1 : -1;
+ }
+ if (i < parts2.length) {
+ return isNumber(parts2[i]) ? -1 : 1;
+ }
+
+ return 0;
+ }
+
+ private boolean isNumber(String str) {
+ return str.matches("\\d+");
+ }
+}
\ No newline at end of file
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/LatestStrategy.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/LatestStrategy.java
new file mode 100644
index 0000000..c442e20
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/LatestStrategy.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy;
+
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.Versioned;
+
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.List;
+
+public interface LatestStrategy extends Comparator<Versioned> {
+ /**
+ * Finds the latest among the given versioned elements. The definition of 'latest'
+ * depends on the strategy itself.
+ */
+ <T extends Versioned> T findLatest(Collection<T> elements);
+
+ /**
+ * Sorts the given versioned elements from oldest to latest. The definition of
+ * 'latest' depends on the strategy itself.
+ */
+ <T extends Versioned> List<T> sort(Collection<T> elements);
+
+ /**
+ * Compares two versioned elements to see which is the 'latest'. The definition of
+ * 'latest' depends on the strategy itself.
+ */
+ int compare(Versioned element1, Versioned element2);
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/LatestVersionMatcher.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/LatestVersionMatcher.java
new file mode 100644
index 0000000..490c7ed
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/LatestVersionMatcher.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy;
+
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ModuleVersionMetaData;
+
+public class LatestVersionMatcher implements VersionMatcher {
+ public boolean canHandle(String selector) {
+ return selector.startsWith("latest.");
+ }
+
+ public boolean isDynamic(String selector) {
+ return true;
+ }
+
+ public boolean needModuleMetadata(String selector, String candidate) {
+ return true;
+ }
+
+ public boolean accept(String selector, String candidate) {
+ throw new UnsupportedOperationException("accept(String, String)");
+ }
+
+ public boolean accept(String selector, ModuleVersionMetaData candidate) {
+ String selectorStatus = selector.substring("latest.".length());
+ int selectorStatusIndex = candidate.getStatusScheme().indexOf(selectorStatus);
+ int candidateStatusIndex = candidate.getStatusScheme().indexOf(candidate.getStatus());
+ return selectorStatusIndex >=0 && selectorStatusIndex <= candidateStatusIndex;
+ }
+
+ public int compare(String selector, String candidate) {
+ return 0;
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/LatestVersionStrategy.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/LatestVersionStrategy.java
new file mode 100644
index 0000000..576d258
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/LatestVersionStrategy.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy;
+
+import com.google.common.collect.Lists;
+
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.Versioned;
+
+import java.util.*;
+
+class LatestVersionStrategy implements LatestStrategy {
+ private final VersionMatcher versionMatcher;
+
+ public LatestVersionStrategy(VersionMatcher versionMatcher) {
+ this.versionMatcher = versionMatcher;
+ }
+
+ public <T extends Versioned> List<T> sort(Collection<T> versions) {
+ List<T> result = Lists.newArrayList(versions);
+ Collections.sort(result, this);
+ return result;
+ }
+
+ public <T extends Versioned> T findLatest(Collection<T> elements) {
+ return Collections.max(elements, this);
+ }
+
+ // TODO: Compared to Ivy's LatestRevisionStrategy.compare(), this method doesn't do any
+ // equivalent of ModuleRevisionId.normalizeRevision(). Should we add this functionality
+ // back in, either here or (probably better) in (Chain)VersionMatcher?
+ public int compare(Versioned element1, Versioned element2) {
+ String version1 = element1.getVersion();
+ String version2 = element2.getVersion();
+
+ /*
+ * The revisions can still be not resolved, so we use the current version matcher to
+ * know if one revision is dynamic, and in this case if it should be considered greater
+ * or lower than the other one. Note that if the version matcher compare method returns
+ * 0, it's because it's not possible to know which revision is greater. In this case we
+ * consider the dynamic one to be greater, because most of the time it will then be
+ * actually resolved and a real comparison will occur.
+ */
+ if (versionMatcher.isDynamic(version1)) {
+ int c = versionMatcher.compare(version1, version2);
+ return c >= 0 ? 1 : -1;
+ } else if (versionMatcher.isDynamic(version2)) {
+ int c = versionMatcher.compare(version2, version1);
+ return c >= 0 ? -1 : 1;
+ }
+
+ return versionMatcher.compare(version1, version2);
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/ResolverStrategy.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/ResolverStrategy.java
new file mode 100644
index 0000000..db0a295
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/ResolverStrategy.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy;
+
+import com.google.common.collect.Maps;
+import org.apache.ivy.plugins.matcher.*;
+
+import java.util.Map;
+
+public class ResolverStrategy {
+ public static final ResolverStrategy INSTANCE = new ResolverStrategy();
+
+ private final VersionMatcher versionMatcher;
+ private final LatestStrategy latestStrategy;
+ private final Map<String, PatternMatcher> matchers = Maps.newHashMap();
+
+ private ResolverStrategy() {
+ ChainVersionMatcher chain = new ChainVersionMatcher();
+ chain.add(new VersionRangeMatcher(new ExactVersionMatcher()));
+ chain.add(new SubVersionMatcher(new ExactVersionMatcher()));
+ chain.add(new LatestVersionMatcher());
+ chain.add(new ExactVersionMatcher());
+
+ versionMatcher = chain;
+ latestStrategy = new LatestVersionStrategy(chain);
+
+ addMatcher(ExactPatternMatcher.INSTANCE);
+ addMatcher(RegexpPatternMatcher.INSTANCE);
+ addMatcher(ExactOrRegexpPatternMatcher.INSTANCE);
+ addMatcher(GlobPatternMatcher.INSTANCE);
+ }
+
+ private void addMatcher(PatternMatcher instance) {
+ matchers.put(instance.getName(), instance);
+ }
+
+ public VersionMatcher getVersionMatcher() {
+ return versionMatcher;
+ }
+
+ public LatestStrategy getLatestStrategy() {
+ return latestStrategy;
+ }
+
+ public PatternMatcher getPatternMatcher(String name) {
+ return matchers.get(name);
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/SubVersionMatcher.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/SubVersionMatcher.java
new file mode 100644
index 0000000..f877fa4
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/SubVersionMatcher.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy;
+
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ModuleVersionMetaData;
+
+import java.util.Comparator;
+
+/**
+ * Version matcher for dynamic version selectors ending in '+'.
+ */
+public class SubVersionMatcher implements VersionMatcher {
+ private final Comparator<String> staticVersionComparator;
+
+ public SubVersionMatcher(VersionMatcher staticVersionComparator) {
+ this.staticVersionComparator = staticVersionComparator;
+ }
+
+ public boolean canHandle(String selector) {
+ return selector.endsWith("+");
+ }
+
+ public boolean isDynamic(String selector) {
+ return true;
+ }
+
+ public boolean needModuleMetadata(String selector, String candidate) {
+ return false;
+ }
+
+ public boolean accept(String selector, String candidate) {
+ String prefix = selector.substring(0, selector.length() - 1);
+ return candidate.startsWith(prefix);
+ }
+
+ public boolean accept(String selector, ModuleVersionMetaData candidate) {
+ return accept(selector, candidate.getId().getVersion());
+ }
+
+ public int compare(String selector, String candidate) {
+ if (accept(selector, candidate)) {
+ return 1;
+ }
+ return staticVersionComparator.compare(selector, candidate);
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/VersionMatcher.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/VersionMatcher.java
new file mode 100644
index 0000000..ce92b58
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/VersionMatcher.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy;
+
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ModuleVersionMetaData;
+
+import java.util.Comparator;
+
+/**
+ * Compares version selectors against candidate versions, indicating whether they match or not.
+ *
+ * <p>This interface was initially derived from {@code org.apache.ivy.plugins.version.VersionMatcher}.
+ */
+public interface VersionMatcher extends Comparator<String> {
+ /**
+ * Tells if this version matcher can handle the given version selector. If {@code false}
+ * is returned, none of the other methods will be called for the given selector.
+ */
+ public boolean canHandle(String selector);
+
+ /**
+ * Indicates if the given version selector is dynamic.
+ */
+ public boolean isDynamic(String selector);
+
+ /**
+ * Indicates if module metadata is required to determine if the given version
+ * selector matches the given candidate version.
+ */
+ public boolean needModuleMetadata(String selector, String candidate);
+
+ /**
+ * Indicates if the given version selector matches the given candidate version.
+ * Only called if {@link #needModuleMetadata} returned {@code false} for the given selector
+ * and candidate version.
+ */
+ public boolean accept(String selector, String candidate);
+
+ /**
+ * Indicates if the given version selector matches the given given candidate version
+ * (whose metadata is provided). May also be called if {@link #isDynamic} returned
+ * {@code false} for the given selector, in which case it should return the same result as
+ * {@code accept(selector, candidate.getId().getVersion()}.
+ */
+ public boolean accept(String selector, ModuleVersionMetaData candidate);
+
+ /**
+ *
+ * Compares a version selector with a candidate version to indicate which is greater. If there is
+ * not enough information to tell which is greater, the version selector should be considered greater
+ * and this method should return 0.
+ */
+ public int compare(String selector, String candidate);
+}
\ No newline at end of file
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/VersionRangeMatcher.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/VersionRangeMatcher.java
new file mode 100644
index 0000000..96182ad
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/VersionRangeMatcher.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy;
+
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ModuleVersionMetaData;
+
+import java.util.Comparator;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Matches version ranges: [1.0,2.0] matches all versions greater or equal to 1.0 and lower or equal
+ * to 2.0 [1.0,2.0[ matches all versions greater or equal to 1.0 and lower than 2.0 ]1.0,2.0]
+ * matches all versions greater than 1.0 and lower or equal to 2.0 ]1.0,2.0[ matches all versions
+ * greater than 1.0 and lower than 2.0 [1.0,) matches all versions greater or equal to 1.0 ]1.0,)
+ * matches all versions greater than 1.0 (,2.0] matches all versions lower or equal to 2.0 (,2.0[
+ * matches all versions lower than 2.0 This class uses a latest strategy to compare revisions. If
+ * none is set, it uses the default one of the ivy instance set through setIvy(). If neither a
+ * latest strategy nor a ivy instance is set, an IllegalStateException will be thrown when calling
+ * accept(). Note that it can't work with latest time strategy, cause no time is known for the
+ * limits of the range. Therefore only purely revision based LatestStrategy can be used.
+ */
+class VersionRangeMatcher implements VersionMatcher {
+ private static final String OPEN_INC = "[";
+
+ private static final String OPEN_EXC = "]";
+ private static final String OPEN_EXC_MAVEN = "(";
+
+ private static final String CLOSE_INC = "]";
+
+ private static final String CLOSE_EXC = "[";
+ private static final String CLOSE_EXC_MAVEN = ")";
+
+ private static final String LOWER_INFINITE = "(";
+
+ private static final String UPPER_INFINITE = ")";
+
+ private static final String SEPARATOR = ",";
+
+ // following patterns are built upon constants above and should not be modified
+ private static final String OPEN_INC_PATTERN = "\\" + OPEN_INC;
+
+ private static final String OPEN_EXC_PATTERN = "\\" + OPEN_EXC + "\\" + OPEN_EXC_MAVEN;
+
+ private static final String CLOSE_INC_PATTERN = "\\" + CLOSE_INC;
+
+ private static final String CLOSE_EXC_PATTERN = "\\" + CLOSE_EXC + "\\" + CLOSE_EXC_MAVEN;
+
+ private static final String LI_PATTERN = "\\" + LOWER_INFINITE;
+
+ private static final String UI_PATTERN = "\\" + UPPER_INFINITE;
+
+ private static final String SEP_PATTERN = "\\s*\\" + SEPARATOR + "\\s*";
+
+ private static final String OPEN_PATTERN = "[" + OPEN_INC_PATTERN + OPEN_EXC_PATTERN + "]";
+
+ private static final String CLOSE_PATTERN = "[" + CLOSE_INC_PATTERN + CLOSE_EXC_PATTERN + "]";
+
+ private static final String ANY_NON_SPECIAL_PATTERN = "[^\\s" + SEPARATOR + OPEN_INC_PATTERN
+ + OPEN_EXC_PATTERN + CLOSE_INC_PATTERN + CLOSE_EXC_PATTERN + LI_PATTERN + UI_PATTERN
+ + "]";
+
+ private static final String FINITE_PATTERN = OPEN_PATTERN + "\\s*(" + ANY_NON_SPECIAL_PATTERN
+ + "+)" + SEP_PATTERN + "(" + ANY_NON_SPECIAL_PATTERN + "+)\\s*" + CLOSE_PATTERN;
+
+ private static final String LOWER_INFINITE_PATTERN = LI_PATTERN + SEP_PATTERN + "("
+ + ANY_NON_SPECIAL_PATTERN + "+)\\s*" + CLOSE_PATTERN;
+
+ private static final String UPPER_INFINITE_PATTERN = OPEN_PATTERN + "\\s*("
+ + ANY_NON_SPECIAL_PATTERN + "+)" + SEP_PATTERN + UI_PATTERN;
+
+ private static final Pattern FINITE_RANGE = Pattern.compile(FINITE_PATTERN);
+
+ private static final Pattern LOWER_INFINITE_RANGE = Pattern.compile(LOWER_INFINITE_PATTERN);
+
+ private static final Pattern UPPER_INFINITE_RANGE = Pattern.compile(UPPER_INFINITE_PATTERN);
+
+ private static final Pattern ALL_RANGE = Pattern.compile(FINITE_PATTERN + "|"
+ + LOWER_INFINITE_PATTERN + "|" + UPPER_INFINITE_PATTERN);
+
+ private final Comparator<String> staticVersionComparator;
+
+ public VersionRangeMatcher(VersionMatcher staticVersionComparator) {
+ this.staticVersionComparator = staticVersionComparator;
+ }
+
+ public boolean canHandle(String selector) {
+ return ALL_RANGE.matcher(selector).matches();
+ }
+
+ public boolean isDynamic(String selector) {
+ return true;
+ }
+
+ public boolean needModuleMetadata(String selector, String candidate) {
+ return false;
+ }
+
+ public boolean accept(String selector, String candidate) {
+ Matcher matcher;
+ matcher = FINITE_RANGE.matcher(selector);
+ if (matcher.matches()) {
+ String lower = matcher.group(1);
+ String upper = matcher.group(2);
+ return isHigher(candidate, lower, selector.startsWith(OPEN_INC))
+ && isLower(candidate, upper, selector.endsWith(CLOSE_INC));
+ }
+ matcher = LOWER_INFINITE_RANGE.matcher(selector);
+ if (matcher.matches()) {
+ String upper = matcher.group(1);
+ return isLower(candidate, upper, selector.endsWith(CLOSE_INC));
+ }
+ matcher = UPPER_INFINITE_RANGE.matcher(selector);
+ if (matcher.matches()) {
+ String lower = matcher.group(1);
+ return isHigher(candidate, lower, selector.startsWith(OPEN_INC));
+ }
+ throw new IllegalArgumentException("Not a version range selector: " + selector);
+ }
+
+ public boolean accept(String selector, ModuleVersionMetaData candidate) {
+ return accept(selector, candidate.getId().getVersion());
+ }
+
+ // doesn't seem to be quite in sync with accept() (e.g. open/close is not distinguished here)
+ public int compare(String selector, String candidate) {
+ Matcher m;
+ m = UPPER_INFINITE_RANGE.matcher(selector);
+ if (m.matches()) {
+ // no upper limit, the selector can always be considered greater
+ return 1;
+ }
+ String upper;
+ m = FINITE_RANGE.matcher(selector);
+ if (m.matches()) {
+ upper = m.group(2);
+ } else {
+ m = LOWER_INFINITE_RANGE.matcher(selector);
+ if (m.matches()) {
+ upper = m.group(1);
+ } else {
+ throw new IllegalArgumentException("Not a version range selector: " + selector);
+ }
+ }
+ int c = staticVersionComparator.compare(upper, candidate);
+ // If the comparison considers them equal, we must return -1, because we can't consider the
+ // dynamic version selector to be greater. Otherwise we can safely return the result of the static
+ // comparison.
+ return c == 0 ? -1 : c;
+ }
+
+ /**
+ * Tells if version1 is lower than version2.
+ */
+ private boolean isLower(String version1, String version2, boolean inclusive) {
+ int result = staticVersionComparator.compare(version1, version2);
+ return result <= (inclusive ? 0 : -1);
+ }
+
+ /**
+ * Tells if version1 is higher than version2.
+ */
+ private boolean isHigher(String version1, String version2, boolean inclusive) {
+ int result = staticVersionComparator.compare(version1, version2);
+ return result >= (inclusive ? 0 : 1);
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/modulecache/CachedModuleDescriptorParseContext.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/modulecache/CachedModuleDescriptorParseContext.java
new file mode 100644
index 0000000..e91c0f2
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/modulecache/CachedModuleDescriptorParseContext.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.modulecache;
+
+import org.apache.ivy.core.module.descriptor.Artifact;
+import org.apache.ivy.core.module.descriptor.DefaultDependencyDescriptor;
+import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
+import org.apache.ivy.core.module.id.ModuleRevisionId;
+import org.gradle.api.internal.artifacts.ivyservice.DefaultBuildableModuleVersionResolveResult;
+import org.gradle.api.internal.artifacts.ivyservice.DependencyToModuleVersionResolver;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.DefaultDependencyMetaData;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.AbstractDescriptorParseContext;
+
+/**
+ * Context used for parsing cached module descriptor files.
+ * Will only be used for parsing ivy.xml files, as pom files are converted before caching.
+ */
+class CachedModuleDescriptorParseContext extends AbstractDescriptorParseContext {
+ private final DependencyToModuleVersionResolver resolver;
+
+ public CachedModuleDescriptorParseContext(DependencyToModuleVersionResolver resolver, String defaultStatus) {
+ super(defaultStatus);
+ this.resolver = resolver;
+ }
+
+ public ModuleRevisionId getCurrentRevisionId() {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean artifactExists(Artifact artifact) {
+ throw new UnsupportedOperationException();
+ }
+
+ public ModuleDescriptor getModuleDescriptor(ModuleRevisionId moduleRevisionId) {
+ DefaultBuildableModuleVersionResolveResult result = new DefaultBuildableModuleVersionResolveResult();
+ resolver.resolve(new DefaultDependencyMetaData(new DefaultDependencyDescriptor(moduleRevisionId, true)), result);
+ return result.getMetaData().getDescriptor();
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/modulecache/DefaultCachedModuleDescriptor.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/modulecache/DefaultCachedModuleDescriptor.java
index 6596c0e..6e4a7ae 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/modulecache/DefaultCachedModuleDescriptor.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/modulecache/DefaultCachedModuleDescriptor.java
@@ -16,8 +16,9 @@
package org.gradle.api.internal.artifacts.ivyservice.modulecache;
import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
-import org.apache.ivy.core.module.id.ModuleRevisionId;
+import org.gradle.api.artifacts.ModuleVersionIdentifier;
import org.gradle.api.artifacts.ResolvedModuleVersion;
+import org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier;
import org.gradle.api.internal.artifacts.ivyservice.dynamicversions.DefaultResolvedModuleVersion;
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ModuleSource;
import org.gradle.internal.TimeProvider;
@@ -48,8 +49,8 @@ class DefaultCachedModuleDescriptor implements ModuleDescriptorCache.CachedModul
}
public ResolvedModuleVersion getModuleVersion() {
- ModuleRevisionId moduleRevisionId = isMissing() ? null : moduleDescriptor.getModuleRevisionId();
- return new DefaultResolvedModuleVersion(moduleRevisionId);
+ ModuleVersionIdentifier moduleVersionIdentifier = isMissing() ? null : DefaultModuleVersionIdentifier.newId(moduleDescriptor.getModuleRevisionId());
+ return new DefaultResolvedModuleVersion(moduleVersionIdentifier);
}
public ModuleDescriptor getModuleDescriptor() {
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/modulecache/DefaultModuleDescriptorCache.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/modulecache/DefaultModuleDescriptorCache.java
index 715c70c..0b663bc 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/modulecache/DefaultModuleDescriptorCache.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/modulecache/DefaultModuleDescriptorCache.java
@@ -20,16 +20,16 @@ import org.gradle.api.artifacts.ModuleVersionIdentifier;
import org.gradle.api.internal.artifacts.ModuleVersionIdentifierSerializer;
import org.gradle.api.internal.artifacts.ivyservice.ArtifactCacheMetaData;
import org.gradle.api.internal.artifacts.ivyservice.CacheLockingManager;
+import org.gradle.api.internal.artifacts.ivyservice.DependencyToModuleVersionResolver;
import org.gradle.api.internal.artifacts.ivyservice.IvyXmlModuleDescriptorWriter;
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ModuleSource;
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ModuleVersionRepository;
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.IvyXmlModuleDescriptorParser;
-import org.gradle.api.internal.filestore.FileStoreEntry;
import org.gradle.api.internal.filestore.PathKeyFileStore;
import org.gradle.cache.PersistentIndexedCache;
import org.gradle.internal.TimeProvider;
-import org.gradle.messaging.serialize.DataStreamBackedSerializer;
-import org.gradle.messaging.serialize.DefaultSerializer;
+import org.gradle.internal.resource.local.LocallyAvailableResource;
+import org.gradle.messaging.serialize.*;
import org.gradle.util.hash.HashValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -67,7 +67,7 @@ public class DefaultModuleDescriptorCache implements ModuleDescriptorCache {
return cacheLockingManager.createCache(artifactResolutionCacheFile, new RevisionKeySerializer(), new ModuleDescriptorCacheEntrySerializer());
}
- public CachedModuleDescriptor getCachedModuleDescriptor(ModuleVersionRepository repository, ModuleVersionIdentifier moduleVersionIdentifier) {
+ public CachedModuleDescriptor getCachedModuleDescriptor(ModuleVersionRepository repository, ModuleVersionIdentifier moduleVersionIdentifier, DependencyToModuleVersionResolver resolver) {
ModuleDescriptorCacheEntry moduleDescriptorCacheEntry = getCache().get(createKey(repository, moduleVersionIdentifier));
if (moduleDescriptorCacheEntry == null) {
return null;
@@ -75,7 +75,7 @@ public class DefaultModuleDescriptorCache implements ModuleDescriptorCache {
if (moduleDescriptorCacheEntry.isMissing) {
return new DefaultCachedModuleDescriptor(moduleDescriptorCacheEntry, null, timeProvider);
}
- ModuleDescriptor descriptor = moduleDescriptorStore.getModuleDescriptor(repository, moduleVersionIdentifier);
+ ModuleDescriptor descriptor = moduleDescriptorStore.getModuleDescriptor(repository, moduleVersionIdentifier, resolver);
if (descriptor == null) {
// Descriptor file has been manually deleted - ignore the entry
return null;
@@ -91,8 +91,8 @@ public class DefaultModuleDescriptorCache implements ModuleDescriptorCache {
getCache().put(createKey(repository, moduleVersionIdentifier), entry);
} else {
LOGGER.debug("Recording module descriptor in cache: {} [changing = {}]", moduleDescriptor.getModuleRevisionId(), isChanging);
- FileStoreEntry fileStoreEntry = moduleDescriptorStore.putModuleDescriptor(repository, moduleDescriptor);
- entry = createEntry(isChanging, fileStoreEntry.getSha1(), moduleSource);
+ LocallyAvailableResource resource = moduleDescriptorStore.putModuleDescriptor(repository, moduleDescriptor);
+ entry = createEntry(isChanging, resource.getSha1(), moduleSource);
getCache().put(createKey(repository, moduleVersionIdentifier), entry);
}
return new DefaultCachedModuleDescriptor(entry, null, timeProvider);
@@ -134,53 +134,45 @@ public class DefaultModuleDescriptorCache implements ModuleDescriptorCache {
}
}
- private static class RevisionKeySerializer extends DataStreamBackedSerializer<RevisionKey> {
+ private static class RevisionKeySerializer implements Serializer<RevisionKey> {
private final ModuleVersionIdentifierSerializer identifierSerializer = new ModuleVersionIdentifierSerializer();
- @Override
- public void write(DataOutput dataOutput, RevisionKey value) throws IOException {
- dataOutput.writeUTF(value.repositoryId);
- identifierSerializer.write(dataOutput, value.moduleVersionIdentifier);
+ public void write(Encoder encoder, RevisionKey value) throws Exception {
+ encoder.writeString(value.repositoryId);
+ identifierSerializer.write(encoder, value.moduleVersionIdentifier);
}
- @Override
- public RevisionKey read(DataInput dataInput) throws IOException {
- String resolverId = dataInput.readUTF();
- ModuleVersionIdentifier identifier = identifierSerializer.read(dataInput);
+ public RevisionKey read(Decoder decoder) throws Exception {
+ String resolverId = decoder.readString();
+ ModuleVersionIdentifier identifier = identifierSerializer.read(decoder);
return new RevisionKey(resolverId, identifier);
}
}
- private static class ModuleDescriptorCacheEntrySerializer extends DataStreamBackedSerializer<ModuleDescriptorCacheEntry> {
+ private static class ModuleDescriptorCacheEntrySerializer implements Serializer<ModuleDescriptorCacheEntry> {
private final DefaultSerializer<ModuleSource> moduleSourceSerializer = new DefaultSerializer<ModuleSource>(ModuleSource.class.getClassLoader());
- @Override
- public void write(DataOutput dataOutput, ModuleDescriptorCacheEntry value) throws IOException {
- dataOutput.writeBoolean(value.isMissing);
- dataOutput.writeBoolean(value.isChanging);
- dataOutput.writeLong(value.createTimestamp);
+ public void write(Encoder encoder, ModuleDescriptorCacheEntry value) throws Exception {
+ encoder.writeBoolean(value.isMissing);
+ encoder.writeBoolean(value.isChanging);
+ encoder.writeLong(value.createTimestamp);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
- moduleSourceSerializer.write(outputStream, value.moduleSource);
+ OutputStreamBackedEncoder sourceEncoder = new OutputStreamBackedEncoder(outputStream);
+ moduleSourceSerializer.write(sourceEncoder, value.moduleSource);
+ sourceEncoder.flush();
byte[] serializedModuleSource = outputStream.toByteArray();
- dataOutput.writeInt(serializedModuleSource.length);
- dataOutput.write(serializedModuleSource);
+ encoder.writeBinary(serializedModuleSource);
byte[] hash = value.moduleDescriptorHash.toByteArray();
- dataOutput.writeInt(hash.length);
- dataOutput.write(hash);
+ encoder.writeBinary(hash);
}
- @Override
- public ModuleDescriptorCacheEntry read(DataInput dataInput) throws Exception {
- boolean isMissing = dataInput.readBoolean();
- boolean isChanging = dataInput.readBoolean();
- long createTimestamp = dataInput.readLong();
- int count = dataInput.readInt();
- byte[] serializedModuleSource = new byte[count];
- dataInput.readFully(serializedModuleSource);
- ModuleSource moduleSource = moduleSourceSerializer.read(new ByteArrayInputStream(serializedModuleSource));
- count = dataInput.readInt();
- byte[] encodedHash = new byte[count];
- dataInput.readFully(encodedHash);
+ public ModuleDescriptorCacheEntry read(Decoder decoder) throws Exception {
+ boolean isMissing = decoder.readBoolean();
+ boolean isChanging = decoder.readBoolean();
+ long createTimestamp = decoder.readLong();
+ byte[] serializedModuleSource = decoder.readBinary();
+ ModuleSource moduleSource = moduleSourceSerializer.read(new InputStreamBackedDecoder(new ByteArrayInputStream(serializedModuleSource)));
+ byte[] encodedHash = decoder.readBinary();
BigInteger hash = new BigInteger(encodedHash);
return new ModuleDescriptorCacheEntry(isChanging, isMissing, createTimestamp, hash, moduleSource);
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleDescriptorCache.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleDescriptorCache.java
index 096535f..ec3427e 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleDescriptorCache.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleDescriptorCache.java
@@ -18,6 +18,7 @@ package org.gradle.api.internal.artifacts.ivyservice.modulecache;
import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
import org.gradle.api.artifacts.ModuleVersionIdentifier;
import org.gradle.api.artifacts.ResolvedModuleVersion;
+import org.gradle.api.internal.artifacts.ivyservice.DependencyToModuleVersionResolver;
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ModuleSource;
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ModuleVersionRepository;
@@ -26,7 +27,8 @@ import java.math.BigInteger;
public interface ModuleDescriptorCache {
CachedModuleDescriptor cacheModuleDescriptor(ModuleVersionRepository repository, ModuleVersionIdentifier resolvedModuleVersionIdentifier, ModuleDescriptor moduleDescriptor, ModuleSource moduleSource, boolean isChanging);
- CachedModuleDescriptor getCachedModuleDescriptor(ModuleVersionRepository repository, ModuleVersionIdentifier moduleVersionIdentifier);
+ // TODO:DAZ Should not need a resolver to parse the cached descriptors: descriptor should be self-contained.
+ CachedModuleDescriptor getCachedModuleDescriptor(ModuleVersionRepository repository, ModuleVersionIdentifier moduleVersionIdentifier, DependencyToModuleVersionResolver resolver);
interface CachedModuleDescriptor {
ResolvedModuleVersion getModuleVersion();
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleDescriptorStore.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleDescriptorStore.java
index 03bf319..c18643a 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleDescriptorStore.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleDescriptorStore.java
@@ -17,43 +17,43 @@ package org.gradle.api.internal.artifacts.ivyservice.modulecache;
import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
import org.apache.ivy.core.module.id.ModuleRevisionId;
-import org.apache.ivy.plugins.parser.ParserSettings;
import org.gradle.api.Action;
import org.gradle.api.artifacts.ModuleVersionIdentifier;
+import org.gradle.api.internal.artifacts.ivyservice.DependencyToModuleVersionResolver;
import org.gradle.api.internal.artifacts.ivyservice.IvyModuleDescriptorWriter;
-import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.IvyContextualiser;
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ModuleVersionRepository;
-import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.IvyXmlModuleDescriptorParser;
-import org.gradle.api.internal.filestore.FileStoreEntry;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.DescriptorParseContext;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.ModuleDescriptorParser;
import org.gradle.api.internal.filestore.PathKeyFileStore;
import org.gradle.internal.UncheckedException;
+import org.gradle.internal.resource.local.LocallyAvailableResource;
import java.io.File;
-import java.net.URL;
public class ModuleDescriptorStore {
public static final String FILE_PATH_PATTERN = "module-metadata/%s/%s/%s/%s/ivy.xml";
- private final IvyXmlModuleDescriptorParser parser;
+ private final ModuleDescriptorParser parser;
private final PathKeyFileStore pathKeyFileStore;
private final IvyModuleDescriptorWriter ivyModuleDescriptorWriter;
- public ModuleDescriptorStore(PathKeyFileStore pathKeyFileStore, IvyModuleDescriptorWriter ivyModuleDescriptorWriter, IvyXmlModuleDescriptorParser ivyXmlModuleDescriptorParser) {
+ public ModuleDescriptorStore(PathKeyFileStore pathKeyFileStore, IvyModuleDescriptorWriter ivyModuleDescriptorWriter, ModuleDescriptorParser ivyXmlModuleDescriptorParser) {
this.pathKeyFileStore = pathKeyFileStore;
this.ivyModuleDescriptorWriter = ivyModuleDescriptorWriter;
parser = ivyXmlModuleDescriptorParser;
}
- public ModuleDescriptor getModuleDescriptor(ModuleVersionRepository repository, ModuleVersionIdentifier moduleVersionIdentifier) {
+ // TODO:DAZ Persisted module descriptors should be self-contained: should not need to resolve included descriptors
+ public ModuleDescriptor getModuleDescriptor(ModuleVersionRepository repository, ModuleVersionIdentifier moduleVersionIdentifier, DependencyToModuleVersionResolver resolver) {
String filePath = getFilePath(repository, moduleVersionIdentifier);
- final FileStoreEntry fileStoreEntry = pathKeyFileStore.get(filePath);
- if (fileStoreEntry != null) {
- return parseModuleDescriptorFile(fileStoreEntry.getFile());
+ final LocallyAvailableResource resource = pathKeyFileStore.get(filePath);
+ if (resource != null) {
+ return parseModuleDescriptorFile(resource.getFile(), resolver);
}
return null;
}
- public FileStoreEntry putModuleDescriptor(ModuleVersionRepository repository, final ModuleDescriptor moduleDescriptor) {
+ public LocallyAvailableResource putModuleDescriptor(ModuleVersionRepository repository, final ModuleDescriptor moduleDescriptor) {
String filePath = getFilePath(repository, moduleDescriptor.getModuleRevisionId());
return pathKeyFileStore.add(filePath, new Action<File>() {
public void execute(File moduleDescriptorFile) {
@@ -66,14 +66,9 @@ public class ModuleDescriptorStore {
});
}
- private ModuleDescriptor parseModuleDescriptorFile(File moduleDescriptorFile) {
- ParserSettings settings = IvyContextualiser.getIvyContext().getSettings();
- try {
- URL result = moduleDescriptorFile.toURI().toURL();
- return parser.parseDescriptor(settings, result, false);
- } catch (Exception e) {
- throw UncheckedException.throwAsUncheckedException(e);
- }
+ private ModuleDescriptor parseModuleDescriptorFile(File moduleDescriptorFile, DependencyToModuleVersionResolver resolver) {
+ DescriptorParseContext parserSettings = new CachedModuleDescriptorParseContext(resolver, "integration");
+ return parser.parseDescriptor(parserSettings, moduleDescriptorFile, false);
}
private String getFilePath(ModuleVersionRepository repository, ModuleRevisionId moduleRevisionId) {
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/ArtifactsExtraAttributesStrategy.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/ArtifactsExtraAttributesStrategy.java
deleted file mode 100644
index 4828e51..0000000
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/ArtifactsExtraAttributesStrategy.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.artifacts.ivyservice.moduleconverter;
-
-import org.gradle.api.artifacts.PublishArtifact;
-
-import java.util.Map;
-
-/**
- * @author Hans Dockter
- */
-public interface ArtifactsExtraAttributesStrategy {
- Map<String, String> createExtraAttributes(PublishArtifact publishArtifact);
-}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/ArtifactsToModuleDescriptorConverter.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/ArtifactsToModuleDescriptorConverter.java
index 112e678..fe2e40f 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/ArtifactsToModuleDescriptorConverter.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/ArtifactsToModuleDescriptorConverter.java
@@ -15,12 +15,9 @@
*/
package org.gradle.api.internal.artifacts.ivyservice.moduleconverter;
-import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor;
import org.gradle.api.artifacts.Configuration;
+import org.gradle.api.internal.artifacts.BuildableModuleVersionPublishMetaData;
-/**
- * @author Hans Dockter
- */
public interface ArtifactsToModuleDescriptorConverter {
- void addArtifacts(DefaultModuleDescriptor moduleDescriptor, Iterable<? extends Configuration> configurations);
+ void addArtifacts(BuildableModuleVersionPublishMetaData metaData, Iterable<? extends Configuration> configurations);
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/ConfigurationsToModuleDescriptorConverter.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/ConfigurationsToModuleDescriptorConverter.java
index 4e033fa..2b82fe3 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/ConfigurationsToModuleDescriptorConverter.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/ConfigurationsToModuleDescriptorConverter.java
@@ -18,9 +18,6 @@ package org.gradle.api.internal.artifacts.ivyservice.moduleconverter;
import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor;
import org.gradle.api.artifacts.Configuration;
-/**
- * @author Hans Dockter
- */
public interface ConfigurationsToModuleDescriptorConverter {
void addConfigurations(DefaultModuleDescriptor moduleDescriptor, Iterable<? extends Configuration> configurations);
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/DefaultArtifactsToModuleDescriptorConverter.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/DefaultArtifactsToModuleDescriptorConverter.java
index 48000c1..a8e3f34 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/DefaultArtifactsToModuleDescriptorConverter.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/DefaultArtifactsToModuleDescriptorConverter.java
@@ -22,46 +22,27 @@ import org.apache.ivy.core.module.id.ModuleRevisionId;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.artifacts.PublishArtifact;
-import org.gradle.api.internal.artifacts.ivyservice.DefaultIvyDependencyPublisher;
+import org.gradle.api.internal.artifacts.BuildableModuleVersionPublishMetaData;
import org.gradle.util.GUtil;
-import org.gradle.util.WrapUtil;
import java.util.HashMap;
import java.util.Map;
-/**
- * @author Hans Dockter
- */
public class DefaultArtifactsToModuleDescriptorConverter implements ArtifactsToModuleDescriptorConverter {
- public final static ArtifactsExtraAttributesStrategy IVY_FILE_STRATEGY = new ArtifactsExtraAttributesStrategy() {
- public Map<String, String> createExtraAttributes(PublishArtifact publishArtifact) {
- return new HashMap<String, String>();
- }
- };
-
- public final static ArtifactsExtraAttributesStrategy RESOLVE_STRATEGY = new ArtifactsExtraAttributesStrategy() {
- public Map<String, String> createExtraAttributes(PublishArtifact publishArtifact) {
- return WrapUtil.toMap(DefaultIvyDependencyPublisher.FILE_ABSOLUTE_PATH_EXTRA_ATTRIBUTE, publishArtifact.getFile().getAbsolutePath());
- }
- };
-
- private ArtifactsExtraAttributesStrategy artifactsExtraAttributesStrategy;
-
- public DefaultArtifactsToModuleDescriptorConverter(ArtifactsExtraAttributesStrategy artifactsExtraAttributesStrategy) {
- this.artifactsExtraAttributesStrategy = artifactsExtraAttributesStrategy;
- }
- public void addArtifacts(DefaultModuleDescriptor moduleDescriptor, Iterable<? extends Configuration> configurations) {
+ public void addArtifacts(BuildableModuleVersionPublishMetaData metaData, Iterable<? extends Configuration> configurations) {
+ DefaultModuleDescriptor moduleDescriptor = metaData.getModuleDescriptor();
for (Configuration configuration : configurations) {
for (PublishArtifact publishArtifact : configuration.getArtifacts()) {
Artifact ivyArtifact = createIvyArtifact(publishArtifact, moduleDescriptor.getModuleRevisionId());
moduleDescriptor.addArtifact(configuration.getName(), ivyArtifact);
+ metaData.addArtifact(ivyArtifact, publishArtifact.getFile());
}
}
}
public Artifact createIvyArtifact(PublishArtifact publishArtifact, ModuleRevisionId moduleRevisionId) {
- Map<String, String> extraAttributes = artifactsExtraAttributesStrategy.createExtraAttributes(publishArtifact);
+ Map<String, String> extraAttributes = new HashMap<String, String>();
if (GUtil.isTrue(publishArtifact.getClassifier())) {
extraAttributes.put(Dependency.CLASSIFIER, publishArtifact.getClassifier());
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/DefaultConfigurationsToModuleDescriptorConverter.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/DefaultConfigurationsToModuleDescriptorConverter.java
index 47dce97..c7cdc2d 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/DefaultConfigurationsToModuleDescriptorConverter.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/DefaultConfigurationsToModuleDescriptorConverter.java
@@ -21,9 +21,6 @@ import org.gradle.api.internal.artifacts.configurations.Configurations;
import java.util.Arrays;
-/**
- * @author Hans Dockter
- */
public class DefaultConfigurationsToModuleDescriptorConverter implements ConfigurationsToModuleDescriptorConverter {
public void addConfigurations(DefaultModuleDescriptor moduleDescriptor, Iterable<? extends Configuration> configurations) {
for (Configuration configuration : configurations) {
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/DefaultExcludeRuleConverter.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/DefaultExcludeRuleConverter.java
index 3b6392e..13090fd 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/DefaultExcludeRuleConverter.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/DefaultExcludeRuleConverter.java
@@ -23,9 +23,6 @@ import org.apache.ivy.plugins.matcher.PatternMatcher;
import org.gradle.api.artifacts.ExcludeRule;
import org.gradle.util.GUtil;
-/**
- * @author Hans Dockter
- */
public class DefaultExcludeRuleConverter implements ExcludeRuleConverter {
public DefaultExcludeRule createExcludeRule(String configurationName, ExcludeRule excludeRule) {
String org = GUtil.elvis(excludeRule.getGroup(), PatternMatcher.ANY_EXPRESSION);
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/DefaultModuleDescriptorFactory.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/DefaultModuleDescriptorFactory.java
index 3abe439..5c1ffe3 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/DefaultModuleDescriptorFactory.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/DefaultModuleDescriptorFactory.java
@@ -15,34 +15,12 @@
*/
package org.gradle.api.internal.artifacts.ivyservice.moduleconverter;
-import org.apache.ivy.Ivy;
-import org.apache.ivy.core.IvyContext;
import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor;
import org.gradle.api.artifacts.Module;
-import org.gradle.api.internal.artifacts.ivyservice.IvyFactory;
import org.gradle.api.internal.artifacts.ivyservice.IvyUtil;
-import org.gradle.api.internal.artifacts.ivyservice.SettingsConverter;
-/**
- * @author Hans Dockter
- */
public class DefaultModuleDescriptorFactory implements ModuleDescriptorFactory {
- private final IvyFactory ivyFactory;
- private final SettingsConverter settingsConverter;
-
- public DefaultModuleDescriptorFactory(IvyFactory ivyFactory, SettingsConverter settingsConverter) {
- this.ivyFactory = ivyFactory;
- this.settingsConverter = settingsConverter;
- }
-
public DefaultModuleDescriptor createModuleDescriptor(Module module) {
- IvyContext ivyContext = IvyContext.pushNewContext();
- try {
- Ivy ivy = ivyFactory.createIvy(settingsConverter.getForResolve());
- ivyContext.setIvy(ivy);
- return new DefaultModuleDescriptor(IvyUtil.createModuleRevisionId(module), module.getStatus(), null);
- } finally {
- IvyContext.popContext();
- }
+ return new DefaultModuleDescriptor(IvyUtil.createModuleRevisionId(module), module.getStatus(), null);
}
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/ExcludeRuleConverter.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/ExcludeRuleConverter.java
index 4ed4bc5..00c5612 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/ExcludeRuleConverter.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/ExcludeRuleConverter.java
@@ -17,9 +17,6 @@ package org.gradle.api.internal.artifacts.ivyservice.moduleconverter;
import org.apache.ivy.core.module.descriptor.ExcludeRule;
-/**
- * @author Hans Dockter
- */
public interface ExcludeRuleConverter {
ExcludeRule createExcludeRule(String configuration, org.gradle.api.artifacts.ExcludeRule excludeRule);
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/ModuleDescriptorFactory.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/ModuleDescriptorFactory.java
index 1f271a9..afc2fe5 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/ModuleDescriptorFactory.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/ModuleDescriptorFactory.java
@@ -18,9 +18,6 @@ package org.gradle.api.internal.artifacts.ivyservice.moduleconverter;
import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor;
import org.gradle.api.artifacts.Module;
-/**
- * @author Hans Dockter
- */
public interface ModuleDescriptorFactory {
DefaultModuleDescriptor createModuleDescriptor(Module module);
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/PublishModuleDescriptorConverter.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/PublishModuleDescriptorConverter.java
index 9f1f656..f98006d 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/PublishModuleDescriptorConverter.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/PublishModuleDescriptorConverter.java
@@ -17,17 +17,14 @@
package org.gradle.api.internal.artifacts.ivyservice.moduleconverter;
import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor;
-import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.Module;
-import org.gradle.api.artifacts.ModuleDependency;
+import org.gradle.api.internal.artifacts.BuildableModuleVersionPublishMetaData;
+import org.gradle.api.internal.artifacts.ModuleVersionPublishMetaData;
import org.gradle.api.internal.artifacts.ivyservice.ModuleDescriptorConverter;
import java.util.Set;
-/**
- * @author Hans Dockter
- */
public class PublishModuleDescriptorConverter implements ModuleDescriptorConverter {
static final String IVY_MAVEN_NAMESPACE = "http://ant.apache.org/ivy/maven";
static final String IVY_MAVEN_NAMESPACE_PREFIX = "m";
@@ -41,19 +38,11 @@ public class PublishModuleDescriptorConverter implements ModuleDescriptorConvert
this.artifactsToModuleDescriptorConverter = artifactsToModuleDescriptorConverter;
}
- public ModuleDescriptor convert(Set<? extends Configuration> configurations, Module module) {
- DefaultModuleDescriptor moduleDescriptor = (DefaultModuleDescriptor) resolveModuleDescriptorConverter
- .convert(configurations, module);
+ public ModuleVersionPublishMetaData convert(Set<? extends Configuration> configurations, Module module) {
+ BuildableModuleVersionPublishMetaData publishMetaData = (BuildableModuleVersionPublishMetaData) resolveModuleDescriptorConverter.convert(configurations, module);
+ DefaultModuleDescriptor moduleDescriptor = publishMetaData.getModuleDescriptor();
moduleDescriptor.addExtraAttributeNamespace(IVY_MAVEN_NAMESPACE_PREFIX, IVY_MAVEN_NAMESPACE);
- artifactsToModuleDescriptorConverter.addArtifacts(moduleDescriptor, configurations);
- return moduleDescriptor;
- }
-
- public ModuleDescriptor createModuleDescriptor(Module module) {
- return resolveModuleDescriptorConverter.createModuleDescriptor(module);
- }
-
- public void addDependencyDescriptor(String configuration, DefaultModuleDescriptor moduleDescriptor, ModuleDependency dependency) {
- resolveModuleDescriptorConverter.addDependencyDescriptor(configuration, moduleDescriptor, dependency);
+ artifactsToModuleDescriptorConverter.addArtifacts(publishMetaData, configurations);
+ return publishMetaData;
}
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/ResolveModuleDescriptorConverter.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/ResolveModuleDescriptorConverter.java
index c29ccb0..388bc6f 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/ResolveModuleDescriptorConverter.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/ResolveModuleDescriptorConverter.java
@@ -17,48 +17,33 @@
package org.gradle.api.internal.artifacts.ivyservice.moduleconverter;
import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor;
-import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.Module;
-import org.gradle.api.artifacts.ModuleDependency;
+import org.gradle.api.internal.artifacts.BuildableModuleVersionPublishMetaData;
+import org.gradle.api.internal.artifacts.DefaultModuleVersionPublishMetaData;
import org.gradle.api.internal.artifacts.ivyservice.ModuleDescriptorConverter;
import org.gradle.api.internal.artifacts.ivyservice.moduleconverter.dependencies.DependenciesToModuleDescriptorConverter;
-import org.gradle.api.internal.artifacts.ivyservice.moduleconverter.dependencies.DependencyDescriptorFactory;
import java.util.Set;
-/**
- * @author Hans Dockter
- */
public class ResolveModuleDescriptorConverter implements ModuleDescriptorConverter {
private final ModuleDescriptorFactory moduleDescriptorFactory;
- private final DependencyDescriptorFactory dependencyDescriptorFactory;
private final ConfigurationsToModuleDescriptorConverter configurationsToModuleDescriptorConverter;
private final DependenciesToModuleDescriptorConverter dependenciesToModuleDescriptorConverter;
public ResolveModuleDescriptorConverter(ModuleDescriptorFactory moduleDescriptorFactory,
- DependencyDescriptorFactory dependencyDescriptorFactory,
ConfigurationsToModuleDescriptorConverter configurationsToModuleDescriptorConverter,
DependenciesToModuleDescriptorConverter dependenciesToModuleDescriptorConverter) {
this.moduleDescriptorFactory = moduleDescriptorFactory;
- this.dependencyDescriptorFactory = dependencyDescriptorFactory;
this.configurationsToModuleDescriptorConverter = configurationsToModuleDescriptorConverter;
this.dependenciesToModuleDescriptorConverter = dependenciesToModuleDescriptorConverter;
}
- public ModuleDescriptor convert(Set<? extends Configuration> configurations, Module module) {
+ public BuildableModuleVersionPublishMetaData convert(Set<? extends Configuration> configurations, Module module) {
assert configurations.size() > 0 : "No configurations found for module: " + module.getName() + ". Configure them or apply a plugin that does it.";
DefaultModuleDescriptor moduleDescriptor = moduleDescriptorFactory.createModuleDescriptor(module);
configurationsToModuleDescriptorConverter.addConfigurations(moduleDescriptor, configurations);
dependenciesToModuleDescriptorConverter.addDependencyDescriptors(moduleDescriptor, configurations);
- return moduleDescriptor;
- }
-
- public ModuleDescriptor createModuleDescriptor(Module module) {
- return moduleDescriptorFactory.createModuleDescriptor(module);
- }
-
- public void addDependencyDescriptor(String configuration, DefaultModuleDescriptor moduleDescriptor, ModuleDependency dependency) {
- dependencyDescriptorFactory.addDependencyDescriptor(configuration, moduleDescriptor, dependency);
+ return new DefaultModuleVersionPublishMetaData(moduleDescriptor);
}
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/AbstractIvyDependencyDescriptorFactory.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/AbstractIvyDependencyDescriptorFactory.java
index 4e8d20e..60d7fd6 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/AbstractIvyDependencyDescriptorFactory.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/AbstractIvyDependencyDescriptorFactory.java
@@ -30,9 +30,6 @@ import java.net.MalformedURLException;
import java.net.URL;
import java.util.Set;
-/**
- * @author Hans Dockter
- */
public abstract class AbstractIvyDependencyDescriptorFactory implements IvyDependencyDescriptorFactory {
private ExcludeRuleConverter excludeRuleConverter;
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/ClientModuleIvyDependencyDescriptorFactory.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/ClientModuleIvyDependencyDescriptorFactory.java
index c4677cc..eeb8d0b 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/ClientModuleIvyDependencyDescriptorFactory.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/ClientModuleIvyDependencyDescriptorFactory.java
@@ -22,9 +22,6 @@ import org.gradle.api.artifacts.ModuleDependency;
import org.gradle.api.internal.artifacts.ivyservice.IvyUtil;
import org.gradle.api.internal.artifacts.ivyservice.moduleconverter.ExcludeRuleConverter;
-/**
- * @author Hans Dockter
-*/
public class ClientModuleIvyDependencyDescriptorFactory extends AbstractIvyDependencyDescriptorFactory {
private ModuleDescriptorFactoryForClientModule moduleDescriptorFactoryForClientModule;
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/DefaultDependenciesToModuleDescriptorConverter.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/DefaultDependenciesToModuleDescriptorConverter.java
index 625accc..c50beff 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/DefaultDependenciesToModuleDescriptorConverter.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/DefaultDependenciesToModuleDescriptorConverter.java
@@ -23,9 +23,6 @@ import org.gradle.api.internal.artifacts.ivyservice.moduleconverter.ExcludeRuleC
import java.util.Collection;
-/**
- * @author Hans Dockter
- */
public class DefaultDependenciesToModuleDescriptorConverter implements DependenciesToModuleDescriptorConverter {
private DependencyDescriptorFactory dependencyDescriptorFactory;
private ExcludeRuleConverter excludeRuleConverter;
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/DefaultDependencyDescriptorFactory.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/DefaultDependencyDescriptorFactory.java
index 23bba49..8ac55c4 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/DefaultDependencyDescriptorFactory.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/DefaultDependencyDescriptorFactory.java
@@ -23,9 +23,6 @@ import org.gradle.util.WrapUtil;
import java.util.List;
-/**
- * @author Hans Dockter
- */
public class DefaultDependencyDescriptorFactory implements DependencyDescriptorFactory {
private List<IvyDependencyDescriptorFactory> dependencyDescriptorFactories;
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/DefaultModuleDescriptorFactoryForClientModule.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/DefaultModuleDescriptorFactoryForClientModule.java
index f55f989..24b5aeb 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/DefaultModuleDescriptorFactoryForClientModule.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/DefaultModuleDescriptorFactoryForClientModule.java
@@ -25,11 +25,8 @@ import org.gradle.api.artifacts.ModuleDependency;
import java.util.Set;
-/**
- * @author Hans Dockter
- */
public class DefaultModuleDescriptorFactoryForClientModule implements ModuleDescriptorFactoryForClientModule {
- // Because of bi directioal dependencies we need setter injection
+ // Because of bidirectional dependencies we need setter injection
private DependencyDescriptorFactory dependencyDescriptorFactory;
public ModuleDescriptor createModuleDescriptor(ModuleRevisionId moduleRevisionId, Set<ModuleDependency> dependencies) {
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/DependenciesToModuleDescriptorConverter.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/DependenciesToModuleDescriptorConverter.java
index 3dc12b0..91ce740 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/DependenciesToModuleDescriptorConverter.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/DependenciesToModuleDescriptorConverter.java
@@ -20,9 +20,6 @@ import org.gradle.api.artifacts.Configuration;
import java.util.Collection;
-/**
- * @author Hans Dockter
- */
public interface DependenciesToModuleDescriptorConverter {
void addDependencyDescriptors(DefaultModuleDescriptor moduleDescriptor, Collection<? extends Configuration> configurations);
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/DependencyDescriptorFactory.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/DependencyDescriptorFactory.java
index c5dbf33..5073472 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/DependencyDescriptorFactory.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/DependencyDescriptorFactory.java
@@ -18,9 +18,6 @@ package org.gradle.api.internal.artifacts.ivyservice.moduleconverter.dependencie
import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor;
import org.gradle.api.artifacts.ModuleDependency;
-/**
- * @author Hans Dockter
- */
public interface DependencyDescriptorFactory {
void addDependencyDescriptor(String configuration, DefaultModuleDescriptor moduleDescriptor, ModuleDependency dependency);
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/ExternalModuleIvyDependencyDescriptorFactory.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/ExternalModuleIvyDependencyDescriptorFactory.java
index f885084..0cffb8b 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/ExternalModuleIvyDependencyDescriptorFactory.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/ExternalModuleIvyDependencyDescriptorFactory.java
@@ -22,9 +22,6 @@ import org.gradle.api.artifacts.ModuleDependency;
import org.gradle.api.internal.artifacts.ivyservice.IvyUtil;
import org.gradle.api.internal.artifacts.ivyservice.moduleconverter.ExcludeRuleConverter;
-/**
- * @author Hans Dockter
-*/
public class ExternalModuleIvyDependencyDescriptorFactory extends AbstractIvyDependencyDescriptorFactory {
public ExternalModuleIvyDependencyDescriptorFactory(ExcludeRuleConverter excludeRuleConverter) {
super(excludeRuleConverter);
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/ModuleDescriptorFactoryForClientModule.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/ModuleDescriptorFactoryForClientModule.java
index 760cf15..0770a7e 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/ModuleDescriptorFactoryForClientModule.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/ModuleDescriptorFactoryForClientModule.java
@@ -21,9 +21,6 @@ import org.gradle.api.artifacts.ModuleDependency;
import java.util.Set;
-/**
- * @author Hans Dockter
- */
public interface ModuleDescriptorFactoryForClientModule {
ModuleDescriptor createModuleDescriptor(ModuleRevisionId moduleRevisionId, Set<ModuleDependency> dependencies);
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/ProjectIvyDependencyDescriptorFactory.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/ProjectIvyDependencyDescriptorFactory.java
index 33e755b..fb16663 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/ProjectIvyDependencyDescriptorFactory.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/ProjectIvyDependencyDescriptorFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2009 the original author or authors.
+ * Copyright 2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,21 +20,20 @@ import org.apache.ivy.core.module.id.ModuleRevisionId;
import org.gradle.api.artifacts.Module;
import org.gradle.api.artifacts.ModuleDependency;
import org.gradle.api.artifacts.ProjectDependency;
+import org.gradle.api.internal.artifacts.dependencies.ProjectDependencyInternal;
import org.gradle.api.internal.artifacts.ivyservice.IvyUtil;
import org.gradle.api.internal.artifacts.ivyservice.moduleconverter.ExcludeRuleConverter;
import org.gradle.api.internal.project.ProjectInternal;
-/**
- * @author Hans Dockter
- */
public class ProjectIvyDependencyDescriptorFactory extends AbstractIvyDependencyDescriptorFactory {
public ProjectIvyDependencyDescriptorFactory(ExcludeRuleConverter excludeRuleConverter) {
super(excludeRuleConverter);
}
public EnhancedDependencyDescriptor createDependencyDescriptor(String configuration, ModuleDependency dependency, ModuleDescriptor parent) {
+ ProjectDependencyInternal projectDependency = (ProjectDependencyInternal) dependency;
+ projectDependency.beforeResolved();
ModuleRevisionId moduleRevisionId = createModuleRevisionId(dependency);
- ProjectDependency projectDependency = (ProjectDependency) dependency;
ProjectDependencyDescriptor dependencyDescriptor = new ProjectDependencyDescriptor(projectDependency, parent, moduleRevisionId, false, false, dependency.isTransitive());
addExcludesArtifactsAndDependencies(configuration, dependency, dependencyDescriptor);
return dependencyDescriptor;
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/projectmodule/DefaultProjectModuleRegistry.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/projectmodule/DefaultProjectModuleRegistry.java
index 0b6b02c..c98b93a 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/projectmodule/DefaultProjectModuleRegistry.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/projectmodule/DefaultProjectModuleRegistry.java
@@ -15,15 +15,11 @@
*/
package org.gradle.api.internal.artifacts.ivyservice.projectmodule;
-import org.apache.ivy.core.module.descriptor.Artifact;
-import org.apache.ivy.core.module.descriptor.DependencyArtifactDescriptor;
-import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
import org.gradle.api.artifacts.Module;
-import org.gradle.api.internal.artifacts.ivyservice.DefaultIvyDependencyPublisher;
+import org.gradle.api.internal.artifacts.ModuleVersionPublishMetaData;
import org.gradle.api.internal.artifacts.ivyservice.ModuleDescriptorConverter;
import org.gradle.api.internal.artifacts.ivyservice.moduleconverter.dependencies.ProjectDependencyDescriptor;
import org.gradle.api.internal.project.ProjectInternal;
-import org.gradle.util.ReflectionUtil;
public class DefaultProjectModuleRegistry implements ProjectModuleRegistry {
private final ModuleDescriptorConverter moduleDescriptorConverter;
@@ -32,22 +28,9 @@ public class DefaultProjectModuleRegistry implements ProjectModuleRegistry {
this.moduleDescriptorConverter = moduleDescriptorConverter;
}
- public ModuleDescriptor findProject(ProjectDependencyDescriptor descriptor) {
+ public ModuleVersionPublishMetaData findProject(ProjectDependencyDescriptor descriptor) {
ProjectInternal project = descriptor.getTargetProject();
Module projectModule = project.getModule();
- ModuleDescriptor projectDescriptor = moduleDescriptorConverter.convert(project.getConfigurations(), projectModule);
-
- for (DependencyArtifactDescriptor artifactDescriptor : descriptor.getAllDependencyArtifacts()) {
- for (Artifact artifact : projectDescriptor.getAllArtifacts()) {
- if (artifact.getName().equals(artifactDescriptor.getName()) && artifact.getExt().equals(
- artifactDescriptor.getExt())) {
- String path = artifact.getExtraAttribute(DefaultIvyDependencyPublisher.FILE_ABSOLUTE_PATH_EXTRA_ATTRIBUTE);
- ReflectionUtil.invoke(artifactDescriptor, "setExtraAttribute",
- new Object[]{DefaultIvyDependencyPublisher.FILE_ABSOLUTE_PATH_EXTRA_ATTRIBUTE, path});
- }
- }
- }
-
- return projectDescriptor;
+ return moduleDescriptorConverter.convert(project.getConfigurations(), projectModule);
}
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/projectmodule/ProjectDependencyResolver.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/projectmodule/ProjectDependencyResolver.java
index 54d67c2..d209d92 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/projectmodule/ProjectDependencyResolver.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/projectmodule/ProjectDependencyResolver.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2009 the original author or authors.
+ * Copyright 2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,46 +18,65 @@ package org.gradle.api.internal.artifacts.ivyservice.projectmodule;
import org.apache.ivy.core.module.descriptor.Artifact;
import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
-import org.apache.ivy.core.module.id.ModuleRevisionId;
-import org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier;
+import org.gradle.api.artifacts.Configuration;
+import org.gradle.api.artifacts.Module;
+import org.gradle.api.artifacts.ModuleVersionIdentifier;
+import org.gradle.api.internal.artifacts.DefaultArtifactIdentifier;
+import org.gradle.api.internal.artifacts.ModuleVersionPublishMetaData;
import org.gradle.api.internal.artifacts.ivyservice.*;
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.DependencyMetaData;
import org.gradle.api.internal.artifacts.ivyservice.moduleconverter.dependencies.ProjectDependencyDescriptor;
-import org.gradle.initialization.ProjectAccessListener;
import java.io.File;
+import java.util.Map;
+import java.util.Set;
-public class ProjectDependencyResolver implements DependencyToModuleResolver {
+public class ProjectDependencyResolver implements DependencyToModuleVersionResolver, ModuleToModuleVersionResolver {
private final ProjectModuleRegistry projectModuleRegistry;
- private final DependencyToModuleResolver resolver;
- private final ProjectArtifactResolver artifactResolver;
- private final ProjectAccessListener projectAccessListener;
+ private final DependencyToModuleVersionResolver resolver;
+ private final ModuleDescriptorConverter moduleDescriptorConverter;
- public ProjectDependencyResolver(ProjectModuleRegistry projectModuleRegistry, DependencyToModuleResolver resolver, ProjectAccessListener projectAccessListener) {
+ public ProjectDependencyResolver(ProjectModuleRegistry projectModuleRegistry, DependencyToModuleVersionResolver resolver, ModuleDescriptorConverter moduleDescriptorConverter) {
this.projectModuleRegistry = projectModuleRegistry;
this.resolver = resolver;
- this.projectAccessListener = projectAccessListener;
- artifactResolver = new ProjectArtifactResolver();
+ this.moduleDescriptorConverter = moduleDescriptorConverter;
}
public void resolve(DependencyMetaData dependency, BuildableModuleVersionResolveResult result) {
DependencyDescriptor descriptor = dependency.getDescriptor();
if (descriptor instanceof ProjectDependencyDescriptor) {
ProjectDependencyDescriptor desc = (ProjectDependencyDescriptor) descriptor;
- projectAccessListener.beforeResolvingProjectDependency(desc.getTargetProject());
- ModuleDescriptor moduleDescriptor = projectModuleRegistry.findProject(desc);
- final ModuleRevisionId moduleRevisionId = moduleDescriptor.getModuleRevisionId();
- final DefaultModuleVersionIdentifier moduleVersionIdentifier = new DefaultModuleVersionIdentifier(moduleRevisionId.getOrganisation(), moduleRevisionId.getName(), moduleRevisionId.getRevision());
- result.resolved(moduleVersionIdentifier, moduleDescriptor, artifactResolver);
+ ModuleVersionPublishMetaData publishMetaData = projectModuleRegistry.findProject(desc);
+ ModuleDescriptor moduleDescriptor = publishMetaData.getModuleDescriptor();
+ ModuleVersionIdentifier moduleVersionIdentifier = publishMetaData.getId();
+ result.resolved(moduleVersionIdentifier, moduleDescriptor, new ProjectArtifactResolver(publishMetaData));
} else {
resolver.resolve(dependency, result);
}
}
+ public void resolve(Module module, Set<? extends Configuration> configurations, BuildableModuleVersionResolveResult result) {
+ ModuleVersionPublishMetaData publishMetaData = moduleDescriptorConverter.convert(configurations, module);
+ ModuleDescriptor moduleDescriptor = publishMetaData.getModuleDescriptor();
+ ModuleVersionIdentifier moduleVersionIdentifier = publishMetaData.getId();
+ result.resolved(moduleVersionIdentifier, moduleDescriptor, new ProjectArtifactResolver(publishMetaData));
+ }
+
private static class ProjectArtifactResolver implements ArtifactResolver {
+ private final ModuleVersionPublishMetaData publishMetaData;
+
+ public ProjectArtifactResolver(ModuleVersionPublishMetaData publishMetaData) {
+ this.publishMetaData = publishMetaData;
+ }
+
public void resolve(Artifact artifact, BuildableArtifactResolveResult result) {
- String path = artifact.getExtraAttribute(DefaultIvyDependencyPublisher.FILE_ABSOLUTE_PATH_EXTRA_ATTRIBUTE);
- result.resolved(new File(path));
+ for (Map.Entry<Artifact, File> entry : publishMetaData.getArtifacts().entrySet()) {
+ if (entry.getKey().getId().equals(artifact.getId())) {
+ result.resolved(entry.getValue());
+ return;
+ }
+ }
+ result.notFound(new DefaultArtifactIdentifier(artifact));
}
}
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/projectmodule/ProjectModuleRegistry.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/projectmodule/ProjectModuleRegistry.java
index 6ffc502..f85a1c7 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/projectmodule/ProjectModuleRegistry.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/projectmodule/ProjectModuleRegistry.java
@@ -15,12 +15,12 @@
*/
package org.gradle.api.internal.artifacts.ivyservice.projectmodule;
-import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
+import org.gradle.api.internal.artifacts.ModuleVersionPublishMetaData;
import org.gradle.api.internal.artifacts.ivyservice.moduleconverter.dependencies.ProjectDependencyDescriptor;
/**
* TODO - this probably should lookup a project by id, much like ClientModuleRegistry. Then, there would be no dependency on ivy DependencyDescriptor.
*/
public interface ProjectModuleRegistry {
- ModuleDescriptor findProject(ProjectDependencyDescriptor descriptor);
+ ModuleVersionPublishMetaData findProject(ProjectDependencyDescriptor descriptor);
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolutionstrategy/DefaultResolutionStrategy.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolutionstrategy/DefaultResolutionStrategy.java
index 740b51a..c9f5ef7 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolutionstrategy/DefaultResolutionStrategy.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolutionstrategy/DefaultResolutionStrategy.java
@@ -36,9 +36,6 @@ import java.util.concurrent.TimeUnit;
import static org.gradle.util.GUtil.flattenElements;
-/**
- * by Szczepan Faber, created at: 10/7/11
- */
public class DefaultResolutionStrategy implements ResolutionStrategyInternal {
private Set<ModuleVersionSelector> forcedModules = new LinkedHashSet<ModuleVersionSelector>();
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolutionstrategy/LatestConflictResolution.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolutionstrategy/LatestConflictResolution.java
index a8022db..860b490 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolutionstrategy/LatestConflictResolution.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolutionstrategy/LatestConflictResolution.java
@@ -20,8 +20,6 @@ import org.gradle.api.artifacts.ConflictResolution;
/**
* Latest resolution strategy
- * <p>
- * by Szczepan Faber, created at: 10/5/11
*/
public class LatestConflictResolution implements ConflictResolution {
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolutionstrategy/ModuleForcingResolveRule.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolutionstrategy/ModuleForcingResolveRule.java
index 4992512..a227620 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolutionstrategy/ModuleForcingResolveRule.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolutionstrategy/ModuleForcingResolveRule.java
@@ -27,9 +27,6 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
-/**
-* by Szczepan Faber, created at: 11/29/12
-*/
public class ModuleForcingResolveRule implements Action<DependencyResolveDetailsInternal> {
private final Map<ModuleIdentifier, String> forcedModules;
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolutionstrategy/StrictConflictResolution.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolutionstrategy/StrictConflictResolution.java
index 4ee1533..3ec3377 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolutionstrategy/StrictConflictResolution.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolutionstrategy/StrictConflictResolution.java
@@ -20,8 +20,6 @@ import org.gradle.api.artifacts.ConflictResolution;
/**
* Strict type, allows configuring (forcing) certain dependency versions using dependency notation
- * <p>
- * by Szczepan Faber, created at: 10/5/11
*/
public class StrictConflictResolution implements ConflictResolution {
}
\ No newline at end of file
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/DefaultDependencyResolver.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/DefaultDependencyResolver.java
index e572e6b..852b2b9 100755
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/DefaultDependencyResolver.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/DefaultDependencyResolver.java
@@ -15,7 +15,10 @@
*/
package org.gradle.api.internal.artifacts.ivyservice.resolveengine;
+import org.apache.ivy.Ivy;
+import org.gradle.api.Transformer;
import org.gradle.api.artifacts.ResolveException;
+import org.gradle.api.artifacts.result.ResolvedModuleVersionResult;
import org.gradle.api.internal.artifacts.ArtifactDependencyResolver;
import org.gradle.api.internal.artifacts.ResolverResults;
import org.gradle.api.internal.artifacts.configurations.ConfigurationInternal;
@@ -27,9 +30,15 @@ import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ResolveIvyFactory
import org.gradle.api.internal.artifacts.ivyservice.projectmodule.ProjectDependencyResolver;
import org.gradle.api.internal.artifacts.ivyservice.projectmodule.ProjectModuleRegistry;
import org.gradle.api.internal.artifacts.ivyservice.resolutionstrategy.StrictConflictResolution;
-import org.gradle.api.internal.artifacts.ivyservice.resolveengine.result.ResolutionResultBuilder;
+import org.gradle.api.internal.artifacts.ivyservice.resolveengine.store.ResolutionResultsStoreFactory;
+import org.gradle.api.internal.artifacts.ivyservice.resolveengine.oldresult.DefaultResolvedConfigurationBuilder;
+import org.gradle.api.internal.artifacts.ivyservice.resolveengine.oldresult.TransientConfigurationResults;
+import org.gradle.api.internal.artifacts.ivyservice.resolveengine.oldresult.TransientResultsStore;
+import org.gradle.api.internal.artifacts.ivyservice.resolveengine.result.ResolvedConfigurationListener;
+import org.gradle.api.internal.artifacts.ivyservice.resolveengine.result.StreamingResolutionResultBuilder;
import org.gradle.api.internal.artifacts.repositories.ResolutionAwareRepository;
-import org.gradle.initialization.ProjectAccessListener;
+import org.gradle.api.internal.cache.BinaryStore;
+import org.gradle.api.internal.cache.Store;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -41,41 +50,58 @@ public class DefaultDependencyResolver implements ArtifactDependencyResolver {
private final ResolvedArtifactFactory resolvedArtifactFactory;
private final ResolveIvyFactory ivyFactory;
private final ProjectModuleRegistry projectModuleRegistry;
- private final ProjectAccessListener projectAccessListener;
private final CacheLockingManager cacheLockingManager;
+ private final IvyContextManager ivyContextManager;
+ private final ResolutionResultsStoreFactory storeFactory;
public DefaultDependencyResolver(ResolveIvyFactory ivyFactory, ModuleDescriptorConverter moduleDescriptorConverter, ResolvedArtifactFactory resolvedArtifactFactory,
- ProjectModuleRegistry projectModuleRegistry, ProjectAccessListener projectAccessListener, CacheLockingManager cacheLockingManager) {
+ ProjectModuleRegistry projectModuleRegistry, CacheLockingManager cacheLockingManager, IvyContextManager ivyContextManager,
+ ResolutionResultsStoreFactory storeFactory) {
this.ivyFactory = ivyFactory;
this.moduleDescriptorConverter = moduleDescriptorConverter;
this.resolvedArtifactFactory = resolvedArtifactFactory;
this.projectModuleRegistry = projectModuleRegistry;
- this.projectAccessListener = projectAccessListener;
this.cacheLockingManager = cacheLockingManager;
+ this.ivyContextManager = ivyContextManager;
+ this.storeFactory = storeFactory;
}
- public ResolverResults resolve(ConfigurationInternal configuration, List<? extends ResolutionAwareRepository> repositories) throws ResolveException {
+ public ResolverResults resolve(final ConfigurationInternal configuration, final List<? extends ResolutionAwareRepository> repositories) throws ResolveException {
LOGGER.debug("Resolving {}", configuration);
+ return ivyContextManager.withIvy(new Transformer<ResolverResults, Ivy>() {
+ public ResolverResults transform(Ivy ivy) {
+ IvyAdapter ivyAdapter = ivyFactory.create(configuration, repositories);
- IvyAdapter ivyAdapter = ivyFactory.create(configuration, repositories);
+ DependencyToModuleVersionResolver dependencyResolver = ivyAdapter.getDependencyToModuleResolver();
+ dependencyResolver = new ClientModuleResolver(dependencyResolver);
+ ProjectDependencyResolver projectDependencyResolver = new ProjectDependencyResolver(projectModuleRegistry, dependencyResolver, moduleDescriptorConverter);
+ dependencyResolver = projectDependencyResolver;
+ DependencyToModuleVersionIdResolver idResolver = new LazyDependencyToModuleResolver(dependencyResolver, ivyAdapter.getVersionMatcher());
+ idResolver = new VersionForcingDependencyToModuleResolver(idResolver, configuration.getResolutionStrategy().getDependencyResolveRule());
- DependencyToModuleResolver dependencyResolver = ivyAdapter.getDependencyToModuleResolver();
- dependencyResolver = new ClientModuleResolver(dependencyResolver);
- dependencyResolver = new ProjectDependencyResolver(projectModuleRegistry, dependencyResolver, projectAccessListener);
- DependencyToModuleVersionIdResolver idResolver = new LazyDependencyToModuleResolver(dependencyResolver, ivyAdapter.getResolveData().getSettings().getVersionMatcher());
- idResolver = new VersionForcingDependencyToModuleResolver(idResolver, configuration.getResolutionStrategy().getDependencyResolveRule());
+ ModuleConflictResolver conflictResolver;
+ if (configuration.getResolutionStrategy().getConflictResolution() instanceof StrictConflictResolution) {
+ conflictResolver = new StrictConflictResolver();
+ } else {
+ conflictResolver = new LatestModuleConflictResolver(ivyAdapter.getLatestStrategy());
+ }
+ conflictResolver = new VersionSelectionReasonResolver(conflictResolver);
- ModuleConflictResolver conflictResolver;
- if (configuration.getResolutionStrategy().getConflictResolution() instanceof StrictConflictResolution) {
- conflictResolver = new StrictConflictResolver();
- } else {
- conflictResolver = new LatestModuleConflictResolver();
- }
- ModuleConflictResolver actualResolver = new VersionSelectionReasonResolver(conflictResolver);
+ DependencyGraphBuilder builder = new DependencyGraphBuilder(idResolver, projectDependencyResolver, conflictResolver, new DefaultDependencyToConfigurationResolver());
- DependencyGraphBuilder builder = new DependencyGraphBuilder(moduleDescriptorConverter, resolvedArtifactFactory, idResolver, actualResolver);
- ResolutionResultBuilder resultBuilder = new ResolutionResultBuilder();
- DefaultLenientConfiguration result = builder.resolve(configuration, ivyAdapter.getResolveData(), resultBuilder);
- return new ResolverResults(new DefaultResolvedConfiguration(result, cacheLockingManager), resultBuilder.getResult());
+ BinaryStore newModelStore = storeFactory.createBinaryStore("new-model");
+ Store<ResolvedModuleVersionResult> newModelCache = storeFactory.createNewModelCache(configuration);
+ ResolvedConfigurationListener newModelBuilder = new StreamingResolutionResultBuilder(newModelStore, newModelCache);
+
+ BinaryStore oldModelStore = storeFactory.createBinaryStore("old-model");
+ Store<TransientConfigurationResults> oldModelCache = storeFactory.createOldModelCache(configuration);
+ TransientResultsStore oldModelResults = new TransientResultsStore(oldModelStore, oldModelCache);
+ DefaultResolvedConfigurationBuilder oldModelBuilder = new DefaultResolvedConfigurationBuilder(resolvedArtifactFactory, oldModelResults);
+
+ builder.resolve(configuration, newModelBuilder, oldModelBuilder);
+ DefaultLenientConfiguration result = new DefaultLenientConfiguration(configuration, oldModelBuilder, cacheLockingManager);
+ return new ResolverResults(new DefaultResolvedConfiguration(result), newModelBuilder.complete());
+ }
+ });
}
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/DefaultDependencyToConfigurationResolver.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/DefaultDependencyToConfigurationResolver.java
new file mode 100644
index 0000000..9ab07c3
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/DefaultDependencyToConfigurationResolver.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.resolveengine;
+
+import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
+import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ConfigurationMetaData;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.DependencyMetaData;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ModuleVersionMetaData;
+
+import java.util.*;
+
+public class DefaultDependencyToConfigurationResolver implements DependencyToConfigurationResolver {
+ // TODO - don't pass in 'from' configuration - the dependency should have whatever context it needs
+ public Set<ConfigurationMetaData> resolveTargetConfigurations(DependencyMetaData dependencyMetaData, ConfigurationMetaData fromConfiguration, ModuleVersionMetaData targetModuleVersion) {
+ // TODO - resolve directly to config meta data
+ ModuleDescriptor targetDescriptor = targetModuleVersion.getDescriptor();
+ DependencyDescriptor dependencyDescriptor = dependencyMetaData.getDescriptor();
+ Set<String> targetConfigurationNames = new LinkedHashSet<String>();
+ for (String config : dependencyDescriptor.getModuleConfigurations()) {
+ if (config.equals("*") || config.equals("%")) {
+ collectTargetConfiguration(dependencyDescriptor, fromConfiguration, fromConfiguration.getName(), targetDescriptor, targetConfigurationNames);
+ } else if (fromConfiguration.getHierarchy().contains(config)) {
+ collectTargetConfiguration(dependencyDescriptor, fromConfiguration, config, targetDescriptor, targetConfigurationNames);
+ }
+ }
+
+ Set<ConfigurationMetaData> targets = new LinkedHashSet<ConfigurationMetaData>();
+ for (String targetConfigurationName : targetConfigurationNames) {
+ // TODO - move this down below
+ if (targetDescriptor.getConfiguration(targetConfigurationName) == null) {
+ throw new RuntimeException(String.format("Module version %s, configuration '%s' declares a dependency on configuration '%s' which is not declared in the module descriptor for %s",
+ fromConfiguration.getModuleVersion().getId(), fromConfiguration.getName(),
+ targetConfigurationName, targetModuleVersion.getId()));
+ }
+ ConfigurationMetaData targetConfiguration = targetModuleVersion.getConfiguration(targetConfigurationName);
+ targets.add(targetConfiguration);
+ }
+ return targets;
+ }
+
+ private void collectTargetConfiguration(DependencyDescriptor dependencyDescriptor, ConfigurationMetaData fromConfiguration, String mappingRhs, ModuleDescriptor targetModule, Collection<String> targetConfigs) {
+ String[] dependencyConfigurations = dependencyDescriptor.getDependencyConfigurations(mappingRhs, fromConfiguration.getName());
+ for (String target : dependencyConfigurations) {
+ String candidate = target;
+ int startFallback = candidate.indexOf('(');
+ if (startFallback >= 0) {
+ if (candidate.charAt(candidate.length() - 1) == ')') {
+ String preferred = candidate.substring(0, startFallback);
+ if (targetModule.getConfiguration(preferred) != null) {
+ targetConfigs.add(preferred);
+ continue;
+ }
+ candidate = candidate.substring(startFallback + 1, candidate.length() - 1);
+ }
+ }
+ if (candidate.equals("*")) {
+ Collections.addAll(targetConfigs, targetModule.getPublicConfigurationsNames());
+ continue;
+ }
+ targetConfigs.add(candidate);
+ }
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/DependencyGraphBuilder.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/DependencyGraphBuilder.java
index f01fe53..b951f61 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/DependencyGraphBuilder.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/DependencyGraphBuilder.java
@@ -15,26 +15,23 @@
*/
package org.gradle.api.internal.artifacts.ivyservice.resolveengine;
-import org.apache.ivy.core.module.descriptor.*;
+import org.apache.ivy.core.module.descriptor.Artifact;
+import org.apache.ivy.core.module.descriptor.DefaultArtifact;
+import org.apache.ivy.core.module.descriptor.DependencyArtifactDescriptor;
+import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
import org.apache.ivy.core.module.id.ModuleId;
import org.apache.ivy.core.module.id.ModuleRevisionId;
-import org.apache.ivy.core.resolve.IvyNode;
-import org.apache.ivy.core.resolve.ResolveData;
-import org.gradle.api.artifacts.ModuleVersionIdentifier;
-import org.gradle.api.artifacts.ModuleVersionSelector;
-import org.gradle.api.artifacts.ResolveException;
-import org.gradle.api.artifacts.ResolvedArtifact;
+import org.gradle.api.artifacts.*;
import org.gradle.api.artifacts.result.ModuleVersionSelectionReason;
-import org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier;
-import org.gradle.api.internal.artifacts.DefaultResolvedDependency;
+import org.gradle.api.internal.artifacts.DefaultModuleIdentifier;
import org.gradle.api.internal.artifacts.ResolvedConfigurationIdentifier;
import org.gradle.api.internal.artifacts.configurations.ConfigurationInternal;
import org.gradle.api.internal.artifacts.ivyservice.*;
-import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.BuildableModuleVersionMetaData;
-import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.DefaultBuildableModuleVersionMetaData;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ConfigurationMetaData;
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.DependencyMetaData;
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ModuleVersionMetaData;
import org.gradle.api.internal.artifacts.ivyservice.moduleconverter.dependencies.EnhancedDependencyDescriptor;
+import org.gradle.api.internal.artifacts.ivyservice.resolveengine.oldresult.ResolvedConfigurationBuilder;
import org.gradle.api.internal.artifacts.ivyservice.resolveengine.result.InternalDependencyResult;
import org.gradle.api.internal.artifacts.ivyservice.resolveengine.result.ModuleVersionSelection;
import org.gradle.api.internal.artifacts.ivyservice.resolveengine.result.ResolvedConfigurationListener;
@@ -44,41 +41,40 @@ import org.slf4j.LoggerFactory;
import java.util.*;
-import static org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier.newId;
-
public class DependencyGraphBuilder {
private static final Logger LOGGER = LoggerFactory.getLogger(DependencyGraphBuilder.class);
- private final ModuleDescriptorConverter moduleDescriptorConverter;
- private final ResolvedArtifactFactory resolvedArtifactFactory;
private final DependencyToModuleVersionIdResolver dependencyResolver;
+ private final DependencyToConfigurationResolver dependencyToConfigurationResolver;
private final InternalConflictResolver conflictResolver;
+ private final ModuleToModuleVersionResolver moduleResolver;
- public DependencyGraphBuilder(ModuleDescriptorConverter moduleDescriptorConverter, ResolvedArtifactFactory resolvedArtifactFactory, DependencyToModuleVersionIdResolver dependencyResolver, ModuleConflictResolver conflictResolver) {
- this.moduleDescriptorConverter = moduleDescriptorConverter;
- this.resolvedArtifactFactory = resolvedArtifactFactory;
+ public DependencyGraphBuilder(DependencyToModuleVersionIdResolver dependencyResolver,
+ ModuleToModuleVersionResolver moduleResolver,
+ ModuleConflictResolver conflictResolver,
+ DependencyToConfigurationResolver dependencyToConfigurationResolver) {
this.dependencyResolver = dependencyResolver;
+ this.moduleResolver = moduleResolver;
+ this.dependencyToConfigurationResolver = dependencyToConfigurationResolver;
this.conflictResolver = new InternalConflictResolver(conflictResolver);
}
- public DefaultLenientConfiguration resolve(ConfigurationInternal configuration, ResolveData resolveData, ResolvedConfigurationListener listener) throws ResolveException {
- ModuleDescriptor rootModuleDescriptor = moduleDescriptorConverter.convert(configuration.getAll(), configuration.getModule());
- BuildableModuleVersionMetaData rootMetaData = new DefaultBuildableModuleVersionMetaData();
- rootMetaData.resolved(rootModuleDescriptor, false, null);
+ public void resolve(ConfigurationInternal configuration,
+ ResolvedConfigurationListener listener,
+ ResolvedConfigurationBuilder configurationBuilder) throws ResolveException {
+ DefaultBuildableModuleVersionResolveResult rootModule = new DefaultBuildableModuleVersionResolveResult();
+ moduleResolver.resolve(configuration.getModule(), configuration.getAll(), rootModule);
- ResolveState resolveState = new ResolveState(rootMetaData, configuration.getName(), dependencyResolver, resolveData);
+ ResolveState resolveState = new ResolveState(rootModule, configuration.getName(), dependencyResolver, dependencyToConfigurationResolver, configurationBuilder);
traverseGraph(resolveState);
- DefaultLenientConfiguration result = new DefaultLenientConfiguration(configuration, resolveState.root.getResult());
- assembleResult(resolveState, result, listener);
-
- return result;
+ assembleResult(resolveState, configurationBuilder, listener);
}
/**
* Traverses the dependency graph, resolving conflicts and building the paths from the root configuration.
*/
private void traverseGraph(ResolveState resolveState) {
- Set<ModuleId> conflicts = new LinkedHashSet<ModuleId>();
+ Set<ModuleIdentifier> conflicts = new LinkedHashSet<ModuleIdentifier>();
resolveState.onMoreSelected(resolveState.root);
@@ -96,20 +92,19 @@ public class DependencyGraphBuilder {
LOGGER.debug("Visiting dependency {}", dependency);
// Resolve dependency to a particular revision
- dependency.resolveModuleRevisionId();
- DefaultModuleRevisionResolveState moduleRevision = dependency.getTargetModuleRevision();
+ ModuleVersionResolveState moduleRevision = dependency.resolveModuleRevisionId();
if (moduleRevision == null) {
// Failed to resolve.
continue;
}
- ModuleId moduleId= moduleRevision.id.getModuleId();
+ ModuleIdentifier moduleId = moduleRevision.id.getModule();
// Check for a new conflict
if (moduleRevision.state == ModuleState.New) {
ModuleResolveState module = resolveState.getModule(moduleId);
// A new module revision. Check for conflict
- Collection<DefaultModuleRevisionResolveState> versions = module.getVersions();
+ Collection<ModuleVersionResolveState> versions = module.getVersions();
if (versions.size() == 1) {
// First version of this module. Select it for now
LOGGER.debug("Selecting new module version {}", moduleRevision);
@@ -121,7 +116,7 @@ public class DependencyGraphBuilder {
// Deselect the currently selected version, and remove all outgoing edges from the version
// This will propagate through the graph and prune configurations that are no longer required
- DefaultModuleRevisionResolveState previouslySelected = module.clearSelection();
+ ModuleVersionResolveState previouslySelected = module.clearSelection();
if (previouslySelected != null) {
for (ConfigurationNode configuration : previouslySelected.configurations) {
configuration.removeOutgoingEdges();
@@ -134,10 +129,10 @@ public class DependencyGraphBuilder {
}
} else {
// We have some batched up conflicts. Resolve the first, and continue traversing the graph
- ModuleId moduleId = conflicts.iterator().next();
+ ModuleIdentifier moduleId = conflicts.iterator().next();
conflicts.remove(moduleId);
ModuleResolveState module = resolveState.getModule(moduleId);
- DefaultModuleRevisionResolveState selected = conflictResolver.select(module.getVersions(), resolveState.root.moduleRevision);
+ ModuleVersionResolveState selected = conflictResolver.select(module.getVersions(), resolveState.root.moduleRevision);
LOGGER.debug("Selected {} from conflicting modules {}.", selected, module.getVersions());
// Restart each configuration. For the evicted configuration, this means moving incoming dependencies across to the
@@ -155,19 +150,24 @@ public class DependencyGraphBuilder {
ModuleVersionIdentifier root = resolveState.root.toId();
listener.start(root);
+ // Visit the nodes
for (ConfigurationNode resolvedConfiguration : resolveState.getConfigurationNodes()) {
if (resolvedConfiguration.isSelected()) {
- resolvedConfiguration.attachToParents(resolvedArtifactFactory, result);
+ resolvedConfiguration.validate();
+ result.newResolvedDependency(resolvedConfiguration.getResult());
resolvedConfiguration.collectFailures(failureState);
listener.resolvedModuleVersion(resolvedConfiguration.moduleRevision);
}
}
+ // Visit the edges
for (ConfigurationNode resolvedConfiguration : resolveState.getConfigurationNodes()) {
if (resolvedConfiguration.isSelected()) {
+ resolvedConfiguration.attachToParents(result);
listener.resolvedConfiguration(resolvedConfiguration.toId(), resolvedConfiguration.outgoingEdges);
}
}
failureState.attachFailures(result);
+ result.done(resolveState.root.getResult());
}
private static class FailureState {
@@ -180,29 +180,29 @@ public class DependencyGraphBuilder {
public void attachFailures(ResolvedConfigurationBuilder result) {
for (Map.Entry<ModuleVersionSelector, BrokenDependency> entry : failuresByRevisionId.entrySet()) {
- Collection<List<ModuleRevisionId>> paths = calculatePaths(entry.getValue());
+ Collection<List<ModuleVersionIdentifier>> paths = calculatePaths(entry.getValue());
result.addUnresolvedDependency(new DefaultUnresolvedDependency(entry.getKey(), entry.getValue().failure.withIncomingPaths(paths)));
}
}
- private Collection<List<ModuleRevisionId>> calculatePaths(BrokenDependency brokenDependency) {
+ private Collection<List<ModuleVersionIdentifier>> calculatePaths(BrokenDependency brokenDependency) {
// Include the shortest path from each version that has a direct dependency on the broken dependency, back to the root
- Map<DefaultModuleRevisionResolveState, List<ModuleRevisionId>> shortestPaths = new LinkedHashMap<DefaultModuleRevisionResolveState, List<ModuleRevisionId>>();
- List<ModuleRevisionId> rootPath = new ArrayList<ModuleRevisionId>();
+ Map<ModuleVersionResolveState, List<ModuleVersionIdentifier>> shortestPaths = new LinkedHashMap<ModuleVersionResolveState, List<ModuleVersionIdentifier>>();
+ List<ModuleVersionIdentifier> rootPath = new ArrayList<ModuleVersionIdentifier>();
rootPath.add(root.moduleRevision.id);
shortestPaths.put(root.moduleRevision, rootPath);
- Set<DefaultModuleRevisionResolveState> directDependees = new LinkedHashSet<DefaultModuleRevisionResolveState>();
+ Set<ModuleVersionResolveState> directDependees = new LinkedHashSet<ModuleVersionResolveState>();
for (ConfigurationNode node : brokenDependency.requiredBy) {
directDependees.add(node.moduleRevision);
}
- Set<DefaultModuleRevisionResolveState> seen = new HashSet<DefaultModuleRevisionResolveState>();
- LinkedList<DefaultModuleRevisionResolveState> queue = new LinkedList<DefaultModuleRevisionResolveState>();
+ Set<ModuleVersionResolveState> seen = new HashSet<ModuleVersionResolveState>();
+ LinkedList<ModuleVersionResolveState> queue = new LinkedList<ModuleVersionResolveState>();
queue.addAll(directDependees);
while (!queue.isEmpty()) {
- DefaultModuleRevisionResolveState version = queue.getFirst();
+ ModuleVersionResolveState version = queue.getFirst();
if (version == root.moduleRevision) {
queue.removeFirst();
} else if (seen.add(version)) {
@@ -213,10 +213,10 @@ public class DependencyGraphBuilder {
}
} else {
queue.remove();
- List<ModuleRevisionId> shortest = null;
+ List<ModuleVersionIdentifier> shortest = null;
for (ConfigurationNode configuration : version.configurations) {
for (DependencyEdge dependencyEdge : configuration.incomingEdges) {
- List<ModuleRevisionId> candidate = shortestPaths.get(dependencyEdge.from.moduleRevision);
+ List<ModuleVersionIdentifier> candidate = shortestPaths.get(dependencyEdge.from.moduleRevision);
if (candidate == null) {
continue;
}
@@ -230,16 +230,16 @@ public class DependencyGraphBuilder {
if (shortest == null) {
continue;
}
- List<ModuleRevisionId> path = new ArrayList<ModuleRevisionId>();
+ List<ModuleVersionIdentifier> path = new ArrayList<ModuleVersionIdentifier>();
path.addAll(shortest);
path.add(version.id);
shortestPaths.put(version, path);
}
}
- List<List<ModuleRevisionId>> paths = new ArrayList<List<ModuleRevisionId>>();
- for (DefaultModuleRevisionResolveState version : directDependees) {
- List<ModuleRevisionId> path = shortestPaths.get(version);
+ List<List<ModuleVersionIdentifier>> paths = new ArrayList<List<ModuleVersionIdentifier>>();
+ for (ModuleVersionResolveState version : directDependees) {
+ List<ModuleVersionIdentifier> path = shortestPaths.get(version);
paths.add(path);
}
return paths;
@@ -264,45 +264,46 @@ public class DependencyGraphBuilder {
}
}
+ /**
+ * Represents the edges in the dependency graph.
+ */
private static class DependencyEdge implements InternalDependencyResult {
private final ConfigurationNode from;
private final DependencyDescriptor dependencyDescriptor;
private final DependencyMetaData dependencyMetaData;
- private final Set<String> targetConfigurationRules;
private final ResolveState resolveState;
private final ModuleVersionSpec selectorSpec;
private final Set<ConfigurationNode> targetConfigurations = new LinkedHashSet<ConfigurationNode>();
- private ModuleVersionSelectorResolveState selector;
- private DefaultModuleRevisionResolveState targetModuleRevision;
+ private final ModuleVersionSelectorResolveState selector;
+ private ModuleVersionResolveState targetModuleRevision;
- public DependencyEdge(ConfigurationNode from, DependencyMetaData dependencyMetaData, Set<String> targetConfigurationRules, ModuleVersionSpec selectorSpec, ResolveState resolveState) {
+ public DependencyEdge(ConfigurationNode from, DependencyMetaData dependencyMetaData, ModuleVersionSpec selectorSpec, ResolveState resolveState) {
this.from = from;
this.dependencyMetaData = dependencyMetaData;
this.dependencyDescriptor = dependencyMetaData.getDescriptor();
- this.targetConfigurationRules = targetConfigurationRules;
this.selectorSpec = selectorSpec;
this.resolveState = resolveState;
+ selector = resolveState.getSelector(dependencyMetaData);
}
@Override
public String toString() {
- return String.format("%s -> %s(%s)", from.toString(), dependencyMetaData.getRequested(), targetConfigurationRules);
- }
-
- public DefaultModuleRevisionResolveState getTargetModuleRevision() {
- return targetModuleRevision;
+ return String.format("%s -> %s(%s)", from.toString(), dependencyMetaData.getRequested(), dependencyDescriptor);
}
- public void resolveModuleRevisionId() {
+ /**
+ * @return The resolved module version
+ */
+ public ModuleVersionResolveState resolveModuleRevisionId() {
if (targetModuleRevision == null) {
- selector = resolveState.getSelector(dependencyMetaData, dependencyDescriptor.getDependencyRevisionId());
targetModuleRevision = selector.resolveModuleRevisionId();
- selector.module.addUnattachedDependency(this);
+ selector.getSelectedModule().addUnattachedDependency(this);
}
+ return targetModuleRevision;
}
public boolean isTransitive() {
- return from.isTransitive() && dependencyDescriptor.isTransitive();
+ return from.isTransitive() && dependencyMetaData.isTransitive();
}
public void attachToTargetConfigurations() {
@@ -314,7 +315,7 @@ public class DependencyGraphBuilder {
targetConfiguration.addIncomingEdge(this);
}
if (!targetConfigurations.isEmpty()) {
- selector.module.removeUnattachedDependency(this);
+ selector.getSelectedModule().removeUnattachedDependency(this);
}
}
@@ -323,10 +324,12 @@ public class DependencyGraphBuilder {
targetConfiguration.removeIncomingEdge(this);
}
targetConfigurations.clear();
+ if (targetModuleRevision != null) {
+ selector.getSelectedModule().removeUnattachedDependency(this);
+ }
}
- public void restart(DefaultModuleRevisionResolveState selected) {
- selector = selector.restart(selected);
+ public void restart(ModuleVersionResolveState selected) {
targetModuleRevision = selected;
attachToTargetConfigurations();
}
@@ -339,121 +342,102 @@ public class DependencyGraphBuilder {
return;
}
- ModuleDescriptor targetDescriptor = targetModuleVersion.getDescriptor();
- IvyNode node = new IvyNode(resolveState.resolveData, targetDescriptor);
- Set<String> targets = new LinkedHashSet<String>();
- for (String targetConfiguration : targetConfigurationRules) {
- Collections.addAll(targets, node.getRealConfs(targetConfiguration));
- }
-
- for (String targetConfigurationName : targets) {
- // TODO - this is the wrong spot for this check
- if (targetDescriptor.getConfiguration(targetConfigurationName) == null) {
- throw new RuntimeException(String.format("Module version group:%s, module:%s, version:%s, configuration:%s declares a dependency on configuration '%s' which is not declared in the module descriptor for group:%s, module:%s, version:%s",
- from.moduleRevision.id.getOrganisation(), from.moduleRevision.id.getName(), from.moduleRevision.id.getRevision(), from.configurationName,
- targetConfigurationName, targetModuleRevision.id.getOrganisation(), targetModuleRevision.id.getName(), targetModuleRevision.id.getRevision()));
- }
- ConfigurationNode targetConfiguration = resolveState.getConfigurationNode(targetModuleRevision, targetConfigurationName);
- targetConfigurations.add(targetConfiguration);
+ Set<ConfigurationMetaData> targetConfigurations = resolveState.dependencyToConfigurationResolver.resolveTargetConfigurations(dependencyMetaData, from.metaData, targetModuleVersion);
+ for (ConfigurationMetaData targetConfiguration : targetConfigurations) {
+ ConfigurationNode targetConfigurationNode = resolveState.getConfigurationNode(targetModuleRevision, targetConfiguration.getName());
+ this.targetConfigurations.add(targetConfigurationNode);
}
}
- private Set<ResolvedArtifact> getArtifacts(ConfigurationNode childConfiguration, ResolvedArtifactFactory resolvedArtifactFactory) {
- String[] targetConfigurations = from.heirarchy.toArray(new String[from.heirarchy.size()]);
+ private Set<ResolvedArtifact> getArtifacts(ConfigurationNode childConfiguration) {
+ String[] targetConfigurations = from.metaData.getHierarchy().toArray(new String[from.metaData.getHierarchy().size()]);
DependencyArtifactDescriptor[] dependencyArtifacts = dependencyDescriptor.getDependencyArtifacts(targetConfigurations);
if (dependencyArtifacts.length == 0) {
return Collections.emptySet();
}
Set<ResolvedArtifact> artifacts = new LinkedHashSet<ResolvedArtifact>();
for (DependencyArtifactDescriptor artifactDescriptor : dependencyArtifacts) {
- MDArtifact artifact = new MDArtifact(childConfiguration.descriptor, artifactDescriptor.getName(), artifactDescriptor.getType(), artifactDescriptor.getExt(), artifactDescriptor.getUrl(), artifactDescriptor.getQualifiedExtraAttributes());
- artifacts.add(resolvedArtifactFactory.create(childConfiguration.getResult(), artifact, selector.resolve().getArtifactResolver()));
+ ModuleRevisionId id = childConfiguration.moduleRevision.metaData.getDescriptor().getModuleRevisionId();
+ Artifact artifact = new DefaultArtifact(id, null, artifactDescriptor.getName(), artifactDescriptor.getType(), artifactDescriptor.getExt(), artifactDescriptor.getUrl(), artifactDescriptor.getQualifiedExtraAttributes());
+ artifacts.add(resolveState.builder.newArtifact(childConfiguration.getResult(), artifact, targetModuleRevision.resolve().getArtifactResolver()));
}
return artifacts;
}
- public void attachToParents(ConfigurationNode childConfiguration, ResolvedArtifactFactory artifactFactory, ResolvedConfigurationBuilder result) {
- DefaultResolvedDependency parent = from.getResult();
- DefaultResolvedDependency child = childConfiguration.getResult();
- parent.addChild(child);
-
- Set<ResolvedArtifact> artifacts = getArtifacts(childConfiguration, artifactFactory);
- if (!artifacts.isEmpty()) {
- child.addParentSpecificArtifacts(parent, artifacts);
- }
+ public void attachToParents(ConfigurationNode childConfiguration, ResolvedConfigurationBuilder result) {
+ ResolvedConfigurationIdentifier parent = from.getResult();
+ ResolvedConfigurationIdentifier child = childConfiguration.getResult();
+ result.addChild(parent, child);
+ Set<ResolvedArtifact> artifacts = getArtifacts(childConfiguration);
if (artifacts.isEmpty()) {
- child.addParentSpecificArtifacts(parent, childConfiguration.getArtifacts(artifactFactory));
- }
- for (ResolvedArtifact artifact : child.getParentArtifacts(parent)) {
- result.addArtifact(artifact);
+ artifacts = childConfiguration.getArtifacts();
}
+ //TODO SF merge with addChild
+ result.addParentSpecificArtifacts(child, parent, artifacts);
- if (parent == result.getRoot()) {
+ if (parent == resolveState.root.getResult()) {
EnhancedDependencyDescriptor enhancedDependencyDescriptor = (EnhancedDependencyDescriptor) dependencyDescriptor;
result.addFirstLevelDependency(enhancedDependencyDescriptor.getModuleDependency(), child);
}
}
public ModuleVersionSpec getSelector() {
- String[] configurations = from.heirarchy.toArray(new String[from.heirarchy.size()]);
+ String[] configurations = from.metaData.getHierarchy().toArray(new String[from.metaData.getHierarchy().size()]);
ModuleVersionSpec selector = ModuleVersionSpec.forExcludes(dependencyDescriptor.getExcludeRules(configurations));
return selector.intersect(selectorSpec);
}
- public boolean isFailed() {
- return selector != null && selector.failure != null;
- }
-
public ModuleVersionSelector getRequested() {
return dependencyMetaData.getRequested();
}
public ModuleVersionResolveException getFailure() {
- //see also getSelected(). For evicted targetModuleRevisions, we need to reach out to the failure of selected module
- //covered in VersionConflictResolutionIntegrationTest
- return selector.failure != null ? selector.failure : getSelected().resolver.failure;
+ return selector.getFailure();
}
- public DefaultModuleRevisionResolveState getSelected() {
- //we cannot use the targetModuleRevision field because it may have been evicted
- //covered in VersionConflictResolutionIntegrationTest
- return selector.module.selected;
+ public ModuleVersionResolveState getSelected() {
+ return selector.getSelected();
}
public ModuleVersionSelectionReason getReason() {
- return getSelected() == null ? selector.idSelectionReason : getSelected().selectionReason;
+ return selector.getSelectionReason();
}
public void collectFailures(FailureState failureState) {
- if (isFailed()) {
- failureState.addUnresolvedDependency(this, selector.dependencyMetaData.getRequested(), selector.failure);
+ ModuleVersionResolveException failure = getFailure();
+ if (failure != null) {
+ failureState.addUnresolvedDependency(this, selector.dependencyMetaData.getRequested(), failure);
}
}
-
}
+ /**
+ * Global resolution state.
+ */
private static class ResolveState {
- private final Map<ModuleId, ModuleResolveState> modules = new LinkedHashMap<ModuleId, ModuleResolveState>();
+ private final Map<ModuleIdentifier, ModuleResolveState> modules = new LinkedHashMap<ModuleIdentifier, ModuleResolveState>();
private final Map<ResolvedConfigurationIdentifier, ConfigurationNode> nodes = new LinkedHashMap<ResolvedConfigurationIdentifier, ConfigurationNode>();
- private final Map<ModuleRevisionId, ModuleVersionSelectorResolveState> selectors = new LinkedHashMap<ModuleRevisionId, ModuleVersionSelectorResolveState>();
+ private final Map<ModuleVersionSelector, ModuleVersionSelectorResolveState> selectors = new LinkedHashMap<ModuleVersionSelector, ModuleVersionSelectorResolveState>();
private final ConfigurationNode root;
private final DependencyToModuleVersionIdResolver resolver;
- private final ResolveData resolveData;
+ private final DependencyToConfigurationResolver dependencyToConfigurationResolver;
+ private final ResolvedConfigurationBuilder builder;
private final Set<ConfigurationNode> queued = new HashSet<ConfigurationNode>();
private final LinkedList<ConfigurationNode> queue = new LinkedList<ConfigurationNode>();
- public ResolveState(BuildableModuleVersionMetaData rootModule, String rootConfigurationName, DependencyToModuleVersionIdResolver resolver, ResolveData resolveData) {
+ public ResolveState(ModuleVersionResolveResult rootResult, String rootConfigurationName, DependencyToModuleVersionIdResolver resolver,
+ DependencyToConfigurationResolver dependencyToConfigurationResolver, ResolvedConfigurationBuilder builder) {
this.resolver = resolver;
- this.resolveData = resolveData;
- DefaultModuleRevisionResolveState rootVersion = getRevision(rootModule.getId());
- rootVersion.setMetaData(rootModule);
+ this.dependencyToConfigurationResolver = dependencyToConfigurationResolver;
+ this.builder = builder;
+ ModuleVersionResolveState rootVersion = getRevision(rootResult.getId());
+ rootVersion.setResolveResult(rootResult);
root = getConfigurationNode(rootVersion, rootConfigurationName);
root.moduleRevision.module.select(root.moduleRevision);
}
- public ModuleResolveState getModule(ModuleId moduleId) {
- ModuleId id = new ModuleId(moduleId.getOrganisation(), moduleId.getName());
+ public ModuleResolveState getModule(ModuleIdentifier id) {
ModuleResolveState module = modules.get(id);
if (module == null) {
module = new ModuleResolveState(id, this);
@@ -462,32 +446,31 @@ public class DependencyGraphBuilder {
return module;
}
- public DefaultModuleRevisionResolveState getRevision(ModuleVersionIdentifier moduleVersionIdentifier) {
- ModuleRevisionId id = new ModuleRevisionId(new ModuleId(moduleVersionIdentifier.getGroup(), moduleVersionIdentifier.getName()), moduleVersionIdentifier.getVersion());
- return getModule(id.getModuleId()).getVersion(id);
+ public ModuleVersionResolveState getRevision(ModuleVersionIdentifier id) {
+ return getModule(id.getModule()).getVersion(id);
}
public Collection<ConfigurationNode> getConfigurationNodes() {
return nodes.values();
}
- public ConfigurationNode getConfigurationNode(DefaultModuleRevisionResolveState module, String configurationName) {
- ModuleRevisionId original = module.id;
- ResolvedConfigurationIdentifier id = new ResolvedConfigurationIdentifier(original.getOrganisation(), original.getName(), original.getRevision(), configurationName);
+ public ConfigurationNode getConfigurationNode(ModuleVersionResolveState module, String configurationName) {
+ ModuleVersionIdentifier original = module.id;
+ ResolvedConfigurationIdentifier id = new ResolvedConfigurationIdentifier(original, configurationName);
ConfigurationNode configuration = nodes.get(id);
if (configuration == null) {
- configuration = new ConfigurationNode(module, module.metaData, configurationName, this);
+ configuration = new ConfigurationNode(module, configurationName, this);
nodes.put(id, configuration);
}
return configuration;
}
- public ModuleVersionSelectorResolveState getSelector(DependencyMetaData dependencyMetaData, ModuleRevisionId original) {
- ModuleRevisionId selectorId = ModuleRevisionId.newInstance(original.getOrganisation(), original.getName(), original.getRevision());
- ModuleVersionSelectorResolveState resolveState = selectors.get(selectorId);
+ public ModuleVersionSelectorResolveState getSelector(DependencyMetaData dependencyMetaData) {
+ ModuleVersionSelector requested = dependencyMetaData.getRequested();
+ ModuleVersionSelectorResolveState resolveState = selectors.get(requested);
if (resolveState == null) {
- resolveState = new ModuleVersionSelectorResolveState(dependencyMetaData, getModule(selectorId.getModuleId()), resolver, this);
- selectors.put(selectorId, resolveState);
+ resolveState = new ModuleVersionSelectorResolveState(dependencyMetaData, resolver, this);
+ selectors.put(requested, resolveState);
}
return resolveState;
}
@@ -531,45 +514,57 @@ public class DependencyGraphBuilder {
Evicted
}
+ /**
+ * Resolution state for a given module.
+ */
private static class ModuleResolveState {
- final ModuleId id;
+ final ModuleIdentifier id;
final Set<DependencyEdge> unattachedDependencies = new LinkedHashSet<DependencyEdge>();
- final Map<ModuleRevisionId, DefaultModuleRevisionResolveState> versions = new LinkedHashMap<ModuleRevisionId, DefaultModuleRevisionResolveState>();
+ final Map<ModuleVersionIdentifier, ModuleVersionResolveState> versions = new LinkedHashMap<ModuleVersionIdentifier, ModuleVersionResolveState>();
+ final Set<ModuleVersionSelectorResolveState> selectors = new HashSet<ModuleVersionSelectorResolveState>();
final ResolveState resolveState;
- DefaultModuleRevisionResolveState selected;
+ ModuleVersionResolveState selected;
- private ModuleResolveState(ModuleId id, ResolveState resolveState) {
+ private ModuleResolveState(ModuleIdentifier id, ResolveState resolveState) {
this.id = id;
this.resolveState = resolveState;
}
- public Collection<DefaultModuleRevisionResolveState> getVersions() {
+ @Override
+ public String toString() {
+ return id.toString();
+ }
+
+ public Collection<ModuleVersionResolveState> getVersions() {
return versions.values();
}
- public void select(DefaultModuleRevisionResolveState selected) {
+ public void select(ModuleVersionResolveState selected) {
assert this.selected == null;
this.selected = selected;
- for (DefaultModuleRevisionResolveState version : versions.values()) {
+ for (ModuleVersionResolveState version : versions.values()) {
version.state = ModuleState.Evicted;
}
selected.state = ModuleState.Selected;
}
- public DefaultModuleRevisionResolveState clearSelection() {
- DefaultModuleRevisionResolveState previousSelection = selected;
+ public ModuleVersionResolveState clearSelection() {
+ ModuleVersionResolveState previousSelection = selected;
selected = null;
- for (DefaultModuleRevisionResolveState version : versions.values()) {
+ for (ModuleVersionResolveState version : versions.values()) {
version.state = ModuleState.Conflict;
}
return previousSelection;
}
- public void restart(DefaultModuleRevisionResolveState selected) {
+ public void restart(ModuleVersionResolveState selected) {
select(selected);
- for (DefaultModuleRevisionResolveState version : versions.values()) {
+ for (ModuleVersionResolveState version : versions.values()) {
version.restart(selected);
}
+ for (ModuleVersionSelectorResolveState selector : selectors) {
+ selector.restart(selected);
+ }
for (DependencyEdge dependency : new ArrayList<DependencyEdge>(unattachedDependencies)) {
dependency.restart(selected);
}
@@ -584,29 +579,37 @@ public class DependencyGraphBuilder {
unattachedDependencies.remove(edge);
}
- public DefaultModuleRevisionResolveState getVersion(ModuleRevisionId id) {
- DefaultModuleRevisionResolveState moduleRevision = versions.get(id);
+ public ModuleVersionResolveState getVersion(ModuleVersionIdentifier id) {
+ ModuleVersionResolveState moduleRevision = versions.get(id);
if (moduleRevision == null) {
- moduleRevision = new DefaultModuleRevisionResolveState(this, id, resolveState);
+ moduleRevision = new ModuleVersionResolveState(this, id, resolveState);
versions.put(id, moduleRevision);
}
return moduleRevision;
}
+
+ public void addSelector(ModuleVersionSelectorResolveState selector) {
+ selectors.add(selector);
+ }
}
- private static class DefaultModuleRevisionResolveState implements ModuleRevisionResolveState, ModuleVersionSelection {
+ /**
+ * Resolution state for a given module version.
+ */
+ private static class ModuleVersionResolveState implements ModuleRevisionResolveState, ModuleVersionSelection {
final ModuleResolveState module;
- final ModuleRevisionId id;
+ final ModuleVersionIdentifier id;
final ResolveState resolveState;
final Set<ConfigurationNode> configurations = new LinkedHashSet<ConfigurationNode>();
- List<DependencyMetaData> dependencies;
ModuleVersionMetaData metaData;
ModuleState state = ModuleState.New;
- ModuleVersionSelectorResolveState resolver;
ModuleVersionSelectionReason selectionReason = VersionSelectionReasons.REQUESTED;
+ ModuleVersionIdResolveResult idResolveResult;
+ ModuleVersionResolveResult resolveResult;
+ ModuleVersionResolveException failure;
- private DefaultModuleRevisionResolveState(ModuleResolveState module, ModuleRevisionId id, ResolveState resolveState) {
+ private ModuleVersionResolveState(ModuleResolveState module, ModuleVersionIdentifier id, ResolveState resolveState) {
this.module = module;
this.id = id;
this.resolveState = resolveState;
@@ -617,47 +620,58 @@ public class DependencyGraphBuilder {
return id.toString();
}
- public String getRevision() {
- return id.getRevision();
+ public String getVersion() {
+ return id.getVersion();
}
- public Iterable<DependencyMetaData> getDependencies() {
- if (dependencies == null) {
- dependencies = getMetaData().getDependencies();
- }
- return dependencies;
+ public String getId() {
+ return String.format("%s:%s:%s", id.getGroup(), id.getName(), id.getVersion());
}
- public String getId() {
- return String.format("%s:%s:%s", id.getOrganisation(), id.getName(), id.getRevision());
+ public ModuleVersionResolveException getFailure() {
+ return failure;
}
- public void restart(DefaultModuleRevisionResolveState selected) {
- for (ConfigurationNode conflictConfiguration : configurations) {
- conflictConfiguration.restart(selected);
+ public void restart(ModuleVersionResolveState selected) {
+ for (ConfigurationNode configuration : configurations) {
+ configuration.restart(selected);
}
}
public void addResolver(ModuleVersionSelectorResolveState resolver) {
- if (this.resolver == null) {
- this.resolver = resolver;
+ if (this.idResolveResult == null) {
+ idResolveResult = resolver.idResolveResult;
+ }
+ }
+
+ public ModuleVersionResolveResult resolve() {
+ if (resolveResult != null) {
+ return resolveResult;
+ }
+ if (failure != null) {
+ return null;
+ }
+
+ resolveResult = idResolveResult.resolve();
+ if (resolveResult.getFailure() != null) {
+ failure = resolveResult.getFailure();
+ return null;
}
+ setResolveResult(resolveResult);
+ return resolveResult;
}
public ModuleVersionMetaData getMetaData() {
if (metaData == null) {
- if (resolver == null) {
- throw new IllegalStateException(String.format("No resolver for %s.", this));
- }
- resolver.resolve();
+ resolve();
}
return metaData;
}
- public void setMetaData(ModuleVersionMetaData metaData) {
- if (this.metaData == null) {
- this.metaData = metaData;
- }
+ public void setResolveResult(ModuleVersionResolveResult resolveResult) {
+ this.resolveResult = resolveResult;
+ this.metaData = resolveResult.getMetaData();
+ this.failure = null;
}
public void addConfiguration(ConfigurationNode configurationNode) {
@@ -665,10 +679,7 @@ public class DependencyGraphBuilder {
}
public ModuleVersionIdentifier getSelectedId() {
- return new DefaultModuleVersionIdentifier(
- id.getOrganisation(),
- id.getName(),
- id.getRevision());
+ return id;
}
public ModuleVersionSelectionReason getSelectionReason() {
@@ -680,65 +691,48 @@ public class DependencyGraphBuilder {
}
}
+ /**
+ * Represents a node in the dependency graph.
+ */
private static class ConfigurationNode {
- final DefaultModuleRevisionResolveState moduleRevision;
+ final ModuleVersionResolveState moduleRevision;
+ final ConfigurationMetaData metaData;
final ResolveState resolveState;
- final DefaultModuleDescriptor descriptor;
- final String configurationName;
- final Set<String> heirarchy = new LinkedHashSet<String>();
final Set<DependencyEdge> incomingEdges = new LinkedHashSet<DependencyEdge>();
final Set<DependencyEdge> outgoingEdges = new LinkedHashSet<DependencyEdge>();
- DefaultResolvedDependency result;
+ final ResolvedConfigurationIdentifier result;
ModuleVersionSpec previousTraversal;
Set<ResolvedArtifact> artifacts;
- private ConfigurationNode(DefaultModuleRevisionResolveState moduleRevision, ModuleVersionMetaData moduleVersionMetaData, String configurationName, ResolveState resolveState) {
+ private ConfigurationNode(ModuleVersionResolveState moduleRevision, String configurationName, ResolveState resolveState) {
this.moduleRevision = moduleRevision;
this.resolveState = resolveState;
- this.descriptor = (DefaultModuleDescriptor) moduleVersionMetaData.getDescriptor();
- this.configurationName = configurationName;
- findAncestors(configurationName, resolveState, heirarchy);
+ this.metaData = moduleRevision.metaData.getConfiguration(configurationName);
+ result = new ResolvedConfigurationIdentifier(moduleRevision.id, configurationName);
moduleRevision.addConfiguration(this);
}
- void findAncestors(String config, ResolveState container, Set<String> ancestors) {
- ancestors.add(config);
- for (String parentConfig : descriptor.getConfiguration(config).getExtends()) {
- ancestors.addAll(container.getConfigurationNode(moduleRevision, parentConfig).heirarchy);
- }
- }
-
@Override
public String toString() {
- return String.format("%s(%s)", moduleRevision, configurationName);
+ return String.format("%s(%s)", moduleRevision, metaData.getName());
}
- public Set<ResolvedArtifact> getArtifacts(ResolvedArtifactFactory resolvedArtifactFactory) {
+ public Set<ResolvedArtifact> getArtifacts() {
if (artifacts == null) {
artifacts = new LinkedHashSet<ResolvedArtifact>();
- for (String config : heirarchy) {
- for (Artifact artifact : descriptor.getArtifacts(config)) {
- artifacts.add(resolvedArtifactFactory.create(getResult(), artifact, moduleRevision.resolver.resolve().getArtifactResolver()));
- }
+ for (Artifact artifact : metaData.getArtifacts()) {
+ artifacts.add(resolveState.builder.newArtifact(getResult(), artifact, moduleRevision.resolve().getArtifactResolver()));
}
}
return artifacts;
}
- public DefaultResolvedDependency getResult() {
- if (result == null) {
- result = new DefaultResolvedDependency(
- moduleRevision.id.getOrganisation(),
- moduleRevision.id.getName(),
- moduleRevision.id.getRevision(),
- configurationName);
- }
-
+ public ResolvedConfigurationIdentifier getResult() {
return result;
}
public boolean isTransitive() {
- return descriptor.getConfiguration(configurationName).isTransitive();
+ return metaData.isTransitive();
}
public void visitOutgoingDependencies(Collection<DependencyEdge> target) {
@@ -747,7 +741,7 @@ public class DependencyGraphBuilder {
// If traversed before, and the selected modules have changed, remove previous outgoing edges and add outgoing edges again with
// the new selections.
// If traversed before, and the selected modules have not changed, ignore
- // If none of the incoming edges is transitive, then the node has no outgoing edges
+ // If none of the incoming edges are transitive, then the node has no outgoing edges
if (moduleRevision.state != ModuleState.Selected) {
LOGGER.debug("version for {} is not selected. ignoring.", this);
@@ -782,35 +776,20 @@ public class DependencyGraphBuilder {
removeOutgoingEdges();
}
- for (DependencyMetaData dependency : moduleRevision.getDependencies()) {
+ for (DependencyMetaData dependency : metaData.getDependencies()) {
DependencyDescriptor dependencyDescriptor = dependency.getDescriptor();
ModuleId targetModuleId = dependencyDescriptor.getDependencyRevisionId().getModuleId();
- Set<String> targetConfigurations = getTargetConfigurations(dependencyDescriptor);
- if (!targetConfigurations.isEmpty()) {
- if (!selectorSpec.isSatisfiedBy(targetModuleId)) {
- LOGGER.debug("{} is excluded from {}.", targetModuleId, this);
- } else {
- DependencyEdge dependencyEdge = new DependencyEdge(this, dependency, targetConfigurations, selectorSpec, resolveState);
- outgoingEdges.add(dependencyEdge);
- target.add(dependencyEdge);
- }
+ if (!selectorSpec.isSatisfiedBy(targetModuleId)) {
+ LOGGER.debug("{} is excluded from {}.", targetModuleId, this);
+ continue;
}
+ DependencyEdge dependencyEdge = new DependencyEdge(this, dependency, selectorSpec, resolveState);
+ outgoingEdges.add(dependencyEdge);
+ target.add(dependencyEdge);
}
previousTraversal = selectorSpec;
}
- Set<String> getTargetConfigurations(DependencyDescriptor dependencyDescriptor) {
- Set<String> targetConfigurations = new LinkedHashSet<String>();
- for (String moduleConfiguration : dependencyDescriptor.getModuleConfigurations()) {
- if (moduleConfiguration.equals("*") || heirarchy.contains(moduleConfiguration)) {
- for (String targetConfiguration : dependencyDescriptor.getDependencyConfigurations(moduleConfiguration)) {
- targetConfigurations.add(targetConfiguration);
- }
- }
- }
- return targetConfigurations;
- }
-
public void addIncomingEdge(DependencyEdge dependencyEdge) {
incomingEdges.add(dependencyEdge);
resolveState.onMoreSelected(this);
@@ -825,10 +804,10 @@ public class DependencyGraphBuilder {
return moduleRevision.state == ModuleState.Selected;
}
- public void attachToParents(ResolvedArtifactFactory artifactFactory, ResolvedConfigurationBuilder result) {
+ public void attachToParents(ResolvedConfigurationBuilder result) {
LOGGER.debug("Attaching {} to its parents.", this);
for (DependencyEdge dependency : incomingEdges) {
- dependency.attachToParents(this, artifactFactory, result);
+ dependency.attachToParents(this, result);
}
}
@@ -849,8 +828,7 @@ public class DependencyGraphBuilder {
selector = selector.union(dependencyEdge.getSelector());
}
}
- String[] configurations = heirarchy.toArray(new String[heirarchy.size()]);
- selector = selector.intersect(ModuleVersionSpec.forExcludes(descriptor.getExcludeRules(configurations)));
+ selector = selector.intersect(ModuleVersionSpec.forExcludes(metaData.getExcludeRules()));
return selector;
}
@@ -862,43 +840,52 @@ public class DependencyGraphBuilder {
previousTraversal = null;
}
- public void restart(DefaultModuleRevisionResolveState state) {
+ public void restart(ModuleVersionResolveState selected) {
// Restarting this configuration after conflict resolution.
// If this configuration belongs to the select version, queue ourselves up for traversal.
// If not, then move our incoming edges across to the selected configuration
- if (moduleRevision == state) {
+ if (moduleRevision == selected) {
resolveState.onMoreSelected(this);
} else {
for (DependencyEdge dependency : incomingEdges) {
- dependency.restart(state);
+ dependency.restart(selected);
}
incomingEdges.clear();
}
}
private ModuleVersionIdentifier toId() {
- return newId(moduleRevision.id.getOrganisation(),
- moduleRevision.id.getName(),
- moduleRevision.id.getRevision());
+ return moduleRevision.id;
+ }
+
+ // TODO:ADAM - remove this
+ public void validate() {
+ for (DependencyEdge incomingEdge : incomingEdges) {
+ ModuleState state = incomingEdge.from.moduleRevision.state;
+ if (state != ModuleState.Selected) {
+ throw new IllegalStateException(String.format("Unexpected state %s for parent node for dependency from %s to %s.", state, incomingEdge.from, this));
+ }
+ }
}
}
+ /**
+ * Resolution state for a given module version selector.
+ */
private static class ModuleVersionSelectorResolveState {
final DependencyToModuleVersionIdResolver resolver;
final ResolveState resolveState;
final DependencyMetaData dependencyMetaData;
- ModuleResolveState module;
ModuleVersionResolveException failure;
- ModuleVersionSelectionReason idSelectionReason;
- DefaultModuleRevisionResolveState targetModuleRevision;
+ ModuleResolveState targetModule;
+ ModuleVersionResolveState targetModuleRevision;
ModuleVersionIdResolveResult idResolveResult;
- ModuleVersionResolveResult resolveResult;
- private ModuleVersionSelectorResolveState(DependencyMetaData dependencyMetaData, ModuleResolveState module, DependencyToModuleVersionIdResolver resolver, ResolveState resolveState) {
+ private ModuleVersionSelectorResolveState(DependencyMetaData dependencyMetaData, DependencyToModuleVersionIdResolver resolver, ResolveState resolveState) {
this.dependencyMetaData = dependencyMetaData;
- this.module = module;
this.resolver = resolver;
this.resolveState = resolveState;
+ targetModule = resolveState.getModule(new DefaultModuleIdentifier(dependencyMetaData.getRequested().getGroup(), dependencyMetaData.getRequested().getName()));
}
@Override
@@ -906,10 +893,26 @@ public class DependencyGraphBuilder {
return dependencyMetaData.toString();
}
+ private ModuleVersionResolveException getFailure() {
+ return failure != null ? failure : targetModuleRevision.getFailure();
+ }
+
+ public ModuleVersionSelectionReason getSelectionReason() {
+ return targetModuleRevision == null ? idResolveResult.getSelectionReason() : targetModuleRevision.getSelectionReason();
+ }
+
+ public ModuleVersionResolveState getSelected() {
+ return targetModule.selected;
+ }
+
+ public ModuleResolveState getSelectedModule() {
+ return targetModule;
+ }
+
/**
* @return The module version, or null if there is a failure to resolve this selector.
*/
- public DefaultModuleRevisionResolveState resolveModuleRevisionId() {
+ public ModuleVersionResolveState resolveModuleRevisionId() {
if (targetModuleRevision != null) {
return targetModuleRevision;
}
@@ -918,7 +921,6 @@ public class DependencyGraphBuilder {
}
idResolveResult = resolver.resolve(dependencyMetaData);
- idSelectionReason = idResolveResult.getSelectionReason();
if (idResolveResult.getFailure() != null) {
failure = idResolveResult.getFailure();
return null;
@@ -927,33 +929,15 @@ public class DependencyGraphBuilder {
targetModuleRevision = resolveState.getRevision(idResolveResult.getId());
targetModuleRevision.addResolver(this);
targetModuleRevision.selectionReason = idResolveResult.getSelectionReason();
-
- //the target module details might have been substituted / forced when resolving ID
- //so update the module:
- this.module = targetModuleRevision.module;
+ targetModule = targetModuleRevision.module;
+ targetModule.addSelector(this);
return targetModuleRevision;
}
- public ModuleVersionResolveResult resolve() {
- if (resolveResult != null) {
- return resolveResult;
- }
- if (failure != null) {
- return null;
- }
-
- try {
- resolveResult = idResolveResult.resolve();
- resolveState.getRevision(resolveResult.getId()).setMetaData(resolveResult.getMetaData());
- } catch (ModuleVersionResolveException e) {
- failure = e;
- }
- return resolveResult;
- }
-
- public ModuleVersionSelectorResolveState restart(DefaultModuleRevisionResolveState moduleRevision) {
- return resolveState.getSelector(dependencyMetaData.withRequestedVersion(moduleRevision.id.getRevision()), moduleRevision.id);
+ public void restart(ModuleVersionResolveState moduleRevision) {
+ this.targetModuleRevision = moduleRevision;
+ this.targetModule = moduleRevision.module;
}
}
@@ -964,7 +948,7 @@ public class DependencyGraphBuilder {
this.resolver = resolver;
}
- DefaultModuleRevisionResolveState select(Collection<DefaultModuleRevisionResolveState> candidates, DefaultModuleRevisionResolveState root) {
+ ModuleVersionResolveState select(Collection<ModuleVersionResolveState> candidates, ModuleVersionResolveState root) {
for (ConfigurationNode configuration : root.configurations) {
for (DependencyEdge outgoingEdge : configuration.outgoingEdges) {
if (outgoingEdge.dependencyDescriptor.isForce() && candidates.contains(outgoingEdge.targetModuleRevision)) {
@@ -973,7 +957,7 @@ public class DependencyGraphBuilder {
}
}
}
- return (DefaultModuleRevisionResolveState) resolver.select(candidates, root);
+ return (ModuleVersionResolveState) resolver.select(candidates);
}
}
}
\ No newline at end of file
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/DependencyToConfigurationResolver.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/DependencyToConfigurationResolver.java
new file mode 100644
index 0000000..b1fc361
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/DependencyToConfigurationResolver.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.resolveengine;
+
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ConfigurationMetaData;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.DependencyMetaData;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ModuleVersionMetaData;
+
+import java.util.Set;
+
+/**
+ * Responsible for mapping a dependency definition to the set of configurations that it refers to.
+ */
+public interface DependencyToConfigurationResolver {
+ Set<ConfigurationMetaData> resolveTargetConfigurations(DependencyMetaData dependencyMetaData, ConfigurationMetaData fromConfiguration, ModuleVersionMetaData targetModuleVersion);
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/LatestModuleConflictResolver.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/LatestModuleConflictResolver.java
index 14be289..17cfbc2 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/LatestModuleConflictResolver.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/LatestModuleConflictResolver.java
@@ -15,23 +15,18 @@
*/
package org.gradle.api.internal.artifacts.ivyservice.resolveengine;
-import org.gradle.api.internal.artifacts.version.LatestVersionSemanticComparator;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.LatestStrategy;
import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
class LatestModuleConflictResolver implements ModuleConflictResolver {
- public ModuleRevisionResolveState select(Collection<? extends ModuleRevisionResolveState> candidates, ModuleRevisionResolveState root) {
- return Collections.max(candidates, new VersionComparator());
- }
-
- private class VersionComparator implements Comparator<ModuleRevisionResolveState> {
+ private final LatestStrategy latestStrategy;
- LatestVersionSemanticComparator delegate = new LatestVersionSemanticComparator();
+ LatestModuleConflictResolver(LatestStrategy latestStrategy) {
+ this.latestStrategy = latestStrategy;
+ }
- public int compare(ModuleRevisionResolveState left, ModuleRevisionResolveState right) {
- return delegate.compare(left.getRevision(), right.getRevision());
- }
+ public ModuleRevisionResolveState select(Collection<? extends ModuleRevisionResolveState> candidates) {
+ return latestStrategy.findLatest(candidates);
}
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/ModuleConflictResolver.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/ModuleConflictResolver.java
index 4336b9e..7450d1f 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/ModuleConflictResolver.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/ModuleConflictResolver.java
@@ -18,5 +18,5 @@ package org.gradle.api.internal.artifacts.ivyservice.resolveengine;
import java.util.Collection;
interface ModuleConflictResolver {
- ModuleRevisionResolveState select(Collection<? extends ModuleRevisionResolveState> candidates, ModuleRevisionResolveState root);
+ ModuleRevisionResolveState select(Collection<? extends ModuleRevisionResolveState> candidates);
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/ModuleRevisionResolveState.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/ModuleRevisionResolveState.java
index 6decc2c..174353d 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/ModuleRevisionResolveState.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/ModuleRevisionResolveState.java
@@ -16,12 +16,11 @@
package org.gradle.api.internal.artifacts.ivyservice.resolveengine;
import org.gradle.api.artifacts.result.ModuleVersionSelectionReason;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.Versioned;
-interface ModuleRevisionResolveState {
+interface ModuleRevisionResolveState extends Versioned {
String getId();
- String getRevision();
-
ModuleVersionSelectionReason getSelectionReason();
void setSelectionReason(ModuleVersionSelectionReason moduleVersionSelectionReason);
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/StrictConflictResolver.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/StrictConflictResolver.java
index 86f6daf..a78b3bb 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/StrictConflictResolver.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/StrictConflictResolver.java
@@ -19,7 +19,7 @@ import java.util.Collection;
import java.util.Formatter;
class StrictConflictResolver implements ModuleConflictResolver {
- public ModuleRevisionResolveState select(Collection<? extends ModuleRevisionResolveState> candidates, ModuleRevisionResolveState root) {
+ public ModuleRevisionResolveState select(Collection<? extends ModuleRevisionResolveState> candidates) {
Formatter formatter = new Formatter();
formatter.format("A conflict was found between the following modules:");
for (ModuleRevisionResolveState candidate : candidates) {
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/VersionSelectionReasonResolver.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/VersionSelectionReasonResolver.java
index cb0d3c2..b4c184c 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/VersionSelectionReasonResolver.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/VersionSelectionReasonResolver.java
@@ -20,9 +20,6 @@ import org.gradle.api.internal.artifacts.ivyservice.resolveengine.result.Version
import java.util.Collection;
-/**
-* by Szczepan Faber, created at: 1/29/13
-*/
public class VersionSelectionReasonResolver implements ModuleConflictResolver {
private final ModuleConflictResolver delegate;
@@ -31,8 +28,8 @@ public class VersionSelectionReasonResolver implements ModuleConflictResolver {
this.delegate = delegate;
}
- public ModuleRevisionResolveState select(Collection<? extends ModuleRevisionResolveState> candidates, ModuleRevisionResolveState root) {
- ModuleRevisionResolveState selected = delegate.select(candidates, root);
+ public ModuleRevisionResolveState select(Collection<? extends ModuleRevisionResolveState> candidates) {
+ ModuleRevisionResolveState selected = delegate.select(candidates);
selected.setSelectionReason(VersionSelectionReasons.withConflictResolution(selected.getSelectionReason()));
return selected;
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/oldresult/DefaultResolvedConfigurationBuilder.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/oldresult/DefaultResolvedConfigurationBuilder.java
new file mode 100644
index 0000000..2b7cfc6
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/oldresult/DefaultResolvedConfigurationBuilder.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.resolveengine.oldresult;
+
+import org.apache.ivy.core.module.descriptor.Artifact;
+import org.gradle.api.artifacts.ModuleDependency;
+import org.gradle.api.artifacts.ResolvedArtifact;
+import org.gradle.api.artifacts.ResolvedDependency;
+import org.gradle.api.artifacts.UnresolvedDependency;
+import org.gradle.api.internal.artifacts.DefaultResolvedArtifact;
+import org.gradle.api.internal.artifacts.ResolvedConfigurationIdentifier;
+import org.gradle.api.internal.artifacts.ivyservice.ArtifactResolver;
+import org.gradle.api.internal.artifacts.ivyservice.ResolvedArtifactFactory;
+import org.gradle.api.internal.artifacts.ivyservice.dynamicversions.DefaultResolvedModuleVersion;
+import org.gradle.internal.Factory;
+import org.gradle.internal.id.IdGenerator;
+import org.gradle.internal.id.LongIdGenerator;
+
+import java.io.File;
+import java.util.*;
+
+public class DefaultResolvedConfigurationBuilder implements
+ ResolvedConfigurationBuilder, ResolvedConfigurationResults, ResolvedContentsMapping {
+
+ private final Map<Long, ResolvedArtifact> artifacts = new LinkedHashMap<Long, ResolvedArtifact>();
+ private final Set<UnresolvedDependency> unresolvedDependencies = new LinkedHashSet<UnresolvedDependency>();
+ private final IdGenerator<Long> idGenerator = new LongIdGenerator();
+ private final Map<ResolvedConfigurationIdentifier, ModuleDependency> modulesMap = new HashMap<ResolvedConfigurationIdentifier, ModuleDependency>();
+
+ private ResolvedArtifactFactory resolvedArtifactFactory;
+
+ private final TransientResultsStore store;
+
+ public DefaultResolvedConfigurationBuilder(ResolvedArtifactFactory resolvedArtifactFactory, TransientResultsStore resultsStore) {
+ this.resolvedArtifactFactory = resolvedArtifactFactory;
+ this.store = resultsStore;
+ }
+
+ public void addUnresolvedDependency(UnresolvedDependency unresolvedDependency) {
+ unresolvedDependencies.add(unresolvedDependency);
+ }
+
+ public void addFirstLevelDependency(ModuleDependency moduleDependency, ResolvedConfigurationIdentifier dependency) {
+ store.firstLevelDependency(dependency);
+ //we don't serialise the module dependencies at this stage so we need to keep track
+ //of the mapping module dependency <-> resolved dependency
+ modulesMap.put(dependency, moduleDependency);
+ }
+
+ public void done(ResolvedConfigurationIdentifier root) {
+ store.done(root);
+ }
+
+ public void addChild(ResolvedConfigurationIdentifier parent, ResolvedConfigurationIdentifier child) {
+ store.parentChildMapping(parent, child);
+ }
+
+ public void addParentSpecificArtifacts(ResolvedConfigurationIdentifier child, ResolvedConfigurationIdentifier parent, Set<ResolvedArtifact> artifacts) {
+ for (ResolvedArtifact a : artifacts) {
+ store.parentSpecificArtifact(child, parent, ((DefaultResolvedArtifact)a).getId());
+ }
+ }
+
+ public void newResolvedDependency(ResolvedConfigurationIdentifier id) {
+ store.resolvedDependency(id);
+ }
+
+ public ResolvedArtifact newArtifact(final ResolvedConfigurationIdentifier owner, Artifact artifact, ArtifactResolver artifactResolver) {
+ Factory<File> artifactSource = resolvedArtifactFactory.artifactSource(artifact, artifactResolver);
+ Factory<ResolvedDependency> dependencySource = new ResolvedDependencyFactory(owner, store, this);
+ long id = idGenerator.generateId();
+ ResolvedArtifact newArtifact = new DefaultResolvedArtifact(new DefaultResolvedModuleVersion(owner.getId()), dependencySource, artifact, artifactSource, id);
+ artifacts.put(id, newArtifact);
+ return newArtifact;
+ }
+
+ public boolean hasError() {
+ return !unresolvedDependencies.isEmpty();
+ }
+
+ public TransientConfigurationResults more() {
+ return store.load(this);
+ }
+
+ public Set<ResolvedArtifact> getArtifacts() {
+ return new LinkedHashSet<ResolvedArtifact>(artifacts.values());
+ }
+
+ public ResolvedArtifact getArtifact(long artifactId) {
+ ResolvedArtifact a = artifacts.get(artifactId);
+ assert a != null : "Unable to find artifact for id: " + artifactId;
+ return a;
+ }
+
+ public ModuleDependency getModuleDependency(ResolvedConfigurationIdentifier id) {
+ ModuleDependency m = modulesMap.get(id);
+ assert m != null : "Unable to find module dependency for id: " + id;
+ return m;
+ }
+
+ public Set<UnresolvedDependency> getUnresolvedDependencies() {
+ return unresolvedDependencies;
+ }
+
+ private static class ResolvedDependencyFactory implements Factory<ResolvedDependency> {
+ private final ResolvedConfigurationIdentifier owner;
+ private TransientResultsStore store;
+ private ResolvedContentsMapping mapping;
+
+ public ResolvedDependencyFactory(ResolvedConfigurationIdentifier owner, TransientResultsStore store, ResolvedContentsMapping mapping) {
+ this.owner = owner;
+ this.store = store;
+ this.mapping = mapping;
+ }
+
+ public ResolvedDependency create() {
+ return store.load(mapping).getResolvedDependency(owner);
+ }
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/oldresult/DefaultTransientConfigurationResults.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/oldresult/DefaultTransientConfigurationResults.java
new file mode 100644
index 0000000..0c8adad
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/oldresult/DefaultTransientConfigurationResults.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.resolveengine.oldresult;
+
+import org.gradle.api.artifacts.ModuleDependency;
+import org.gradle.api.artifacts.ResolvedDependency;
+import org.gradle.api.internal.artifacts.DefaultResolvedDependency;
+import org.gradle.api.internal.artifacts.ResolvedConfigurationIdentifier;
+
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+public class DefaultTransientConfigurationResults implements TransientConfigurationResults {
+
+ final Map<ModuleDependency, ResolvedDependency> firstLevelDependencies = new LinkedHashMap<ModuleDependency, ResolvedDependency>();
+ ResolvedDependency root;
+ final Map<ResolvedConfigurationIdentifier, DefaultResolvedDependency> allDependencies = new HashMap<ResolvedConfigurationIdentifier, DefaultResolvedDependency>();
+
+ public Map<ModuleDependency, ResolvedDependency> getFirstLevelDependencies() {
+ return firstLevelDependencies;
+ }
+
+ public ResolvedDependency getRoot() {
+ return root;
+ }
+
+ public ResolvedDependency getResolvedDependency(ResolvedConfigurationIdentifier id) {
+ return allDependencies.get(id);
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/oldresult/ResolvedConfigurationBuilder.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/oldresult/ResolvedConfigurationBuilder.java
new file mode 100644
index 0000000..55739e9
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/oldresult/ResolvedConfigurationBuilder.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.resolveengine.oldresult;
+
+import org.apache.ivy.core.module.descriptor.Artifact;
+import org.gradle.api.artifacts.ModuleDependency;
+import org.gradle.api.artifacts.ResolvedArtifact;
+import org.gradle.api.artifacts.UnresolvedDependency;
+import org.gradle.api.internal.artifacts.ResolvedConfigurationIdentifier;
+import org.gradle.api.internal.artifacts.ivyservice.ArtifactResolver;
+
+import java.util.Set;
+
+//listens to result events tailored for old resolved dependency graph
+public interface ResolvedConfigurationBuilder {
+
+ void addFirstLevelDependency(ModuleDependency moduleDependency, ResolvedConfigurationIdentifier dependency);
+
+ void addUnresolvedDependency(UnresolvedDependency unresolvedDependency);
+
+ void addChild(ResolvedConfigurationIdentifier parent, ResolvedConfigurationIdentifier child);
+
+ void done(ResolvedConfigurationIdentifier root);
+
+ void addParentSpecificArtifacts(ResolvedConfigurationIdentifier child, ResolvedConfigurationIdentifier parent, Set<ResolvedArtifact> artifacts);
+
+ void newResolvedDependency(ResolvedConfigurationIdentifier id);
+
+ ResolvedArtifact newArtifact(ResolvedConfigurationIdentifier owner, Artifact artifact, ArtifactResolver artifactResolver);
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/oldresult/ResolvedConfigurationResults.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/oldresult/ResolvedConfigurationResults.java
new file mode 100644
index 0000000..34c0cb0
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/oldresult/ResolvedConfigurationResults.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.resolveengine.oldresult;
+
+import org.gradle.api.artifacts.ResolvedArtifact;
+import org.gradle.api.artifacts.UnresolvedDependency;
+
+import java.util.Set;
+
+public interface ResolvedConfigurationResults {
+ boolean hasError();
+
+ Set<UnresolvedDependency> getUnresolvedDependencies();
+
+ Set<ResolvedArtifact> getArtifacts();
+
+ TransientConfigurationResults more();
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/oldresult/ResolvedContentsMapping.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/oldresult/ResolvedContentsMapping.java
new file mode 100644
index 0000000..7fb9266
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/oldresult/ResolvedContentsMapping.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.resolveengine.oldresult;
+
+import org.gradle.api.artifacts.ModuleDependency;
+import org.gradle.api.artifacts.ResolvedArtifact;
+import org.gradle.api.internal.artifacts.ResolvedConfigurationIdentifier;
+
+public interface ResolvedContentsMapping {
+
+ ResolvedArtifact getArtifact(long id);
+
+ ModuleDependency getModuleDependency(ResolvedConfigurationIdentifier id);
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/oldresult/TransientConfigurationResults.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/oldresult/TransientConfigurationResults.java
new file mode 100644
index 0000000..634f969
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/oldresult/TransientConfigurationResults.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.resolveengine.oldresult;
+
+import org.gradle.api.artifacts.ModuleDependency;
+import org.gradle.api.artifacts.ResolvedDependency;
+import org.gradle.api.internal.artifacts.ResolvedConfigurationIdentifier;
+
+import java.util.Map;
+
+public interface TransientConfigurationResults {
+
+ Map<ModuleDependency, ResolvedDependency> getFirstLevelDependencies();
+
+ ResolvedDependency getRoot();
+
+ ResolvedDependency getResolvedDependency(ResolvedConfigurationIdentifier id);
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/oldresult/TransientResultsStore.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/oldresult/TransientResultsStore.java
new file mode 100644
index 0000000..b267800
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/oldresult/TransientResultsStore.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.resolveengine.oldresult;
+
+import org.gradle.api.internal.artifacts.DefaultResolvedDependency;
+import org.gradle.api.internal.artifacts.ResolvedConfigurationIdentifier;
+import org.gradle.api.internal.artifacts.ResolvedConfigurationIdentifierSerializer;
+import org.gradle.api.internal.artifacts.ivyservice.resolveengine.store.EncodedWriteAction;
+import org.gradle.api.internal.cache.BinaryStore;
+import org.gradle.api.internal.cache.Store;
+import org.gradle.api.logging.Logger;
+import org.gradle.api.logging.Logging;
+import org.gradle.internal.Factory;
+import org.gradle.messaging.serialize.FlushableEncoder;
+import org.gradle.messaging.serialize.InputStreamBackedDecoder;
+import org.gradle.util.Clock;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import static com.google.common.collect.Sets.newHashSet;
+
+//TODO SF unit coverage
+public class TransientResultsStore {
+
+ private final static Logger LOG = Logging.getLogger(TransientResultsStore.class);
+
+ private static final byte NEW_DEP = 1;
+ private static final byte ROOT = 2;
+ private static final byte FIRST_LVL = 3;
+ private static final byte PARENT_CHILD = 4;
+ private static final byte PARENT_ARTIFACT = 5;
+
+ private final Object lock = new Object();
+
+ private BinaryStore binaryStore;
+ private Store<TransientConfigurationResults> cache;
+ private final ResolvedConfigurationIdentifierSerializer resolvedConfigurationIdentifierSerializer = new ResolvedConfigurationIdentifierSerializer();
+ private BinaryStore.BinaryData binaryData;
+
+ public TransientResultsStore(BinaryStore binaryStore, Store<TransientConfigurationResults> cache) {
+ this.binaryStore = binaryStore;
+ this.cache = cache;
+ }
+
+ private void writeId(final byte type, final ResolvedConfigurationIdentifier... ids) {
+ binaryStore.write(new EncodedWriteAction() {
+ public void write(FlushableEncoder encoder) throws IOException {
+ encoder.writeByte(type);
+ for (ResolvedConfigurationIdentifier id : ids) {
+ resolvedConfigurationIdentifierSerializer.write(encoder, id);
+ }
+ }
+ });
+ }
+
+ public void resolvedDependency(ResolvedConfigurationIdentifier id) {
+ writeId(NEW_DEP, id);
+ }
+
+ public void done(ResolvedConfigurationIdentifier id) {
+ writeId(ROOT, id);
+ LOG.debug("Flushing resolved configuration data in {}. Wrote root {}.", binaryStore, id);
+ binaryData = binaryStore.done();
+ }
+
+ public void firstLevelDependency(ResolvedConfigurationIdentifier id) {
+ writeId(FIRST_LVL, id);
+ }
+
+ public void parentChildMapping(ResolvedConfigurationIdentifier parent, ResolvedConfigurationIdentifier child) {
+ writeId(PARENT_CHILD, parent, child);
+ }
+
+ public void parentSpecificArtifact(ResolvedConfigurationIdentifier child, ResolvedConfigurationIdentifier parent, final long artifactId) {
+ writeId(PARENT_ARTIFACT, child, parent);
+ binaryStore.write(new BinaryStore.WriteAction() {
+ public void write(DataOutputStream output) throws IOException {
+ output.writeLong(artifactId);
+ }
+ });
+ }
+
+ public TransientConfigurationResults load(final ResolvedContentsMapping mapping) {
+ synchronized (lock) {
+ return cache.load(new Factory<TransientConfigurationResults>() {
+ public TransientConfigurationResults create() {
+ try {
+ return binaryData.read(new BinaryStore.ReadAction<TransientConfigurationResults>() {
+ public TransientConfigurationResults read(DataInputStream input) throws IOException {
+ return deserialize(input, mapping);
+ }
+ });
+ } finally {
+ binaryData.done();
+ }
+ }
+ });
+ }
+ }
+
+ private TransientConfigurationResults deserialize(DataInputStream input, ResolvedContentsMapping mapping) {
+ Clock clock = new Clock();
+ DefaultTransientConfigurationResults results = new DefaultTransientConfigurationResults();
+ int valuesRead = 0;
+ byte type = -1;
+ InputStreamBackedDecoder decoder = new InputStreamBackedDecoder(input);
+ try {
+ while (true) {
+ type = decoder.readByte();
+ ResolvedConfigurationIdentifier id;
+ valuesRead++;
+ switch (type) {
+ case NEW_DEP:
+ id = resolvedConfigurationIdentifierSerializer.read(decoder);
+ results.allDependencies.put(id, new DefaultResolvedDependency(id.getId(), id.getConfiguration()));
+ break;
+ case ROOT:
+ id = resolvedConfigurationIdentifierSerializer.read(decoder);
+ results.root = results.allDependencies.get(id);
+ if (results.root == null) {
+ throw new IllegalStateException(String.format("Unexpected root id %s. Seen ids: %s", id, results.allDependencies.keySet()));
+ }
+ //root should be the last
+ LOG.debug("Loaded resolved configuration results ({}) from {}", clock.getTime(), binaryStore);
+ return results;
+ case FIRST_LVL:
+ id = resolvedConfigurationIdentifierSerializer.read(decoder);
+ DefaultResolvedDependency dependency = results.allDependencies.get(id);
+ if (dependency == null) {
+ throw new IllegalStateException(String.format("Unexpected first level id %s. Seen ids: %s", id, results.allDependencies.keySet()));
+ }
+ results.firstLevelDependencies.put(mapping.getModuleDependency(id), dependency);
+ break;
+ case PARENT_CHILD:
+ ResolvedConfigurationIdentifier parentId = resolvedConfigurationIdentifierSerializer.read(decoder);
+ ResolvedConfigurationIdentifier childId = resolvedConfigurationIdentifierSerializer.read(decoder);
+ DefaultResolvedDependency parent = results.allDependencies.get(parentId);
+ DefaultResolvedDependency child = results.allDependencies.get(childId);
+ if (parent == null) {
+ throw new IllegalStateException(String.format("Unexpected parent dependency id %s. Seen ids: %s", parentId, results.allDependencies.keySet()));
+ }
+ if (child == null) {
+ throw new IllegalStateException(String.format("Unexpected child dependency id %s. Seen ids: %s", childId, results.allDependencies.keySet()));
+ }
+ parent.addChild(child);
+ break;
+ case PARENT_ARTIFACT:
+ ResolvedConfigurationIdentifier artifactParentId = resolvedConfigurationIdentifierSerializer.read(decoder);
+ ResolvedConfigurationIdentifier artifactChildId = resolvedConfigurationIdentifierSerializer.read(decoder);
+ DefaultResolvedDependency artifactParent = results.allDependencies.get(artifactParentId);
+ DefaultResolvedDependency artifactChild = results.allDependencies.get(artifactChildId);
+ if (artifactParent == null) {
+ throw new IllegalStateException(String.format("Unexpected parent dependency id %s. Seen ids: %s", artifactParentId, results.allDependencies.keySet()));
+ }
+ if (artifactChild == null) {
+ throw new IllegalStateException(String.format("Unexpected child dependency id %s. Seen ids: %s", artifactChildId, results.allDependencies.keySet()));
+ }
+ artifactParent.addParentSpecificArtifacts(artifactChild, newHashSet(mapping.getArtifact(decoder.readLong())));
+ break;
+ default:
+ throw new IOException("Unknown value type read from stream: " + type);
+ }
+ }
+ } catch (IOException e) {
+ throw new RuntimeException("Problems loading the resolved configuration. Read " + valuesRead + " values, last was: " + type, e);
+ }
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/CachingDependencyResultFactory.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/CachingDependencyResultFactory.java
index 95d6eff..7340657 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/CachingDependencyResultFactory.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/CachingDependencyResultFactory.java
@@ -23,6 +23,7 @@ import org.gradle.api.artifacts.result.ResolvedModuleVersionResult;
import org.gradle.api.artifacts.result.UnresolvedDependencyResult;
import org.gradle.api.internal.artifacts.ivyservice.ModuleVersionResolveException;
import org.gradle.api.internal.artifacts.result.DefaultResolvedDependencyResult;
+import org.gradle.api.internal.artifacts.result.DefaultResolvedModuleVersionResult;
import org.gradle.api.internal.artifacts.result.DefaultUnresolvedDependencyResult;
import java.util.HashMap;
@@ -31,9 +32,6 @@ import java.util.Map;
import static java.util.Arrays.asList;
-/**
- * by Szczepan Faber, created at: 10/1/12
- */
public class CachingDependencyResultFactory {
private final Map<List, DefaultUnresolvedDependencyResult> unresolvedDependencies = new HashMap<List, DefaultUnresolvedDependencyResult>();
@@ -48,7 +46,7 @@ public class CachingDependencyResultFactory {
return unresolvedDependencies.get(key);
}
- public ResolvedDependencyResult createResolvedDependency(ModuleVersionSelector requested, ResolvedModuleVersionResult from, ResolvedModuleVersionResult selected) {
+ public ResolvedDependencyResult createResolvedDependency(ModuleVersionSelector requested, ResolvedModuleVersionResult from, DefaultResolvedModuleVersionResult selected) {
List<Object> key = asList(requested, from, selected);
if (!resolvedDependencies.containsKey(key)) {
resolvedDependencies.put(key, new DefaultResolvedDependencyResult(requested, selected, from));
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/DefaultInternalDependencyResult.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/DefaultInternalDependencyResult.java
new file mode 100644
index 0000000..5bac938
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/DefaultInternalDependencyResult.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.resolveengine.result;
+
+import org.gradle.api.artifacts.ModuleVersionSelector;
+import org.gradle.api.artifacts.result.ModuleVersionSelectionReason;
+import org.gradle.api.internal.artifacts.ivyservice.ModuleVersionResolveException;
+
+public class DefaultInternalDependencyResult implements InternalDependencyResult {
+
+ private final ModuleVersionSelector requested;
+ private final ModuleVersionSelection selected;
+ private final ModuleVersionSelectionReason reason;
+ private ModuleVersionResolveException failure;
+
+ public DefaultInternalDependencyResult(ModuleVersionSelector requested,
+ ModuleVersionSelection selected,
+ ModuleVersionSelectionReason reason,
+ ModuleVersionResolveException failure) {
+ assert requested != null;
+ assert reason != null;
+ assert failure != null || selected != null;
+
+ this.requested = requested;
+ this.reason = reason;
+ this.selected = selected;
+ this.failure = failure;
+ }
+
+ public ModuleVersionSelector getRequested() {
+ return requested;
+ }
+
+ public ModuleVersionSelection getSelected() {
+ return selected;
+ }
+
+ public ModuleVersionSelectionReason getReason() {
+ return reason;
+ }
+
+ public ModuleVersionResolveException getFailure() {
+ return failure;
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/DefaultModuleVersionSelection.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/DefaultModuleVersionSelection.java
new file mode 100644
index 0000000..600d1c6
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/DefaultModuleVersionSelection.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.resolveengine.result;
+
+import org.gradle.api.artifacts.ModuleVersionIdentifier;
+import org.gradle.api.artifacts.result.ModuleVersionSelectionReason;
+
+class DefaultModuleVersionSelection implements ModuleVersionSelection {
+ private ModuleVersionIdentifier id;
+ private ModuleVersionSelectionReason reason;
+
+ public DefaultModuleVersionSelection(ModuleVersionIdentifier id, ModuleVersionSelectionReason reason) {
+ this.id = id;
+ this.reason = reason;
+ }
+
+ public ModuleVersionIdentifier getSelectedId() {
+ return id;
+ }
+
+ public ModuleVersionSelectionReason getSelectionReason() {
+ return reason;
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/InternalDependencyResult.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/InternalDependencyResult.java
index 13250d2..4074c7e 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/InternalDependencyResult.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/InternalDependencyResult.java
@@ -21,9 +21,6 @@ import org.gradle.api.artifacts.ModuleVersionSelector;
import org.gradle.api.artifacts.result.ModuleVersionSelectionReason;
import org.gradle.api.internal.artifacts.ivyservice.ModuleVersionResolveException;
-/**
- * by Szczepan Faber, created at: 8/24/12
- */
public interface InternalDependencyResult {
ModuleVersionSelector getRequested();
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/InternalDependencyResultSerializer.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/InternalDependencyResultSerializer.java
new file mode 100644
index 0000000..0636a21
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/InternalDependencyResultSerializer.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.resolveengine.result;
+
+import org.gradle.api.artifacts.ModuleVersionSelector;
+import org.gradle.api.artifacts.result.ModuleVersionSelectionReason;
+import org.gradle.api.internal.artifacts.ModuleVersionSelectorSerializer;
+import org.gradle.api.internal.artifacts.ivyservice.ModuleVersionResolveException;
+import org.gradle.messaging.serialize.Decoder;
+import org.gradle.messaging.serialize.Encoder;
+
+import java.io.IOException;
+import java.util.Map;
+
+public class InternalDependencyResultSerializer {
+ private final static byte SUCCESSFUL = 0;
+ private final static byte FAILED = 1;
+ private final ModuleVersionSelectorSerializer moduleVersionSelectorSerializer = new ModuleVersionSelectorSerializer();
+ private final ModuleVersionSelectionReasonSerializer moduleVersionSelectionReasonSerializer = new ModuleVersionSelectionReasonSerializer();
+ private final ModuleVersionSelectionSerializer moduleVersionSelectionSerializer = new ModuleVersionSelectionSerializer();
+
+ public InternalDependencyResult read(Decoder decoder, Map<ModuleVersionSelector, ModuleVersionResolveException> failures) throws IOException {
+ ModuleVersionSelector requested = moduleVersionSelectorSerializer.read(decoder);
+ ModuleVersionSelectionReason reason = moduleVersionSelectionReasonSerializer.read(decoder);
+ byte resultByte = decoder.readByte();
+ if (resultByte == SUCCESSFUL) {
+ ModuleVersionSelection selected = moduleVersionSelectionSerializer.read(decoder);
+ return new DefaultInternalDependencyResult(requested, selected, reason, null);
+ } else if (resultByte == FAILED) {
+ ModuleVersionResolveException failure = failures.get(requested);
+ return new DefaultInternalDependencyResult(requested, null, reason, failure);
+ } else {
+ throw new IllegalArgumentException("Unknown result byte: " + resultByte);
+ }
+ }
+
+ public void write(Encoder encoder, InternalDependencyResult value) throws IOException {
+ moduleVersionSelectorSerializer.write(encoder, value.getRequested());
+ moduleVersionSelectionReasonSerializer.write(encoder, value.getReason());
+ if (value.getFailure() == null) {
+ encoder.writeByte(SUCCESSFUL);
+ moduleVersionSelectionSerializer.write(encoder, value.getSelected());
+ } else {
+ encoder.writeByte(FAILED);
+ }
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/ModuleVersionSelection.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/ModuleVersionSelection.java
index bf702f4..11b8849 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/ModuleVersionSelection.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/ModuleVersionSelection.java
@@ -19,9 +19,6 @@ package org.gradle.api.internal.artifacts.ivyservice.resolveengine.result;
import org.gradle.api.artifacts.ModuleVersionIdentifier;
import org.gradle.api.artifacts.result.ModuleVersionSelectionReason;
-/**
-* by Szczepan Faber, created at: 8/31/12
-*/
public interface ModuleVersionSelection {
ModuleVersionIdentifier getSelectedId();
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/ModuleVersionSelectionReasonSerializer.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/ModuleVersionSelectionReasonSerializer.java
new file mode 100644
index 0000000..2595aed
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/ModuleVersionSelectionReasonSerializer.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.resolveengine.result;
+
+import com.google.common.collect.BiMap;
+import com.google.common.collect.HashBiMap;
+import org.gradle.api.artifacts.result.ModuleVersionSelectionReason;
+import org.gradle.messaging.serialize.Decoder;
+import org.gradle.messaging.serialize.Encoder;
+import org.gradle.messaging.serialize.Serializer;
+
+import java.io.IOException;
+
+import static org.gradle.api.internal.artifacts.ivyservice.resolveengine.result.VersionSelectionReasons.*;
+
+public class ModuleVersionSelectionReasonSerializer implements Serializer<ModuleVersionSelectionReason> {
+
+ private static final BiMap<Byte, ModuleVersionSelectionReason> REASONS = HashBiMap.create(6);
+
+ static {
+ REASONS.put((byte) 1, REQUESTED);
+ REASONS.put((byte) 2, ROOT);
+ REASONS.put((byte) 3, FORCED);
+ REASONS.put((byte) 4, CONFLICT_RESOLUTION);
+ REASONS.put((byte) 5, SELECTED_BY_RULE);
+ REASONS.put((byte) 6, CONFLICT_RESOLUTION_BY_RULE);
+ }
+
+ public ModuleVersionSelectionReason read(Decoder decoder) throws IOException {
+ byte id = decoder.readByte();
+ ModuleVersionSelectionReason out = REASONS.get(id);
+ if (out == null) {
+ throw new IllegalArgumentException("Unable to find selection reason with id: " + id);
+ }
+ return out;
+ }
+
+ public void write(Encoder encoder, ModuleVersionSelectionReason value) throws IOException {
+ Byte id = REASONS.inverse().get(value);
+ if (id == null) {
+ throw new IllegalArgumentException("Unknown selection reason: " + value);
+ }
+ encoder.writeByte(id);
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/ModuleVersionSelectionSerializer.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/ModuleVersionSelectionSerializer.java
new file mode 100644
index 0000000..b68b0dd
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/ModuleVersionSelectionSerializer.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.resolveengine.result;
+
+import org.gradle.api.artifacts.ModuleVersionIdentifier;
+import org.gradle.api.artifacts.result.ModuleVersionSelectionReason;
+import org.gradle.api.internal.artifacts.ModuleVersionIdentifierSerializer;
+import org.gradle.messaging.serialize.Decoder;
+import org.gradle.messaging.serialize.Encoder;
+import org.gradle.messaging.serialize.Serializer;
+
+import java.io.IOException;
+
+public class ModuleVersionSelectionSerializer implements Serializer<ModuleVersionSelection> {
+
+ private final ModuleVersionIdentifierSerializer idSerializer = new ModuleVersionIdentifierSerializer();
+ private final ModuleVersionSelectionReasonSerializer reasonSerializer = new ModuleVersionSelectionReasonSerializer();
+
+ public ModuleVersionSelection read(Decoder decoder) throws IOException {
+ ModuleVersionIdentifier id = idSerializer.read(decoder);
+ ModuleVersionSelectionReason reason = reasonSerializer.read(decoder);
+ return new DefaultModuleVersionSelection(id, reason);
+ }
+
+ public void write(Encoder encoder, ModuleVersionSelection value) throws IOException {
+ idSerializer.write(encoder, value.getSelectedId());
+ reasonSerializer.write(encoder, value.getSelectionReason());
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/ResolutionResultBuilder.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/ResolutionResultBuilder.java
index 2323616..46db100 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/ResolutionResultBuilder.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/ResolutionResultBuilder.java
@@ -17,19 +17,15 @@
package org.gradle.api.internal.artifacts.ivyservice.resolveengine.result;
import org.gradle.api.artifacts.ModuleVersionIdentifier;
-import org.gradle.api.artifacts.result.DependencyResult;
-import org.gradle.api.artifacts.result.ModuleVersionSelectionReason;
-import org.gradle.api.artifacts.result.ResolvedDependencyResult;
+import org.gradle.api.artifacts.result.*;
import org.gradle.api.internal.artifacts.result.DefaultResolutionResult;
import org.gradle.api.internal.artifacts.result.DefaultResolvedModuleVersionResult;
+import org.gradle.internal.Factory;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
-/**
- * by Szczepan Faber, created at: 7/26/12
- */
public class ResolutionResultBuilder implements ResolvedConfigurationListener {
private DefaultResolvedModuleVersionResult rootModule;
@@ -44,8 +40,8 @@ public class ResolutionResultBuilder implements ResolvedConfigurationListener {
return this;
}
- public DefaultResolutionResult getResult() {
- return new DefaultResolutionResult(rootModule);
+ public ResolutionResult complete() {
+ return new DefaultResolutionResult(new RootFactory(rootModule));
}
public void resolvedModuleVersion(ModuleVersionSelection moduleVersion) {
@@ -73,4 +69,16 @@ public class ResolutionResultBuilder implements ResolvedConfigurationListener {
}
return modules.get(id);
}
+
+ private static class RootFactory implements Factory<ResolvedModuleVersionResult> {
+ private DefaultResolvedModuleVersionResult rootModule;
+
+ public RootFactory(DefaultResolvedModuleVersionResult rootModule) {
+ this.rootModule = rootModule;
+ }
+
+ public ResolvedModuleVersionResult create() {
+ return rootModule;
+ }
+ }
}
\ No newline at end of file
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/ResolvedConfigurationListener.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/ResolvedConfigurationListener.java
index 1ac0e97..ccd26d2 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/ResolvedConfigurationListener.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/ResolvedConfigurationListener.java
@@ -17,14 +17,14 @@
package org.gradle.api.internal.artifacts.ivyservice.resolveengine.result;
import org.gradle.api.artifacts.ModuleVersionIdentifier;
+import org.gradle.api.artifacts.result.ResolutionResult;
import java.util.Collection;
-/**
- * by Szczepan Faber, created at: 7/26/12
- */
+//listens to result events tailored for the new dependency graph model, TODO SF rename job needed
public interface ResolvedConfigurationListener {
ResolvedConfigurationListener start(ModuleVersionIdentifier root);
void resolvedModuleVersion(ModuleVersionSelection moduleVersion);
void resolvedConfiguration(ModuleVersionIdentifier id, Collection<? extends InternalDependencyResult> dependencies);
+ ResolutionResult complete();
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/StreamingResolutionResultBuilder.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/StreamingResolutionResultBuilder.java
new file mode 100644
index 0000000..d30a709
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/StreamingResolutionResultBuilder.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.resolveengine.result;
+
+import org.gradle.api.artifacts.ModuleVersionIdentifier;
+import org.gradle.api.artifacts.ModuleVersionSelector;
+import org.gradle.api.artifacts.result.ResolutionResult;
+import org.gradle.api.artifacts.result.ResolvedModuleVersionResult;
+import org.gradle.api.internal.artifacts.ModuleVersionIdentifierSerializer;
+import org.gradle.api.internal.artifacts.ivyservice.ModuleVersionResolveException;
+import org.gradle.api.internal.artifacts.ivyservice.resolveengine.store.EncodedWriteAction;
+import org.gradle.api.internal.artifacts.result.DefaultResolutionResult;
+import org.gradle.api.internal.cache.BinaryStore;
+import org.gradle.api.internal.cache.Store;
+import org.gradle.api.logging.Logger;
+import org.gradle.api.logging.Logging;
+import org.gradle.internal.Factory;
+import org.gradle.messaging.serialize.Decoder;
+import org.gradle.messaging.serialize.FlushableEncoder;
+import org.gradle.messaging.serialize.InputStreamBackedDecoder;
+import org.gradle.util.Clock;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * by Szczepan Faber on 7/28/13
+ */
+public class StreamingResolutionResultBuilder implements ResolvedConfigurationListener {
+
+ private final static byte ROOT = 1;
+ private final static byte MODULE = 2;
+ private final static byte DEPENDENCY = 3;
+ private final static byte DONE = 4;
+
+ private final Map<ModuleVersionSelector, ModuleVersionResolveException> failures = new HashMap<ModuleVersionSelector, ModuleVersionResolveException>();
+ private final BinaryStore store;
+ private final ModuleVersionIdentifierSerializer moduleVersionIdentifierSerializer = new ModuleVersionIdentifierSerializer();
+ private final ModuleVersionSelectionSerializer moduleVersionSelectionSerializer = new ModuleVersionSelectionSerializer();
+ private Store<ResolvedModuleVersionResult> cache;
+ private final InternalDependencyResultSerializer internalDependencyResultSerializer = new InternalDependencyResultSerializer();
+
+ public StreamingResolutionResultBuilder(BinaryStore store, Store<ResolvedModuleVersionResult> cache) {
+ this.store = store;
+ this.cache = cache;
+ }
+
+ public ResolutionResult complete() {
+ store.write(new EncodedWriteAction() {
+ public void write(FlushableEncoder encoder) throws IOException {
+ encoder.writeByte(DONE);
+ }
+ });
+ BinaryStore.BinaryData data = store.done();
+ RootFactory rootSource = new RootFactory(data, failures, cache);
+ return new DefaultResolutionResult(rootSource);
+ }
+
+ public ResolvedConfigurationListener start(final ModuleVersionIdentifier root) {
+ store.write(new EncodedWriteAction() {
+ public void write(FlushableEncoder encoder) throws IOException {
+ encoder.writeByte(ROOT);
+ moduleVersionIdentifierSerializer.write(encoder, root);
+ }
+ });
+ return this;
+ }
+
+ Set<ModuleVersionIdentifier> visitedModules = new HashSet<ModuleVersionIdentifier>();
+
+ public void resolvedModuleVersion(final ModuleVersionSelection moduleVersion) {
+ if (visitedModules.add(moduleVersion.getSelectedId())) {
+ store.write(new EncodedWriteAction() {
+ public void write(FlushableEncoder encoder) throws IOException {
+ encoder.writeByte(MODULE);
+ moduleVersionSelectionSerializer.write(encoder, moduleVersion);
+ }
+ });
+ }
+ }
+
+ public void resolvedConfiguration(final ModuleVersionIdentifier from, final Collection<? extends InternalDependencyResult> dependencies) {
+ if (!dependencies.isEmpty()) {
+ store.write(new EncodedWriteAction() {
+ public void write(FlushableEncoder encoder) throws IOException {
+ encoder.writeByte(DEPENDENCY);
+ moduleVersionIdentifierSerializer.write(encoder, from);
+ encoder.writeInt(dependencies.size());
+ for (InternalDependencyResult dependency : dependencies) {
+ internalDependencyResultSerializer.write(encoder, dependency);
+ if (dependency.getFailure() != null) {
+ //by keying the failures only be 'requested' we lose some precision
+ //at edge case we'll lose info about a different exception if we have different failure for the same requested version
+ failures.put(dependency.getRequested(), dependency.getFailure());
+ }
+ }
+ }
+ });
+ }
+ }
+
+ private static class RootFactory implements Factory<ResolvedModuleVersionResult> {
+
+ private final static Logger LOG = Logging.getLogger(RootFactory.class);
+ private final ModuleVersionSelectionSerializer moduleVersionSelectionSerializer = new ModuleVersionSelectionSerializer();
+
+ private BinaryStore.BinaryData data;
+ private final Map<ModuleVersionSelector, ModuleVersionResolveException> failures;
+ private Store<ResolvedModuleVersionResult> cache;
+ private final Object lock = new Object();
+ private final ModuleVersionIdentifierSerializer moduleVersionIdentifierSerializer = new ModuleVersionIdentifierSerializer();
+ private final InternalDependencyResultSerializer internalDependencyResultSerializer = new InternalDependencyResultSerializer();
+
+ public RootFactory(BinaryStore.BinaryData data, Map<ModuleVersionSelector, ModuleVersionResolveException> failures,
+ Store<ResolvedModuleVersionResult> cache) {
+ this.data = data;
+ this.failures = failures;
+ this.cache = cache;
+ }
+
+ public ResolvedModuleVersionResult create() {
+ synchronized (lock) {
+ return cache.load(new Factory<ResolvedModuleVersionResult>() {
+ public ResolvedModuleVersionResult create() {
+ try {
+ return data.read(new BinaryStore.ReadAction<ResolvedModuleVersionResult>() {
+ public ResolvedModuleVersionResult read(DataInputStream input) throws IOException {
+ return deserialize(input);
+ }
+ });
+ } finally {
+ data.done();
+ }
+ }
+ });
+ }
+ }
+
+ private ResolvedModuleVersionResult deserialize(DataInputStream input) {
+ int valuesRead = 0;
+ byte type = -1;
+ Clock clock = new Clock();
+ try {
+ ResolutionResultBuilder builder = new ResolutionResultBuilder();
+ Decoder decoder = new InputStreamBackedDecoder(input);
+ while (true) {
+ type = decoder.readByte();
+ valuesRead++;
+ switch (type) {
+ case ROOT:
+ ModuleVersionIdentifier id = moduleVersionIdentifierSerializer.read(decoder);
+ builder.start(id);
+ break;
+ case MODULE:
+ ModuleVersionSelection sel = moduleVersionSelectionSerializer.read(decoder);
+ builder.resolvedModuleVersion(sel);
+ break;
+ case DEPENDENCY:
+ id = moduleVersionIdentifierSerializer.read(decoder);
+ int size = decoder.readInt();
+ List<InternalDependencyResult> deps = new LinkedList<InternalDependencyResult>();
+ for (int i = 0; i < size; i++) {
+ deps.add(internalDependencyResultSerializer.read(decoder, failures));
+ }
+ builder.resolvedConfiguration(id, deps);
+ break;
+ case DONE:
+ ResolvedModuleVersionResult root = builder.complete().getRoot();
+ LOG.debug("Loaded resolution results ({}) from {}", clock.getTime(), data);
+ return root;
+ default:
+ throw new IOException("Unknown value type read from stream: " + type);
+ }
+ }
+ } catch (IOException e) {
+ throw new RuntimeException("Problems loading the resolution results (" + clock.getTime() + "). "
+ + "Read " + valuesRead + " values, last was: " + type, e);
+ }
+ }
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/VersionSelectionReasons.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/VersionSelectionReasons.java
index 9b9e45a..39c9180 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/VersionSelectionReasons.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/VersionSelectionReasons.java
@@ -18,9 +18,6 @@ package org.gradle.api.internal.artifacts.ivyservice.resolveengine.result;
import org.gradle.api.artifacts.result.ModuleVersionSelectionReason;
-/**
- * by Szczepan Faber, created at: 10/1/12
- */
public class VersionSelectionReasons {
public static final ModuleVersionSelectionReason REQUESTED = new DefaultModuleVersionSelectionReason(false, false, false, "requested");
public static final ModuleVersionSelectionReason ROOT = new DefaultModuleVersionSelectionReason(false, false, false, "root");
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/store/CachedStoreFactory.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/store/CachedStoreFactory.java
new file mode 100644
index 0000000..f618c11
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/store/CachedStoreFactory.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.resolveengine.store;
+
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import org.gradle.api.internal.cache.Store;
+import org.gradle.api.logging.Logger;
+import org.gradle.api.logging.Logging;
+import org.gradle.internal.Factory;
+
+import java.util.concurrent.atomic.AtomicLong;
+
+import static org.gradle.util.Clock.prettyTime;
+
+public class CachedStoreFactory<T> {
+
+ private static final Logger LOG = Logging.getLogger(CachedStoreFactory.class);
+
+ private final Cache<Object, T> cache;
+ private final Stats stats;
+ private String displayName;
+
+ public CachedStoreFactory(String displayName) {
+ this.displayName = displayName;
+ cache = CacheBuilder.newBuilder().maximumSize(100).build();
+ stats = new Stats();
+ }
+
+ public Store<T> createCachedStore(final Object id) {
+ return new SimpleStore<T>(cache, id, stats);
+ }
+
+ public void close() {
+ LOG.debug(displayName + " cache closed. Cache reads: "
+ + stats.readsFromCache + ", disk reads: "
+ + stats.readsFromDisk + " (avg: " + prettyTime(stats.getDiskReadsAvgMs()) + ", total: " + prettyTime(stats.diskReadsTotalMs.get()) + ")");
+ }
+
+ private static class Stats {
+ private final AtomicLong diskReadsTotalMs = new AtomicLong();
+ private final AtomicLong readsFromCache = new AtomicLong();
+ private final AtomicLong readsFromDisk = new AtomicLong();
+
+ public void readFromDisk(long start) {
+ long duration = System.currentTimeMillis() - start;
+ readsFromDisk.incrementAndGet();
+ diskReadsTotalMs.addAndGet(duration);
+ }
+
+ public void readFromCache() {
+ readsFromCache.incrementAndGet();
+ }
+
+ public long getDiskReadsAvgMs() {
+ if (readsFromDisk.get() == 0) {
+ return 0;
+ }
+ return diskReadsTotalMs.get() / readsFromDisk.get();
+ }
+ }
+
+ private static class SimpleStore<T> implements Store<T> {
+ private Cache<Object, T> cache;
+ private final Object id;
+ private Stats stats;
+
+ public SimpleStore(Cache<Object, T> cache, Object id, Stats stats) {
+ this.cache = cache;
+ this.id = id;
+ this.stats = stats;
+ }
+
+ public T load(Factory<T> createIfNotPresent) {
+ T out = cache.getIfPresent(id);
+ if (out != null) {
+ stats.readFromCache();
+ return out;
+ }
+ long start = System.currentTimeMillis();
+ T value = createIfNotPresent.create();
+ stats.readFromDisk(start);
+ cache.put(id, value);
+ return value;
+ }
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/store/DefaultBinaryStore.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/store/DefaultBinaryStore.java
new file mode 100644
index 0000000..247bbac
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/store/DefaultBinaryStore.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.resolveengine.store;
+
+import org.gradle.api.internal.cache.BinaryStore;
+import org.gradle.util.GStreamUtil;
+
+import java.io.*;
+
+import static org.gradle.internal.UncheckedException.throwAsUncheckedException;
+
+class DefaultBinaryStore implements BinaryStore {
+ private File file;
+ private DataOutputStream outputStream;
+ private int offset = -1;
+
+ public DefaultBinaryStore(File file) {
+ this.file = file;
+ }
+
+ public void write(WriteAction write) {
+ if (outputStream == null) {
+ try {
+ outputStream = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file)));
+ } catch (FileNotFoundException e) {
+ throw throwAsUncheckedException(e);
+ }
+ }
+ if (offset == -1) {
+ offset = outputStream.size();
+ if (offset == Integer.MAX_VALUE) {
+ throw new IllegalStateException("Unable to write to binary store. "
+ + "The bytes offset has reached a point where using it is unsafe. Please report this error.");
+ }
+ }
+ try {
+ write.write(outputStream);
+ } catch (IOException e) {
+ throw new RuntimeException("Problems writing to " + diagnose(), e);
+ }
+ }
+
+ private String diagnose() {
+ return toString() + " (exist: " + file.exists() + ")";
+ }
+
+ public String toString() {
+ return "Binary store in " + file;
+ }
+
+ public BinaryData done() {
+ try {
+ if (outputStream != null) {
+ outputStream.flush();
+ }
+ return new SimpleBinaryData(file, offset, diagnose());
+ } catch (IOException e) {
+ throw new RuntimeException("Problems flushing data to " + diagnose(), e);
+ } finally {
+ offset = -1;
+ }
+ }
+
+ public void close() {
+ try {
+ if (outputStream != null) {
+ outputStream.close();
+ }
+ } catch (IOException e) {
+ throw throwAsUncheckedException(e);
+ } finally {
+ file.delete();
+ outputStream = null;
+ file = null;
+ }
+ }
+
+ File getFile() {
+ return file;
+ }
+
+ long getSize() {
+ return file.length();
+ }
+
+ private static class SimpleBinaryData implements BinaryData {
+ private DataInputStream input;
+ private File inputFile;
+ private int offset;
+ private final String sourceDescription;
+
+ public SimpleBinaryData(File inputFile, int offset, String sourceDescription) {
+ this.inputFile = inputFile;
+ this.offset = offset;
+ this.sourceDescription = sourceDescription;
+ }
+
+ public <T> T read(ReadAction<T> readAction) {
+ try {
+ if (input == null) {
+ input = new DataInputStream(new BufferedInputStream(new FileInputStream(inputFile)));
+ GStreamUtil.skipBytes(offset, input);
+ }
+ return readAction.read(input);
+ } catch (Exception e) {
+ throw new RuntimeException("Problems reading data from " + sourceDescription, e);
+ }
+ }
+
+ public void done() {
+ try {
+ if (input != null) {
+ input.close();
+ }
+ } catch (IOException e) {
+ throw new RuntimeException("Problems closing the " + sourceDescription, e);
+ }
+ input = null;
+ }
+
+ public String toString() {
+ return sourceDescription;
+ }
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/store/EncodedWriteAction.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/store/EncodedWriteAction.java
new file mode 100644
index 0000000..ad4b560
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/store/EncodedWriteAction.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.resolveengine.store;
+
+import org.gradle.api.internal.cache.BinaryStore;
+import org.gradle.messaging.serialize.FlushableEncoder;
+import org.gradle.messaging.serialize.OutputStreamBackedEncoder;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public abstract class EncodedWriteAction implements BinaryStore.WriteAction {
+ public final void write(DataOutputStream output) throws IOException {
+ write(new OutputStreamBackedEncoder(output));
+ }
+
+ public abstract void write(FlushableEncoder encoder) throws IOException;
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/store/ResolutionResultsStoreFactory.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/store/ResolutionResultsStoreFactory.java
new file mode 100644
index 0000000..26c792a
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/store/ResolutionResultsStoreFactory.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.resolveengine.store;
+
+import org.gradle.api.internal.cache.Store;
+import org.gradle.api.internal.file.TemporaryFileProvider;
+import org.gradle.api.logging.Logger;
+import org.gradle.api.logging.Logging;
+import org.gradle.internal.CompositeStoppable;
+import org.gradle.util.Clock;
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+public class ResolutionResultsStoreFactory implements Closeable {
+ private final static Logger LOG = Logging.getLogger(ResolutionResultsStoreFactory.class);
+ private static final int DEFAULT_MAX_SIZE = 2000000000; //2 gigs
+
+ private final TemporaryFileProvider temp;
+ private int maxSize;
+
+ private CachedStoreFactory oldModelCache;
+ private CachedStoreFactory newModelCache;
+
+ public ResolutionResultsStoreFactory(TemporaryFileProvider temp) {
+ this(temp, DEFAULT_MAX_SIZE);
+ }
+
+ /**
+ * @param temp
+ * @param maxSize - indicates the approx. maximum size of the binary store that will trigger rolling of the file
+ */
+ ResolutionResultsStoreFactory(TemporaryFileProvider temp, int maxSize) {
+ this.temp = temp;
+ this.maxSize = maxSize;
+ }
+
+ private final Map<String, DefaultBinaryStore> stores = new HashMap<String, DefaultBinaryStore>();
+ private final CompositeStoppable cleanUpLater = new CompositeStoppable();
+
+ public DefaultBinaryStore createBinaryStore(String id) {
+ String storeKey = Thread.currentThread().getId() + id; //one store per thread
+ DefaultBinaryStore store = stores.get(storeKey);
+ if (store == null || isFull(store)) {
+ File storeFile = temp.createTemporaryFile("gradle", ".bin");
+ storeFile.deleteOnExit();
+ store = new DefaultBinaryStore(storeFile);
+ stores.put(storeKey, store);
+ cleanUpLater.add(store);
+ }
+ return store;
+ }
+
+ //offset based implementation is only safe up to certain figure
+ //because of the int max value
+ //for large streams/files (huge builds), we need to roll the file
+ //otherwise the stream.size() returns max integer and the offset is no longer correct
+ private boolean isFull(DefaultBinaryStore store) {
+ return store.getSize() > maxSize;
+ }
+
+ public void close() throws IOException {
+ Clock clock = new Clock();
+ cleanUpLater.stop();
+ LOG.debug("Deleted {} resolution results binary files in {}", stores.size(), clock.getTime());
+ oldModelCache = null;
+ newModelCache = null;
+ stores.clear();
+ }
+
+ public <T> Store<T> createOldModelCache(Object id) {
+ if (oldModelCache == null) {
+ oldModelCache = new CachedStoreFactory("Resolution result");
+ cleanUpLater.add(oldModelCache);
+ }
+ return oldModelCache.createCachedStore(id);
+ }
+
+ public <T> Store<T> createNewModelCache(Object id) {
+ if (newModelCache == null) {
+ newModelCache = new CachedStoreFactory("Resolved configuration");
+ cleanUpLater.add(newModelCache);
+ }
+ return newModelCache.createCachedStore(id);
+ }
+}
\ No newline at end of file
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/mvnsettings/DefaultLocalMavenRepositoryLocator.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/mvnsettings/DefaultLocalMavenRepositoryLocator.java
index 4f232aa..4797f5e 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/mvnsettings/DefaultLocalMavenRepositoryLocator.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/mvnsettings/DefaultLocalMavenRepositoryLocator.java
@@ -16,7 +16,7 @@
package org.gradle.api.internal.artifacts.mvnsettings;
import org.gradle.mvn3.org.apache.maven.settings.Settings;
-import org.gradle.mvn3.org.apache.maven.settings.building.*;
+import org.gradle.mvn3.org.apache.maven.settings.building.SettingsBuildingException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -25,9 +25,6 @@ import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-/**
- * @author Steve Ebersole
- */
public class DefaultLocalMavenRepositoryLocator implements LocalMavenRepositoryLocator {
private static final Logger LOGGER = LoggerFactory.getLogger(DefaultLocalMavenRepositoryLocator.class);
private static final Pattern PLACEHOLDER_PATTERN = Pattern.compile("\\$\\{([^\\}]*)\\}");
@@ -55,7 +52,7 @@ public class DefaultLocalMavenRepositoryLocator implements LocalMavenRepositoryL
return defaultLocation;
}
} catch (SettingsBuildingException e) {
- throw new CannotLocateLocalMavenRepositoryException("Unable to parse local maven settings.", e);
+ throw new CannotLocateLocalMavenRepositoryException("Unable to parse local Maven settings.", e);
}
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/mvnsettings/DefaultMavenFileLocations.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/mvnsettings/DefaultMavenFileLocations.java
index ff01ffc..b07ce89 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/mvnsettings/DefaultMavenFileLocations.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/mvnsettings/DefaultMavenFileLocations.java
@@ -22,9 +22,6 @@ import org.gradle.util.DeprecationLogger;
import java.io.File;
-/**
-* @author Szczepan Faber, created at: 3/30/11
-*/
public class DefaultMavenFileLocations implements MavenFileLocations {
public File getUserMavenDir() {
return new File(SystemProperties.getUserHome(), ".m2");
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/mvnsettings/DefaultMavenSettingsProvider.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/mvnsettings/DefaultMavenSettingsProvider.java
index 6846eb3..04ec293 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/mvnsettings/DefaultMavenSettingsProvider.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/mvnsettings/DefaultMavenSettingsProvider.java
@@ -18,9 +18,6 @@ package org.gradle.api.internal.artifacts.mvnsettings;
import org.gradle.mvn3.org.apache.maven.settings.Settings;
import org.gradle.mvn3.org.apache.maven.settings.building.*;
-/**
- * @author Szczepan Faber/Steve Ebersole
- */
public class DefaultMavenSettingsProvider implements MavenSettingsProvider {
private final MavenFileLocations mavenFileLocations;
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/DefaultBaseRepositoryFactory.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/DefaultBaseRepositoryFactory.java
index c776957..a17b580 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/DefaultBaseRepositoryFactory.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/DefaultBaseRepositoryFactory.java
@@ -16,53 +16,52 @@
package org.gradle.api.internal.artifacts.repositories;
-import org.apache.ivy.core.cache.RepositoryCacheManager;
import org.apache.ivy.core.module.id.ArtifactRevisionId;
import org.apache.ivy.plugins.resolver.DependencyResolver;
import org.gradle.api.InvalidUserDataException;
import org.gradle.api.artifacts.dsl.RepositoryHandler;
import org.gradle.api.artifacts.repositories.*;
import org.gradle.api.internal.artifacts.BaseRepositoryFactory;
+import org.gradle.api.internal.artifacts.ModuleMetadataProcessor;
+import org.gradle.api.internal.artifacts.dsl.DefaultRepositoryHandler;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.MetaDataParser;
import org.gradle.api.internal.artifacts.mvnsettings.LocalMavenRepositoryLocator;
+import org.gradle.api.internal.artifacts.repositories.legacy.LegacyDependencyResolverRepositoryFactory;
import org.gradle.api.internal.artifacts.repositories.transport.RepositoryTransportFactory;
import org.gradle.api.internal.externalresource.local.LocallyAvailableResourceFinder;
import org.gradle.api.internal.file.FileResolver;
import org.gradle.internal.reflect.Instantiator;
-import org.gradle.logging.ProgressLoggerFactory;
import org.gradle.util.ConfigureUtil;
import java.io.File;
import java.util.Map;
-/**
- * @author Hans Dockter
- */
public class DefaultBaseRepositoryFactory implements BaseRepositoryFactory {
private final LocalMavenRepositoryLocator localMavenRepositoryLocator;
private final FileResolver fileResolver;
private final Instantiator instantiator;
private final RepositoryTransportFactory transportFactory;
private final LocallyAvailableResourceFinder<ArtifactRevisionId> locallyAvailableResourceFinder;
- private final ProgressLoggerFactory progressLoggerFactory;
- private final RepositoryCacheManager localCacheManager;
- private final RepositoryCacheManager downloadingCacheManager;
+ private final MetaDataParser metaDataParser;
+ private final ModuleMetadataProcessor metadataProcessor;
+ private final LegacyDependencyResolverRepositoryFactory legacyDependencyResolverRepositoryFactory;
public DefaultBaseRepositoryFactory(LocalMavenRepositoryLocator localMavenRepositoryLocator,
FileResolver fileResolver,
Instantiator instantiator,
RepositoryTransportFactory transportFactory,
LocallyAvailableResourceFinder<ArtifactRevisionId> locallyAvailableResourceFinder,
- ProgressLoggerFactory progressLoggerFactory,
- RepositoryCacheManager localCacheManager,
- RepositoryCacheManager downloadingCacheManager) {
+ MetaDataParser metaDataParser,
+ ModuleMetadataProcessor metadataProcessor,
+ LegacyDependencyResolverRepositoryFactory legacyDependencyResolverRepositoryFactory) {
this.localMavenRepositoryLocator = localMavenRepositoryLocator;
this.fileResolver = fileResolver;
this.instantiator = instantiator;
this.transportFactory = transportFactory;
this.locallyAvailableResourceFinder = locallyAvailableResourceFinder;
- this.progressLoggerFactory = progressLoggerFactory;
- this.localCacheManager = localCacheManager;
- this.downloadingCacheManager = downloadingCacheManager;
+ this.metaDataParser = metaDataParser;
+ this.metadataProcessor = metadataProcessor;
+ this.legacyDependencyResolverRepositoryFactory = legacyDependencyResolverRepositoryFactory;
}
public ArtifactRepository createRepository(Object userDescription) {
@@ -81,17 +80,14 @@ public class DefaultBaseRepositoryFactory implements BaseRepositoryFactory {
return repository;
}
- DependencyResolver result;
if (userDescription instanceof DependencyResolver) {
- result = (DependencyResolver) userDescription;
- } else {
- throw new InvalidUserDataException(String.format("Cannot create a DependencyResolver instance from %s", userDescription));
+ return legacyDependencyResolverRepositoryFactory.createRepository((DependencyResolver) userDescription);
}
- return new CustomResolverArtifactRepository(result, progressLoggerFactory, localCacheManager, downloadingCacheManager);
+ throw new InvalidUserDataException(String.format("Cannot create a DependencyResolver instance from %s", userDescription));
}
public FlatDirectoryArtifactRepository createFlatDirRepository() {
- return instantiator.newInstance(DefaultFlatDirArtifactRepository.class, fileResolver, localCacheManager);
+ return instantiator.newInstance(DefaultFlatDirArtifactRepository.class, fileResolver, transportFactory, locallyAvailableResourceFinder, metaDataParser, metadataProcessor);
}
public MavenArtifactRepository createMavenLocalRepository() {
@@ -101,6 +97,12 @@ public class DefaultBaseRepositoryFactory implements BaseRepositoryFactory {
return mavenRepository;
}
+ public MavenArtifactRepository createJCenterRepository() {
+ MavenArtifactRepository mavenRepository = createMavenRepository();
+ mavenRepository.setUrl(DefaultRepositoryHandler.BINTRAY_JCENTER_URL);
+ return mavenRepository;
+ }
+
public MavenArtifactRepository createMavenCentralRepository() {
MavenArtifactRepository mavenRepository = createMavenRepository();
mavenRepository.setUrl(RepositoryHandler.MAVEN_CENTRAL_URL);
@@ -109,13 +111,13 @@ public class DefaultBaseRepositoryFactory implements BaseRepositoryFactory {
public IvyArtifactRepository createIvyRepository() {
return instantiator.newInstance(DefaultIvyArtifactRepository.class, fileResolver, createPasswordCredentials(), transportFactory,
- locallyAvailableResourceFinder, instantiator
+ locallyAvailableResourceFinder, instantiator, metaDataParser, metadataProcessor
);
}
public MavenArtifactRepository createMavenRepository() {
return instantiator.newInstance(DefaultMavenArtifactRepository.class, fileResolver, createPasswordCredentials(), transportFactory,
- locallyAvailableResourceFinder
+ locallyAvailableResourceFinder, metaDataParser, metadataProcessor
);
}
@@ -130,5 +132,4 @@ public class DefaultBaseRepositoryFactory implements BaseRepositoryFactory {
private PasswordCredentials createPasswordCredentials() {
return instantiator.newInstance(DefaultPasswordCredentials.class);
}
-
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/DefaultFlatDirArtifactRepository.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/DefaultFlatDirArtifactRepository.java
index 9ba4a83..d149036 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/DefaultFlatDirArtifactRepository.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/DefaultFlatDirArtifactRepository.java
@@ -16,13 +16,17 @@
package org.gradle.api.internal.artifacts.repositories;
import com.google.common.collect.Lists;
-import org.apache.ivy.core.cache.RepositoryCacheManager;
+import org.apache.ivy.core.module.id.ArtifactRevisionId;
import org.apache.ivy.plugins.resolver.DependencyResolver;
-import org.apache.ivy.plugins.resolver.FileSystemResolver;
import org.gradle.api.InvalidUserDataException;
import org.gradle.api.artifacts.repositories.FlatDirectoryArtifactRepository;
-import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.IvyAwareModuleVersionRepository;
-import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.IvyDependencyResolverAdapter;
+import org.gradle.api.internal.artifacts.ModuleMetadataProcessor;
+import org.gradle.api.internal.artifacts.ModuleVersionPublisher;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ConfiguredModuleVersionRepository;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.MetaDataParser;
+import org.gradle.api.internal.artifacts.repositories.resolver.IvyResolver;
+import org.gradle.api.internal.artifacts.repositories.transport.RepositoryTransportFactory;
+import org.gradle.api.internal.externalresource.local.LocallyAvailableResourceFinder;
import org.gradle.api.internal.file.FileResolver;
import java.io.File;
@@ -34,11 +38,20 @@ import java.util.Set;
public class DefaultFlatDirArtifactRepository extends AbstractArtifactRepository implements FlatDirectoryArtifactRepository {
private final FileResolver fileResolver;
private List<Object> dirs = new ArrayList<Object>();
- private final RepositoryCacheManager localCacheManager;
+ private final RepositoryTransportFactory transportFactory;
+ private final LocallyAvailableResourceFinder<ArtifactRevisionId> locallyAvailableResourceFinder;
+ private final MetaDataParser metaDataParser;
+ private final ModuleMetadataProcessor metadataProcessor;
- public DefaultFlatDirArtifactRepository(FileResolver fileResolver, RepositoryCacheManager localCacheManager) {
+ public DefaultFlatDirArtifactRepository(FileResolver fileResolver,
+ RepositoryTransportFactory transportFactory,
+ LocallyAvailableResourceFinder<ArtifactRevisionId> locallyAvailableResourceFinder,
+ MetaDataParser metaDataParser, ModuleMetadataProcessor metadataProcessor) {
this.fileResolver = fileResolver;
- this.localCacheManager = localCacheManager;
+ this.transportFactory = transportFactory;
+ this.locallyAvailableResourceFinder = locallyAvailableResourceFinder;
+ this.metaDataParser = metaDataParser;
+ this.metadataProcessor = metadataProcessor;
}
public Set<File> getDirs() {
@@ -57,28 +70,30 @@ public class DefaultFlatDirArtifactRepository extends AbstractArtifactRepository
this.dirs.addAll(Arrays.asList(dirs));
}
- public DependencyResolver createPublisher() {
- return createLegacyDslObject();
+ public ModuleVersionPublisher createPublisher() {
+ return createRealResolver();
}
- public IvyAwareModuleVersionRepository createResolver() {
- return new IvyDependencyResolverAdapter(createLegacyDslObject());
+ public ConfiguredModuleVersionRepository createResolver() {
+ return createRealResolver();
}
public DependencyResolver createLegacyDslObject() {
+ IvyResolver resolver = createRealResolver();
+ return new LegacyDependencyResolver(resolver);
+ }
+
+ private IvyResolver createRealResolver() {
Set<File> dirs = getDirs();
if (dirs.isEmpty()) {
throw new InvalidUserDataException("You must specify at least one directory for a flat directory repository.");
}
- FileSystemResolver resolver = new FileSystemResolver();
- resolver.setName(getName());
+ IvyResolver resolver = new IvyResolver(getName(), transportFactory.createFileTransport(getName()), locallyAvailableResourceFinder, metaDataParser, metadataProcessor, false);
for (File root : dirs) {
resolver.addArtifactPattern(root.getAbsolutePath() + "/[artifact]-[revision](-[classifier]).[ext]");
resolver.addArtifactPattern(root.getAbsolutePath() + "/[artifact](-[classifier]).[ext]");
}
- resolver.setValidate(false);
- resolver.setRepositoryCacheManager(localCacheManager);
return resolver;
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/DefaultIvyArtifactRepository.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/DefaultIvyArtifactRepository.java
index 0955405..1e1e4a0 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/DefaultIvyArtifactRepository.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/DefaultIvyArtifactRepository.java
@@ -22,11 +22,14 @@ import org.gradle.api.InvalidUserDataException;
import org.gradle.api.artifacts.repositories.IvyArtifactRepository;
import org.gradle.api.artifacts.repositories.IvyArtifactRepositoryMetaDataProvider;
import org.gradle.api.artifacts.repositories.PasswordCredentials;
-import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ExternalResourceResolverAdapter;
-import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.IvyAwareModuleVersionRepository;
+import org.gradle.api.internal.artifacts.ModuleMetadataProcessor;
+import org.gradle.api.internal.artifacts.ModuleVersionPublisher;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ConfiguredModuleVersionRepository;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.MetaDataParser;
import org.gradle.api.internal.artifacts.repositories.layout.*;
import org.gradle.api.internal.artifacts.repositories.resolver.IvyResolver;
import org.gradle.api.internal.artifacts.repositories.resolver.PatternBasedResolver;
+import org.gradle.api.internal.artifacts.repositories.transport.RepositoryTransport;
import org.gradle.api.internal.artifacts.repositories.transport.RepositoryTransportFactory;
import org.gradle.api.internal.externalresource.local.LocallyAvailableResourceFinder;
import org.gradle.api.internal.file.FileResolver;
@@ -47,9 +50,12 @@ public class DefaultIvyArtifactRepository extends AbstractAuthenticationSupporte
private final LocallyAvailableResourceFinder<ArtifactRevisionId> locallyAvailableResourceFinder;
private final MetaDataProvider metaDataProvider;
private final Instantiator instantiator;
+ private final MetaDataParser metaDataParser;
+ private final ModuleMetadataProcessor metadataProcessor;
public DefaultIvyArtifactRepository(FileResolver fileResolver, PasswordCredentials credentials, RepositoryTransportFactory transportFactory,
- LocallyAvailableResourceFinder<ArtifactRevisionId> locallyAvailableResourceFinder, Instantiator instantiator) {
+ LocallyAvailableResourceFinder<ArtifactRevisionId> locallyAvailableResourceFinder, Instantiator instantiator,
+ MetaDataParser metaDataParser, ModuleMetadataProcessor metadataProcessor) {
super(credentials);
this.fileResolver = fileResolver;
this.transportFactory = transportFactory;
@@ -58,23 +64,21 @@ public class DefaultIvyArtifactRepository extends AbstractAuthenticationSupporte
this.layout = new GradleRepositoryLayout();
this.metaDataProvider = new MetaDataProvider();
this.instantiator = instantiator;
+ this.metaDataParser = metaDataParser;
+ this.metadataProcessor = metadataProcessor;
}
public DependencyResolver createLegacyDslObject() {
IvyResolver resolver = createRealResolver();
- return new LegacyDependencyResolver(resolver, wrapResolver(resolver));
+ return new LegacyDependencyResolver(resolver);
}
- public DependencyResolver createPublisher() {
+ public ModuleVersionPublisher createPublisher() {
return createRealResolver();
}
- public IvyAwareModuleVersionRepository createResolver() {
- return wrapResolver(createRealResolver());
- }
-
- private ExternalResourceResolverAdapter wrapResolver(IvyResolver resolver) {
- return new ExternalResourceResolverAdapter(resolver, metaDataProvider.dynamicResolve);
+ public ConfiguredModuleVersionRepository createResolver() {
+ return createRealResolver();
}
protected IvyResolver createRealResolver() {
@@ -100,14 +104,21 @@ public class DefaultIvyArtifactRepository extends AbstractAuthenticationSupporte
throw new InvalidUserDataException("You may only specify 'file', 'http' and 'https' urls for an Ivy repository.");
}
if (WrapUtil.toSet("http", "https").containsAll(schemes)) {
- return new IvyResolver(getName(), transportFactory.createHttpTransport(getName(), getCredentials()), locallyAvailableResourceFinder);
+ return createResolver(transportFactory.createHttpTransport(getName(), getCredentials()));
}
if (WrapUtil.toSet("file").containsAll(schemes)) {
- return new IvyResolver(getName(), transportFactory.createFileTransport(getName()), locallyAvailableResourceFinder);
+ return createResolver(transportFactory.createFileTransport(getName()));
}
throw new InvalidUserDataException("You cannot mix file and http(s) urls for a single Ivy repository. Please declare 2 separate repositories.");
}
+ private IvyResolver createResolver(RepositoryTransport httpTransport) {
+ return new IvyResolver(
+ getName(), httpTransport,
+ locallyAvailableResourceFinder,
+ metaDataParser, metadataProcessor, metaDataProvider.dynamicResolve);
+ }
+
public URI getUrl() {
return baseUrl == null ? null : fileResolver.resolveUri(baseUrl);
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/DefaultMavenArtifactRepository.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/DefaultMavenArtifactRepository.java
index 60fe1b5..b52f0f5 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/DefaultMavenArtifactRepository.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/DefaultMavenArtifactRepository.java
@@ -21,8 +21,10 @@ import org.apache.ivy.plugins.resolver.DependencyResolver;
import org.gradle.api.InvalidUserDataException;
import org.gradle.api.artifacts.repositories.MavenArtifactRepository;
import org.gradle.api.artifacts.repositories.PasswordCredentials;
-import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ExternalResourceResolverAdapter;
-import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.IvyAwareModuleVersionRepository;
+import org.gradle.api.internal.artifacts.ModuleMetadataProcessor;
+import org.gradle.api.internal.artifacts.ModuleVersionPublisher;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ConfiguredModuleVersionRepository;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.MetaDataParser;
import org.gradle.api.internal.artifacts.repositories.resolver.MavenResolver;
import org.gradle.api.internal.artifacts.repositories.transport.RepositoryTransport;
import org.gradle.api.internal.artifacts.repositories.transport.RepositoryTransportFactory;
@@ -41,13 +43,18 @@ public class DefaultMavenArtifactRepository extends AbstractAuthenticationSuppor
private Object url;
private List<Object> additionalUrls = new ArrayList<Object>();
private final LocallyAvailableResourceFinder<ArtifactRevisionId> locallyAvailableResourceFinder;
+ private final MetaDataParser metaDataParser;
+ private final ModuleMetadataProcessor metadataProcessor;
public DefaultMavenArtifactRepository(FileResolver fileResolver, PasswordCredentials credentials, RepositoryTransportFactory transportFactory,
- LocallyAvailableResourceFinder<ArtifactRevisionId> locallyAvailableResourceFinder) {
+ LocallyAvailableResourceFinder<ArtifactRevisionId> locallyAvailableResourceFinder, MetaDataParser metaDataParser,
+ ModuleMetadataProcessor metadataProcessor) {
super(credentials);
this.fileResolver = fileResolver;
this.transportFactory = transportFactory;
this.locallyAvailableResourceFinder = locallyAvailableResourceFinder;
+ this.metaDataParser = metaDataParser;
+ this.metadataProcessor = metadataProcessor;
}
public URI getUrl() {
@@ -74,21 +81,17 @@ public class DefaultMavenArtifactRepository extends AbstractAuthenticationSuppor
additionalUrls = Lists.newArrayList(urls);
}
- public DependencyResolver createPublisher() {
+ public ModuleVersionPublisher createPublisher() {
return createRealResolver();
}
public DependencyResolver createLegacyDslObject() {
MavenResolver resolver = createRealResolver();
- return new LegacyMavenResolver(resolver, wrapResolver(resolver));
+ return new LegacyMavenResolver(resolver);
}
- public IvyAwareModuleVersionRepository createResolver() {
- return wrapResolver(createRealResolver());
- }
-
- private ExternalResourceResolverAdapter wrapResolver(MavenResolver resolver) {
- return new ExternalResourceResolverAdapter(resolver, false);
+ public ConfiguredModuleVersionRepository createResolver() {
+ return createRealResolver();
}
protected MavenResolver createRealResolver() {
@@ -97,7 +100,7 @@ public class DefaultMavenArtifactRepository extends AbstractAuthenticationSuppor
throw new InvalidUserDataException("You must specify a URL for a Maven repository.");
}
- MavenResolver resolver = new MavenResolver(getName(), rootUri, getTransport(rootUri.getScheme()), locallyAvailableResourceFinder);
+ MavenResolver resolver = new MavenResolver(getName(), rootUri, getTransport(rootUri.getScheme()), locallyAvailableResourceFinder, metaDataParser, metadataProcessor);
for (URI repoUrl : getArtifactUrls()) {
resolver.addArtifactLocation(repoUrl, null);
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/FixedResolverArtifactRepository.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/FixedResolverArtifactRepository.java
index d5ff8b0..7b02f40 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/FixedResolverArtifactRepository.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/FixedResolverArtifactRepository.java
@@ -16,7 +16,9 @@
package org.gradle.api.internal.artifacts.repositories;
import org.apache.ivy.plugins.resolver.DependencyResolver;
-import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.IvyAwareModuleVersionRepository;
+import org.gradle.api.internal.artifacts.ModuleVersionPublisher;
+import org.gradle.api.internal.artifacts.ivyservice.IvyResolverBackedModuleVersionPublisher;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ConfiguredModuleVersionRepository;
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.IvyDependencyResolverAdapter;
public class FixedResolverArtifactRepository extends AbstractArtifactRepository {
@@ -38,11 +40,11 @@ public class FixedResolverArtifactRepository extends AbstractArtifactRepository
super.setName(name);
}
- public DependencyResolver createPublisher() {
- return resolver;
+ public ModuleVersionPublisher createPublisher() {
+ return new IvyResolverBackedModuleVersionPublisher(resolver);
}
- public IvyAwareModuleVersionRepository createResolver() {
+ public ConfiguredModuleVersionRepository createResolver() {
// Handle a repository wrapped in a resolver for backwards compatibility
if (resolver instanceof ResolutionAwareRepository) {
ResolutionAwareRepository resolutionAwareRepository = (ResolutionAwareRepository) resolver;
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/LegacyDependencyResolver.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/LegacyDependencyResolver.java
index afca9f7..3bfa9a0 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/LegacyDependencyResolver.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/LegacyDependencyResolver.java
@@ -31,15 +31,17 @@ import org.apache.ivy.core.search.OrganisationEntry;
import org.apache.ivy.core.search.RevisionEntry;
import org.apache.ivy.plugins.latest.LatestStrategy;
import org.apache.ivy.plugins.namespace.Namespace;
+import org.apache.ivy.plugins.resolver.BasicResolver;
import org.apache.ivy.plugins.resolver.DependencyResolver;
import org.apache.ivy.plugins.resolver.ResolverSettings;
import org.apache.ivy.plugins.resolver.util.ResolvedResource;
-import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.IvyAwareModuleVersionRepository;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ConfiguredModuleVersionRepository;
import org.gradle.api.internal.artifacts.repositories.resolver.ExternalResourceResolver;
import java.io.File;
import java.io.IOException;
import java.text.ParseException;
+import java.util.Arrays;
import java.util.List;
import java.util.Map;
@@ -49,11 +51,10 @@ import java.util.Map;
*/
public class LegacyDependencyResolver implements DependencyResolver, ResolutionAwareRepository {
private final ExternalResourceResolver resolver;
- private final IvyAwareModuleVersionRepository repository;
+ private ResolverSettings settings;
- public LegacyDependencyResolver(ExternalResourceResolver resolver, IvyAwareModuleVersionRepository repository) {
+ public LegacyDependencyResolver(ExternalResourceResolver resolver) {
this.resolver = resolver;
- this.repository = repository;
}
public String getName() {
@@ -68,16 +69,16 @@ public class LegacyDependencyResolver implements DependencyResolver, ResolutionA
return resolver.toString();
}
- public IvyAwareModuleVersionRepository createResolver() {
- return repository;
+ public ConfiguredModuleVersionRepository createResolver() {
+ return resolver;
}
- public void setSettings(ResolverSettings ivy) {
- resolver.setSettings(ivy);
+ public void setSettings(ResolverSettings settings) {
+ this.settings = settings;
}
public ResolverSettings getSettings() {
- return resolver.getSettings();
+ return settings;
}
public ResolvedModuleRevision getDependency(DependencyDescriptor dd, ResolveData data) throws ParseException {
@@ -230,7 +231,16 @@ public class LegacyDependencyResolver implements DependencyResolver, ResolutionA
* @param descriptorRule the descriptor rule to use with this resolver.
*/
public void setDescriptor(String descriptorRule) {
- resolver.setDescriptor(descriptorRule);
+ if (BasicResolver.DESCRIPTOR_REQUIRED.equals(descriptorRule)) {
+ setAllownomd(false);
+ } else if (BasicResolver.DESCRIPTOR_OPTIONAL.equals(descriptorRule)) {
+ setAllownomd(true);
+ } else {
+ throw new IllegalArgumentException(
+ "unknown descriptor rule '" + descriptorRule
+ + "'. Allowed rules are: "
+ + Arrays.asList(BasicResolver.DESCRIPTOR_REQUIRED, BasicResolver.DESCRIPTOR_OPTIONAL));
+ }
}
public String[] getChecksumAlgorithms() {
@@ -242,19 +252,19 @@ public class LegacyDependencyResolver implements DependencyResolver, ResolutionA
}
public LatestStrategy getLatestStrategy() {
- return resolver.getLatestStrategy();
+ throw new UnsupportedOperationException("getLatestStrategy");
}
public void setLatestStrategy(LatestStrategy latestStrategy) {
- resolver.setLatestStrategy(latestStrategy);
+ throw new UnsupportedOperationException("setLatestStrategy");
}
- public void setLatest(String strategyName) {
- resolver.setLatest(strategyName);
+ public String getLatest() {
+ throw new UnsupportedOperationException("getLatest");
}
- public String getLatest() {
- return resolver.getLatest();
+ public void setLatest(String strategyName) {
+ throw new UnsupportedOperationException("setLatest");
}
public void setChangingMatcher(String changingMatcherName) {
@@ -274,7 +284,7 @@ public class LegacyDependencyResolver implements DependencyResolver, ResolutionA
}
public void setCheckmodified(boolean check) {
- resolver.setCheckmodified(check);
+ throw new UnsupportedOperationException();
}
public RepositoryCacheManager getRepositoryCacheManager() {
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/LegacyMavenResolver.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/LegacyMavenResolver.java
index f409088..0810786 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/LegacyMavenResolver.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/LegacyMavenResolver.java
@@ -16,14 +16,13 @@
package org.gradle.api.internal.artifacts.repositories;
-import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.IvyAwareModuleVersionRepository;
import org.gradle.api.internal.artifacts.repositories.resolver.MavenResolver;
public class LegacyMavenResolver extends LegacyDependencyResolver {
private final MavenResolver resolver;
- public LegacyMavenResolver(MavenResolver resolver, IvyAwareModuleVersionRepository repository) {
- super(resolver, repository);
+ public LegacyMavenResolver(MavenResolver resolver) {
+ super(resolver);
this.resolver = resolver;
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/ResolutionAwareRepository.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/ResolutionAwareRepository.java
index ceb2598..d86d2db 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/ResolutionAwareRepository.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/ResolutionAwareRepository.java
@@ -16,8 +16,8 @@
package org.gradle.api.internal.artifacts.repositories;
-import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.IvyAwareModuleVersionRepository;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ConfiguredModuleVersionRepository;
public interface ResolutionAwareRepository {
- IvyAwareModuleVersionRepository createResolver();
+ ConfiguredModuleVersionRepository createResolver();
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/cachemanager/AbstractRepositoryArtifactCache.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/cachemanager/AbstractRepositoryArtifactCache.java
new file mode 100644
index 0000000..a946036
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/cachemanager/AbstractRepositoryArtifactCache.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.repositories.cachemanager;
+
+abstract class AbstractRepositoryArtifactCache implements RepositoryArtifactCache {
+
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/cachemanager/AbstractRepositoryCacheManager.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/cachemanager/AbstractRepositoryCacheManager.java
deleted file mode 100644
index d87c553..0000000
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/cachemanager/AbstractRepositoryCacheManager.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.artifacts.repositories.cachemanager;
-
-import org.apache.ivy.core.cache.ArtifactOrigin;
-import org.apache.ivy.core.cache.CacheMetadataOptions;
-import org.apache.ivy.core.cache.ModuleDescriptorWriter;
-import org.apache.ivy.core.cache.RepositoryCacheManager;
-import org.apache.ivy.core.module.descriptor.Artifact;
-import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
-import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
-import org.apache.ivy.core.module.id.ModuleRevisionId;
-import org.apache.ivy.core.resolve.ResolvedModuleRevision;
-import org.apache.ivy.core.settings.IvySettings;
-import org.apache.ivy.plugins.parser.ModuleDescriptorParser;
-import org.apache.ivy.plugins.parser.ParserSettings;
-import org.apache.ivy.plugins.repository.Resource;
-import org.apache.ivy.plugins.resolver.DependencyResolver;
-import org.apache.ivy.plugins.resolver.util.ResolvedResource;
-import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.IvyContextualiser;
-import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.ModuleScopedParserSettings;
-import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.ParserRegistry;
-import org.gradle.internal.UncheckedException;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.URL;
-import java.text.ParseException;
-
-abstract class AbstractRepositoryCacheManager implements RepositoryCacheManager {
- protected final String name;
- private final ParserRegistry parserRegistry = new ParserRegistry();
-
- public AbstractRepositoryCacheManager(String name) {
- this.name = name;
- }
-
- public String getName() {
- return name;
- }
-
- public void saveResolvers(ModuleDescriptor descriptor, String metadataResolverName, String artifactResolverName) {
- }
-
- public ArtifactOrigin getSavedArtifactOrigin(Artifact artifact) {
- return null;
- }
-
- public ResolvedModuleRevision findModuleInCache(DependencyDescriptor dd, ModuleRevisionId requestedRevisionId, CacheMetadataOptions options, String expectedResolver) {
- return null;
- }
-
- public void originalToCachedModuleDescriptor(DependencyResolver resolver, ResolvedResource originalMetadataRef, Artifact requestedMetadataArtifact, ResolvedModuleRevision rmr, ModuleDescriptorWriter writer) {
- }
-
- public void clean() {
- }
-
- public void saveResolvedRevision(ModuleRevisionId dynamicMrid, String revision) {
- }
-
- protected ModuleDescriptor parseModuleDescriptor(DependencyResolver resolver, Artifact moduleArtifact, CacheMetadataOptions options, File artifactFile, Resource resource) throws ParseException {
- ModuleRevisionId moduleRevisionId = moduleArtifact.getId().getModuleRevisionId();
- try {
- IvySettings ivySettings = IvyContextualiser.getIvyContext().getSettings();
- ParserSettings parserSettings = new ModuleScopedParserSettings(ivySettings, resolver, moduleRevisionId);
- ModuleDescriptorParser parser = parserRegistry.forResource(resource);
- return parser.parseDescriptor(parserSettings, new URL(artifactFile.toURI().toASCIIString()), resource, options.isValidate());
- } catch (IOException e) {
- throw UncheckedException.throwAsUncheckedException(e);
- }
- }
-}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/cachemanager/DownloadingRepositoryArtifactCache.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/cachemanager/DownloadingRepositoryArtifactCache.java
new file mode 100644
index 0000000..3c26dfa
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/cachemanager/DownloadingRepositoryArtifactCache.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.repositories.cachemanager;
+
+import org.apache.ivy.core.module.id.ArtifactRevisionId;
+import org.gradle.api.internal.artifacts.ivyservice.CacheLockingManager;
+import org.gradle.api.internal.externalresource.DefaultLocallyAvailableExternalResource;
+import org.gradle.api.internal.externalresource.ExternalResource;
+import org.gradle.api.internal.externalresource.LocallyAvailableExternalResource;
+import org.gradle.api.internal.externalresource.cached.CachedExternalResourceIndex;
+import org.gradle.api.internal.externalresource.metadata.ExternalResourceMetaData;
+import org.gradle.api.internal.file.TemporaryFileProvider;
+import org.gradle.internal.Factory;
+import org.gradle.internal.filestore.FileStore;
+import org.gradle.internal.resource.local.LocallyAvailableResource;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * A cache manager for remote repositories, that downloads files and stores them in the FileStore provided.
+ */
+public class DownloadingRepositoryArtifactCache implements RepositoryArtifactCache {
+
+ private final FileStore<ArtifactRevisionId> fileStore;
+ private final CachedExternalResourceIndex<String> artifactUrlCachedResolutionIndex;
+ private final TemporaryFileProvider temporaryFileProvider;
+ private final CacheLockingManager cacheLockingManager;
+
+ public DownloadingRepositoryArtifactCache(FileStore<ArtifactRevisionId> fileStore, CachedExternalResourceIndex<String> artifactUrlCachedResolutionIndex,
+ TemporaryFileProvider temporaryFileProvider, CacheLockingManager cacheLockingManager) {
+ this.fileStore = fileStore;
+ this.artifactUrlCachedResolutionIndex = artifactUrlCachedResolutionIndex;
+ this.temporaryFileProvider = temporaryFileProvider;
+ this.cacheLockingManager = cacheLockingManager;
+ }
+
+ public boolean isLocal() {
+ return false;
+ }
+
+ public LocallyAvailableExternalResource downloadAndCacheArtifactFile(final ArtifactRevisionId artifactId, ExternalResourceDownloader resourceDownloader, final ExternalResource resource) throws IOException {
+ final File tmpFile = temporaryFileProvider.createTemporaryFile("gradle_download", "bin");
+ try {
+ resourceDownloader.download(resource, tmpFile);
+ return cacheLockingManager.useCache(String.format("Store %s", artifactId), new Factory<LocallyAvailableExternalResource>() {
+ public LocallyAvailableExternalResource create() {
+ LocallyAvailableResource cachedResource = fileStore.move(artifactId, tmpFile);
+ File fileInFileStore = cachedResource.getFile();
+ ExternalResourceMetaData metaData = resource.getMetaData();
+ artifactUrlCachedResolutionIndex.store(metaData.getLocation(), fileInFileStore, metaData);
+ return new DefaultLocallyAvailableExternalResource(resource.getName(), cachedResource, metaData);
+ }
+ });
+ } finally {
+ tmpFile.delete();
+ }
+ }
+
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/cachemanager/DownloadingRepositoryCacheManager.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/cachemanager/DownloadingRepositoryCacheManager.java
deleted file mode 100644
index 94c9032..0000000
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/cachemanager/DownloadingRepositoryCacheManager.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.artifacts.repositories.cachemanager;
-
-import org.apache.ivy.core.cache.ArtifactOrigin;
-import org.apache.ivy.core.cache.CacheDownloadOptions;
-import org.apache.ivy.core.cache.CacheMetadataOptions;
-import org.apache.ivy.core.cache.DownloadListener;
-import org.apache.ivy.core.module.descriptor.Artifact;
-import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
-import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
-import org.apache.ivy.core.module.id.ArtifactRevisionId;
-import org.apache.ivy.core.report.ArtifactDownloadReport;
-import org.apache.ivy.core.report.DownloadStatus;
-import org.apache.ivy.core.report.MetadataArtifactDownloadReport;
-import org.apache.ivy.core.resolve.ResolvedModuleRevision;
-import org.apache.ivy.plugins.repository.ArtifactResourceResolver;
-import org.apache.ivy.plugins.repository.Resource;
-import org.apache.ivy.plugins.repository.ResourceDownloader;
-import org.apache.ivy.plugins.resolver.DependencyResolver;
-import org.apache.ivy.plugins.resolver.util.ResolvedResource;
-import org.apache.ivy.util.Message;
-import org.gradle.api.internal.artifacts.ivyservice.CacheLockingManager;
-import org.gradle.api.internal.externalresource.ExternalResource;
-import org.gradle.api.internal.externalresource.cached.CachedExternalResourceIndex;
-import org.gradle.api.internal.externalresource.metadata.ExternalResourceMetaData;
-import org.gradle.api.internal.file.TemporaryFileProvider;
-import org.gradle.api.internal.filestore.FileStore;
-import org.gradle.api.internal.filestore.FileStoreEntry;
-import org.gradle.internal.Factory;
-
-import java.io.File;
-import java.io.IOException;
-import java.text.ParseException;
-
-/**
- * A cache manager for remote repositories, that downloads files and stores them in the FileStore provided.
- */
-public class DownloadingRepositoryCacheManager extends AbstractRepositoryCacheManager {
- private final FileStore<ArtifactRevisionId> fileStore;
- private final CachedExternalResourceIndex<String> artifactUrlCachedResolutionIndex;
- private final TemporaryFileProvider temporaryFileProvider;
- private final CacheLockingManager cacheLockingManager;
-
- public DownloadingRepositoryCacheManager(String name, FileStore<ArtifactRevisionId> fileStore, CachedExternalResourceIndex<String> artifactUrlCachedResolutionIndex,
- TemporaryFileProvider temporaryFileProvider, CacheLockingManager cacheLockingManager) {
- super(name);
- this.fileStore = fileStore;
- this.artifactUrlCachedResolutionIndex = artifactUrlCachedResolutionIndex;
- this.temporaryFileProvider = temporaryFileProvider;
- this.cacheLockingManager = cacheLockingManager;
- }
-
- public EnhancedArtifactDownloadReport download(Artifact artifact, ArtifactResourceResolver resourceResolver,
- ResourceDownloader resourceDownloader, CacheDownloadOptions options) {
- EnhancedArtifactDownloadReport adr = new EnhancedArtifactDownloadReport(artifact);
-
- DownloadListener listener = options.getListener();
- if (listener != null) {
- listener.needArtifact(this, artifact);
- }
-
- long start = System.currentTimeMillis();
- try {
- ResolvedResource artifactRef = resourceResolver.resolve(artifact);
- if (artifactRef != null) {
- final Resource resource = artifactRef.getResource();
- ArtifactOrigin origin = new ArtifactOrigin(artifact, resource.isLocal(), resource.getName());
- if (listener != null) {
- listener.startArtifactDownload(this, artifactRef, artifact, origin);
- }
-
- File artifactFile = downloadArtifactFile(artifact, resourceDownloader, artifactRef);
-
- adr.setDownloadTimeMillis(System.currentTimeMillis() - start);
- adr.setSize(artifactFile.length());
- adr.setDownloadStatus(DownloadStatus.SUCCESSFUL);
- adr.setArtifactOrigin(origin);
- adr.setLocalFile(artifactFile);
- } else {
- adr.setDownloadTimeMillis(System.currentTimeMillis() - start);
- adr.setDownloadStatus(DownloadStatus.FAILED);
- adr.setDownloadDetails(ArtifactDownloadReport.MISSING_ARTIFACT);
- }
- } catch (Throwable throwable) {
- adr.setDownloadTimeMillis(System.currentTimeMillis() - start);
- adr.failed(throwable);
- }
- if (listener != null) {
- listener.endArtifactDownload(this, artifact, adr, adr.getLocalFile());
- }
- return adr;
- }
-
- private File downloadArtifactFile(final Artifact artifact, final ResourceDownloader resourceDownloader, final ResolvedResource artifactRef) throws IOException {
- final Resource resource = artifactRef.getResource();
- final File tmpFile = temporaryFileProvider.createTemporaryFile("gradle_download", "bin");
- try {
- resourceDownloader.download(artifact, resource, tmpFile);
- return cacheLockingManager.useCache(String.format("Store %s", artifact), new Factory<File>() {
- public File create() {
- FileStoreEntry fileStoreEntry = fileStore.move(artifact.getId(), tmpFile);
- File fileInFileStore = fileStoreEntry.getFile();
- if (resource instanceof ExternalResource) {
- ExternalResource externalResource = (ExternalResource) resource;
- ExternalResourceMetaData metaData = externalResource.getMetaData();
- artifactUrlCachedResolutionIndex.store(metaData.getLocation(), fileInFileStore, metaData);
- }
- return fileInFileStore;
- }
- });
- } finally {
- tmpFile.delete();
- }
- }
-
- public ResolvedModuleRevision cacheModuleDescriptor(DependencyResolver resolver, final ResolvedResource resolvedResource, DependencyDescriptor dd, Artifact moduleArtifact, ResourceDownloader downloader, CacheMetadataOptions options) throws ParseException {
- if (!moduleArtifact.isMetadata()) {
- return null;
- }
-
- ArtifactResourceResolver artifactResourceResolver = new ArtifactResourceResolver() {
- public ResolvedResource resolve(Artifact artifact) {
- return resolvedResource;
- }
- };
- ArtifactDownloadReport report = download(moduleArtifact, artifactResourceResolver, downloader, new CacheDownloadOptions().setListener(options.getListener()).setForce(true));
-
- if (report.getDownloadStatus() == DownloadStatus.FAILED) {
- Message.warn("problem while downloading module descriptor: " + resolvedResource.getResource()
- + ": " + report.getDownloadDetails()
- + " (" + report.getDownloadTimeMillis() + "ms)");
- return null;
- }
-
- ModuleDescriptor md = parseModuleDescriptor(resolver, moduleArtifact, options, report.getLocalFile(), resolvedResource.getResource());
- Message.debug("\t" + getName() + ": parsed downloaded md file for " + moduleArtifact.getModuleRevisionId() + "; parsed=" + md.getModuleRevisionId());
-
- MetadataArtifactDownloadReport madr = new MetadataArtifactDownloadReport(md.getMetadataArtifact());
- madr.setSearched(true);
- madr.setDownloadStatus(report.getDownloadStatus());
- madr.setDownloadDetails(report.getDownloadDetails());
- madr.setArtifactOrigin(report.getArtifactOrigin());
- madr.setDownloadTimeMillis(report.getDownloadTimeMillis());
- madr.setOriginalLocalFile(report.getLocalFile());
- madr.setSize(report.getSize());
-
- return new ResolvedModuleRevision(resolver, resolver, md, madr);
- }
-
-}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/cachemanager/EnhancedArtifactDownloadReport.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/cachemanager/EnhancedArtifactDownloadReport.java
deleted file mode 100644
index 3d270bf..0000000
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/cachemanager/EnhancedArtifactDownloadReport.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.artifacts.repositories.cachemanager;
-
-import org.apache.ivy.core.module.descriptor.Artifact;
-import org.apache.ivy.core.report.ArtifactDownloadReport;
-import org.apache.ivy.core.report.DownloadStatus;
-
-public class EnhancedArtifactDownloadReport extends ArtifactDownloadReport {
- private Throwable failure;
-
- public EnhancedArtifactDownloadReport(Artifact artifact) {
- super(artifact);
- }
-
- public Throwable getFailure() {
- return failure;
- }
-
- public void failed(Throwable throwable) {
- setDownloadStatus(DownloadStatus.FAILED);
- setDownloadDetails(throwable.getMessage());
- failure = throwable;
- }
-}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/cachemanager/LocalFileRepositoryArtifactCache.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/cachemanager/LocalFileRepositoryArtifactCache.java
new file mode 100644
index 0000000..f0f39ab
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/cachemanager/LocalFileRepositoryArtifactCache.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.repositories.cachemanager;
+
+import org.apache.ivy.core.module.id.ArtifactRevisionId;
+import org.gradle.api.internal.externalresource.DefaultLocallyAvailableExternalResource;
+import org.gradle.api.internal.externalresource.ExternalResource;
+import org.gradle.api.internal.externalresource.LocallyAvailableExternalResource;
+import org.gradle.internal.resource.local.DefaultLocallyAvailableResource;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * A cache manager for local repositories. Doesn't cache anything, and uses artifacts from their origin.
+ */
+public class LocalFileRepositoryArtifactCache implements RepositoryArtifactCache {
+
+ public boolean isLocal() {
+ return true;
+ }
+
+ public LocallyAvailableExternalResource downloadAndCacheArtifactFile(ArtifactRevisionId artifactId, ExternalResourceDownloader resourceDownloader, ExternalResource resource) throws IOException {
+ // Does not download, copy or cache local files.
+ assert resource.isLocal();
+ File file = new File(resource.getName());
+ assert file.isFile();
+ return new DefaultLocallyAvailableExternalResource(resource.getName(), new DefaultLocallyAvailableResource(file));
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/cachemanager/LocalFileRepositoryCacheManager.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/cachemanager/LocalFileRepositoryCacheManager.java
deleted file mode 100644
index 5ac65cd..0000000
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/cachemanager/LocalFileRepositoryCacheManager.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.artifacts.repositories.cachemanager;
-
-import org.apache.ivy.core.cache.ArtifactOrigin;
-import org.apache.ivy.core.cache.CacheDownloadOptions;
-import org.apache.ivy.core.cache.CacheMetadataOptions;
-import org.apache.ivy.core.module.descriptor.Artifact;
-import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
-import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
-import org.apache.ivy.core.report.ArtifactDownloadReport;
-import org.apache.ivy.core.report.DownloadStatus;
-import org.apache.ivy.core.report.MetadataArtifactDownloadReport;
-import org.apache.ivy.core.resolve.ResolvedModuleRevision;
-import org.apache.ivy.plugins.repository.ArtifactResourceResolver;
-import org.apache.ivy.plugins.repository.ResourceDownloader;
-import org.apache.ivy.plugins.resolver.DependencyResolver;
-import org.apache.ivy.plugins.resolver.util.ResolvedResource;
-
-import java.io.File;
-import java.text.ParseException;
-
-/**
- * A cache manager for local repositories. Doesn't cache anything, and uses artifacts from their origin.
- */
-public class LocalFileRepositoryCacheManager extends AbstractRepositoryCacheManager {
-
- public LocalFileRepositoryCacheManager(String name) {
- super(name);
- }
-
- public EnhancedArtifactDownloadReport download(Artifact artifact, ArtifactResourceResolver resourceResolver, ResourceDownloader resourceDownloader, CacheDownloadOptions options) {
- long start = System.currentTimeMillis();
- EnhancedArtifactDownloadReport report = new EnhancedArtifactDownloadReport(artifact);
- ResolvedResource resolvedResource = resourceResolver.resolve(artifact);
- if (resolvedResource == null) {
- report.setDownloadStatus(DownloadStatus.FAILED);
- report.setDownloadDetails(ArtifactDownloadReport.MISSING_ARTIFACT);
- report.setDownloadTimeMillis(System.currentTimeMillis() - start);
- return report;
- }
- assert resolvedResource.getResource().isLocal();
- File file = new File(resolvedResource.getResource().getName());
- assert file.isFile();
-
- ArtifactOrigin origin = new ArtifactOrigin(artifact, true, file.getAbsolutePath());
- report.setDownloadStatus(DownloadStatus.NO);
- report.setArtifactOrigin(origin);
- report.setSize(file.length());
- report.setLocalFile(file);
- return report;
- }
-
- public ResolvedModuleRevision cacheModuleDescriptor(DependencyResolver resolver, ResolvedResource resolvedResource, DependencyDescriptor dd, Artifact moduleArtifact, ResourceDownloader downloader, CacheMetadataOptions options) throws ParseException {
- if (!moduleArtifact.isMetadata()) {
- return null;
- }
-
- assert resolvedResource.getResource().isLocal();
- File file = new File(resolvedResource.getResource().getName());
- assert file.isFile();
-
- ArtifactOrigin origin = new ArtifactOrigin(moduleArtifact, true, file.getAbsolutePath());
- MetadataArtifactDownloadReport report = new MetadataArtifactDownloadReport(moduleArtifact);
- report.setDownloadStatus(DownloadStatus.NO);
- report.setArtifactOrigin(origin);
- report.setSize(file.length());
- report.setLocalFile(file);
- report.setSearched(false);
- report.setOriginalLocalFile(file);
-
- ModuleDescriptor descriptor = parseModuleDescriptor(resolver, moduleArtifact, options, file, resolvedResource.getResource());
- return new ResolvedModuleRevision(resolver, resolver, descriptor, report);
- }
-}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/cachemanager/RepositoryArtifactCache.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/cachemanager/RepositoryArtifactCache.java
new file mode 100644
index 0000000..6be8069
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/cachemanager/RepositoryArtifactCache.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.repositories.cachemanager;
+
+import org.apache.ivy.core.module.id.ArtifactRevisionId;
+import org.gradle.api.internal.externalresource.ExternalResource;
+import org.gradle.api.internal.externalresource.LocallyAvailableExternalResource;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * This is a transitional interface for moving away from the Ivy RepositoryCacheManager.
+ */
+public interface RepositoryArtifactCache {
+ boolean isLocal();
+
+ /**
+ * Downloads the artifact file, moving it into the correct location in the cache.
+ *
+ * @param artifactId The id of the artifact this resource represents
+ * @param resourceDownloader An action to use for downloading the resource
+ * @param resource The artifact resource
+ * @return The cached resource
+ */
+ LocallyAvailableExternalResource downloadAndCacheArtifactFile(ArtifactRevisionId artifactId, ExternalResourceDownloader resourceDownloader, ExternalResource resource) throws IOException;
+
+ interface ExternalResourceDownloader {
+ public void download(ExternalResource resource, File dest) throws IOException;
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/layout/MavenRepositoryLayout.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/layout/MavenRepositoryLayout.java
index ae57ac4..97156fd 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/layout/MavenRepositoryLayout.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/layout/MavenRepositoryLayout.java
@@ -27,7 +27,7 @@ import java.net.URI;
* <li>Ivy: $baseUri/{@value IvyArtifactRepository#MAVEN_IVY_PATTERN}</li>
* </ul>
*
- * Following the maven convention, the 'organisation' value is further processed by replacing '.' with '/'.
+ * Following the Maven convention, the 'organisation' value is further processed by replacing '.' with '/'.
* Note that the resolver will follow the layout only, but will <em>not</em> use .pom files for meta data. Ivy metadata files are required/published.
*/
public class MavenRepositoryLayout extends RepositoryLayout {
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/legacy/AbstractRepositoryCacheManager.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/legacy/AbstractRepositoryCacheManager.java
new file mode 100644
index 0000000..bbf1446
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/legacy/AbstractRepositoryCacheManager.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.repositories.legacy;
+
+import org.apache.ivy.core.cache.ArtifactOrigin;
+import org.apache.ivy.core.cache.CacheMetadataOptions;
+import org.apache.ivy.core.cache.ModuleDescriptorWriter;
+import org.apache.ivy.core.cache.RepositoryCacheManager;
+import org.apache.ivy.core.module.descriptor.Artifact;
+import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
+import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
+import org.apache.ivy.core.module.id.ModuleRevisionId;
+import org.apache.ivy.core.resolve.ResolvedModuleRevision;
+import org.apache.ivy.core.settings.IvySettings;
+import org.apache.ivy.plugins.parser.ModuleDescriptorParser;
+import org.apache.ivy.plugins.parser.ModuleDescriptorParserRegistry;
+import org.apache.ivy.plugins.parser.ParserSettings;
+import org.apache.ivy.plugins.repository.Resource;
+import org.apache.ivy.plugins.resolver.DependencyResolver;
+import org.apache.ivy.plugins.resolver.util.ResolvedResource;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.IvyContextualiser;
+import org.gradle.internal.UncheckedException;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.text.ParseException;
+
+abstract class AbstractRepositoryCacheManager implements RepositoryCacheManager {
+ protected final String name;
+
+ public AbstractRepositoryCacheManager(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void saveResolvers(ModuleDescriptor descriptor, String metadataResolverName, String artifactResolverName) {
+ }
+
+ public ArtifactOrigin getSavedArtifactOrigin(Artifact artifact) {
+ return null;
+ }
+
+ public ResolvedModuleRevision findModuleInCache(DependencyDescriptor dd, ModuleRevisionId requestedRevisionId, CacheMetadataOptions options, String expectedResolver) {
+ return null;
+ }
+
+ public void originalToCachedModuleDescriptor(DependencyResolver resolver, ResolvedResource originalMetadataRef, Artifact requestedMetadataArtifact, ResolvedModuleRevision rmr, ModuleDescriptorWriter writer) {
+ }
+
+ public void clean() {
+ }
+
+ public void saveResolvedRevision(ModuleRevisionId dynamicMrid, String revision) {
+ }
+
+ protected ModuleDescriptor parseModuleDescriptor(DependencyResolver resolver, Artifact moduleArtifact, CacheMetadataOptions options, File artifactFile, Resource resource) throws ParseException {
+ ModuleRevisionId moduleRevisionId = moduleArtifact.getId().getModuleRevisionId();
+ try {
+ IvySettings ivySettings = IvyContextualiser.getIvyContext().getSettings();
+ ParserSettings parserSettings = new LegacyResolverParserSettings(ivySettings, resolver, moduleRevisionId);
+ ModuleDescriptorParser parser = ModuleDescriptorParserRegistry.getInstance().getParser(resource);
+ return parser.parseDescriptor(parserSettings, new URL(artifactFile.toURI().toASCIIString()), resource, options.isValidate());
+ } catch (IOException e) {
+ throw UncheckedException.throwAsUncheckedException(e);
+ }
+ }
+
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/legacy/CustomIvyResolverRepositoryFactory.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/legacy/CustomIvyResolverRepositoryFactory.java
new file mode 100644
index 0000000..e5b23c4
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/legacy/CustomIvyResolverRepositoryFactory.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.repositories.legacy;
+
+import org.apache.ivy.core.cache.RepositoryCacheManager;
+import org.apache.ivy.plugins.resolver.DependencyResolver;
+import org.gradle.api.artifacts.repositories.ArtifactRepository;
+import org.gradle.api.internal.artifacts.repositories.CustomResolverArtifactRepository;
+import org.gradle.logging.ProgressLoggerFactory;
+
+public class CustomIvyResolverRepositoryFactory implements LegacyDependencyResolverRepositoryFactory {
+ private final ProgressLoggerFactory progressLoggerFactory;
+ private final RepositoryCacheManager localCacheManager;
+ private final RepositoryCacheManager downloadingCacheManager;
+
+ public CustomIvyResolverRepositoryFactory(ProgressLoggerFactory progressLoggerFactory,
+ RepositoryCacheManager localCacheManager,
+ RepositoryCacheManager downloadingCacheManager) {
+ this.progressLoggerFactory = progressLoggerFactory;
+ this.localCacheManager = localCacheManager;
+ this.downloadingCacheManager = downloadingCacheManager;
+ }
+
+ public ArtifactRepository createRepository(DependencyResolver dependencyResolver) {
+ return new CustomResolverArtifactRepository(dependencyResolver, progressLoggerFactory, localCacheManager, downloadingCacheManager);
+ }
+
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/legacy/DownloadingRepositoryCacheManager.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/legacy/DownloadingRepositoryCacheManager.java
new file mode 100644
index 0000000..c5b90a4
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/legacy/DownloadingRepositoryCacheManager.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.repositories.legacy;
+
+import org.apache.ivy.core.cache.ArtifactOrigin;
+import org.apache.ivy.core.cache.CacheDownloadOptions;
+import org.apache.ivy.core.cache.CacheMetadataOptions;
+import org.apache.ivy.core.cache.DownloadListener;
+import org.apache.ivy.core.module.descriptor.Artifact;
+import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
+import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
+import org.apache.ivy.core.module.id.ArtifactRevisionId;
+import org.apache.ivy.core.report.ArtifactDownloadReport;
+import org.apache.ivy.core.report.DownloadStatus;
+import org.apache.ivy.core.report.MetadataArtifactDownloadReport;
+import org.apache.ivy.core.resolve.ResolvedModuleRevision;
+import org.apache.ivy.plugins.repository.ArtifactResourceResolver;
+import org.apache.ivy.plugins.repository.Resource;
+import org.apache.ivy.plugins.repository.ResourceDownloader;
+import org.apache.ivy.plugins.resolver.DependencyResolver;
+import org.apache.ivy.plugins.resolver.util.ResolvedResource;
+import org.gradle.api.internal.artifacts.ivyservice.CacheLockingManager;
+import org.gradle.api.internal.file.TemporaryFileProvider;
+import org.gradle.internal.Factory;
+import org.gradle.internal.filestore.FileStore;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.IOException;
+import java.text.ParseException;
+
+/**
+ * A cache manager for remote repositories, that downloads files and stores them in the FileStore provided.
+ */
+public class DownloadingRepositoryCacheManager extends AbstractRepositoryCacheManager {
+ private static final Logger LOGGER = LoggerFactory.getLogger(DownloadingRepositoryCacheManager.class);
+
+ private final FileStore<ArtifactRevisionId> fileStore;
+ private final TemporaryFileProvider temporaryFileProvider;
+ private final CacheLockingManager cacheLockingManager;
+
+ public DownloadingRepositoryCacheManager(String name, FileStore<ArtifactRevisionId> fileStore,
+ TemporaryFileProvider temporaryFileProvider, CacheLockingManager cacheLockingManager) {
+ super(name);
+ this.fileStore = fileStore;
+ this.temporaryFileProvider = temporaryFileProvider;
+ this.cacheLockingManager = cacheLockingManager;
+ }
+
+ public boolean isLocal() {
+ return false;
+ }
+
+ public EnhancedArtifactDownloadReport download(Artifact artifact, ArtifactResourceResolver resourceResolver,
+ ResourceDownloader resourceDownloader, CacheDownloadOptions options) {
+ EnhancedArtifactDownloadReport adr = new EnhancedArtifactDownloadReport(artifact);
+
+ DownloadListener listener = options.getListener();
+ if (listener != null) {
+ listener.needArtifact(this, artifact);
+ }
+
+ long start = System.currentTimeMillis();
+ try {
+ ResolvedResource artifactRef = resourceResolver.resolve(artifact);
+ if (artifactRef != null) {
+ final Resource resource = artifactRef.getResource();
+ ArtifactOrigin origin = new ArtifactOrigin(artifact, resource.isLocal(), resource.getName());
+ if (listener != null) {
+ listener.startArtifactDownload(this, artifactRef, artifact, origin);
+ }
+
+ File artifactFile = downloadAndCacheArtifactFile(artifact, resourceDownloader, artifactRef.getResource());
+
+ adr.setDownloadTimeMillis(System.currentTimeMillis() - start);
+ adr.setSize(artifactFile.length());
+ adr.setDownloadStatus(DownloadStatus.SUCCESSFUL);
+ adr.setArtifactOrigin(origin);
+ adr.setLocalFile(artifactFile);
+ } else {
+ adr.setDownloadTimeMillis(System.currentTimeMillis() - start);
+ adr.setDownloadStatus(DownloadStatus.FAILED);
+ adr.setDownloadDetails(ArtifactDownloadReport.MISSING_ARTIFACT);
+ }
+ } catch (Throwable throwable) {
+ adr.setDownloadTimeMillis(System.currentTimeMillis() - start);
+ adr.failed(throwable);
+ }
+ if (listener != null) {
+ listener.endArtifactDownload(this, artifact, adr, adr.getLocalFile());
+ }
+ return adr;
+ }
+
+ private File downloadAndCacheArtifactFile(final Artifact artifact, ResourceDownloader resourceDownloader, Resource resource) throws IOException {
+ final File tmpFile = temporaryFileProvider.createTemporaryFile("gradle_download", "bin");
+ try {
+ resourceDownloader.download(artifact, resource, tmpFile);
+ return cacheLockingManager.useCache(String.format("Store %s", artifact), new Factory<File>() {
+ public File create() {
+ return fileStore.move(artifact.getId(), tmpFile).getFile();
+ }
+ });
+ } finally {
+ tmpFile.delete();
+ }
+ }
+
+ public ResolvedModuleRevision cacheModuleDescriptor(DependencyResolver resolver, final ResolvedResource resolvedResource, DependencyDescriptor dd, Artifact moduleArtifact, ResourceDownloader downloader, CacheMetadataOptions options) throws ParseException {
+ if (!moduleArtifact.isMetadata()) {
+ return null;
+ }
+
+ ArtifactResourceResolver artifactResourceResolver = new ArtifactResourceResolver() {
+ public ResolvedResource resolve(Artifact artifact) {
+ return resolvedResource;
+ }
+ };
+ ArtifactDownloadReport report = download(moduleArtifact, artifactResourceResolver, downloader, new CacheDownloadOptions().setListener(options.getListener()).setForce(true));
+
+ if (report.getDownloadStatus() == DownloadStatus.FAILED) {
+ LOGGER.warn("problem while downloading module descriptor: {}: {} ({} ms)", resolvedResource.getResource(), report.getDownloadDetails(), report.getDownloadTimeMillis());
+ return null;
+ }
+
+ ModuleDescriptor md = parseModuleDescriptor(resolver, moduleArtifact, options, report.getLocalFile(), resolvedResource.getResource());
+ LOGGER.debug("\t{}: parsed downloaded md file for {}; parsed={}" + getName(), moduleArtifact.getModuleRevisionId(), md.getModuleRevisionId());
+
+ MetadataArtifactDownloadReport madr = new MetadataArtifactDownloadReport(md.getMetadataArtifact());
+ madr.setSearched(true);
+ madr.setDownloadStatus(report.getDownloadStatus());
+ madr.setDownloadDetails(report.getDownloadDetails());
+ madr.setArtifactOrigin(report.getArtifactOrigin());
+ madr.setDownloadTimeMillis(report.getDownloadTimeMillis());
+ madr.setOriginalLocalFile(report.getLocalFile());
+ madr.setSize(report.getSize());
+
+ return new ResolvedModuleRevision(resolver, resolver, md, madr);
+ }
+
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/legacy/EnhancedArtifactDownloadReport.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/legacy/EnhancedArtifactDownloadReport.java
new file mode 100644
index 0000000..50ff9b9
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/legacy/EnhancedArtifactDownloadReport.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.repositories.legacy;
+
+import org.apache.ivy.core.module.descriptor.Artifact;
+import org.apache.ivy.core.report.ArtifactDownloadReport;
+import org.apache.ivy.core.report.DownloadStatus;
+
+public class EnhancedArtifactDownloadReport extends ArtifactDownloadReport {
+ private Throwable failure;
+
+ public EnhancedArtifactDownloadReport(Artifact artifact) {
+ super(artifact);
+ }
+
+ public Throwable getFailure() {
+ return failure;
+ }
+
+ public void failed(Throwable throwable) {
+ setDownloadStatus(DownloadStatus.FAILED);
+ setDownloadDetails(throwable.getMessage());
+ failure = throwable;
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/legacy/LegacyDependencyResolverRepositoryFactory.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/legacy/LegacyDependencyResolverRepositoryFactory.java
new file mode 100644
index 0000000..9a27910
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/legacy/LegacyDependencyResolverRepositoryFactory.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.repositories.legacy;
+
+import org.apache.ivy.plugins.resolver.DependencyResolver;
+import org.gradle.api.artifacts.repositories.ArtifactRepository;
+
+public interface LegacyDependencyResolverRepositoryFactory {
+ ArtifactRepository createRepository(DependencyResolver dependencyResolver);
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/legacy/LegacyResolverParserSettings.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/legacy/LegacyResolverParserSettings.java
new file mode 100644
index 0000000..8030383
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/legacy/LegacyResolverParserSettings.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.repositories.legacy;
+
+import org.apache.ivy.core.RelativeUrlResolver;
+import org.apache.ivy.core.cache.ResolutionCacheManager;
+import org.apache.ivy.core.module.id.ModuleId;
+import org.apache.ivy.core.module.id.ModuleRevisionId;
+import org.apache.ivy.core.module.status.StatusManager;
+import org.apache.ivy.plugins.conflict.ConflictManager;
+import org.apache.ivy.plugins.matcher.PatternMatcher;
+import org.apache.ivy.plugins.namespace.Namespace;
+import org.apache.ivy.plugins.parser.ParserSettings;
+import org.apache.ivy.plugins.resolver.DependencyResolver;
+
+import java.io.File;
+import java.util.Map;
+
+/**
+ * ParserSettings that control the scope of searches carried out during parsing.
+ * If the parser asks for a resolver for the currently resolving revision, the resolver scope is only the repository where the module was resolved.
+ * If the parser asks for a resolver for a different revision, the resolver scope is all repositories.
+ */
+public class LegacyResolverParserSettings implements ParserSettings {
+ private final ParserSettings settings;
+ private final DependencyResolver currentResolver;
+ private final ModuleRevisionId currentRevisionId;
+
+ public LegacyResolverParserSettings(ParserSettings settings, DependencyResolver currentResolver, ModuleRevisionId currentRevisionId) {
+ this.settings = settings;
+ this.currentResolver = currentResolver;
+ this.currentRevisionId = currentRevisionId;
+ }
+
+ public DependencyResolver getResolver(ModuleRevisionId mRevId) {
+ if (mRevId.equals(currentRevisionId)) {
+ return currentResolver;
+ }
+ return settings.getResolver(mRevId);
+ }
+
+ public ConflictManager getConflictManager(String name) {
+ return settings.getConflictManager(name);
+ }
+
+ public String substitute(String value) {
+ return settings.substitute(value);
+ }
+
+ public Map substitute(Map strings) {
+ return settings.substitute(strings);
+ }
+
+ public ResolutionCacheManager getResolutionCacheManager() {
+ return settings.getResolutionCacheManager();
+ }
+
+ public PatternMatcher getMatcher(String matcherName) {
+ return settings.getMatcher(matcherName);
+ }
+
+ public Namespace getNamespace(String namespace) {
+ return settings.getNamespace(namespace);
+ }
+
+ public StatusManager getStatusManager() {
+ return settings.getStatusManager();
+ }
+
+ public RelativeUrlResolver getRelativeUrlResolver() {
+ return settings.getRelativeUrlResolver();
+ }
+
+ public File resolveFile(String filename) {
+ return settings.resolveFile(filename);
+ }
+
+ public String getDefaultBranch(ModuleId moduleId) {
+ return settings.getDefaultBranch(moduleId);
+ }
+
+ public Namespace getContextNamespace() {
+ return settings.getContextNamespace();
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/legacy/LocalFileRepositoryCacheManager.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/legacy/LocalFileRepositoryCacheManager.java
new file mode 100644
index 0000000..2e1520c
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/legacy/LocalFileRepositoryCacheManager.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.repositories.legacy;
+
+import org.apache.ivy.core.cache.ArtifactOrigin;
+import org.apache.ivy.core.cache.CacheDownloadOptions;
+import org.apache.ivy.core.cache.CacheMetadataOptions;
+import org.apache.ivy.core.module.descriptor.Artifact;
+import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
+import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
+import org.apache.ivy.core.report.ArtifactDownloadReport;
+import org.apache.ivy.core.report.DownloadStatus;
+import org.apache.ivy.core.report.MetadataArtifactDownloadReport;
+import org.apache.ivy.core.resolve.ResolvedModuleRevision;
+import org.apache.ivy.plugins.repository.ArtifactResourceResolver;
+import org.apache.ivy.plugins.repository.ResourceDownloader;
+import org.apache.ivy.plugins.resolver.DependencyResolver;
+import org.apache.ivy.plugins.resolver.util.ResolvedResource;
+
+import java.io.File;
+import java.text.ParseException;
+
+/**
+ * A cache manager for local repositories. Doesn't cache anything, and uses artifacts from their origin.
+ */
+public class LocalFileRepositoryCacheManager extends AbstractRepositoryCacheManager {
+
+ public LocalFileRepositoryCacheManager(String name) {
+ super(name);
+ }
+
+ public EnhancedArtifactDownloadReport download(Artifact artifact, ArtifactResourceResolver resourceResolver, ResourceDownloader resourceDownloader, CacheDownloadOptions options) {
+ ResolvedResource resolvedResource = resourceResolver.resolve(artifact);
+ long start = System.currentTimeMillis();
+ EnhancedArtifactDownloadReport report = new EnhancedArtifactDownloadReport(artifact);
+ if (resolvedResource == null) {
+ report.setDownloadStatus(DownloadStatus.FAILED);
+ report.setDownloadDetails(ArtifactDownloadReport.MISSING_ARTIFACT);
+ report.setDownloadTimeMillis(System.currentTimeMillis() - start);
+ return report;
+ }
+ assert resolvedResource.getResource().isLocal();
+ File file = new File(resolvedResource.getResource().getName());
+ assert file.isFile();
+
+ ArtifactOrigin origin = new ArtifactOrigin(artifact, true, file.getAbsolutePath());
+ report.setDownloadStatus(DownloadStatus.NO);
+ report.setArtifactOrigin(origin);
+ report.setSize(file.length());
+ report.setLocalFile(file);
+ return report;
+ }
+
+ public ResolvedModuleRevision cacheModuleDescriptor(DependencyResolver resolver, ResolvedResource resolvedResource, DependencyDescriptor dd, Artifact moduleArtifact, ResourceDownloader downloader, CacheMetadataOptions options) throws ParseException {
+ if (!moduleArtifact.isMetadata()) {
+ return null;
+ }
+
+ assert resolvedResource.getResource().isLocal();
+ File file = new File(resolvedResource.getResource().getName());
+ assert file.isFile();
+
+ ArtifactOrigin origin = new ArtifactOrigin(moduleArtifact, true, file.getAbsolutePath());
+ MetadataArtifactDownloadReport report = new MetadataArtifactDownloadReport(moduleArtifact);
+ report.setDownloadStatus(DownloadStatus.NO);
+ report.setArtifactOrigin(origin);
+ report.setSize(file.length());
+ report.setLocalFile(file);
+ report.setSearched(false);
+ report.setOriginalLocalFile(file);
+
+ ModuleDescriptor descriptor = parseModuleDescriptor(resolver, moduleArtifact, options, file, resolvedResource.getResource());
+ return new ResolvedModuleRevision(resolver, resolver, descriptor, report);
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/AbstractVersionList.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/AbstractVersionList.java
index 695ecbe..f423aae 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/AbstractVersionList.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/AbstractVersionList.java
@@ -16,48 +16,22 @@
package org.gradle.api.internal.artifacts.repositories.resolver;
-import org.apache.ivy.plugins.latest.ArtifactInfo;
-import org.apache.ivy.plugins.latest.LatestStrategy;
+import com.google.common.collect.Lists;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.LatestStrategy;
-import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
abstract class AbstractVersionList implements VersionList {
public boolean isEmpty() {
- return getVersionStrings().isEmpty();
+ return getVersions().isEmpty();
}
- public List<String> sortLatestFirst(LatestStrategy latestStrategy) {
- List<String> versions = new ArrayList<String>(getVersionStrings());
- ArtifactInfo[] artifactInfos = new ArtifactInfo[versions.size()];
- for (int i = 0; i < versions.size(); i++) {
- String version = versions.get(i);
- artifactInfos[i] = new VersionArtifactInfo(version);
- }
- List<ArtifactInfo> sorted = latestStrategy.sort(artifactInfos);
+ public List<ListedVersion> sortLatestFirst(LatestStrategy latestStrategy) {
+ List<ListedVersion> versions = Lists.newArrayList(getVersions());
+ List<ListedVersion> sorted = latestStrategy.sort(versions);
Collections.reverse(sorted);
- List<String> sortedVersions = new ArrayList<String>();
- for (ArtifactInfo info : sorted) {
- sortedVersions.add(info.getRevision());
- }
- return sortedVersions;
- }
-
- private class VersionArtifactInfo implements ArtifactInfo {
- private final String version;
-
- private VersionArtifactInfo(String version) {
- this.version = version;
- }
-
- public String getRevision() {
- return version;
- }
-
- public long getLastModified() {
- return 0;
- }
+ return sorted;
}
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/ChainedVersionLister.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/ChainedVersionLister.java
index fb1657c..bc4ec85 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/ChainedVersionLister.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/ChainedVersionLister.java
@@ -17,7 +17,7 @@
package org.gradle.api.internal.artifacts.repositories.resolver;
import org.apache.ivy.core.module.descriptor.Artifact;
-import org.apache.ivy.core.module.id.ModuleRevisionId;
+import org.gradle.api.artifacts.ModuleVersionSelector;
import org.gradle.api.internal.resource.ResourceException;
import org.gradle.api.internal.resource.ResourceNotFoundException;
import org.gradle.util.DeprecationLogger;
@@ -35,10 +35,10 @@ public class ChainedVersionLister implements VersionLister {
this.versionListers = Arrays.asList(versionlisters);
}
- public VersionList getVersionList(final ModuleRevisionId moduleRevisionId) {
+ public VersionList getVersionList(final ModuleVersionSelector selector) {
final List<VersionList> versionLists = new ArrayList<VersionList>();
for (VersionLister lister : versionListers) {
- versionLists.add(lister.getVersionList(moduleRevisionId));
+ versionLists.add(lister.getVersionList(selector));
}
return new AbstractVersionList() {
public void visit(ResourcePattern pattern, Artifact artifact) throws ResourceNotFoundException, ResourceException {
@@ -56,21 +56,21 @@ public class ChainedVersionLister implements VersionLister {
if (versionListIterator.hasNext()) {
String deprecationMessage = String.format(
"Error listing versions of %s using %s. Will attempt an alternate way to list versions",
- moduleRevisionId, list.getClass()
+ selector, list.getClass()
);
DeprecationLogger.nagUserOfDeprecatedBehaviour(deprecationMessage);
LOGGER.debug(deprecationMessage, e);
} else {
- throw new ResourceException(String.format("Failed to list versions for %s.", moduleRevisionId), e);
+ throw new ResourceException(String.format("Failed to list versions for %s.", selector), e);
}
}
}
}
- public Set<String> getVersionStrings() {
- Set<String> allVersions = new HashSet<String>();
+ public Set<ListedVersion> getVersions() {
+ Set<ListedVersion> allVersions = new HashSet<ListedVersion>();
for (VersionList versionList : versionLists) {
- allVersions.addAll(versionList.getVersionStrings());
+ allVersions.addAll(versionList.getVersions());
}
return allVersions;
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/ComponentMetadataDetailsAdapter.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/ComponentMetadataDetailsAdapter.java
new file mode 100644
index 0000000..fa65350
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/ComponentMetadataDetailsAdapter.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.repositories.resolver;
+
+import org.gradle.api.artifacts.ComponentMetadataDetails;
+import org.gradle.api.artifacts.ModuleVersionIdentifier;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.MutableModuleVersionMetaData;
+
+import java.util.List;
+
+public class ComponentMetadataDetailsAdapter implements ComponentMetadataDetails {
+ private final MutableModuleVersionMetaData metadata;
+
+ public ComponentMetadataDetailsAdapter(MutableModuleVersionMetaData metadata) {
+ this.metadata = metadata;
+ }
+
+ public ModuleVersionIdentifier getId() {
+ return metadata.getId();
+ }
+
+ public boolean isChanging() {
+ return metadata.isChanging();
+ }
+
+ public String getStatus() {
+ return metadata.getStatus();
+ }
+
+ public List<String> getStatusScheme() {
+ return metadata.getStatusScheme();
+ }
+
+ public void setChanging(boolean changing) {
+ metadata.setChanging(changing);
+ }
+
+ public void setStatus(String status) {
+ metadata.setStatus(status);
+ }
+
+ public void setStatusScheme(List<String> statusScheme) {
+ metadata.setStatusScheme(statusScheme);
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/DefaultVersionList.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/DefaultVersionList.java
index 9eafb22..fdec609 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/DefaultVersionList.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/DefaultVersionList.java
@@ -16,34 +16,33 @@
package org.gradle.api.internal.artifacts.repositories.resolver;
-import com.google.common.collect.Iterables;
import org.apache.ivy.core.module.descriptor.Artifact;
import org.gradle.api.internal.resource.ResourceException;
import org.gradle.api.internal.resource.ResourceNotFoundException;
+import java.util.HashMap;
import java.util.HashSet;
-import java.util.List;
+import java.util.Map;
import java.util.Set;
public class DefaultVersionList extends AbstractVersionList {
- private final Set<String> versions = new HashSet<String>();
-
- public DefaultVersionList(List<String> versionStrings) {
- this.versions.addAll(versionStrings);
- }
+ private final Map<String, ListedVersion> versions = new HashMap<String, ListedVersion>();
public DefaultVersionList() {
}
- protected void add(Iterable<String> versionStrings) {
- Iterables.addAll(versions, versionStrings);
+ protected void add(ListedVersion newVersion) {
+ if (versions.containsKey(newVersion.getVersion())) {
+ return;
+ }
+ versions.put(newVersion.getVersion(), newVersion);
}
public void visit(ResourcePattern pattern, Artifact artifact) throws ResourceNotFoundException, ResourceException {
throw new UnsupportedOperationException();
}
- public Set<String> getVersionStrings() {
- return versions;
+ public Set<ListedVersion> getVersions() {
+ return new HashSet<ListedVersion>(versions.values());
}
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/ExternalResourceResolver.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/ExternalResourceResolver.java
index 3dfdda8..f54fa91 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/ExternalResourceResolver.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/ExternalResourceResolver.java
@@ -16,48 +16,31 @@
package org.gradle.api.internal.artifacts.repositories.resolver;
+import com.google.common.base.Joiner;
import org.apache.ivy.core.cache.ArtifactOrigin;
-import org.apache.ivy.core.cache.CacheDownloadOptions;
-import org.apache.ivy.core.cache.CacheMetadataOptions;
-import org.apache.ivy.core.cache.RepositoryCacheManager;
import org.apache.ivy.core.module.descriptor.*;
import org.apache.ivy.core.module.id.ArtifactRevisionId;
-import org.apache.ivy.core.module.id.ModuleId;
import org.apache.ivy.core.module.id.ModuleRevisionId;
-import org.apache.ivy.core.report.ArtifactDownloadReport;
-import org.apache.ivy.core.report.DownloadReport;
-import org.apache.ivy.core.report.DownloadStatus;
-import org.apache.ivy.core.report.MetadataArtifactDownloadReport;
-import org.apache.ivy.core.resolve.DownloadOptions;
-import org.apache.ivy.core.resolve.ResolveData;
-import org.apache.ivy.core.resolve.ResolvedModuleRevision;
-import org.apache.ivy.core.search.ModuleEntry;
-import org.apache.ivy.core.search.OrganisationEntry;
-import org.apache.ivy.core.search.RevisionEntry;
-import org.apache.ivy.plugins.latest.LatestStrategy;
+import org.apache.ivy.core.settings.IvySettings;
import org.apache.ivy.plugins.matcher.PatternMatcher;
-import org.apache.ivy.plugins.namespace.Namespace;
-import org.apache.ivy.plugins.parser.ModuleDescriptorParser;
-import org.apache.ivy.plugins.parser.ModuleDescriptorParserRegistry;
-import org.apache.ivy.plugins.repository.ArtifactResourceResolver;
-import org.apache.ivy.plugins.repository.Resource;
-import org.apache.ivy.plugins.repository.ResourceDownloader;
-import org.apache.ivy.plugins.resolver.BasicResolver;
-import org.apache.ivy.plugins.resolver.DependencyResolver;
-import org.apache.ivy.plugins.resolver.ResolverSettings;
-import org.apache.ivy.plugins.resolver.util.MDResolvedResource;
-import org.apache.ivy.plugins.resolver.util.ResolvedResource;
-import org.apache.ivy.plugins.resolver.util.ResourceMDParser;
-import org.apache.ivy.plugins.version.VersionMatcher;
import org.apache.ivy.util.ChecksumHelper;
-import org.apache.ivy.util.Message;
+import org.gradle.api.artifacts.ArtifactIdentifier;
+import org.gradle.api.artifacts.ModuleVersionSelector;
+import org.gradle.api.internal.artifacts.*;
import org.gradle.api.internal.artifacts.ivyservice.BuildableArtifactResolveResult;
+import org.gradle.api.internal.artifacts.ivyservice.DependencyToModuleVersionResolver;
+import org.gradle.api.internal.artifacts.ivyservice.IvyUtil;
import org.gradle.api.internal.artifacts.ivyservice.ModuleVersionResolveException;
-import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ArtifactResolveException;
-import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.BuildableModuleVersionMetaData;
-import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ModuleSource;
-import org.gradle.api.internal.artifacts.repositories.cachemanager.EnhancedArtifactDownloadReport;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.*;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.MetaDataParseException;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.MetaDataParser;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.ModuleDescriptorAdapter;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.LatestStrategy;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.ResolverStrategy;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.VersionMatcher;
+import org.gradle.api.internal.artifacts.repositories.cachemanager.RepositoryArtifactCache;
import org.gradle.api.internal.externalresource.ExternalResource;
+import org.gradle.api.internal.externalresource.LocallyAvailableExternalResource;
import org.gradle.api.internal.externalresource.MetaDataOnlyExternalResource;
import org.gradle.api.internal.externalresource.MissingExternalResource;
import org.gradle.api.internal.externalresource.local.LocallyAvailableResourceCandidates;
@@ -65,58 +48,72 @@ import org.gradle.api.internal.externalresource.local.LocallyAvailableResourceFi
import org.gradle.api.internal.externalresource.metadata.ExternalResourceMetaData;
import org.gradle.api.internal.externalresource.transport.ExternalResourceRepository;
import org.gradle.api.internal.resource.ResourceNotFoundException;
+import org.gradle.internal.SystemProperties;
import org.gradle.util.GFileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
-import java.text.ParseException;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
-public class ExternalResourceResolver implements DependencyResolver {
+import static org.gradle.api.internal.artifacts.repositories.cachemanager.RepositoryArtifactCache.ExternalResourceDownloader;
+
+public class ExternalResourceResolver implements ModuleVersionPublisher, ConfiguredModuleVersionRepository {
private static final Logger LOGGER = LoggerFactory.getLogger(ExternalResourceResolver.class);
+ private final MetaDataParser metaDataParser;
+ private final ModuleMetadataProcessor metadataProcessor;
+
private List<String> ivyPatterns = new ArrayList<String>();
private List<String> artifactPatterns = new ArrayList<String>();
- private boolean m2compatible;
- private boolean checkconsistency = true;
- private boolean allownomd = true;
+ private boolean m2Compatible;
+ private boolean checkConsistency = true;
+ private boolean allowMissingDescriptor = true;
private boolean force;
private String checksums;
private String name;
- private ResolverSettings settings;
- private LatestStrategy latestStrategy;
- private String latestStrategyName;
- private String cacheManagerName;
- private RepositoryCacheManager repositoryCacheManager;
+ private RepositoryArtifactCache repositoryCacheManager;
private String changingMatcherName;
private String changingPattern;
- private Boolean checkmodified;
+ private DependencyToModuleVersionResolver nestedResolver;
private final ExternalResourceRepository repository;
private final LocallyAvailableResourceFinder<ArtifactRevisionId> locallyAvailableResourceFinder;
+ private final LatestStrategy latestStrategy;
+ private final VersionMatcher versionMatcher;
+
protected VersionLister versionLister;
- private ArtifactResourceResolver artifactResourceResolver = new ArtifactResourceResolver() {
- public ResolvedResource resolve(Artifact artifact) {
- return getArtifactRef(artifact, null);
- }
- };
- private final ResourceDownloader resourceDownloader = new ResourceDownloader() {
- public void download(Artifact artifact, Resource resource, File dest) throws IOException {
- getAndCheck(resource, dest);
+
+ // TODO:DAZ Get rid of this
+ private final ExternalResourceDownloader resourceDownloader = new ExternalResourceDownloader() {
+ public void download(ExternalResource resource, File dest) throws IOException {
+ get(resource, dest);
+ verifyChecksums(resource, dest);
}
};
public ExternalResourceResolver(String name,
ExternalResourceRepository repository,
VersionLister versionLister,
- LocallyAvailableResourceFinder<ArtifactRevisionId> locallyAvailableResourceFinder
- ) {
+ LocallyAvailableResourceFinder<ArtifactRevisionId> locallyAvailableResourceFinder,
+ MetaDataParser metaDataParser, ModuleMetadataProcessor metadataProcessor) {
this.name = name;
this.versionLister = versionLister;
this.repository = repository;
this.locallyAvailableResourceFinder = locallyAvailableResourceFinder;
+ this.metaDataParser = metaDataParser;
+ this.metadataProcessor = metadataProcessor;
+
+ latestStrategy = ResolverStrategy.INSTANCE.getLatestStrategy();
+ versionMatcher = ResolverStrategy.INSTANCE.getVersionMatcher();
+ }
+
+ public String getId() {
+ return DependencyResolverIdentifier.forExternalResourceResolver(this);
}
public String getName() {
@@ -127,367 +124,267 @@ public class ExternalResourceResolver implements DependencyResolver {
this.name = name;
}
- public String toString() {
- return getName();
+ public boolean isDynamicResolveMode() {
+ return false;
}
- public void setSettings(ResolverSettings ivy) {
- this.settings = ivy;
+ public String toString() {
+ return String.format("Repository '%s'", getName());
}
- public ResolverSettings getSettings() {
- return settings;
+ public void setResolver(DependencyToModuleVersionResolver resolver) {
+ this.nestedResolver = resolver;
}
protected ExternalResourceRepository getRepository() {
return repository;
}
- public ResolvedModuleRevision getDependency(DependencyDescriptor dd, ResolveData data) throws ParseException {
- // This is not used
- throw new UnsupportedOperationException();
+ public boolean isLocal() {
+ return repositoryCacheManager.isLocal();
}
- public void getDependency(DependencyDescriptor dependencyDescriptor, BuildableModuleVersionMetaData result) {
- ModuleRevisionId nsMrid = dependencyDescriptor.getDependencyRevisionId();
+ public void getDependency(DependencyMetaData dependency, BuildableModuleVersionMetaDataResolveResult result) {
+ getDependency(dependency.getDescriptor(), result);
+ }
- boolean isDynamic = getVersionMatcher().isDynamic(nsMrid);
+ protected void getDependency(DependencyDescriptor dependencyDescriptor, BuildableModuleVersionMetaDataResolveResult result) {
+ ModuleRevisionId moduleRevisionId = dependencyDescriptor.getDependencyRevisionId();
+ boolean isDynamic = versionMatcher.isDynamic(moduleRevisionId.getRevision());
- ResolvedResource ivyRef = findIvyFileRef(dependencyDescriptor);
+ ResolvedArtifact ivyRef = findIvyFileRef(dependencyDescriptor);
// get module descriptor
- ModuleDescriptor nsMd;
if (ivyRef == null) {
if (!isAllownomd()) {
- LOGGER.debug("No ivy file found for module '{}' in repository '{}'.", nsMrid, getName());
+ LOGGER.debug("No ivy file found for module '{}' in repository '{}'.", moduleRevisionId, getName());
result.missing();
return;
}
- nsMd = DefaultModuleDescriptor.newDefaultInstance(nsMrid, dependencyDescriptor.getAllDependencyArtifacts());
- ResolvedResource artifactRef = findFirstArtifactRef(nsMd);
+ DefaultModuleDescriptor generatedModuleDescriptor = DefaultModuleDescriptor.newDefaultInstance(moduleRevisionId, dependencyDescriptor.getAllDependencyArtifacts());
+ ResolvedArtifact artifactRef = findAnyArtifact(generatedModuleDescriptor);
if (artifactRef == null) {
- LOGGER.debug("No ivy file nor artifact found for module '{}' in repository '{}'.", nsMrid, getName());
+ LOGGER.debug("No ivy file nor artifact found for module '{}' in repository '{}'.", moduleRevisionId, getName());
result.missing();
} else {
- long lastModified = artifactRef.getLastModified();
- if (lastModified != 0 && nsMd instanceof DefaultModuleDescriptor) {
- ((DefaultModuleDescriptor) nsMd).setLastModified(lastModified);
+ long lastModified = artifactRef.resource.getLastModified();
+ if (lastModified != 0) {
+ generatedModuleDescriptor.setLastModified(lastModified);
}
- LOGGER.debug("No ivy file found for module '{}' in repository '{}', using default data instead.", nsMrid, getName());
+ LOGGER.debug("No ivy file found for module '{}' in repository '{}', using default data instead.", moduleRevisionId, getName());
if (isDynamic) {
- nsMd.setResolvedModuleRevisionId(ModuleRevisionId.newInstance(nsMrid, artifactRef.getRevision()));
+ generatedModuleDescriptor.setResolvedModuleRevisionId(artifactRef.artifact.getModuleRevisionId());
}
- result.resolved(nsMd, isChanging(nsMd), null);
+ result.resolved(generatedModuleDescriptor, isChanging(generatedModuleDescriptor), null);
}
} else {
try {
- ResolvedModuleRevision rmr = null;
- if (ivyRef instanceof MDResolvedResource) {
- rmr = ((MDResolvedResource) ivyRef).getResolvedModuleRevision();
- }
- if (rmr == null) {
- rmr = parse(ivyRef, dependencyDescriptor);
+ ModuleVersionMetaData moduleVersionMetaData;
+ if (ivyRef instanceof DownloadedAndParsedMetaDataArtifact) {
+ moduleVersionMetaData = ((DownloadedAndParsedMetaDataArtifact) ivyRef).moduleVersionMetaData;
+ } else {
+ moduleVersionMetaData = getArtifactMetadata(ivyRef.artifact, ivyRef.resource);
}
- nsMd = rmr.getDescriptor();
-
- // check descriptor data is in sync with resource revision and names
if (isCheckconsistency()) {
- checkDescriptorConsistency(nsMrid, nsMd, ivyRef);
+ checkMetadataConsistency(DefaultModuleVersionSelector.newSelector(moduleRevisionId), moduleVersionMetaData, ivyRef);
}
- LOGGER.debug("Ivy file found for module '{}' in repository '{}'.", nsMrid, getName());
- result.resolved(nsMd, isChanging(nsMd), null);
- } catch (ParseException e) {
- result.failed(new ModuleVersionResolveException(nsMrid, e));
+ LOGGER.debug("Ivy file found for module '{}' in repository '{}'.", moduleRevisionId, getName());
+ result.resolved(moduleVersionMetaData.getDescriptor(), isChanging(moduleVersionMetaData.getDescriptor()), null);
+ } catch (MetaDataParseException e) {
+ result.failed(new ModuleVersionResolveException(moduleRevisionId, e));
}
}
}
- protected VersionMatcher getVersionMatcher() {
- return getSettings().getVersionMatcher();
+ private MutableModuleVersionMetaData getArtifactMetadata(Artifact artifact, ExternalResource resource) {
+ MutableModuleVersionMetaData metadata = doGetArtifactMetadata(artifact, resource);
+ metadataProcessor.process(metadata);
+ return metadata;
}
- private ResolvedModuleRevision parse(final ResolvedResource mdRef, DependencyDescriptor dd) throws ParseException {
- //TODO: check why we don't use our own ParserRegistry here.
- ModuleRevisionId mrid = dd.getDependencyRevisionId();
- ModuleDescriptorParser parser = ModuleDescriptorParserRegistry.getInstance().getParser(mdRef.getResource());
- if (parser == null) {
- throw new RuntimeException("no module descriptor parser available for " + mdRef.getResource());
- }
-
- ModuleRevisionId resolvedMrid = mrid;
-
- // first check if this dependency has not yet been resolved
- if (getVersionMatcher().isDynamic(mrid)) {
- resolvedMrid = ModuleRevisionId.newInstance(mrid, mdRef.getRevision());
- }
-
- Artifact moduleArtifact = parser.getMetadataArtifact(resolvedMrid, mdRef.getResource());
- return getRepositoryCacheManager().cacheModuleDescriptor(this, mdRef, dd, moduleArtifact, resourceDownloader, new CacheMetadataOptions());
- }
-
- private void checkDescriptorConsistency(ModuleRevisionId mrid, ModuleDescriptor md,
- ResolvedResource ivyRef) throws ParseException {
- boolean ok = true;
- StringBuilder errors = new StringBuilder();
- if (!mrid.getOrganisation().equals(md.getModuleRevisionId().getOrganisation())) {
- Message.error("\t" + getName() + ": bad organisation found in " + ivyRef.getResource()
- + ": expected='" + mrid.getOrganisation() + "' found='"
- + md.getModuleRevisionId().getOrganisation() + "'");
- errors.append("bad organisation: expected='" + mrid.getOrganisation() + "' found='"
- + md.getModuleRevisionId().getOrganisation() + "'; ");
- ok = false;
- }
- if (!mrid.getName().equals(md.getModuleRevisionId().getName())) {
- Message.error("\t" + getName() + ": bad module name found in " + ivyRef.getResource()
- + ": expected='" + mrid.getName() + " found='"
- + md.getModuleRevisionId().getName() + "'");
- errors.append("bad module name: expected='" + mrid.getName() + "' found='"
- + md.getModuleRevisionId().getName() + "'; ");
- ok = false;
- }
- if (mrid.getBranch() != null
- && !mrid.getBranch().equals(md.getModuleRevisionId().getBranch())) {
- Message.error("\t" + getName() + ": bad branch name found in " + ivyRef.getResource()
- + ": expected='" + mrid.getBranch() + " found='"
- + md.getModuleRevisionId().getBranch() + "'");
- errors.append("bad branch name: expected='" + mrid.getBranch() + "' found='"
- + md.getModuleRevisionId().getBranch() + "'; ");
- ok = false;
- }
- if (ivyRef.getRevision() != null && !ivyRef.getRevision().startsWith("working@")) {
- ModuleRevisionId expectedMrid = ModuleRevisionId
- .newInstance(mrid, ivyRef.getRevision());
- if (!getVersionMatcher().accept(expectedMrid, md)) {
- Message.error("\t" + getName() + ": bad revision found in " + ivyRef.getResource()
- + ": expected='" + ivyRef.getRevision() + " found='"
- + md.getModuleRevisionId().getRevision() + "'");
- errors.append("bad revision: expected='" + ivyRef.getRevision() + "' found='"
- + md.getModuleRevisionId().getRevision() + "'; ");
- ok = false;
+ private MutableModuleVersionMetaData doGetArtifactMetadata(Artifact artifact, ExternalResource resource) {
+ if (artifact.isMetadata()) {
+ ModuleRevisionId dependencyRevisionId = artifact.getId().getModuleRevisionId();
+ LocallyAvailableExternalResource cachedResource;
+ try {
+ cachedResource = repositoryCacheManager.downloadAndCacheArtifactFile(artifact.getId(), resourceDownloader, resource);
+ } catch (IOException e) {
+ // TODO:DAZ Work out if/when/why this happens
+ LOGGER.warn("Problem while downloading module descriptor: {}: {}", resource, e.getMessage());
+ return null;
}
- }
- if (!getSettings().getStatusManager().isStatus(md.getStatus())) {
- Message.error("\t" + getName() + ": bad status found in " + ivyRef.getResource()
- + ": '" + md.getStatus() + "'");
- errors.append("bad status: '" + md.getStatus() + "'; ");
- ok = false;
- }
- if (!ok) {
- throw new ParseException("inconsistent module descriptor file found in '"
- + ivyRef.getResource() + "': " + errors, 0);
+
+ return metaDataParser.parseModuleMetaData(cachedResource, new ExternalResourceResolverDescriptorParseContext(nestedResolver, this, dependencyRevisionId));
+ } else {
+ // Create dummy metadata where no metadata artifact exists
+ DefaultModuleDescriptor md = DefaultModuleDescriptor.newDefaultInstance(artifact.getModuleRevisionId());
+ md.setStatus("integration");
+ return new ModuleDescriptorAdapter(artifact.getModuleRevisionId(), md);
}
}
- public ResolvedResource findIvyFileRef(DependencyDescriptor dd, ResolveData data) {
- // This is not used
- throw new UnsupportedOperationException();
+ private void checkMetadataConsistency(ModuleVersionSelector selector, ModuleVersionMetaData metadata,
+ ResolvedArtifact ivyRef) throws MetaDataParseException {
+ List<String> errors = new ArrayList<String>();
+ if (!selector.getGroup().equals(metadata.getId().getGroup())) {
+ errors.add("bad group: expected='" + selector.getGroup() + "' found='" + metadata.getId().getGroup() + "'");
+ }
+ if (!selector.getName().equals(metadata.getId().getName())) {
+ errors.add("bad module name: expected='" + selector.getName() + "' found='" + metadata.getId().getName() + "'");
+ }
+ String revision = ivyRef.artifact.getModuleRevisionId().getRevision();
+ if (revision != null && !revision.startsWith("working@")) {
+ if (!versionMatcher.accept(revision, metadata)) {
+ errors.add("bad version: expected='" + revision + "' found='" + metadata.getId().getVersion() + "'");
+ }
+ }
+ if (!metadata.getStatusScheme().contains(metadata.getStatus())) {
+ errors.add("bad status: '" + metadata.getStatus() + "'; ");
+ }
+ if (errors.size() > 0) {
+ throw new MetaDataParseException(String.format("inconsistent module metadata found. Descriptor: %s Errors: %s",
+ ivyRef.resource, Joiner.on(SystemProperties.getLineSeparator()).join(errors)));
+ }
}
- public ResolvedResource findIvyFileRef(DependencyDescriptor dd) {
+ protected ResolvedArtifact findIvyFileRef(DependencyDescriptor dd) {
ModuleRevisionId mrid = dd.getDependencyRevisionId();
Artifact artifact = DefaultArtifact.newIvyArtifact(mrid, null);
- return findResourceUsingPatterns(mrid, ivyPatterns, artifact, getRMDParser(dd), null, true);
+ return findResourceUsingPatterns(DefaultModuleVersionSelector.newSelector(mrid), ivyPatterns, artifact, true);
}
- protected ResolvedResource findFirstArtifactRef(ModuleDescriptor md) {
- for (String configuration : md.getConfigurationsNames()) {
- for (Artifact artifact : md.getArtifacts(configuration)) {
- ResolvedResource artifactRef = getArtifactRef(artifact, null, false);
- if (artifactRef != null) {
- return artifactRef;
- }
+ private ResolvedArtifact findAnyArtifact(ModuleDescriptor md) {
+ for (Artifact artifact : md.getAllArtifacts()) {
+ ResolvedArtifact artifactRef = getArtifactRef(artifact, false);
+ if (artifactRef != null) {
+ return artifactRef;
}
}
return null;
}
- public boolean exists(Artifact artifact) {
- // This is never used
- throw new UnsupportedOperationException();
- }
-
public ArtifactOrigin locate(Artifact artifact) {
- ResolvedResource artifactRef = getArtifactRef(artifact, null, false);
- if (artifactRef != null && artifactRef.getResource().exists()) {
- final Resource resource = artifactRef.getResource();
+ ResolvedArtifact artifactRef = getArtifactRef(artifact, false);
+ if (artifactRef != null && artifactRef.resource.exists()) {
+ ExternalResource resource = artifactRef.resource;
return new ArtifactOrigin(artifact, resource.isLocal(), resource.getName());
}
return null;
}
- protected ResolvedResource getArtifactRef(Artifact artifact, Date date) {
- return getArtifactRef(artifact, date, true);
+ private ResolvedArtifact getArtifactRef(Artifact artifact, boolean forDownload) {
+ ModuleVersionSelector selector = DefaultModuleVersionSelector.newSelector(artifact.getModuleRevisionId());
+ return findResourceUsingPatterns(selector, getArtifactPatterns(), artifact, forDownload);
}
- protected ResolvedResource getArtifactRef(Artifact artifact, Date date, boolean forDownload) {
- ModuleRevisionId moduleRevisionId = artifact.getModuleRevisionId();
- ResourceMDParser parser = getDefaultRMDParser(artifact.getModuleRevisionId().getModuleId());
- return findResourceUsingPatterns(moduleRevisionId, getArtifactPatterns(), artifact, parser, date, forDownload);
+ protected ResolvedArtifact findResourceUsingPatterns(ModuleVersionSelector selector, List<String> patternList, Artifact artifact, boolean forDownload) {
+ if (versionMatcher.isDynamic(selector.getVersion())) {
+ return findDynamicResourceUsingPatterns(selector, patternList, artifact, forDownload);
+ } else {
+ return findStaticResourceUsingPatterns(selector, patternList, artifact, forDownload);
+ }
}
- protected ResourceMDParser getRMDParser(final DependencyDescriptor dd) {
- return new ResourceMDParser() {
- public MDResolvedResource parse(Resource resource, String rev) {
- try {
- ResolvedModuleRevision rmr = ExternalResourceResolver.this.parse(new ResolvedResource(resource, rev), dd);
- if (rmr == null) {
- return null;
- } else {
- return new MDResolvedResource(resource, rev, rmr);
- }
- } catch (ParseException e) {
- Message.warn("Failed to parse the file '" + resource + "': "
- + e.getMessage());
- return null;
- }
+ private ResolvedArtifact findStaticResourceUsingPatterns(ModuleVersionSelector selector, List<String> patternList, Artifact artifact, boolean forDownload) {
+ // Static version, return first found
+ for (String pattern : patternList) {
+ ResourcePattern resourcePattern = toResourcePattern(pattern);
+ String resourceName = resourcePattern.toPath(artifact);
+ LOGGER.debug("Loading {}", resourceName);
+ ExternalResource resource = getResource(resourceName, artifact.getId(), forDownload);
+ if (resource.exists()) {
+ return new ResolvedArtifact(resource, artifact);
+ } else {
+ LOGGER.debug("Resource not reachable for {}: res={}", selector, resource);
}
-
- };
+ }
+ return null;
}
- protected ResourceMDParser getDefaultRMDParser(final ModuleId mid) {
- return new ResourceMDParser() {
- public MDResolvedResource parse(Resource resource, String rev) {
- DefaultModuleDescriptor md = DefaultModuleDescriptor.newDefaultInstance(new ModuleRevisionId(mid, rev));
- md.setStatus("integration");
- MetadataArtifactDownloadReport madr = new MetadataArtifactDownloadReport(md.getMetadataArtifact());
- madr.setDownloadStatus(DownloadStatus.NO);
- madr.setSearched(true);
- return new MDResolvedResource(resource, rev, new ResolvedModuleRevision(ExternalResourceResolver.this, ExternalResourceResolver.this, md, madr, isForce()));
- }
- };
+ private ResolvedArtifact findDynamicResourceUsingPatterns(ModuleVersionSelector selector, List<String> patternList, Artifact artifact, boolean forDownload) {
+ // Dynamic version: list all, then choose latest
+ VersionList versionList = listVersionsForAllPatterns(selector, patternList, artifact);
+ return findLatestResource(selector, versionList, artifact, forDownload);
}
- protected ResolvedResource findResourceUsingPatterns(ModuleRevisionId moduleRevision, List<String> patternList, Artifact artifact, ResourceMDParser rmdparser, Date date, boolean forDownload) {
- List<ResolvedResource> resolvedResources = new ArrayList<ResolvedResource>();
- Set<String> foundRevisions = new HashSet<String>();
- boolean dynamic = getVersionMatcher().isDynamic(moduleRevision);
+ private VersionList listVersionsForAllPatterns(ModuleVersionSelector selector, List<String> patternList, Artifact artifact) {
+ VersionList versionList = versionLister.getVersionList(selector);
for (String pattern : patternList) {
ResourcePattern resourcePattern = toResourcePattern(pattern);
- ResolvedResource rres = findResourceUsingPattern(moduleRevision, resourcePattern, artifact, rmdparser, date, forDownload);
- if ((rres != null) && !foundRevisions.contains(rres.getRevision())) {
- // only add the first found ResolvedResource for each revision
- foundRevisions.add(rres.getRevision());
- resolvedResources.add(rres);
- if (!dynamic) {
- break;
- }
- }
- }
-
- if (resolvedResources.size() > 1) {
- ResolvedResource[] rress = resolvedResources.toArray(new ResolvedResource[resolvedResources.size()]);
- List<ResolvedResource> sortedResources = getLatestStrategy().sort(rress);
- // Discard all but the last, which is returned
- for (int i = 0; i < sortedResources.size() - 1; i++) {
- ResolvedResource resolvedResource = sortedResources.get(i);
- discardResource(resolvedResource.getResource());
+ try {
+ versionList.visit(resourcePattern, artifact);
+ } catch (ResourceNotFoundException e) {
+ LOGGER.debug(String.format("Unable to load version list for %s from %s", selector, getRepository()));
+ // Don't add any versions
+ // TODO:DAZ Should fail?
}
- return sortedResources.get(sortedResources.size() - 1);
- } else if (resolvedResources.size() == 1) {
- return resolvedResources.get(0);
- } else {
- return null;
}
+ return versionList;
}
- public ResolvedResource findLatestResource(ModuleRevisionId mrid, VersionList versions, ResourceMDParser rmdparser, Date date, ResourcePattern pattern, Artifact artifact, boolean forDownload) {
+ private ResolvedArtifact findLatestResource(ModuleVersionSelector selector, VersionList versions, Artifact artifact, boolean forDownload) {
+ String requestedVersion = selector.getVersion();
String name = getName();
- VersionMatcher versionMatcher = getVersionMatcher();
- List<String> sorted = versions.sortLatestFirst(getLatestStrategy());
- for (String version : sorted) {
- ModuleRevisionId foundMrid = ModuleRevisionId.newInstance(mrid, version);
- if (!versionMatcher.accept(mrid, foundMrid)) {
- LOGGER.debug(name + ": rejected by version matcher: " + version);
+ for (VersionList.ListedVersion listedVersion : versions.sortLatestFirst(latestStrategy)) {
+ String foundVersion = listedVersion.getVersion();
+
+ boolean needsMetadata = versionMatcher.needModuleMetadata(requestedVersion, foundVersion);
+ if (!needsMetadata && !versionMatcher.accept(requestedVersion, foundVersion)) {
+ LOGGER.debug(name + ": rejected by version matcher: " + foundVersion);
continue;
}
- boolean needsModuleDescriptor = versionMatcher.needModuleDescriptor(mrid, foundMrid);
- artifact = DefaultArtifact.cloneWithAnotherMrid(artifact, foundMrid);
- String resourcePath = pattern.toPath(artifact);
- Resource resource = getResource(resourcePath, artifact, forDownload || needsModuleDescriptor);
- String description = version + " [" + resource + "]";
+ ModuleRevisionId revision = IvyUtil.createModuleRevisionId(selector.getGroup(), selector.getName(), foundVersion, null);
+ artifact = DefaultArtifact.cloneWithAnotherMrid(artifact, revision);
+ String resourcePath = listedVersion.getPattern().toPath(artifact);
+ ExternalResource resource = getResource(resourcePath, artifact.getId(), forDownload || needsMetadata);
+ String description = foundVersion + " [" + resource + "]";
if (!resource.exists()) {
LOGGER.debug(name + ": unreachable: " + description);
discardResource(resource);
continue;
}
- if (date != null && resource.getLastModified() > date.getTime()) {
- LOGGER.debug(name + ": too young: " + description);
- discardResource(resource);
- continue;
- }
- if (versionMatcher.needModuleDescriptor(mrid, foundMrid)) {
- MDResolvedResource parsedResource = rmdparser.parse(resource, version);
- if (parsedResource == null) {
+ if (needsMetadata) {
+ MutableModuleVersionMetaData metaData = getArtifactMetadata(artifact, resource);
+ if (metaData == null) {
LOGGER.debug(name + ": impossible to get module descriptor resource: " + description);
discardResource(resource);
continue;
}
- ModuleDescriptor md = parsedResource.getResolvedModuleRevision().getDescriptor();
- if (!versionMatcher.accept(mrid, md)) {
+ if (!versionMatcher.accept(requestedVersion, metaData)) {
LOGGER.debug(name + ": md rejected by version matcher: " + description);
discardResource(resource);
continue;
}
- return parsedResource;
+ return new DownloadedAndParsedMetaDataArtifact(resource, artifact, metaData);
}
- return new ResolvedResource(resource, version);
+ return new ResolvedArtifact(resource, artifact);
}
return null;
}
- protected ResolvedResource findResourceUsingPattern(ModuleRevisionId moduleRevisionId, ResourcePattern pattern, Artifact artifact, ResourceMDParser resourceParser, Date date, boolean forDownload) {
- VersionMatcher versionMatcher = getVersionMatcher();
- if (!versionMatcher.isDynamic(moduleRevisionId)) {
- return findStaticResourceUsingPattern(moduleRevisionId, pattern, artifact, forDownload);
- } else {
- return findDynamicResourceUsingPattern(resourceParser, moduleRevisionId, pattern, artifact, date, forDownload);
- }
- }
-
- private ResolvedResource findStaticResourceUsingPattern(ModuleRevisionId moduleRevisionId, ResourcePattern pattern, Artifact artifact, boolean forDownload) {
- String resourceName = pattern.toPath(artifact);
- LOGGER.debug("Loading {}", resourceName);
- Resource res = getResource(resourceName, artifact, forDownload);
- if (res.exists()) {
- String revision = moduleRevisionId.getRevision();
- return new ResolvedResource(res, revision);
- } else {
- LOGGER.debug("Resource not reachable for {}: res={}", moduleRevisionId, res);
- return null;
- }
- }
-
- private ResolvedResource findDynamicResourceUsingPattern(ResourceMDParser resourceParser, ModuleRevisionId moduleRevisionId, ResourcePattern pattern, Artifact artifact, Date date, boolean forDownload) {
- VersionList versions = listVersions(moduleRevisionId, pattern, artifact);
- ResolvedResource found = findLatestResource(moduleRevisionId, versions, resourceParser, date, pattern, artifact, forDownload);
- if (found == null) {
- LOGGER.debug("No resource found for {}: pattern={}", moduleRevisionId, pattern);
+ protected void discardResource(ExternalResource resource) {
+ try {
+ resource.close();
+ } catch (IOException e) {
+ LOGGER.warn("Exception closing resource " + resource.getName(), e);
}
- return found;
}
- protected void discardResource(Resource resource) {
- if (resource instanceof ExternalResource) {
- try {
- ((ExternalResource) resource).close();
- } catch (IOException e) {
- LOGGER.warn("Exception closing resource " + resource.getName(), e);
- }
- }
- }
+ public void resolve(ArtifactIdentifier artifact, BuildableArtifactResolveResult result, ModuleSource moduleSource) {
+ Artifact ivyArtifact = DefaultArtifactIdentifier.toArtifact(artifact);
- public void resolve(Artifact artifact, BuildableArtifactResolveResult result, ModuleSource moduleSource) {
- EnhancedArtifactDownloadReport artifactDownloadReport = download(artifact, moduleSource);
- if (downloadFailed(artifactDownloadReport)) {
- result.failed(new ArtifactResolveException(artifactDownloadReport.getArtifact(), artifactDownloadReport.getFailure()));
+ File localFile;
+ try {
+ localFile = download(ivyArtifact, moduleSource);
+ } catch (IOException e) {
+ result.failed(new ArtifactResolveException(artifact, e));
return;
}
- File localFile = artifactDownloadReport.getLocalFile();
+
if (localFile != null) {
result.resolved(localFile);
} else {
@@ -495,80 +392,23 @@ public class ExternalResourceResolver implements DependencyResolver {
}
}
- protected EnhancedArtifactDownloadReport download(Artifact artifact, ModuleSource moduleSource) {
+ protected File download(Artifact artifact, ModuleSource moduleSource) throws IOException {
return download(artifact);
}
- public EnhancedArtifactDownloadReport download(Artifact artifact) {
- RepositoryCacheManager cacheManager = getRepositoryCacheManager();
-
- return (EnhancedArtifactDownloadReport) cacheManager.download(artifact, artifactResourceResolver, resourceDownloader, new CacheDownloadOptions());
- }
-
- public DownloadReport download(Artifact[] artifacts, DownloadOptions options) {
- // This is never used
- throw new UnsupportedOperationException();
- }
-
- public ArtifactDownloadReport download(ArtifactOrigin origin, DownloadOptions options) {
- // This is never used
- throw new UnsupportedOperationException();
- }
-
- public void reportFailure() {
- // This is never used
- throw new UnsupportedOperationException();
- }
-
- public void reportFailure(Artifact art) {
- // This is never used
- throw new UnsupportedOperationException();
- }
-
- public String[] listTokenValues(String token, Map otherTokenValues) {
- // This is never used
- throw new UnsupportedOperationException();
- }
-
- public Map[] listTokenValues(String[] tokens, Map criteria) {
- // This is never used
- throw new UnsupportedOperationException();
- }
-
- public OrganisationEntry[] listOrganisations() {
- // This is never used
- throw new UnsupportedOperationException();
- }
-
- public ModuleEntry[] listModules(OrganisationEntry org) {
- // This is never used
- throw new UnsupportedOperationException();
- }
-
- public RevisionEntry[] listRevisions(ModuleEntry mod) {
- // This is never used
- throw new UnsupportedOperationException();
- }
-
- public void abortPublishTransaction() throws IOException {
- }
-
- public void beginPublishTransaction(ModuleRevisionId module, boolean overwrite) throws IOException {
- }
-
- public void commitPublishTransaction() throws IOException {
- }
+ protected File download(Artifact artifact) throws IOException {
+ ResolvedArtifact artifactRef = getArtifactRef(artifact, true);
+ if (artifactRef == null) {
+ return null;
+ }
- public Namespace getNamespace() {
- // This is never used
- throw new UnsupportedOperationException();
+ return repositoryCacheManager.downloadAndCacheArtifactFile(artifact.getId(), resourceDownloader, artifactRef.resource).getLocalResource().getFile();
}
- protected Resource getResource(String source, Artifact target, boolean forDownload) {
+ private ExternalResource getResource(String source, ArtifactRevisionId target, boolean forDownload) {
try {
if (forDownload) {
- ArtifactRevisionId arid = target.getId();
- LocallyAvailableResourceCandidates localCandidates = locallyAvailableResourceFinder.findCandidates(arid);
+ LocallyAvailableResourceCandidates localCandidates = locallyAvailableResourceFinder.findCandidates(target);
ExternalResource resource = repository.getResource(source, localCandidates);
return resource == null ? new MissingExternalResource(source) : resource;
} else {
@@ -581,47 +421,28 @@ public class ExternalResourceResolver implements DependencyResolver {
}
}
- protected VersionList listVersions(ModuleRevisionId moduleRevisionId, ResourcePattern pattern, Artifact artifact) {
- try {
- VersionList versionList = versionLister.getVersionList(moduleRevisionId);
- versionList.visit(pattern, artifact);
- return versionList;
- } catch (ResourceNotFoundException e) {
- LOGGER.debug(String.format("Unable to load version list for %s from %s", moduleRevisionId.getModuleId(), getRepository()));
- return new DefaultVersionList(Collections.<String>emptyList());
- }
- }
-
- protected long get(Resource resource, File destination) throws IOException {
+ private void get(ExternalResource resource, File destination) throws IOException {
LOGGER.debug("Downloading {} to {}", resource.getName(), destination);
if (destination.getParentFile() != null) {
GFileUtils.mkdirs(destination.getParentFile());
}
- if (!(resource instanceof ExternalResource)) {
- throw new IllegalArgumentException("Can only download ExternalResource");
- }
-
- ExternalResource externalResource = (ExternalResource) resource;
try {
- externalResource.writeTo(destination);
+ resource.writeTo(destination);
} finally {
- externalResource.close();
+ resource.close();
}
- return destination.length();
}
- private long getAndCheck(Resource resource, File dest) throws IOException {
- long size = get(resource, dest);
+ private void verifyChecksums(ExternalResource resource, File dest) throws IOException {
String[] checksums = getChecksumAlgorithms();
boolean checked = false;
for (int i = 0; i < checksums.length && !checked; i++) {
checked = check(resource, dest, checksums[i]);
}
- return size;
}
- private boolean check(Resource resource, File dest, String algorithm) throws IOException {
+ private boolean check(ExternalResource resource, File dest, String algorithm) throws IOException {
if (!ChecksumHelper.isKnownAlgorithm(algorithm)) {
throw new IllegalArgumentException("Unknown checksum algorithm: " + algorithm);
}
@@ -633,7 +454,7 @@ public class ExternalResourceResolver implements DependencyResolver {
try {
get(checksumResource, csFile);
ChecksumHelper.check(dest, csFile, algorithm);
- Message.verbose(algorithm + " OK for " + resource);
+ LOGGER.debug("{} OK for {}", algorithm, resource);
return true;
} finally {
csFile.delete();
@@ -643,7 +464,17 @@ public class ExternalResourceResolver implements DependencyResolver {
}
}
- public void publish(Artifact artifact, File src, boolean overwrite) throws IOException {
+ // TODO:DAZ Remove the need for this, by using our own set of PatternMatchers
+ public void setSettings(IvySettings settings) {
+ }
+
+ public void publish(ModuleVersionPublishMetaData moduleVersion) throws IOException {
+ for (Map.Entry<Artifact, File> entry : moduleVersion.getArtifacts().entrySet()) {
+ publish(entry.getKey(), entry.getValue());
+ }
+ }
+
+ private void publish(Artifact artifact, File src) throws IOException {
String destinationPattern;
if ("ivy".equals(artifact.getType()) && !getIvyPatterns().isEmpty()) {
destinationPattern = getIvyPatterns().get(0);
@@ -692,25 +523,20 @@ public class ExternalResourceResolver implements DependencyResolver {
artifactPatterns = patterns;
}
- public void dumpSettings() {
- // this is not used
- throw new UnsupportedOperationException();
- }
-
public boolean isM2compatible() {
- return m2compatible;
+ return m2Compatible;
}
public void setM2compatible(boolean compatible) {
- m2compatible = compatible;
+ m2Compatible = compatible;
}
public boolean isCheckconsistency() {
- return checkconsistency;
+ return checkConsistency;
}
public void setCheckconsistency(boolean checkConsistency) {
- checkconsistency = checkConsistency;
+ this.checkConsistency = checkConsistency;
}
public void setForce(boolean force) {
@@ -722,33 +548,11 @@ public class ExternalResourceResolver implements DependencyResolver {
}
public boolean isAllownomd() {
- return allownomd;
- }
-
- public void setAllownomd(boolean b) {
- Message.deprecated(
- "allownomd is deprecated, please use descriptor=\""
- + (b ? BasicResolver.DESCRIPTOR_OPTIONAL : BasicResolver.DESCRIPTOR_REQUIRED) + "\" instead");
- allownomd = b;
- }
-
- /**
- * Sets the module descriptor presence rule.
- * Should be one of {@link BasicResolver#DESCRIPTOR_REQUIRED} or {@link BasicResolver#DESCRIPTOR_OPTIONAL}.
- *
- * @param descriptorRule the descriptor rule to use with this resolver.
- */
- public void setDescriptor(String descriptorRule) {
- if (BasicResolver.DESCRIPTOR_REQUIRED.equals(descriptorRule)) {
- allownomd = false;
- } else if (BasicResolver.DESCRIPTOR_OPTIONAL.equals(descriptorRule)) {
- allownomd = true;
- } else {
- throw new IllegalArgumentException(
- "unknown descriptor rule '" + descriptorRule
- + "'. Allowed rules are: "
- + Arrays.asList(new String[] {BasicResolver.DESCRIPTOR_REQUIRED, BasicResolver.DESCRIPTOR_OPTIONAL}));
- }
+ return allowMissingDescriptor;
+ }
+
+ public void setAllownomd(boolean allowMissingDescriptor) {
+ this.allowMissingDescriptor = allowMissingDescriptor;
}
public String[] getChecksumAlgorithms() {
@@ -772,97 +576,58 @@ public class ExternalResourceResolver implements DependencyResolver {
this.checksums = checksums;
}
- public LatestStrategy getLatestStrategy() {
- if (latestStrategy == null) {
- initLatestStrategyFromSettings();
- }
- return latestStrategy;
- }
-
- private void initLatestStrategyFromSettings() {
- if (getSettings() != null) {
- if (latestStrategyName != null && !"default".equals(latestStrategyName)) {
- latestStrategy = getSettings().getLatestStrategy(latestStrategyName);
- if (latestStrategy == null) {
- throw new IllegalStateException(
- "unknown latest strategy '" + latestStrategyName + "'");
- }
- } else {
- latestStrategy = getSettings().getDefaultLatestStrategy();
- Message.debug(getName() + ": no latest strategy defined: using default");
- }
- } else {
- throw new IllegalStateException(
- "no ivy instance found: "
- + "impossible to get a latest strategy without ivy instance");
- }
- }
-
- public void setLatestStrategy(LatestStrategy latestStrategy) {
- this.latestStrategy = latestStrategy;
- }
-
- public void setLatest(String strategyName) {
- latestStrategyName = strategyName;
- }
-
- public String getLatest() {
- if (latestStrategyName == null) {
- latestStrategyName = "default";
- }
- return latestStrategyName;
- }
-
- public void setChangingMatcher(String changingMatcherName) {
- this.changingMatcherName = changingMatcherName;
- }
-
public String getChangingMatcherName() {
return changingMatcherName;
}
- public void setChangingPattern(String changingPattern) {
- this.changingPattern = changingPattern;
+ public void setChangingMatcher(String changingMatcherName) {
+ this.changingMatcherName = changingMatcherName;
}
public String getChangingPattern() {
return changingPattern;
}
- public void setCheckmodified(boolean check) {
- checkmodified = Boolean.valueOf(check);
- }
-
- public RepositoryCacheManager getRepositoryCacheManager() {
- return repositoryCacheManager;
+ public void setChangingPattern(String changingPattern) {
+ this.changingPattern = changingPattern;
}
- public void setRepositoryCacheManager(RepositoryCacheManager repositoryCacheManager) {
+ public void setRepositoryCacheManager(RepositoryArtifactCache repositoryCacheManager) {
this.repositoryCacheManager = repositoryCacheManager;
}
- public void setCache(String cacheName) {
- cacheManagerName = cacheName;
- }
-
protected ResourcePattern toResourcePattern(String pattern) {
return isM2compatible() ? new M2ResourcePattern(pattern) : new IvyResourcePattern(pattern);
}
- protected boolean downloadFailed(ArtifactDownloadReport artifactReport) {
- return artifactReport.getDownloadStatus() == DownloadStatus.FAILED
- && !artifactReport.getDownloadDetails().equals(ArtifactDownloadReport.MISSING_ARTIFACT);
- }
-
private boolean isChanging(ModuleDescriptor moduleDescriptor) {
if (changingMatcherName == null || changingPattern == null) {
- return false;
+ return false; // TODO: tell from module metadata (rule)
}
- PatternMatcher matcher = settings.getMatcher(changingMatcherName);
+ PatternMatcher matcher = ResolverStrategy.INSTANCE.getPatternMatcher(changingMatcherName);
if (matcher == null) {
throw new IllegalStateException("unknown matcher '" + changingMatcherName
+ "'. It is set as changing matcher in " + this);
}
return matcher.getMatcher(changingPattern).matches(moduleDescriptor.getResolvedModuleRevisionId().getRevision());
}
+
+ protected static class ResolvedArtifact {
+ private final ExternalResource resource;
+ private final Artifact artifact;
+
+ public ResolvedArtifact(ExternalResource resource, Artifact artifact) {
+ this.resource = resource;
+ this.artifact = artifact;
+ }
+ }
+
+ private static class DownloadedAndParsedMetaDataArtifact extends ResolvedArtifact {
+ private final ModuleVersionMetaData moduleVersionMetaData;
+
+ public DownloadedAndParsedMetaDataArtifact(ExternalResource resource, Artifact artifact, ModuleVersionMetaData moduleVersionMetaData) {
+ super(resource, artifact);
+ this.moduleVersionMetaData = moduleVersionMetaData;
+ }
+ }
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/ExternalResourceResolverDescriptorParseContext.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/ExternalResourceResolverDescriptorParseContext.java
new file mode 100644
index 0000000..d828030
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/ExternalResourceResolverDescriptorParseContext.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.repositories.resolver;
+
+import org.apache.ivy.core.cache.ArtifactOrigin;
+import org.apache.ivy.core.module.descriptor.Artifact;
+import org.apache.ivy.core.module.descriptor.DefaultDependencyDescriptor;
+import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
+import org.apache.ivy.core.module.id.ModuleRevisionId;
+import org.gradle.api.internal.artifacts.ivyservice.DefaultBuildableModuleVersionResolveResult;
+import org.gradle.api.internal.artifacts.ivyservice.DependencyToModuleVersionResolver;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.DefaultDependencyMetaData;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.AbstractDescriptorParseContext;
+
+/**
+ * ParserSettings that control the scope of searches carried out during parsing.
+ * If the parser asks for a resolver for the currently resolving revision, the resolver scope is only the repository where the module was resolved.
+ * If the parser asks for a resolver for a different revision, the resolver scope is all repositories.
+ */
+public class ExternalResourceResolverDescriptorParseContext extends AbstractDescriptorParseContext {
+ private final DependencyToModuleVersionResolver mainResolver;
+ private final ExternalResourceResolver moduleResolver;
+ private final ModuleRevisionId moduleRevisionId;
+
+ public ExternalResourceResolverDescriptorParseContext(DependencyToModuleVersionResolver mainResolver, ExternalResourceResolver moduleResolver, ModuleRevisionId moduleRevisionId) {
+ super("integration");
+ this.mainResolver = mainResolver;
+ this.moduleResolver = moduleResolver;
+ this.moduleRevisionId = moduleRevisionId;
+ }
+
+ public ModuleRevisionId getCurrentRevisionId() {
+ return moduleRevisionId;
+ }
+
+ public ModuleDescriptor getModuleDescriptor(ModuleRevisionId moduleRevisionId) {
+ DefaultBuildableModuleVersionResolveResult result = new DefaultBuildableModuleVersionResolveResult();
+ mainResolver.resolve(new DefaultDependencyMetaData(new DefaultDependencyDescriptor(moduleRevisionId, true)), result);
+ return result.getMetaData().getDescriptor();
+ }
+
+ public boolean artifactExists(Artifact artifact) {
+ return !ArtifactOrigin.isUnknown(moduleResolver.locate(artifact));
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/IvyResolver.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/IvyResolver.java
index e5fb66b..7b8cdd5 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/IvyResolver.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/IvyResolver.java
@@ -16,6 +16,8 @@
package org.gradle.api.internal.artifacts.repositories.resolver;
import org.apache.ivy.core.module.id.ArtifactRevisionId;
+import org.gradle.api.internal.artifacts.ModuleMetadataProcessor;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.MetaDataParser;
import org.gradle.api.internal.artifacts.repositories.transport.RepositoryTransport;
import org.gradle.api.internal.externalresource.local.LocallyAvailableResourceFinder;
@@ -24,13 +26,22 @@ import java.net.URI;
public class IvyResolver extends ExternalResourceResolver implements PatternBasedResolver {
private final RepositoryTransport transport;
+ private final boolean dynamicResolve;
public IvyResolver(String name, RepositoryTransport transport,
- LocallyAvailableResourceFinder<ArtifactRevisionId> locallyAvailableResourceFinder
+ LocallyAvailableResourceFinder<ArtifactRevisionId> locallyAvailableResourceFinder,
+ MetaDataParser metaDataParser, ModuleMetadataProcessor metadataProcessor,
+ boolean dynamicResolve
) {
- super(name, transport.getRepository(), new ResourceVersionLister(transport.getRepository()), locallyAvailableResourceFinder);
+ super(name, transport.getRepository(), new ResourceVersionLister(transport.getRepository()), locallyAvailableResourceFinder, metaDataParser, metadataProcessor);
this.transport = transport;
this.transport.configureCacheManager(this);
+ this.dynamicResolve = dynamicResolve;
+ }
+
+ @Override
+ public boolean isDynamicResolveMode() {
+ return dynamicResolve;
}
public void addArtifactLocation(URI baseUri, String pattern) {
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/MavenMetadataLoader.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/MavenMetadataLoader.java
index d4cb7d6..9e51bd9 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/MavenMetadataLoader.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/MavenMetadataLoader.java
@@ -16,9 +16,9 @@
package org.gradle.api.internal.artifacts.repositories.resolver;
-import org.apache.ivy.plugins.repository.Resource;
import org.apache.ivy.util.ContextualSAXHandler;
import org.apache.ivy.util.XMLHelper;
+import org.gradle.api.internal.ErroringAction;
import org.gradle.api.internal.externalresource.ExternalResource;
import org.gradle.api.internal.externalresource.transport.ExternalResourceRepository;
import org.gradle.api.internal.resource.ResourceException;
@@ -64,23 +64,26 @@ class MavenMetadataLoader {
}
}
- private void parseMavenMetadataInto(Resource metadataResource, final MavenMetadata mavenMetadata) throws IOException, SAXException, ParserConfigurationException {
+ private void parseMavenMetadataInto(ExternalResource metadataResource, final MavenMetadata mavenMetadata) throws IOException, SAXException, ParserConfigurationException {
LOGGER.debug("parsing maven-metadata: {}", metadataResource);
- InputStream metadataStream = metadataResource.openStream();
- XMLHelper.parse(metadataStream, null, new ContextualSAXHandler() {
- public void endElement(String uri, String localName, String qName)
- throws SAXException {
- if ("metadata/versioning/snapshot/timestamp".equals(getContext())) {
- mavenMetadata.timestamp = getText();
- }
- if ("metadata/versioning/snapshot/buildNumber".equals(getContext())) {
- mavenMetadata.buildNumber = getText();
- }
- if ("metadata/versioning/versions/version".equals(getContext())) {
- mavenMetadata.versions.add(getText().trim());
- }
- super.endElement(uri, localName, qName);
+ metadataResource.withContent(new ErroringAction<InputStream>() {
+ public void doExecute(InputStream inputStream) throws ParserConfigurationException, SAXException, IOException {
+ XMLHelper.parse(inputStream, null, new ContextualSAXHandler() {
+ public void endElement(String uri, String localName, String qName)
+ throws SAXException {
+ if ("metadata/versioning/snapshot/timestamp".equals(getContext())) {
+ mavenMetadata.timestamp = getText();
+ }
+ if ("metadata/versioning/snapshot/buildNumber".equals(getContext())) {
+ mavenMetadata.buildNumber = getText();
+ }
+ if ("metadata/versioning/versions/version".equals(getContext())) {
+ mavenMetadata.versions.add(getText().trim());
+ }
+ super.endElement(uri, localName, qName);
+ }
+ }, null);
}
- }, null);
+ });
}
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/MavenResolver.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/MavenResolver.java
index 71eb83f..125eeb1 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/MavenResolver.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/MavenResolver.java
@@ -21,11 +21,11 @@ import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
import org.apache.ivy.core.module.id.ArtifactRevisionId;
import org.apache.ivy.core.module.id.ModuleRevisionId;
import org.apache.ivy.plugins.matcher.PatternMatcher;
-import org.apache.ivy.plugins.resolver.util.ResolvedResource;
-import org.apache.ivy.plugins.resolver.util.ResourceMDParser;
-import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.BuildableModuleVersionMetaData;
+import org.gradle.api.internal.artifacts.DefaultModuleVersionSelector;
+import org.gradle.api.internal.artifacts.ModuleMetadataProcessor;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.BuildableModuleVersionMetaDataResolveResult;
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ModuleSource;
-import org.gradle.api.internal.artifacts.repositories.cachemanager.EnhancedArtifactDownloadReport;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.MetaDataParser;
import org.gradle.api.internal.artifacts.repositories.transport.RepositoryTransport;
import org.gradle.api.internal.externalresource.local.LocallyAvailableResourceFinder;
import org.gradle.api.internal.resource.ResourceNotFoundException;
@@ -35,6 +35,8 @@ import org.gradle.util.WrapUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.io.File;
+import java.io.IOException;
import java.net.URI;
import java.util.*;
@@ -49,11 +51,14 @@ public class MavenResolver extends ExternalResourceResolver implements PatternBa
private final MavenMetadataLoader mavenMetaDataLoader;
public MavenResolver(String name, URI rootUri, RepositoryTransport transport,
- LocallyAvailableResourceFinder<ArtifactRevisionId> locallyAvailableResourceFinder) {
+ LocallyAvailableResourceFinder<ArtifactRevisionId> locallyAvailableResourceFinder,
+ MetaDataParser metaDataParser, ModuleMetadataProcessor metadataProcessor
+ ) {
super(name,
transport.getRepository(),
new ChainedVersionLister(new MavenVersionLister(transport.getRepository()), new ResourceVersionLister(transport.getRepository())),
- locallyAvailableResourceFinder);
+ locallyAvailableResourceFinder,
+ metaDataParser, metadataProcessor);
transport.configureCacheManager(this);
this.mavenMetaDataLoader = new MavenMetadataLoader(transport.getRepository());
@@ -69,7 +74,7 @@ public class MavenResolver extends ExternalResourceResolver implements PatternBa
updatePatterns();
}
- public void getDependency(DependencyDescriptor dd, BuildableModuleVersionMetaData result) {
+ protected void getDependency(DependencyDescriptor dd, BuildableModuleVersionMetaDataResolveResult result) {
if (isSnapshotVersion(dd)) {
getSnapshotDependency(dd, result);
} else {
@@ -77,13 +82,13 @@ public class MavenResolver extends ExternalResourceResolver implements PatternBa
}
}
- private void getSnapshotDependency(DependencyDescriptor dd, BuildableModuleVersionMetaData result) {
+ private void getSnapshotDependency(DependencyDescriptor dd, BuildableModuleVersionMetaDataResolveResult result) {
final ModuleRevisionId dependencyRevisionId = dd.getDependencyRevisionId();
final String uniqueSnapshotVersion = findUniqueSnapshotVersion(dependencyRevisionId);
if (uniqueSnapshotVersion != null) {
DependencyDescriptor enrichedDependencyDescriptor = enrichDependencyDescriptorWithSnapshotVersionInfo(dd, dependencyRevisionId, uniqueSnapshotVersion);
super.getDependency(enrichedDependencyDescriptor, result);
- if (result.getState() == BuildableModuleVersionMetaData.State.Resolved) {
+ if (result.getState() == BuildableModuleVersionMetaDataResolveResult.State.Resolved) {
result.setModuleSource(new TimestampedModuleSource(uniqueSnapshotVersion));
}
} else {
@@ -102,20 +107,17 @@ public class MavenResolver extends ExternalResourceResolver implements PatternBa
return dd.getDependencyRevisionId().getRevision().endsWith("SNAPSHOT");
}
- protected EnhancedArtifactDownloadReport download(Artifact artifact, ModuleSource moduleSource) {
- EnhancedArtifactDownloadReport artifactDownloadReport;
-
+ protected File download(Artifact artifact, ModuleSource moduleSource) throws IOException {
if (moduleSource instanceof TimestampedModuleSource) {
TimestampedModuleSource timestampedModuleSource = (TimestampedModuleSource) moduleSource;
String timestampedVersion = timestampedModuleSource.getTimestampedVersion();
- artifactDownloadReport = downloadTimestampedVersion(artifact, timestampedVersion);
+ return downloadTimestampedVersion(artifact, timestampedVersion);
} else {
- artifactDownloadReport = download(artifact);
+ return download(artifact);
}
- return artifactDownloadReport;
}
- private EnhancedArtifactDownloadReport downloadTimestampedVersion(Artifact artifact, String timestampedVersion) {
+ private File downloadTimestampedVersion(Artifact artifact, String timestampedVersion) throws IOException {
final ModuleRevisionId artifactModuleRevisionId = artifact.getModuleRevisionId();
final ModuleRevisionId moduleRevisionId = ModuleRevisionId.newInstance(artifactModuleRevisionId.getOrganisation(),
artifactModuleRevisionId.getName(),
@@ -157,13 +159,12 @@ public class MavenResolver extends ExternalResourceResolver implements PatternBa
setArtifactPatterns(artifactPatterns);
}
- public ResolvedResource findIvyFileRef(DependencyDescriptor dd) {
+ protected ResolvedArtifact findIvyFileRef(DependencyDescriptor dd) {
if (isUsepoms()) {
ModuleRevisionId moduleRevisionId = dd.getDependencyRevisionId();
- //we might need a own implementation of DefaultArtifact here as there is no way to pass extraAttributes AND isMetaData to DefaultArtifact
- Artifact pomArtifact = new DefaultArtifact(moduleRevisionId, null, moduleRevisionId.getName(), "pom", "pom", moduleRevisionId.getExtraAttributes());
- ResourceMDParser parser = getRMDParser(dd);
- return findResourceUsingPatterns(moduleRevisionId, getIvyPatterns(), pomArtifact, parser, null, true);
+ ArtifactRevisionId artifactRevisionId = ArtifactRevisionId.newInstance(moduleRevisionId, moduleRevisionId.getName(), "pom", "pom", moduleRevisionId.getExtraAttributes());
+ Artifact pomArtifact = new DefaultArtifact(artifactRevisionId, null, null, true);
+ return findResourceUsingPatterns(DefaultModuleVersionSelector.newSelector(moduleRevisionId), getIvyPatterns(), pomArtifact, true);
}
return null;
@@ -191,7 +192,7 @@ public class MavenResolver extends ExternalResourceResolver implements PatternBa
} catch (ResourceNotFoundException e) {
return new MavenMetadata();
} catch (ResourceException e) {
- LOGGER.warn("impossible to access maven metadata file, ignored.", e);
+ LOGGER.warn("impossible to access Maven metadata file, ignored.", e);
}
}
return new MavenMetadata();
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/MavenVersionLister.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/MavenVersionLister.java
index 2609b47..07c9d5c 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/MavenVersionLister.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/MavenVersionLister.java
@@ -17,7 +17,7 @@
package org.gradle.api.internal.artifacts.repositories.resolver;
import org.apache.ivy.core.module.descriptor.Artifact;
-import org.apache.ivy.core.module.id.ModuleRevisionId;
+import org.gradle.api.artifacts.ModuleVersionSelector;
import org.gradle.api.internal.externalresource.transport.ExternalResourceRepository;
import org.gradle.api.internal.resource.ResourceException;
import org.gradle.api.internal.resource.ResourceNotFoundException;
@@ -32,7 +32,7 @@ public class MavenVersionLister implements VersionLister {
this.mavenMetadataLoader = new MavenMetadataLoader(repository);
}
- public VersionList getVersionList(final ModuleRevisionId moduleRevisionId) {
+ public VersionList getVersionList(ModuleVersionSelector selector) {
return new DefaultVersionList() {
final Set<String> searched = new HashSet<String>();
@@ -42,7 +42,9 @@ public class MavenVersionLister implements VersionLister {
return;
}
MavenMetadata mavenMetaData = mavenMetadataLoader.load(metadataLocation);
- add(mavenMetaData.versions);
+ for (String version : mavenMetaData.versions) {
+ add(new ListedVersion(version, resourcePattern));
+ }
}
};
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/PatternBasedResolver.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/PatternBasedResolver.java
index e71e0e0..3bdb961 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/PatternBasedResolver.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/PatternBasedResolver.java
@@ -15,12 +15,10 @@
*/
package org.gradle.api.internal.artifacts.repositories.resolver;
-import org.apache.ivy.plugins.resolver.DependencyResolver;
-
import java.net.URI;
import java.util.List;
-public interface PatternBasedResolver extends DependencyResolver {
+public interface PatternBasedResolver {
void addArtifactLocation(URI baseUri, String pattern);
void addDescriptorLocation(URI baseUri, String pattern);
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/ResourceVersionLister.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/ResourceVersionLister.java
index 3034b1a..cd30f39 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/ResourceVersionLister.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/ResourceVersionLister.java
@@ -18,7 +18,7 @@ package org.gradle.api.internal.artifacts.repositories.resolver;
import org.apache.ivy.core.IvyPatternHelper;
import org.apache.ivy.core.module.descriptor.Artifact;
-import org.apache.ivy.core.module.id.ModuleRevisionId;
+import org.gradle.api.artifacts.ModuleVersionSelector;
import org.gradle.api.internal.externalresource.transport.ExternalResourceRepository;
import org.gradle.api.internal.resource.ResourceException;
import org.gradle.api.internal.resource.ResourceNotFoundException;
@@ -42,7 +42,7 @@ public class ResourceVersionLister implements VersionLister {
this.repository = repository;
}
- public VersionList getVersionList(final ModuleRevisionId moduleRevisionId) {
+ public VersionList getVersionList(ModuleVersionSelector selector) {
return new DefaultVersionList() {
final Set<String> directories = new HashSet<String>();
@@ -51,7 +51,9 @@ public class ResourceVersionLister implements VersionLister {
LOGGER.debug("Listing all in {}", partiallyResolvedPattern);
try {
List<String> versionStrings = listRevisionToken(partiallyResolvedPattern);
- add(versionStrings);
+ for (String versionString : versionStrings) {
+ add(new ListedVersion(versionString, resourcePattern));
+ }
} catch (ResourceNotFoundException e) {
throw e;
} catch (Exception e) {
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/VersionList.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/VersionList.java
index 16bf49d..1bd9cf2 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/VersionList.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/VersionList.java
@@ -17,7 +17,8 @@
package org.gradle.api.internal.artifacts.repositories.resolver;
import org.apache.ivy.core.module.descriptor.Artifact;
-import org.apache.ivy.plugins.latest.LatestStrategy;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.LatestStrategy;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.Versioned;
import org.gradle.api.internal.resource.ResourceException;
import org.gradle.api.internal.resource.ResourceNotFoundException;
@@ -33,9 +34,41 @@ public interface VersionList {
*/
void visit(ResourcePattern pattern, Artifact artifact) throws ResourceNotFoundException, ResourceException;
- Set<String> getVersionStrings();
+ Set<ListedVersion> getVersions();
boolean isEmpty();
- List<String> sortLatestFirst(LatestStrategy latestStrategy);
+ List<ListedVersion> sortLatestFirst(LatestStrategy latestStrategy);
+
+ class ListedVersion implements Versioned {
+ private String version;
+ private ResourcePattern pattern;
+
+ public ListedVersion(String version, ResourcePattern pattern) {
+ this.pattern = pattern;
+ this.version = version;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ /**
+ * @return The pattern that can be used to load this version.
+ */
+ public ResourcePattern getPattern() {
+ return pattern;
+ }
+
+ public boolean equals(Object other) {
+ if (!(other instanceof ListedVersion)) {
+ return false;
+ }
+ return version.equals(((ListedVersion) other).getVersion());
+ }
+
+ public int hashCode() {
+ return version.hashCode();
+ }
+ }
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/VersionLister.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/VersionLister.java
index 975c336..9b16869 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/VersionLister.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/resolver/VersionLister.java
@@ -16,11 +16,11 @@
package org.gradle.api.internal.artifacts.repositories.resolver;
-import org.apache.ivy.core.module.id.ModuleRevisionId;
+import org.gradle.api.artifacts.ModuleVersionSelector;
public interface VersionLister {
/**
- * Creates an empty version list for the given module version. Call {@link VersionList#visit(String, org.apache.ivy.core.module.descriptor.Artifact)} to search for versions.
+ * Creates an empty version list for the given module version. Call {@link VersionList#visit(ResourcePattern, org.apache.ivy.core.module.descriptor.Artifact)} to search for versions.
*/
- VersionList getVersionList(ModuleRevisionId moduleRevisionId);
+ VersionList getVersionList(ModuleVersionSelector selector);
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/transport/RepositoryTransportFactory.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/transport/RepositoryTransportFactory.java
index 3a645bc..21fe348 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/transport/RepositoryTransportFactory.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/repositories/transport/RepositoryTransportFactory.java
@@ -15,8 +15,8 @@
*/
package org.gradle.api.internal.artifacts.repositories.transport;
-import org.apache.ivy.core.cache.RepositoryCacheManager;
import org.gradle.api.artifacts.repositories.PasswordCredentials;
+import org.gradle.api.internal.artifacts.repositories.cachemanager.RepositoryArtifactCache;
import org.gradle.api.internal.externalresource.cached.CachedExternalResourceIndex;
import org.gradle.api.internal.externalresource.transport.file.FileTransport;
import org.gradle.api.internal.externalresource.transport.http.HttpTransport;
@@ -24,15 +24,15 @@ import org.gradle.api.internal.file.TemporaryFileProvider;
import org.gradle.logging.ProgressLoggerFactory;
public class RepositoryTransportFactory {
- private final RepositoryCacheManager downloadingCacheManager;
+ private final RepositoryArtifactCache downloadingCacheManager;
private final TemporaryFileProvider temporaryFileProvider;
private final CachedExternalResourceIndex<String> cachedExternalResourceIndex;
- private final RepositoryCacheManager localCacheManager;
+ private final RepositoryArtifactCache localCacheManager;
private final ProgressLoggerFactory progressLoggerFactory;
public RepositoryTransportFactory(ProgressLoggerFactory progressLoggerFactory,
- RepositoryCacheManager localCacheManager,
- RepositoryCacheManager downloadingCacheManager,
+ RepositoryArtifactCache localCacheManager,
+ RepositoryArtifactCache downloadingCacheManager,
TemporaryFileProvider temporaryFileProvider,
CachedExternalResourceIndex<String> cachedExternalResourceIndex) {
this.progressLoggerFactory = progressLoggerFactory;
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/result/AbstractDependencyResult.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/result/AbstractDependencyResult.java
index 4ccb18f..5b86df5 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/result/AbstractDependencyResult.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/result/AbstractDependencyResult.java
@@ -20,9 +20,6 @@ import org.gradle.api.artifacts.ModuleVersionSelector;
import org.gradle.api.artifacts.result.DependencyResult;
import org.gradle.api.artifacts.result.ResolvedModuleVersionResult;
-/**
- * by Szczepan Faber, created at: 7/26/12
- */
public class AbstractDependencyResult implements DependencyResult {
private final ModuleVersionSelector requested;
private final ResolvedModuleVersionResult from;
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/result/DefaultResolutionResult.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/result/DefaultResolutionResult.java
index 09d2ce0..3cf2feb 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/result/DefaultResolutionResult.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/result/DefaultResolutionResult.java
@@ -24,25 +24,23 @@ import org.gradle.api.artifacts.result.ResolvedDependencyResult;
import org.gradle.api.artifacts.result.ResolvedModuleVersionResult;
import org.gradle.api.internal.Actions;
import org.gradle.api.internal.ClosureBackedAction;
+import org.gradle.internal.Factory;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
-/**
- * by Szczepan Faber, created at: 8/10/12
- */
public class DefaultResolutionResult implements ResolutionResult {
- private final ResolvedModuleVersionResult root;
+ private Factory<ResolvedModuleVersionResult> rootSource;
- public DefaultResolutionResult(ResolvedModuleVersionResult root) {
- assert root != null;
- this.root = root;
+ public DefaultResolutionResult(Factory<ResolvedModuleVersionResult> rootSource) {
+ assert rootSource != null;
+ this.rootSource = rootSource;
}
public ResolvedModuleVersionResult getRoot() {
- return root;
+ return rootSource.create();
}
public Set<? extends DependencyResult> getAllDependencies() {
@@ -56,7 +54,7 @@ public class DefaultResolutionResult implements ResolutionResult {
}
public void allDependencies(Action<? super DependencyResult> action) {
- eachElement(root, Actions.doNothing(), action, new HashSet<ResolvedModuleVersionResult>());
+ eachElement(getRoot(), Actions.doNothing(), action, new HashSet<ResolvedModuleVersionResult>());
}
public void allDependencies(final Closure closure) {
@@ -80,12 +78,12 @@ public class DefaultResolutionResult implements ResolutionResult {
public Set<ResolvedModuleVersionResult> getAllModuleVersions() {
final Set<ResolvedModuleVersionResult> out = new LinkedHashSet<ResolvedModuleVersionResult>();
- eachElement(root, Actions.doNothing(), Actions.doNothing(), out);
+ eachElement(getRoot(), Actions.doNothing(), Actions.doNothing(), out);
return out;
}
public void allModuleVersions(final Action<? super ResolvedModuleVersionResult> action) {
- eachElement(root, action, Actions.doNothing(), new HashSet<ResolvedModuleVersionResult>());
+ eachElement(getRoot(), action, Actions.doNothing(), new HashSet<ResolvedModuleVersionResult>());
}
public void allModuleVersions(final Closure closure) {
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/result/DefaultResolvedDependencyResult.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/result/DefaultResolvedDependencyResult.java
index 074e5e4..5a8d47f 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/result/DefaultResolvedDependencyResult.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/result/DefaultResolvedDependencyResult.java
@@ -20,9 +20,6 @@ import org.gradle.api.artifacts.ModuleVersionSelector;
import org.gradle.api.artifacts.result.ResolvedDependencyResult;
import org.gradle.api.artifacts.result.ResolvedModuleVersionResult;
-/**
- * by Szczepan Faber, created at: 7/26/12
- */
public class DefaultResolvedDependencyResult extends AbstractDependencyResult implements ResolvedDependencyResult {
private final ResolvedModuleVersionResult selected;
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/result/DefaultResolvedModuleVersionResult.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/result/DefaultResolvedModuleVersionResult.java
index 0bff383..18671fe 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/result/DefaultResolvedModuleVersionResult.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/result/DefaultResolvedModuleVersionResult.java
@@ -21,25 +21,17 @@ import org.gradle.api.artifacts.result.DependencyResult;
import org.gradle.api.artifacts.result.ModuleVersionSelectionReason;
import org.gradle.api.artifacts.result.ResolvedDependencyResult;
import org.gradle.api.artifacts.result.ResolvedModuleVersionResult;
-import org.gradle.api.internal.artifacts.ivyservice.resolveengine.result.VersionSelectionReasons;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
-/**
- * by Szczepan Faber, created at: 8/10/12
- */
public class DefaultResolvedModuleVersionResult implements ResolvedModuleVersionResult {
private final ModuleVersionIdentifier id;
private final Set<DependencyResult> dependencies = new LinkedHashSet<DependencyResult>();
private final Set<ResolvedDependencyResult> dependents = new LinkedHashSet<ResolvedDependencyResult>();
private final ModuleVersionSelectionReason selectionReason;
- public DefaultResolvedModuleVersionResult(ModuleVersionIdentifier id) {
- this(id, VersionSelectionReasons.REQUESTED);
- }
-
public DefaultResolvedModuleVersionResult(ModuleVersionIdentifier id, ModuleVersionSelectionReason selectionReason) {
assert id != null;
assert selectionReason != null;
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/result/DefaultUnresolvedDependencyResult.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/result/DefaultUnresolvedDependencyResult.java
index 6b95007..59cbf12 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/result/DefaultUnresolvedDependencyResult.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/artifacts/result/DefaultUnresolvedDependencyResult.java
@@ -22,9 +22,6 @@ import org.gradle.api.artifacts.result.ResolvedModuleVersionResult;
import org.gradle.api.artifacts.result.UnresolvedDependencyResult;
import org.gradle.api.internal.artifacts.ivyservice.ModuleVersionResolveException;
-/**
- * by Szczepan Faber, created at: 7/26/12
- */
public class DefaultUnresolvedDependencyResult extends AbstractDependencyResult implements UnresolvedDependencyResult {
private final ModuleVersionSelectionReason reason;
private final ModuleVersionResolveException failure;
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/AbstractExternalResource.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/AbstractExternalResource.java
index 72610c1..1142f22 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/AbstractExternalResource.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/AbstractExternalResource.java
@@ -16,11 +16,16 @@
package org.gradle.api.internal.externalresource;
import org.apache.commons.io.IOUtils;
-import org.apache.ivy.plugins.repository.Resource;
+import org.gradle.api.Action;
+import org.gradle.api.Transformer;
import java.io.*;
public abstract class AbstractExternalResource implements ExternalResource {
+ /**
+ * Opens an unbuffered input stream to read the contents of this resource.
+ */
+ protected abstract InputStream openStream() throws IOException;
public void writeTo(File destination) throws IOException {
FileOutputStream output = new FileOutputStream(destination);
@@ -40,9 +45,22 @@ public abstract class AbstractExternalResource implements ExternalResource {
}
}
+ public void withContent(Action<? super InputStream> readAction) throws IOException {
+ InputStream input = openStream();
+ try {
+ readAction.execute(input);
+ } finally {
+ input.close();
+ }
+ }
- public Resource clone(String cloneName) {
- throw new UnsupportedOperationException();
+ public <T> T withContent(Transformer<? extends T, ? super InputStream> readAction) throws IOException {
+ InputStream input = openStream();
+ try {
+ return readAction.transform(input);
+ } finally {
+ input.close();
+ }
}
public void close() throws IOException {
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/DefaultLocallyAvailableExternalResource.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/DefaultLocallyAvailableExternalResource.java
new file mode 100644
index 0000000..ec51cc5
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/DefaultLocallyAvailableExternalResource.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.externalresource;
+
+import org.gradle.api.internal.externalresource.metadata.ExternalResourceMetaData;
+import org.gradle.internal.resource.local.LocallyAvailableResource;
+import org.gradle.util.hash.HashValue;
+
+public class DefaultLocallyAvailableExternalResource extends LocalFileStandInExternalResource implements LocallyAvailableExternalResource {
+ private final LocallyAvailableResource locallyAvailableResource;
+
+ public DefaultLocallyAvailableExternalResource(String source, LocallyAvailableResource locallyAvailableResource) {
+ this(source, locallyAvailableResource, null);
+ }
+
+ public DefaultLocallyAvailableExternalResource(String source, LocallyAvailableResource locallyAvailableResource, ExternalResourceMetaData metaData) {
+ super(source, locallyAvailableResource.getFile(), metaData);
+ this.locallyAvailableResource = locallyAvailableResource;
+ }
+
+ public LocallyAvailableResource getLocalResource() {
+ return locallyAvailableResource;
+ }
+
+ @Override
+ public long getContentLength() {
+ return locallyAvailableResource.getContentLength();
+ }
+
+ @Override
+ protected HashValue getLocalFileSha1() {
+ return locallyAvailableResource.getSha1();
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/ExternalResource.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/ExternalResource.java
index a588007..1e2ce4a 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/ExternalResource.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/ExternalResource.java
@@ -15,24 +15,74 @@
*/
package org.gradle.api.internal.externalresource;
-import org.apache.ivy.plugins.repository.Resource;
-import org.gradle.api.Nullable;
+import org.gradle.api.Action;
+import org.gradle.api.Transformer;
import org.gradle.api.internal.externalresource.metadata.ExternalResourceMetaData;
import java.io.File;
import java.io.IOException;
+import java.io.InputStream;
import java.io.OutputStream;
-public interface ExternalResource extends Resource {
+public interface ExternalResource {
+ /**
+ * Get the name of the resource.
+ */
+ public String getName();
+
+ /**
+ * Get the date the resource was last modified
+ *
+ * @return A <code>long</code> value representing the time the file was last modified,
+ * measured in milliseconds since the epoch (00:00:00 GMT, January 1, 1970), or
+ * <code>0L</code> if the file does not exist or if an I/O error occurs.
+ */
+ public long getLastModified();
+
+ /**
+ * Get the resource size
+ *
+ * @return a <code>long</code> value representing the size of the resource in bytes.
+ */
+ public long getContentLength();
+
+ /**
+ * Determine if the resource is available.
+ * </p>
+ * Note that this method only checks for availability, not for actual existence.
+ *
+ * @return <code>boolean</code> value indicating if the resource is available.
+ */
+ public boolean exists();
+
+ /**
+ * Is this resource local to this host, i.e. is it on the file system?
+ *
+ * @return <code>boolean</code> value indicating if the resource is local.
+ */
+ public boolean isLocal();
+
+ /**
+ * Copies the contents of this resource to the given file.
+ */
void writeTo(File destination) throws IOException;
/**
- * Writes to the given stream. Does not close the stream.
+ * Copies the contents of this resource to the given stream. Does not close the stream.
*/
void writeTo(OutputStream destination) throws IOException;
+ /**
+ * Executes the given action against the contents of this resource.
+ */
+ void withContent(Action<? super InputStream> readAction) throws IOException;
+
+ /**
+ * Executes the given action against the contents of this resource.
+ */
+ <T> T withContent(Transformer<? extends T, ? super InputStream> readAction) throws IOException;
+
void close() throws IOException;
- @Nullable
ExternalResourceMetaData getMetaData();
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/LocallyAvailableExternalResource.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/LocallyAvailableExternalResource.java
index 0b4cb72..0d7e582 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/LocallyAvailableExternalResource.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/LocallyAvailableExternalResource.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012 the original author or authors.
+ * Copyright 2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,30 +16,12 @@
package org.gradle.api.internal.externalresource;
-import org.gradle.api.internal.externalresource.local.LocallyAvailableResource;
-import org.gradle.api.internal.externalresource.metadata.ExternalResourceMetaData;
-import org.gradle.util.hash.HashValue;
+import org.gradle.internal.resource.local.LocallyAvailableResource;
-public class LocallyAvailableExternalResource extends LocalFileStandInExternalResource {
-
- private final LocallyAvailableResource locallyAvailableResource;
-
- public LocallyAvailableExternalResource(String source, LocallyAvailableResource locallyAvailableResource) {
- this(source, locallyAvailableResource, null);
- }
-
- public LocallyAvailableExternalResource(String source, LocallyAvailableResource locallyAvailableResource, ExternalResourceMetaData metaData) {
- super(source, locallyAvailableResource.getFile(), metaData);
- this.locallyAvailableResource = locallyAvailableResource;
- }
-
- @Override
- public long getContentLength() {
- return locallyAvailableResource.getContentLength();
- }
-
- @Override
- protected HashValue getLocalFileSha1() {
- return locallyAvailableResource.getSha1();
- }
+/**
+ * Represents an external resource whose meta-data and content is available locally. The content and meta-data may be a copy of some original resource and the original may or may not be a local
+ * resource.
+ */
+public interface LocallyAvailableExternalResource extends ExternalResource {
+ LocallyAvailableResource getLocalResource();
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/UrlExternalResource.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/UrlExternalResource.java
new file mode 100644
index 0000000..f47a3bf
--- /dev/null
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/UrlExternalResource.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.externalresource;
+
+import org.gradle.api.internal.externalresource.metadata.DefaultExternalResourceMetaData;
+import org.gradle.api.internal.externalresource.metadata.ExternalResourceMetaData;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLConnection;
+
+public class UrlExternalResource extends AbstractExternalResource {
+ private final URL url;
+ private final URLConnection connection;
+ private final DefaultExternalResourceMetaData metaData;
+
+ public UrlExternalResource(URL url) throws IOException {
+ this.url = url;
+ connection = url.openConnection();
+ metaData = new DefaultExternalResourceMetaData(url.toString(), connection.getLastModified(), connection.getContentLength(), null, null);
+ }
+
+ public String getName() {
+ return url.toExternalForm();
+ }
+
+ public ExternalResourceMetaData getMetaData() {
+ return metaData;
+ }
+
+ public boolean isLocal() {
+ return url.getProtocol().equalsIgnoreCase("file");
+ }
+
+ public long getContentLength() {
+ return connection.getContentLength();
+ }
+
+ public long getLastModified() {
+ return connection.getLastModified();
+ }
+
+ public boolean exists() {
+ return true;
+ }
+
+ public InputStream openStream() throws IOException {
+ return connection.getInputStream();
+ }
+}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/ivy/ArtifactAtRepositoryCachedArtifactIndex.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/ivy/ArtifactAtRepositoryCachedArtifactIndex.java
index 9f297a4..bf33e52 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/ivy/ArtifactAtRepositoryCachedArtifactIndex.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/ivy/ArtifactAtRepositoryCachedArtifactIndex.java
@@ -16,17 +16,20 @@
package org.gradle.api.internal.externalresource.ivy;
+import org.gradle.api.artifacts.ArtifactIdentifier;
+import org.gradle.api.artifacts.ModuleVersionIdentifier;
+import org.gradle.api.internal.artifacts.DefaultArtifactIdentifier;
+import org.gradle.api.internal.artifacts.ModuleVersionIdentifierSerializer;
import org.gradle.api.internal.artifacts.ivyservice.CacheLockingManager;
import org.gradle.api.internal.externalresource.cached.CachedArtifact;
import org.gradle.api.internal.externalresource.cached.CachedArtifactIndex;
import org.gradle.api.internal.externalresource.cached.DefaultCachedArtifact;
import org.gradle.internal.TimeProvider;
-import org.gradle.messaging.serialize.DataStreamBackedSerializer;
+import org.gradle.messaging.serialize.Decoder;
+import org.gradle.messaging.serialize.Encoder;
+import org.gradle.messaging.serialize.Serializer;
-import java.io.DataInput;
-import java.io.DataOutput;
import java.io.File;
-import java.io.IOException;
import java.math.BigInteger;
public class ArtifactAtRepositoryCachedArtifactIndex extends AbstractCachedIndex<ArtifactAtRepositoryKey, CachedArtifact> implements CachedArtifactIndex {
@@ -55,47 +58,51 @@ public class ArtifactAtRepositoryCachedArtifactIndex extends AbstractCachedIndex
return new DefaultCachedArtifact(timeProvider.getCurrentTime(), descriptorHash);
}
- private static class ArtifactAtRepositoryKeySerializer extends DataStreamBackedSerializer<ArtifactAtRepositoryKey> {
- @Override
- public void write(DataOutput dataOutput, ArtifactAtRepositoryKey value) throws IOException {
- dataOutput.writeUTF(value.getRepositoryId());
- dataOutput.writeUTF(value.getArtifactId());
+ private static class ArtifactAtRepositoryKeySerializer implements Serializer<ArtifactAtRepositoryKey> {
+ private final ModuleVersionIdentifierSerializer modIdSerializer = new ModuleVersionIdentifierSerializer();
+
+ public void write(Encoder encoder, ArtifactAtRepositoryKey value) throws Exception {
+ encoder.writeString(value.getRepositoryId());
+ ArtifactIdentifier artifact = value.getArtifactId();
+ modIdSerializer.write(encoder, artifact.getModuleVersionIdentifier());
+ encoder.writeString(artifact.getName());
+ encoder.writeNullableString(artifact.getExtension());
+ encoder.writeNullableString(artifact.getClassifier());
+ encoder.writeNullableString(artifact.getType());
}
- @Override
- public ArtifactAtRepositoryKey read(DataInput dataInput) throws IOException {
- String repositoryId = dataInput.readUTF();
- String artifactId = dataInput.readUTF();
- return new ArtifactAtRepositoryKey(repositoryId, artifactId);
+ public ArtifactAtRepositoryKey read(Decoder decoder) throws Exception {
+ String repositoryId = decoder.readString();
+ ModuleVersionIdentifier moduleVersionIdentifier = modIdSerializer.read(decoder);
+ String artifactName = decoder.readString();
+ String extension = decoder.readNullableString();
+ String classifier = decoder.readNullableString();
+ String type = decoder.readNullableString();
+ return new ArtifactAtRepositoryKey(repositoryId, new DefaultArtifactIdentifier(moduleVersionIdentifier, artifactName, type, extension, classifier));
}
}
- private static class CachedArtifactSerializer extends DataStreamBackedSerializer<CachedArtifact> {
- @Override
- public void write(DataOutput dataOutput, CachedArtifact value) throws IOException {
- dataOutput.writeBoolean(value.isMissing());
+ private static class CachedArtifactSerializer implements Serializer<CachedArtifact> {
+ public void write(Encoder encoder, CachedArtifact value) throws Exception {
+ encoder.writeBoolean(value.isMissing());
if (!value.isMissing()) {
- dataOutput.writeUTF(value.getCachedFile().getPath());
+ encoder.writeString(value.getCachedFile().getPath());
}
- dataOutput.writeLong(value.getCachedAt());
+ encoder.writeLong(value.getCachedAt());
byte[] hash = value.getDescriptorHash().toByteArray();
- dataOutput.writeInt(hash.length);
- dataOutput.write(hash);
+ encoder.writeBinary(hash);
}
- @Override
- public CachedArtifact read(DataInput dataInput) throws Exception {
- boolean isMissing = dataInput.readBoolean();
+ public CachedArtifact read(Decoder decoder) throws Exception {
+ boolean isMissing = decoder.readBoolean();
File file;
if (!isMissing) {
- file = new File(dataInput.readUTF());
+ file = new File(decoder.readString());
} else {
file = null;
}
- long createTimestamp = dataInput.readLong();
- int count = dataInput.readInt();
- byte[] encodedHash = new byte[count];
- dataInput.readFully(encodedHash);
+ long createTimestamp = decoder.readLong();
+ byte[] encodedHash = decoder.readBinary();
BigInteger hash = new BigInteger(encodedHash);
return new DefaultCachedArtifact(file, createTimestamp, hash);
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/ivy/ArtifactAtRepositoryKey.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/ivy/ArtifactAtRepositoryKey.java
index 760159f..e1cc064 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/ivy/ArtifactAtRepositoryKey.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/ivy/ArtifactAtRepositoryKey.java
@@ -16,37 +16,18 @@
package org.gradle.api.internal.externalresource.ivy;
-import org.apache.ivy.core.IvyPatternHelper;
-import org.apache.ivy.core.module.descriptor.Artifact;
-import org.apache.ivy.core.module.descriptor.DefaultArtifact;
-import org.apache.ivy.core.module.id.ArtifactRevisionId;
-import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ModuleVersionRepository;
+import org.gradle.api.artifacts.ArtifactIdentifier;
public class ArtifactAtRepositoryKey {
private final String repositoryId;
- private final String artifactId;
+ private final ArtifactIdentifier artifactId;
- public ArtifactAtRepositoryKey(ModuleVersionRepository repository, ArtifactRevisionId artifactId) {
- this(repository, getArtifactKey(artifactId));
- }
-
- public ArtifactAtRepositoryKey(String repositoryId, String artifactId) {
+ public ArtifactAtRepositoryKey(String repositoryId, ArtifactIdentifier artifactId) {
this.repositoryId = repositoryId;
this.artifactId = artifactId;
}
- private ArtifactAtRepositoryKey(ModuleVersionRepository repository, String artifactPath) {
- this.repositoryId = repository.getId();
- this.artifactId = artifactPath;
- }
-
- private static String getArtifactKey(ArtifactRevisionId artifactId) {
- String format = "[organisation]/[module](/[branch])/[revision]/[type]/[artifact](-[classifier])(.[ext])";
- Artifact dummyArtifact = new DefaultArtifact(artifactId, null, null, false);
- return IvyPatternHelper.substitute(format, dummyArtifact);
- }
-
- public String getArtifactId() {
+ public ArtifactIdentifier getArtifactId() {
return artifactId;
}
@@ -65,11 +46,11 @@ public class ArtifactAtRepositoryKey {
return false;
}
ArtifactAtRepositoryKey other = (ArtifactAtRepositoryKey) o;
- return toString().equals(other.toString());
+ return repositoryId.equals(other.repositoryId) && artifactId.equals(other.artifactId);
}
@Override
public int hashCode() {
- return toString().hashCode();
+ return repositoryId.hashCode() ^ artifactId.hashCode();
}
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/local/CompositeLocallyAvailableResourceFinder.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/local/CompositeLocallyAvailableResourceFinder.java
index db6f783..4eee4be 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/local/CompositeLocallyAvailableResourceFinder.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/local/CompositeLocallyAvailableResourceFinder.java
@@ -16,6 +16,7 @@
package org.gradle.api.internal.externalresource.local;
+import org.gradle.internal.resource.local.LocallyAvailableResource;
import org.gradle.util.hash.HashValue;
import java.util.LinkedList;
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/local/DefaultLocallyAvailableResource.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/local/DefaultLocallyAvailableResource.java
deleted file mode 100644
index b6ff3d1..0000000
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/local/DefaultLocallyAvailableResource.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.externalresource.local;
-
-import org.gradle.util.hash.HashUtil;
-import org.gradle.util.hash.HashValue;
-
-import java.io.File;
-
-public class DefaultLocallyAvailableResource implements LocallyAvailableResource {
- private final File origin;
-
- // Calculated on demand
- private HashValue sha1;
- private Long contentLength;
- private Long lastModified;
-
- public DefaultLocallyAvailableResource(File origin) {
- this.origin = origin;
- }
-
- public DefaultLocallyAvailableResource(File origin, HashValue sha1) {
- this(origin);
- this.sha1 = sha1;
- }
-
- public File getFile() {
- return origin;
- }
-
- public HashValue getSha1() {
- if (sha1 == null) {
- this.sha1 = HashUtil.sha1(origin);
- }
- return sha1;
- }
-
- public long getContentLength() {
- if (contentLength == null) {
- contentLength = origin.length();
- }
- return contentLength;
- }
-
- public long getLastModified() {
- if (lastModified == null) {
- lastModified = origin.lastModified();
- }
- return lastModified;
- }
-
-}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/local/LazyLocallyAvailableResourceCandidates.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/local/LazyLocallyAvailableResourceCandidates.java
index f9a9b69..789d481 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/local/LazyLocallyAvailableResourceCandidates.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/local/LazyLocallyAvailableResourceCandidates.java
@@ -17,6 +17,8 @@
package org.gradle.api.internal.externalresource.local;
import org.gradle.internal.Factory;
+import org.gradle.internal.resource.local.DefaultLocallyAvailableResource;
+import org.gradle.internal.resource.local.LocallyAvailableResource;
import org.gradle.util.hash.HashUtil;
import org.gradle.util.hash.HashValue;
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/local/LocallyAvailableResource.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/local/LocallyAvailableResource.java
deleted file mode 100644
index 5113da1..0000000
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/local/LocallyAvailableResource.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.externalresource.local;
-
-import org.gradle.util.hash.HashValue;
-
-import java.io.File;
-
-public interface LocallyAvailableResource {
-
- File getFile();
-
- HashValue getSha1();
-
- long getLastModified();
-
- long getContentLength();
-}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/local/LocallyAvailableResourceCandidates.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/local/LocallyAvailableResourceCandidates.java
index 5694ce0..6d45b8d 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/local/LocallyAvailableResourceCandidates.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/local/LocallyAvailableResourceCandidates.java
@@ -16,6 +16,7 @@
package org.gradle.api.internal.externalresource.local;
+import org.gradle.internal.resource.local.LocallyAvailableResource;
import org.gradle.util.hash.HashValue;
/**
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/local/LocallyAvailableResourceFinder.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/local/LocallyAvailableResourceFinder.java
index 610c33e..5c84337 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/local/LocallyAvailableResourceFinder.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/local/LocallyAvailableResourceFinder.java
@@ -21,7 +21,7 @@ package org.gradle.api.internal.externalresource.local;
*
* This is different to our caching in that we know very little about locally available resources, other than their
* binary content. If we can determine the sha1 value of an external resource, we can search the local system to see
- * if a copy can be found (e.g. the local maven cache).
+ * if a copy can be found (e.g. the local Maven cache).
*
* @param <C> The type of the criterion object used to find candidates
*/
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/local/LocallyAvailableResourceFinderSearchableFileStoreAdapter.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/local/LocallyAvailableResourceFinderSearchableFileStoreAdapter.java
index 436c373..6047525 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/local/LocallyAvailableResourceFinderSearchableFileStoreAdapter.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/local/LocallyAvailableResourceFinderSearchableFileStoreAdapter.java
@@ -17,9 +17,9 @@
package org.gradle.api.internal.externalresource.local;
import org.gradle.api.Transformer;
-import org.gradle.api.internal.filestore.FileStoreEntry;
-import org.gradle.api.internal.filestore.FileStoreSearcher;
+import org.gradle.internal.filestore.FileStoreSearcher;
import org.gradle.internal.Factory;
+import org.gradle.internal.resource.local.LocallyAvailableResource;
import org.gradle.util.CollectionUtils;
import java.io.File;
@@ -38,9 +38,9 @@ public class LocallyAvailableResourceFinderSearchableFileStoreAdapter<C> extends
public Factory<List<File>> transform(final C criterion) {
return new Factory<List<File>>() {
public List<File> create() {
- Set<? extends FileStoreEntry> entries = fileStore.search(criterion);
- return CollectionUtils.collect(entries, new ArrayList<File>(entries.size()), new Transformer<File, FileStoreEntry>() {
- public File transform(FileStoreEntry original) {
+ Set<? extends LocallyAvailableResource> entries = fileStore.search(criterion);
+ return CollectionUtils.collect(entries, new ArrayList<File>(entries.size()), new Transformer<File, LocallyAvailableResource>() {
+ public File transform(LocallyAvailableResource original) {
return original.getFile();
}
});
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/local/ivy/LocallyAvailableResourceFinderFactory.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/local/ivy/LocallyAvailableResourceFinderFactory.java
index 3cec598..3905eb0 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/local/ivy/LocallyAvailableResourceFinderFactory.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/local/ivy/LocallyAvailableResourceFinderFactory.java
@@ -23,8 +23,9 @@ import org.gradle.api.internal.artifacts.repositories.resolver.IvyResourcePatter
import org.gradle.api.internal.artifacts.repositories.resolver.M2ResourcePattern;
import org.gradle.api.internal.artifacts.repositories.resolver.ResourcePattern;
import org.gradle.api.internal.externalresource.local.*;
-import org.gradle.api.internal.filestore.FileStoreSearcher;
+import org.gradle.internal.filestore.FileStoreSearcher;
import org.gradle.internal.Factory;
+import org.gradle.internal.resource.local.LocallyAvailableResource;
import org.gradle.util.hash.HashValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -55,6 +56,12 @@ public class LocallyAvailableResourceFinderFactory implements Factory<LocallyAva
// The current filestore
finders.add(new LocallyAvailableResourceFinderSearchableFileStoreAdapter<ArtifactRevisionId>(fileStore));
+ // 1.5
+ addForPattern(finders, "artifacts-24", "filestore/[organisation]/[module](/[branch])/[revision]/[type]/*/[artifact]-[revision](-[classifier])(.[ext])");
+
+ // 1.4
+ addForPattern(finders, "artifacts-23", "filestore/[organisation]/[module](/[branch])/[revision]/[type]/*/[artifact]-[revision](-[classifier])(.[ext])");
+
// 1.3
addForPattern(finders, "artifacts-15", "filestore/[organisation]/[module](/[branch])/[revision]/[type]/*/[artifact]-[revision](-[classifier])(.[ext])");
@@ -110,7 +117,7 @@ public class LocallyAvailableResourceFinderFactory implements Factory<LocallyAva
public LocallyAvailableResourceCandidates findCandidates(ArtifactRevisionId criterion) {
if(!logged){
LOGGER.warn("Unable to locate local Maven repository.");
- LOGGER.debug("Problems while locating local maven repository.", ex);
+ LOGGER.debug("Problems while locating local Maven repository.", ex);
logged = true;
}
return new LocallyAvailableResourceCandidates() {
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/transfer/DefaultCacheAwareExternalResourceAccessor.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/transfer/DefaultCacheAwareExternalResourceAccessor.java
index 97c97b0..2cfb362 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/transfer/DefaultCacheAwareExternalResourceAccessor.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/transfer/DefaultCacheAwareExternalResourceAccessor.java
@@ -17,12 +17,12 @@
package org.gradle.api.internal.externalresource.transfer;
import org.gradle.api.Nullable;
+import org.gradle.api.internal.externalresource.DefaultLocallyAvailableExternalResource;
import org.gradle.api.internal.externalresource.ExternalResource;
-import org.gradle.api.internal.externalresource.LocallyAvailableExternalResource;
import org.gradle.api.internal.externalresource.cached.CachedExternalResource;
import org.gradle.api.internal.externalresource.cached.CachedExternalResourceAdapter;
import org.gradle.api.internal.externalresource.cached.CachedExternalResourceIndex;
-import org.gradle.api.internal.externalresource.local.LocallyAvailableResource;
+import org.gradle.internal.resource.local.LocallyAvailableResource;
import org.gradle.api.internal.externalresource.local.LocallyAvailableResourceCandidates;
import org.gradle.api.internal.externalresource.metadata.ExternalResourceMetaData;
import org.gradle.api.internal.externalresource.metadata.ExternalResourceMetaDataCompare;
@@ -94,7 +94,7 @@ public class DefaultCacheAwareExternalResourceAccessor implements CacheAwareExte
LocallyAvailableResource local = localCandidates.findByHashValue(remoteChecksum);
if (local != null) {
LOGGER.info("Found locally available resource with matching checksum: [{}, {}]", location, local.getFile());
- return new LocallyAvailableExternalResource(location, local, remoteMetaData);
+ return new DefaultLocallyAvailableExternalResource(location, local, remoteMetaData);
}
}
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/transfer/ProgressLoggingExternalResourceAccessor.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/transfer/ProgressLoggingExternalResourceAccessor.java
index 32182a8..ff1b095 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/transfer/ProgressLoggingExternalResourceAccessor.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/transfer/ProgressLoggingExternalResourceAccessor.java
@@ -16,8 +16,9 @@
package org.gradle.api.internal.externalresource.transfer;
-import org.apache.ivy.plugins.repository.Resource;
+import org.gradle.api.Action;
import org.gradle.api.Nullable;
+import org.gradle.api.Transformer;
import org.gradle.api.internal.externalresource.ExternalResource;
import org.gradle.api.internal.externalresource.metadata.ExternalResourceMetaData;
import org.gradle.logging.ProgressLoggerFactory;
@@ -81,8 +82,12 @@ public class ProgressLoggingExternalResourceAccessor extends AbstractProgressLog
}
}
- public Resource clone(String cloneName) {
- return resource.clone(cloneName);
+ public void withContent(Action<? super InputStream> readAction) throws IOException {
+ resource.withContent(readAction);
+ }
+
+ public <T> T withContent(Transformer<? extends T, ? super InputStream> readAction) throws IOException {
+ return resource.withContent(readAction);
}
public void close() throws IOException {
@@ -114,10 +119,6 @@ public class ProgressLoggingExternalResourceAccessor extends AbstractProgressLog
return resource.isLocal();
}
- public InputStream openStream() throws IOException {
- return resource.openStream();
- }
-
public String toString(){
return resource.toString();
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/transport/file/FileResourceConnector.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/transport/file/FileResourceConnector.java
index c375699..94e696a 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/transport/file/FileResourceConnector.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/transport/file/FileResourceConnector.java
@@ -16,18 +16,16 @@
package org.gradle.api.internal.externalresource.transport.file;
import org.apache.commons.io.IOUtils;
+import org.gradle.api.internal.externalresource.DefaultLocallyAvailableExternalResource;
import org.gradle.api.internal.externalresource.ExternalResource;
-import org.gradle.api.internal.externalresource.LocallyAvailableExternalResource;
-import org.gradle.api.internal.externalresource.local.DefaultLocallyAvailableResource;
import org.gradle.api.internal.externalresource.metadata.ExternalResourceMetaData;
import org.gradle.api.internal.externalresource.transfer.ExternalResourceAccessor;
import org.gradle.api.internal.externalresource.transfer.ExternalResourceLister;
import org.gradle.api.internal.externalresource.transfer.ExternalResourceUploader;
import org.gradle.internal.Factory;
+import org.gradle.internal.resource.local.DefaultLocallyAvailableResource;
import org.gradle.util.GFileUtils;
import org.gradle.util.hash.HashValue;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileOutputStream;
@@ -37,9 +35,6 @@ import java.util.ArrayList;
import java.util.List;
public class FileResourceConnector implements ExternalResourceLister, ExternalResourceAccessor, ExternalResourceUploader {
-
- private static final Logger LOGGER = LoggerFactory.getLogger(FileResourceConnector.class);
-
public List<String> list(String parent) throws IOException {
File dir = getFile(parent);
if (dir.exists() && dir.isDirectory()) {
@@ -81,7 +76,7 @@ public class FileResourceConnector implements ExternalResourceLister, ExternalRe
if (!localFile.exists()) {
return null;
}
- return new LocallyAvailableExternalResource(location, new DefaultLocallyAvailableResource(localFile));
+ return new DefaultLocallyAvailableExternalResource(location, new DefaultLocallyAvailableResource(localFile));
}
public ExternalResourceMetaData getMetaData(String location) throws IOException {
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/transport/file/FileTransport.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/transport/file/FileTransport.java
index 652e5d6..240e7d4 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/transport/file/FileTransport.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/transport/file/FileTransport.java
@@ -15,8 +15,8 @@
*/
package org.gradle.api.internal.externalresource.transport.file;
-import org.apache.ivy.core.cache.RepositoryCacheManager;
import org.gradle.api.Nullable;
+import org.gradle.api.internal.artifacts.repositories.cachemanager.RepositoryArtifactCache;
import org.gradle.api.internal.artifacts.repositories.resolver.ExternalResourceResolver;
import org.gradle.api.internal.artifacts.repositories.transport.RepositoryTransport;
import org.gradle.api.internal.externalresource.ExternalResource;
@@ -32,10 +32,10 @@ import java.net.URI;
public class FileTransport implements RepositoryTransport {
private final String name;
- private final RepositoryCacheManager repositoryCacheManager;
+ private final RepositoryArtifactCache repositoryCacheManager;
private final ExternalResourceRepository repository;
- public FileTransport(String name, RepositoryCacheManager repositoryCacheManager, TemporaryFileProvider temporaryFileProvider) {
+ public FileTransport(String name, RepositoryArtifactCache repositoryCacheManager, TemporaryFileProvider temporaryFileProvider) {
this.name = name;
this.repositoryCacheManager = repositoryCacheManager;
repository = createRepository(temporaryFileProvider);
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/transport/http/ApacheDirectoryListingParser.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/transport/http/ApacheDirectoryListingParser.java
index 7762d60..437d14e 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/transport/http/ApacheDirectoryListingParser.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/transport/http/ApacheDirectoryListingParser.java
@@ -25,8 +25,7 @@ import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
-import java.io.IOException;
-import java.io.StringReader;
+import java.io.*;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
@@ -40,14 +39,14 @@ public class ApacheDirectoryListingParser {
public ApacheDirectoryListingParser() {
}
- public List<URI> parse(URI baseURI, byte[] content, String contentType) throws Exception {
+ public List<URI> parse(URI baseURI, InputStream content, String contentType) throws Exception {
baseURI = addTrailingSlashes(baseURI);
if (contentType == null || !contentType.startsWith("text/html")) {
throw new ResourceException(String.format("Unsupported ContentType %s for DirectoryListing", contentType));
}
String contentEncoding = contentType.contains("charset=") ? contentType.substring(contentType.indexOf('=') + 1) : "utf-8";
- final String htmlText = new String(content, contentEncoding);
- final InputSource inputSource = new InputSource(new StringReader(htmlText));
+ final Reader htmlText = new InputStreamReader(content, contentEncoding);
+ final InputSource inputSource = new InputSource(htmlText);
final SAXParser htmlParser = new SAXParser();
final AnchorListerHandler anchorListerHandler = new AnchorListerHandler();
htmlParser.setContentHandler(anchorListerHandler);
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/transport/http/HttpResourceLister.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/transport/http/HttpResourceLister.java
index 5905481..ad5179d 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/transport/http/HttpResourceLister.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/transport/http/HttpResourceLister.java
@@ -16,12 +16,12 @@
package org.gradle.api.internal.externalresource.transport.http;
-import org.gradle.api.internal.externalresource.ExternalResource;
+import org.gradle.api.Transformer;
import org.gradle.api.internal.externalresource.transfer.ExternalResourceLister;
import org.gradle.api.internal.resource.ResourceException;
-import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
@@ -35,7 +35,7 @@ public class HttpResourceLister implements ExternalResourceLister {
}
public List<String> list(String parent) throws IOException {
- URI baseURI;
+ final URI baseURI;
try {
baseURI = new URI(parent);
} catch (URISyntaxException ex) {
@@ -46,15 +46,18 @@ public class HttpResourceLister implements ExternalResourceLister {
return null;
}
try {
- byte[] resourceContent = loadResourceContent(resource);
- String contentType = resource.getContentType();
- ApacheDirectoryListingParser directoryListingParser = new ApacheDirectoryListingParser();
- try {
- List<URI> uris = directoryListingParser.parse(baseURI, resourceContent, contentType);
- return convertToStringList(uris);
- } catch (Exception e) {
- throw new ResourceException("Unable to parse Http directory listing", e);
- }
+ return resource.withContent(new Transformer<List<String>, InputStream>() {
+ public List<String> transform(InputStream inputStream) {
+ String contentType = resource.getContentType();
+ ApacheDirectoryListingParser directoryListingParser = new ApacheDirectoryListingParser();
+ try {
+ List<URI> uris = directoryListingParser.parse(baseURI, inputStream, contentType);
+ return convertToStringList(uris);
+ } catch (Exception e) {
+ throw new ResourceException("Unable to parse Http directory listing", e);
+ }
+ }
+ });
} finally {
resource.close();
}
@@ -67,10 +70,4 @@ public class HttpResourceLister implements ExternalResourceLister {
}
return ret;
}
-
- private byte[] loadResourceContent(ExternalResource resource) throws IOException {
- ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
- resource.writeTo(outputStream);
- return outputStream.toByteArray();
- }
}
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/transport/http/HttpTransport.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/transport/http/HttpTransport.java
index c23ea02..e8c10d2 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/transport/http/HttpTransport.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/externalresource/transport/http/HttpTransport.java
@@ -15,8 +15,8 @@
*/
package org.gradle.api.internal.externalresource.transport.http;
-import org.apache.ivy.core.cache.RepositoryCacheManager;
import org.gradle.api.artifacts.repositories.PasswordCredentials;
+import org.gradle.api.internal.artifacts.repositories.cachemanager.RepositoryArtifactCache;
import org.gradle.api.internal.artifacts.repositories.resolver.ExternalResourceResolver;
import org.gradle.api.internal.artifacts.repositories.transport.RepositoryTransport;
import org.gradle.api.internal.externalresource.cached.CachedExternalResourceIndex;
@@ -32,10 +32,10 @@ import java.net.URI;
public class HttpTransport implements RepositoryTransport {
private final String name;
- private final RepositoryCacheManager repositoryCacheManager;
+ private final RepositoryArtifactCache repositoryCacheManager;
private final ExternalResourceRepository repository;
- public HttpTransport(String name, PasswordCredentials credentials, RepositoryCacheManager repositoryCacheManager,
+ public HttpTransport(String name, PasswordCredentials credentials, RepositoryArtifactCache repositoryCacheManager,
ProgressLoggerFactory progressLoggerFactory, TemporaryFileProvider temporaryFileProvider,
CachedExternalResourceIndex<String> cachedExternalResourceIndex) {
this.name = name;
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/notations/ClientModuleNotationParserFactory.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/notations/ClientModuleNotationParserFactory.java
index a4451a1..60382b4 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/notations/ClientModuleNotationParserFactory.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/notations/ClientModuleNotationParserFactory.java
@@ -21,9 +21,6 @@ import org.gradle.api.internal.notations.api.NotationParser;
import org.gradle.internal.Factory;
import org.gradle.internal.reflect.Instantiator;
-/**
- * @author Hans Dockter
- */
public class ClientModuleNotationParserFactory implements Factory<NotationParser<ClientModule>> {
private final Instantiator instantiator;
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/notations/DependencyMapNotationParser.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/notations/DependencyMapNotationParser.java
index c15e792..f6f5b72 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/notations/DependencyMapNotationParser.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/notations/DependencyMapNotationParser.java
@@ -16,17 +16,14 @@
package org.gradle.api.internal.notations;
import org.gradle.api.artifacts.ExternalDependency;
-import org.gradle.internal.reflect.Instantiator;
import org.gradle.api.internal.artifacts.dsl.dependencies.ModuleFactoryHelper;
import org.gradle.api.internal.notations.parsers.MapKey;
import org.gradle.api.internal.notations.parsers.MapNotationParser;
import org.gradle.api.tasks.Optional;
+import org.gradle.internal.reflect.Instantiator;
import java.util.Collection;
-/**
- * @author Hans Dockter
- */
public class DependencyMapNotationParser<T extends ExternalDependency> extends MapNotationParser<T> {
private final Instantiator instantiator;
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/notations/DependencyNotationParser.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/notations/DependencyNotationParser.java
index 3f019dd..dcf7572 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/notations/DependencyNotationParser.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/notations/DependencyNotationParser.java
@@ -22,9 +22,6 @@ import org.gradle.api.internal.notations.api.NotationParser;
import java.util.Collection;
-/**
- * by Szczepan Faber, created at: 11/8/11
- */
public class DependencyNotationParser implements NotationParser<Dependency> {
private final NotationParser<Dependency> delegate;
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/notations/DependencyProjectNotationParser.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/notations/DependencyProjectNotationParser.java
index f4e0cd8..4e0fd13 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/notations/DependencyProjectNotationParser.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/notations/DependencyProjectNotationParser.java
@@ -23,9 +23,6 @@ import org.gradle.api.internal.notations.parsers.TypedNotationParser;
import java.util.Collection;
-/**
- * by Szczepan Faber, created at: 11/10/11
- */
public class DependencyProjectNotationParser extends TypedNotationParser<Project, ProjectDependency> {
private final DefaultProjectDependencyFactory factory;
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/notations/DependencyStringNotationParser.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/notations/DependencyStringNotationParser.java
index 45f2f5e..c8d100e 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/notations/DependencyStringNotationParser.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/notations/DependencyStringNotationParser.java
@@ -28,9 +28,6 @@ import java.util.Collection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-/**
- * by Szczepan Faber, created at: 11/10/11
- */
public class DependencyStringNotationParser<T extends ExternalDependency> extends TypedNotationParser<CharSequence, T> {
private final Instantiator instantiator;
diff --git a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/notations/ProjectDependencyFactory.java b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/notations/ProjectDependencyFactory.java
index 9995133..687af32 100644
--- a/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/notations/ProjectDependencyFactory.java
+++ b/subprojects/core-impl/src/main/groovy/org/gradle/api/internal/notations/ProjectDependencyFactory.java
@@ -25,9 +25,6 @@ import org.gradle.api.tasks.Optional;
import java.util.Collection;
import java.util.Map;
-/**
- * @author Hans Dockter
- */
public class ProjectDependencyFactory {
private final DefaultProjectDependencyFactory factory;
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/artifacts/ArtifactsTestUtils.java b/subprojects/core-impl/src/test/groovy/org/gradle/api/artifacts/ArtifactsTestUtils.java
deleted file mode 100644
index be631ac..0000000
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/artifacts/ArtifactsTestUtils.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.artifacts;
-
-import org.apache.ivy.core.module.descriptor.Artifact;
-import org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier;
-import org.gradle.api.internal.artifacts.DefaultResolvedArtifact;
-import org.gradle.internal.Factory;
-import org.jmock.Expectations;
-import org.jmock.Mockery;
-
-import java.io.File;
-import java.util.Collections;
-
-public class ArtifactsTestUtils {
-
- public static DefaultResolvedArtifact createResolvedArtifact(final Mockery context, final String name, final String type, final String extension, final File file) {
- final Artifact artifactStub = context.mock(Artifact.class, "artifact" + name);
- context.checking(new Expectations() {{
- allowing(artifactStub).getName();
- will(returnValue(name));
- allowing(artifactStub).getType();
- will(returnValue(type));
- allowing(artifactStub).getExt();
- will(returnValue(extension));
- allowing(artifactStub).getExtraAttributes();
- will(returnValue(Collections.emptyMap()));
- allowing(artifactStub).getQualifiedExtraAttributes();
- will(returnValue(Collections.emptyMap()));
- allowing(artifactStub).getExtraAttribute(with(org.hamcrest.Matchers.notNullValue(String.class)));
- will(returnValue(null));
- }});
- final Factory artifactSource = context.mock(Factory.class);
- context.checking(new Expectations() {{
- allowing(artifactSource).create();
- will(returnValue(file));
- }});
- final ResolvedDependency resolvedDependency = context.mock(ResolvedDependency.class);
- final ResolvedModuleVersion version = context.mock(ResolvedModuleVersion.class);
- context.checking(new Expectations() {{
- allowing(resolvedDependency).getModule();
- will(returnValue(version));
- allowing(version).getId();
- will(returnValue(new DefaultModuleVersionIdentifier("group", name, "1.2")));
- }});
- return new DefaultResolvedArtifact(resolvedDependency, artifactStub, artifactSource);
- }
-
-}
\ No newline at end of file
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/DefaultArtifactIdentifierTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/DefaultArtifactIdentifierTest.groovy
new file mode 100644
index 0000000..61dbe88
--- /dev/null
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/DefaultArtifactIdentifierTest.groovy
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts
+
+import spock.lang.Specification
+
+import static org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier.newId
+import static org.gradle.util.Matchers.strictlyEqual
+import static org.hamcrest.MatcherAssert.assertThat
+
+class DefaultArtifactIdentifierTest extends Specification {
+
+ def "equals"() {
+ def base = new DefaultArtifactIdentifier(newId("org", "lib", "1.0"), "someArtifact", "jar", "jar", "")
+ def same = new DefaultArtifactIdentifier(newId("org", "lib", "1.0"), "someArtifact", "jar", "jar", "")
+
+ def badId = new DefaultArtifactIdentifier(newId("org", "lib", "2.0"), "someArtifact", "jar", "jar", "")
+ def badName = new DefaultArtifactIdentifier(newId("org", "lib", "1.0"), "foo", "jar", "jar", "")
+ def badType = new DefaultArtifactIdentifier(newId("org", "lib", "1.0"), "someArtifact", "bar", "jar", "")
+ def badExtension = new DefaultArtifactIdentifier(newId("org", "lib", "1.0"), "someArtifact", "jar", "xxx", "")
+ def badClassifier = new DefaultArtifactIdentifier(newId("org", "lib", "1.0"), "someArtifact", "jar", "jar", "sources")
+
+ expect:
+ assertThat(base, strictlyEqual(same))
+
+ base != badId
+ base != badName
+ base != badType
+ base != badExtension
+ base != badClassifier
+ }
+}
\ No newline at end of file
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/DefaultDependencyManagementServicesTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/DefaultDependencyManagementServicesTest.groovy
index 9c33caf..513d7cc 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/DefaultDependencyManagementServicesTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/DefaultDependencyManagementServicesTest.groovy
@@ -67,6 +67,7 @@ class DefaultDependencyManagementServicesTest extends Specification {
_ * parent.get(TimeProvider) >> Mock(TimeProvider)
_ * parent.get(TemporaryFileProvider) >> Mock(TemporaryFileProvider)
_ * parent.get(ProjectAccessListener) >> Mock(ProjectAccessListener)
+ _ * parent.get(FileResolver) >> Stub(FileResolver)
}
private CacheRepository initCacheRepository() {
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/DefaultModuleVersionSelectorTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/DefaultModuleVersionSelectorTest.groovy
index bf1032d..09e502e 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/DefaultModuleVersionSelectorTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/DefaultModuleVersionSelectorTest.groovy
@@ -16,14 +16,12 @@
package org.gradle.api.internal.artifacts
+import org.apache.ivy.core.module.id.ModuleRevisionId
import spock.lang.Specification
import static org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier.newId
import static org.gradle.api.internal.artifacts.DefaultModuleVersionSelector.newSelector
-/**
- * by Szczepan Faber, created at: 2/11/13
- */
class DefaultModuleVersionSelectorTest extends Specification {
def "equality"() {
@@ -56,4 +54,16 @@ class DefaultModuleVersionSelectorTest extends Specification {
!selector.matchesStrictly(differentName)
!selector.matchesStrictly(differentVersion)
}
+
+ def "construct from ModuleRevisionId"() {
+ def module = ModuleRevisionId.newInstance("group", "name", "version")
+ def selector = newSelector(module)
+
+ expect:
+ with(selector) {
+ group == "group"
+ name == "name"
+ version == "version"
+ }
+ }
}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/DefaultResolvedArtifactTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/DefaultResolvedArtifactTest.groovy
index eb7aba8..b1cb0cc 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/DefaultResolvedArtifactTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/DefaultResolvedArtifactTest.groovy
@@ -16,7 +16,6 @@
package org.gradle.api.internal.artifacts
import org.apache.ivy.core.module.descriptor.Artifact
-import org.gradle.api.artifacts.ResolvedDependency
import org.gradle.api.artifacts.ResolvedModuleVersion
import org.gradle.internal.Factory
import org.gradle.util.Matchers
@@ -27,29 +26,29 @@ class DefaultResolvedArtifactTest extends Specification {
def "uses extended attributes to determine classifier"() {
Artifact ivyArtifact = ivyArtifact("name", "type", "ext", ['m:classifier': 'classifier'])
- ResolvedDependency dependency = Mock()
- def artifact = new DefaultResolvedArtifact(dependency, ivyArtifact, artifactSource)
+ ResolvedModuleVersion owner = Mock()
+ def artifact = new DefaultResolvedArtifact(owner, {} as Factory, ivyArtifact, artifactSource, 0)
expect:
artifact.classifier == 'classifier'
}
def "attributes are equal when module, name, type, extension and extended attributes are equal"() {
- ResolvedDependency dependency = dep("group", "module1", "1.2")
- ResolvedDependency dependencySameModule = dep("group", "module1", "1.2")
- ResolvedDependency dependency2 = dep("group", "module2", "1-beta")
+ def dependency = dep("group", "module1", "1.2")
+ def dependencySameModule = dep("group", "module1", "1.2")
+ def dependency2 = dep("group", "module2", "1-beta")
Artifact ivyArt = ivyArtifact("name", "type", "ext", [attr: "value"])
Artifact ivyArtifactWithDifferentName = ivyArtifact("name2", "type", "ext", [attr: "value"])
Artifact ivyArtifactWithDifferentType = ivyArtifact("name", "type2", "ext", [attr: "value"])
Artifact ivyArtifactWithDifferentExt = ivyArtifact("name", "type", "ext2", [attr: "value"])
Artifact ivyArtWithDifferentAttributes = ivyArtifact("name", "type", "ext", [attr: "value2"])
- def artifact = new DefaultResolvedArtifact(dependency, ivyArt, artifactSource)
- def equalArtifact = new DefaultResolvedArtifact(dependencySameModule, ivyArt, artifactSource)
- def differentModule = new DefaultResolvedArtifact(dependency2, ivyArt, artifactSource)
- def differentName = new DefaultResolvedArtifact(dependency, ivyArtifactWithDifferentName, artifactSource)
- def differentType = new DefaultResolvedArtifact(dependency, ivyArtifactWithDifferentType, artifactSource)
- def differentExtension = new DefaultResolvedArtifact(dependency, ivyArtifactWithDifferentExt, artifactSource)
- def differentAttributes = new DefaultResolvedArtifact(dependency, ivyArtWithDifferentAttributes, artifactSource)
+ def artifact = new DefaultResolvedArtifact(dependency, {} as Factory, ivyArt, artifactSource, 0)
+ def equalArtifact = new DefaultResolvedArtifact(dependencySameModule, {} as Factory, ivyArt, artifactSource, 0)
+ def differentModule = new DefaultResolvedArtifact(dependency2, {} as Factory, ivyArt, artifactSource, 0)
+ def differentName = new DefaultResolvedArtifact(dependency, {} as Factory, ivyArtifactWithDifferentName, artifactSource, 0)
+ def differentType = new DefaultResolvedArtifact(dependency, {} as Factory, ivyArtifactWithDifferentType, artifactSource, 0)
+ def differentExtension = new DefaultResolvedArtifact(dependency, {} as Factory, ivyArtifactWithDifferentExt, artifactSource, 0)
+ def differentAttributes = new DefaultResolvedArtifact(dependency, {} as Factory, ivyArtWithDifferentAttributes, artifactSource, 0)
expect:
artifact Matchers.strictlyEqual(equalArtifact)
@@ -70,10 +69,8 @@ class DefaultResolvedArtifactTest extends Specification {
}
def dep(String group, String moduleName, String version) {
- ResolvedDependency dependency = Mock()
ResolvedModuleVersion module = Mock()
- _ * dependency.module >> module
_ * module.id >> new DefaultModuleVersionIdentifier(group, moduleName, version)
- return dependency
+ module
}
}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/DefaultResolvedDependencySpec.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/DefaultResolvedDependencySpec.groovy
index 35836cf..a28a53f 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/DefaultResolvedDependencySpec.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/DefaultResolvedDependencySpec.groovy
@@ -19,7 +19,7 @@ import org.gradle.api.artifacts.ResolvedArtifact
import spock.lang.Specification
class DefaultResolvedDependencySpec extends Specification {
- final DefaultResolvedDependency dependency = new DefaultResolvedDependency("name", "group", "module", "version", "config")
+ final dependency = new DefaultResolvedDependency(DefaultModuleVersionIdentifier.newId("group", "module", "version"), "config")
def "provides meta-data about the module"() {
expect:
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/DefaultResolvedDependencyTest.java b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/DefaultResolvedDependencyTest.java
index 1d110a5..4a011d9 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/DefaultResolvedDependencyTest.java
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/DefaultResolvedDependencyTest.java
@@ -15,10 +15,15 @@
*/
package org.gradle.api.internal.artifacts;
+import org.apache.ivy.core.module.descriptor.Artifact;
import org.gradle.api.InvalidUserDataException;
import org.gradle.api.artifacts.ResolvedArtifact;
import org.gradle.api.artifacts.ResolvedDependency;
+import org.gradle.api.artifacts.ResolvedModuleVersion;
+import org.gradle.internal.Factory;
import org.gradle.util.JUnit4GroovyMockery;
+import org.jmock.Expectations;
+import org.jmock.Mockery;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.junit.Test;
@@ -28,16 +33,13 @@ import java.util.Set;
import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Sets.newHashSet;
-import static org.gradle.api.artifacts.ArtifactsTestUtils.createResolvedArtifact;
+import static org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier.newId;
import static org.gradle.util.Matchers.strictlyEqual;
import static org.gradle.util.WrapUtil.toSet;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertThat;
-/**
- * @author Hans Dockter
- */
public class DefaultResolvedDependencyTest {
private JUnit4Mockery context = new JUnit4GroovyMockery();
@@ -47,7 +49,7 @@ public class DefaultResolvedDependencyTest {
String someName = "someName";
String someVersion = "someVersion";
String someConfiguration = "someConfiguration";
- DefaultResolvedDependency resolvedDependency = new DefaultResolvedDependency(someGroup, someName, someVersion, someConfiguration);
+ DefaultResolvedDependency resolvedDependency = new DefaultResolvedDependency(newId(someGroup, someName, someVersion), someConfiguration);
assertThat(resolvedDependency.getName(), equalTo(someGroup + ":" + someName + ":" + someVersion));
assertThat(resolvedDependency.getModuleGroup(), equalTo(someGroup));
assertThat(resolvedDependency.getModuleName(), equalTo(someName));
@@ -62,9 +64,9 @@ public class DefaultResolvedDependencyTest {
public void getAllModuleArtifacts() {
ResolvedArtifact moduleArtifact = createArtifact("moduleArtifact");
ResolvedArtifact childModuleArtifact = createArtifact("childModuleArtifact");
- DefaultResolvedDependency resolvedDependency = new DefaultResolvedDependency("someGroup", "someName", "someVersion", "someConfiguration");
+ DefaultResolvedDependency resolvedDependency = new DefaultResolvedDependency(newId("someGroup", "someName", "someVersion"), "someConfiguration");
resolvedDependency.addModuleArtifact(moduleArtifact);
- DefaultResolvedDependency childDependency = new DefaultResolvedDependency("someGroup", "someChild", "someVersion", "someChildConfiguration");
+ DefaultResolvedDependency childDependency = new DefaultResolvedDependency(newId("someGroup", "someChild", "someVersion"), "someChildConfiguration");
childDependency.addModuleArtifact(childModuleArtifact);
resolvedDependency.getChildren().add(childDependency);
assertThat(resolvedDependency.getAllModuleArtifacts(), equalTo(toSet(moduleArtifact, childModuleArtifact)));
@@ -88,8 +90,40 @@ public class DefaultResolvedDependencyTest {
return createResolvedArtifact(context, name, "someType", "someExt", new File("pathTo" + name));
}
+ public static DefaultResolvedArtifact createResolvedArtifact(final Mockery context, final String name, final String type, final String extension, final File file) {
+ final Artifact artifactStub = context.mock(Artifact.class, "artifact" + name);
+ context.checking(new Expectations() {{
+ allowing(artifactStub).getName();
+ will(returnValue(name));
+ allowing(artifactStub).getType();
+ will(returnValue(type));
+ allowing(artifactStub).getExt();
+ will(returnValue(extension));
+ allowing(artifactStub).getExtraAttributes();
+ will(returnValue(Collections.emptyMap()));
+ allowing(artifactStub).getQualifiedExtraAttributes();
+ will(returnValue(Collections.emptyMap()));
+ allowing(artifactStub).getExtraAttribute(with(org.hamcrest.Matchers.notNullValue(String.class)));
+ will(returnValue(null));
+ }});
+ final Factory artifactSource = context.mock(Factory.class);
+ context.checking(new Expectations() {{
+ allowing(artifactSource).create();
+ will(returnValue(file));
+ }});
+ final ResolvedDependency resolvedDependency = context.mock(ResolvedDependency.class);
+ final ResolvedModuleVersion version = context.mock(ResolvedModuleVersion.class);
+ context.checking(new Expectations() {{
+ allowing(resolvedDependency).getModule();
+ will(returnValue(version));
+ allowing(version).getId();
+ will(returnValue(new DefaultModuleVersionIdentifier("group", name, "1.2")));
+ }});
+ return new DefaultResolvedArtifact(resolvedDependency.getModule(), null , artifactStub, artifactSource, 0);
+ }
+
private DefaultResolvedDependency createResolvedDependency() {
- return new DefaultResolvedDependency("someGroup", "someName", "someVersion", "someConfiguration");
+ return new DefaultResolvedDependency(newId("someGroup", "someName", "someVersion"), "someConfiguration");
}
@Test
@@ -106,7 +140,7 @@ public class DefaultResolvedDependencyTest {
public void getArtifactsWithParentWithoutParentArtifacts() {
DefaultResolvedDependency resolvedDependency = createResolvedDependency();
- DefaultResolvedDependency parent = new DefaultResolvedDependency("someGroup", "parent", "someVersion", "someConfiguration");
+ DefaultResolvedDependency parent = new DefaultResolvedDependency(newId("someGroup", "parent", "someVersion"), "someConfiguration");
resolvedDependency.getParents().add(parent);
assertThat(resolvedDependency.getArtifacts(parent), equalTo(Collections.<ResolvedArtifact>emptySet()));
}
@@ -115,7 +149,7 @@ public class DefaultResolvedDependencyTest {
public void getParentArtifactsWithParentWithoutParentArtifacts() {
DefaultResolvedDependency resolvedDependency = createResolvedDependency();
- DefaultResolvedDependency parent = new DefaultResolvedDependency("someGroup", "parent", "someVersion", "someConfiguration");
+ DefaultResolvedDependency parent = new DefaultResolvedDependency(newId("someGroup", "parent", "someVersion"), "someConfiguration");
resolvedDependency.getParents().add(parent);
assertThat(resolvedDependency.getParentArtifacts(parent), equalTo(Collections.<ResolvedArtifact>emptySet()));
}
@@ -123,7 +157,7 @@ public class DefaultResolvedDependencyTest {
@Test(expected = InvalidUserDataException.class)
public void getParentArtifactsWithUnknownParent() {
DefaultResolvedDependency resolvedDependency = createResolvedDependency();
- DefaultResolvedDependency unknownParent = new DefaultResolvedDependency("someGroup", "parent2", "someVersion", "someConfiguration");
+ DefaultResolvedDependency unknownParent = new DefaultResolvedDependency(newId("someGroup", "parent2", "someVersion"), "someConfiguration");
assertThat(resolvedDependency.getParentArtifacts(unknownParent),
equalTo(Collections.<ResolvedArtifact>emptySet()));
}
@@ -133,7 +167,7 @@ public class DefaultResolvedDependencyTest {
Set<ResolvedArtifact> someModuleArtifacts = toSet(createArtifact("someModuleResolvedArtifact"));
DefaultResolvedDependency resolvedDependency = createResolvedDependency();
- DefaultResolvedDependency unknownParent = new DefaultResolvedDependency("someGroup", "parent2", "someVersion", "someConfiguration");
+ DefaultResolvedDependency unknownParent = new DefaultResolvedDependency(newId("someGroup", "parent2", "someVersion"), "someConfiguration");
assertThat(resolvedDependency.getParentArtifacts(unknownParent),
equalTo(someModuleArtifacts));
}
@@ -147,7 +181,7 @@ public class DefaultResolvedDependencyTest {
createAndAddParent("parent2", resolvedDependency, newHashSet(createArtifact("parent2Specific")));
- DefaultResolvedDependency child = new DefaultResolvedDependency("someGroup", "someChild", "someVersion", "someChildConfiguration");
+ DefaultResolvedDependency child = new DefaultResolvedDependency(newId("someGroup", "someChild", "someVersion"), "someChildConfiguration");
resolvedDependency.getChildren().add(child);
Set<ResolvedArtifact> childParent1SpecificArtifacts = newHashSet(createArtifact("childParent1Specific"));
@@ -162,12 +196,12 @@ public class DefaultResolvedDependencyTest {
@Test
public void equalsAndHashCode() {
- DefaultResolvedDependency dependency = new DefaultResolvedDependency("group", "name", "version", "config");
- DefaultResolvedDependency same = new DefaultResolvedDependency("group", "name", "version", "config");
- DefaultResolvedDependency differentGroup = new DefaultResolvedDependency("other", "name", "version", "config");
- DefaultResolvedDependency differentName = new DefaultResolvedDependency("group", "other", "version", "config");
- DefaultResolvedDependency differentVersion = new DefaultResolvedDependency("group", "name", "other", "config");
- DefaultResolvedDependency differentConfiguration = new DefaultResolvedDependency("group", "name", "version", "other");
+ DefaultResolvedDependency dependency = new DefaultResolvedDependency(newId("group", "name", "version"), "config");
+ DefaultResolvedDependency same = new DefaultResolvedDependency(newId("group", "name", "version"), "config");
+ DefaultResolvedDependency differentGroup = new DefaultResolvedDependency(newId("other", "name", "version"), "config");
+ DefaultResolvedDependency differentName = new DefaultResolvedDependency(newId("group", "other", "version"), "config");
+ DefaultResolvedDependency differentVersion = new DefaultResolvedDependency(newId("group", "name", "other"), "config");
+ DefaultResolvedDependency differentConfiguration = new DefaultResolvedDependency(newId("group", "name", "version"), "other");
assertThat(dependency, strictlyEqual(same));
assertThat(dependency, not(equalTo(differentGroup)));
@@ -177,7 +211,7 @@ public class DefaultResolvedDependencyTest {
}
private DefaultResolvedDependency createAndAddParent(String parentName, DefaultResolvedDependency resolvedDependency, Set<ResolvedArtifact> parentSpecificArtifacts) {
- DefaultResolvedDependency parent = new DefaultResolvedDependency("someGroup", parentName, "someVersion", "someConfiguration");
+ DefaultResolvedDependency parent = new DefaultResolvedDependency(newId("someGroup", parentName, "someVersion"), "someConfiguration");
resolvedDependency.getParents().add(parent);
resolvedDependency.addParentSpecificArtifacts(parent, parentSpecificArtifacts);
return parent;
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ModuleVersionSelectorSerializerTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ModuleVersionSelectorSerializerTest.groovy
new file mode 100644
index 0000000..40e3c28
--- /dev/null
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ModuleVersionSelectorSerializerTest.groovy
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts
+
+import org.gradle.messaging.serialize.SerializerSpec
+
+import static org.gradle.api.internal.artifacts.DefaultModuleVersionSelector.newSelector
+
+class ModuleVersionSelectorSerializerTest extends SerializerSpec {
+ private serializer = new ModuleVersionSelectorSerializer()
+
+ def "serializes"() {
+ when:
+ def result = serialize(newSelector("org", "foo", "5.0"), serializer)
+
+ then:
+ result == newSelector("org", "foo", "5.0")
+ }
+}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ResolvedConfigurationIdentifierSerializerTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ResolvedConfigurationIdentifierSerializerTest.groovy
new file mode 100644
index 0000000..233d792
--- /dev/null
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ResolvedConfigurationIdentifierSerializerTest.groovy
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts
+
+import org.gradle.messaging.serialize.SerializerSpec
+
+import static org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier.newId
+
+class ResolvedConfigurationIdentifierSerializerTest extends SerializerSpec {
+
+ def s = new ResolvedConfigurationIdentifierSerializer()
+
+ def "serializes"() {
+ def id = newId("org", "foo", "2.0")
+
+ when:
+ def out = serialize(new ResolvedConfigurationIdentifier(id, "conf"), s)
+
+ then:
+ out.configuration == "conf"
+ out.id == id
+ }
+}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ResolvedConfigurationIdentifierSpec.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ResolvedConfigurationIdentifierSpec.groovy
index e975224..441ce80 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ResolvedConfigurationIdentifierSpec.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ResolvedConfigurationIdentifierSpec.groovy
@@ -21,15 +21,17 @@ package org.gradle.api.internal.artifacts
import spock.lang.Specification
import org.gradle.util.Matchers
+import static org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier.*
+
class ResolvedConfigurationIdentifierSpec extends Specification {
def equalsAndHashCode() {
when:
- ResolvedConfigurationIdentifier id = new ResolvedConfigurationIdentifier('group', 'name', 'version', 'config')
- ResolvedConfigurationIdentifier same = new ResolvedConfigurationIdentifier('group', 'name', 'version', 'config')
- ResolvedConfigurationIdentifier differentGroup = new ResolvedConfigurationIdentifier('other', 'name', 'version', 'config')
- ResolvedConfigurationIdentifier differentName = new ResolvedConfigurationIdentifier('group', 'other', 'version', 'config')
- ResolvedConfigurationIdentifier differentVersion = new ResolvedConfigurationIdentifier('group', 'name', 'other', 'config')
- ResolvedConfigurationIdentifier differentConfig = new ResolvedConfigurationIdentifier('group', 'name', 'version', 'other')
+ ResolvedConfigurationIdentifier id = new ResolvedConfigurationIdentifier(newId('group', 'name', 'version'), 'config')
+ ResolvedConfigurationIdentifier same = new ResolvedConfigurationIdentifier(newId('group', 'name', 'version'), 'config')
+ ResolvedConfigurationIdentifier differentGroup = new ResolvedConfigurationIdentifier(newId('other', 'name', 'version'), 'config')
+ ResolvedConfigurationIdentifier differentName = new ResolvedConfigurationIdentifier(newId('group', 'other', 'version'), 'config')
+ ResolvedConfigurationIdentifier differentVersion = new ResolvedConfigurationIdentifier(newId('group', 'name', 'other'), 'config')
+ ResolvedConfigurationIdentifier differentConfig = new ResolvedConfigurationIdentifier(newId('group', 'name', 'version'), 'other')
then:
Matchers.strictlyEquals(id, same)
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ResolverResultsSpec.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ResolverResultsSpec.groovy
index 00529ba..29355f6 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ResolverResultsSpec.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ResolverResultsSpec.groovy
@@ -21,9 +21,6 @@ import org.gradle.api.artifacts.ResolvedConfiguration
import org.gradle.api.artifacts.result.ResolutionResult
import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 10/16/12
- */
class ResolverResultsSpec extends Specification {
private resolvedConfiguration = Mock(ResolvedConfiguration)
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/configurations/ConfigurationsTest.java b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/configurations/ConfigurationsTest.java
index 5d97ed4..3a3ecb1 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/configurations/ConfigurationsTest.java
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/configurations/ConfigurationsTest.java
@@ -20,18 +20,10 @@ import org.junit.Test;
import static org.junit.Assert.assertThat;
-/**
- * @author Hans Dockter
- */
public class ConfigurationsTest {
private static final String TEST_CONF = "testConf";
@Test
- public void testUploadInternalTaskName() {
- assertThat(Configurations.uploadInternalTaskName(TEST_CONF), Matchers.equalTo("uploadTestConfInternal"));
- }
-
- @Test
public void testUploadTaskName() {
assertThat(Configurations.uploadTaskName(TEST_CONF), Matchers.equalTo("uploadTestConf"));
}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/configurations/DefaultConfigurationContainerSpec.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/configurations/DefaultConfigurationContainerSpec.groovy
index 7c63a99..848d31c 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/configurations/DefaultConfigurationContainerSpec.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/configurations/DefaultConfigurationContainerSpec.groovy
@@ -46,7 +46,7 @@ public class DefaultConfigurationContainerSpec extends Specification {
resolver, listenerManager, metaDataProvider, _ as ResolutionStrategyInternal) >> conf
when:
- def compile = configurationContainer.add("compile")
+ def compile = configurationContainer.create("compile")
then:
configurationContainer.getByName("compile") == compile
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/configurations/DefaultConfigurationContainerTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/configurations/DefaultConfigurationContainerTest.groovy
index 1cd233a..6efd9ed 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/configurations/DefaultConfigurationContainerTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/configurations/DefaultConfigurationContainerTest.groovy
@@ -35,9 +35,6 @@ import org.junit.runner.RunWith
import static org.hamcrest.Matchers.*
import static org.junit.Assert.assertThat
-/**
- * @author Hans Dockter
- */
@RunWith(JMock)
class DefaultConfigurationContainerTest {
@@ -47,7 +44,7 @@ class DefaultConfigurationContainerTest {
private ListenerManager listenerManager = context.mock(ListenerManager.class)
private DependencyMetaDataProvider metaDataProvider = context.mock(DependencyMetaDataProvider.class)
private Instantiator instantiator = new ClassGeneratorBackedInstantiator(new AsmBackedClassGenerator(), new DirectInstantiator())
- private DefaultConfigurationContainer configurationHandler = instantiator.newInstance(DefaultConfigurationContainer.class,
+ private DefaultConfigurationContainer configurationContainer = instantiator.newInstance(DefaultConfigurationContainer.class,
resolver, instantiator, { name -> name } as DomainObjectContext,
listenerManager, metaDataProvider)
@@ -60,42 +57,42 @@ class DefaultConfigurationContainerTest {
@Test
void addsNewConfigurationWhenConfiguringSelf() {
- configurationHandler.configure {
+ configurationContainer.configure {
newConf
}
- assertThat(configurationHandler.findByName('newConf'), notNullValue())
- assertThat(configurationHandler.newConf, notNullValue())
+ assertThat(configurationContainer.findByName('newConf'), notNullValue())
+ assertThat(configurationContainer.newConf, notNullValue())
}
@Test(expected = UnknownConfigurationException)
void doesNotAddNewConfigurationWhenNotConfiguringSelf() {
- configurationHandler.getByName('unknown')
+ configurationContainer.getByName('unknown')
}
@Test
void makesExistingConfigurationAvailableAsProperty() {
- Configuration configuration = configurationHandler.add('newConf')
+ Configuration configuration = configurationContainer.create('newConf')
assertThat(configuration, notNullValue())
- assertThat(configurationHandler.getByName("newConf"), sameInstance(configuration))
- assertThat(configurationHandler.newConf, sameInstance(configuration))
+ assertThat(configurationContainer.getByName("newConf"), sameInstance(configuration))
+ assertThat(configurationContainer.newConf, sameInstance(configuration))
}
@Test
void addsNewConfigurationWithClosureWhenConfiguringSelf() {
String someDesc = 'desc1'
- configurationHandler.configure {
+ configurationContainer.configure {
newConf {
description = someDesc
}
}
- assertThat(configurationHandler.newConf.getDescription(), equalTo(someDesc))
+ assertThat(configurationContainer.newConf.getDescription(), equalTo(someDesc))
}
@Test
void makesExistingConfigurationAvailableAsConfigureMethod() {
String someDesc = 'desc1'
- configurationHandler.add('newConf')
- Configuration configuration = configurationHandler.newConf {
+ configurationContainer.create('newConf')
+ Configuration configuration = configurationContainer.newConf {
description = someDesc
}
assertThat(configuration.getDescription(), equalTo(someDesc))
@@ -104,8 +101,8 @@ class DefaultConfigurationContainerTest {
@Test
void makesExistingConfigurationAvailableAsConfigureMethodWhenConfiguringSelf() {
String someDesc = 'desc1'
- Configuration configuration = configurationHandler.add('newConf')
- configurationHandler.configure {
+ Configuration configuration = configurationContainer.create('newConf')
+ configurationContainer.configure {
newConf {
description = someDesc
}
@@ -115,6 +112,6 @@ class DefaultConfigurationContainerTest {
@Test(expected = MissingMethodException)
void newConfigurationWithNonClosureParametersShouldThrowMissingMethodEx() {
- configurationHandler.newConf('a', 'b')
+ configurationContainer.newConf('a', 'b')
}
}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/configurations/DefaultConfigurationTest.java b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/configurations/DefaultConfigurationTest.java
index 5384568..736253f 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/configurations/DefaultConfigurationTest.java
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/configurations/DefaultConfigurationTest.java
@@ -270,7 +270,7 @@ public class DefaultConfigurationTest {
@Test
public void filesWithClosureSpec() {
- Closure closure = HelperUtil.toClosure("{ dep -> dep.group == 'group1' }");
+ Closure closure = TestUtil.toClosure("{ dep -> dep.group == 'group1' }");
final Set<File> fileSet = toSet(new File("somePath"));
prepareForFilesBySpec(fileSet);
assertThat(configuration.files(closure), equalTo(fileSet));
@@ -279,7 +279,7 @@ public class DefaultConfigurationTest {
@Test
public void fileCollectionWithClosureSpec() {
- Closure closure = HelperUtil.toClosure("{ dep -> dep.group == 'group1' }");
+ Closure closure = TestUtil.toClosure("{ dep -> dep.group == 'group1' }");
DefaultConfiguration.ConfigurationFileCollection fileCollection = (DefaultConfiguration.ConfigurationFileCollection)
configuration.fileCollection(closure);
assertThat(fileCollection.getDependencySpec().isSatisfiedBy(createDependency("group1", "name", "version")),
@@ -680,7 +680,7 @@ public class DefaultConfigurationTest {
one(closure).call(artifact);
}});
- configuration.getArtifacts().whenObjectAdded(HelperUtil.toClosure(closure));
+ configuration.getArtifacts().whenObjectAdded(TestUtil.toClosure(closure));
configuration.getArtifacts().add(artifact);
}
@@ -695,7 +695,7 @@ public class DefaultConfigurationTest {
one(closure).call(artifact);
}});
- configuration.getArtifacts().whenObjectRemoved(HelperUtil.toClosure(closure));
+ configuration.getArtifacts().whenObjectRemoved(TestUtil.toClosure(closure));
configuration.getArtifacts().remove(artifact);
}
@@ -755,7 +755,7 @@ public class DefaultConfigurationTest {
Set<Dependency> expectedDependenciesToCopy = new HashSet<Dependency>(configuration.getDependencies());
configuration.getDependencies().add(createDependency("group3", "name3", "version3"));
- Closure specClosure = HelperUtil.toClosure("{ element -> !element.group.equals(\"group3\")}");
+ Closure specClosure = TestUtil.toClosure("{ element -> !element.group.equals(\"group3\")}");
Configuration copiedConfiguration = configuration.copy(specClosure);
assertThatCopiedConfigurationHasElementsAndName(copiedConfiguration, expectedDependenciesToCopy);
@@ -800,7 +800,7 @@ public class DefaultConfigurationTest {
Set<Dependency> expectedDependenciesToCopy = new HashSet<Dependency>(configuration.getAllDependencies());
configuration.getDependencies().add(createDependency("group3", "name3", "version3"));
- Closure specClosure = HelperUtil.toClosure("{ element -> !element.group.equals(\"group3\")}");
+ Closure specClosure = TestUtil.toClosure("{ element -> !element.group.equals(\"group3\")}");
Configuration copiedConfiguration = configuration.copyRecursive(specClosure);
assertThatCopiedConfigurationHasElementsAndName(copiedConfiguration, expectedDependenciesToCopy);
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/dsl/ArtifactFileTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/dsl/ArtifactFileTest.groovy
index 878e386..6326326 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/dsl/ArtifactFileTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/dsl/ArtifactFileTest.groovy
@@ -16,9 +16,6 @@
package org.gradle.api.internal.artifacts.dsl
import spock.lang.Specification
-/**
- * @author Hans Dockter
- */
public class ArtifactFileTest extends Specification {
final String module = '1.2'
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/dsl/DefaultArtifactHandlerTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/dsl/DefaultArtifactHandlerTest.groovy
index a31f49b..52b7ef5 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/dsl/DefaultArtifactHandlerTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/dsl/DefaultArtifactHandlerTest.groovy
@@ -16,18 +16,15 @@
package org.gradle.api.internal.artifacts.dsl
-import org.gradle.api.artifacts.PublishArtifactSet
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.ConfigurationContainer
import org.gradle.api.artifacts.PublishArtifact
+import org.gradle.api.artifacts.PublishArtifactSet
import org.gradle.api.internal.artifacts.publish.DefaultPublishArtifact
+import org.gradle.api.internal.notations.api.NotationParser
import org.gradle.util.JUnit4GroovyMockery
import spock.lang.Specification
-import org.gradle.api.internal.notations.api.NotationParser
-/**
- * @author Hans Dockter
- */
class DefaultArtifactHandlerTest extends Specification {
private static final String TEST_CONF_NAME = "someConf"
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/dsl/ModuleVersionSelectorParsersTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/dsl/ModuleVersionSelectorParsersTest.groovy
index f42522c..03dbf4b 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/dsl/ModuleVersionSelectorParsersTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/dsl/ModuleVersionSelectorParsersTest.groovy
@@ -24,9 +24,6 @@ import static org.gradle.api.internal.artifacts.DefaultModuleVersionSelector.new
import static org.gradle.api.internal.artifacts.dsl.ModuleVersionSelectorParsers.multiParser
import static org.gradle.api.internal.artifacts.dsl.ModuleVersionSelectorParsers.parser
-/**
- * by Szczepan Faber, created at: 10/14/11
- */
public class ModuleVersionSelectorParsersTest extends Specification {
def "understands group:name:version notation"() {
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/dsl/PublishArtifactNotationParserFactoryTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/dsl/PublishArtifactNotationParserFactoryTest.groovy
index 4d2bf8f..1ca5ee6 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/dsl/PublishArtifactNotationParserFactoryTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/dsl/PublishArtifactNotationParserFactoryTest.groovy
@@ -30,9 +30,6 @@ import spock.lang.Specification
import java.awt.*
-/**
- * @author Hans Dockter
- */
public class PublishArtifactNotationParserFactoryTest extends Specification {
final DependencyMetaDataProvider provider = Mock()
final Instantiator instantiator = ThreadGlobalInstantiator.getOrCreate()
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultBuildableArtifactResolveResultTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultBuildableArtifactResolveResultTest.groovy
index 292b4bc..2eacaa9 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultBuildableArtifactResolveResultTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultBuildableArtifactResolveResultTest.groovy
@@ -16,8 +16,7 @@
package org.gradle.api.internal.artifacts.ivyservice
-import org.apache.ivy.core.module.descriptor.DefaultArtifact
-import org.apache.ivy.core.module.id.ModuleRevisionId
+import org.gradle.api.artifacts.ArtifactIdentifier
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ArtifactNotFoundException
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ArtifactResolveException
import spock.lang.Specification
@@ -57,7 +56,7 @@ class DefaultBuildableArtifactResolveResultTest extends Specification {
def "fails with not found exception when artifact not found"() {
when:
- result.notFound(new DefaultArtifact(ModuleRevisionId.newInstance("org", "module", "rev"), new Date(), "art", "type", "type"))
+ result.notFound(Stub(ArtifactIdentifier))
then:
result.failure instanceof ArtifactNotFoundException
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultDependencyResolveDetailsSpec.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultDependencyResolveDetailsSpec.groovy
index 3cb3df0..16e513a 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultDependencyResolveDetailsSpec.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultDependencyResolveDetailsSpec.groovy
@@ -16,14 +16,11 @@
package org.gradle.api.internal.artifacts.ivyservice
+import org.gradle.api.internal.artifacts.ivyservice.resolveengine.result.VersionSelectionReasons
import spock.lang.Specification
import static org.gradle.api.internal.artifacts.DefaultModuleVersionSelector.newSelector
-import org.gradle.api.internal.artifacts.ivyservice.resolveengine.result.VersionSelectionReasons
-/**
- * by Szczepan Faber, created at: 12/13/12
- */
class DefaultDependencyResolveDetailsSpec extends Specification {
def "can specify version to use"() {
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultIvyContextManagerTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultIvyContextManagerTest.groovy
new file mode 100644
index 0000000..099072c
--- /dev/null
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultIvyContextManagerTest.groovy
@@ -0,0 +1,225 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice
+
+import org.apache.ivy.Ivy
+import org.apache.ivy.core.IvyContext
+import org.apache.ivy.plugins.resolver.DependencyResolver
+import org.gradle.api.Action
+import org.gradle.api.Transformer
+import org.gradle.test.fixtures.concurrent.ConcurrentSpec
+
+class DefaultIvyContextManagerTest extends ConcurrentSpec {
+ final manager = new DefaultIvyContextManager()
+
+ def setup() {
+ IvyContext.currentStack.clear()
+ }
+
+ def "executes action against an Ivy instance"() {
+ def action = Mock(Action)
+
+ when:
+ manager.withIvy(action)
+
+ then:
+ 1 * action.execute({it != null})
+ 0 * action._
+ }
+
+ def "executes action against an Ivy instance and returns the result"() {
+ def action = Mock(Transformer)
+
+ when:
+ def result = manager.withIvy(action)
+
+ then:
+ result == "result"
+
+ and:
+ 1 * action.transform({it != null}) >> "result"
+ 0 * action._
+ }
+
+ def "nested actions are executed against the same Ivy instance"() {
+ def action1 = Mock(Action)
+ def action2 = Mock(Action)
+ def transformer = Mock(Transformer)
+ def ivy
+
+ when:
+ manager.withIvy(action1)
+
+ then:
+ 1 * action1.execute(_) >> { Ivy param ->
+ ivy = param
+ manager.withIvy(transformer)
+ }
+ 1 * transformer.transform(_) >> { Ivy param ->
+ assert param.is(ivy)
+ manager.withIvy(action2)
+ }
+ 1 * action2.execute(_) >> { Ivy param ->
+ assert param.is(ivy)
+ }
+ 0 * _._
+ }
+
+ def "sets up Ivy context stack and cleans up after action"() {
+ given:
+ def action = Mock(Action)
+
+ when:
+ manager.withIvy(action)
+
+ then:
+ 1 * action.execute(_) >> { Ivy ivy ->
+ assert IvyContext.context.ivy.is(ivy)
+ }
+
+ and:
+ IvyContext.currentStack.empty()
+ }
+
+ def "cleans up after failed action"() {
+ given:
+ def action = Mock(Action)
+ def failure = new RuntimeException()
+
+ and:
+ action.execute(_) >> { Ivy ivy ->
+ throw failure
+ }
+
+ when:
+ manager.withIvy(action)
+
+ then:
+ RuntimeException e = thrown()
+ e == failure
+
+ and:
+ IvyContext.currentStack.empty()
+ }
+
+ def "reuses Ivy and IvySettings instances"() {
+ given:
+ def action = Mock(Action)
+ def ivy
+ def ivySettings
+
+ when:
+ manager.withIvy(action)
+
+ then:
+ 1 * action.execute(_) >> { Ivy param ->
+ ivy = param
+ ivySettings = param.settings
+ }
+
+ when:
+ manager.withIvy(action)
+
+ then:
+ 1 * action.execute(_) >> { Ivy param ->
+ assert param.is(ivy)
+ assert param.settings.is(ivySettings)
+ assert IvyContext.context.ivy.is(ivy)
+ }
+
+ when:
+ async {
+ start {
+ manager.withIvy(action)
+ }
+ }
+
+ then:
+ 1 * action.execute(_) >> { Ivy param ->
+ assert param.is(ivy)
+ assert param.settings.is(ivySettings)
+ assert IvyContext.context.ivy.is(ivy)
+ }
+
+ and:
+ IvyContext.currentStack.empty()
+ }
+
+ def "resets Ivy settings on reuse"() {
+ given:
+ def action1 = Mock(Action)
+ def action2 = Mock(Action)
+ def ivy
+ def ivySettings
+
+ when:
+ manager.withIvy(action1)
+
+ then:
+ 1 * action1.execute(_) >> { Ivy param ->
+ ivy = param
+ ivySettings = param.settings
+ ivySettings.addResolver(Stub(DependencyResolver) { getName() >> "some-resolver" })
+ ivySettings.setDefaultResolver("some-resolver")
+ }
+
+ when:
+ manager.withIvy(action2)
+
+ then:
+ 1 * action2.execute(_) >> { Ivy param ->
+ assert param.settings.is(ivySettings)
+ assert ivySettings.defaultResolverName == null
+ assert ivySettings.resolvers.empty
+ assert ivySettings.resolverNames.empty
+ }
+ }
+
+ def "each thread is given a separate Ivy instance and context"() {
+ given:
+ def ivy1
+ def ivySettings1
+ def ivy2
+ def ivySettings2
+
+ when:
+ async {
+ start {
+ manager.withIvy({ param ->
+ instant.action1
+ thread.blockUntil.action2
+ ivy1 = param
+ ivySettings1 = param.settings
+ assert IvyContext.context.ivy.is(ivy1)
+ } as Action)
+ }
+ start {
+ manager.withIvy({ param ->
+ instant.action2
+ thread.blockUntil.action1
+ ivy2 = param
+ ivySettings2 = param.settings
+ assert IvyContext.context.ivy.is(ivy2)
+ } as Action)
+ }
+ }
+
+ then:
+ !ivy1.is(ivy2)
+ !ivySettings1.is(ivySettings2)
+ }
+}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultIvyFactoryTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultIvyFactoryTest.groovy
deleted file mode 100644
index 521ee61..0000000
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultIvyFactoryTest.groovy
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.artifacts.ivyservice
-
-import spock.lang.Specification
-import org.apache.ivy.core.settings.IvySettings
-
-class DefaultIvyFactoryTest extends Specification {
- final DefaultIvyFactory factory = new DefaultIvyFactory()
-
- def "creates Ivy instance for IvySettings"() {
- def ivySettings = new IvySettings()
-
- expect:
- def ivy = factory.createIvy(ivySettings)
- ivy.settings == ivySettings
- }
-
- def "caches Ivy instance for given IvySettings"() {
- def ivySettings = new IvySettings()
-
- expect:
- def ivy1 = factory.createIvy(ivySettings)
- def ivy2 = factory.createIvy(ivySettings)
- ivy1.is(ivy2)
- }
-}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultSettingsConverterTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultSettingsConverterTest.groovy
deleted file mode 100644
index aed2959..0000000
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultSettingsConverterTest.groovy
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright 2007 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.artifacts.ivyservice
-
-import org.apache.ivy.core.settings.IvySettings
-import org.apache.ivy.plugins.resolver.DependencyResolver
-import org.apache.ivy.plugins.resolver.IBiblioResolver
-import org.gradle.internal.Factory
-import spock.lang.Specification
-
-class DefaultSettingsConverterTest extends Specification {
- final DependencyResolver defaultResolver = Mock()
- final IBiblioResolver testResolver = new IBiblioResolver()
- final IBiblioResolver testResolver2 = new IBiblioResolver()
-
- final Factory<IvySettings> ivySettingsFactory = Mock()
- final IvySettings ivySettings = new IvySettings()
-
- DefaultSettingsConverter converter = new DefaultSettingsConverter(ivySettingsFactory)
-
- public void setup() {
- testResolver.name = 'resolver'
- }
-
- public void testConvertForResolve() {
- when:
- IvySettings settings = converter.convertForResolve(defaultResolver)
-
- then:
- 1 * ivySettingsFactory.create() >> ivySettings
- 1 * defaultResolver.setSettings(ivySettings)
- _ * defaultResolver.getName() >> 'default'
- 0 * _._
-
- assert settings.is(ivySettings)
-
- assert settings.defaultResolver == defaultResolver
- assert settings.resolvers.size() == 1
- }
-
- public void shouldReuseResolveSettings() {
- given:
- 1 * ivySettingsFactory.create() >> ivySettings
- _ * defaultResolver.getName() >> 'default'
- IvySettings settings = converter.convertForResolve(defaultResolver)
- settings.addResolver(testResolver)
- settings.addResolver(testResolver2)
-
- when:
- settings = converter.convertForResolve(defaultResolver)
-
- then:
- assert settings.is(ivySettings)
-
- assert settings.defaultResolver == defaultResolver
- assert settings.resolvers.size() == 1
- }
-
- public void testConvertForPublish() {
- when:
- IvySettings settings = converter.convertForPublish([testResolver, testResolver2])
-
- then:
- settings.is(ivySettings)
-
- and:
- [testResolver, testResolver2].each {
- it.settings == settings
- it.repositoryCacheManager.settings == settings
- }
-
- and:
- 1 * ivySettingsFactory.create() >> ivySettings
- 0 * _._
- }
-
- public void reusesPublishSettings() {
- when:
- IvySettings settings = converter.convertForPublish([testResolver])
-
- then:
- settings.is(ivySettings)
-
- and:
- 1 * ivySettingsFactory.create() >> ivySettings
- 0 * _._
-
- when:
- settings = converter.convertForPublish([testResolver, testResolver2])
-
- then:
- settings.is(ivySettings)
-
- and:
- [testResolver, testResolver2].each {
- it.settings == settings
- it.repositoryCacheManager.settings == settings
- }
- }
-}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultUnresolvedDependencySpec.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultUnresolvedDependencySpec.groovy
index 585e5c3..93ee3b5 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultUnresolvedDependencySpec.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/DefaultUnresolvedDependencySpec.groovy
@@ -19,9 +19,6 @@ package org.gradle.api.internal.artifacts.ivyservice
import org.gradle.api.internal.artifacts.DefaultModuleVersionSelector
import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 5/11/12
- */
class DefaultUnresolvedDependencySpec extends Specification {
def "provides module details"() {
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ErrorHandlingArtifactDependencyResolverTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ErrorHandlingArtifactDependencyResolverTest.groovy
index d587aa7..f34650b 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ErrorHandlingArtifactDependencyResolverTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ErrorHandlingArtifactDependencyResolverTest.groovy
@@ -13,9 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.gradle.api.internal.artifacts.ivyservice;
-
+package org.gradle.api.internal.artifacts.ivyservice
+import org.gradle.api.artifacts.LenientConfiguration;
import org.gradle.api.artifacts.ResolveException
import org.gradle.api.artifacts.ResolvedConfiguration
import org.gradle.api.artifacts.result.ResolutionResult
@@ -46,12 +46,13 @@ public class ErrorHandlingArtifactDependencyResolverTest extends Specification {
outerResults.resolvedConfiguration.hasError()
outerResults.resolvedConfiguration.rethrowFailure()
outerResults.resolvedConfiguration.getFiles(Specs.satisfyAll())
+ outerResults.resolutionResult.getRoot()
then:
1 * resolvedConfiguration.hasError()
1 * resolvedConfiguration.rethrowFailure()
1 * resolvedConfiguration.getFiles(Specs.satisfyAll())
- outerResults.resolutionResult == resolutionResult
+ 1 * resolutionResult.getRoot()
}
void "wraps operations with the failure"() {
@@ -79,19 +80,63 @@ public class ErrorHandlingArtifactDependencyResolverTest extends Specification {
resolvedConfiguration.rethrowFailure() >> { throw failure }
resolvedConfiguration.getFiles(Specs.satisfyAll()) >> { throw failure }
resolvedConfiguration.getFirstLevelModuleDependencies() >> { throw failure }
+ resolvedConfiguration.getFirstLevelModuleDependencies(_) >> { throw failure }
resolvedConfiguration.getResolvedArtifacts() >> { throw failure }
+ resolvedConfiguration.getLenientConfiguration() >> { throw failure }
delegate.resolve(configuration, repositories) >> { new ResolverResults(resolvedConfiguration, resolutionResult) }
when:
- ResolverResults results = resolver.resolve(configuration, repositories);
+ def result = resolver.resolve(configuration, repositories).resolvedConfiguration
+
+ then:
+ failsWith(failure)
+ .when { result.rethrowFailure() }
+ .when { result.getFiles(Specs.satisfyAll()) }
+ .when { result.firstLevelModuleDependencies }
+ .when { result.getFirstLevelModuleDependencies(Specs.satisfyAll()) }
+ .when { result.resolvedArtifacts }
+ .when { result.lenientConfiguration }
+ }
+
+ void "wraps exceptions thrown by resolved lenient configuration"() {
+ given:
+ def failure = new RuntimeException()
+ def lenientConfiguration = Stub(LenientConfiguration)
+
+ resolvedConfiguration.getLenientConfiguration() >> lenientConfiguration
+ lenientConfiguration.getFiles(_) >> { throw failure }
+ lenientConfiguration.getFirstLevelModuleDependencies(_) >> { throw failure }
+ lenientConfiguration.getArtifacts(_) >> { throw failure }
+ lenientConfiguration.getUnresolvedModuleDependencies() >> { throw failure }
+
+ delegate.resolve(configuration, repositories) >> { new ResolverResults(resolvedConfiguration, resolutionResult) }
+
+ when:
+ def result = resolver.resolve(configuration, repositories).resolvedConfiguration.lenientConfiguration
+
+ then:
+ failsWith(failure)
+ .when { result.getFiles(Specs.satisfyAll()) }
+ .when { result.getFirstLevelModuleDependencies(Specs.satisfyAll()) }
+ .when { result.getArtifacts(Specs.satisfyAll()) }
+ .when { result.unresolvedModuleDependencies }
+ }
+
+ void "wraps exceptions thrown by resolution result"() {
+ given:
+ def failure = new RuntimeException()
+
+ resolutionResult.root >> { throw failure }
+
+ delegate.resolve(configuration, repositories) >> { new ResolverResults(resolvedConfiguration, resolutionResult) }
+
+ when:
+ def result = resolver.resolve(configuration, repositories).resolutionResult
then:
failsWith(failure)
- .when { results.resolvedConfiguration.rethrowFailure(); }
- .when { results.resolvedConfiguration.getFiles(Specs.satisfyAll()); }
- .when { results.resolvedConfiguration.getFirstLevelModuleDependencies(); }
- .when { results.resolvedConfiguration.getResolvedArtifacts(); }
+ .when { result.root }
}
ExceptionFixture failsWith(Throwable failure) {
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/IvyBackedArtifactPublisherTest.java b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/IvyBackedArtifactPublisherTest.java
deleted file mode 100644
index 272474e..0000000
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/IvyBackedArtifactPublisherTest.java
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.artifacts.ivyservice;
-
-import org.apache.ivy.Ivy;
-import org.apache.ivy.core.event.EventManager;
-import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
-import org.apache.ivy.core.settings.IvySettings;
-import org.apache.ivy.plugins.resolver.DependencyResolver;
-import org.gradle.api.artifacts.Configuration;
-import org.gradle.api.artifacts.Module;
-import org.gradle.api.internal.artifacts.configurations.ConfigurationInternal;
-import org.gradle.api.internal.artifacts.configurations.Configurations;
-import org.gradle.api.internal.artifacts.configurations.DependencyMetaDataProvider;
-import org.gradle.api.internal.artifacts.ivyservice.resolutionstrategy.DefaultResolutionStrategy;
-import org.gradle.api.internal.artifacts.repositories.PublicationAwareRepository;
-import org.gradle.util.JUnit4GroovyMockery;
-import org.gradle.util.WrapUtil;
-import org.jmock.Expectations;
-import org.jmock.integration.junit4.JMock;
-import org.jmock.integration.junit4.JUnit4Mockery;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.io.File;
-import java.io.IOException;
-import java.text.ParseException;
-import java.util.List;
-import java.util.Set;
-
-import static org.hamcrest.Matchers.equalTo;
-
-/**
- * @author Hans Dockter
- */
- at RunWith(JMock.class)
-public class IvyBackedArtifactPublisherTest {
- private JUnit4Mockery context = new JUnit4GroovyMockery();
-
- private ModuleDescriptor publishModuleDescriptorDummy = context.mock(ModuleDescriptor.class);
- private ModuleDescriptor fileModuleDescriptorMock = context.mock(ModuleDescriptor.class);
- private DependencyMetaDataProvider dependencyMetaDataProviderMock = context.mock(DependencyMetaDataProvider.class);
- private IvyFactory ivyFactoryStub = context.mock(IvyFactory.class);
- private SettingsConverter settingsConverterStub = context.mock(SettingsConverter.class);
- private IvyDependencyPublisher ivyDependencyPublisherMock = context.mock(IvyDependencyPublisher.class);
- private ModuleDescriptorConverter publishModuleDescriptorConverter = context.mock(ModuleDescriptorConverter.class, "publishConverter");
- private ModuleDescriptorConverter fileModuleDescriptorConverter = context.mock(ModuleDescriptorConverter.class, "fileConverter");
- private DependencyResolver resolver1 = context.mock(DependencyResolver.class);
- private DependencyResolver resolver2 = context.mock(DependencyResolver.class);
- private PublicationAwareRepository repo1 = repo(resolver1);
- private PublicationAwareRepository repo2 = repo(resolver2);
- final List<DependencyResolver> publishResolversDummy = WrapUtil.toList(resolver1, resolver2);
- final List<PublicationAwareRepository> publishRepositoriesDummy = WrapUtil.toList(repo1, repo2);
-
- @Test
- public void testPublish() throws IOException, ParseException {
- final IvySettings ivySettingsDummy = new IvySettings();
- final EventManager ivyEventManagerDummy = new EventManager();
- final ConfigurationInternal configuration = context.mock(ConfigurationInternal.class);
- final Set<Configuration> configurations = createConfiguration();
- final File someDescriptorDestination = new File("somePath");
- final Module moduleDummy = context.mock(Module.class, "moduleForResolve");
- final IvyBackedArtifactPublisher ivyService = createIvyService();
-
- setUpIvyFactory(ivySettingsDummy, ivyEventManagerDummy);
- setUpForPublish(configurations, publishResolversDummy, moduleDummy, ivySettingsDummy);
-
- final Set<String> expectedConfigurations = Configurations.getNames(configurations, true);
- context.checking(new Expectations() {{
- allowing(configuration).getHierarchy();
- will(returnValue(configurations));
- allowing(configuration).getModule();
- will(returnValue(moduleDummy));
- allowing(configuration).getResolutionStrategy();
- will(returnValue(new DefaultResolutionStrategy()));
- one(ivyDependencyPublisherMock).publish(expectedConfigurations,
- publishResolversDummy, publishModuleDescriptorDummy, someDescriptorDestination, ivyEventManagerDummy);
- }});
-
- ivyService.publish(publishRepositoriesDummy, configuration.getModule(), configuration.getHierarchy(), someDescriptorDestination);
- }
-
- private IvyBackedArtifactPublisher createIvyService() {
- return new IvyBackedArtifactPublisher(
- settingsConverterStub,
- publishModuleDescriptorConverter,
- ivyFactoryStub,
- ivyDependencyPublisherMock);
- }
-
- private Set<Configuration> createConfiguration() {
- final Configuration configurationStub1 = context.mock(Configuration.class, "confStub1");
- final Configuration configurationStub2 = context.mock(Configuration.class, "confStub2");
- context.checking(new Expectations() {{
- allowing(configurationStub1).getName();
- will(returnValue("conf1"));
-
- allowing(configurationStub1).getHierarchy();
- will(returnValue(WrapUtil.toLinkedSet(configurationStub1)));
-
- allowing(configurationStub1).getAll();
- will(returnValue(WrapUtil.toLinkedSet(configurationStub1, configurationStub2)));
-
- allowing(configurationStub2).getName();
- will(returnValue("conf2"));
-
- allowing(configurationStub2).getHierarchy();
- will(returnValue(WrapUtil.toLinkedSet(configurationStub2)));
-
- allowing(configurationStub2).getAll();
- will(returnValue(WrapUtil.toLinkedSet(configurationStub1, configurationStub2)));
- }});
- return WrapUtil.toSet(configurationStub1, configurationStub2);
- }
-
- private void setUpForPublish(final Set<Configuration> configurations,
- final List<DependencyResolver> publishResolversDummy, final Module moduleDummy,
- final IvySettings ivySettingsDummy) {
- context.checking(new Expectations() {{
- allowing(dependencyMetaDataProviderMock).getModule();
- will(returnValue(moduleDummy));
-
- allowing(settingsConverterStub).convertForPublish(publishResolversDummy);
- will(returnValue(ivySettingsDummy));
-
- allowing(publishModuleDescriptorConverter).convert(with(equalTo(configurations)),
- with(equalTo(moduleDummy)));
- will(returnValue(publishModuleDescriptorDummy));
-
- allowing(fileModuleDescriptorConverter).convert(with(equalTo(configurations)),
- with(equalTo(moduleDummy)));
- will(returnValue(fileModuleDescriptorMock));
-
- }});
- }
-
- private Ivy setUpIvyFactory(final IvySettings ivySettingsDummy, final EventManager ivyEventManagerDummy) {
- final Ivy ivyStub = context.mock(Ivy.class);
- context.checking(new Expectations() {{
- allowing(ivyFactoryStub).createIvy(ivySettingsDummy);
- will(returnValue(ivyStub));
-
- allowing(ivyStub).getSettings();
- will(returnValue(ivySettingsDummy));
-
- allowing(ivyStub).getEventManager();
- will(returnValue(ivyEventManagerDummy));
- }});
- return ivyStub;
- }
-
- private PublicationAwareRepository repo(final DependencyResolver resolver) {
- final PublicationAwareRepository repository = context.mock(PublicationAwareRepository.class);
- context.checking(new Expectations() {{
- one(repository).createPublisher();
- will(returnValue(resolver));
- }});
- return repository;
- }
-}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/IvySettingsFactoryTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/IvySettingsFactoryTest.groovy
deleted file mode 100644
index b0cbbdc..0000000
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/IvySettingsFactoryTest.groovy
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.artifacts.ivyservice
-
-import org.gradle.api.artifacts.ArtifactRepositoryContainer
-import spock.lang.Specification
-
-class IvySettingsFactoryTest extends Specification {
- final File cacheDir = new File('user-dir')
- final ArtifactCacheMetaData cacheMetaData = Mock()
- final IvySettingsFactory factory = new IvySettingsFactory(cacheMetaData)
-
- def "creates and configures an IvySettings instance"() {
- given:
- _ * cacheMetaData.cacheDir >> cacheDir
-
- when:
- def settings = factory.create()
-
- then:
- settings.defaultCache == new File(cacheDir, 'ivy')
- settings.defaultCacheArtifactPattern == ArtifactRepositoryContainer.DEFAULT_CACHE_ARTIFACT_PATTERN
- }
-}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/IvyUtilTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/IvyUtilTest.groovy
index 6dbe063..d865d7c 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/IvyUtilTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/IvyUtilTest.groovy
@@ -18,11 +18,9 @@ package org.gradle.api.internal.artifacts.ivyservice
import org.apache.ivy.core.module.id.ModuleRevisionId
import org.junit.Test
+
import static org.junit.Assert.assertEquals
-/**
- * @author Hans Dockter
- */
class IvyUtilTest {
@Test public void testModuleRevisionId() {
List l = ['myorg', 'myname', 'myrev']
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ModuleVersionNotFoundExceptionTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ModuleVersionNotFoundExceptionTest.groovy
index 2de2301..7939b7b 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ModuleVersionNotFoundExceptionTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ModuleVersionNotFoundExceptionTest.groovy
@@ -34,9 +34,9 @@ class ModuleVersionNotFoundExceptionTest extends Specification {
}
def "can add incoming paths to exception"() {
- def a = newInstance("org", "a", "1.2")
- def b = newInstance("org", "b", "5")
- def c = newInstance("org", "c", "1.0")
+ def a = newId("org", "a", "1.2")
+ def b = newId("org", "b", "5")
+ def c = newId("org", "c", "1.0")
def exception = new ModuleVersionNotFoundException(newInstance("a", "b", "c"))
def onePath = exception.withIncomingPaths([[a, b, c]])
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ModuleVersionResolveExceptionTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ModuleVersionResolveExceptionTest.groovy
index 6cbeda6..fab33e6 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ModuleVersionResolveExceptionTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ModuleVersionResolveExceptionTest.groovy
@@ -37,9 +37,9 @@ class ModuleVersionResolveExceptionTest extends Specification {
}
def "can add incoming paths to exception"() {
- def a = newInstance("org", "a", "1.2")
- def b = newInstance("org", "b", "5")
- def c = newInstance("org", "c", "1.0")
+ def a = newId("org", "a", "1.2")
+ def b = newId("org", "b", "5")
+ def c = newId("org", "c", "1.0")
def cause = new RuntimeException()
def exception = new ModuleVersionResolveException(newInstance("a", "b", "c"), cause)
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ResolvedArtifactFactoryTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ResolvedArtifactFactoryTest.groovy
index 243015e..14ce8ae 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ResolvedArtifactFactoryTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ResolvedArtifactFactoryTest.groovy
@@ -15,39 +15,36 @@
*/
package org.gradle.api.internal.artifacts.ivyservice
+import org.apache.ivy.Ivy
import org.apache.ivy.core.module.descriptor.Artifact
-import org.gradle.api.artifacts.ResolvedArtifact
-import org.gradle.api.artifacts.ResolvedDependency
+import org.gradle.api.Transformer
import org.gradle.internal.Factory
-import org.gradle.api.internal.artifacts.DefaultResolvedArtifact
import spock.lang.Specification
class ResolvedArtifactFactoryTest extends Specification {
final CacheLockingManager lockingManager = Mock()
- final ResolvedArtifactFactory factory = new ResolvedArtifactFactory(lockingManager)
+ final IvyContextManager ivyContextManager = Mock()
+ final ResolvedArtifactFactory factory = new ResolvedArtifactFactory(lockingManager, ivyContextManager)
- def "creates an artifact backed by module resolve result"() {
+ def "provides artifact source"() {
Artifact artifact = Mock()
ArtifactResolver artifactResolver = Mock()
- ResolvedDependency resolvedDependency = Mock()
File file = new File("something.jar")
given:
artifact.qualifiedExtraAttributes >> [:]
when:
- ResolvedArtifact resolvedArtifact = factory.create(resolvedDependency, artifact, artifactResolver)
-
- then:
- resolvedArtifact instanceof DefaultResolvedArtifact
-
- when:
- resolvedArtifact.file
+ File f = factory.artifactSource(artifact, artifactResolver).create()
then:
+ f == file
1 * lockingManager.useCache(!null, !null) >> {String displayName, Factory<?> action ->
return action.create()
}
+ 1 * ivyContextManager.withIvy(!null) >> {Transformer action ->
+ return action.transform(Stub(Ivy))
+ }
1 * artifactResolver.resolve(artifact, _) >> { args -> args[1].resolved(file) }
0 * _._
}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/clientmodule/ClientModuleResolverTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/clientmodule/ClientModuleResolverTest.groovy
index dd8b5df..837eee6 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/clientmodule/ClientModuleResolverTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/clientmodule/ClientModuleResolverTest.groovy
@@ -1,5 +1,5 @@
/*
- * Copyright 2007-2009 the original author or authors.
+ * Copyright 2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,7 +21,7 @@ import org.apache.ivy.core.module.descriptor.ModuleDescriptor
import org.apache.ivy.core.module.id.ModuleId
import org.apache.ivy.core.module.id.ModuleRevisionId
import org.gradle.api.internal.artifacts.ivyservice.BuildableModuleVersionResolveResult
-import org.gradle.api.internal.artifacts.ivyservice.DependencyToModuleResolver
+import org.gradle.api.internal.artifacts.ivyservice.DependencyToModuleVersionResolver
import org.gradle.api.internal.artifacts.ivyservice.ModuleVersionResolveException
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.DependencyMetaData
import org.gradle.api.internal.artifacts.ivyservice.moduleconverter.dependencies.ClientModuleDependencyDescriptor
@@ -29,13 +29,10 @@ import spock.lang.Specification
import static org.gradle.api.internal.artifacts.DefaultModuleVersionSelector.newSelector
-/**
- * @author Hans Dockter
- */
class ClientModuleResolverTest extends Specification {
final ModuleDescriptor module = Mock()
final ModuleRevisionId moduleId = new ModuleRevisionId(new ModuleId("org", "name"), "1.0")
- final DependencyToModuleResolver target = Mock()
+ final DependencyToModuleVersionResolver target = Mock()
final ClientModuleResolver resolver = new ClientModuleResolver(target)
def "replaces meta-data for a client module dependency"() {
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/CachingModuleVersionRepositoryTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/CachingModuleVersionRepositoryTest.groovy
index 81d2d7a..dac2e6e 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/CachingModuleVersionRepositoryTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/CachingModuleVersionRepositoryTest.groovy
@@ -16,13 +16,10 @@
package org.gradle.api.internal.artifacts.ivyservice.ivyresolve
-import org.apache.ivy.core.module.descriptor.Artifact
-import org.apache.ivy.core.module.id.ArtifactId
-import org.apache.ivy.core.module.id.ArtifactRevisionId
-import org.apache.ivy.core.module.id.ModuleId
-import org.apache.ivy.core.module.id.ModuleRevisionId
+import org.gradle.api.artifacts.ArtifactIdentifier
import org.gradle.api.internal.artifacts.configurations.dynamicversion.CachePolicy
import org.gradle.api.internal.artifacts.ivyservice.BuildableArtifactResolveResult
+import org.gradle.api.internal.artifacts.ivyservice.DependencyToModuleVersionResolver
import org.gradle.api.internal.artifacts.ivyservice.dynamicversions.ModuleResolutionCache
import org.gradle.api.internal.artifacts.ivyservice.modulecache.ModuleDescriptorCache
import org.gradle.api.internal.externalresource.cached.CachedArtifactIndex
@@ -35,13 +32,14 @@ import spock.lang.Unroll
class CachingModuleVersionRepositoryTest extends Specification {
- ModuleVersionRepository realRepo = Mock()
- ModuleResolutionCache moduleResolutionCache = Mock()
- ModuleDescriptorCache moduleDescriptorCache = Mock()
- CachedArtifactIndex artifactAtRepositoryCache = Mock()
- CachePolicy cachePolicy = Mock()
- CachingModuleVersionRepository repo = new CachingModuleVersionRepository(realRepo, moduleResolutionCache, moduleDescriptorCache, artifactAtRepositoryCache, cachePolicy, new TrueTimeProvider())
- ModuleRevisionId moduleRevisionId = Mock()
+ final realRepo = Mock(ModuleVersionRepository)
+ final moduleResolutionCache = Mock(ModuleResolutionCache)
+ final moduleDescriptorCache = Mock(ModuleDescriptorCache)
+ final artifactAtRepositoryCache = Mock(CachedArtifactIndex)
+ final resolver = Mock(DependencyToModuleVersionResolver)
+ final cachePolicy = Mock(CachePolicy)
+ CachingModuleVersionRepository repo = new CachingModuleVersionRepository(realRepo, moduleResolutionCache, moduleDescriptorCache, artifactAtRepositoryCache,
+ resolver, cachePolicy, new TrueTimeProvider())
int descriptorHash = 1234
CachingModuleVersionRepository.CachingModuleSource moduleSource = Mock()
@@ -51,12 +49,11 @@ class CachingModuleVersionRepositoryTest extends Specification {
ExternalResourceMetaData externalResourceMetaData = new DefaultExternalResourceMetaData("remote url", lastModified, -1, null, null)
File file = new File("local")
BuildableArtifactResolveResult result = Mock()
- Artifact artifact = Mock()
- ArtifactRevisionId id = arid()
- ArtifactAtRepositoryKey atRepositoryKey = new ArtifactAtRepositoryKey(realRepo, id)
+ ArtifactIdentifier artifact = Stub()
+ ArtifactAtRepositoryKey atRepositoryKey = new ArtifactAtRepositoryKey("repo-id", artifact)
and:
- _ * artifact.getModuleRevisionId() >> moduleRevisionId;
+ _ * realRepo.id >> "repo-id"
_ * realRepo.isLocal() >> false
_ * moduleSource.descriptorHash >> descriptorHash
_ * moduleSource.isChangingModule >> true
@@ -64,7 +61,6 @@ class CachingModuleVersionRepositoryTest extends Specification {
_ * realRepo.resolve(artifact, result, null)
_ * result.file >> file
_ * result.externalResourceMetaData >> externalResourceMetaData
- _ * artifact.getId() >> id
when:
repo.resolve(artifact, result, moduleSource)
@@ -75,20 +71,4 @@ class CachingModuleVersionRepositoryTest extends Specification {
where:
lastModified << [new Date(), null]
}
-
- ArtifactRevisionId arid(Map attrs = [:]) {
- Map defaults = [
- org: "org", name: "name", revision: "1.0",
- type: "type", ext: "ext"
- ]
-
- attrs = defaults + attrs
-
- ModuleId mid = new ModuleId(attrs.org, attrs.name)
- new ArtifactRevisionId(
- new ArtifactId(mid, mid.name, attrs.type, attrs.ext),
- new ModuleRevisionId(mid, attrs.revision)
- )
- }
-
}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/DefaultBuildableModuleVersionMetaDataResolveResultTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/DefaultBuildableModuleVersionMetaDataResolveResultTest.groovy
new file mode 100644
index 0000000..925e0aa
--- /dev/null
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/DefaultBuildableModuleVersionMetaDataResolveResultTest.groovy
@@ -0,0 +1,428 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve
+
+import org.apache.ivy.core.module.descriptor.*
+import org.apache.ivy.core.module.id.ModuleRevisionId
+import org.gradle.api.artifacts.ModuleVersionIdentifier
+import org.gradle.api.internal.artifacts.ivyservice.ModuleVersionResolveException
+import spock.lang.Specification
+
+import static org.gradle.api.internal.artifacts.DefaultModuleVersionSelector.newSelector
+
+class DefaultBuildableModuleVersionMetaDataResolveResultTest extends Specification {
+ final DefaultBuildableModuleVersionMetaDataResolveResult descriptor = new DefaultBuildableModuleVersionMetaDataResolveResult()
+ ModuleSource moduleSource = Stub()
+
+ def "has unknown state by default"() {
+ expect:
+ descriptor.state == BuildableModuleVersionMetaDataResolveResult.State.Unknown
+ }
+
+ def "can mark as missing"() {
+ when:
+ descriptor.missing()
+
+ then:
+ descriptor.state == BuildableModuleVersionMetaDataResolveResult.State.Missing
+ descriptor.failure == null
+ }
+
+ def "can mark as probably missing"() {
+ when:
+ descriptor.probablyMissing()
+
+ then:
+ descriptor.state == BuildableModuleVersionMetaDataResolveResult.State.ProbablyMissing
+ descriptor.failure == null
+ }
+
+ def "can mark as failed"() {
+ def failure = new ModuleVersionResolveException(newSelector("a", "b", "c"), "broken")
+
+ when:
+ descriptor.failed(failure)
+
+ then:
+ descriptor.state == BuildableModuleVersionMetaDataResolveResult.State.Failed
+ descriptor.failure == failure
+ }
+
+ def "can mark as resolved"() {
+ def id = Stub(ModuleVersionIdentifier)
+ def moduleDescriptor = Stub(ModuleDescriptor)
+
+ when:
+ descriptor.resolved(id, moduleDescriptor, true, moduleSource)
+
+ then:
+ descriptor.state == BuildableModuleVersionMetaDataResolveResult.State.Resolved
+ descriptor.failure == null
+ descriptor.id == id
+ descriptor.descriptor == moduleDescriptor
+ descriptor.changing
+ descriptor.moduleSource == moduleSource
+ }
+
+ def "builds and caches the dependency meta-data from the module descriptor"() {
+ def id = Stub(ModuleVersionIdentifier)
+ def moduleDescriptor = Mock(ModuleDescriptor)
+ def dependency1 = new DefaultDependencyDescriptor(ModuleRevisionId.newInstance("org", "module", "1.2"), false)
+ def dependency2 = new DefaultDependencyDescriptor(ModuleRevisionId.newInstance("org", "module", "1.2"), false)
+
+ given:
+ moduleDescriptor.dependencies >> ([dependency1, dependency2] as DependencyDescriptor[])
+
+ and:
+ descriptor.resolved(id, moduleDescriptor, true, moduleSource)
+
+ when:
+ def deps = descriptor.dependencies
+
+ then:
+ deps.size() == 2
+ deps[0].descriptor == dependency1
+ deps[1].descriptor == dependency2
+
+ when:
+ def deps2 = descriptor.dependencies
+
+ then:
+ deps2.is(deps)
+
+ and:
+ 0 * moduleDescriptor._
+ }
+
+ def "builds and caches the configuration meta-data from the module descriptor"() {
+ def id = Stub(ModuleVersionIdentifier)
+ def moduleDescriptor = Mock(ModuleDescriptor)
+
+ given:
+ descriptor.resolved(id, moduleDescriptor, true, moduleSource)
+
+ when:
+ def config = descriptor.getConfiguration("conf")
+
+ then:
+ 1 * moduleDescriptor.getConfiguration("conf") >> Stub(Configuration)
+
+ when:
+ def config2 = descriptor.getConfiguration("conf")
+
+ then:
+ config2.is(config)
+
+ and:
+ 0 * moduleDescriptor._
+ }
+
+ def "returns null for unknown configuration"() {
+ def id = Stub(ModuleVersionIdentifier)
+ def moduleDescriptor = Mock(ModuleDescriptor)
+
+ given:
+ moduleDescriptor.getConfiguration("conf") >> null
+
+ and:
+ descriptor.resolved(id, moduleDescriptor, true, moduleSource)
+
+ expect:
+ descriptor.getConfiguration("conf") == null
+ }
+
+ def "builds and caches dependencies for a configuration"() {
+ def id = Stub(ModuleVersionIdentifier)
+ def moduleDescriptor = Stub(ModuleDescriptor)
+ def config = Stub(Configuration)
+ def dependency1 = new DefaultDependencyDescriptor(ModuleRevisionId.newInstance("org", "module", "1.2"), false)
+ dependency1.addDependencyConfiguration("conf", "a")
+ def dependency2 = new DefaultDependencyDescriptor(ModuleRevisionId.newInstance("org", "module", "1.2"), false)
+ dependency2.addDependencyConfiguration("*", "b")
+ def dependency3 = new DefaultDependencyDescriptor(ModuleRevisionId.newInstance("org", "module", "1.2"), false)
+ dependency3.addDependencyConfiguration("super", "c")
+ def dependency4 = new DefaultDependencyDescriptor(ModuleRevisionId.newInstance("org", "module", "1.2"), false)
+ dependency4.addDependencyConfiguration("other", "d")
+ def dependency5 = new DefaultDependencyDescriptor(ModuleRevisionId.newInstance("org", "module", "1.2"), false)
+ dependency5.addDependencyConfiguration("%", "e")
+
+ given:
+ moduleDescriptor.dependencies >> ([dependency1, dependency2, dependency3, dependency4, dependency5] as DependencyDescriptor[])
+ moduleDescriptor.getConfiguration("conf") >> config
+ config.extends >> ["super"]
+
+ and:
+ descriptor.resolved(id, moduleDescriptor, true, moduleSource)
+
+ when:
+ def dependencies = descriptor.getConfiguration("conf").dependencies
+
+ then:
+ dependencies*.descriptor == [dependency1, dependency2, dependency3, dependency5]
+
+ and:
+ descriptor.getConfiguration("conf").dependencies.is(dependencies)
+
+ when:
+ descriptor.setDependencies([])
+
+ then:
+ descriptor.getConfiguration("conf").dependencies == []
+ }
+
+ def "builds and caches artifacts from the module descriptor"() {
+ def id = Stub(ModuleVersionIdentifier)
+ def moduleDescriptor = new DefaultModuleDescriptor(ModuleRevisionId.newInstance("org", "group", "version"), "status", null)
+ def artifact1 = Stub(Artifact)
+ def artifact2 = Stub(Artifact)
+
+ given:
+ moduleDescriptor.addConfiguration(new Configuration("config"))
+ moduleDescriptor.addArtifact("config", artifact1)
+ moduleDescriptor.addArtifact("config", artifact2)
+
+ and:
+ descriptor.resolved(id, moduleDescriptor, true, moduleSource)
+
+ when:
+ def artifacts = descriptor.getConfiguration("config").artifacts
+
+ then:
+ artifacts as List == [artifact1, artifact2]
+
+ and:
+ descriptor.getConfiguration("config").artifacts.is(artifacts)
+ }
+
+ def "artifacts include those inherited from other configurations"() {
+ def id = Stub(ModuleVersionIdentifier)
+ def moduleDescriptor = new DefaultModuleDescriptor(ModuleRevisionId.newInstance("org", "group", "version"), "status", null)
+ def artifact1 = Stub(Artifact)
+ def artifact2 = Stub(Artifact)
+ def artifact3 = Stub(Artifact)
+
+ given:
+ moduleDescriptor.addConfiguration(new Configuration("super"))
+ moduleDescriptor.addConfiguration(new Configuration("config", Configuration.Visibility.PUBLIC, "", ["super"] as String[], true, null))
+ moduleDescriptor.addArtifact("super", artifact1)
+ moduleDescriptor.addArtifact("super", artifact2)
+ moduleDescriptor.addArtifact("config", artifact2)
+ moduleDescriptor.addArtifact("config", artifact3)
+
+ and:
+ descriptor.resolved(id, moduleDescriptor, true, moduleSource)
+
+ when:
+ def artifacts = descriptor.getConfiguration("config").artifacts
+
+ then:
+ artifacts as List == [artifact2, artifact3, artifact1]
+ }
+
+ def "builds and caches exclude rules for a configuration"() {
+ def id = Stub(ModuleVersionIdentifier)
+ def moduleDescriptor = new DefaultModuleDescriptor(ModuleRevisionId.newInstance("org", "group", "version"), "status", null)
+ def rule1 = Stub(ExcludeRule)
+ def rule2 = Stub(ExcludeRule)
+ def rule3 = Stub(ExcludeRule)
+
+ given:
+ rule1.configurations >> ["config"]
+ rule2.configurations >> ["super"]
+ rule3.configurations >> ["other"]
+
+ and:
+ moduleDescriptor.addConfiguration(new Configuration("super"))
+ moduleDescriptor.addConfiguration(new Configuration("config", Configuration.Visibility.PUBLIC, "", ["super"] as String[], true, null))
+ moduleDescriptor.addExcludeRule(rule1)
+ moduleDescriptor.addExcludeRule(rule2)
+ moduleDescriptor.addExcludeRule(rule3)
+
+ and:
+ descriptor.resolved(id, moduleDescriptor, true, moduleSource)
+
+ when:
+ def excludeRules = descriptor.getConfiguration("config").excludeRules
+
+ then:
+ excludeRules as List == [rule1, rule2]
+
+ and:
+ descriptor.getConfiguration("config").excludeRules.is(excludeRules)
+ }
+
+ def "can replace the dependencies for the module version"() {
+ def id = Stub(ModuleVersionIdentifier)
+ def moduleDescriptor = Mock(ModuleDescriptor)
+ def dependency1 = Stub(DependencyMetaData)
+ def dependency2 = Stub(DependencyMetaData)
+
+ given:
+ descriptor.resolved(id, moduleDescriptor, true, moduleSource)
+
+ when:
+ descriptor.dependencies = [dependency1, dependency2]
+
+ then:
+ descriptor.dependencies == [dependency1, dependency2]
+
+ and:
+ 0 * moduleDescriptor._
+ }
+
+ def "cannot get failure when not resolved"() {
+ when:
+ descriptor.failure
+
+ then:
+ thrown(IllegalStateException)
+ }
+
+ def "cannot get meta-data when not resolved"() {
+ when:
+ descriptor.metaData
+
+ then:
+ thrown(IllegalStateException)
+ }
+
+ def "cannot get meta-data when failed"() {
+ given:
+ def failure = new ModuleVersionResolveException(newSelector("a", "b", "c"), "broken")
+ descriptor.failed(failure)
+
+ when:
+ descriptor.metaData
+
+ then:
+ ModuleVersionResolveException e = thrown()
+ e == failure
+ }
+
+ def "cannot get descriptor when not resolved"() {
+ when:
+ descriptor.descriptor
+
+ then:
+ thrown(IllegalStateException)
+ }
+
+ def "cannot get descriptor when failed"() {
+ given:
+ def failure = new ModuleVersionResolveException(newSelector("a", "b", "c"), "broken")
+ descriptor.failed(failure)
+
+ when:
+ descriptor.descriptor
+
+ then:
+ ModuleVersionResolveException e = thrown()
+ e == failure
+ }
+
+ def "cannot get descriptor when missing"() {
+ given:
+ descriptor.missing()
+
+ when:
+ descriptor.descriptor
+
+ then:
+ thrown(IllegalStateException)
+ }
+
+ def "cannot get descriptor when probably missing"() {
+ given:
+ descriptor.probablyMissing()
+
+ when:
+ descriptor.descriptor
+
+ then:
+ thrown(IllegalStateException)
+ }
+
+ def "cannot get module source when failed"() {
+ given:
+ def failure = new ModuleVersionResolveException(newSelector("a", "b", "c"), "broken")
+ descriptor.failed(failure)
+
+ when:
+ descriptor.getModuleSource()
+
+ then:
+ ModuleVersionResolveException e = thrown()
+ e == failure
+ }
+
+ def "cannot set module source when failed"() {
+ given:
+ def failure = new ModuleVersionResolveException(newSelector("a", "b", "c"), "broken")
+ descriptor.failed(failure)
+
+ when:
+ descriptor.setModuleSource(Mock(ModuleSource))
+
+ then:
+ ModuleVersionResolveException e = thrown()
+ e == failure
+ }
+
+ def "cannot get module source when missing"() {
+ given:
+ descriptor.missing()
+
+ when:
+ descriptor.getModuleSource()
+
+ then:
+ thrown(IllegalStateException)
+ }
+
+ def "cannot set module source when missing"() {
+ given:
+ descriptor.missing()
+
+ when:
+ descriptor.setModuleSource(Mock(ModuleSource))
+
+ then:
+ thrown(IllegalStateException)
+ }
+
+ def "cannot get module source when probably missing"() {
+ given:
+ descriptor.probablyMissing()
+
+ when:
+ descriptor.getModuleSource()
+
+ then:
+ thrown(IllegalStateException)
+ }
+
+ def "cannot set module source when probably missing"() {
+ given:
+ descriptor.probablyMissing()
+
+ when:
+ descriptor.setModuleSource(Mock(ModuleSource))
+
+ then:
+ thrown(IllegalStateException)
+ }
+}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/DefaultBuildableModuleVersionMetaDataTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/DefaultBuildableModuleVersionMetaDataTest.groovy
deleted file mode 100644
index df18c01..0000000
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/DefaultBuildableModuleVersionMetaDataTest.groovy
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve
-
-import org.apache.ivy.core.module.descriptor.DefaultDependencyDescriptor
-import org.apache.ivy.core.module.descriptor.DependencyDescriptor
-import org.apache.ivy.core.module.descriptor.ModuleDescriptor
-import org.apache.ivy.core.module.id.ModuleRevisionId
-import org.gradle.api.artifacts.ModuleVersionIdentifier
-import org.gradle.api.internal.artifacts.ivyservice.ModuleVersionResolveException
-import spock.lang.Specification
-
-import static org.gradle.api.internal.artifacts.DefaultModuleVersionSelector.newSelector
-
-class DefaultBuildableModuleVersionMetaDataTest extends Specification {
- final DefaultBuildableModuleVersionMetaData descriptor = new DefaultBuildableModuleVersionMetaData()
- ModuleSource moduleSource = Mock()
-
- def "has unknown state by default"() {
- expect:
- descriptor.state == BuildableModuleVersionMetaData.State.Unknown
- }
-
- def "can mark as missing"() {
- when:
- descriptor.missing()
-
- then:
- descriptor.state == BuildableModuleVersionMetaData.State.Missing
- descriptor.failure == null
- }
-
- def "can mark as probably missing"() {
- when:
- descriptor.probablyMissing()
-
- then:
- descriptor.state == BuildableModuleVersionMetaData.State.ProbablyMissing
- descriptor.failure == null
- }
-
- def "can mark as failed"() {
- def failure = new ModuleVersionResolveException(newSelector("a", "b", "c"), "broken")
-
- when:
- descriptor.failed(failure)
-
- then:
- descriptor.state == BuildableModuleVersionMetaData.State.Failed
- descriptor.failure == failure
- }
-
- def "can mark as resolved"() {
- def id = Mock(ModuleVersionIdentifier)
- def moduleDescriptor = Mock(ModuleDescriptor)
-
- when:
- descriptor.resolved(id, moduleDescriptor, true, moduleSource)
-
- then:
- descriptor.state == BuildableModuleVersionMetaData.State.Resolved
- descriptor.failure == null
- descriptor.id == id
- descriptor.descriptor == moduleDescriptor
- descriptor.changing
- descriptor.moduleSource == moduleSource
- }
-
- def "builds and caches the dependency meta-data from the module descriptor"() {
- def id = Mock(ModuleVersionIdentifier)
- def moduleDescriptor = Mock(ModuleDescriptor)
- def dependency1 = new DefaultDependencyDescriptor(ModuleRevisionId.newInstance("org", "module", "1.2"), false)
- def dependency2 = new DefaultDependencyDescriptor(ModuleRevisionId.newInstance("org", "module", "1.2"), false)
-
- given:
- moduleDescriptor.dependencies >> ([dependency1, dependency2] as DependencyDescriptor[])
-
- and:
- descriptor.resolved(id, moduleDescriptor, true, moduleSource)
-
- when:
- def deps = descriptor.dependencies
-
- then:
- deps.size() == 2
- deps[0].descriptor == dependency1
- deps[1].descriptor == dependency2
-
- and:
- descriptor.dependencies.is(deps)
- }
-
- def "can replace the dependencies for the module version"() {
- def id = Mock(ModuleVersionIdentifier)
- def moduleDescriptor = Mock(ModuleDescriptor)
- def dependency1 = Mock(DependencyMetaData)
- def dependency2 = Mock(DependencyMetaData)
-
- given:
- descriptor.resolved(id, moduleDescriptor, true, moduleSource)
-
- when:
- descriptor.dependencies = [dependency1, dependency2]
-
- then:
- descriptor.dependencies == [dependency1, dependency2]
-
- and:
- 0 * moduleDescriptor._
- }
-
- def "cannot get descriptor when not resolved"() {
- when:
- descriptor.descriptor
-
- then:
- thrown(IllegalStateException)
-
- when:
- descriptor.failure
-
- then:
- thrown(IllegalStateException)
- }
-
- def "cannot get descriptor when failed"() {
- given:
- def failure = new ModuleVersionResolveException(newSelector("a", "b", "c"), "broken")
- descriptor.failed(failure)
-
- when:
- descriptor.descriptor
-
- then:
- ModuleVersionResolveException e = thrown()
- e == failure
- }
-
- def "cannot get descriptor when missing"() {
- given:
- descriptor.missing()
-
- when:
- descriptor.descriptor
-
- then:
- thrown(IllegalStateException)
- }
-
- def "cannot get descriptor when probably missing"() {
- given:
- descriptor.probablyMissing()
-
- when:
- descriptor.descriptor
-
- then:
- thrown(IllegalStateException)
- }
-
- def "cannot get module source when failed"() {
- given:
- def failure = new ModuleVersionResolveException(newSelector("a", "b", "c"), "broken")
- descriptor.failed(failure)
-
- when:
- descriptor.getModuleSource()
-
- then:
- ModuleVersionResolveException e = thrown()
- e == failure
- }
-
- def "cannot set module source when failed"() {
- given:
- def failure = new ModuleVersionResolveException(newSelector("a", "b", "c"), "broken")
- descriptor.failed(failure)
-
- when:
- descriptor.setModuleSource(Mock(ModuleSource))
-
- then:
- ModuleVersionResolveException e = thrown()
- e == failure
- }
-
- def "cannot get module source when missing"() {
- given:
- descriptor.missing()
-
- when:
- descriptor.getModuleSource()
-
- then:
- thrown(IllegalStateException)
- }
-
- def "cannot set module source when missing"() {
- given:
- descriptor.missing()
-
- when:
- descriptor.setModuleSource(Mock(ModuleSource))
-
- then:
- thrown(IllegalStateException)
- }
-
- def "cannot get module source when probably missing"() {
- given:
- descriptor.probablyMissing()
-
- when:
- descriptor.getModuleSource()
-
- then:
- thrown(IllegalStateException)
- }
-
- def "cannot set module source when probably missing"() {
- given:
- descriptor.probablyMissing()
-
- when:
- descriptor.setModuleSource(Mock(ModuleSource))
-
- then:
- thrown(IllegalStateException)
- }
-}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/DependencyResolverIdentifierTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/DependencyResolverIdentifierTest.groovy
index 00268c2..952294e 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/DependencyResolverIdentifierTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/DependencyResolverIdentifierTest.groovy
@@ -21,15 +21,6 @@ import org.gradle.api.internal.artifacts.repositories.resolver.ExternalResourceR
import spock.lang.Specification
public class DependencyResolverIdentifierTest extends Specification {
- def "uses dependency resolver name"() {
- given:
- DependencyResolver resolver = Mock()
- resolver.name >> "resolver-name"
-
- expect:
- new DependencyResolverIdentifier(resolver).name == "resolver-name"
- }
-
def "dependency resolvers of unknown type are identified by their name"() {
given:
DependencyResolver resolver1 = Mock()
@@ -123,6 +114,10 @@ public class DependencyResolverIdentifierTest extends Specification {
}
def id(DependencyResolver resolver) {
- return new DependencyResolverIdentifier(resolver).uniqueId
+ return DependencyResolverIdentifier.forIvyResolver(resolver)
+ }
+
+ def id(ExternalResourceResolver resolver) {
+ return DependencyResolverIdentifier.forExternalResourceResolver(resolver)
}
}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/IvyDynamicResolveModuleVersionRepositoryTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/IvyDynamicResolveModuleVersionRepositoryTest.groovy
index 2da5d0a..c4e8377 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/IvyDynamicResolveModuleVersionRepositoryTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/IvyDynamicResolveModuleVersionRepositoryTest.groovy
@@ -22,8 +22,9 @@ import spock.lang.Specification
class IvyDynamicResolveModuleVersionRepositoryTest extends Specification {
final target = Mock(LocalAwareModuleVersionRepository)
+ final metaData = Mock(ModuleVersionMetaData)
final requestedDependency = Mock(DependencyMetaData)
- final result = Mock(BuildableModuleVersionMetaData)
+ final result = Mock(BuildableModuleVersionMetaDataResolveResult)
final repository = new IvyDynamicResolveModuleVersionRepository(target)
def "replaces each dependency version with revConstraint"() {
@@ -31,7 +32,8 @@ class IvyDynamicResolveModuleVersionRepositoryTest extends Specification {
def transformed = dependency()
given:
- result.state >> BuildableModuleVersionMetaData.State.Resolved
+ result.state >> BuildableModuleVersionMetaDataResolveResult.State.Resolved
+ result.metaData >> metaData
when:
repository.getLocalDependency(requestedDependency, result)
@@ -40,7 +42,7 @@ class IvyDynamicResolveModuleVersionRepositoryTest extends Specification {
1 * target.getLocalDependency(requestedDependency, result)
and:
- 1 * result.dependencies >> [original]
+ 1 * metaData.dependencies >> [original]
1 * original.withRequestedVersion('1.2+') >> transformed
1 * result.setDependencies([transformed])
}
@@ -51,7 +53,7 @@ class IvyDynamicResolveModuleVersionRepositoryTest extends Specification {
then:
1 * target.getLocalDependency(requestedDependency, result)
- _ * result.state >> BuildableModuleVersionMetaData.State.Missing
+ _ * result.state >> BuildableModuleVersionMetaDataResolveResult.State.Missing
0 * result._
}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/LazyDependencyToModuleResolverTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/LazyDependencyToModuleResolverTest.groovy
index 8828189..e53f6cb 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/LazyDependencyToModuleResolverTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/LazyDependencyToModuleResolverTest.groovy
@@ -14,25 +14,24 @@
* limitations under the License.
*/
package org.gradle.api.internal.artifacts.ivyservice.ivyresolve
-
import org.apache.ivy.core.module.descriptor.Artifact
import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor
import org.apache.ivy.core.module.descriptor.DependencyDescriptor
import org.apache.ivy.core.module.descriptor.ModuleDescriptor
import org.apache.ivy.core.module.id.ModuleRevisionId
-import org.apache.ivy.plugins.version.VersionMatcher
import org.gradle.api.artifacts.ModuleVersionSelector
import org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier
import org.gradle.api.internal.artifacts.DefaultModuleVersionSelector
import org.gradle.api.internal.artifacts.ivyservice.*
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.VersionMatcher
import spock.lang.Specification
-import static org.gradle.api.internal.artifacts.DefaultModuleVersionSelector.newSelector
import static org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier.newId
+import static org.gradle.api.internal.artifacts.DefaultModuleVersionSelector.newSelector
class LazyDependencyToModuleResolverTest extends Specification {
- final DependencyToModuleResolver target = Mock()
- final VersionMatcher matcher = Mock()
+ final target = Mock(DependencyToModuleVersionResolver)
+ final matcher = Mock(VersionMatcher)
final LazyDependencyToModuleResolver resolver = new LazyDependencyToModuleResolver(target, matcher)
def "does not resolve module for static version dependency until requested"() {
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/UserResolverChainTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/UserResolverChainTest.groovy
index 2afc920..ba14783 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/UserResolverChainTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/UserResolverChainTest.groovy
@@ -19,42 +19,38 @@ package org.gradle.api.internal.artifacts.ivyservice.ivyresolve
import org.apache.ivy.core.module.descriptor.DependencyDescriptor
import org.apache.ivy.core.module.descriptor.ModuleDescriptor
import org.apache.ivy.core.module.id.ModuleRevisionId
-import org.apache.ivy.plugins.latest.LatestRevisionStrategy
-import org.apache.ivy.plugins.resolver.ResolverSettings
-import org.apache.ivy.plugins.version.VersionMatcher
import org.gradle.api.artifacts.ModuleVersionIdentifier
import org.gradle.api.artifacts.ModuleVersionSelector
import org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier
import org.gradle.api.internal.artifacts.ivyservice.BuildableModuleVersionResolveResult
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.LatestStrategy
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.VersionMatcher
import spock.lang.Specification
class UserResolverChainTest extends Specification {
- final UserResolverChain resolver = new UserResolverChain()
- final ModuleVersionSelector dependencyId = Stub()
- final DependencyMetaData dependency = Stub()
- final DependencyDescriptor dependencyDescriptor = Stub()
final ModuleDescriptor descriptor = descriptor("1.2")
final ModuleVersionIdentifier resolvedId = moduleVersionIdentifier(descriptor)
+ final dependencyId = Stub(ModuleVersionSelector)
+ final dependency = Stub(DependencyMetaData)
+ final dependencyDescriptor = Stub(DependencyDescriptor)
+ final matcher = Stub(VersionMatcher)
+ final latestStrategy = Stub(LatestStrategy)
+ final result = Mock(BuildableModuleVersionResolveResult)
+ final moduleSource = Mock(ModuleSource)
+
+ final UserResolverChain resolver = new UserResolverChain(matcher, latestStrategy)
ModuleVersionIdentifier moduleVersionIdentifier(ModuleDescriptor moduleDescriptor) {
def moduleRevId = moduleDescriptor.moduleRevisionId
new DefaultModuleVersionIdentifier(moduleRevId.organisation, moduleRevId.name, moduleRevId.revision)
}
- final BuildableModuleVersionResolveResult result = Mock()
- final VersionMatcher matcher = Stub()
- final ModuleSource moduleSource = Mock()
-
def setup() {
_ * dependencyId.group >> "group"
_ * dependencyId.name >> "project"
_ * dependencyId.version >> "1.0"
_ * dependency.requested >> dependencyId
_ * dependency.descriptor >> dependencyDescriptor
- def settings = Stub(ResolverSettings)
- _ * settings.versionMatcher >> matcher
- _ * settings.defaultLatestStrategy >> new LatestRevisionStrategy();
- resolver.settings = settings
}
def "uses local dependency when available"() {
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/memcache/CachedModuleVersionResultTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/memcache/CachedModuleVersionResultTest.groovy
new file mode 100644
index 0000000..29a2f20
--- /dev/null
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/memcache/CachedModuleVersionResultTest.groovy
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve.memcache
+
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.BuildableModuleVersionMetaDataResolveResult
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ModuleVersionMetaData
+import spock.lang.Specification
+
+class CachedModuleVersionResultTest extends Specification {
+
+ def "knows if result is cachable"() {
+ def resolved = Mock(BuildableModuleVersionMetaDataResolveResult) {
+ getState() >> BuildableModuleVersionMetaDataResolveResult.State.Resolved
+ getMetaData() >> Stub(ModuleVersionMetaData)
+ }
+ def missing = Mock(BuildableModuleVersionMetaDataResolveResult) { getState() >> BuildableModuleVersionMetaDataResolveResult.State.Missing }
+ def probablyMissing = Mock(BuildableModuleVersionMetaDataResolveResult) { getState() >> BuildableModuleVersionMetaDataResolveResult.State.ProbablyMissing }
+ def failed = Mock(BuildableModuleVersionMetaDataResolveResult) { getState() >> BuildableModuleVersionMetaDataResolveResult.State.Failed }
+
+ expect:
+ new CachedModuleVersionResult(resolved).cacheable
+ new CachedModuleVersionResult(missing).cacheable
+ new CachedModuleVersionResult(probablyMissing).cacheable
+ !new CachedModuleVersionResult(failed).cacheable
+ }
+
+ def "interrogates result only when resolved"() {
+ def resolved = Mock(BuildableModuleVersionMetaDataResolveResult)
+ def missing = Mock(BuildableModuleVersionMetaDataResolveResult)
+
+ when:
+ new CachedModuleVersionResult(missing)
+
+ then:
+ 1 * missing.getState() >> BuildableModuleVersionMetaDataResolveResult.State.Missing
+ 0 * missing._
+
+ when:
+ new CachedModuleVersionResult(resolved)
+
+ then:
+ 1 * resolved.getState() >> BuildableModuleVersionMetaDataResolveResult.State.Resolved
+ 1 * resolved.getMetaData() >> Stub(ModuleVersionMetaData)
+ }
+
+ def "supplies cached data"() {
+ def resolved = Mock(BuildableModuleVersionMetaDataResolveResult) {
+ getState() >> BuildableModuleVersionMetaDataResolveResult.State.Resolved
+ getMetaData() >> Stub(ModuleVersionMetaData)
+ }
+ def missing = Mock(BuildableModuleVersionMetaDataResolveResult) { getState() >> BuildableModuleVersionMetaDataResolveResult.State.Missing }
+ def probablyMissing = Mock(BuildableModuleVersionMetaDataResolveResult) { getState() >> BuildableModuleVersionMetaDataResolveResult.State.ProbablyMissing }
+
+ def result = Mock(BuildableModuleVersionMetaDataResolveResult)
+
+ when:
+ new CachedModuleVersionResult(resolved).supply(result)
+ then:
+ 1 * result.resolved(_, _, _, _)
+
+ when:
+ new CachedModuleVersionResult(missing).supply(result)
+ then:
+ 1 * result.missing()
+
+ when:
+ new CachedModuleVersionResult(probablyMissing).supply(result)
+ then:
+ 1 * result.probablyMissing()
+ }
+}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/memcache/CachedRepositoryTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/memcache/CachedRepositoryTest.groovy
new file mode 100644
index 0000000..9e9a1a5
--- /dev/null
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/memcache/CachedRepositoryTest.groovy
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve.memcache
+
+import org.gradle.api.artifacts.ArtifactIdentifier
+import org.gradle.api.internal.artifacts.ivyservice.BuildableArtifactResolveResult
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.BuildableModuleVersionMetaDataResolveResult
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.DependencyMetaData
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.LocalAwareModuleVersionRepository
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ModuleSource
+import spock.lang.Specification
+
+import static org.gradle.api.internal.artifacts.DefaultModuleVersionSelector.newSelector
+
+class CachedRepositoryTest extends Specification {
+
+ def stats = new DependencyMetadataCacheStats()
+ def cache = Mock(DependencyMetadataCache)
+ def delegate = Mock(LocalAwareModuleVersionRepository)
+ def repo = new CachedRepository(cache, delegate, stats)
+
+ def lib = newSelector("org", "lib", "1.0")
+ def dep = Stub(DependencyMetaData) { getRequested() >> lib }
+ def result = Mock(BuildableModuleVersionMetaDataResolveResult)
+
+ def "delegates"() {
+ when:
+ def id = repo.getId()
+ def name = repo.getName()
+
+ then:
+ id == "x"
+ name == "localRepo"
+ 1 * delegate.getId() >> "x"
+ 1 * delegate.getName() >> "localRepo"
+ }
+
+ def "retrieves and caches local dependencies"() {
+ when:
+ repo.getLocalDependency(dep, result)
+
+ then:
+ 1 * cache.supplyLocalMetaData(lib, result) >> false
+ 1 * delegate.getLocalDependency(dep, result)
+ 1 * cache.newLocalDependencyResult(lib, result)
+ 0 * _
+ }
+
+ def "uses local dependencies from cache"() {
+ when:
+ repo.getLocalDependency(dep, result)
+
+ then:
+ 1 * cache.supplyLocalMetaData(lib, result) >> true
+ 0 * _
+ }
+
+ def "retrieves and caches dependencies"() {
+ when:
+ repo.getDependency(dep, result)
+
+ then:
+ 1 * cache.supplyMetaData(lib, result) >> false
+ 1 * delegate.getDependency(dep, result)
+ 1 * cache.newDependencyResult(lib, result)
+ 0 * _
+ }
+
+ def "uses dependencies from cache"() {
+ when:
+ repo.getDependency(dep, result)
+
+ then:
+ 1 * cache.supplyMetaData(lib, result) >> true
+ 0 * _
+ }
+
+ def "retrieves and caches artifacts"() {
+ def result = Mock(BuildableArtifactResolveResult)
+ def artifact = Stub(ArtifactIdentifier)
+ def source = Mock(ModuleSource)
+
+ when:
+ repo.resolve(artifact, result, source)
+
+ then:
+ 1 * cache.supplyArtifact(artifact, result) >> false
+ 1 * delegate.resolve(artifact, result, source)
+ 1 * cache.newArtifact(artifact, result)
+ 0 * _
+ }
+
+ def "uses artifacts from cache"() {
+ def result = Mock(BuildableArtifactResolveResult)
+ def artifact = Stub(ArtifactIdentifier)
+
+ when:
+ repo.resolve(artifact, result, Mock(ModuleSource))
+
+ then:
+ 1 * cache.supplyArtifact(artifact, result) >> true
+ 0 * _
+ }
+}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/memcache/DependencyMetadataCacheTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/memcache/DependencyMetadataCacheTest.groovy
new file mode 100644
index 0000000..cd4ff8f
--- /dev/null
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/memcache/DependencyMetadataCacheTest.groovy
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve.memcache
+
+import org.gradle.api.artifacts.ArtifactIdentifier
+import org.gradle.api.internal.artifacts.ivyservice.BuildableArtifactResolveResult
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.BuildableModuleVersionMetaDataResolveResult
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ModuleVersionMetaData
+import spock.lang.Specification
+
+import static org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier.newId
+import static org.gradle.api.internal.artifacts.DefaultModuleVersionSelector.newSelector
+
+class DependencyMetadataCacheTest extends Specification {
+
+ def stats = new DependencyMetadataCacheStats()
+ def cache = new DependencyMetadataCache(stats)
+
+ def "caches and supplies remote metadata"() {
+ def resolvedResult = Mock(BuildableModuleVersionMetaDataResolveResult.class) {
+ getState() >> BuildableModuleVersionMetaDataResolveResult.State.Resolved
+ getMetaData() >> Stub(ModuleVersionMetaData)
+ }
+ cache.newDependencyResult(newSelector("org", "foo", "1.0"), resolvedResult)
+ def result = Mock(BuildableModuleVersionMetaDataResolveResult.class)
+
+ when:
+ def local = cache.supplyLocalMetaData(newSelector("org", "foo", "1.0"), result)
+ def differentSelector = cache.supplyMetaData(newSelector("org", "XXX", "1.0"), result)
+
+ then:
+ !local
+ !differentSelector
+ stats.metadataServed == 0
+ 0 * result._
+
+ when:
+ def match = cache.supplyMetaData(newSelector("org", "foo", "1.0"), result)
+
+ then:
+ match
+ stats.metadataServed == 1
+ 1 * result.resolved(_, _, _, _)
+ }
+
+ def "caches and supplies remote and local metadata"() {
+ def resolvedLocal = Mock(BuildableModuleVersionMetaDataResolveResult.class) {
+ getMetaData() >> Mock(ModuleVersionMetaData)
+ getState() >> BuildableModuleVersionMetaDataResolveResult.State.Resolved
+ }
+ def resolvedRemote = Mock(BuildableModuleVersionMetaDataResolveResult.class) {
+ getMetaData() >> Mock(ModuleVersionMetaData)
+ getState() >> BuildableModuleVersionMetaDataResolveResult.State.Resolved
+ }
+
+ cache.newDependencyResult(newSelector("org", "remote", "1.0"), resolvedRemote)
+ cache.newLocalDependencyResult(newSelector("org", "local", "1.0"), resolvedLocal)
+
+ def result = Mock(BuildableModuleVersionMetaDataResolveResult.class)
+
+ when:
+ def local = cache.supplyLocalMetaData(newSelector("org", "local", "1.0"), result)
+ def remote = cache.supplyMetaData(newSelector("org", "remote", "1.0"), result)
+
+ then:
+ local
+ remote
+ stats.metadataServed == 2
+ 1 * result.resolved(_, _, _, _)
+ 1 * result.resolved(_, _, _, _)
+ }
+
+ def "does not cache failed resolves"() {
+ def failedResult = Mock(BuildableModuleVersionMetaDataResolveResult.class) { getState() >> BuildableModuleVersionMetaDataResolveResult.State.Failed }
+ cache.newDependencyResult(newSelector("org", "lib", "1.0"), failedResult)
+
+ def result = Mock(BuildableModuleVersionMetaDataResolveResult.class)
+
+ when:
+ def fromCache = cache.supplyMetaData(newSelector("org", "lib", "1.0"), result)
+
+ then:
+ !fromCache
+ 0 * result._
+ }
+
+ def "caches and supplies artifacts"() {
+ def foo = Stub(ArtifactIdentifier) { getModuleVersionIdentifier() >> newId("org", "foo", "1.0") }
+ def fooFile = new File("foo")
+ def fooResult = Mock(BuildableArtifactResolveResult) { getFile() >> fooFile }
+ def anotherFooResult = Mock(BuildableArtifactResolveResult)
+
+ def different = Stub(ArtifactIdentifier) { getModuleVersionIdentifier() >> newId("org", "XXX", "1.0") }
+ def differentResult = Mock(BuildableArtifactResolveResult)
+
+ cache.newArtifact(foo, fooResult)
+
+ when:
+ def differentCached = cache.supplyArtifact(different, differentResult )
+
+ then:
+ !differentCached
+ 0 * differentResult._
+
+ when:
+ def fooCached = cache.supplyArtifact(foo, anotherFooResult )
+
+ then:
+ fooCached
+ 1 * anotherFooResult.resolved(fooFile)
+ }
+}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/memcache/InMemoryDependencyMetadataCacheTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/memcache/InMemoryDependencyMetadataCacheTest.groovy
new file mode 100644
index 0000000..fe3067b
--- /dev/null
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/memcache/InMemoryDependencyMetadataCacheTest.groovy
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve.memcache
+
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.LocalAwareModuleVersionRepository
+import org.gradle.util.SetSystemProperties
+import org.junit.Rule
+import spock.lang.Specification
+
+class InMemoryDependencyMetadataCacheTest extends Specification {
+
+ @Rule SetSystemProperties sysProp = new SetSystemProperties()
+ def cache = new InMemoryDependencyMetadataCache()
+
+ def "can be turned off via system property"() {
+ System.properties.setProperty(InMemoryDependencyMetadataCache.TOGGLE_PROPERTY, "false")
+ def repo = Mock(LocalAwareModuleVersionRepository) { getId() >> "mavenCentral" }
+
+ when:
+ def out = cache.cached(repo)
+
+ then:
+ out.is(repo)
+ }
+
+ def "wraps repositories"() {
+ def repo1 = Mock(LocalAwareModuleVersionRepository) { getId() >> "mavenCentral" }
+ def repo2 = Mock(LocalAwareModuleVersionRepository) { getId() >> "localRepo" }
+ def repo3 = Mock(LocalAwareModuleVersionRepository) { getId() >> "mavenCentral" }
+
+ when:
+ CachedRepository c1 = cache.cached(repo1)
+ CachedRepository c2 = cache.cached(repo2)
+ CachedRepository c3 = cache.cached(repo3)
+
+ then:
+ c1.delegate == repo1
+ c2.delegate == repo2
+ c3.delegate == repo3
+
+ c1.cache == c3.cache //same repo id, same cache
+ c2.cache != c1.cache
+
+ cache.stats.reposWrapped == 3
+ cache.stats.cacheInstances == 2
+
+ cache.cachePerRepo.size() == 2
+ }
+
+ def "cleans cache on close"() {
+ when:
+ cache.cached(Mock(LocalAwareModuleVersionRepository) { getId() >> "x"} )
+ cache.stop()
+
+ then:
+ cache.cachePerRepo.isEmpty()
+ }
+}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/DownloadedIvyModuleDescriptorParserTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/DownloadedIvyModuleDescriptorParserTest.groovy
index a7162e4..39e458d 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/DownloadedIvyModuleDescriptorParserTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/DownloadedIvyModuleDescriptorParserTest.groovy
@@ -16,9 +16,6 @@
package org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser
-import org.apache.ivy.core.settings.IvySettings
-import org.apache.ivy.plugins.parser.ParserSettings
-import org.apache.ivy.plugins.repository.Resource
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
import org.junit.Rule
import spock.lang.Specification
@@ -26,6 +23,7 @@ import spock.lang.Specification
class DownloadedIvyModuleDescriptorParserTest extends Specification {
@Rule TestNameTestDirectoryProvider tmpDir
final DownloadedIvyModuleDescriptorParser parser = new DownloadedIvyModuleDescriptorParser()
+ final parserSettings = Mock(DescriptorParseContext)
def "discards the default attribute"() {
def ivyFile = tmpDir.createFile("ivy.xml")
@@ -34,12 +32,9 @@ class DownloadedIvyModuleDescriptorParserTest extends Specification {
<info organisation="org" module="someModule" revision="1.2" default="true"/>
</ivy-module>
"""
- def url = ivyFile.toURI().toURL()
- ParserSettings settings = new IvySettings()
- Resource resource = Mock()
-
when:
- def descriptor = parser.parseDescriptor(settings, url, resource, true)
+ parserSettings.substitute(_ as String) >> {String value -> value}
+ def descriptor = parser.parseDescriptor(parserSettings, ivyFile, true)
then:
!descriptor.default
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/GradlePomModuleDescriptorParserTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/GradlePomModuleDescriptorParserTest.groovy
index 57a5d3a..57be866 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/GradlePomModuleDescriptorParserTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/GradlePomModuleDescriptorParserTest.groovy
@@ -14,12 +14,11 @@
* limitations under the License.
*/
package org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser
-
import org.apache.ivy.core.module.descriptor.DependencyDescriptor
import org.apache.ivy.core.module.descriptor.ModuleDescriptor
import org.apache.ivy.core.module.id.ArtifactRevisionId
+import org.apache.ivy.core.module.id.ModuleId
import org.apache.ivy.core.module.id.ModuleRevisionId
-import org.apache.ivy.plugins.parser.ParserSettings
import org.gradle.test.fixtures.file.TestFile
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
import org.junit.Rule
@@ -29,7 +28,7 @@ import spock.lang.Specification
class GradlePomModuleDescriptorParserTest extends Specification {
@Rule public final TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider()
final GradlePomModuleDescriptorParser parser = new GradlePomModuleDescriptorParser()
- final ModuleScopedParserSettings ivySettings = Mock()
+ final parseContext = Mock(DescriptorParseContext)
TestFile pomFile
def "setup"() {
@@ -57,7 +56,7 @@ class GradlePomModuleDescriptorParserTest extends Specification {
</project>
"""
and:
- ivySettings.currentRevisionId >> moduleId('group-one', 'artifact-one', 'version-one')
+ parseContext.currentRevisionId >> moduleId('group-one', 'artifact-one', 'version-one')
when:
def descriptor = parsePom()
@@ -70,6 +69,55 @@ class GradlePomModuleDescriptorParserTest extends Specification {
hasDefaultDependencyArtifact(descriptor.dependencies.first())
}
+ def "uses dependency management section to provide default values for a dependency"() {
+ given:
+ pomFile << """
+<project>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>group-one</groupId>
+ <artifactId>artifact-one</artifactId>
+ <version>version-one</version>
+
+ <dependencies>
+ <dependency>
+ <groupId>group-two</groupId>
+ <artifactId>artifact-two</artifactId>
+ </dependency>
+ </dependencies>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>group-two</groupId>
+ <artifactId>artifact-two</artifactId>
+ <version>1.2</version>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>group-three</groupId>
+ <artifactId>artifact-three</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+</project>
+"""
+ and:
+ parseContext.currentRevisionId >> moduleId('group-one', 'artifact-one', 'version-one')
+
+ when:
+ def descriptor = parsePom()
+
+ then:
+ descriptor.dependencies.length == 1
+ def dep = descriptor.dependencies.first()
+ dep.dependencyRevisionId == moduleId('group-two', 'artifact-two', '1.2')
+ dep.moduleConfigurations == ['test']
+ dep.allExcludeRules.length == 1
+ dep.allExcludeRules.first().id.moduleId == ModuleId.newInstance('group-three', 'artifact-three')
+ hasDefaultDependencyArtifact(dep)
+ }
+
def "pom with dependency with classifier"() {
given:
pomFile << """
@@ -90,7 +138,7 @@ class GradlePomModuleDescriptorParserTest extends Specification {
</project>
"""
and:
- ivySettings.currentRevisionId >> moduleId('group-one', 'artifact-one', 'version-one')
+ parseContext.currentRevisionId >> moduleId('group-one', 'artifact-one', 'version-one')
when:
def descriptor = parsePom()
@@ -124,7 +172,7 @@ class GradlePomModuleDescriptorParserTest extends Specification {
</project>
"""
and:
- ivySettings.currentRevisionId >> moduleId('group-one', 'artifact-one', 'version-one')
+ parseContext.currentRevisionId >> moduleId('group-one', 'artifact-one', 'version-one')
when:
def descriptor = parsePom()
@@ -150,7 +198,7 @@ class GradlePomModuleDescriptorParserTest extends Specification {
</project>
"""
and:
- ivySettings.currentRevisionId >> moduleId('group-one', 'artifact-one', 'version-one')
+ parseContext.currentRevisionId >> moduleId('group-one', 'artifact-one', 'version-one')
when:
def descriptor = parsePom()
@@ -161,8 +209,25 @@ class GradlePomModuleDescriptorParserTest extends Specification {
descriptor.dependencies.length == 0
}
+ def "fails when POM is not well formed XML"() {
+ given:
+ pomFile << """
+<project>
+ <modelVersion
+</project>
+"""
+
+ when:
+ parsePom()
+
+ then:
+ def e = thrown(MetaDataParseException)
+ e.message == "Could not parse POM ${pomFile.toURI()}"
+ e.cause.message.contains('Element type "modelVersion"')
+ }
+
private ModuleDescriptor parsePom() {
- parser.parseDescriptor(ivySettings, pomFile.toURI().toURL(), false)
+ parser.parseDescriptor(parseContext, pomFile, true)
}
private void hasArtifact(ModuleDescriptor descriptor, String name, String type, String ext, String classifier = null) {
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/IvyXmlModuleDescriptorParserTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/IvyXmlModuleDescriptorParserTest.groovy
index b8f0ba2..f442c40 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/IvyXmlModuleDescriptorParserTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/IvyXmlModuleDescriptorParserTest.groovy
@@ -16,35 +16,51 @@
package org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser
import org.apache.ivy.core.module.descriptor.*
-import org.apache.ivy.core.settings.IvySettings
import org.apache.ivy.plugins.matcher.ExactPatternMatcher
import org.apache.ivy.plugins.matcher.GlobPatternMatcher
import org.apache.ivy.plugins.matcher.PatternMatcher
+import org.apache.ivy.plugins.matcher.RegexpPatternMatcher
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
import org.gradle.util.Resources
-import org.hamcrest.Matchers
import org.junit.Rule
+import spock.lang.Issue
import spock.lang.Specification
-import java.text.ParseException
-
-import static junit.framework.Assert.*
-import static org.junit.Assert.assertThat
+import static org.junit.Assert.*
class IvyXmlModuleDescriptorParserTest extends Specification {
- @Rule public final Resources resources = new Resources()
+ @Rule
+ public final Resources resources = new Resources()
@Rule TestNameTestDirectoryProvider temporaryFolder = new TestNameTestDirectoryProvider()
IvyXmlModuleDescriptorParser parser = new IvyXmlModuleDescriptorParser()
- IvySettings settings = new IvySettings()
+ DescriptorParseContext parseContext = Mock()
def setup() {
- settings.setDefaultCache(temporaryFolder.createDir("ivy/cache"))
+ parseContext.substitute(_ as String) >> {String value -> value}
+ parseContext.getMatcher("exact") >> ExactPatternMatcher.INSTANCE
+ parseContext.getMatcher("glob") >> GlobPatternMatcher.INSTANCE
+ parseContext.getMatcher("regexp") >> RegexpPatternMatcher.INSTANCE
}
- def testEmptyDependencies() throws Exception {
+ def "parses Ivy descriptor with empty dependencies section"() throws Exception {
when:
- ModuleDescriptor md = parser.parseDescriptor(settings, resources.getResource("test-empty-dependencies.xml").toURI().toURL(), true)
+ def file = temporaryFolder.file("ivy.xml") << """
+<ivy-module version="1.0">
+ <info organisation="myorg"
+ module="mymodule"
+ revision="myrev"
+ status="integration"
+ publication="20041101110000"
+ />
+ <dependencies>
+ </dependencies>
+</ivy-module>
+"""
+ ModuleDescriptor md = parser.parseDescriptor(parseContext, file, true)
+
+ and:
+
then:
md != null
"myorg" == md.getModuleRevisionId().getOrganisation()
@@ -61,25 +77,90 @@ class IvyXmlModuleDescriptorParserTest extends Specification {
0 == md.getDependencies().length
}
- public void testBadConfs() throws IOException {
+ public void "fails when configuration extends an unknown configuration"() throws IOException {
+ def file = temporaryFolder.file("ivy.xml") << """
+<ivy-module version="1.0">
+ <info organisation="myorg"
+ module="mymodule"
+ status="integration"
+ />
+ <configurations>
+ <conf name="A" extends="invalidConf"/>
+ </configurations>
+</ivy-module>
+"""
+
+ when:
+ parser.parseDescriptor(parseContext, file, true)
+
+ then:
+ def e = thrown(MetaDataParseException)
+ e.message == "Could not parse Ivy file ${file.toURI()}"
+ e.cause.message == "unknown configuration 'invalidConf'. It is extended by A"
+ }
+
+ public void "fails when there is a cycle in configuration hierarchy"() throws IOException {
+ def file = temporaryFolder.file("ivy.xml") << """
+<ivy-module version="1.0">
+ <info organisation="myorg"
+ module="mymodule"
+ status="integration"
+ />
+ <configurations>
+ <conf name="A" extends="B"/>
+ <conf name="B" extends="A"/>
+ </configurations>
+</ivy-module>
+"""
+
+ when:
+ parser.parseDescriptor(parseContext, file, true)
+
+ then:
+ def e = thrown(MetaDataParseException)
+ e.message == "Could not parse Ivy file ${file.toURI()}"
+ e.cause.message == "illegal cycle detected in configuration extension: A => B => A"
+ }
+
+ public void "fails when descriptor contains badly formed XML"() {
+ def file = temporaryFolder.file("ivy.xml") << """
+<ivy-module version="1.0">
+ <info
+</ivy-module>
+"""
+
when:
- parser.parseDescriptor(settings, resources.getResource("test-bad-confs.xml").toURI().toURL(), true)
+ parser.parseDescriptor(parseContext, file, true)
+
then:
- def e = thrown(ParseException)
- assertThat(e.message, Matchers.startsWith("unknown configuration 'invalidConf'"))
+ def e = thrown(MetaDataParseException)
+ e.message == "Could not parse Ivy file ${file.toURI()}"
+ e.cause.message.contains('Element type "info"')
}
- public void testCyclicConfs() throws IOException {
+ public void "fails when descriptor does not match schema"() {
+ def file = temporaryFolder.file("ivy.xml") << """
+<ivy-module version="1.0">
+ <not-an-ivy-file/>
+</ivy-module>
+"""
+
when:
- parser.parseDescriptor(settings, resources.getResource("test-cyclic-confs1.xml").toURI().toURL(), true)
+ parser.parseDescriptor(parseContext, file, true)
+
then:
- def e = thrown(ParseException)
- assertThat(e.message, Matchers.startsWith("illegal cycle detected in configuration extension: A => B => A"))
+ def e = thrown(MetaDataParseException)
+ e.message == "Could not parse Ivy file ${file.toURI()}"
+ e.cause.message.contains('unknown tag not-an-ivy-file')
}
- public void testFull() throws Exception {
+ public void "parses a full Ivy descriptor"() throws Exception {
+ def file = temporaryFolder.file("ivy.xml")
+ file.text = resources.getResource("test-full.xml").text
+
when:
- ModuleDescriptor md = parser.parseDescriptor(settings, resources.getResource("test-full.xml").toURI().toURL(), false)
+ ModuleDescriptor md = parser.parseDescriptor(parseContext, file, true)
+
then:
assertNotNull(md)
assertEquals("myorg", md.getModuleRevisionId().getOrganisation())
@@ -136,6 +217,128 @@ class IvyXmlModuleDescriptorParserTest extends Specification {
true
}
+ @Issue("http://issues.gradle.org/browse/GRADLE-2766")
+ def "defaultconfmapping is respected"() {
+ given:
+ def file = temporaryFolder.createFile("ivy.xml")
+ file.text = """
+ <ivy-module version="2.0" xmlns:e="http://ant.apache.org/ivy/extra">
+ <info organisation="myorg"
+ module="mymodule"
+ revision="myrev"
+ status="integration"
+ publication="20041101110000">
+ </info>
+ <configurations>
+ <conf name="myconf" />
+ </configurations>
+ <publications/>
+ <dependencies defaultconfmapping="myconf->default">
+ <dependency name="mymodule2"/>
+ </dependencies>
+ </ivy-module>
+ """
+
+ when:
+ def descriptor = parser.parseDescriptor(parseContext, file, false)
+ def dependency = descriptor.dependencies.first()
+
+ then:
+ dependency.moduleConfigurations == ["myconf"]
+ }
+
+ def "parses dependency config mappings"() {
+ given:
+ def file = temporaryFolder.createFile("ivy.xml")
+ file.text = """
+ <ivy-module version="2.0" xmlns:e="http://ant.apache.org/ivy/extra">
+ <info organisation="myorg"
+ module="mymodule"
+ revision="myrev">
+ </info>
+ <configurations>
+ <conf name="a" />
+ <conf name="b" />
+ <conf name="c" />
+ </configurations>
+ <publications/>
+ <dependencies>
+ <dependency name="mymodule2" conf="a"/>
+ <dependency name="mymodule2" conf="a->other"/>
+ <dependency name="mymodule2" conf="*->@"/>
+ <dependency name="mymodule2" conf="a->other;%->@"/>
+ <dependency name="mymodule2" conf="*,!a->@"/>
+ <dependency name="mymodule2" conf="a->*"/>
+ <dependency name="mymodule2" conf="a->one,two;a,b->three;*->four;%->none"/>
+ <dependency name="mymodule2" conf="a->#"/>
+ <dependency name="mymodule2" conf="a->a;%->@"/>
+ <dependency name="mymodule2" conf="a->a;*,!a->b"/>
+ </dependencies>
+ </ivy-module>
+ """
+
+ when:
+ def descriptor = parser.parseDescriptor(parseContext, file, false)
+
+ then:
+ def dependency1 = descriptor.dependencies[0]
+ dependency1.moduleConfigurations == ["a"]
+ dependency1.getDependencyConfigurations("a") == ["a"]
+ dependency1.getDependencyConfigurations("a", "requested") == ["a"]
+
+ def dependency2 = descriptor.dependencies[1]
+ dependency2.moduleConfigurations == ["a"]
+ dependency2.getDependencyConfigurations("a") == ["other"]
+ dependency2.getDependencyConfigurations("a", "requested") == ["other"]
+
+ def dependency3 = descriptor.dependencies[2]
+ dependency3.moduleConfigurations == ["*"]
+ dependency3.getDependencyConfigurations("a") == ["a"]
+ dependency3.getDependencyConfigurations("a", "requested") == ["a"]
+
+ def dependency4 = descriptor.dependencies[3]
+ dependency4.moduleConfigurations == ["a", "%"]
+ dependency4.getDependencyConfigurations("a") == ["other"]
+ dependency4.getDependencyConfigurations("a", "requested") == ["other"]
+ dependency4.getDependencyConfigurations("b") == ["b"]
+ dependency4.getDependencyConfigurations("b", "requested") == ["b"]
+
+ def dependency5 = descriptor.dependencies[4]
+ dependency5.moduleConfigurations == ["*", "!a"]
+ dependency5.getDependencyConfigurations("a") == ["a"]
+ dependency5.getDependencyConfigurations("a", "requested") == ["a"]
+
+ def dependency6 = descriptor.dependencies[5]
+ dependency6.moduleConfigurations == ["a"]
+ dependency6.getDependencyConfigurations("a") == ["*"]
+ dependency6.getDependencyConfigurations("a", "requested") == ["*"]
+
+ def dependency7 = descriptor.dependencies[6]
+ dependency7.moduleConfigurations == ["a", "b", "*", "%"]
+ dependency7.getDependencyConfigurations("a") == ["one", "two", "three", "four"]
+ dependency7.getDependencyConfigurations("b") == ["three", "four"]
+ dependency7.getDependencyConfigurations("c") == ["none", "four"]
+
+ def dependency8 = descriptor.dependencies[7]
+ dependency8.moduleConfigurations == ["a"]
+ dependency8.getDependencyConfigurations("a") == ["a"]
+ dependency8.getDependencyConfigurations("a", "requested") == ["requested"]
+
+ def dependency9 = descriptor.dependencies[8]
+ dependency9.moduleConfigurations == ["a", "%"]
+ dependency9.getDependencyConfigurations("a") == ["a"]
+ dependency9.getDependencyConfigurations("a", "requested") == ["a"]
+ dependency9.getDependencyConfigurations("b") == ["b"]
+ dependency9.getDependencyConfigurations("b", "requested") == ["b"]
+
+ def dependency10 = descriptor.dependencies[9]
+ dependency10.moduleConfigurations == ["a", "*", "!a"]
+ dependency10.getDependencyConfigurations("a") == ["a", "b"]
+ dependency10.getDependencyConfigurations("a", "requested") == ["a", "b"]
+ dependency10.getDependencyConfigurations("b") == ["b"]
+ dependency10.getDependencyConfigurations("b", "requested") == ["b"]
+ }
+
def verifyFullDependencies(DependencyDescriptor[] dependencies) {
// no conf def => equivalent to *->*
DependencyDescriptor dd = getDependency(dependencies, "mymodule2")
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/ChainVersionMatcherTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/ChainVersionMatcherTest.groovy
new file mode 100644
index 0000000..5d09bb0
--- /dev/null
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/ChainVersionMatcherTest.groovy
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy
+
+import org.gradle.api.artifacts.ModuleVersionIdentifier
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ModuleVersionMetaData
+import spock.lang.Specification
+
+class ChainVersionMatcherTest extends Specification {
+ def chain = new ChainVersionMatcher()
+ def matcher1 = Mock(VersionMatcher)
+ def matcher2 = Mock(VersionMatcher)
+ def matcher3 = Mock(VersionMatcher)
+
+ def setup() {
+ chain.add(matcher1)
+ chain.add(matcher2)
+ chain.add(matcher3)
+ }
+
+ def "doesn't support canHandle method (no known use case)"() {
+ when:
+ chain.canHandle("1")
+
+ then:
+ UnsupportedOperationException e = thrown()
+ e.message.contains("canHandle")
+ }
+
+ def "delegates isDynamic to first matcher that can handle the selector"() {
+ when:
+ def result = chain.isDynamic("1+")
+
+ then:
+ 1 * matcher1.canHandle("1+") >> false
+ 1 * matcher2.canHandle("1+") >> true
+ 1 * matcher2.isDynamic("1+") >> true
+ 0 * _
+
+ and:
+ result
+ }
+
+ def "delegates needModuleMetadata to first matcher that can handle the selector"() {
+ when:
+ def result = chain.needModuleMetadata("1+", "2")
+
+ then:
+ 1 * matcher1.canHandle("1+") >> false
+ 1 * matcher2.canHandle("1+") >> true
+ 1 * matcher2.needModuleMetadata("1+", "2") >> false
+ 0 * _
+
+ and:
+ !result
+ }
+
+ def "delegates accept to first matcher that can handle the selector"() {
+ when:
+ def result = chain.accept("1+", "2")
+
+ then:
+ 1 * matcher1.canHandle("1+") >> false
+ 1 * matcher2.canHandle("1+") >> true
+ 1 * matcher2.accept("1+", "2") >> false
+ 0 * _
+
+ and:
+ !result
+ }
+
+ def "delegates metadata-aware accept to first matcher that can handle the selector"() {
+ def metadata = Stub(ModuleVersionMetaData) {
+ getId() >> Stub(ModuleVersionIdentifier) {
+ getVersion() >> "2"
+ }
+ }
+
+ when:
+ def result = chain.accept("1+", metadata)
+
+ then:
+ 1 * matcher1.canHandle("1+") >> false
+ 1 * matcher2.canHandle("1+") >> true
+ 1 * matcher2.accept("1+", metadata) >> false
+ 0 * _
+
+ and:
+ !result
+ }
+
+ def "delegates compare to first matcher that can handle the selector"() {
+ def comparator = Stub(Comparator)
+
+ when:
+ def result = chain.compare("1+", "2")
+
+ then:
+ 1 * matcher1.canHandle("1+") >> false
+ 1 * matcher2.canHandle("1+") >> true
+ 1 * matcher2.compare("1+", "2") >> -3
+ 0 * _
+
+ and:
+ result == -3
+ }
+
+ def "complains if a version selector isn't matched by any matcher"() {
+ when:
+ chain.accept("1+", "1")
+
+ then:
+ IllegalArgumentException e = thrown()
+ e.message == "Invalid version selector: 1+"
+ }
+}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/ExactVersionMatcherTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/ExactVersionMatcherTest.groovy
new file mode 100644
index 0000000..3934423
--- /dev/null
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/ExactVersionMatcherTest.groovy
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy
+
+import org.gradle.api.artifacts.ModuleVersionIdentifier
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ModuleVersionMetaData
+
+import spock.lang.Specification
+
+class ExactVersionMatcherTest extends Specification {
+ def matcher = new ExactVersionMatcher()
+
+ def "can handle any version selector"() {
+ expect:
+ matcher.canHandle("1.0")
+ matcher.canHandle("[1.0,2.0]")
+ matcher.canHandle("!@#%")
+ }
+
+ def "considers selector as static"() {
+ expect:
+ !matcher.isDynamic("1.0")
+ !matcher.isDynamic("[1.0,2.0]")
+ }
+
+ def "doesn't need metadata"() {
+ expect:
+ !matcher.needModuleMetadata("1.0", "1.0")
+ !matcher.needModuleMetadata("[1.0,2.0]", "2.0")
+ }
+
+ def "accepts candidate version iff it literally matches the selector"() {
+ expect:
+ matcher.accept("", "")
+ matcher.accept("1.0", "1.0")
+ matcher.accept("2.0", "2.0")
+ matcher.accept("!@#%", "!@#%")
+ matcher.accept("hey joe", "hey joe")
+ !matcher.accept("1.0", "1.1")
+ !matcher.accept("2.0", "3.0")
+ !matcher.accept("!@#%", "%#@!")
+ !matcher.accept("hey joe", "hoe hey")
+ }
+
+ def "does not accept candidate version that differs in separator"() {
+ expect:
+ !matcher.accept("1.0", "1_0")
+ !matcher.accept("1_0", "1-0")
+ !matcher.accept("1-0", "1+0")
+ !matcher.accept("1.a.2", "1a2")
+ }
+
+ def "does not accept candidate version that has different number of trailing .0's"() {
+ expect:
+ !matcher.accept("1.0.0", "1.0")
+ !matcher.accept("1", "1.0.0")
+ }
+
+ def "does not accept candidate version that has different capitalization"() {
+ !matcher.accept("1.0-alpha", "1.0-ALPHA")
+ }
+
+ def "supports metadata-aware accept method (with same result)"() {
+ def metadata = Stub(ModuleVersionMetaData) {
+ getId() >> Stub(ModuleVersionIdentifier) {
+ getVersion() >> metadataVersion
+ }
+ }
+
+ expect:
+ matcher.accept("1.0", metadata) == result
+
+ where:
+ metadataVersion | result
+ "1.0" | true
+ "2.0" | false
+ }
+
+ def "compares versions lexicographically"() {
+ expect:
+ matcher.compare(v1, v2) < 0
+ matcher.compare(v2, v1) > 0
+ matcher.compare(v1, v1) == 0
+ matcher.compare(v2, v2) == 0
+
+ where:
+ v1 | v2
+ "1.0" | "2.0"
+ "1.0" | "1.1"
+ "1.0.1" | "1.1.0"
+ "1.2" | "1.2.3"
+ "1.0-1" | "1.0-2"
+ "1.0.a" | "1.0.b"
+ "1.0-alpha" | "1.0"
+ "1.0-alpha" | "1.0-beta"
+ "1.0.alpha" | "1.0.b"
+ }
+
+ def "gives some special treatment to 'dev', 'rc', and 'final' qualifiers"() {
+ expect:
+ matcher.compare(v1, v2) < 0
+ matcher.compare(v2, v1) > 0
+ matcher.compare(v1, v1) == 0
+ matcher.compare(v2, v2) == 0
+
+ where:
+ v1 | v2
+ "1.0-dev-1" | "1.0"
+ "1.0-dev-1" | "1.0-dev-2"
+ "1.0-rc-1" | "1.0"
+ "1.0-rc-1" | "1.0-rc-2"
+ "1.0-final" | "1.0"
+ "1.0-dev-1" | "1.0-rc-1"
+ "1.0-rc-1" | "1.0-final"
+ "1.0-dev-1" | "1.0-final"
+ }
+
+ def "compares identical versions equal"() {
+ expect:
+ matcher.compare(v1, v2) == 0
+ matcher.compare(v2, v1) == 0
+
+ where:
+ v1 | v2
+ "" | ""
+ "1" | "1"
+ "1.0.0" | "1.0.0"
+ "!@#%" | "!@#%"
+ "hey joe" | "hey joe"
+ }
+
+ def "compares versions that differ only in separators equal"() {
+ expect:
+ matcher.compare("1.0", "1_0") == 0
+ matcher.compare("1_0", "1-0") == 0
+ matcher.compare("1-0", "1+0") == 0
+ matcher.compare("1.a.2", "1a2") == 0 // number-word and word-number boundaries are considered separators
+ }
+
+ def "compares unrelated versions unequal"() {
+ expect:
+ matcher.compare("1.0", "") != 0
+ matcher.compare("1.0", "!@#%") != 0
+ matcher.compare("1.0", "hey joe") != 0
+ }
+
+ // original Ivy behavior - should we change it?
+ def "does not compare versions with different number of trailing .0's equal"() {
+ expect:
+ matcher.compare(v1, v2) > 0
+ matcher.compare(v2, v1) < 0
+
+ where:
+ v1 | v2
+ "1.0.0" | "1.0"
+ "1.0.0" | "1"
+ }
+
+ def "does not compare versions with different capitalization equal"() {
+ expect:
+ matcher.compare(v1, v2) > 0
+ matcher.compare(v2, v1) < 0
+
+ where:
+ v1 | v2
+ "1.0-alpha" | "1.0-ALPHA"
+ }
+}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/LatestVersionMatcherTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/LatestVersionMatcherTest.groovy
new file mode 100644
index 0000000..11c530f
--- /dev/null
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/LatestVersionMatcherTest.groovy
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy
+
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ModuleVersionMetaData
+import spock.lang.Specification
+
+class LatestVersionMatcherTest extends Specification {
+ def matcher = new LatestVersionMatcher()
+
+ def "handles selectors starting with 'latest.'"() {
+ expect:
+ matcher.canHandle("latest.integration")
+ matcher.canHandle("latest.foo")
+ matcher.canHandle("latest.123")
+ !matcher.canHandle("1.0")
+ !matcher.canHandle("[1.0,2.0]")
+ }
+
+ def "all handled selectors are dynamic"() {
+ expect:
+ matcher.isDynamic("latest.integration")
+ matcher.isDynamic("latest.foo")
+ matcher.isDynamic("latest.123")
+ }
+
+ def "always needs metadata"() {
+ expect:
+ matcher.needModuleMetadata("latest.integration", "1.0")
+ matcher.needModuleMetadata("latest.foo", "1.0")
+ matcher.needModuleMetadata("latest.123", "1.0")
+ }
+
+ def "only supports metadata-aware accept method"() {
+ when:
+ matcher.accept("latest.integration", "1.0")
+
+ then:
+ UnsupportedOperationException e = thrown()
+ e.message.contains("accept")
+ }
+
+ def "accepts a candidate version iff its status is equal to or higher than the selector's status"() {
+ def metadata = Stub(ModuleVersionMetaData) {
+ getStatus() >> "silver"
+ getStatusScheme() >> ["bronze", "silver", "gold"]
+ }
+
+ expect:
+ matcher.accept("latest.bronze", metadata)
+ matcher.accept("latest.silver", metadata)
+ !matcher.accept("latest.gold", metadata)
+ }
+
+ def "rejects a candidate version if selector's status is not contained in candidate's status scheme"() {
+ def metadata = Stub(ModuleVersionMetaData) {
+ getStatus() >> "silver"
+ getStatusScheme() >> ["bronze", "silver", "gold"]
+ }
+
+ expect:
+ !matcher.accept("latest.other", metadata)
+ }
+
+ def "cannot tell which of version selector and candidate version is greater"() {
+ expect:
+ matcher.compare("latest.integration", "1.0") == 0
+ matcher.compare("latest.release", "2.0") == 0
+ }
+}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/LatestVersionStrategyTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/LatestVersionStrategyTest.groovy
new file mode 100644
index 0000000..36db721
--- /dev/null
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/LatestVersionStrategyTest.groovy
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy
+
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.VersionInfo
+
+import spock.lang.Specification
+
+class LatestVersionStrategyTest extends Specification {
+ def chain = new ChainVersionMatcher()
+ def strategy = new LatestVersionStrategy(chain)
+ def matcher = Mock(VersionMatcher)
+
+ def setup() {
+ chain.add(new SubVersionMatcher(new ExactVersionMatcher()))
+ chain.add(matcher)
+ chain.add(new ExactVersionMatcher())
+ }
+
+ def "compares static versions according to version matcher"() {
+ expect:
+ strategy.compare(new VersionInfo("1.0"), new VersionInfo("2.0")) < 0
+ strategy.compare(new VersionInfo("1.0"), new VersionInfo("1.0")) == 0
+ strategy.compare(new VersionInfo("2.0"), new VersionInfo("1.0")) > 0
+ }
+
+ def "compares dynamic and static version according to version matcher"() {
+ expect:
+ strategy.compare(new VersionInfo("1.+"), new VersionInfo("2.0")) < 0
+ strategy.compare(new VersionInfo("2.0"), new VersionInfo("1.+")) > 0
+ strategy.compare(new VersionInfo("1.+"), new VersionInfo("1.11")) > 0
+ strategy.compare(new VersionInfo("1.11"), new VersionInfo("1.+")) < 0
+ }
+
+ def "considers dynamic version greater if it compares equal according to version matcher"() {
+ matcher.canHandle("foo") >> true
+ matcher.isDynamic("foo") >> true
+ matcher.isDynamic("1.0") >> false
+ matcher.compare(_, _) >> 0
+
+ expect:
+ strategy.compare(new VersionInfo("foo"), new VersionInfo("1.0")) > 0
+ strategy.compare(new VersionInfo("1.0"), new VersionInfo("foo")) < 0
+ }
+
+ def "sorts elements in ascending order according to version matcher"() {
+ def version1 = new VersionInfo("1.0")
+ def version2 = new VersionInfo("1.+")
+ def version3 = new VersionInfo("2.2")
+ def version4 = new VersionInfo("2.+")
+
+ expect:
+ strategy.sort([version3, version1, version2, version4]) == [version1, version2, version3, version4]
+ }
+
+ def "finds latest element according to version matcher"() {
+ def version1 = new VersionInfo("1.0")
+ def version2 = new VersionInfo("1.+")
+ def version3 = new VersionInfo("2.2")
+ def version4 = new VersionInfo("2.+")
+
+ expect:
+ strategy.findLatest([version3, version1, version2, version4]) == version4
+ }
+}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/SubVersionMatcherTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/SubVersionMatcherTest.groovy
new file mode 100644
index 0000000..64c1969
--- /dev/null
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/SubVersionMatcherTest.groovy
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy
+
+import org.gradle.api.artifacts.ModuleVersionIdentifier
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ModuleVersionMetaData
+
+import spock.lang.Specification
+
+class SubVersionMatcherTest extends Specification {
+ def matcher = new SubVersionMatcher(new ExactVersionMatcher())
+
+ def "handles selectors that end in '+'"() {
+ expect:
+ matcher.canHandle("1+")
+ matcher.canHandle("1.2.3+")
+ !matcher.canHandle("1")
+ !matcher.canHandle("1.+.3")
+ }
+
+ def "all handled selectors are dynamic"() {
+ expect:
+ matcher.isDynamic("1+")
+ matcher.isDynamic("1.2.3+")
+ }
+
+ def "never needs metadata"() {
+ expect:
+ !matcher.needModuleMetadata("1+", "1")
+ !matcher.needModuleMetadata("1.2.3+", "1.2.3")
+ }
+
+ def "accepts candidate versions that literally match the selector up until the trailing '+'"() {
+ expect:
+ matcher.accept("1+", "11")
+ matcher.accept("1.+", "1.2")
+ matcher.accept("1.2.3+", "1.2.3.11")
+ !matcher.accept("1+", "2")
+ !matcher.accept("1.+", "11")
+ !matcher.accept("1.2.3+", "1.2")
+ }
+
+ def "metadata-aware accept method delivers same results"() {
+ def metadata = Stub(ModuleVersionMetaData) {
+ getId() >> Stub(ModuleVersionIdentifier) {
+ getVersion() >> metadataVersion
+ }
+ }
+
+ expect:
+ matcher.accept("1.+", metadata) == result
+
+ where:
+ metadataVersion | result
+ "1.5" | true
+ "2.5" | false
+ }
+
+ def "considers a '+' selector greater than any matching candidate version"() {
+ expect:
+ matcher.compare("1+", "11") > 0
+ matcher.compare("1.+", "1.2") > 0
+ matcher.compare("1.2.3+", "1.2.3.11") > 0
+ }
+
+ def "falls back to the provided comparator if selector doesn't match candidate version"() {
+ expect:
+ matcher.compare("1+", "2") < 0
+ matcher.compare("1+", "0.5") > 0
+ }
+}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/VersionRangeMatcherTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/VersionRangeMatcherTest.groovy
new file mode 100644
index 0000000..61bf399
--- /dev/null
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/strategy/VersionRangeMatcherTest.groovy
@@ -0,0 +1,208 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy
+
+import org.gradle.api.artifacts.ModuleVersionIdentifier
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ModuleVersionMetaData
+
+import spock.lang.Specification
+
+public class VersionRangeMatcherTest extends Specification {
+ def matcher = new VersionRangeMatcher(new ExactVersionMatcher())
+
+ def "handles selectors that use valid version range syntax"() {
+ expect:
+ matcher.canHandle("[1.0,2.0]")
+ matcher.canHandle("[1.0,2.0[")
+ matcher.canHandle("]1.0,2.0]")
+ matcher.canHandle("]1.0,2.0[")
+ matcher.canHandle("[1.0,)")
+ matcher.canHandle("]1.0,)")
+ matcher.canHandle("(,2.0]")
+ matcher.canHandle("(,2.0[")
+ }
+
+ def "does not handle selectors that use no or invalid version range syntax"() {
+ expect:
+ !matcher.canHandle("1")
+ !matcher.canHandle("1+")
+ !matcher.canHandle("[1")
+ !matcher.canHandle("[]")
+ !matcher.canHandle("[1,2,3]")
+ }
+
+ def "all handled selectors are dynamic"() {
+ expect:
+ matcher.isDynamic("[1.0,2.0]")
+ matcher.isDynamic("[1.0,)")
+ }
+
+ def "never needs metadata"() {
+ expect:
+ !matcher.needModuleMetadata("[1.0,2.0]", "1.0")
+ !matcher.needModuleMetadata("[1.0,)", "1.0")
+ !matcher.needModuleMetadata("1", "1")
+ }
+
+ def "accepts candidate versions that fall into the selector's range"() {
+ expect:
+ matcher.accept("[1.0,2.0]", "1.0")
+ matcher.accept("[1.0,2.0]", "1.2.3")
+ matcher.accept("[1.0,2.0]", "2.0")
+
+ matcher.accept("[1.0,2.0[", "1.0")
+ matcher.accept("[1.0,2.0[", "1.2.3")
+ matcher.accept("[1.0,2.0[", "1.99")
+
+ matcher.accept("]1.0,2.0]", "1.0.1")
+ matcher.accept("]1.0,2.0]", "1.2.3")
+ matcher.accept("]1.0,2.0]", "2.0")
+
+ matcher.accept("]1.0,2.0[", "1.0.1")
+ matcher.accept("]1.0,2.0[", "1.2.3")
+ matcher.accept("]1.0,2.0[", "1.99")
+
+ matcher.accept("[1.0,)", "1.0")
+ matcher.accept("[1.0,)", "1.2.3")
+ matcher.accept("[1.0,)", "2.3.4")
+
+ matcher.accept("]1.0,)", "1.0.1")
+ matcher.accept("]1.0,)", "1.2.3")
+ matcher.accept("]1.0,)", "2.3.4")
+
+ matcher.accept("(,2.0]", "0")
+ matcher.accept("(,2.0]", "0.1.2")
+ matcher.accept("(,2.0]", "2.0")
+
+ matcher.accept("(,2.0[", "0")
+ matcher.accept("(,2.0[", "0.1.2")
+ matcher.accept("(,2.0[", "1.99")
+ }
+
+ def "accepts candidate versions that fall into the selector's range (adding qualifiers to the mix)"() {
+ expect:
+ matcher.accept("[1.0,2.0]", "1.5-dev-1")
+ matcher.accept("[1.0,2.0]", "1.2.3-rc-2")
+ matcher.accept("[1.0,2.0]", "2.0-final")
+
+ matcher.accept("[1.0-dev-1,2.0[", "1.0")
+ matcher.accept("[1.0,2.0-rc-2[", "2.0-rc-1")
+ matcher.accept("[1.0,2.0[", "2.0-final")
+
+ matcher.accept("]1.0-dev-1,2.0]", "1.0")
+ matcher.accept("]1.0-rc-2,2.0]", "1.0-rc-3")
+
+ matcher.accept("]1.0-dev-1,1.0-dev-3[", "1.0-dev-2")
+ matcher.accept("]1.0-dev-1,1.0-rc-1[", "1.0-dev-99")
+ }
+
+ def "rejects candidate versions that don't fall into the selector's range"() {
+ expect:
+ !matcher.accept("[1.0,2.0]", "0.99")
+ !matcher.accept("[1.0,2.0]", "2.0.1")
+ !matcher.accept("[1.0,2.0]", "42")
+
+ !matcher.accept("[1.0,2.0[", "0.99")
+ !matcher.accept("[1.0,2.0[", "2.0")
+ !matcher.accept("[1.0,2.0[", "42")
+
+ !matcher.accept("]1.0,2.0]", "1.0")
+ !matcher.accept("]1.0,2.0]", "2.0.1")
+ !matcher.accept("]1.0,2.0]", "42")
+
+ !matcher.accept("]1.0,2.0[", "1.0")
+ !matcher.accept("]1.0,2.0[", "2.0")
+ !matcher.accept("]1.0,2.0[", "42")
+
+ !matcher.accept("[1.0,)", "0")
+ !matcher.accept("[1.0,)", "0.99")
+
+ !matcher.accept("]1.0,)", "0")
+ !matcher.accept("]1.0,)", "1")
+ !matcher.accept("]1.0,)", "1.0")
+
+ !matcher.accept("(,2.0]", "2.0.1")
+ !matcher.accept("(,2.0]", "42")
+
+ !matcher.accept("(,2.0[", "2.0")
+ !matcher.accept("(,2.0[", "42")
+ }
+
+ def "rejects candidate versions that don't fall into the selector's range (adding qualifiers to the mix)"() {
+ expect:
+ !matcher.accept("[1.0,2.0]", "2.5-dev-1")
+ !matcher.accept("[1.0,2.0]", "1.0-rc-2")
+ !matcher.accept("[1.0,2.0]", "1.0-final")
+
+ !matcher.accept("[1.0-dev-2,2.0[", "1.0-dev-1")
+ !matcher.accept("[1.0,2.0-rc-2[", "2.0-rc-2")
+ !matcher.accept("[1.0,2.0-final[", "2.0")
+
+ !matcher.accept("]1.0-dev-1,2.0]", "1.0-dev-1")
+ !matcher.accept("]1.0-rc-2,2.0]", "1.0-dev-3")
+
+ !matcher.accept("]1.0-dev-1,1.0-dev-3[", "1.0-dev-3")
+ !matcher.accept("]1.0-dev-1,1.0-rc-1[", "1.0-final-0")
+ }
+
+ def "metadata-aware accept method delivers same results"() {
+ def metadata = Stub(ModuleVersionMetaData) {
+ getId() >> Stub(ModuleVersionIdentifier) {
+ getVersion() >> metadataVersion
+ }
+ }
+
+ expect:
+ matcher.accept("[1.0,2.0]", metadata) == result
+
+ where:
+ metadataVersion | result
+ "1.5" | true
+ "2.5" | false
+ }
+
+ def "compares candidate versions against the selector's upper bound"() {
+ expect:
+ matcher.compare(range, "0.5") > 0
+ matcher.compare(range, "1.0") > 0
+ matcher.compare(range, "1.5") > 0
+ matcher.compare(range, "2.0") < 0 // unsure why [1.0,2.0] isn't considered equal to 2.0 (apparently never returns 0)
+ matcher.compare(range, "2.5") < 0
+
+ where:
+ range | _
+ "[1.0,2.0]" | _
+ "[1.0,2.0[" | _
+ "]1.0,2.0]" | _
+ "]1.0,2.0[" | _
+ "(,2.0]" | _
+ "(,2.0[" | _
+ }
+
+ def "selectors with infinite upper bound compare greater than any candidate version"() {
+ expect:
+ matcher.compare(range, "0.5") > 0
+ matcher.compare(range, "1.0") > 0
+ matcher.compare(range, "1.5") > 0
+ matcher.compare(range, "2.0") > 0
+ matcher.compare(range, "2.5") > 0
+
+ where:
+ range | _
+ "[1.0,)" | _
+ "]1.0,)" | _
+ }
+}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleDescriptorStoreTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleDescriptorStoreTest.groovy
index b5f32cb..aaf4b4f 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleDescriptorStoreTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleDescriptorStoreTest.groovy
@@ -19,11 +19,12 @@ package org.gradle.api.internal.artifacts.ivyservice.modulecache
import org.apache.ivy.core.module.descriptor.ModuleDescriptor
import org.apache.ivy.core.module.id.ModuleRevisionId
import org.gradle.api.artifacts.ModuleVersionIdentifier
+import org.gradle.api.internal.artifacts.ivyservice.DependencyToModuleVersionResolver
import org.gradle.api.internal.artifacts.ivyservice.IvyModuleDescriptorWriter
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ModuleVersionRepository
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.IvyXmlModuleDescriptorParser
-import org.gradle.api.internal.filestore.FileStoreEntry
import org.gradle.api.internal.filestore.PathKeyFileStore
+import org.gradle.internal.resource.local.LocallyAvailableResource
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
import org.junit.Rule
import spock.lang.Specification
@@ -35,11 +36,12 @@ class ModuleDescriptorStoreTest extends Specification {
PathKeyFileStore pathKeyFileStore = Mock()
ModuleRevisionId moduleRevisionId = Mock()
ModuleVersionRepository repository = Mock()
- FileStoreEntry fileStoreEntry = Mock()
+ LocallyAvailableResource fileStoreEntry = Mock()
ModuleDescriptor moduleDescriptor = Mock()
IvyModuleDescriptorWriter ivyModuleDescriptorWriter = Mock()
IvyXmlModuleDescriptorParser ivyXmlModuleDescriptorParser = Mock()
ModuleVersionIdentifier moduleVersionIdentifier = Mock()
+ def resolver = Mock(DependencyToModuleVersionResolver)
def setup() {
store = new ModuleDescriptorStore(pathKeyFileStore, ivyModuleDescriptorWriter, ivyXmlModuleDescriptorParser);
@@ -54,12 +56,12 @@ class ModuleDescriptorStoreTest extends Specification {
when:
pathKeyFileStore.get("module-metadata/org.test/testArtifact/1.0/repositoryId/ivy.xml") >> null
then:
- null == store.getModuleDescriptor(repository, moduleVersionIdentifier)
+ null == store.getModuleDescriptor(repository, moduleVersionIdentifier, resolver)
}
def "getModuleDescriptorFile uses PathKeyFileStore to get file"() {
when:
- store.getModuleDescriptor(repository, moduleVersionIdentifier);
+ store.getModuleDescriptor(repository, moduleVersionIdentifier, resolver);
then:
1 * pathKeyFileStore.get("module-metadata/org.test/testArtifact/1.0/repositoryId/ivy.xml") >> null
}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/DefaultArtifactsToModuleDescriptorConverterTest.java b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/DefaultArtifactsToModuleDescriptorConverterTest.java
index 8e973ca..79b2d02 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/DefaultArtifactsToModuleDescriptorConverterTest.java
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/DefaultArtifactsToModuleDescriptorConverterTest.java
@@ -19,31 +19,29 @@ import org.apache.ivy.core.module.descriptor.Artifact;
import org.apache.ivy.core.module.descriptor.DefaultArtifact;
import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor;
import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
-import org.gradle.api.artifacts.PublishArtifactSet;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.artifacts.PublishArtifact;
-import org.gradle.api.internal.artifacts.ivyservice.DefaultIvyDependencyPublisher;
+import org.gradle.api.artifacts.PublishArtifactSet;
+import org.gradle.api.internal.artifacts.BuildableModuleVersionPublishMetaData;
import org.gradle.api.internal.artifacts.publish.DefaultPublishArtifact;
-import org.gradle.util.HelperUtil;
+import org.gradle.util.TestUtil;
import org.gradle.util.JUnit4GroovyMockery;
import org.gradle.util.WrapUtil;
-import static org.hamcrest.Matchers.equalTo;
import org.jmock.Expectations;
import org.jmock.integration.junit4.JMock;
import org.jmock.integration.junit4.JUnit4Mockery;
-import static org.junit.Assert.assertThat;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.Date;
-import java.util.HashMap;
import java.util.Map;
-/**
- * @author Hans Dockter
- */
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.junit.Assert.assertThat;
+
@RunWith(JMock.class)
public class DefaultArtifactsToModuleDescriptorConverterTest {
private JUnit4Mockery context = new JUnit4GroovyMockery();
@@ -54,53 +52,32 @@ public class DefaultArtifactsToModuleDescriptorConverterTest {
Configuration configurationStub1 = createConfigurationStub(publishArtifactConf1);
final PublishArtifact publishArtifactConf2 = createNamedPublishArtifact("conf2");
Configuration configurationStub2 = createConfigurationStub(publishArtifactConf2);
- final ArtifactsExtraAttributesStrategy artifactsExtraAttributesStrategyMock = context.mock(ArtifactsExtraAttributesStrategy.class);
- final Map<String, String> extraAttributesArtifact1 = WrapUtil.toMap("name", publishArtifactConf1.getName());
- final Map<String, String> extraAttributesArtifact2 = WrapUtil.toMap("name", publishArtifactConf2.getName());
+ final DefaultModuleDescriptor moduleDescriptor = TestUtil.createModuleDescriptor(WrapUtil.toSet(configurationStub1.getName(),
+ configurationStub2.getName()));
+ final BuildableModuleVersionPublishMetaData publishMetaData = context.mock(BuildableModuleVersionPublishMetaData.class);
context.checking(new Expectations() {{
- one(artifactsExtraAttributesStrategyMock).createExtraAttributes(publishArtifactConf1);
- will(returnValue(extraAttributesArtifact1));
- one(artifactsExtraAttributesStrategyMock).createExtraAttributes(publishArtifactConf2);
- will(returnValue(extraAttributesArtifact2));
+ allowing(publishMetaData).getModuleDescriptor();
+ will(returnValue(moduleDescriptor));
+ exactly(2).of(publishMetaData).addArtifact(with(notNullValue(Artifact.class)), with(notNullValue(File.class)));
}});
- DefaultModuleDescriptor moduleDescriptor = HelperUtil.createModuleDescriptor(WrapUtil.toSet(configurationStub1.getName(),
- configurationStub2.getName()));
- DefaultArtifactsToModuleDescriptorConverter artifactsToModuleDescriptorConverter =
- new DefaultArtifactsToModuleDescriptorConverter(artifactsExtraAttributesStrategyMock);
+ DefaultArtifactsToModuleDescriptorConverter artifactsToModuleDescriptorConverter = new DefaultArtifactsToModuleDescriptorConverter();
- artifactsToModuleDescriptorConverter.addArtifacts(moduleDescriptor, WrapUtil.toSet(configurationStub1, configurationStub2));
+ artifactsToModuleDescriptorConverter.addArtifacts(publishMetaData, WrapUtil.toSet(configurationStub1, configurationStub2));
- assertArtifactIsAdded(configurationStub1, moduleDescriptor, extraAttributesArtifact1);
- assertArtifactIsAdded(configurationStub2, moduleDescriptor, extraAttributesArtifact2);
+ assertArtifactIsAdded(configurationStub1, moduleDescriptor);
+ assertArtifactIsAdded(configurationStub2, moduleDescriptor);
assertThat(moduleDescriptor.getAllArtifacts().length, equalTo(2));
}
- @Test
- public void testIvyFileStrategy() {
- assertThat(
- DefaultArtifactsToModuleDescriptorConverter.IVY_FILE_STRATEGY.createExtraAttributes(context.mock(PublishArtifact.class)),
- equalTo((Map) new HashMap<String, String>()));
- }
-
- @Test
- public void testResolveStrategy() {
- PublishArtifact publishArtifact = createNamedPublishArtifact("someName");
- Map<String, String> expectedExtraAttributes = WrapUtil.toMap(DefaultIvyDependencyPublisher.FILE_ABSOLUTE_PATH_EXTRA_ATTRIBUTE, publishArtifact.getFile().getAbsolutePath());
- assertThat(
- DefaultArtifactsToModuleDescriptorConverter.RESOLVE_STRATEGY.createExtraAttributes(publishArtifact),
- equalTo(expectedExtraAttributes));
- }
-
- private void assertArtifactIsAdded(Configuration configuration, DefaultModuleDescriptor moduleDescriptor, Map<String, String> extraAttributes) {
+ private void assertArtifactIsAdded(Configuration configuration, DefaultModuleDescriptor moduleDescriptor) {
assertThat(moduleDescriptor.getArtifacts(configuration.getName()),
- equalTo(WrapUtil.toArray(expectedIvyArtifact(configuration, moduleDescriptor, extraAttributes))));
+ equalTo(WrapUtil.toArray(expectedIvyArtifact(configuration, moduleDescriptor))));
}
- private Artifact expectedIvyArtifact(Configuration configuration, ModuleDescriptor moduleDescriptor, Map<String, String> additionalExtraAttributes) {
+ private Artifact expectedIvyArtifact(Configuration configuration, ModuleDescriptor moduleDescriptor) {
PublishArtifact publishArtifact = configuration.getArtifacts().iterator().next();
Map<String, String> extraAttributes = WrapUtil.toMap(Dependency.CLASSIFIER, publishArtifact.getClassifier());
- extraAttributes.putAll(additionalExtraAttributes);
return new DefaultArtifact(moduleDescriptor.getModuleRevisionId(),
publishArtifact.getDate(),
publishArtifact.getName(),
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/DefaultConfigurationsToModuleDescriptorConverterTest.java b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/DefaultConfigurationsToModuleDescriptorConverterTest.java
index 3b27122..69688de 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/DefaultConfigurationsToModuleDescriptorConverterTest.java
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/DefaultConfigurationsToModuleDescriptorConverterTest.java
@@ -18,21 +18,19 @@ package org.gradle.api.internal.artifacts.ivyservice.moduleconverter;
import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.internal.artifacts.configurations.Configurations;
-import org.gradle.util.HelperUtil;
+import org.gradle.util.TestUtil;
import org.gradle.util.WrapUtil;
-import static org.hamcrest.Matchers.equalTo;
import org.jmock.Expectations;
import org.jmock.integration.junit4.JMock;
import org.jmock.integration.junit4.JUnit4Mockery;
-import static org.junit.Assert.assertThat;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.Collections;
-/**
- * @author Hans Dockter
- */
+import static org.hamcrest.Matchers.equalTo;
+import static org.junit.Assert.assertThat;
+
@RunWith(JMock.class)
public class DefaultConfigurationsToModuleDescriptorConverterTest {
private DefaultConfigurationsToModuleDescriptorConverter configurationsToModuleDescriptorConverter = new DefaultConfigurationsToModuleDescriptorConverter();
@@ -43,7 +41,7 @@ public class DefaultConfigurationsToModuleDescriptorConverterTest {
public void testAddConfigurations() {
Configuration configurationStub1 = createNamesAndExtendedConfigurationStub("conf1");
Configuration configurationStub2 = createNamesAndExtendedConfigurationStub("conf2", configurationStub1);
- final DefaultModuleDescriptor moduleDescriptor = HelperUtil.createModuleDescriptor(Collections.EMPTY_SET);
+ final DefaultModuleDescriptor moduleDescriptor = TestUtil.createModuleDescriptor(Collections.EMPTY_SET);
configurationsToModuleDescriptorConverter.addConfigurations(moduleDescriptor, WrapUtil.toSet(configurationStub1, configurationStub2));
@@ -80,7 +78,7 @@ public class DefaultConfigurationsToModuleDescriptorConverterTest {
will(returnValue(true));
allowing(configurationStub).getDescription();
- will(returnValue(HelperUtil.createUniqueId()));
+ will(returnValue(TestUtil.createUniqueId()));
allowing(configurationStub).isVisible();
will(returnValue(true));
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/DefaultExcludeRuleConverterTest.java b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/DefaultExcludeRuleConverterTest.java
index 6af0160..61df00e 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/DefaultExcludeRuleConverterTest.java
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/DefaultExcludeRuleConverterTest.java
@@ -24,9 +24,6 @@ import org.junit.Test;
import static org.junit.Assert.assertThat;
-/**
- * @author Hans Dockter
- */
public class DefaultExcludeRuleConverterTest {
@Test
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/DefaultModuleDescriptorFactoryTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/DefaultModuleDescriptorFactoryTest.groovy
index 808f5cc..49ec853 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/DefaultModuleDescriptorFactoryTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/DefaultModuleDescriptorFactoryTest.groovy
@@ -13,52 +13,28 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.gradle.api.internal.artifacts.ivyservice.moduleconverter;
+package org.gradle.api.internal.artifacts.ivyservice.moduleconverter
-
-import org.apache.ivy.Ivy
import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor
-import org.apache.ivy.core.module.id.ModuleId
-import org.apache.ivy.core.module.status.StatusManager
-import org.apache.ivy.core.settings.IvySettings
import org.gradle.api.artifacts.Module
import org.gradle.api.internal.artifacts.DefaultModule
-import org.gradle.api.internal.artifacts.ivyservice.IvyFactory
-import org.gradle.api.internal.artifacts.ivyservice.SettingsConverter
import spock.lang.Specification
-/**
- * @author Hans Dockter
- */
public class DefaultModuleDescriptorFactoryTest extends Specification {
- final IvyFactory ivyFactory = Mock()
- final SettingsConverter settingsConverter = Mock()
- final DefaultModuleDescriptorFactory factory = new DefaultModuleDescriptorFactory(ivyFactory, settingsConverter)
+ final DefaultModuleDescriptorFactory factory = new DefaultModuleDescriptorFactory()
public void testCreateModuleDescriptor() {
given:
- IvySettings ivySettings = Mock()
- Ivy ivy = Mock()
- StatusManager statusManager = Mock()
Module module = new DefaultModule("org", "name", "version", "status");
when:
DefaultModuleDescriptor moduleDescriptor = factory.createModuleDescriptor(module);
then:
- 1 * settingsConverter.getForResolve() >> ivySettings
- 1 * ivyFactory.createIvy(ivySettings) >> ivy
- _ * ivy.settings >> ivySettings
- 1 * ivySettings.statusManager >> statusManager
- 1 * statusManager.defaultStatus >> "default status"
- 1 * ivySettings.getDefaultBranch(ModuleId.newInstance("org", "name")) >> "default branch"
- 0 * _._
-
- and:
- moduleDescriptor.moduleRevisionId.organisation == module.group;
- moduleDescriptor.moduleRevisionId.name == module.name;
- moduleDescriptor.moduleRevisionId.revision == module.version;
- moduleDescriptor.status == module.getStatus();
- moduleDescriptor.publicationDate == null;
+ moduleDescriptor.moduleRevisionId.organisation == module.group
+ moduleDescriptor.moduleRevisionId.name == module.name
+ moduleDescriptor.moduleRevisionId.revision == module.version
+ moduleDescriptor.status == module.status
+ moduleDescriptor.publicationDate == null
}
}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/IvyConverterTestUtil.java b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/IvyConverterTestUtil.java
index 9cea636..3a06d68 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/IvyConverterTestUtil.java
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/IvyConverterTestUtil.java
@@ -19,9 +19,6 @@ import org.gradle.api.artifacts.Configuration;
import org.jmock.Expectations;
import org.jmock.Mockery;
-/**
- * @author Hans Dockter
- */
public class IvyConverterTestUtil {
public static Configuration createNamedConfigurationStub(final String name, Mockery context) {
final Configuration configurationStub = context.mock(Configuration.class, name);
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/PublishModuleDescriptorConverterTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/PublishModuleDescriptorConverterTest.groovy
index 1c0e2ff..33cacae 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/PublishModuleDescriptorConverterTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/PublishModuleDescriptorConverterTest.groovy
@@ -14,18 +14,15 @@
* limitations under the License.
*/
-package org.gradle.api.internal.artifacts.ivyservice.moduleconverter;
-
+package org.gradle.api.internal.artifacts.ivyservice.moduleconverter
import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.Module
+import org.gradle.api.internal.artifacts.BuildableModuleVersionPublishMetaData
import org.gradle.api.internal.artifacts.ivyservice.ModuleDescriptorConverter
import spock.lang.Specification
-/**
- * @author Hans Dockter, Szczepan
- */
public class PublishModuleDescriptorConverterTest extends Specification {
def "converts"() {
@@ -33,6 +30,7 @@ public class PublishModuleDescriptorConverterTest extends Specification {
def configurationsDummy = [Mock(Configuration)] as Set
def moduleDummy = Mock(Module)
def moduleDescriptorDummy = Mock(DefaultModuleDescriptor)
+ def publishMetaDataDummy = Mock(BuildableModuleVersionPublishMetaData)
def artifactsToModuleDescriptorConverter = Mock(ArtifactsToModuleDescriptorConverter)
def resolveModuleDescriptorConverter = Mock(ModuleDescriptorConverter)
@@ -40,15 +38,19 @@ public class PublishModuleDescriptorConverterTest extends Specification {
resolveModuleDescriptorConverter,
artifactsToModuleDescriptorConverter);
- resolveModuleDescriptorConverter.convert(configurationsDummy, moduleDummy) >> moduleDescriptorDummy
+ and:
+ publishMetaDataDummy.moduleDescriptor >> moduleDescriptorDummy
+ resolveModuleDescriptorConverter.convert(configurationsDummy, moduleDummy) >> publishMetaDataDummy
when:
- def actualModuleDescriptor = publishModuleDescriptorConverter.convert(configurationsDummy, moduleDummy);
+ def actualMetaData = publishModuleDescriptorConverter.convert(configurationsDummy, moduleDummy);
then:
1 * moduleDescriptorDummy.addExtraAttributeNamespace(PublishModuleDescriptorConverter.IVY_MAVEN_NAMESPACE_PREFIX,
PublishModuleDescriptorConverter.IVY_MAVEN_NAMESPACE);
- 1 * artifactsToModuleDescriptorConverter.addArtifacts(moduleDescriptorDummy, configurationsDummy)
- actualModuleDescriptor == moduleDescriptorDummy
+ 1 * artifactsToModuleDescriptorConverter.addArtifacts(publishMetaDataDummy, configurationsDummy)
+
+ and:
+ actualMetaData == publishMetaDataDummy
}
}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/ResolveModuleDescriptorConverterTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/ResolveModuleDescriptorConverterTest.groovy
index b28e9a1..31664ff 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/ResolveModuleDescriptorConverterTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/ResolveModuleDescriptorConverterTest.groovy
@@ -14,19 +14,16 @@
* limitations under the License.
*/
-package org.gradle.api.internal.artifacts.ivyservice.moduleconverter;
-
+package org.gradle.api.internal.artifacts.ivyservice.moduleconverter
import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor
+import org.apache.ivy.core.module.id.ModuleRevisionId
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.Module
+import org.gradle.api.internal.artifacts.DefaultModuleVersionPublishMetaData
import org.gradle.api.internal.artifacts.ivyservice.moduleconverter.dependencies.DependenciesToModuleDescriptorConverter
-import org.gradle.api.internal.artifacts.ivyservice.moduleconverter.dependencies.DependencyDescriptorFactory
import spock.lang.Specification
-/**
- * @author Hans Dockter, Szczepan
- */
public class ResolveModuleDescriptorConverterTest extends Specification {
def "converts"() {
@@ -35,25 +32,27 @@ public class ResolveModuleDescriptorConverterTest extends Specification {
def module = Mock(Module)
def moduleDescriptor = Mock(DefaultModuleDescriptor)
def moduleDescriptorFactory = Mock(ModuleDescriptorFactory)
- def dependencyDescriptorFactory = Mock(DependencyDescriptorFactory)
def configurationsConverter = Mock(ConfigurationsToModuleDescriptorConverter)
def dependenciesConverter = Mock(DependenciesToModuleDescriptorConverter)
ResolveModuleDescriptorConverter resolveModuleDescriptorConverter = new ResolveModuleDescriptorConverter(
moduleDescriptorFactory,
- dependencyDescriptorFactory,
configurationsConverter,
dependenciesConverter);
- moduleDescriptorFactory.createModuleDescriptor(module) >> moduleDescriptor
+ and:
+ moduleDescriptor.moduleRevisionId >> ModuleRevisionId.newInstance("group", "module", "version")
when:
def actualDescriptor = resolveModuleDescriptorConverter.convert(configurations, module);
then:
+ 1 * moduleDescriptorFactory.createModuleDescriptor(module) >> moduleDescriptor
1 * configurationsConverter.addConfigurations(moduleDescriptor, configurations)
1 * dependenciesConverter.addDependencyDescriptors(moduleDescriptor, configurations)
- actualDescriptor == moduleDescriptor
+ and:
+ actualDescriptor instanceof DefaultModuleVersionPublishMetaData
+ actualDescriptor.moduleDescriptor == moduleDescriptor
}
}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/AbstractDependencyDescriptorFactoryInternalTest.java b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/AbstractDependencyDescriptorFactoryInternalTest.java
index 3d70134..2651112 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/AbstractDependencyDescriptorFactoryInternalTest.java
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/AbstractDependencyDescriptorFactoryInternalTest.java
@@ -30,7 +30,7 @@ import org.gradle.api.artifacts.ExcludeRule;
import org.gradle.api.artifacts.ModuleDependency;
import org.gradle.api.internal.artifacts.dependencies.DefaultDependencyArtifact;
import org.gradle.api.internal.artifacts.ivyservice.moduleconverter.ExcludeRuleConverter;
-import org.gradle.util.HelperUtil;
+import org.gradle.util.TestUtil;
import org.gradle.util.WrapUtil;
import org.jmock.Expectations;
import org.jmock.integration.junit4.JMock;
@@ -47,9 +47,6 @@ import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
-/**
- * @author Hans Dockter
- */
@RunWith(JMock.class)
public abstract class AbstractDependencyDescriptorFactoryInternalTest {
private JUnit4Mockery context = new JUnit4Mockery();
@@ -60,7 +57,7 @@ public abstract class AbstractDependencyDescriptorFactoryInternalTest {
protected static final ExcludeRule TEST_EXCLUDE_RULE = new org.gradle.api.internal.artifacts.DefaultExcludeRule("testOrg", null);
protected static final org.apache.ivy.core.module.descriptor.ExcludeRule TEST_IVY_EXCLUDE_RULE = getTestExcludeRule();
protected ExcludeRuleConverter excludeRuleConverterStub = context.mock(ExcludeRuleConverter.class);
- protected final DefaultModuleDescriptor moduleDescriptor = HelperUtil.createModuleDescriptor(WrapUtil.toSet(TEST_CONF));
+ protected final DefaultModuleDescriptor moduleDescriptor = TestUtil.createModuleDescriptor(WrapUtil.toSet(TEST_CONF));
private DefaultDependencyArtifact artifact = new DefaultDependencyArtifact("name", "type", null, null, null);
private DefaultDependencyArtifact artifactWithClassifiers = new DefaultDependencyArtifact("name2", "type2", "ext2", "classifier2", "http://www.url2.com");
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/ClientModuleDependencyDescriptorFactoryTest.java b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/ClientModuleDependencyDescriptorFactoryTest.java
index 6f21ece..158cace 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/ClientModuleDependencyDescriptorFactoryTest.java
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/ClientModuleDependencyDescriptorFactoryTest.java
@@ -32,9 +32,6 @@ import org.junit.Test;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.*;
-/**
- * @author Hans Dockter
- */
public class ClientModuleDependencyDescriptorFactoryTest extends AbstractDependencyDescriptorFactoryInternalTest {
private JUnit4Mockery context = new JUnit4Mockery();
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/DefaultDependenciesToModuleDescriptorConverterTest.java b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/DefaultDependenciesToModuleDescriptorConverterTest.java
index 12f2ca1..1ac36a0 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/DefaultDependenciesToModuleDescriptorConverterTest.java
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/DefaultDependenciesToModuleDescriptorConverterTest.java
@@ -24,7 +24,7 @@ import org.gradle.api.internal.artifacts.DefaultExcludeRule;
import org.gradle.api.internal.artifacts.dependencies.DefaultExternalModuleDependency;
import org.gradle.api.internal.artifacts.ivyservice.moduleconverter.ExcludeRuleConverter;
import org.gradle.api.internal.artifacts.ivyservice.moduleconverter.IvyConverterTestUtil;
-import org.gradle.util.HelperUtil;
+import org.gradle.util.TestUtil;
import org.gradle.util.JUnit4GroovyMockery;
import org.gradle.util.WrapUtil;
import org.jmock.Expectations;
@@ -40,9 +40,6 @@ import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.sameInstance;
import static org.junit.Assert.assertThat;
-/**
- * @author Hans Dockter
- */
@RunWith(JMock.class)
public class DefaultDependenciesToModuleDescriptorConverterTest {
private JUnit4Mockery context = new JUnit4GroovyMockery();
@@ -68,7 +65,7 @@ public class DefaultDependenciesToModuleDescriptorConverterTest {
Configuration configurationStub1 = createNamedConfigurationStubWithDependenciesAndExcludeRules("conf1", GRADLE_EXCLUDE_RULE_DUMMY_1, dependencyDummy1, similarDependency1);
Configuration configurationStub2 = createNamedConfigurationStubWithDependenciesAndExcludeRules("conf2", GRADLE_EXCLUDE_RULE_DUMMY_2, dependencyDummy2, similarDependency2);
Configuration configurationStub3 = createNamedConfigurationStubWithDependenciesAndExcludeRules("conf3", null, similarDependency3);
- final DefaultModuleDescriptor moduleDescriptor = HelperUtil.createModuleDescriptor(toSet(configurationStub1.getName(),
+ final DefaultModuleDescriptor moduleDescriptor = TestUtil.createModuleDescriptor(toSet(configurationStub1.getName(),
configurationStub2.getName()));
associateDependencyWithDescriptor(dependencyDummy1, moduleDescriptor, configurationStub1);
associateDependencyWithDescriptor(dependencyDummy2, moduleDescriptor, configurationStub2);
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/DefaultModuleDescriptorFactoryForClientModuleTest.java b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/DefaultModuleDescriptorFactoryForClientModuleTest.java
index bfa2b1c..330109d 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/DefaultModuleDescriptorFactoryForClientModuleTest.java
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/DefaultModuleDescriptorFactoryForClientModuleTest.java
@@ -28,9 +28,6 @@ import org.junit.Test;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
-/**
- * @author Hans Dockter
- */
public class DefaultModuleDescriptorFactoryForClientModuleTest {
private JUnit4Mockery context = new JUnit4Mockery();
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/ExternalModuleDependencyDescriptorFactoryTest.java b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/ExternalModuleDependencyDescriptorFactoryTest.java
index 1b58c4c..7cd5814 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/ExternalModuleDependencyDescriptorFactoryTest.java
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/ExternalModuleDependencyDescriptorFactoryTest.java
@@ -30,9 +30,6 @@ import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
-/**
- * @author Hans Dockter
- */
public class ExternalModuleDependencyDescriptorFactoryTest extends AbstractDependencyDescriptorFactoryInternalTest {
private JUnit4Mockery context = new JUnit4Mockery();
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/ProjectDependencyDescriptorFactoryTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/ProjectDependencyDescriptorFactoryTest.groovy
new file mode 100644
index 0000000..067651c
--- /dev/null
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/ProjectDependencyDescriptorFactoryTest.groovy
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.moduleconverter.dependencies;
+
+
+import org.apache.ivy.core.module.id.ModuleRevisionId
+import org.gradle.api.artifacts.ExternalModuleDependency
+import org.gradle.api.artifacts.ProjectDependency
+import org.gradle.api.internal.artifacts.dependencies.DefaultProjectDependency
+import org.gradle.api.internal.project.AbstractProject
+import org.gradle.initialization.ProjectAccessListener
+import org.gradle.util.TestUtil
+import org.jmock.integration.junit4.JUnit4Mockery
+import org.junit.Test
+
+import static org.hamcrest.Matchers.equalTo
+import static org.junit.Assert.*
+
+//TODO SF spockify
+public class ProjectDependencyDescriptorFactoryTest extends AbstractDependencyDescriptorFactoryInternalTest {
+ private JUnit4Mockery context = new JUnit4Mockery();
+
+ private ProjectIvyDependencyDescriptorFactory projectDependencyDescriptorFactory =
+ new ProjectIvyDependencyDescriptorFactory(excludeRuleConverterStub);
+
+ @Test
+ public void canConvert() {
+ assertThat(projectDependencyDescriptorFactory.canConvert(context.mock(ProjectDependency.class)), equalTo(true));
+ assertThat(projectDependencyDescriptorFactory.canConvert(context.mock(ExternalModuleDependency.class)), equalTo(false));
+ }
+
+ @Test
+ public void testCreateFromProjectDependency() {
+ ProjectDependency projectDependency = createProjectDependency(TEST_DEP_CONF);
+ setUpDependency(projectDependency);
+ ProjectDependencyDescriptor dependencyDescriptor = (ProjectDependencyDescriptor) projectDependencyDescriptorFactory.createDependencyDescriptor(TEST_CONF, projectDependency, moduleDescriptor);
+
+ assertDependencyDescriptorHasCommonFixtureValues(dependencyDescriptor);
+ assertFalse(dependencyDescriptor.isChanging());
+ assertFalse(dependencyDescriptor.isForce());
+ assertEquals(ModuleRevisionId.newInstance("someGroup", "test", "someVersion"), dependencyDescriptor.getDependencyRevisionId());
+ assertSame(projectDependency.getDependencyProject(), dependencyDescriptor.getTargetProject());
+ }
+
+ private ProjectDependency createProjectDependency(String dependencyConfiguration) {
+ AbstractProject dependencyProject = TestUtil.createRootProject();
+ dependencyProject.setGroup("someGroup");
+ dependencyProject.setVersion("someVersion");
+ return new DefaultProjectDependency(dependencyProject, dependencyConfiguration, {} as ProjectAccessListener, true);
+ }
+}
\ No newline at end of file
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/ProjectDependencyDescriptorFactoryTest.java b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/ProjectDependencyDescriptorFactoryTest.java
deleted file mode 100644
index e5b7fb9..0000000
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/ProjectDependencyDescriptorFactoryTest.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.artifacts.ivyservice.moduleconverter.dependencies;
-
-import org.apache.ivy.core.module.id.ModuleRevisionId;
-import org.gradle.api.artifacts.ExternalModuleDependency;
-import org.gradle.api.artifacts.ProjectDependency;
-import org.gradle.api.internal.artifacts.dependencies.DefaultProjectDependency;
-import org.gradle.api.internal.project.AbstractProject;
-import org.gradle.util.HelperUtil;
-import org.jmock.integration.junit4.JUnit4Mockery;
-import org.junit.Test;
-
-import static org.hamcrest.Matchers.equalTo;
-import static org.junit.Assert.*;
-
-/**
- * @author Hans Dockter
- */
-//TODO SF spockify
-public class ProjectDependencyDescriptorFactoryTest extends AbstractDependencyDescriptorFactoryInternalTest {
- private JUnit4Mockery context = new JUnit4Mockery();
-
- private ProjectIvyDependencyDescriptorFactory projectDependencyDescriptorFactory =
- new ProjectIvyDependencyDescriptorFactory(excludeRuleConverterStub);
-
- @Test
- public void canConvert() {
- assertThat(projectDependencyDescriptorFactory.canConvert(context.mock(ProjectDependency.class)), equalTo(true));
- assertThat(projectDependencyDescriptorFactory.canConvert(context.mock(ExternalModuleDependency.class)), equalTo(false));
- }
-
- @Test
- public void testCreateFromProjectDependency() {
- ProjectDependency projectDependency = createProjectDependency(TEST_DEP_CONF);
- setUpDependency(projectDependency);
- ProjectDependencyDescriptor dependencyDescriptor = (ProjectDependencyDescriptor) projectDependencyDescriptorFactory.createDependencyDescriptor(TEST_CONF, projectDependency, moduleDescriptor);
-
- assertDependencyDescriptorHasCommonFixtureValues(dependencyDescriptor);
- assertFalse(dependencyDescriptor.isChanging());
- assertFalse(dependencyDescriptor.isForce());
- assertEquals(ModuleRevisionId.newInstance("someGroup", "test", "someVersion"), dependencyDescriptor.getDependencyRevisionId());
- assertSame(projectDependency.getDependencyProject(), dependencyDescriptor.getTargetProject());
- }
-
- private ProjectDependency createProjectDependency(String dependencyConfiguration) {
- AbstractProject dependencyProject = HelperUtil.createRootProject();
- dependencyProject.setGroup("someGroup");
- dependencyProject.setVersion("someVersion");
- return new DefaultProjectDependency(dependencyProject, dependencyConfiguration, null, true);
- }
-}
\ No newline at end of file
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/ReflectiveDependencyDescriptorFactoryTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/ReflectiveDependencyDescriptorFactoryTest.groovy
index 9b92d9b..294e868 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/ReflectiveDependencyDescriptorFactoryTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/moduleconverter/dependencies/ReflectiveDependencyDescriptorFactoryTest.groovy
@@ -16,13 +16,10 @@
package org.gradle.api.internal.artifacts.ivyservice.moduleconverter.dependencies
+import org.apache.ivy.core.module.descriptor.*
import org.apache.ivy.core.module.id.ModuleRevisionId
import spock.lang.Specification
-import org.apache.ivy.core.module.descriptor.*
-/**
- * by Szczepan Faber, created at: 1/29/13
- */
class ReflectiveDependencyDescriptorFactoryTest extends Specification {
def factory = new ReflectiveDependencyDescriptorFactory()
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/projectmodule/ProjectDependencyResolverTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/projectmodule/ProjectDependencyResolverTest.groovy
index 30d2d65..32a3db8 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/projectmodule/ProjectDependencyResolverTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/projectmodule/ProjectDependencyResolverTest.groovy
@@ -17,32 +17,32 @@ package org.gradle.api.internal.artifacts.ivyservice.projectmodule
import org.apache.ivy.core.module.descriptor.DependencyDescriptor
import org.apache.ivy.core.module.descriptor.ModuleDescriptor
-import org.apache.ivy.core.module.id.ModuleRevisionId
import org.gradle.api.artifacts.ModuleVersionIdentifier
+import org.gradle.api.internal.artifacts.ModuleVersionPublishMetaData
import org.gradle.api.internal.artifacts.ivyservice.BuildableModuleVersionResolveResult
-import org.gradle.api.internal.artifacts.ivyservice.DependencyToModuleResolver
+import org.gradle.api.internal.artifacts.ivyservice.DependencyToModuleVersionResolver
+import org.gradle.api.internal.artifacts.ivyservice.ModuleDescriptorConverter
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.DependencyMetaData
import org.gradle.api.internal.artifacts.ivyservice.moduleconverter.dependencies.ProjectDependencyDescriptor
import org.gradle.api.internal.project.ProjectInternal
-import org.gradle.initialization.ProjectAccessListener
import spock.lang.Specification
class ProjectDependencyResolverTest extends Specification {
final ProjectModuleRegistry registry = Mock()
- final ModuleRevisionId moduleRevisionId = Mock()
- final DependencyToModuleResolver target = Mock()
- final ProjectAccessListener projectAccessListener = Mock()
- final ProjectDependencyResolver resolver = new ProjectDependencyResolver(registry, target, projectAccessListener)
+ final DependencyToModuleVersionResolver target = Mock()
+ final ModuleDescriptorConverter converter = Mock()
+ final ProjectDependencyResolver resolver = new ProjectDependencyResolver(registry, target, converter)
def "resolves project dependency"() {
setup:
- 1 * moduleRevisionId.organisation >> "group"
- 1 * moduleRevisionId.name >> "project"
- 1 * moduleRevisionId.revision >> "1.0"
-
- def moduleDescriptor = Mock(ModuleDescriptor)
+ def ModuleVersionIdentifier moduleId = Stub(ModuleVersionIdentifier)
+ def moduleDescriptor = Stub(ModuleDescriptor)
+ def publishMetaData = Stub(ModuleVersionPublishMetaData) {
+ getId() >> moduleId
+ getModuleDescriptor() >> moduleDescriptor
+ }
def result = Mock(BuildableModuleVersionResolveResult)
- def dependencyProject = Mock(ProjectInternal)
+ def dependencyProject = Stub(ProjectInternal)
def dependencyDescriptor = Stub(ProjectDependencyDescriptor) {
getTargetProject() >> dependencyProject
}
@@ -54,21 +54,14 @@ class ProjectDependencyResolverTest extends Specification {
resolver.resolve(dependencyMetaData, result)
then:
- 1 * registry.findProject(dependencyDescriptor) >> moduleDescriptor
- _ * moduleDescriptor.moduleRevisionId >> moduleRevisionId
- 1 * result.resolved(_, moduleDescriptor, _) >> { args ->
- ModuleVersionIdentifier moduleVersionIdentifier = args[0]
- moduleVersionIdentifier.group == "group"
- moduleVersionIdentifier.name == "project"
- moduleVersionIdentifier.version == "1.0"
- }
- 1 * projectAccessListener.beforeResolvingProjectDependency(dependencyProject)
+ 1 * registry.findProject(dependencyDescriptor) >> publishMetaData
+ 1 * result.resolved(moduleId, moduleDescriptor, _)
0 * result._
}
def "delegates to backing resolver for non-project dependency"() {
def result = Mock(BuildableModuleVersionResolveResult)
- def dependencyDescriptor = Mock(DependencyDescriptor)
+ def dependencyDescriptor = Stub(DependencyDescriptor)
def dependencyMetaData = Stub(DependencyMetaData) {
getDescriptor() >> dependencyDescriptor
}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolutionstrategy/DefaultResolutionStrategySpec.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolutionstrategy/DefaultResolutionStrategySpec.groovy
index 0d8a100..577f4eb 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolutionstrategy/DefaultResolutionStrategySpec.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolutionstrategy/DefaultResolutionStrategySpec.groovy
@@ -27,9 +27,6 @@ import java.util.concurrent.TimeUnit
import static org.gradle.api.internal.artifacts.DefaultModuleVersionSelector.newSelector
import static org.gradle.util.Assertions.assertThat
-/**
- * by Szczepan Faber, created at: 11/2/11
- */
public class DefaultResolutionStrategySpec extends Specification {
def cachePolicy = Mock(DefaultCachePolicy)
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolutionstrategy/ModuleForcingResolveRuleSpec.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolutionstrategy/ModuleForcingResolveRuleSpec.groovy
index 29b75eb..e806a87 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolutionstrategy/ModuleForcingResolveRuleSpec.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolutionstrategy/ModuleForcingResolveRuleSpec.groovy
@@ -22,9 +22,6 @@ import spock.lang.Specification
import static org.gradle.api.internal.artifacts.DefaultModuleVersionSelector.newSelector
-/**
- * by Szczepan Faber, created at: 11/29/12
- */
class ModuleForcingResolveRuleSpec extends Specification {
def "forces modules"() {
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/DependencyGraphBuilderTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/DependencyGraphBuilderTest.groovy
index 48e159f..b66937f 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/DependencyGraphBuilderTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/DependencyGraphBuilderTest.groovy
@@ -19,46 +19,42 @@ import org.apache.ivy.core.module.descriptor.*
import org.apache.ivy.core.module.id.ArtifactId
import org.apache.ivy.core.module.id.ModuleId
import org.apache.ivy.core.module.id.ModuleRevisionId
-import org.apache.ivy.core.resolve.ResolveData
-import org.apache.ivy.core.resolve.ResolveEngine
-import org.apache.ivy.core.resolve.ResolveOptions
import org.apache.ivy.plugins.matcher.ExactPatternMatcher
import org.apache.ivy.plugins.matcher.PatternMatcher
import org.gradle.api.artifacts.*
import org.gradle.api.internal.artifacts.DefaultModuleVersionSelector
-import org.gradle.api.internal.artifacts.DefaultResolvedArtifact
import org.gradle.api.internal.artifacts.configurations.ConfigurationInternal
import org.gradle.api.internal.artifacts.ivyservice.*
-import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.DefaultBuildableModuleVersionMetaData
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.DefaultBuildableModuleVersionMetaDataResolveResult
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ModuleVersionMetaData
import org.gradle.api.internal.artifacts.ivyservice.moduleconverter.dependencies.EnhancedDependencyDescriptor
+import org.gradle.api.internal.artifacts.ivyservice.resolveengine.oldresult.DefaultResolvedConfigurationBuilder
+import org.gradle.api.internal.artifacts.ivyservice.resolveengine.oldresult.TransientResultsStore
+import org.gradle.api.internal.artifacts.ivyservice.resolveengine.result.DummyBinaryStore
+import org.gradle.api.internal.artifacts.ivyservice.resolveengine.result.DummyStore
import org.gradle.api.internal.artifacts.ivyservice.resolveengine.result.ResolvedConfigurationListener
+import org.gradle.api.internal.artifacts.ivyservice.resolveengine.result.VersionSelectionReasons
import org.gradle.api.specs.Spec
import spock.lang.Specification
import static org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier.newId
import static org.gradle.api.internal.artifacts.DefaultModuleVersionSelector.newSelector
-import org.gradle.api.internal.artifacts.ivyservice.resolveengine.result.VersionSelectionReasons
class DependencyGraphBuilderTest extends Specification {
- final ModuleDescriptorConverter moduleDescriptorConverter = Mock()
- final ResolvedArtifactFactory resolvedArtifactFactory = Mock()
final ConfigurationInternal configuration = Mock()
- final ResolveEngine resolveEngine = Mock()
- final ResolveData resolveData = new ResolveData(resolveEngine, new ResolveOptions())
final ModuleConflictResolver conflictResolver = Mock()
final DependencyToModuleVersionIdResolver dependencyResolver = Mock()
final ResolvedConfigurationListener listener = Mock()
final ModuleVersionMetaData root = revision('root')
- final DependencyGraphBuilder builder = new DependencyGraphBuilder(moduleDescriptorConverter, resolvedArtifactFactory, dependencyResolver, conflictResolver)
+ final ModuleToModuleVersionResolver moduleResolver = Mock()
+ final DependencyToConfigurationResolver dependencyToConfigurationResolver = new DefaultDependencyToConfigurationResolver()
+ final DependencyGraphBuilder builder = new DependencyGraphBuilder(dependencyResolver, moduleResolver, conflictResolver, dependencyToConfigurationResolver)
def setup() {
config(root, 'root', 'default')
_ * configuration.name >> 'root'
- _ * moduleDescriptorConverter.convert(_, _) >> root.descriptor
- _ * resolvedArtifactFactory.create(_, _, _) >> { owner, artifact, resolver ->
- return new DefaultResolvedArtifact(owner, artifact, null)
- }
+ _ * configuration.path >> 'root'
+ _ * moduleResolver.resolve(_, _, _) >> { it[2].resolved(root, Mock(ArtifactResolver)) }
}
def "does not resolve a given module selector more than once"() {
@@ -72,13 +68,20 @@ class DependencyGraphBuilderTest extends Specification {
doesNotResolve b, c
when:
- def result = builder.resolve(configuration, resolveData, listener)
+ def result = resolve()
result.rethrowFailure()
then:
modules(result) == ids(a, b, c)
}
+ private DefaultLenientConfiguration resolve() {
+ def results = new DefaultResolvedConfigurationBuilder(Stub(ResolvedArtifactFactory),
+ new TransientResultsStore(new DummyBinaryStore(), new DummyStore()))
+ builder.resolve(configuration, listener, results)
+ new DefaultLenientConfiguration(configuration, results, Stub(CacheLockingManager))
+ }
+
def "correctly notifies the resolved configuration listener"() {
given:
def a = revision("a")
@@ -91,7 +94,7 @@ class DependencyGraphBuilderTest extends Specification {
traversesMissing a, d
when:
- builder.resolve(configuration, resolveData, listener)
+ resolve()
then:
1 * listener.start(newId("group", "root", "1.0"))
@@ -115,7 +118,7 @@ class DependencyGraphBuilderTest extends Specification {
doesNotResolve c, d
when:
- def result = builder.resolve(configuration, resolveData, listener)
+ def result = resolve()
result.rethrowFailure()
then:
@@ -138,13 +141,14 @@ class DependencyGraphBuilderTest extends Specification {
doesNotResolve evicted, e
when:
- def result = builder.resolve(configuration, resolveData, listener)
+ def result = resolve()
result.rethrowFailure()
then:
- 1 * conflictResolver.select(!null, !null) >> { Collection<ModuleRevisionResolveState> candidates, ModuleRevisionResolveState root ->
- assert candidates*.revision == ['1.2', '1.1']
- return candidates.find { it.revision == '1.2' }
+ 1 * conflictResolver.select(!null) >> {
+ Collection<ModuleRevisionResolveState> candidates = it[0]
+ assert candidates*.version == ['1.2', '1.1']
+ return candidates.find { it.version == '1.2' }
}
0 * conflictResolver._
@@ -168,13 +172,14 @@ class DependencyGraphBuilderTest extends Specification {
traverses selected, e
when:
- def result = builder.resolve(configuration, resolveData, listener)
+ def result = resolve()
result.rethrowFailure()
then:
- 1 * conflictResolver.select(!null, !null) >> { Collection<ModuleRevisionResolveState> candidates, ModuleRevisionResolveState root ->
- assert candidates*.revision == ['1.1', '1.2']
- return candidates.find { it.revision == '1.2' }
+ 1 * conflictResolver.select(!null) >> {
+ Collection<ModuleRevisionResolveState> candidates = it[0]
+ assert candidates*.version == ['1.1', '1.2']
+ return candidates.find { it.version == '1.2' }
}
0 * conflictResolver._
@@ -198,13 +203,14 @@ class DependencyGraphBuilderTest extends Specification {
traverses selected, e
when:
- def result = builder.resolve(configuration, resolveData, listener)
+ def result = resolve()
result.rethrowFailure()
then:
- 1 * conflictResolver.select(!null, !null) >> { Collection<ModuleRevisionResolveState> candidates, ModuleRevisionResolveState root ->
- assert candidates*.revision == ['1.1', '1.2']
- return candidates.find { it.revision == '1.2' }
+ 1 * conflictResolver.select(!null) >> {
+ Collection<ModuleRevisionResolveState> candidates = it[0]
+ assert candidates*.version == ['1.1', '1.2']
+ return candidates.find { it.version == '1.2' }
}
0 * conflictResolver._
@@ -224,13 +230,14 @@ class DependencyGraphBuilderTest extends Specification {
doesNotResolve evicted, c
when:
- def result = builder.resolve(configuration, resolveData, listener)
+ def result = resolve()
result.rethrowFailure()
then:
- 1 * conflictResolver.select(!null, !null) >> { Collection<ModuleRevisionResolveState> candidates, ModuleRevisionResolveState root ->
- assert candidates*.revision == ['1.2', '1.1']
- return candidates.find { it.revision == '1.2' }
+ 1 * conflictResolver.select(!null) >> {
+ Collection<ModuleRevisionResolveState> candidates = it[0]
+ assert candidates*.version == ['1.2', '1.1']
+ return candidates.find { it.version == '1.2' }
}
0 * conflictResolver._
@@ -253,13 +260,14 @@ class DependencyGraphBuilderTest extends Specification {
doesNotResolve b, evicted
when:
- def result = builder.resolve(configuration, resolveData, listener)
+ def result = resolve()
result.rethrowFailure()
then:
- 1 * conflictResolver.select(!null, !null) >> { Collection<ModuleRevisionResolveState> candidates, ModuleRevisionResolveState root ->
- assert candidates*.revision == ['1.1', '1.2']
- return candidates.find { it.revision == '1.2' }
+ 1 * conflictResolver.select(!null) >> {
+ Collection<ModuleRevisionResolveState> candidates = it[0]
+ assert candidates*.version == ['1.1', '1.2']
+ return candidates.find { it.version == '1.2' }
}
0 * conflictResolver._
@@ -283,18 +291,21 @@ class DependencyGraphBuilderTest extends Specification {
doesNotResolve selectedB, evictedA2
when:
- def result = builder.resolve(configuration, resolveData, listener)
+ def result = resolve()
result.rethrowFailure()
then:
- 1 * conflictResolver.select({ it*.revision == ['1.1', '1.2'] }, !null) >> { Collection<ModuleRevisionResolveState> candidates, ModuleRevisionResolveState root ->
- return candidates.find { it.revision == '1.2' }
+ 1 * conflictResolver.select({ it*.version == ['1.1', '1.2'] }) >> {
+ Collection<ModuleRevisionResolveState> candidates = it[0]
+ return candidates.find { it.version == '1.2' }
}
- 1 * conflictResolver.select({ it*.revision == ['2.1', '2.2'] }, !null) >> { Collection<ModuleRevisionResolveState> candidates, ModuleRevisionResolveState root ->
- return candidates.find { it.revision == '2.2' }
+ 1 * conflictResolver.select({ it*.version == ['2.1', '2.2'] }) >> {
+ Collection<ModuleRevisionResolveState> candidates = it[0]
+ return candidates.find { it.version == '2.2' }
}
- 1 * conflictResolver.select({ it*.revision == ['1.1', '1.2', '1.0'] }, !null) >> { Collection<ModuleRevisionResolveState> candidates, ModuleRevisionResolveState root ->
- return candidates.find { it.revision == '1.2' }
+ 1 * conflictResolver.select({ it*.version == ['1.1', '1.2', '1.0'] }) >> {
+ Collection<ModuleRevisionResolveState> candidates = it[0]
+ return candidates.find { it.version == '1.2' }
}
0 * conflictResolver._
@@ -319,12 +330,13 @@ class DependencyGraphBuilderTest extends Specification {
traverses e, selected // conflict is deeper than 'b', to ensure 'b' has been visited
when:
- def result = builder.resolve(configuration, resolveData, listener)
+ def result = resolve()
result.rethrowFailure()
then:
- 1 * conflictResolver.select({ it*.revision == ['1', '2'] }, !null) >> { Collection<ModuleRevisionResolveState> candidates, ModuleRevisionResolveState root ->
- return candidates.find { it.revision == '2' }
+ 1 * conflictResolver.select({ it*.version == ['1', '2'] }) >> {
+ Collection<ModuleRevisionResolveState> candidates = it[0]
+ return candidates.find { it.version == '2' }
}
0 * conflictResolver._
@@ -349,12 +361,13 @@ class DependencyGraphBuilderTest extends Specification {
traverses e, selected // conflict is deeper than 'b', to ensure 'b' has been visited
when:
- def result = builder.resolve(configuration, resolveData, listener)
+ def result = resolve()
result.rethrowFailure()
then:
- 1 * conflictResolver.select({ it*.revision == ['1', '2'] }, !null) >> { Collection<ModuleRevisionResolveState> candidates, ModuleRevisionResolveState root ->
- return candidates.find { it.revision == '2' }
+ 1 * conflictResolver.select({ it*.version == ['1', '2'] }) >> {
+ Collection<ModuleRevisionResolveState> candidates = it[0]
+ return candidates.find { it.version == '2' }
}
0 * conflictResolver._
@@ -372,7 +385,7 @@ class DependencyGraphBuilderTest extends Specification {
doesNotResolve b, c
when:
- def result = builder.resolve(configuration, resolveData, listener)
+ def result = resolve()
result.rethrowFailure()
then:
@@ -387,12 +400,13 @@ class DependencyGraphBuilderTest extends Specification {
doesNotResolve root, evicted
when:
- def result = builder.resolve(configuration, resolveData, listener)
+ def result = resolve()
result.rethrowFailure()
then:
- 1 * conflictResolver.select(!null, !null) >> { Collection<ModuleRevisionResolveState> candidates, ModuleRevisionResolveState root ->
- return candidates.find { it.revision == '1.2' }
+ 1 * conflictResolver.select(!null) >> {
+ Collection<ModuleRevisionResolveState> candidates = it[0]
+ return candidates.find { it.version == '1.2' }
}
and:
@@ -412,7 +426,7 @@ class DependencyGraphBuilderTest extends Specification {
doesNotResolve d, c
when:
- def result = builder.resolve(configuration, resolveData, listener)
+ def result = resolve()
result.rethrowFailure()
then:
@@ -433,7 +447,7 @@ class DependencyGraphBuilderTest extends Specification {
traverses d, c
when:
- def result = builder.resolve(configuration, resolveData, listener)
+ def result = resolve()
result.rethrowFailure()
then:
@@ -452,7 +466,7 @@ class DependencyGraphBuilderTest extends Specification {
doesNotResolve c, a
when:
- def result = builder.resolve(configuration, resolveData, listener)
+ def result = resolve()
result.rethrowFailure()
then:
@@ -475,7 +489,7 @@ class DependencyGraphBuilderTest extends Specification {
doesNotResolve d, e
when:
- def result = builder.resolve(configuration, resolveData, listener)
+ def result = resolve()
result.rethrowFailure()
then:
@@ -494,7 +508,7 @@ class DependencyGraphBuilderTest extends Specification {
traverses a, b
when:
- def result = builder.resolve(configuration, resolveData, listener)
+ def result = resolve()
result.rethrowFailure()
then:
@@ -512,7 +526,7 @@ class DependencyGraphBuilderTest extends Specification {
doesNotResolve b, c
when:
- def result = builder.resolve(configuration, resolveData, listener)
+ def result = resolve()
result.rethrowFailure()
then:
@@ -532,7 +546,7 @@ class DependencyGraphBuilderTest extends Specification {
doesNotResolve b, c
when:
- def result = builder.resolve(configuration, resolveData, listener)
+ def result = resolve()
then:
result.unresolvedModuleDependencies.size() == 1
@@ -562,7 +576,7 @@ class DependencyGraphBuilderTest extends Specification {
brokenSelector a, 'unknown'
when:
- def result = builder.resolve(configuration, resolveData, listener)
+ def result = resolve()
then:
result.unresolvedModuleDependencies.size() == 1
@@ -591,7 +605,7 @@ class DependencyGraphBuilderTest extends Specification {
doesNotResolve b, c
when:
- def result = builder.resolve(configuration, resolveData, listener)
+ def result = resolve()
then:
result.unresolvedModuleDependencies.size() == 1
@@ -621,7 +635,7 @@ class DependencyGraphBuilderTest extends Specification {
doesNotResolve b, c
when:
- def result = builder.resolve(configuration, resolveData, listener)
+ def result = resolve()
then:
result.unresolvedModuleDependencies.size() == 1
@@ -651,7 +665,7 @@ class DependencyGraphBuilderTest extends Specification {
doesNotResolve b, c
when:
- def result = builder.resolve(configuration, resolveData, listener)
+ def result = resolve()
then:
result.unresolvedModuleDependencies.size() == 1
@@ -680,7 +694,7 @@ class DependencyGraphBuilderTest extends Specification {
traversesMissing b, c
when:
- def result = builder.resolve(configuration, resolveData, listener)
+ def result = resolve()
then:
result.unresolvedModuleDependencies.size() == 1
@@ -714,11 +728,12 @@ class DependencyGraphBuilderTest extends Specification {
doesNotResolve selected, c
when:
- def result = builder.resolve(configuration, resolveData, listener)
+ def result = resolve()
then:
- 1 * conflictResolver.select(!null, !null) >> { Collection<ModuleRevisionResolveState> candidates, ModuleRevisionResolveState root ->
- return candidates.find { it.revision == '1.2' }
+ 1 * conflictResolver.select(!null) >> {
+ Collection<ModuleRevisionResolveState> candidates = it[0]
+ return candidates.find { it.version == '1.2' }
}
when:
@@ -744,18 +759,19 @@ class DependencyGraphBuilderTest extends Specification {
traversesMissing b, selected
when:
- def result = builder.resolve(configuration, resolveData, listener)
+ def result = resolve()
result.rethrowFailure()
then:
- 1 * conflictResolver.select(!null, !null) >> { Collection<ModuleRevisionResolveState> candidates, ModuleRevisionResolveState root ->
- return candidates.find { it.revision == '1.2' }
+ 1 * conflictResolver.select(!null) >> {
+ Collection<ModuleRevisionResolveState> candidates = it[0]
+ return candidates.find { it.version == '1.2' }
}
and:
ResolveException e = thrown()
e.cause instanceof ModuleVersionNotFoundException
- e.cause.message.contains("group:root:1.0 > group:b:1.0")
+ e.cause.message.contains("group:root:1.0")
}
def "does not fail when conflict resolution evicts a version that does not exist"() {
@@ -768,12 +784,13 @@ class DependencyGraphBuilderTest extends Specification {
traverses b, selected
when:
- def result = builder.resolve(configuration, resolveData, listener)
+ def result = resolve()
result.rethrowFailure()
then:
- 1 * conflictResolver.select(!null, !null) >> { Collection<ModuleRevisionResolveState> candidates, ModuleRevisionResolveState root ->
- return candidates.find { it.revision == '1.2' }
+ 1 * conflictResolver.select(!null) >> {
+ Collection<ModuleRevisionResolveState> candidates = it[0]
+ return candidates.find { it.version == '1.2' }
}
and:
@@ -792,12 +809,13 @@ class DependencyGraphBuilderTest extends Specification {
traverses c, selected
when:
- def result = builder.resolve(configuration, resolveData, listener)
+ def result = resolve()
result.rethrowFailure()
then:
- 1 * conflictResolver.select(!null, !null) >> { Collection<ModuleRevisionResolveState> candidates, ModuleRevisionResolveState root ->
- return candidates.find { it.revision == '1.2' }
+ 1 * conflictResolver.select(!null) >> {
+ Collection<ModuleRevisionResolveState> candidates = it[0]
+ return candidates.find { it.version == '1.2' }
}
and:
@@ -814,7 +832,7 @@ class DependencyGraphBuilderTest extends Specification {
doesNotResolve b, evicted
when:
- def result = builder.resolve(configuration, resolveData, listener)
+ def result = resolve()
result.rethrowFailure()
then:
@@ -823,7 +841,7 @@ class DependencyGraphBuilderTest extends Specification {
def revision(String name, String revision = '1.0') {
DefaultModuleDescriptor descriptor = new DefaultModuleDescriptor(new ModuleRevisionId(new ModuleId("group", name), revision), "release", new Date())
- DefaultBuildableModuleVersionMetaData metaData = new DefaultBuildableModuleVersionMetaData()
+ DefaultBuildableModuleVersionMetaDataResolveResult metaData = new DefaultBuildableModuleVersionMetaDataResolveResult()
metaData.resolved(descriptor, false, null)
config(metaData, 'default')
descriptor.addArtifact('default', new DefaultArtifact(descriptor.moduleRevisionId, new Date(), "art1", "art", "zip"))
@@ -841,15 +859,15 @@ class DependencyGraphBuilderTest extends Specification {
def idResolveResult = selectorResolvesTo(descriptor, to.id);
ModuleVersionResolveResult resolveResult = Mock()
1 * idResolveResult.resolve() >> resolveResult
- 1 * resolveResult.id >> to.id
- 1 * resolveResult.metaData >> to
+ _ * resolveResult.id >> to.id
+ _ * resolveResult.metaData >> to
}
def doesNotResolve(Map<String, ?> args = [:], ModuleVersionMetaData from, ModuleVersionMetaData to) {
def descriptor = dependsOn(args, from.descriptor, to.descriptor.moduleRevisionId)
ModuleVersionIdResolveResult result = Mock()
(0..1) * dependencyResolver.resolve({it.descriptor == descriptor}) >> result
- (0..1) * result.id >> to.id;
+ _ * result.id >> to.id;
_ * result.failure >> null
_ * result.selectionReason >> null
0 * result._
@@ -860,7 +878,7 @@ class DependencyGraphBuilderTest extends Specification {
def idResolveResult = selectorResolvesTo(descriptor, to.id)
ModuleVersionResolveResult resolveResult = Mock()
1 * idResolveResult.resolve() >> resolveResult
- 1 * resolveResult.id >> { throw new ModuleVersionNotFoundException(newId("org", "a", "1.2")) }
+ _ * resolveResult.failure >> { return new ModuleVersionNotFoundException(newId("org", "a", "1.2")) }
}
def traversesBroken(Map<String, ?> args = [:], ModuleVersionMetaData from, ModuleVersionMetaData to) {
@@ -868,7 +886,7 @@ class DependencyGraphBuilderTest extends Specification {
def idResolveResult = selectorResolvesTo(descriptor, to.id)
ModuleVersionResolveResult resolveResult = Mock()
1 * idResolveResult.resolve() >> resolveResult
- 1 * resolveResult.id >> { throw new ModuleVersionResolveException(newSelector("a", "b", "c"), "broken") }
+ _ * resolveResult.failure >> { return new ModuleVersionResolveException(newSelector("a", "b", "c"), "broken") }
}
ModuleVersionIdentifier toModuleVersionIdentifier(ModuleRevisionId moduleRevisionId) {
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/VersionSelectionReasonResolverTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/VersionSelectionReasonResolverTest.groovy
index 062c409..ff4ada1 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/VersionSelectionReasonResolverTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/VersionSelectionReasonResolverTest.groovy
@@ -16,30 +16,26 @@
package org.gradle.api.internal.artifacts.ivyservice.resolveengine
-import spock.lang.Specification
import org.gradle.api.internal.artifacts.ivyservice.resolveengine.result.VersionSelectionReasons
+import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 1/29/13
- */
class VersionSelectionReasonResolverTest extends Specification {
def "configures selection reason"() {
def delegate = Mock(ModuleConflictResolver)
VersionSelectionReasonResolver resolver = new VersionSelectionReasonResolver(delegate)
- def root = Mock(ModuleRevisionResolveState)
def candidate1 = Mock(ModuleRevisionResolveState)
def candidate2 = Mock(ModuleRevisionResolveState)
when:
- def out = resolver.select([candidate1, candidate2], root)
+ def out = resolver.select([candidate1, candidate2])
then:
out == candidate2
and:
- 1 * delegate.select([candidate1, candidate2], root) >> candidate2
+ 1 * delegate.select([candidate1, candidate2]) >> candidate2
1 * candidate2.getSelectionReason() >> VersionSelectionReasons.REQUESTED
1 * candidate2.setSelectionReason(VersionSelectionReasons.CONFLICT_RESOLUTION)
0 * _._
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/CachingDependencyResultFactoryTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/CachingDependencyResultFactoryTest.groovy
index 1c1521c..428da60 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/CachingDependencyResultFactoryTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/CachingDependencyResultFactoryTest.groovy
@@ -16,16 +16,13 @@
package org.gradle.api.internal.artifacts.ivyservice.resolveengine.result
+import org.gradle.api.artifacts.result.ModuleVersionSelectionReason
+import org.gradle.api.internal.artifacts.ivyservice.ModuleVersionResolveException
import spock.lang.Specification
import static org.gradle.api.internal.artifacts.DefaultModuleVersionSelector.newSelector
import static org.gradle.api.internal.artifacts.result.ResolutionResultDataBuilder.newModule
-import org.gradle.api.internal.artifacts.ivyservice.ModuleVersionResolveException
-import org.gradle.api.artifacts.result.ModuleVersionSelectionReason
-/**
- * by Szczepan Faber, created at: 10/1/12
- */
class CachingDependencyResultFactoryTest extends Specification {
CachingDependencyResultFactory factory = new CachingDependencyResultFactory()
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/DummyBinaryStore.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/DummyBinaryStore.groovy
new file mode 100644
index 0000000..b20b89a
--- /dev/null
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/DummyBinaryStore.groovy
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.resolveengine.result
+
+import org.gradle.api.internal.cache.BinaryStore
+
+public class DummyBinaryStore implements BinaryStore {
+
+ private final ByteArrayOutputStream bytes = new ByteArrayOutputStream()
+ private DataOutputStream output = new DataOutputStream(bytes)
+
+ void write(BinaryStore.WriteAction write) {
+ write.write(output)
+ }
+
+ String diagnose() {
+ "dummy in-memory binary store"
+ }
+
+ BinaryStore.BinaryData done() {
+ new BinaryStore.BinaryData() {
+ DataInputStream input
+ def <T> T read(BinaryStore.ReadAction<T> readAction) {
+ if (input == null) {
+ input = new DataInputStream(new ByteArrayInputStream(bytes.toByteArray()))
+ }
+ readAction.read(input)
+ }
+
+ void done() {
+ input = null
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/DummyStore.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/DummyStore.groovy
new file mode 100644
index 0000000..03ee7aa
--- /dev/null
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/DummyStore.groovy
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.resolveengine.result
+
+import org.gradle.api.internal.cache.Store
+
+class DummyStore implements Store<Object> {
+ Object load(org.gradle.internal.Factory<Object> createIfNotPresent) {
+ return createIfNotPresent.create();
+ }
+}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/InternalDependencyResultSerializerTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/InternalDependencyResultSerializerTest.groovy
new file mode 100644
index 0000000..afa114d
--- /dev/null
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/InternalDependencyResultSerializerTest.groovy
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.resolveengine.result
+
+import org.gradle.api.artifacts.ModuleVersionSelector
+import org.gradle.api.internal.artifacts.ivyservice.ModuleVersionResolveException
+import org.gradle.messaging.serialize.InputStreamBackedDecoder
+import org.gradle.messaging.serialize.OutputStreamBackedEncoder
+import spock.lang.Specification
+
+import static org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier.newId
+import static org.gradle.api.internal.artifacts.DefaultModuleVersionSelector.newSelector
+
+class InternalDependencyResultSerializerTest extends Specification {
+
+ def serializer = new InternalDependencyResultSerializer()
+
+ def "serializes successful dependency result"() {
+ def successful = Mock(InternalDependencyResult) {
+ getRequested() >> newSelector("org", "foo", "1.0")
+ getFailure() >> null
+ getSelected() >> new DefaultModuleVersionSelection(newId("org", "foo", "1.0"), VersionSelectionReasons.REQUESTED)
+ getReason() >> VersionSelectionReasons.REQUESTED
+ }
+
+ when:
+ def bytes = new ByteArrayOutputStream()
+ def encoder = new OutputStreamBackedEncoder(bytes)
+ serializer.write(encoder, successful)
+ encoder.flush()
+ def out = serializer.read(new InputStreamBackedDecoder(new ByteArrayInputStream(bytes.toByteArray())), [:])
+
+ then:
+ out.requested == newSelector("org", "foo", "1.0")
+ out.failure == null
+ out.selected.selectedId == newId("org", "foo", "1.0")
+ out.selected.selectionReason == VersionSelectionReasons.REQUESTED
+ }
+
+ def "serializes failed dependency result"() {
+ ModuleVersionSelector requested = newSelector("x", "y", "1.0")
+ def failure = new ModuleVersionResolveException(newSelector("x", "y", "1.2"), new RuntimeException("Boo!"))
+
+ def failed = Mock(InternalDependencyResult) {
+ getRequested() >> requested
+ getFailure() >> failure
+ getSelected() >> null
+ getReason() >> VersionSelectionReasons.CONFLICT_RESOLUTION
+ }
+
+ when:
+ def bytes = new ByteArrayOutputStream()
+ def encoder = new OutputStreamBackedEncoder(bytes)
+ serializer.write(encoder, failed)
+ encoder.flush()
+ Map<ModuleVersionSelector, ModuleVersionResolveException> map = new HashMap<>()
+ map.put(requested, failure)
+ def out = serializer.read(new InputStreamBackedDecoder(new ByteArrayInputStream(bytes.toByteArray())), map)
+
+ then:
+ out.requested == newSelector("x", "y", "1.0")
+ out.failure.cause.message == "Boo!"
+ out.selected == null
+ out.reason == VersionSelectionReasons.CONFLICT_RESOLUTION
+ }
+}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/ModuleVersionSelectionReasonSerializerTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/ModuleVersionSelectionReasonSerializerTest.groovy
new file mode 100644
index 0000000..e05047b
--- /dev/null
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/ModuleVersionSelectionReasonSerializerTest.groovy
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.resolveengine.result
+
+import org.gradle.api.artifacts.result.ModuleVersionSelectionReason
+import org.gradle.messaging.serialize.InputStreamBackedDecoder
+import org.gradle.messaging.serialize.SerializerSpec
+
+class ModuleVersionSelectionReasonSerializerTest extends SerializerSpec {
+
+ private serializer = new ModuleVersionSelectionReasonSerializer()
+
+ def "serializes"() {
+ expect:
+ check(VersionSelectionReasons.CONFLICT_RESOLUTION)
+ check(VersionSelectionReasons.CONFLICT_RESOLUTION_BY_RULE)
+ check(VersionSelectionReasons.FORCED)
+ check(VersionSelectionReasons.REQUESTED)
+ check(VersionSelectionReasons.ROOT)
+ check(VersionSelectionReasons.SELECTED_BY_RULE)
+ }
+
+ def "yields informative message on incorrect input"() {
+ when:
+ check({} as ModuleVersionSelectionReason)
+ then:
+ thrown(IllegalArgumentException)
+
+ when:
+ serializer.read(new InputStreamBackedDecoder(new ByteArrayInputStream("foo".bytes)))
+
+ then:
+ thrown(IllegalArgumentException)
+ }
+
+ void check(ModuleVersionSelectionReason reason) {
+ def result = serialize(reason, serializer)
+ assert result == reason
+ }
+}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/ModuleVersionSelectionSerializerTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/ModuleVersionSelectionSerializerTest.groovy
new file mode 100644
index 0000000..fe56683
--- /dev/null
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/ModuleVersionSelectionSerializerTest.groovy
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.resolveengine.result
+
+import org.gradle.messaging.serialize.SerializerSpec
+
+import static org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier.newId
+
+class ModuleVersionSelectionSerializerTest extends SerializerSpec {
+
+ def serializer = new ModuleVersionSelectionSerializer()
+
+ def "serializes"() {
+ def selection = new DefaultModuleVersionSelection(newId("org", "foo", "2.0"), VersionSelectionReasons.REQUESTED)
+
+ when:
+ def result = serialize(selection, serializer)
+
+ then:
+ result.selectionReason == VersionSelectionReasons.REQUESTED
+ result.selectedId == newId("org", "foo", "2.0")
+ }
+}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/ResolutionResultBuilderSpec.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/ResolutionResultBuilderSpec.groovy
index 68749dd..2d7341c 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/ResolutionResultBuilderSpec.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/ResolutionResultBuilderSpec.groovy
@@ -18,16 +18,14 @@ package org.gradle.api.internal.artifacts.ivyservice.resolveengine.result
import org.gradle.api.artifacts.ModuleVersionIdentifier
import org.gradle.api.artifacts.ModuleVersionSelector
-import spock.lang.Specification
import org.gradle.api.artifacts.result.*
+import org.gradle.api.internal.artifacts.ivyservice.ModuleVersionResolveException
+import spock.lang.Specification
import static org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier.newId
import static org.gradle.api.internal.artifacts.DefaultModuleVersionSelector.newSelector
-import org.gradle.api.internal.artifacts.ivyservice.ModuleVersionResolveException
+import static org.gradle.api.internal.artifacts.ivyservice.resolveengine.result.ResolutionResultPrinter.printGraph
-/**
- * by Szczepan Faber, created at: 8/27/12
- */
class ResolutionResultBuilderSpec extends Specification {
def builder = new ResolutionResultBuilder()
@@ -46,10 +44,10 @@ class ResolutionResultBuilderSpec extends Specification {
resolvedConf("leaf4", [])
when:
- def result = builder.getResult()
+ def result = builder.complete()
then:
- print(result.root) == """x:root:1
+ printGraph(result.root) == """x:root:1
x:mid1:1 [root]
x:leaf1:1 [mid1]
x:leaf2:1 [mid1]
@@ -69,10 +67,10 @@ class ResolutionResultBuilderSpec extends Specification {
resolvedConf("b3", [])
when:
- def result = builder.getResult()
+ def result = builder.complete()
then:
- print(result.root) == """x:a:1
+ printGraph(result.root) == """x:a:1
x:b1:1 [a]
x:b2:1 [a,b1]
x:b3:1 [a,b1,b2]
@@ -90,10 +88,10 @@ class ResolutionResultBuilderSpec extends Specification {
resolvedConf("c", [dep("a")])
when:
- def result = builder.getResult()
+ def result = builder.complete()
then:
- print(result.root) == """x:a:1
+ printGraph(result.root) == """x:a:1
x:b:1 [a]
x:c:1 [b]
x:a:1 [c]
@@ -109,7 +107,7 @@ class ResolutionResultBuilderSpec extends Specification {
resolvedConf("d", [])
when:
- def deps = builder.result.root.dependencies
+ def deps = builder.complete().root.dependencies
then:
def b = deps.find { it.selected.id.name == 'b' }
@@ -127,7 +125,7 @@ class ResolutionResultBuilderSpec extends Specification {
resolvedConf("c", [dep("a")])
when:
- def a = builder.getResult().root
+ def a = builder.complete().root
then:
def b = first(a.dependencies).selected
@@ -162,10 +160,10 @@ class ResolutionResultBuilderSpec extends Specification {
resolvedConf("leaf2", [])
when:
- def result = builder.getResult()
+ def result = builder.complete()
then:
- print(result.root) == """x:root:1
+ printGraph(result.root) == """x:root:1
x:mid1:1 [root]
x:leaf1:1 [mid1]
x:leaf2:1 [mid1]
@@ -182,7 +180,7 @@ class ResolutionResultBuilderSpec extends Specification {
resolvedConf("mid1", [dep("leaf2", new RuntimeException("baz!"))])
when:
- def result = builder.getResult()
+ def result = builder.complete()
then:
def mid1 = first(result.root.dependencies)
@@ -198,10 +196,10 @@ class ResolutionResultBuilderSpec extends Specification {
resolvedConf("c", [])
when:
- def result = builder.getResult()
+ def result = builder.complete()
then:
- print(result.root) == """x:a:1
+ printGraph(result.root) == """x:a:1
x:b:1 [a]
x:c:1 [a]
x:U:1 -> x:U:1 - Could not resolve x:U:1.
@@ -230,30 +228,6 @@ class ResolutionResultBuilderSpec extends Specification {
newId("x", module, "1")
}
- String print(ResolvedModuleVersionResult root) {
- StringBuilder sb = new StringBuilder();
- sb.append(root).append("\n");
- for (DependencyResult d : root.getDependencies()) {
- print(d, sb, new HashSet(), " ");
- }
-
- sb.toString();
- }
-
- void print(DependencyResult dep, StringBuilder sb, Set visited, String indent) {
- if (dep instanceof UnresolvedDependencyResult) {
- sb.append(indent + dep + "\n");
- return
- }
- if (!visited.add(dep.getSelected())) {
- return
- }
- sb.append(indent + dep + " [" + dep.selected.dependents*.from.id.name.join(",") + "]\n");
- for (ResolvedDependencyResult d : dep.getSelected().getDependencies()) {
- print(d, sb, visited, " " + indent);
- }
- }
-
class DummyModuleVersionSelection implements ModuleVersionSelection {
ModuleVersionIdentifier selectedId
ModuleVersionSelectionReason selectionReason
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/ResolutionResultPrinter.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/ResolutionResultPrinter.groovy
new file mode 100644
index 0000000..f59c6d7
--- /dev/null
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/ResolutionResultPrinter.groovy
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.resolveengine.result
+
+import org.gradle.api.artifacts.result.DependencyResult
+import org.gradle.api.artifacts.result.ResolvedModuleVersionResult
+import org.gradle.api.artifacts.result.UnresolvedDependencyResult;
+
+public class ResolutionResultPrinter {
+ private static void printNode(DependencyResult dep, StringBuilder sb, Set visited, String indent) {
+ if (dep instanceof UnresolvedDependencyResult) {
+ sb.append(indent + dep + "\n");
+ return
+ }
+ if (!visited.add(dep.getSelected())) {
+ return
+ }
+ String reason = dep.selected.selectionReason.conflictResolution? "(C)" : "";
+ sb.append(indent + dep + reason + " [" + dep.selected.dependents*.from.id.name.join(",") + "]\n");
+ for (DependencyResult d : dep.getSelected().getDependencies()) {
+ printNode(d, sb, visited, " " + indent);
+ }
+ }
+
+ static String printGraph(ResolvedModuleVersionResult root) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(root).append("\n");
+ for (DependencyResult d : root.getDependencies()) {
+ printNode(d, sb, new HashSet(), " ");
+ }
+
+ sb.toString();
+ }
+}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/StreamingResolutionResultBuilderTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/StreamingResolutionResultBuilderTest.groovy
new file mode 100644
index 0000000..c1eec1b
--- /dev/null
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/StreamingResolutionResultBuilderTest.groovy
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.resolveengine.result
+
+import org.gradle.api.artifacts.result.ModuleVersionSelectionReason
+import org.gradle.api.internal.artifacts.ivyservice.ModuleVersionResolveException
+import spock.lang.Specification
+
+import static org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier.newId
+import static org.gradle.api.internal.artifacts.DefaultModuleVersionSelector.newSelector
+import static org.gradle.api.internal.artifacts.ivyservice.resolveengine.result.ResolutionResultPrinter.printGraph
+import static org.gradle.api.internal.artifacts.ivyservice.resolveengine.result.VersionSelectionReasons.CONFLICT_RESOLUTION
+import static org.gradle.api.internal.artifacts.ivyservice.resolveengine.result.VersionSelectionReasons.REQUESTED
+
+class StreamingResolutionResultBuilderTest extends Specification {
+
+ StreamingResolutionResultBuilder builder = new StreamingResolutionResultBuilder(new DummyBinaryStore(), new DummyStore())
+
+ def "result can be read multiple times"() {
+ builder.start(newId("org", "root", "1.0"))
+
+ when:
+ def result = builder.complete()
+
+ then:
+ with(result) {
+ root.id == newId("org", "root", "1.0")
+ root.selectionReason == VersionSelectionReasons.ROOT
+ }
+ printGraph(result.root) == """org:root:1.0
+"""
+ }
+
+ def "maintains graph in byte stream"() {
+ builder.start(newId("org", "root", "1.0"))
+
+ builder.resolvedModuleVersion(sel("org", "dep1", "2.0", CONFLICT_RESOLUTION))
+ builder.resolvedConfiguration(newId("org", "root", "1.0"), [
+ new DefaultInternalDependencyResult(newSelector("org", "dep1", "2.0"), sel("org", "dep1", "2.0", CONFLICT_RESOLUTION), CONFLICT_RESOLUTION, null),
+ new DefaultInternalDependencyResult(newSelector("org", "dep2", "3.0"), null, CONFLICT_RESOLUTION, new ModuleVersionResolveException(newSelector("org", "dep2", "3.0"), new RuntimeException("Boo!")))
+ ])
+
+ when:
+ def result = builder.complete()
+
+ then:
+ printGraph(result.root) == """org:root:1.0
+ org:dep1:2.0(C) [root]
+ org:dep2:3.0 -> org:dep2:3.0 - Could not resolve org:dep2:3.0.
+"""
+ }
+
+ def "visiting resolved module version again has no effect"() {
+ builder.start(newId("org", "root", "1.0"))
+ builder.resolvedModuleVersion(sel("org", "root", "1.0", REQUESTED)) //it's fine
+
+ builder.resolvedModuleVersion(sel("org", "dep1", "2.0", CONFLICT_RESOLUTION))
+ builder.resolvedModuleVersion(sel("org", "dep1", "2.0", REQUESTED)) //will be ignored
+
+ builder.resolvedConfiguration(newId("org", "root", "1.0"),
+ [new DefaultInternalDependencyResult(newSelector("org", "dep1", "2.0"), sel("org", "dep1", "2.0", CONFLICT_RESOLUTION), CONFLICT_RESOLUTION, null)])
+
+ when:
+ def result = builder.complete()
+
+ then:
+ printGraph(result.root) == """org:root:1.0
+ org:dep1:2.0(C) [root]
+"""
+ }
+
+ def "visiting resolved configuration again accumulates dependencies"() {
+ builder.start(newId("org", "root", "1.0"))
+
+ builder.resolvedModuleVersion(sel("org", "dep1", "2.0", REQUESTED))
+ builder.resolvedModuleVersion(sel("org", "dep2", "2.0", REQUESTED))
+
+ builder.resolvedConfiguration(newId("org", "root", "1.0"), [
+ new DefaultInternalDependencyResult(newSelector("org", "dep1", "2.0"), sel("org", "dep1", "2.0", REQUESTED), REQUESTED, null),
+ ])
+ builder.resolvedConfiguration(newId("org", "root", "1.0"), [
+ new DefaultInternalDependencyResult(newSelector("org", "dep2", "2.0"), sel("org", "dep2", "2.0", REQUESTED), REQUESTED, null),
+ ])
+
+ when:
+ def result = builder.complete()
+
+ then:
+ printGraph(result.root) == """org:root:1.0
+ org:dep1:2.0 [root]
+ org:dep2:2.0 [root]
+"""
+ }
+
+ def "dependency failures are remembered"() {
+ builder.start(newId("org", "root", "1.0"))
+
+ builder.resolvedModuleVersion(sel("org", "dep1", "2.0", REQUESTED))
+ builder.resolvedModuleVersion(sel("org", "dep2", "2.0", REQUESTED))
+
+ builder.resolvedConfiguration(newId("org", "root", "1.0"), [
+ new DefaultInternalDependencyResult(newSelector("org", "dep1", "2.0"), null, REQUESTED, new ModuleVersionResolveException(newSelector("org", "dep1", "1.0"), new RuntimeException())),
+ new DefaultInternalDependencyResult(newSelector("org", "dep2", "2.0"), sel("org", "dep2", "2.0", REQUESTED), REQUESTED, null),
+ ])
+ builder.resolvedConfiguration(newId("org", "dep2", "2.0"), [
+ new DefaultInternalDependencyResult(newSelector("org", "dep1", "5.0"), null, REQUESTED, new ModuleVersionResolveException(newSelector("org", "dep1", "5.0"), new RuntimeException())),
+ ])
+
+ when:
+ def result = builder.complete()
+
+ then:
+ printGraph(result.root) == """org:root:1.0
+ org:dep1:2.0 -> org:dep1:1.0 - Could not resolve org:dep1:1.0.
+ org:dep2:2.0 [root]
+ org:dep1:5.0 -> org:dep1:5.0 - Could not resolve org:dep1:5.0.
+"""
+ }
+
+ private DefaultModuleVersionSelection sel(String org, String name, String ver, ModuleVersionSelectionReason reason) {
+ new DefaultModuleVersionSelection(newId(org, name, ver), reason)
+ }
+}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/VersionSelectionReasonsTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/VersionSelectionReasonsTest.groovy
index 1584706..164491e 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/VersionSelectionReasonsTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/VersionSelectionReasonsTest.groovy
@@ -20,9 +20,6 @@ import spock.lang.Specification
import static org.gradle.api.internal.artifacts.ivyservice.resolveengine.result.VersionSelectionReasons.*
-/**
- * by Szczepan Faber, created at: 1/29/13
- */
class VersionSelectionReasonsTest extends Specification {
def "decorates with conflict resolution"() {
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/store/CachedStoreFactoryTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/store/CachedStoreFactoryTest.groovy
new file mode 100644
index 0000000..6bf7e78
--- /dev/null
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/store/CachedStoreFactoryTest.groovy
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.resolveengine.store
+
+import org.gradle.internal.Factory
+import spock.lang.Specification
+
+class CachedStoreFactoryTest extends Specification {
+
+ def "stores results"() {
+ def factory = new CachedStoreFactory("some cache")
+
+ def results1 = new Object()
+ def results2 = new Object()
+
+ def store1 = factory.createCachedStore("conf1")
+ def store1b = factory.createCachedStore("conf1")
+ def store2 = factory.createCachedStore("conf2")
+
+ expect:
+ store1.load({results1} as Factory) == results1
+ store1.load({assert false} as Factory) == results1
+ store1b.load({assert false} as Factory) == results1
+ store2.load({results2} as Factory) == results2
+ }
+}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/store/DefaultBinaryStoreTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/store/DefaultBinaryStoreTest.groovy
new file mode 100644
index 0000000..a00bbd4
--- /dev/null
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/store/DefaultBinaryStoreTest.groovy
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.resolveengine.store
+
+import org.gradle.api.internal.cache.BinaryStore
+import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
+import org.junit.Rule
+import spock.lang.Specification
+
+class DefaultBinaryStoreTest extends Specification {
+
+ @Rule TestNameTestDirectoryProvider temp = new TestNameTestDirectoryProvider()
+
+ def "stores binary data"() {
+ def store = new DefaultBinaryStore(temp.file("foo.bin"))
+
+ when:
+ store.write({ it.writeInt(10) } as BinaryStore.WriteAction)
+ store.write({ it.writeUTF("x") } as BinaryStore.WriteAction)
+ def data1 = store.done()
+ store.write({ it.writeUTF("y") } as BinaryStore.WriteAction)
+ def data2 = store.done()
+
+ then:
+ data1.read({ it.readInt() } as BinaryStore.ReadAction) == 10
+ data1.read({ it.readUTF() } as BinaryStore.ReadAction) == "x"
+ data1.done()
+
+ data2.read({ it.readUTF() } as BinaryStore.ReadAction) == "y"
+ data2.done()
+
+ cleanup:
+ store.close()
+ }
+
+ def "data can be re-read"() {
+ def store = new DefaultBinaryStore(temp.file("foo.bin"))
+
+ when:
+ store.write({ it.writeInt(10) } as BinaryStore.WriteAction)
+ store.write({ it.writeUTF("x") } as BinaryStore.WriteAction)
+ def data = store.done()
+
+ then:
+ data.read({ it.readInt() } as BinaryStore.ReadAction) == 10
+ data.read({ it.readUTF() } as BinaryStore.ReadAction) == "x"
+ data.done()
+
+ then:
+ data.read({ it.readInt() } as BinaryStore.ReadAction) == 10
+ data.read({ it.readUTF() } as BinaryStore.ReadAction) == "x"
+ data.done()
+
+ cleanup:
+ store.close()
+ }
+
+ def "may be empty"() {
+ def store = new DefaultBinaryStore(temp.file("foo.bin"))
+
+ when:
+ def data = store.done()
+ store.close()
+
+ then:
+ data.done()
+ }
+}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/store/ResolutionResultsStoreFactoryTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/store/ResolutionResultsStoreFactoryTest.groovy
new file mode 100644
index 0000000..0f2a270
--- /dev/null
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/store/ResolutionResultsStoreFactoryTest.groovy
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.ivyservice.resolveengine.store
+
+import org.gradle.api.internal.cache.BinaryStore
+import org.gradle.api.internal.file.TmpDirTemporaryFileProvider
+import org.gradle.internal.CompositeStoppable
+import spock.lang.Specification
+
+class ResolutionResultsStoreFactoryTest extends Specification {
+
+ def f = new ResolutionResultsStoreFactory(new TmpDirTemporaryFileProvider())
+
+ def "provides binary stores"() {
+ def store1 = f.createBinaryStore("1")
+ def store2 = f.createBinaryStore("2")
+
+ expect:
+ store1 != store2
+ store1 == f.createBinaryStore("1")
+ }
+
+ def "rolls the file"() {
+ f = new ResolutionResultsStoreFactory(new TmpDirTemporaryFileProvider(), 2);
+
+ when:
+ def store = f.createBinaryStore("1")
+ store.write({it.writeByte(1); it.writeByte(2) } as BinaryStore.WriteAction)
+ store.done()
+ def store2 = f.createBinaryStore("1")
+
+ then:
+ store.file == store2.file
+
+ when:
+ store2.write({it.writeByte(4)} as BinaryStore.WriteAction)
+ store2.done()
+
+ then:
+ f.createBinaryStore("1").file != store2.file
+ }
+
+ def "cleans up binary files"() {
+ f = new ResolutionResultsStoreFactory(new TmpDirTemporaryFileProvider(), 1);
+
+ when:
+ def store = f.createBinaryStore("1")
+ store.write({it.writeByte(1); it.writeByte(2) } as BinaryStore.WriteAction)
+ store.done()
+ def store2 = f.createBinaryStore("1") //rolled
+ def store3 = f.createBinaryStore("2")
+
+ then:
+ store.file != store2.file //rolled
+ [store.file, store2.file, store3.file].each { it.exists() }
+
+ when:
+ new CompositeStoppable().add(store, store2, store3)
+
+ then:
+ [store.file, store2.file, store3.file].each { !it.exists() }
+ }
+
+ def "provides caches"() {
+ expect:
+ f.createNewModelCache("x").load({"x"} as org.gradle.internal.Factory) == "x"
+ f.createNewModelCache("y").load({"y"} as org.gradle.internal.Factory) == "y"
+ f.createNewModelCache("y").load({"yyyy"} as org.gradle.internal.Factory) == "y"
+
+ f.createOldModelCache("x").load({"x"} as org.gradle.internal.Factory) == "x"
+ f.createOldModelCache("y").load({"y"} as org.gradle.internal.Factory) == "y"
+ f.createOldModelCache("y").load({"yyyy"} as org.gradle.internal.Factory) == "y"
+ }
+}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/mvnsettings/DefaultLocalMavenRepositoryLocatorTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/mvnsettings/DefaultLocalMavenRepositoryLocatorTest.groovy
index 18896b8..32615ae 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/mvnsettings/DefaultLocalMavenRepositoryLocatorTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/mvnsettings/DefaultLocalMavenRepositoryLocatorTest.groovy
@@ -52,7 +52,7 @@ class DefaultLocalMavenRepositoryLocatorTest extends Specification {
locator.localMavenRepository
then:
def ex = thrown(CannotLocateLocalMavenRepositoryException);
- ex.message == "Unable to parse local maven settings."
+ ex.message == "Unable to parse local Maven settings."
ex.cause.message.contains(settingsFile.absolutePath)
}
@@ -64,7 +64,7 @@ class DefaultLocalMavenRepositoryLocatorTest extends Specification {
locator.localMavenRepository
then:
def ex = thrown(CannotLocateLocalMavenRepositoryException)
- ex.message == "Unable to parse local maven settings."
+ ex.message == "Unable to parse local Maven settings."
ex.cause.message.contains(settingsFile.absolutePath)
}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/repositories/DefaultBaseRepositoryFactoryTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/repositories/DefaultBaseRepositoryFactoryTest.groovy
index d3f1c8e..31ba2f6 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/repositories/DefaultBaseRepositoryFactoryTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/repositories/DefaultBaseRepositoryFactoryTest.groovy
@@ -16,138 +16,153 @@
package org.gradle.api.internal.artifacts.repositories
-import org.apache.ivy.core.cache.RepositoryCacheManager
import org.apache.ivy.plugins.resolver.DependencyResolver
import org.gradle.api.InvalidUserDataException
import org.gradle.api.artifacts.dsl.RepositoryHandler
import org.gradle.api.artifacts.repositories.ArtifactRepository
+import org.gradle.api.internal.artifacts.ModuleMetadataProcessor
+import org.gradle.api.internal.artifacts.dsl.DefaultRepositoryHandler
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.MetaDataParser
import org.gradle.api.internal.artifacts.mvnsettings.LocalMavenRepositoryLocator
+import org.gradle.api.internal.artifacts.repositories.legacy.LegacyDependencyResolverRepositoryFactory
import org.gradle.api.internal.artifacts.repositories.transport.RepositoryTransportFactory
import org.gradle.api.internal.externalresource.local.LocallyAvailableResourceFinder
import org.gradle.api.internal.file.FileResolver
import org.gradle.internal.reflect.DirectInstantiator
import org.gradle.logging.ProgressLoggerFactory
-import org.gradle.util.JUnit4GroovyMockery
-import org.hamcrest.Matchers
-import org.jmock.integration.junit4.JMock
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-/**
- * @author Hans Dockter
- */
- at RunWith(JMock.class)
-class DefaultBaseRepositoryFactoryTest {
+import spock.lang.Specification
+
+class DefaultBaseRepositoryFactoryTest extends Specification {
static final URI RESOLVER_URL = new URI('http://a.b.c/')
static final String TEST_REPO = 'http://www.gradle.org'
static final URI TEST_REPO_URL = new URI('http://www.gradle.org/')
static final URI TEST_REPO2_URL = new URI('http://www.gradleware.com/')
- final JUnit4GroovyMockery context = new JUnit4GroovyMockery()
- final LocalMavenRepositoryLocator localMavenRepoLocator = context.mock(LocalMavenRepositoryLocator.class)
- final FileResolver fileResolver = context.mock(FileResolver.class)
- final RepositoryTransportFactory transportFactory = context.mock(RepositoryTransportFactory.class)
- final LocallyAvailableResourceFinder locallyAvailableResourceFinder = context.mock(LocallyAvailableResourceFinder.class)
- final RepositoryCacheManager localCacheManager = context.mock(RepositoryCacheManager)
- final RepositoryCacheManager downloadingCacheManager = context.mock(RepositoryCacheManager)
- final ProgressLoggerFactory progressLoggerFactory = context.mock(ProgressLoggerFactory)
+ final LocalMavenRepositoryLocator localMavenRepoLocator = Mock()
+ final FileResolver fileResolver = Mock()
+ final RepositoryTransportFactory transportFactory = Mock()
+ final LocallyAvailableResourceFinder locallyAvailableResourceFinder = Mock()
+ final ProgressLoggerFactory progressLoggerFactory = Mock()
+ final MetaDataParser metaDataParser = Mock()
+ final ModuleMetadataProcessor metadataProcessor = Mock()
+ final LegacyDependencyResolverRepositoryFactory legacyDependencyResolverRepositoryFactory = Mock()
+
final DefaultBaseRepositoryFactory factory = new DefaultBaseRepositoryFactory(
localMavenRepoLocator, fileResolver, new DirectInstantiator(), transportFactory, locallyAvailableResourceFinder,
- progressLoggerFactory, localCacheManager, downloadingCacheManager
+ metaDataParser, metadataProcessor, legacyDependencyResolverRepositoryFactory
)
- @Before public void setup() {
- context.checking {
- allowing(fileResolver).resolveUri('uri');
- will(returnValue(RESOLVER_URL))
- allowing(fileResolver).resolveUri(TEST_REPO);
- will(returnValue(TEST_REPO_URL))
- allowing(fileResolver).resolveUri('uri2');
- will(returnValue(TEST_REPO2_URL))
- allowing(fileResolver).resolveUri(withParam(Matchers.instanceOf(URI)));
- will { uri -> return uri }
- }
- }
+ def testCreateResolverWithStringDescription() {
+ when:
+ fileResolver.resolveUri('uri') >> RESOLVER_URL
- @Test public void testCreateResolverWithStringDescription() {
+ then:
def repository = factory.createRepository('uri')
- assert repository instanceof DefaultMavenArtifactRepository
- assert repository.url == RESOLVER_URL
- assert repository.name == null
- assert repository.artifactUrls.isEmpty()
+ repository instanceof DefaultMavenArtifactRepository
+ repository.name == null
+ repository.url == RESOLVER_URL
+ repository.artifactUrls.isEmpty()
}
- @Test public void testCreateResolverWithMapDescription() {
+ def testCreateResolverWithMapDescription() {
+ when:
+ fileResolver.resolveUri('uri') >> RESOLVER_URL
+
+ then:
def repository = factory.createRepository([name: 'name', url: 'uri'])
- assert repository instanceof DefaultMavenArtifactRepository
- assert repository.url == RESOLVER_URL
- assert repository.name == 'name'
- assert repository.artifactUrls.isEmpty()
+ repository instanceof DefaultMavenArtifactRepository
+ repository.name == 'name'
+ repository.url == RESOLVER_URL
+ repository.artifactUrls.isEmpty()
}
- @Test public void testCreateResolverWithResolverDescription() {
- DependencyResolver resolver = context.mock(DependencyResolver)
-
- ArtifactRepository repository = factory.createRepository(resolver)
+ def testCreateResolverWithResolverDescription() {
+ def repository = Mock(ArtifactRepository)
+ def resolver = Mock(DependencyResolver)
+
+ when:
+ legacyDependencyResolverRepositoryFactory.createRepository(resolver) >> repository
- assert repository instanceof FixedResolverArtifactRepository
- assert repository.resolver == resolver
+ then:
+ factory.createRepository(resolver) == repository
}
- @Test public void testCreateResolverWithArtifactRepositoryDescription() {
- ArtifactRepository repo = context.mock(ArtifactRepository)
+ def testCreateResolverWithArtifactRepositoryDescription() {
+ when:
+ ArtifactRepository repo = Mock(ArtifactRepository)
- assert factory.createRepository(repo) == repo
+ then:
+ factory.createRepository(repo) == repo
}
- @Test(expected = InvalidUserDataException) public void testCreateResolverForUnknownDescription() {
+ def testCreateResolverForUnknownDescription() {
+ when:
def someIllegalDescription = new NullPointerException()
+
factory.createRepository(someIllegalDescription)
+
+ then:
+ thrown InvalidUserDataException
}
- @Test public void testCreateFlatDirResolver() {
+ def testCreateFlatDirResolver() {
+ expect:
def repo =factory.createFlatDirRepository()
- assert repo instanceof DefaultFlatDirArtifactRepository
+ repo instanceof DefaultFlatDirArtifactRepository
}
- @Test public void testCreateLocalMavenRepo() {
+ def testCreateLocalMavenRepo() {
+ given:
File repoDir = new File(".m2/repository")
- context.checking {
- one(localMavenRepoLocator).getLocalMavenRepository()
- will(returnValue(repoDir))
- allowing(fileResolver).resolveUri(repoDir)
- will(returnValue(repoDir.toURI()))
- }
+ when:
+ localMavenRepoLocator.getLocalMavenRepository() >> repoDir
+ fileResolver.resolveUri(repoDir) >> repoDir.toURI()
+ then:
def repo = factory.createMavenLocalRepository()
- assert repo instanceof DefaultMavenArtifactRepository
- assert repo.url == repoDir.toURI()
+ repo instanceof DefaultMavenArtifactRepository
+ repo.url == repoDir.toURI()
+ }
+
+ def testCreateJCenterRepo() {
+ given:
+ def jcenterUrl = new URI(DefaultRepositoryHandler.BINTRAY_JCENTER_URL)
+
+ when:
+ fileResolver.resolveUri(DefaultRepositoryHandler.BINTRAY_JCENTER_URL) >> jcenterUrl
+
+ then:
+ def repo = factory.createJCenterRepository()
+ repo instanceof DefaultMavenArtifactRepository
+ repo.url == jcenterUrl
}
- @Test public void testCreateMavenCentralRepo() {
+ def testCreateMavenCentralRepo() {
+ given:
def centralUrl = new URI(RepositoryHandler.MAVEN_CENTRAL_URL)
- context.checking {
- allowing(fileResolver).resolveUri(RepositoryHandler.MAVEN_CENTRAL_URL)
- will(returnValue(centralUrl))
- }
+ when:
+ fileResolver.resolveUri(RepositoryHandler.MAVEN_CENTRAL_URL) >> centralUrl
+ then:
def repo = factory.createMavenCentralRepository()
- assert repo instanceof DefaultMavenArtifactRepository
- assert repo.url == centralUrl
+ repo instanceof DefaultMavenArtifactRepository
+ repo.url == centralUrl
}
- @Test public void createIvyRepository() {
+ def createIvyRepository() {
+ expect:
def repo = factory.createIvyRepository()
- assert repo instanceof DefaultIvyArtifactRepository
+ repo instanceof DefaultIvyArtifactRepository
}
- @Test public void createMavenRepository() {
+ def createMavenRepository() {
+ expect:
def repo = factory.createMavenRepository()
- assert repo instanceof DefaultMavenArtifactRepository
+ repo instanceof DefaultMavenArtifactRepository
}
}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/repositories/DefaultFlatDirArtifactRepositoryTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/repositories/DefaultFlatDirArtifactRepositoryTest.groovy
index 9fcf452..1ca8535 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/repositories/DefaultFlatDirArtifactRepositoryTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/repositories/DefaultFlatDirArtifactRepositoryTest.groovy
@@ -14,33 +14,49 @@
* limitations under the License.
*/
package org.gradle.api.internal.artifacts.repositories
-
-import org.apache.ivy.core.cache.RepositoryCacheManager
-import org.apache.ivy.plugins.resolver.FileSystemResolver
+import org.apache.ivy.core.module.id.ArtifactRevisionId
import org.gradle.api.InvalidUserDataException
+import org.gradle.api.internal.artifacts.ModuleMetadataProcessor
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.MetaDataParser
+import org.gradle.api.internal.artifacts.repositories.resolver.IvyResolver
+import org.gradle.api.internal.artifacts.repositories.transport.RepositoryTransport
+import org.gradle.api.internal.artifacts.repositories.transport.RepositoryTransportFactory
+import org.gradle.api.internal.externalresource.local.LocallyAvailableResourceFinder
+import org.gradle.api.internal.externalresource.transport.ExternalResourceRepository
import org.gradle.api.internal.file.FileResolver
import org.gradle.api.internal.file.collections.SimpleFileCollection
import spock.lang.Specification
class DefaultFlatDirArtifactRepositoryTest extends Specification {
final FileResolver fileResolver = Mock()
- final RepositoryCacheManager localCacheManager = Mock()
- final DefaultFlatDirArtifactRepository repository = new DefaultFlatDirArtifactRepository(fileResolver, localCacheManager)
+ final ExternalResourceRepository resourceRepository = Mock()
+ final RepositoryTransport repositoryTransport = Mock()
+ final RepositoryTransportFactory transportFactory = Mock()
+ final LocallyAvailableResourceFinder<ArtifactRevisionId> locallyAvailableResourceFinder = Mock()
+ final MetaDataParser metaDataParser = Mock()
+ final ModuleMetadataProcessor metadataProcessor = Mock()
+ final DefaultFlatDirArtifactRepository repository = new DefaultFlatDirArtifactRepository(
+ fileResolver, transportFactory, locallyAvailableResourceFinder, metaDataParser, metadataProcessor)
def "creates a repository with multiple root directories"() {
given:
def dir1 = new File('a')
def dir2 = new File('b')
_ * fileResolver.resolveFiles(['a', 'b']) >> new SimpleFileCollection(dir1, dir2)
+ _ * repositoryTransport.repository >> resourceRepository
and:
+ repository.name = 'repo-name'
repository.dirs('a', 'b')
when:
- def repo = repository.createLegacyDslObject()
+ def repo = repository.createResolver()
then:
- repo instanceof FileSystemResolver
+ 1 * transportFactory.createFileTransport("repo-name") >> repositoryTransport
+
+ and:
+ repo instanceof IvyResolver
def expectedPatterns = [
"$dir1.absolutePath/[artifact]-[revision](-[classifier]).[ext]",
"$dir1.absolutePath/[artifact](-[classifier]).[ext]",
@@ -57,7 +73,7 @@ class DefaultFlatDirArtifactRepositoryTest extends Specification {
_ * fileResolver.resolveFiles(_) >> new SimpleFileCollection()
when:
- repository.createLegacyDslObject()
+ repository.createResolver()
then:
InvalidUserDataException e = thrown()
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/repositories/DefaultIvyArtifactRepositoryTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/repositories/DefaultIvyArtifactRepositoryTest.groovy
index 44adf6b..e0f6a16 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/repositories/DefaultIvyArtifactRepositoryTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/repositories/DefaultIvyArtifactRepositoryTest.groovy
@@ -14,20 +14,16 @@
* limitations under the License.
*/
package org.gradle.api.internal.artifacts.repositories
-
-import org.apache.ivy.core.cache.RepositoryCacheManager
import org.gradle.api.InvalidUserDataException
import org.gradle.api.artifacts.repositories.PasswordCredentials
-import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ExternalResourceResolverAdapter
+import org.gradle.api.internal.artifacts.ModuleMetadataProcessor
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.MetaDataParser
import org.gradle.api.internal.artifacts.repositories.resolver.IvyResolver
+import org.gradle.api.internal.artifacts.repositories.transport.RepositoryTransport
import org.gradle.api.internal.artifacts.repositories.transport.RepositoryTransportFactory
-import org.gradle.api.internal.externalresource.cached.CachedExternalResourceIndex
import org.gradle.api.internal.externalresource.local.LocallyAvailableResourceFinder
import org.gradle.api.internal.externalresource.transport.ExternalResourceRepository
-import org.gradle.api.internal.externalresource.transport.file.FileTransport
-import org.gradle.api.internal.externalresource.transport.http.HttpTransport
import org.gradle.api.internal.file.FileResolver
-import org.gradle.api.internal.file.TemporaryFileProvider
import org.gradle.internal.reflect.DirectInstantiator
import org.gradle.logging.ProgressLoggerFactory
import spock.lang.Specification
@@ -36,13 +32,14 @@ class DefaultIvyArtifactRepositoryTest extends Specification {
final FileResolver fileResolver = Mock()
final PasswordCredentials credentials = Mock()
final RepositoryTransportFactory transportFactory = Mock()
- final RepositoryCacheManager cacheManager = Mock()
final LocallyAvailableResourceFinder locallyAvailableResourceFinder = Mock()
- final CachedExternalResourceIndex cachedExternalResourceIndex = Mock()
+ final ExternalResourceRepository resourceRepository = Mock()
final ProgressLoggerFactory progressLoggerFactory = Mock()
+ final MetaDataParser metaDataParser = Mock()
+ final ModuleMetadataProcessor metadataProcessor = Mock()
final DefaultIvyArtifactRepository repository = new DefaultIvyArtifactRepository(
- fileResolver, credentials, transportFactory, locallyAvailableResourceFinder, new DirectInstantiator()
+ fileResolver, credentials, transportFactory, locallyAvailableResourceFinder, new DirectInstantiator(), metaDataParser, metadataProcessor
)
def "default values"() {
@@ -59,7 +56,7 @@ class DefaultIvyArtifactRepositoryTest extends Specification {
fileResolver.resolveUri('pattern1') >> new URI('scheme:resource1')
when:
- repository.createRealResolver()
+ repository.createResolver()
then:
InvalidUserDataException e = thrown()
@@ -76,7 +73,7 @@ class DefaultIvyArtifactRepositoryTest extends Specification {
fileResolver.resolveUri('pattern2') >> new URI('file:resource2')
when:
- repository.createRealResolver()
+ repository.createResolver()
then:
InvalidUserDataException e = thrown()
@@ -92,15 +89,15 @@ class DefaultIvyArtifactRepositoryTest extends Specification {
given:
fileResolver.resolveUri('http://host/') >> new URI('http://host/')
fileResolver.resolveUri('http://other/') >> new URI('http://other/')
- transportFactory.createHttpTransport('name', credentials) >> createHttpTransport("name", credentials)
+ transportFactory.createHttpTransport('name', credentials) >> transport()
when:
- def resolver = repository.createRealResolver()
+ def resolver = repository.createResolver()
then:
with(resolver) {
it instanceof IvyResolver
- repository instanceof ExternalResourceRepository
+ repository == resourceRepository
name == 'name'
artifactPatterns == ['http://host/[organisation]/[artifact]-[revision].[ext]', 'http://other/[module]/[artifact]-[revision].[ext]']
ivyPatterns == ['http://host/[module]/ivy-[revision].xml']
@@ -117,18 +114,18 @@ class DefaultIvyArtifactRepositoryTest extends Specification {
given:
fileResolver.resolveUri('repo/') >> fileUri
- transportFactory.createFileTransport('name') >> new FileTransport('name', cacheManager, Mock(TemporaryFileProvider))
+ transportFactory.createFileTransport('name') >> transport()
when:
- def resolver = repository.createRealResolver()
+ def resolver = repository.createResolver()
then:
with(resolver) {
it instanceof IvyResolver
repository instanceof ExternalResourceRepository
name == 'name'
- artifactPatterns == ["${file.absolutePath}/[organisation]/[artifact]-[revision].[ext]", "${file.absolutePath}/[organisation]/[module]/[artifact]-[revision].[ext]"]
- ivyPatterns == ["${file.absolutePath}/[organisation]/[module]/ivy-[revision].xml"]
+ artifactPatterns == ["${fileUri}/[organisation]/[artifact]-[revision].[ext]", "${fileUri}/[organisation]/[module]/[artifact]-[revision].[ext]"]
+ ivyPatterns == ["${fileUri}/[organisation]/[module]/ivy-[revision].xml"]
}
}
@@ -140,7 +137,7 @@ class DefaultIvyArtifactRepositoryTest extends Specification {
given:
fileResolver.resolveUri('repo/') >> fileUri
- transportFactory.createFileTransport('name') >> new FileTransport('name', cacheManager, Mock(TemporaryFileProvider))
+ transportFactory.createFileTransport('name') >> transport()
when:
def wrapper = repository.createLegacyDslObject()
@@ -155,8 +152,7 @@ class DefaultIvyArtifactRepositoryTest extends Specification {
def repo = wrapper.createResolver()
then:
- repo instanceof ExternalResourceResolverAdapter
- repo.resolver.is(wrapper.resolver)
+ repo.is(wrapper.resolver)
}
def "uses gradle patterns with specified url and default layout"() {
@@ -165,10 +161,10 @@ class DefaultIvyArtifactRepositoryTest extends Specification {
given:
fileResolver.resolveUri('http://host') >> new URI('http://host/')
- transportFactory.createHttpTransport('name', credentials) >> createHttpTransport("name", credentials)
+ transportFactory.createHttpTransport('name', credentials) >> transport()
when:
- def resolver = repository.createRealResolver()
+ def resolver = repository.createResolver()
then:
with(resolver) {
@@ -187,10 +183,10 @@ class DefaultIvyArtifactRepositoryTest extends Specification {
given:
fileResolver.resolveUri('http://host') >> new URI('http://host/')
- transportFactory.createHttpTransport('name', credentials) >> createHttpTransport("name", credentials)
+ transportFactory.createHttpTransport('name', credentials) >> transport()
when:
- def resolver = repository.createRealResolver()
+ def resolver = repository.createResolver()
then:
with(resolver) {
@@ -213,10 +209,10 @@ class DefaultIvyArtifactRepositoryTest extends Specification {
given:
fileResolver.resolveUri('http://host') >> new URI('http://host/')
- transportFactory.createHttpTransport('name', credentials) >> createHttpTransport("name", credentials)
+ transportFactory.createHttpTransport('name', credentials) >> transport()
when:
- def resolver = repository.createRealResolver()
+ def resolver = repository.createResolver()
then:
with(resolver) {
@@ -240,10 +236,10 @@ class DefaultIvyArtifactRepositoryTest extends Specification {
given:
fileResolver.resolveUri('http://host') >> new URI('http://host/')
- transportFactory.createHttpTransport('name', credentials) >> createHttpTransport("name", credentials)
+ transportFactory.createHttpTransport('name', credentials) >> transport()
when:
- def resolver = repository.createRealResolver()
+ def resolver = repository.createResolver()
then:
with(resolver) {
@@ -264,10 +260,10 @@ class DefaultIvyArtifactRepositoryTest extends Specification {
given:
fileResolver.resolveUri('http://host/') >> new URI('http://host/')
- transportFactory.createHttpTransport('name', credentials) >> createHttpTransport("name", credentials)
+ transportFactory.createHttpTransport('name', credentials) >> transport()
when:
- def resolver = repository.createRealResolver()
+ def resolver = repository.createResolver()
then:
with(resolver) {
@@ -286,14 +282,14 @@ class DefaultIvyArtifactRepositoryTest extends Specification {
artifact '[layoutPattern]'
}
repository.artifactPattern 'http://other/[additionalPattern]'
- transportFactory.createHttpTransport('name', credentials) >> createHttpTransport("name", credentials)
+ transportFactory.createHttpTransport('name', credentials) >> transport()
given:
fileResolver.resolveUri('http://host') >> new URI('http://host')
fileResolver.resolveUri('http://other/') >> new URI('http://other/')
when:
- def resolver = repository.createRealResolver()
+ def resolver = repository.createResolver()
then:
resolver.artifactPatterns == ['http://host/[layoutPattern]', 'http://other/[additionalPattern]']
@@ -302,17 +298,23 @@ class DefaultIvyArtifactRepositoryTest extends Specification {
def "fails when no artifact patterns specified"() {
given:
- transportFactory.createHttpTransport('name', credentials) >> createHttpTransport("name", credentials)
+ transportFactory.createHttpTransport('name', credentials) >> transport()
when:
- repository.createRealResolver()
+ repository.createResolver()
then:
InvalidUserDataException e = thrown()
e.message == 'You must specify a base url or at least one artifact pattern for an Ivy repository.'
}
- private HttpTransport createHttpTransport(String name, PasswordCredentials credentials) {
- return new HttpTransport(name, credentials, cacheManager, progressLoggerFactory, Mock(TemporaryFileProvider), cachedExternalResourceIndex)
+ private RepositoryTransport transport() {
+ return Mock(RepositoryTransport) {
+ getRepository() >> resourceRepository
+ convertToPath(_) >> { URI uri ->
+ def result = uri.toString()
+ return result.endsWith('/') ? result : result + '/'
+ }
+ }
}
}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/repositories/DefaultMavenArtifactRepositoryTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/repositories/DefaultMavenArtifactRepositoryTest.groovy
index 7ce96a5..64f7b54 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/repositories/DefaultMavenArtifactRepositoryTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/repositories/DefaultMavenArtifactRepositoryTest.groovy
@@ -15,39 +15,39 @@
*/
package org.gradle.api.internal.artifacts.repositories
-import org.apache.ivy.core.cache.RepositoryCacheManager
import org.gradle.api.InvalidUserDataException
import org.gradle.api.artifacts.repositories.PasswordCredentials
-import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ExternalResourceResolverAdapter
+import org.gradle.api.internal.artifacts.ModuleMetadataProcessor
+
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.MetaDataParser
import org.gradle.api.internal.artifacts.repositories.resolver.MavenResolver
+import org.gradle.api.internal.artifacts.repositories.transport.RepositoryTransport
import org.gradle.api.internal.artifacts.repositories.transport.RepositoryTransportFactory
-import org.gradle.api.internal.externalresource.transport.file.FileTransport
-import org.gradle.api.internal.externalresource.transport.http.HttpTransport
-import org.gradle.api.internal.file.FileResolver
-import org.gradle.api.internal.file.TemporaryFileProvider
-import spock.lang.Specification
import org.gradle.api.internal.externalresource.local.LocallyAvailableResourceFinder
-import org.gradle.api.internal.externalresource.cached.CachedExternalResourceIndex
+import org.gradle.api.internal.externalresource.transport.ExternalResourceRepository
+import org.gradle.api.internal.file.FileResolver
import org.gradle.logging.ProgressLoggerFactory
+import spock.lang.Specification
class DefaultMavenArtifactRepositoryTest extends Specification {
final FileResolver resolver = Mock()
final PasswordCredentials credentials = Mock()
final RepositoryTransportFactory transportFactory = Mock()
- final RepositoryCacheManager cacheManager = Mock()
final LocallyAvailableResourceFinder locallyAvailableResourceFinder = Mock()
- final CachedExternalResourceIndex cachedExternalResourceIndex = Mock()
+ final ExternalResourceRepository resourceRepository = Mock()
+ final MetaDataParser metaDataParser = Mock()
+ final ModuleMetadataProcessor metadataProcessor = Mock()
- final DefaultMavenArtifactRepository repository = new DefaultMavenArtifactRepository(resolver, credentials, transportFactory, locallyAvailableResourceFinder)
+ final DefaultMavenArtifactRepository repository = new DefaultMavenArtifactRepository(
+ resolver, credentials, transportFactory, locallyAvailableResourceFinder, metaDataParser, metadataProcessor)
final ProgressLoggerFactory progressLoggerFactory = Mock();
-
def "creates local repository"() {
given:
def file = new File('repo')
def uri = file.toURI()
_ * resolver.resolveUri('repo-dir') >> uri
- transportFactory.createFileTransport('repo') >> new FileTransport('repo', cacheManager, Mock(TemporaryFileProvider))
+ transportFactory.createFileTransport('repo') >> transport()
and:
repository.name = 'repo'
@@ -58,7 +58,7 @@ class DefaultMavenArtifactRepositoryTest extends Specification {
then:
repo instanceof MavenResolver
- repo.root == "${file.absolutePath}/"
+ repo.root == "${uri}/"
}
def "creates http repository"() {
@@ -67,9 +67,7 @@ class DefaultMavenArtifactRepositoryTest extends Specification {
_ * resolver.resolveUri('repo-dir') >> uri
_ * credentials.getUsername() >> 'username'
_ * credentials.getPassword() >> 'password'
- transportFactory.createHttpTransport('repo', credentials) >> createHttpTransport("repo", credentials)
- cacheManager.name >> 'cache'
- 0 * _._
+ transportFactory.createHttpTransport('repo', credentials) >> transport()
and:
repository.name = 'repo'
@@ -88,7 +86,7 @@ class DefaultMavenArtifactRepositoryTest extends Specification {
def file = new File('repo')
def uri = file.toURI()
_ * this.resolver.resolveUri('repo-dir') >> uri
- transportFactory.createFileTransport('repo') >> new FileTransport('repo', cacheManager, Mock(TemporaryFileProvider))
+ transportFactory.createFileTransport('repo') >> transport()
and:
repository.name = 'repo'
@@ -105,8 +103,7 @@ class DefaultMavenArtifactRepositoryTest extends Specification {
def repo = resolver.createResolver()
then:
- repo instanceof ExternalResourceResolverAdapter
- repo.resolver.is(resolver.resolver)
+ repo.is(resolver.resolver)
}
def "creates repository with additional artifact URLs"() {
@@ -117,7 +114,7 @@ class DefaultMavenArtifactRepositoryTest extends Specification {
_ * resolver.resolveUri('repo-dir') >> uri
_ * resolver.resolveUri('repo1') >> uri1
_ * resolver.resolveUri('repo2') >> uri2
- transportFactory.createHttpTransport('repo', credentials) >> createHttpTransport("repo", credentials)
+ transportFactory.createHttpTransport('repo', credentials) >> transport()
and:
repository.name = 'repo'
@@ -136,10 +133,6 @@ class DefaultMavenArtifactRepositoryTest extends Specification {
repo.artifactPatterns.any { it.startsWith uri2.toString() }
}
- private HttpTransport createHttpTransport(String repo, PasswordCredentials credentials) {
- return new HttpTransport(repo, credentials, cacheManager, progressLoggerFactory, Mock(TemporaryFileProvider), cachedExternalResourceIndex)
- }
-
def "fails when no root url specified"() {
when:
repository.createLegacyDslObject()
@@ -148,4 +141,15 @@ class DefaultMavenArtifactRepositoryTest extends Specification {
InvalidUserDataException e = thrown()
e.message == 'You must specify a URL for a Maven repository.'
}
+
+ private RepositoryTransport transport() {
+ return Mock(RepositoryTransport) {
+ getRepository() >> resourceRepository
+ convertToPath(_) >> { URI uri ->
+ def result = uri.toString()
+ return result.endsWith('/') ? result : result + '/'
+ }
+ }
+ }
+
}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/repositories/cachemanager/DownloadingRepositoryCacheManagerTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/repositories/cachemanager/DownloadingRepositoryCacheManagerTest.groovy
deleted file mode 100644
index 61bff84..0000000
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/repositories/cachemanager/DownloadingRepositoryCacheManagerTest.groovy
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.artifacts.repositories.cachemanager
-
-import org.apache.ivy.core.module.descriptor.Artifact
-import org.apache.ivy.core.module.id.ArtifactRevisionId
-import org.apache.ivy.plugins.repository.Resource
-import org.apache.ivy.plugins.repository.ResourceDownloader
-import org.apache.ivy.plugins.resolver.util.ResolvedResource
-import org.gradle.api.internal.artifacts.ivyservice.CacheLockingManager
-import org.gradle.api.internal.externalresource.cached.CachedExternalResourceIndex
-import org.gradle.api.internal.file.TemporaryFileProvider
-import org.gradle.api.internal.filestore.FileStore
-import org.gradle.api.internal.filestore.FileStoreEntry
-import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
-import org.junit.Rule
-import spock.lang.Specification
-
-class DownloadingRepositoryCacheManagerTest extends Specification {
- FileStore<ArtifactRevisionId> fileStore = Mock()
- CachedExternalResourceIndex<String> artifactUrlCachedResolutionIndex = Mock()
- CacheLockingManager lockingManager = Mock()
- TemporaryFileProvider tmpFileProvider = Mock()
- ArtifactRevisionId artifactId = Mock()
- Artifact artifact = Mock()
- ResourceDownloader resourceDownloader = Mock()
- ResolvedResource artifactRef = Mock()
- Resource resource = Mock();
- FileStoreEntry fileStoreEntry = Mock()
- DownloadingRepositoryCacheManager downloadingRepositoryCacheManager = new DownloadingRepositoryCacheManager("TestCacheManager", fileStore, artifactUrlCachedResolutionIndex, tmpFileProvider, lockingManager)
-
- @Rule TestNameTestDirectoryProvider temporaryFolder;
-
- void "downloadArtifactFile downloads artifact to temporary file and then moves it into the file store"() {
- setup:
-
- def downloadFile = temporaryFolder.createFile("download")
- def storeFile = temporaryFolder.createFile("store")
-
- _ * artifact.id >> artifactId
- _ * artifactRef.resource >> resource
- _ * fileStoreEntry.file >> storeFile;
- _ * tmpFileProvider._ >> downloadFile
-
- when:
- downloadingRepositoryCacheManager.downloadArtifactFile(artifact, resourceDownloader, artifactRef)
-
- then:
- 1 * lockingManager.useCache(_, _) >> {name, action ->
- return action.create()
- }
- 1 * resourceDownloader.download(artifact, resource, downloadFile)
- 1 * fileStore.move(artifactId, downloadFile) >> {key, action ->
- return fileStoreEntry
- }
- }
-}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/repositories/legacy/DownloadingRepositoryCacheManagerTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/repositories/legacy/DownloadingRepositoryCacheManagerTest.groovy
new file mode 100644
index 0000000..23c89c4
--- /dev/null
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/repositories/legacy/DownloadingRepositoryCacheManagerTest.groovy
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.repositories.legacy
+
+import org.apache.ivy.core.module.descriptor.Artifact
+import org.apache.ivy.core.module.id.ArtifactRevisionId
+import org.apache.ivy.plugins.repository.Resource
+import org.apache.ivy.plugins.repository.ResourceDownloader
+import org.gradle.api.internal.artifacts.ivyservice.CacheLockingManager
+import org.gradle.api.internal.file.TemporaryFileProvider
+import org.gradle.internal.filestore.FileStore
+import org.gradle.internal.resource.local.LocallyAvailableResource
+import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
+import org.junit.Rule
+import spock.lang.Specification
+
+class DownloadingRepositoryCacheManagerTest extends Specification {
+ FileStore<ArtifactRevisionId> fileStore = Mock()
+ CacheLockingManager lockingManager = Mock()
+ TemporaryFileProvider tmpFileProvider = Mock()
+ ArtifactRevisionId artifactId = Mock()
+ Artifact artifact = Mock()
+ ResourceDownloader resourceDownloader = Mock()
+ Resource resource = Mock();
+ LocallyAvailableResource fileStoreEntry = Mock()
+ DownloadingRepositoryCacheManager downloadingRepositoryCacheManager = new DownloadingRepositoryCacheManager("TestCacheManager", fileStore, tmpFileProvider, lockingManager)
+
+ @Rule TestNameTestDirectoryProvider temporaryFolder;
+
+ void "downloads artifact to temporary file and then moves it into the file store"() {
+ setup:
+
+ def downloadFile = temporaryFolder.createFile("download")
+ def storeFile = temporaryFolder.createFile("store")
+
+ _ * artifact.id >> artifactId
+ _ * fileStoreEntry.file >> storeFile;
+ _ * tmpFileProvider._ >> downloadFile
+
+ when:
+ downloadingRepositoryCacheManager.downloadAndCacheArtifactFile(artifact, resourceDownloader, resource)
+
+ then:
+ 1 * lockingManager.useCache(_, _) >> {name, action ->
+ return action.create()
+ }
+ 1 * resourceDownloader.download(artifact, resource, downloadFile)
+ 1 * fileStore.move(artifactId, downloadFile) >> {key, action ->
+ return fileStoreEntry
+ }
+ }
+}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/repositories/resolver/ChainedVersionListerTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/repositories/resolver/ChainedVersionListerTest.groovy
index 2cac12d..349f432 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/repositories/resolver/ChainedVersionListerTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/repositories/resolver/ChainedVersionListerTest.groovy
@@ -17,7 +17,7 @@
package org.gradle.api.internal.artifacts.repositories.resolver
import org.apache.ivy.core.module.descriptor.Artifact
-import org.apache.ivy.core.module.id.ModuleRevisionId
+import org.gradle.api.artifacts.ModuleVersionSelector
import org.gradle.api.internal.resource.ResourceNotFoundException
import spock.lang.Specification
import spock.lang.Unroll
@@ -33,17 +33,17 @@ class ChainedVersionListerTest extends Specification {
ResourcePattern pattern = Mock()
Artifact artifact = Mock()
- ModuleRevisionId moduleRevisionId = Mock()
+ ModuleVersionSelector selector = Mock()
- def chainedVersionLister = new org.gradle.api.internal.artifacts.repositories.resolver.ChainedVersionLister(lister1, lister2)
+ def chainedVersionLister = new ChainedVersionLister(lister1, lister2)
def "visit stops listing after first success"() {
when:
- VersionList versionList = chainedVersionLister.getVersionList(moduleRevisionId);
+ VersionList versionList = chainedVersionLister.getVersionList(selector);
then:
- 1 * lister1.getVersionList(moduleRevisionId) >> versionList1
- 1 * lister2.getVersionList(moduleRevisionId) >> versionList2
+ 1 * lister1.getVersionList(selector) >> versionList1
+ 1 * lister2.getVersionList(selector) >> versionList2
when:
versionList.visit(pattern, artifact)
@@ -53,23 +53,23 @@ class ChainedVersionListerTest extends Specification {
0 * _._
when:
- def result = versionList.versionStrings
+ def result = versionList.versions
then:
result == ["1.0", "1.2"] as Set
and:
- versionList1.versionStrings >> ["1.0", "1.2"]
- versionList2.versionStrings >> []
+ versionList1.versions >> ["1.0", "1.2"]
+ versionList2.versions >> []
}
@Unroll
def "visit ignores #exception.class.simpleName of failed VersionLister"() {
given:
- lister1.getVersionList(moduleRevisionId) >> versionList1
- lister2.getVersionList(moduleRevisionId) >> versionList2
+ lister1.getVersionList(selector) >> versionList1
+ lister2.getVersionList(selector) >> versionList2
- VersionList versionList = chainedVersionLister.getVersionList(moduleRevisionId)
+ VersionList versionList = chainedVersionLister.getVersionList(selector)
when:
versionList.visit(pattern, artifact)
@@ -85,10 +85,10 @@ class ChainedVersionListerTest extends Specification {
def "visit rethrows ResourceNotFoundException of failed last VersionLister"() {
given:
def exception = new ResourceNotFoundException("not found")
- lister1.getVersionList(moduleRevisionId) >> versionList1
- lister2.getVersionList(moduleRevisionId) >> versionList2
+ lister1.getVersionList(selector) >> versionList1
+ lister2.getVersionList(selector) >> versionList2
- VersionList versionList = chainedVersionLister.getVersionList(moduleRevisionId)
+ VersionList versionList = chainedVersionLister.getVersionList(selector)
when:
versionList.visit(pattern, artifact)
@@ -105,17 +105,17 @@ class ChainedVersionListerTest extends Specification {
def "visit wraps failed last VersionLister"() {
given:
def exception = new RuntimeException("broken")
- lister1.getVersionList(moduleRevisionId) >> versionList1
- lister2.getVersionList(moduleRevisionId) >> versionList2
+ lister1.getVersionList(selector) >> versionList1
+ lister2.getVersionList(selector) >> versionList2
- VersionList versionList = chainedVersionLister.getVersionList(moduleRevisionId)
+ VersionList versionList = chainedVersionLister.getVersionList(selector)
when:
versionList.visit(pattern, artifact)
then:
def e = thrown(ResourceException)
- e.message == "Failed to list versions for ${moduleRevisionId}."
+ e.message == "Failed to list versions for ${selector}."
e.cause == exception
and:
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/repositories/resolver/ExternalResourceResolverTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/repositories/resolver/ExternalResourceResolverTest.groovy
index b2211cf..1f4b9a5 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/repositories/resolver/ExternalResourceResolverTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/repositories/resolver/ExternalResourceResolverTest.groovy
@@ -15,15 +15,14 @@
*/
package org.gradle.api.internal.artifacts.repositories.resolver
-
-import org.apache.ivy.core.module.descriptor.Artifact
import org.apache.ivy.core.module.id.ArtifactRevisionId
-import org.apache.ivy.core.module.id.ModuleId
-import org.apache.ivy.core.module.id.ModuleRevisionId
-import org.apache.ivy.core.report.ArtifactDownloadReport
-import org.apache.ivy.core.report.DownloadStatus
+import org.gradle.api.artifacts.ArtifactIdentifier
+import org.gradle.api.internal.artifacts.DefaultArtifactIdentifier
+import org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier
+import org.gradle.api.internal.artifacts.ModuleMetadataProcessor
import org.gradle.api.internal.artifacts.ivyservice.BuildableArtifactResolveResult
-import org.gradle.api.internal.artifacts.repositories.cachemanager.EnhancedArtifactDownloadReport
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ArtifactResolveException
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.MetaDataParser
import org.gradle.api.internal.externalresource.local.LocallyAvailableResourceFinder
import org.gradle.api.internal.externalresource.transport.ExternalResourceRepository
import spock.lang.Specification
@@ -34,17 +33,16 @@ class ExternalResourceResolverTest extends Specification {
VersionLister versionLister = Mock()
LocallyAvailableResourceFinder<ArtifactRevisionId> locallyAvailableResourceFinder = Mock()
BuildableArtifactResolveResult result = Mock()
- Artifact artifact = Mock()
+ MetaDataParser parser = Mock()
+ ModuleMetadataProcessor metadataProcessor = Mock()
+ ArtifactIdentifier artifact = new DefaultArtifactIdentifier(DefaultModuleVersionIdentifier.newId("group", "module", "version"), "name", "type", "ext", "classifier")
MavenResolver.TimestampedModuleSource moduleSource = Mock()
- EnhancedArtifactDownloadReport downloadReport = Mock()
-
+ File downloadedFile = Mock(File)
ExternalResourceResolver resolver
- ModuleRevisionId artifactModuleRevisionId = Mock()
def setup() {
//We use a spy here to avoid dealing with all the overhead ivys basicresolver brings in here.
- resolver = Spy(ExternalResourceResolver, constructorArgs: [name, repository, versionLister, locallyAvailableResourceFinder])
- resolver.download(_) >> downloadReport
+ resolver = Spy(ExternalResourceResolver, constructorArgs: [name, repository, versionLister, locallyAvailableResourceFinder, parser, metadataProcessor])
}
def reportsNotFoundArtifactResolveResult() {
@@ -61,14 +59,15 @@ class ExternalResourceResolverTest extends Specification {
def reportsFailedArtifactResolveResult() {
given:
- downloadIsFailing()
+ downloadIsFailing(new IOException("DOWNLOAD FAILURE"))
when:
resolver.resolve(artifact, result, moduleSource)
then:
- 1 * result.failed(_) >> { exception ->
- assert exception.message.toString() == "[Could not download artifact 'group:projectA:1.0 at jar']"
+ 1 * result.failed(_) >> { ArtifactResolveException exception ->
+ assert exception.message == "Could not download artifact 'group:module:version:classifier at ext'"
+ assert exception.cause.message == "DOWNLOAD FAILURE"
}
0 * result._
}
@@ -100,39 +99,19 @@ class ExternalResourceResolverTest extends Specification {
def artifactIsTimestampedSnapshotVersion() {
_ * moduleSource.timestampedVersion >> "1.0-20100101.120001-1"
- _ * artifact.getModuleRevisionId() >> artifactModuleRevisionId
- _ * artifactModuleRevisionId.organisation >> "group"
- _ * artifactModuleRevisionId.name >> "projectA"
- _ * artifactModuleRevisionId.revision >> "1.0"
- ModuleId moduleId = Mock()
- _ * moduleId.equals(_) >> true
- _ * artifactModuleRevisionId.moduleId >> moduleId
- _ * artifactModuleRevisionId.qualifiedExtraAttributes >> [:]
}
def artifactIsMissing() {
- 1 * downloadReport.getDownloadStatus() >> DownloadStatus.FAILED
- 1 * downloadReport.getDownloadDetails() >> ArtifactDownloadReport.MISSING_ARTIFACT;
+ resolver.download(_) >> null
}
- def downloadIsFailing() {
- 1 * downloadReport.getDownloadStatus() >> DownloadStatus.FAILED
- 1 * downloadReport.getDownloadDetails() >> "Broken Connection";
- 1 * downloadReport.getArtifact() >> artifact
- 1 * artifact.getModuleRevisionId() >> {
- ModuleRevisionId moduleRevisionId = Mock()
- 1 * moduleRevisionId.organisation >> "group"
- 1 * moduleRevisionId.name >> "projectA"
- 1 * moduleRevisionId.revision >> "1.0"
- 1 * artifact.ext >> "jar"
- moduleRevisionId
- };
+ def downloadIsFailing(IOException failure) {
+ resolver.download(_) >> {
+ throw failure
+ }
}
-
def artifactCanBeResolved() {
- 1 * downloadReport.getDownloadStatus() >> DownloadStatus.SUCCESSFUL
- 1 * downloadReport.getLocalFile() >> Mock(File);
-
+ resolver.download(_) >> downloadedFile
}
}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/repositories/resolver/MavenResolverTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/repositories/resolver/MavenResolverTest.groovy
index bde5c11..e19952a 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/repositories/resolver/MavenResolverTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/repositories/resolver/MavenResolverTest.groovy
@@ -16,6 +16,8 @@
package org.gradle.api.internal.artifacts.repositories.resolver
+import org.gradle.api.internal.artifacts.ModuleMetadataProcessor
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.MetaDataParser
import org.gradle.api.internal.artifacts.repositories.transport.RepositoryTransport
import org.gradle.api.internal.externalresource.local.LocallyAvailableResourceFinder
import org.gradle.api.internal.externalresource.transport.ExternalResourceRepository
@@ -28,6 +30,8 @@ class MavenResolverTest extends Specification {
def rootUri = URI.create("localhost:8081:/testrepo/")
def locallyAvailableResourceFinder = Mock(LocallyAvailableResourceFinder)
+ def parser = Mock(MetaDataParser)
+ def processor = Mock(ModuleMetadataProcessor)
def setup() {
repositoryTransport.getRepository() >> repository
@@ -36,7 +40,7 @@ class MavenResolverTest extends Specification {
@Unroll
def "setUseMavenMetaData '#value' adapts versionLister to #classname"() {
setup:
- MavenResolver testresolver = new MavenResolver("test maven resolver", rootUri, repositoryTransport, locallyAvailableResourceFinder)
+ MavenResolver testresolver = new MavenResolver("test maven resolver", rootUri, repositoryTransport, locallyAvailableResourceFinder, parser, processor)
when:
testresolver.setUseMavenMetadata(value)
then:
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/repositories/resolver/MavenVersionListerTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/repositories/resolver/MavenVersionListerTest.groovy
index 1538348..03293fb 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/repositories/resolver/MavenVersionListerTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/repositories/resolver/MavenVersionListerTest.groovy
@@ -18,37 +18,43 @@ package org.gradle.api.internal.artifacts.repositories.resolver
import org.apache.ivy.core.module.descriptor.DefaultArtifact
import org.apache.ivy.core.module.id.ModuleRevisionId
+import org.gradle.api.Action
+import org.gradle.api.internal.artifacts.DefaultModuleVersionSelector
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.ExactVersionMatcher
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.LatestVersionStrategy
import org.gradle.api.internal.externalresource.ExternalResource
import org.gradle.api.internal.externalresource.transport.ExternalResourceRepository
import org.gradle.api.internal.resource.ResourceException
import org.gradle.api.internal.resource.ResourceNotFoundException
+import org.gradle.internal.UncheckedException
import org.xml.sax.SAXParseException
import spock.lang.Specification
class MavenVersionListerTest extends Specification {
def repo = Mock(ExternalResourceRepository)
def moduleRevisionId = ModuleRevisionId.newInstance("org.acme", "testproject", "1.0")
+ def selector = DefaultModuleVersionSelector.newSelector(moduleRevisionId)
def artifact = new DefaultArtifact(moduleRevisionId, new Date(), "testproject", "jar", "jar")
def repository = Mock(ExternalResourceRepository)
def pattern = pattern("localhost:8081/testRepo/" + MavenPattern.M2_PATTERN)
String metaDataResource = 'localhost:8081/testRepo/org/acme/testproject/maven-metadata.xml'
- final org.gradle.api.internal.artifacts.repositories.resolver.MavenVersionLister lister = new org.gradle.api.internal.artifacts.repositories.resolver.MavenVersionLister(repository)
+ final MavenVersionLister lister = new MavenVersionLister(repository)
def "visit parses maven-metadata.xml"() {
ExternalResource resource = Mock()
when:
- def versionList = lister.getVersionList(moduleRevisionId)
+ def versionList = lister.getVersionList(selector)
versionList.visit(pattern, artifact)
then:
- versionList.versionStrings == ['1.1', '1.2'] as Set
+ sort(versionList).collect {it.version} == ['1.2', '1.1']
and:
1 * repository.getResource(metaDataResource) >> resource
- 1 * resource.openStream() >> new ByteArrayInputStream("""
+ 1 * resource.withContent(_) >> { Action action -> action.execute(new ByteArrayInputStream("""
<metadata>
<versioning>
<versions>
@@ -56,7 +62,8 @@ class MavenVersionListerTest extends Specification {
<version>1.2</version>
</versions>
</versioning>
-</metadata>""".bytes)
+</metadata>""".bytes))
+ }
1 * resource.close()
0 * repository._
0 * resource._
@@ -67,16 +74,19 @@ class MavenVersionListerTest extends Specification {
ExternalResource resource2 = Mock()
when:
- def versionList = lister.getVersionList(moduleRevisionId)
- versionList.visit(pattern("prefix1/" + MavenPattern.M2_PATTERN), artifact)
- versionList.visit(pattern("prefix2/" + MavenPattern.M2_PATTERN), artifact)
+ def versionList = lister.getVersionList(selector)
+ final pattern1 = pattern("prefix1/" + MavenPattern.M2_PATTERN)
+ versionList.visit(pattern1, artifact)
+ final pattern2 = pattern("prefix2/" + MavenPattern.M2_PATTERN)
+ versionList.visit(pattern2, artifact)
then:
- versionList.versionStrings == ['1.1', '1.2', '1.3'] as Set
+ sort(versionList).collect {it.version} == ['1.3', '1.2', '1.1']
+ sort(versionList).collect {it.pattern} == [pattern2, pattern1, pattern1]
and:
1 * repository.getResource('prefix1/org/acme/testproject/maven-metadata.xml') >> resource1
- 1 * resource1.openStream() >> new ByteArrayInputStream("""
+ 1 * resource1.withContent(_) >> { Action action -> action.execute(new ByteArrayInputStream("""
<metadata>
<versioning>
<versions>
@@ -84,9 +94,10 @@ class MavenVersionListerTest extends Specification {
<version>1.2</version>
</versions>
</versioning>
-</metadata>""".bytes)
+</metadata>""".bytes))
+ }
1 * repository.getResource('prefix2/org/acme/testproject/maven-metadata.xml') >> resource2
- 1 * resource2.openStream() >> new ByteArrayInputStream("""
+ 1 * resource2.withContent(_) >> { Action action -> action.execute(new ByteArrayInputStream("""
<metadata>
<versioning>
<versions>
@@ -94,23 +105,24 @@ class MavenVersionListerTest extends Specification {
<version>1.3</version>
</versions>
</versioning>
-</metadata>""".bytes)
+</metadata>""".bytes))
+ }
}
def "visit ignores duplicate patterns"() {
ExternalResource resource = Mock()
when:
- def versionList = lister.getVersionList(moduleRevisionId)
+ def versionList = lister.getVersionList(selector)
versionList.visit(pattern, artifact)
versionList.visit(pattern, artifact)
then:
- versionList.versionStrings == ['1.1', '1.2'] as Set
+ sort(versionList).collect {it.version} == ['1.2', '1.1']
and:
1 * repository.getResource(metaDataResource) >> resource
- 1 * resource.openStream() >> new ByteArrayInputStream("""
+ 1 * resource.withContent(_) >> { Action action -> action.execute(new ByteArrayInputStream("""
<metadata>
<versioning>
<versions>
@@ -118,15 +130,21 @@ class MavenVersionListerTest extends Specification {
<version>1.2</version>
</versions>
</versioning>
-</metadata>""".bytes)
+</metadata>""".bytes))
+ }
1 * resource.close()
0 * repository._
0 * resource._
}
+ private static List<VersionList.ListedVersion> sort(VersionList versionList) {
+ def latestStrategy = new LatestVersionStrategy(new ExactVersionMatcher())
+ versionList.sortLatestFirst(latestStrategy)
+ }
+
def "visit throws ResourceNotFoundException when maven-metadata not available"() {
when:
- def versionList = lister.getVersionList(moduleRevisionId)
+ def versionList = lister.getVersionList(selector)
versionList.visit(pattern, artifact)
then:
@@ -140,16 +158,17 @@ class MavenVersionListerTest extends Specification {
ExternalResource resource = Mock()
when:
- def versionList = lister.getVersionList(moduleRevisionId)
+ def versionList = lister.getVersionList(selector)
versionList.visit(pattern, artifact)
then:
ResourceException e = thrown()
e.message == "Unable to load Maven meta-data from $metaDataResource."
- e.cause instanceof SAXParseException
+ e.cause instanceof UncheckedException
+ e.cause.cause instanceof SAXParseException
1 * resource.close()
1 * repository.getResource(metaDataResource) >> resource;
- 1 * resource.openStream() >> new ByteArrayInputStream("yo".bytes)
+ 1 * resource.withContent(_) >> { Action action -> action.execute(new ByteArrayInputStream("yo".bytes)) }
0 * repository._
}
@@ -157,7 +176,7 @@ class MavenVersionListerTest extends Specification {
def failure = new IOException()
when:
- def versionList = lister.getVersionList(moduleRevisionId)
+ def versionList = lister.getVersionList(selector)
versionList.visit(pattern, artifact)
then:
@@ -169,6 +188,6 @@ class MavenVersionListerTest extends Specification {
}
def pattern(String pattern) {
- return new org.gradle.api.internal.artifacts.repositories.resolver.M2ResourcePattern(pattern)
+ return new M2ResourcePattern(pattern)
}
}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/repositories/resolver/ResourceVersionListerTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/repositories/resolver/ResourceVersionListerTest.groovy
index 42128df..92f0b39 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/repositories/resolver/ResourceVersionListerTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/repositories/resolver/ResourceVersionListerTest.groovy
@@ -15,9 +15,11 @@
*/
package org.gradle.api.internal.artifacts.repositories.resolver
-
import org.apache.ivy.core.module.descriptor.DefaultArtifact
import org.apache.ivy.core.module.id.ModuleRevisionId
+import org.gradle.api.internal.artifacts.DefaultModuleVersionSelector
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.ExactVersionMatcher
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.LatestVersionStrategy
import org.gradle.api.internal.externalresource.transport.ExternalResourceRepository
import org.gradle.api.internal.resource.ResourceException
import org.gradle.api.internal.resource.ResourceNotFoundException
@@ -28,12 +30,13 @@ class ResourceVersionListerTest extends Specification {
def repo = Mock(ExternalResourceRepository)
def moduleRevisionId = ModuleRevisionId.newInstance("org.acme", "proj1", "1.0")
+ def selector = DefaultModuleVersionSelector.newSelector(moduleRevisionId)
def artifact = new DefaultArtifact(moduleRevisionId, new Date(), "proj1", "jar", "jar")
- def org.gradle.api.internal.artifacts.repositories.resolver.ResourceVersionLister lister;
+ def ResourceVersionLister lister;
def setup() {
- lister = new org.gradle.api.internal.artifacts.repositories.resolver.ResourceVersionLister(repo)
+ lister = new ResourceVersionLister(repo)
}
def "visit propagates Exceptions as ResourceException"() {
@@ -43,7 +46,7 @@ class ResourceVersionListerTest extends Specification {
1 * repo.list(_) >> { throw failure }
when:
- def versionList = lister.getVersionList(moduleRevisionId)
+ def versionList = lister.getVersionList(selector)
versionList.visit(testPattern, artifact)
then:
@@ -57,7 +60,7 @@ class ResourceVersionListerTest extends Specification {
1 * repo.list(_) >> null
when:
- def versionList = lister.getVersionList(moduleRevisionId)
+ def versionList = lister.getVersionList(selector)
versionList.visit(pattern(testPattern), artifact)
then:
@@ -73,7 +76,7 @@ class ResourceVersionListerTest extends Specification {
1 * repo.list(_) >> []
when:
- def versionList = lister.getVersionList(moduleRevisionId)
+ def versionList = lister.getVersionList(selector)
versionList.visit(pattern("/some/[revision]"), artifact)
then:
@@ -83,11 +86,11 @@ class ResourceVersionListerTest extends Specification {
@Unroll
def "visit resolves versions from from pattern with '#testPattern'"() {
when:
- def versionList = lister.getVersionList(moduleRevisionId)
+ def versionList = lister.getVersionList(selector)
versionList.visit(pattern(testPattern), artifact)
then:
- versionList.versionStrings == ["1", "2.1", "a-version"] as Set
+ sort(versionList).collect { it.version } == ["2.1", "1", "a-version"]
and:
1 * repo.list(repoListingPath) >> repoResult
@@ -116,12 +119,15 @@ class ResourceVersionListerTest extends Specification {
def "visit builds union of versions"() {
when:
- def versionList = lister.getVersionList(moduleRevisionId)
- versionList.visit(pattern("/[revision]/[artifact]-[revision].[ext]"), artifact)
- versionList.visit(pattern("/[organisation]/[revision]/[artifact]-[revision].[ext]"), artifact)
+ def versionList = lister.getVersionList(selector)
+ def pattern1 = pattern("/[revision]/[artifact]-[revision].[ext]")
+ def pattern2 = pattern("/[organisation]/[revision]/[artifact]-[revision].[ext]")
+ versionList.visit(pattern1, artifact)
+ versionList.visit(pattern2, artifact)
then:
- versionList.versionStrings == ["1.2", "1.3", "1.4"] as Set
+ sort(versionList).collect { it.version } == ["1.4", "1.3", "1.2"]
+ sort(versionList).collect { it.pattern } == [pattern2, pattern1, pattern1]
and:
1 * repo.list("/") >> ["1.2", "1.3"]
@@ -131,21 +137,28 @@ class ResourceVersionListerTest extends Specification {
def "visit ignores duplicate patterns"() {
when:
- def versionList = lister.getVersionList(moduleRevisionId)
- versionList.visit(pattern("/a/[revision]/[artifact]-[revision].[ext]"), artifact)
+ def versionList = lister.getVersionList(selector)
+ final patternA = pattern("/a/[revision]/[artifact]-[revision].[ext]")
+ versionList.visit(patternA, artifact)
versionList.visit(pattern("/a/[revision]/[artifact]-[revision]"), artifact)
then:
- versionList.versionStrings == ["1.2", "1.3"] as Set
+ sort(versionList).collect { it.version } == ["1.3", "1.2"]
+ sort(versionList).collect { it.pattern } == [patternA, patternA]
and:
1 * repo.list("/a/") >> ["1.2", "1.3"]
0 * repo._
}
+ private static List<VersionList.ListedVersion> sort(VersionList versionList) {
+ def latestStrategy = new LatestVersionStrategy(new ExactVersionMatcher())
+ versionList.sortLatestFirst(latestStrategy)
+ }
+
def "visit substitutes non revision placeholders from pattern before hitting repository"() {
when:
- def versionList = lister.getVersionList(moduleRevisionId)
+ def versionList = lister.getVersionList(selector)
versionList.visit(pattern(inputPattern), artifact)
then:
@@ -167,7 +180,7 @@ class ResourceVersionListerTest extends Specification {
repo.list(_) >> repoResult
when:
- def versionList = lister.getVersionList(moduleRevisionId)
+ def versionList = lister.getVersionList(selector)
versionList.visit(pattern(testPattern), artifact)
then:
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/resolutioncache/DefaultArtifactResolutionCacheTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/resolutioncache/DefaultArtifactResolutionCacheTest.groovy
deleted file mode 100644
index f352560..0000000
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/resolutioncache/DefaultArtifactResolutionCacheTest.groovy
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.artifacts.resolutioncache
-
-import org.gradle.CacheUsage
-import org.gradle.api.internal.artifacts.ivyservice.DefaultCacheLockingManager
-import org.gradle.api.internal.externalresource.cached.DefaultCachedExternalResourceIndex
-import org.gradle.api.internal.externalresource.metadata.DefaultExternalResourceMetaData
-import org.gradle.cache.internal.CacheFactory
-import org.gradle.cache.internal.DefaultCacheRepository
-import org.gradle.internal.TimeProvider
-import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
-import org.gradle.testfixtures.internal.InMemoryCacheFactory
-import org.junit.Rule
-import spock.lang.Specification
-import spock.lang.Unroll
-
-class DefaultArtifactResolutionCacheTest extends Specification {
-
- @Rule TestNameTestDirectoryProvider tmp = new TestNameTestDirectoryProvider()
-
- Date time = new Date(0)
- TimeProvider timeProvider = new TimeProvider() {
- long getCurrentTime() { time.getTime() }
- }
-
- CacheFactory cacheFactory = new InMemoryCacheFactory()
- DefaultCacheRepository cacheRepository
- DefaultCacheLockingManager cacheLockingManager
-
- DefaultCachedExternalResourceIndex<String> index
-
- def setup() {
- cacheRepository = new DefaultCacheRepository(tmp.createDir('user-home'), tmp.createDir('project-cache'), CacheUsage.ON, cacheFactory)
- cacheLockingManager = new DefaultCacheLockingManager(cacheRepository)
- index = new DefaultCachedExternalResourceIndex(tmp.createFile("index"), String, timeProvider, cacheLockingManager)
- }
-
- @Unroll "stores entry - lastModified = #lastModified, artifactUrl = #artifactUrl"() {
- given:
- def key = "key"
- def artifactFile = tmp.createFile("artifact") << "content"
-
- when:
- index.store(key, artifactFile, new DefaultExternalResourceMetaData(artifactUrl, lastModified, 100, null, null))
-
- then:
- def cached = index.lookup(key)
-
- and:
- cached != null
- cached.cachedFile == artifactFile
- cached.externalResourceMetaData != null
- cached.externalResourceMetaData.lastModified == lastModified
- cached.externalResourceMetaData.location == artifactUrl
-
-
- where:
- lastModified | artifactUrl
- new Date() | null
- null | "abc"
- null | null
- new Date() | "abc"
- }
-
-}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/result/DefaultResolutionResultTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/result/DefaultResolutionResultTest.groovy
index 919106c..6f71085 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/result/DefaultResolutionResultTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/result/DefaultResolutionResultTest.groovy
@@ -19,11 +19,9 @@ package org.gradle.api.internal.artifacts.result
import spock.lang.Specification
import static org.gradle.api.internal.artifacts.DefaultModuleVersionSelector.newSelector
+import org.gradle.internal.Factory;
import static org.gradle.api.internal.artifacts.result.ResolutionResultDataBuilder.*
-/**
- * by Szczepan Faber, created at: 9/20/12
- */
class DefaultResolutionResultTest extends Specification {
def "provides all modules and dependencies including unresolved"() {
@@ -39,8 +37,8 @@ class DefaultResolutionResultTest extends Specification {
dep2.selected.addDependency(dep3).addDependency(dep4)
when:
- def deps = new DefaultResolutionResult(root).allDependencies
- def modules = new DefaultResolutionResult(root).allModuleVersions
+ def deps = new DefaultResolutionResult({root} as Factory).allDependencies
+ def modules = new DefaultResolutionResult({root} as Factory).allModuleVersions
then:
deps == [dep1, dep2, dep3, dep4] as Set
@@ -58,7 +56,7 @@ class DefaultResolutionResultTest extends Specification {
def root = newModule('root').addDependency(dep).addDependency(newDependency('dep2')).addDependency(dep3)
dep.selected.addDependency(dep3)
- def result = new DefaultResolutionResult(root)
+ def result = new DefaultResolutionResult({root} as Factory)
when:
def deps = []
@@ -82,8 +80,8 @@ class DefaultResolutionResultTest extends Specification {
dep1.selected.addDependency(new DefaultResolvedDependencyResult(newSelector('a', 'a', '1'), root, dep1.selected))
when:
- def deps = new DefaultResolutionResult(root).allDependencies
- def modules = new DefaultResolutionResult(root).allModuleVersions
+ def deps = new DefaultResolutionResult({root} as Factory).allDependencies
+ def modules = new DefaultResolutionResult({root} as Factory).allModuleVersions
then:
deps.size() == 2
@@ -98,7 +96,7 @@ class DefaultResolutionResultTest extends Specification {
def root = newModule('root').addDependency(dep1).addDependency(dep2)
when:
- def result = new DefaultResolutionResult(root)
+ def result = new DefaultResolutionResult({root} as Factory)
then:
result.allDependencies == [dep1, dep2] as Set
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/result/DefaultResolvedModuleVersionResultSpec.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/result/DefaultResolvedModuleVersionResultSpec.groovy
index 127622c..e19bc8c 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/result/DefaultResolvedModuleVersionResultSpec.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/artifacts/result/DefaultResolvedModuleVersionResultSpec.groovy
@@ -20,10 +20,6 @@ import spock.lang.Specification
import static org.gradle.api.internal.artifacts.result.ResolutionResultDataBuilder.*
-/**
- * Created: 10/08/2012
- * @author Szczepan Faber
- */
class DefaultResolvedModuleVersionResultSpec extends Specification {
def "mutating dependencies or dependents is harmless"() {
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/externalresource/CachedExternalResourceAdapterTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/externalresource/CachedExternalResourceAdapterTest.groovy
deleted file mode 100644
index 282e36b..0000000
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/externalresource/CachedExternalResourceAdapterTest.groovy
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.externalresource
-
-import org.gradle.api.internal.externalresource.cached.CachedExternalResource
-import org.gradle.api.internal.externalresource.cached.CachedExternalResourceAdapter
-import org.gradle.api.internal.externalresource.metadata.DefaultExternalResourceMetaData
-import org.gradle.api.internal.externalresource.transfer.ExternalResourceAccessor
-import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
-import org.gradle.util.hash.HashUtil
-import org.gradle.util.hash.HashValue
-import org.junit.Rule
-import spock.lang.Specification
-
-public class CachedExternalResourceAdapterTest extends Specification {
- @Rule final TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider()
-
- ExternalResourceAccessor accessor = Mock()
- CachedExternalResource cachedExternalResource = Mock()
- CachedExternalResourceAdapter cachedResource
- def origin = tmpDir.file('origin')
- def destination = tmpDir.file('destination')
- def download = tmpDir.file('download')
-
- def setup() {
- cachedExternalResource.cachedFile >> origin
- cachedExternalResource.sha1 >> { HashUtil.createHash(origin, "SHA1") }
- cachedResource = new CachedExternalResourceAdapter("resource-source", cachedExternalResource, accessor)
- }
-
- def "delegates to cached artifact"() {
- given:
- cachedExternalResource.contentLength >> 22
- cachedExternalResource.externalResourceMetaData >> new DefaultExternalResourceMetaData("url")
- cachedExternalResource.externalLastModifiedAsTimestamp >> 33
-
- expect:
- cachedResource.contentLength == 22
- cachedResource.lastModified == 33
- }
-
- def "will copy cache file to destination"() {
- given:
- origin << "some content"
-
- when:
- cachedResource.writeTo(destination)
-
- then:
- destination.assertIsCopyOf(origin)
- }
-
- def "will copy download resource if destination does not match original sha1 after copy"() {
- given:
- origin << "some content"
- download << "some other content"
- ExternalResource resource = Mock()
-
- when:
- cachedResource.writeTo(destination)
-
- then:
- cachedExternalResource.cachedFile >> origin
- cachedExternalResource.sha1 >> new HashValue("1234")
-
- and:
- accessor.getResource("resource-source") >> resource
- resource.writeTo(destination)
- }
-}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/externalresource/cached/CachedExternalResourceAdapterTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/externalresource/cached/CachedExternalResourceAdapterTest.groovy
new file mode 100644
index 0000000..53f0ee9
--- /dev/null
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/externalresource/cached/CachedExternalResourceAdapterTest.groovy
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.externalresource.cached
+
+import org.gradle.api.internal.externalresource.ExternalResource
+import org.gradle.api.internal.externalresource.metadata.DefaultExternalResourceMetaData
+import org.gradle.api.internal.externalresource.transfer.ExternalResourceAccessor
+import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
+import org.gradle.util.hash.HashUtil
+import org.gradle.util.hash.HashValue
+import org.junit.Rule
+import spock.lang.Specification
+
+public class CachedExternalResourceAdapterTest extends Specification {
+ @Rule final TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider()
+
+ ExternalResourceAccessor accessor = Mock()
+ CachedExternalResource cachedExternalResource = Mock()
+ CachedExternalResourceAdapter cachedResource
+ def origin = tmpDir.file('origin')
+ def destination = tmpDir.file('destination')
+ def download = tmpDir.file('download')
+
+ def setup() {
+ cachedExternalResource.cachedFile >> origin
+ cachedExternalResource.sha1 >> { HashUtil.createHash(origin, "SHA1") }
+ cachedResource = new CachedExternalResourceAdapter("resource-source", cachedExternalResource, accessor)
+ }
+
+ def "delegates to cached artifact"() {
+ given:
+ cachedExternalResource.contentLength >> 22
+ cachedExternalResource.externalResourceMetaData >> new DefaultExternalResourceMetaData("url")
+ cachedExternalResource.externalLastModifiedAsTimestamp >> 33
+
+ expect:
+ cachedResource.contentLength == 22
+ cachedResource.lastModified == 33
+ }
+
+ def "will copy cache file to destination"() {
+ given:
+ origin << "some content"
+
+ when:
+ cachedResource.writeTo(destination)
+
+ then:
+ destination.assertIsCopyOf(origin)
+ }
+
+ def "will copy download resource if destination does not match original sha1 after copy"() {
+ given:
+ origin << "some content"
+ download << "some other content"
+ ExternalResource resource = Mock()
+
+ when:
+ cachedResource.writeTo(destination)
+
+ then:
+ cachedExternalResource.cachedFile >> origin
+ cachedExternalResource.sha1 >> new HashValue("1234")
+
+ and:
+ accessor.getResource("resource-source") >> resource
+ resource.writeTo(destination)
+ }
+}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/externalresource/cached/DefaultArtifactResolutionCacheTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/externalresource/cached/DefaultArtifactResolutionCacheTest.groovy
new file mode 100644
index 0000000..87666aa
--- /dev/null
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/externalresource/cached/DefaultArtifactResolutionCacheTest.groovy
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.externalresource.cached
+
+import org.gradle.CacheUsage
+import org.gradle.api.internal.artifacts.ivyservice.DefaultCacheLockingManager
+import org.gradle.api.internal.externalresource.metadata.DefaultExternalResourceMetaData
+import org.gradle.cache.internal.CacheFactory
+import org.gradle.cache.internal.DefaultCacheRepository
+import org.gradle.internal.TimeProvider
+import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
+import org.gradle.testfixtures.internal.InMemoryCacheFactory
+import org.junit.Rule
+import spock.lang.Specification
+import spock.lang.Unroll
+
+class DefaultArtifactResolutionCacheTest extends Specification {
+
+ @Rule TestNameTestDirectoryProvider tmp = new TestNameTestDirectoryProvider()
+
+ Date time = new Date(0)
+ TimeProvider timeProvider = new TimeProvider() {
+ long getCurrentTime() { time.getTime() }
+ }
+
+ CacheFactory cacheFactory = new InMemoryCacheFactory()
+ DefaultCacheRepository cacheRepository
+ DefaultCacheLockingManager cacheLockingManager
+
+ DefaultCachedExternalResourceIndex<String> index
+
+ def setup() {
+ cacheRepository = new DefaultCacheRepository(tmp.createDir('user-home'), tmp.createDir('project-cache'), CacheUsage.ON, cacheFactory)
+ cacheLockingManager = new DefaultCacheLockingManager(cacheRepository)
+ index = new DefaultCachedExternalResourceIndex(tmp.createFile("index"), String, timeProvider, cacheLockingManager)
+ }
+
+ @Unroll "stores entry - lastModified = #lastModified, artifactUrl = #artifactUrl"() {
+ given:
+ def key = "key"
+ def artifactFile = tmp.createFile("artifact") << "content"
+
+ when:
+ index.store(key, artifactFile, new DefaultExternalResourceMetaData(artifactUrl, lastModified, 100, null, null))
+
+ then:
+ def cached = index.lookup(key)
+
+ and:
+ cached != null
+ cached.cachedFile == artifactFile
+ cached.externalResourceMetaData != null
+ cached.externalResourceMetaData.lastModified == lastModified
+ cached.externalResourceMetaData.location == artifactUrl
+
+
+ where:
+ lastModified | artifactUrl
+ new Date() | null
+ null | "abc"
+ null | null
+ new Date() | "abc"
+ }
+
+}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/externalresource/ivy/ArtifactAtRepositoryCachedArtifactIndexTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/externalresource/ivy/ArtifactAtRepositoryCachedArtifactIndexTest.groovy
index 7af9d1b..41d3eb4 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/externalresource/ivy/ArtifactAtRepositoryCachedArtifactIndexTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/externalresource/ivy/ArtifactAtRepositoryCachedArtifactIndexTest.groovy
@@ -16,8 +16,8 @@
package org.gradle.api.internal.externalresource.ivy
+import org.gradle.api.artifacts.ArtifactIdentifier
import org.gradle.api.internal.artifacts.ivyservice.CacheLockingManager
-import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.CachingModuleVersionRepository
import org.gradle.api.internal.externalresource.cached.CachedArtifact
import org.gradle.api.internal.externalresource.metadata.ExternalResourceMetaData
import org.gradle.cache.PersistentIndexedCache
@@ -32,8 +32,6 @@ class ArtifactAtRepositoryCachedArtifactIndexTest extends Specification {
TimeProvider timeProvider = Mock()
ArtifactAtRepositoryKey key = Mock()
ExternalResourceMetaData metaData = Mock()
- CachingModuleVersionRepository moduleVersionRepository = Mock()
-
@Rule TestNameTestDirectoryProvider folder = new TestNameTestDirectoryProvider();
PersistentIndexedCache persistentIndexedCache = Mock()
@@ -67,9 +65,8 @@ class ArtifactAtRepositoryCachedArtifactIndexTest extends Specification {
def "stored artifact is put into persistentIndexedCache"() {
setup:
- 1 * moduleVersionRepository.getId() >> "RepoID"
1 * cacheLockingManager.createCache(persistentCacheFile, _, _) >> persistentIndexedCache
- def key = new ArtifactAtRepositoryKey(moduleVersionRepository, "artifactId");
+ def key = new ArtifactAtRepositoryKey("RepoID", Stub(ArtifactIdentifier));
def testFile = folder.createFile("aTestFile");
when:
index.store(key, testFile, BigInteger.TEN)
@@ -122,10 +119,9 @@ class ArtifactAtRepositoryCachedArtifactIndexTest extends Specification {
}
def createEntryInPersistentCache() {
- 1 * moduleVersionRepository.getId() >> "RepoID"
1 * cacheLockingManager.createCache(persistentCacheFile, _, _) >> persistentIndexedCache
1 * cacheLockingManager.useCache("lookup from artifact resolution cache \'cacheFile\'", _) >> {descr, factory -> factory.create()}
- def key = new ArtifactAtRepositoryKey(moduleVersionRepository, "artifactId");
+ def key = new ArtifactAtRepositoryKey("RepoID", Stub(ArtifactIdentifier));
1 * persistentIndexedCache.get(key) >> cachedArtifact;
key
}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/externalresource/local/CompositeLocallyAvailableResourceFinderTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/externalresource/local/CompositeLocallyAvailableResourceFinderTest.groovy
index cb6f7c1..20fedef 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/externalresource/local/CompositeLocallyAvailableResourceFinderTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/externalresource/local/CompositeLocallyAvailableResourceFinderTest.groovy
@@ -16,6 +16,7 @@
package org.gradle.api.internal.externalresource.local
+import org.gradle.internal.resource.local.LocallyAvailableResource
import spock.lang.Specification
import org.gradle.util.hash.HashUtil
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/externalresource/local/DefaultLocallyAvailableResourceTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/externalresource/local/DefaultLocallyAvailableResourceTest.groovy
deleted file mode 100644
index 3db4adc..0000000
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/externalresource/local/DefaultLocallyAvailableResourceTest.groovy
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.externalresource.local
-
-import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
-import org.gradle.util.hash.HashUtil
-import org.junit.Rule
-import spock.lang.Specification
-
-public class DefaultLocallyAvailableResourceTest extends Specification {
- @Rule final TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider()
-
- def "uses value from origin file"() {
- given:
- def origin = tmpDir.file("origin")
- origin << "some text"
-
- when:
- def DefaultLocallyAvailableResource resource = new DefaultLocallyAvailableResource(origin)
-
- then:
- resource.sha1 == HashUtil.createHash(origin, 'SHA1')
- resource.contentLength == origin.length()
- resource.lastModified == origin.lastModified()
- }
-
- def "sha1 content length and last modified do not change when file is subsequently modified"() {
- given:
- def origin = tmpDir.file("origin")
- origin << "some text"
-
-
- when:
- def DefaultLocallyAvailableResource resource = new DefaultLocallyAvailableResource(origin)
- def originalSha1 = resource.sha1
- def originalContentLength = resource.contentLength
- def originalLastModified = resource.lastModified
-
- and:
- origin << "some more text"
- origin.setLastModified(11)
-
- then:
- resource.sha1 != HashUtil.createHash(origin, 'SHA1')
- resource.contentLength != origin.length()
- resource.lastModified != origin.lastModified()
-
- and:
- resource.sha1 == originalSha1
- resource.contentLength == originalContentLength
- resource.lastModified == originalLastModified
- }
-}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/externalresource/transfer/DefaultCacheAwareExternalResourceAccessorTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/externalresource/transfer/DefaultCacheAwareExternalResourceAccessorTest.groovy
index 13312f4..ecab39a 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/externalresource/transfer/DefaultCacheAwareExternalResourceAccessorTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/externalresource/transfer/DefaultCacheAwareExternalResourceAccessorTest.groovy
@@ -22,8 +22,8 @@ import org.gradle.api.internal.externalresource.local.LocallyAvailableResourceCa
import org.gradle.api.internal.externalresource.cached.CachedExternalResource
import org.gradle.api.internal.externalresource.metadata.ExternalResourceMetaData
import org.gradle.util.hash.HashValue
-import org.gradle.api.internal.externalresource.local.LocallyAvailableResource
-import org.gradle.api.internal.externalresource.LocallyAvailableExternalResource
+import org.gradle.internal.resource.local.LocallyAvailableResource
+import org.gradle.api.internal.externalresource.DefaultLocallyAvailableExternalResource
class DefaultCacheAwareExternalResourceAccessorTest extends Specification {
final accessor = Mock(ExternalResourceAccessor)
@@ -54,6 +54,6 @@ class DefaultCacheAwareExternalResourceAccessorTest extends Specification {
1 * localCandidates.findByHashValue(sha1) >> localCandidate
and:
- foundResource instanceof LocallyAvailableExternalResource
+ foundResource instanceof DefaultLocallyAvailableExternalResource
}
}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/externalresource/transfer/ProgressLoggingExternalResourceAccessorTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/externalresource/transfer/ProgressLoggingExternalResourceAccessorTest.groovy
index 259dcc3..e5168cd 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/externalresource/transfer/ProgressLoggingExternalResourceAccessorTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/externalresource/transfer/ProgressLoggingExternalResourceAccessorTest.groovy
@@ -106,19 +106,6 @@ class ProgressLoggingExternalResourceAccessorTest extends Specification {
then:
1 * externalResource."$method"()
where:
- method << ['close', 'getMetaData', 'getName', 'getLastModified', 'getContentLength', 'isLocal', 'openStream']
- }
-
- @Unroll
- def "ProgressLoggingExternalResource #method to delegate ExternalResource"() {
- when:
- accessor.getResource("location") >> externalResource
- def plExternalResource = progressLoggerAccessor.getResource("location")
- and:
- plExternalResource."$method"()
- then:
- 1 * externalResource."$method"()
- where:
- method << ['close', 'getMetaData', 'getName', 'getLastModified', 'getContentLength', 'isLocal', 'openStream', 'toString']
+ method << ['close', 'getMetaData', 'getName', 'getLastModified', 'getContentLength', 'isLocal']
}
}
\ No newline at end of file
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/externalresource/transport/http/ApacheDirectoryListingParserTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/externalresource/transport/http/ApacheDirectoryListingParserTest.groovy
index d8eb05f..62ef640 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/externalresource/transport/http/ApacheDirectoryListingParserTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/externalresource/transport/http/ApacheDirectoryListingParserTest.groovy
@@ -33,7 +33,7 @@ class ApacheDirectoryListingParserTest extends Specification {
def "parse returns empty List if no link can be found"() {
expect:
- List urls = parser.parse(baseUrl, "<html>no link here</html>".bytes, CONTENT_TYPE)
+ List urls = parser.parse(baseUrl, new ByteArrayInputStream("<html>no link here</html>".bytes), CONTENT_TYPE)
assertNotNull(urls)
urls.isEmpty()
}
@@ -55,7 +55,7 @@ class ApacheDirectoryListingParserTest extends Specification {
<a href="directory3">directory3</a>
<a href="directory4"/>"""
expect:
- def uris = parser.parse(baseUrl, html.bytes, CONTENT_TYPE)
+ def uris = parser.parse(baseUrl, new ByteArrayInputStream(html.bytes), CONTENT_TYPE)
assertNotNull(uris)
uris.collect {it.toString()} == ["http://testrepo/directory1", "http://testrepo/directory2", "http://testrepo/directory3", "http://testrepo/directory4"]
}
@@ -65,7 +65,7 @@ class ApacheDirectoryListingParserTest extends Specification {
<a href="directory1">directory1</a>
<a href="directory2">directory2</a>"""
when:
- parser.parse(baseUrl, html.bytes, contentType)
+ parser.parse(baseUrl, new ByteArrayInputStream(html.bytes), contentType)
then:
thrown(ResourceException)
where:
@@ -80,7 +80,7 @@ class ApacheDirectoryListingParserTest extends Specification {
assert !Arrays.equals(encodedHtml, html.getBytes("utf-8"))
expect:
- def uris = parser.parse(baseUrl, encodedHtml, 'text/html;charset=ISO-8859-1')
+ def uris = parser.parse(baseUrl, new ByteArrayInputStream(encodedHtml), 'text/html;charset=ISO-8859-1')
uris.collect {it.toString()} == ["http://testrepo/\u00c1\u00d2"]
}
@@ -91,14 +91,14 @@ class ApacheDirectoryListingParserTest extends Specification {
def encodedHtml = html.getBytes('utf-8')
expect:
- def uris = parser.parse(baseUrl, encodedHtml, 'text/html')
+ def uris = parser.parse(baseUrl, new ByteArrayInputStream(encodedHtml), 'text/html')
uris.collect {it.toString()} == ["http://testrepo/\u0321\u0322"]
}
@Unroll
def "parse ignores #descr"() {
expect:
- parser.parse(baseUrl, "<a href=\"${href}\">link</a>".toString().bytes, CONTENT_TYPE).isEmpty()
+ parser.parse(baseUrl, new ByteArrayInputStream("<a href=\"${href}\">link</a>".toString().bytes), CONTENT_TYPE).isEmpty()
where:
href | descr
"http://anothertestrepo/" | "URLs which aren't children of base URL"
@@ -115,7 +115,7 @@ class ApacheDirectoryListingParserTest extends Specification {
def "parseLink handles #urlDescr"() {
def listingParser = new ApacheDirectoryListingParser()
expect:
- def foundURIs = listingParser.parse(URI.create(baseUri), "<a href=\"${href}\">link</a>".toString().bytes, CONTENT_TYPE)
+ def foundURIs = listingParser.parse(URI.create(baseUri), new ByteArrayInputStream("<a href=\"${href}\">link</a>".toString().bytes), CONTENT_TYPE)
!foundURIs.isEmpty()
foundURIs.collect {it.toString()} == ["${baseUri}/directory1"]
where:
@@ -137,7 +137,7 @@ class ApacheDirectoryListingParserTest extends Specification {
setup:
def byte[] content = resources.getResource("${repoType}_dirlisting.html").bytes
expect:
- List<URI> urls = new ApacheDirectoryListingParser().parse(new URI(artifactRootURI), content, CONTENT_TYPE)
+ List<URI> urls = new ApacheDirectoryListingParser().parse(new URI(artifactRootURI), new ByteArrayInputStream(content), CONTENT_TYPE)
urls.collect {it.toString()} as Set == ["${artifactRootURI}3.7/",
"${artifactRootURI}3.8/",
"${artifactRootURI}3.8.1/",
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/externalresource/transport/http/HttpResourceListerTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/externalresource/transport/http/HttpResourceListerTest.groovy
index 147bdd2..e68c664 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/externalresource/transport/http/HttpResourceListerTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/externalresource/transport/http/HttpResourceListerTest.groovy
@@ -16,6 +16,7 @@
package org.gradle.api.internal.externalresource.transport.http
+import org.gradle.api.Transformer
import spock.lang.Specification
class HttpResourceListerTest extends Specification {
@@ -30,7 +31,7 @@ class HttpResourceListerTest extends Specification {
when:
lister.list("http://testrepo/")
then:
- 1 * externalResource.writeTo(_) >> {OutputStream outputStream -> outputStream.write("<a href='child'/>".bytes)}
+ 1 * externalResource.withContent(_) >> {Transformer action -> return action.transform(new ByteArrayInputStream("<a href='child'/>".bytes))}
1 * externalResource.getContentType() >> "text/html"
1 * externalResource.close()
}
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/notations/DependencyMapNotationParserTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/notations/DependencyMapNotationParserTest.groovy
index c5b2231..8d71ab8 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/notations/DependencyMapNotationParserTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/notations/DependencyMapNotationParserTest.groovy
@@ -14,17 +14,13 @@
* limitations under the License.
*/
-package org.gradle.api.internal.notations;
-
+package org.gradle.api.internal.notations
import org.gradle.api.artifacts.DependencyArtifact
-import org.gradle.internal.reflect.DirectInstantiator
import org.gradle.api.internal.artifacts.dependencies.DefaultExternalModuleDependency
+import org.gradle.internal.reflect.DirectInstantiator
import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 11/10/11
- */
public class DependencyMapNotationParserTest extends Specification {
def parser = new DependencyMapNotationParser<DefaultExternalModuleDependency>(new DirectInstantiator(), DefaultExternalModuleDependency.class);
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/notations/DependencyNotationParserTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/notations/DependencyNotationParserTest.groovy
index 2fdda25..7a01230 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/notations/DependencyNotationParserTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/notations/DependencyNotationParserTest.groovy
@@ -21,9 +21,6 @@ import org.gradle.api.GradleException
import org.gradle.api.internal.notations.api.NotationParser
import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 11/9/11
- */
public class DependencyNotationParserTest extends Specification {
def notationParser = Mock(NotationParser)
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/notations/DependencyStringNotationParserTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/notations/DependencyStringNotationParserTest.groovy
index 387701c..a6c99b5 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/notations/DependencyStringNotationParserTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/notations/DependencyStringNotationParserTest.groovy
@@ -14,19 +14,15 @@
* limitations under the License.
*/
-package org.gradle.api.internal.notations;
-
+package org.gradle.api.internal.notations
import org.gradle.api.artifacts.DependencyArtifact
-import org.gradle.internal.reflect.DirectInstantiator
import org.gradle.api.internal.artifacts.dependencies.DefaultClientModule
import org.gradle.api.internal.artifacts.dependencies.DefaultExternalModuleDependency
-import org.gradle.util.HelperUtil
+import org.gradle.internal.reflect.DirectInstantiator
+import org.gradle.util.TestUtil
import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 11/10/11
- */
public class DependencyStringNotationParserTest extends Specification {
def parser = new DependencyStringNotationParser(new DirectInstantiator(), DefaultExternalModuleDependency.class);
@@ -85,7 +81,7 @@ public class DependencyStringNotationParserTest extends Specification {
def "with 3-element GString"() {
when:
- def gstring = HelperUtil.createScript("descriptor = 'org.gradle:gradle-core:1.0'; \"\$descriptor\"").run()
+ def gstring = TestUtil.createScript("descriptor = 'org.gradle:gradle-core:1.0'; \"\$descriptor\"").run()
def d = parser.parseNotation(gstring);
then:
diff --git a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/notations/ProjectDependencyFactoryTest.groovy b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/notations/ProjectDependencyFactoryTest.groovy
index 7b877c6..32a6d94 100644
--- a/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/notations/ProjectDependencyFactoryTest.groovy
+++ b/subprojects/core-impl/src/test/groovy/org/gradle/api/internal/notations/ProjectDependencyFactoryTest.groovy
@@ -25,9 +25,6 @@ import org.gradle.internal.reflect.DirectInstantiator
import org.gradle.util.GUtil
import spock.lang.Specification
-/**
- * @author Hans Dockter
- */
public class ProjectDependencyFactoryTest extends Specification {
def projectDummy = Mock(ProjectInternal)
diff --git a/subprojects/core-impl/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/test-bad-confs.xml b/subprojects/core-impl/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/test-bad-confs.xml
deleted file mode 100644
index 7287882..0000000
--- a/subprojects/core-impl/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/test-bad-confs.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<!--
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- 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.
--->
-<ivy-module version="1.0">
- <info organisation="myorg"
- module="mymodule"
- status="integration"
- />
- <configurations>
- <conf name="A" extends="invalidConf"/>
- </configurations>
-</ivy-module>
diff --git a/subprojects/core-impl/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/test-cyclic-confs1.xml b/subprojects/core-impl/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/test-cyclic-confs1.xml
deleted file mode 100644
index 3890369..0000000
--- a/subprojects/core-impl/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/test-cyclic-confs1.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- 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.
--->
-<ivy-module version="1.0">
- <info organisation="myorg"
- module="mymodule"
- status="integration"
- />
- <configurations>
- <conf name="A" extends="B"/>
- <conf name="B" extends="A"/>
- </configurations>
-</ivy-module>
diff --git a/subprojects/core-impl/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/test-empty-dependencies.xml b/subprojects/core-impl/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/test-empty-dependencies.xml
deleted file mode 100644
index 3240dc4..0000000
--- a/subprojects/core-impl/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/test-empty-dependencies.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- 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.
--->
-<ivy-module version="1.0">
- <info organisation="myorg"
- module="mymodule"
- revision="myrev"
- status="integration"
- publication="20041101110000"
- />
- <dependencies>
- </dependencies>
-</ivy-module>
diff --git a/subprojects/core-impl/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/test-full.xml b/subprojects/core-impl/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/test-full.xml
index dfb4a55..dbc6812 100644
--- a/subprojects/core-impl/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/test-full.xml
+++ b/subprojects/core-impl/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/test-full.xml
@@ -26,12 +26,10 @@
e:attr1="value1">
<license name="MyLicense" url="http://www.my.org/mymodule/mylicense.html"/>
- <repository name="ivyrep" url="http://www.jayasoft.fr/org/ivyrep/" pattern="[organisation]/[module]/ivy-[revision].xml" ivys="true" artifacts="false"/>
-
<ivyauthor name="jayasoft" url="http://www.jayasoft.org/"/>
<ivyauthor name="myorg" url="http://www.myorg.org/"/>
+ <repository name="ivyrep" url="http://www.jayasoft.fr/org/ivyrep/" pattern="[organisation]/[module]/ivy-[revision].xml" ivys="true" artifacts="false"/>
-
<description homepage="http://www.my.org/mymodule/">
This module is <b>great</b> !<br/>
You can use it especially with myconf1 and myconf2, and myconf4 is not too bad too.
diff --git a/subprojects/core-impl/src/testFixtures/groovy/org/gradle/api/internal/artifacts/result/ResolutionResultDataBuilder.groovy b/subprojects/core-impl/src/testFixtures/groovy/org/gradle/api/internal/artifacts/result/ResolutionResultDataBuilder.groovy
index da4afe7..d8138d4 100644
--- a/subprojects/core-impl/src/testFixtures/groovy/org/gradle/api/internal/artifacts/result/ResolutionResultDataBuilder.groovy
+++ b/subprojects/core-impl/src/testFixtures/groovy/org/gradle/api/internal/artifacts/result/ResolutionResultDataBuilder.groovy
@@ -17,15 +17,12 @@
package org.gradle.api.internal.artifacts.result
import org.gradle.api.artifacts.result.ModuleVersionSelectionReason
+import org.gradle.api.internal.artifacts.ivyservice.ModuleVersionResolveException
import org.gradle.api.internal.artifacts.ivyservice.resolveengine.result.VersionSelectionReasons
import static org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier.newId
import static org.gradle.api.internal.artifacts.DefaultModuleVersionSelector.newSelector
-import org.gradle.api.internal.artifacts.ivyservice.ModuleVersionResolveException
-/**
- * by Szczepan Faber, created at: 10/2/12
- */
class ResolutionResultDataBuilder {
static DefaultResolvedDependencyResult newDependency(String group='a', String module='a', String version='1', String selectedVersion='1') {
diff --git a/subprojects/core/core.gradle b/subprojects/core/core.gradle
index fd5a202..bcfa2b5 100755
--- a/subprojects/core/core.gradle
+++ b/subprojects/core/core.gradle
@@ -21,13 +21,14 @@ configurations {
}
dependencies {
- groovy libraries.groovy
+ compile libraries.groovy
publishCompile libraries.slf4j_api
publishCompile project(":baseServices")
publishCompile project(":messaging")
compile project(":baseServicesGroovy")
+ compile project(":resources")
compile libraries.asm
compile libraries.ant
compile libraries.commons_collections
@@ -45,6 +46,8 @@ dependencies {
compile project(":cli")
compile project(":native")
+ runtime project(":docs")
+
runtime libraries.log4j_to_slf4j
runtime libraries.jcl_to_slf4j
@@ -64,6 +67,7 @@ dependencies {
}
useTestFixtures()
+useTestFixtures(project: ":messaging")
[compileGroovy, compileTestGroovy]*.groovyOptions*.fork(memoryInitialSize: '128M', memoryMaximumSize: '1G')
diff --git a/subprojects/core/src/integTest/groovy/org/gradle/DeprecationHandlingIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/DeprecationHandlingIntegrationTest.groovy
new file mode 100644
index 0000000..031ee8d
--- /dev/null
+++ b/subprojects/core/src/integTest/groovy/org/gradle/DeprecationHandlingIntegrationTest.groovy
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle
+
+import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+
+class DeprecationHandlingIntegrationTest extends AbstractIntegrationSpec {
+ def "reports first usage of deprecated feature from a build script"() {
+ buildFile << """
+
+someFeature()
+someFeature()
+task broken(type: DeprecatedTask) {
+ otherFeature()
+}
+
+repositories {
+ mavenRepo url: 'build/repo'
+}
+
+def someFeature() {
+ DeprecationLogger.nagUserOfDiscontinuedMethod("someFeature()")
+}
+
+class DeprecatedTask extends DefaultTask {
+ def otherFeature() {
+ DeprecationLogger.nagUserOfDiscontinuedMethod("otherFeature()")
+ }
+}
+"""
+
+ when:
+ executer.withDeprecationChecksDisabled()
+ run()
+
+ then:
+ output.contains("Build file '$buildFile': line 3")
+ output.count("The someFeature() method has been deprecated") == 1
+ output.contains("Build file '$buildFile': line 6")
+ output.count("The otherFeature() method has been deprecated") == 1
+ output.contains("Build file '$buildFile': line 10")
+ output.count("The RepositoryHandler.mavenRepo() method has been deprecated") == 1
+
+ // Run again to ensure logging is reset
+ when:
+ executer.withDeprecationChecksDisabled()
+ run()
+
+ then:
+ output.contains("Build file '$buildFile': line 3")
+ output.count("The someFeature() method has been deprecated") == 1
+ output.contains("Build file '$buildFile': line 6")
+ output.count("The otherFeature() method has been deprecated") == 1
+ output.contains("Build file '$buildFile': line 10")
+ output.count("The RepositoryHandler.mavenRepo() method has been deprecated") == 1
+
+ // Not shown at quiet level
+ when:
+ executer.withArgument("--quiet")
+ run()
+
+ then:
+ output.count("The someFeature() method has been deprecated") == 0
+ output.count("The otherFeature() method has been deprecated") == 0
+ output.count("The RepositoryHandler.mavenRepo() method has been deprecated") == 0
+ errorOutput == ""
+ }
+
+ def "reports usage of deprecated feature from an init script"() {
+ def initScript = file("init.gradle") << """
+allprojects {
+ someFeature()
+}
+
+def someFeature() {
+ DeprecationLogger.nagUserOfDiscontinuedMethod("someFeature()")
+}
+
+"""
+
+ when:
+ executer.withDeprecationChecksDisabled().usingInitScript(initScript)
+ run()
+
+ then:
+ output.contains("Initialization script '$initScript': line 3")
+ output.count("The someFeature() method has been deprecated") == 1
+ errorOutput == ""
+ }
+
+ def "reports usage of deprecated feature from an applied script"() {
+ def script = file("project.gradle") << """
+
+def someFeature() {
+ DeprecationLogger.nagUserOfDiscontinuedMethod("someFeature()")
+}
+
+someFeature()
+"""
+ buildFile << "allprojects { apply from: 'project.gradle' }"
+
+ when:
+ executer.withDeprecationChecksDisabled()
+ run()
+
+ then:
+ output.contains("Script '$script': line 7")
+ output.count("The someFeature() method has been deprecated") == 1
+ errorOutput == ""
+ }
+}
diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/ApplyPluginIntegSpec.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/ApplyPluginIntegSpec.groovy
new file mode 100644
index 0000000..0762af7
--- /dev/null
+++ b/subprojects/core/src/integTest/groovy/org/gradle/api/ApplyPluginIntegSpec.groovy
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api
+
+import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+import org.gradle.integtests.fixtures.executer.UnexpectedBuildFailure
+import org.gradle.testfixtures.ProjectBuilder
+import spock.lang.FailsWith
+import spock.lang.Issue
+
+// TODO: This needs a better home - Possibly in the test kit package in the future
+class ApplyPluginIntegSpec extends AbstractIntegrationSpec {
+
+ @Issue("GRADLE-2358")
+ @FailsWith(UnexpectedBuildFailure) // Test is currently failing
+ def "can reference plugin by id in unitest"() {
+
+ given:
+ file("src/main/groovy/org/acme/TestPlugin.groovy") << """
+ package com.acme
+ import org.gradle.api.*
+
+ class TestPlugin implements Plugin<Project> {
+ void apply(Project project) {
+ println "testplugin applied"
+ }
+ }
+ """
+
+ file("src/main/resources/META-INF/gradle-plugins/testplugin.properties") << "implementation-class=org.acme.TestPlugin"
+
+ file("src/test/groovy/org/acme/TestPluginSpec.groovy") << """
+ import spock.lang.Specification
+ import ${ProjectBuilder.name}
+ import ${Project.name}
+ import com.acme.TestPlugin
+
+ class TestPluginSpec extends Specification {
+ def "can apply plugin by id"() {
+ when:
+ Project project = ProjectBuilder.builder().build()
+ project.apply(plugin: "testplugin")
+
+ then:
+ project.plugins.withType(TestPlugin).size() == 1
+ }
+ }
+ """
+
+ and:
+ buildFile << '''
+ apply plugin: 'groovy'
+
+ repositories {
+ mavenCentral()
+ }
+
+ dependencies {
+ compile gradleApi()
+ compile localGroovy()
+ compile "org.spockframework:spock-core:0.7-groovy-1.8", {
+ exclude module: "groovy-all"
+ }
+ }
+ '''
+
+ expect:
+ succeeds("test")
+ }
+}
\ No newline at end of file
diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/BuildScriptErrorIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/BuildScriptErrorIntegrationTest.groovy
new file mode 100755
index 0000000..f4df3c8
--- /dev/null
+++ b/subprojects/core/src/integTest/groovy/org/gradle/api/BuildScriptErrorIntegrationTest.groovy
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api
+import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+
+import static org.hamcrest.Matchers.containsString
+
+public class BuildScriptErrorIntegrationTest extends AbstractIntegrationSpec {
+
+ def "setup"() {
+ settingsFile << "rootProject.name = 'ProjectError'"
+ }
+
+ def "produces reasonable error message when buildFile evaluation fails with Groovy Exception"() {
+ buildFile << """
+ createTakk('do-stuff')
+"""
+ when:
+ fails()
+
+ then:
+ failure.assertHasDescription("A problem occurred evaluating root project 'ProjectError'.")
+ .assertHasCause("Could not find method createTakk() for arguments [do-stuff] on root project 'ProjectError")
+ .assertHasFileName("Build file '$buildFile'")
+ .assertHasLineNumber(2)
+ }
+
+ def "produces reasonable error message when buildFile evaluation fails on script compilation"() {
+ buildFile << """
+ // a comment
+ import org.gradle.unknown.Unknown
+ new Unknown()
+"""
+
+ when:
+ fails()
+
+ then:
+ failure.assertHasDescription("Could not compile build file '${buildFile}'.")
+ .assertThatCause(containsString("build file '$buildFile': 3: unable to resolve class org.gradle.unknown.Unknown"))
+ .assertHasFileName("Build file '$buildFile'")
+ .assertHasLineNumber(3)
+ }
+
+ def "produces reasonable error message when buildFile evaluation fails with exception"() {
+ when:
+ buildFile << """
+ throw new RuntimeException("script failure")
+ task test
+"""
+ then:
+ fails('test')
+ failure.assertHasDescription("A problem occurred evaluating root project 'ProjectError'.")
+ .assertHasCause("script failure")
+ .assertHasFileName("Build file '${buildFile.path}'")
+ .assertHasLineNumber(2)
+ }
+
+ def "produces reasonable error message when nested buildFile evaluation fails"() {
+ settingsFile << """
+include 'child'
+"""
+ buildFile << """
+ evaluationDependsOn 'child'
+ task t
+"""
+ final childBuildFile = file("child/build.gradle")
+ childBuildFile << """
+ def broken = { ->
+ throw new RuntimeException('failure')
+ }
+ broken()
+"""
+
+ when:
+ fails()
+
+ then:
+ failure.assertHasDescription("A problem occurred evaluating project ':child'.")
+ .assertHasCause("failure")
+ .assertHasFileName("Build file '$childBuildFile'")
+ .assertHasLineNumber(3)
+ }
+}
diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/ConfigurationOnDemandIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/ConfigurationOnDemandIntegrationTest.groovy
index 6d50251..a14305d 100644
--- a/subprojects/core/src/integTest/groovy/org/gradle/api/ConfigurationOnDemandIntegrationTest.groovy
+++ b/subprojects/core/src/integTest/groovy/org/gradle/api/ConfigurationOnDemandIntegrationTest.groovy
@@ -17,12 +17,11 @@
package org.gradle.api
import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+import org.gradle.integtests.fixtures.executer.GradleContextualExecuter
import org.gradle.integtests.fixtures.executer.ProjectLifecycleFixture
import org.junit.Rule
+import spock.lang.IgnoreIf
-/**
- * by Szczepan Faber, created at: 11/21/12
- */
class ConfigurationOnDemandIntegrationTest extends AbstractIntegrationSpec {
@Rule ProjectLifecycleFixture fixture = new ProjectLifecycleFixture(executer, temporaryFolder)
@@ -31,13 +30,41 @@ class ConfigurationOnDemandIntegrationTest extends AbstractIntegrationSpec {
file("gradle.properties") << "org.gradle.configureondemand=true"
}
- def "works with single-module project"() {
+ @IgnoreIf({ GradleContextualExecuter.isParallel() }) //parallel mode hides incubating message
+ def "presents incubating message"() {
+ file("gradle.properties") << "org.gradle.configureondemand=false"
buildFile << "task foo"
+
when:
- run("foo")
+ run("foo", "--configure-on-demand")
+
+ then:
+ fixture.assertProjectsConfigured(":")
+ output.count("Configuration on demand is an incubating feature") == 1
+ }
+
+ @IgnoreIf({ GradleContextualExecuter.isParallel() }) //parallel mode hides incubating message
+ def "presents incubating message with parallel mode"() {
+ file("gradle.properties") << "org.gradle.configureondemand=false"
+ buildFile << "task foo"
+
+ when:
+ run("foo", "--configure-on-demand", "--parallel")
+
+ then:
+ fixture.assertProjectsConfigured(":")
+ output.count("Parallel execution with configuration on demand is an incubating feature") == 1
+ }
+
+ def "can be enabled from command line for a single module build"() {
+ file("gradle.properties") << "org.gradle.configureondemand=false"
+ buildFile << "task foo"
+
+ when:
+ run("foo", "--configure-on-demand")
+
then:
fixture.assertProjectsConfigured(":")
- assert output.contains("Configuration on demand is an incubating feature")
}
def "evaluates only project referenced in the task list"() {
@@ -49,15 +76,14 @@ class ConfigurationOnDemandIntegrationTest extends AbstractIntegrationSpec {
then:
fixture.assertProjectsConfigured(":", ":util:impl")
- assert output.contains("Configuration on demand is an incubating feature")
}
- def "does not show configuration on demand message in a regular mode"() {
+ def "does not show configuration on demand incubating message in a regular mode"() {
file("gradle.properties").text = "org.gradle.configureondemand=false"
when:
run()
then:
- assert !output.contains("Configuration on demand is an incubating feature")
+ !output.contains("Configuration on demand is incubating")
}
def "follows java project dependencies"() {
@@ -106,6 +132,26 @@ class ConfigurationOnDemandIntegrationTest extends AbstractIntegrationSpec {
fixture.assertProjectsConfigured(":", ":util", ":impl", ":api")
}
+ def "can have cycles in project dependencies"() {
+ settingsFile << "include 'api', 'impl', 'util'"
+ buildFile << """
+allprojects { apply plugin: 'java' }
+project(':impl') {
+ dependencies { compile project(path: ':api', configuration: 'archives') }
+}
+project(':api') {
+ dependencies { runtime project(':impl') }
+ task run(dependsOn: configurations.runtime)
+}
+"""
+
+ when:
+ run(":api:run")
+
+ then:
+ fixture.assertProjectsConfigured(":", ":api", ':impl')
+ }
+
def "follows project dependencies when ran in subproject"() {
settingsFile << "include 'api', 'impl', 'util'"
@@ -220,12 +266,9 @@ class ConfigurationOnDemandIntegrationTest extends AbstractIntegrationSpec {
run("impl:build", "--no-rebuild") // impl -> api
then:
- //api tasks are not executed
+ //api tasks are not executed and api is not configured
!result.executedTasks.find { it.startsWith ":api" }
- //but the api project is still configured
- //ideally, the ':api' project is not configured in the configure on demand mode
- //but this is complicated to implement so lets leave it for now
- fixture.assertProjectsConfigured(":", ":impl", ":api")
+ fixture.assertProjectsConfigured(":", ":impl")
}
def "respects external task dependencies"() {
@@ -258,8 +301,30 @@ class ConfigurationOnDemandIntegrationTest extends AbstractIntegrationSpec {
buildFile << "task foo(type: FooTask)"
when:
- run("foo")
+ run("foo", "-s")
then:
output.contains "Horray!!!"
}
+
+ def "may configure project at execution time"() {
+ settingsFile << "include 'a', 'b', 'c'"
+ file('a/build.gradle') << """
+ configurations { conf }
+ dependencies { conf project(path: ":b", configuration: "conf") }
+ task resolveConf << {
+ //resolves at execution time, forcing 'b' to get configured
+ configurations.conf.files
+ }
+ """
+
+ file('b/build.gradle') << """
+ configurations { conf }
+ """
+
+ when:
+ run(":a:resolveConf", "-i")
+
+ then:
+ fixture.assertProjectsConfigured(":", ":a", ":b")
+ }
}
\ No newline at end of file
diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/CrossProcessFileLockIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/CrossProcessFileLockIntegrationTest.groovy
new file mode 100644
index 0000000..769cada
--- /dev/null
+++ b/subprojects/core/src/integTest/groovy/org/gradle/api/CrossProcessFileLockIntegrationTest.groovy
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api;
+
+import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+
+import static org.gradle.test.fixtures.ConcurrentTestUtil.poll
+
+public class CrossProcessFileLockIntegrationTest extends AbstractIntegrationSpec {
+
+ def "the task history lock can be acquired when the initial owner is busy executing tasks"() {
+ settingsFile << "include 'a', 'b'"
+
+ file("a/src/main/java/A.java") << "public class A {}"
+ file("b/src/main/java/B.java") << "public class B {}"
+
+ when:
+ buildFile << """
+ def waitForStop() {
+ def sanityWaitUntil = System.currentTimeMillis() + 120000
+ println 'waiting for file...'
+ while(!file('stop.txt').exists()) {
+ Thread.sleep(300)
+ assert System.currentTimeMillis() < sanityWaitUntil : "Timeout waiting for file"
+ }
+ println 'no more waiting!'
+ }
+ def stopNow() {
+ assert file('stop.txt').createNewFile()
+ }
+ subprojects {
+ apply plugin: 'java'
+ }
+ project(":a") {
+ compileJava.doFirst { waitForStop() }
+ }
+ project(":b") {
+ compileJava.doFirst { stopNow() }
+ }
+ """
+
+ then:
+ def handle1 = executer.withArguments(':a:build', '-i').start()
+ poll(120) {
+ assert handle1.standardOutput.contains('waiting for file...')
+ }
+ //first build is waiting for file, so the lock should be releasable now (for example: the task history lock)
+
+ and:
+ def handle2 = executer.withArguments('b:build', '-is').start()
+ handle2.waitForFinish()
+ handle1.waitForFinish()
+
+ and:
+ file("a/build/libs/a.jar").assertExists()
+ file("b/build/libs/b.jar").assertExists()
+ }
+}
diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/DeferredConfigurableExtensionIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/DeferredConfigurableExtensionIntegrationTest.groovy
new file mode 100755
index 0000000..f70c11a
--- /dev/null
+++ b/subprojects/core/src/integTest/groovy/org/gradle/api/DeferredConfigurableExtensionIntegrationTest.groovy
@@ -0,0 +1,174 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api
+import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+
+public class DeferredConfigurableExtensionIntegrationTest extends AbstractIntegrationSpec {
+
+ def "setup"() {
+ settingsFile << "rootProject.name = 'customProject'"
+
+ buildFile << """
+public class CustomPlugin implements Plugin<Project> {
+ public void apply(Project project) {
+ project.getExtensions().create("custom", CustomExtension.class)
+ }
+}
+
+public class BrokenCustomPlugin implements Plugin<Project> {
+ public void apply(Project project) {
+ project.getPlugins().apply(CustomPlugin)
+ project.getExtensions().configure(CustomExtension, {
+ throw new RuntimeException("broken configuration in plugin")
+ } as Action)
+ }
+}
+
+ at org.gradle.api.plugins.DeferredConfigurable
+public class CustomExtension {
+ private final StringBuilder builder = new StringBuilder()
+ public void append(String value) {
+ builder.append(value)
+ }
+
+ public String getString() {
+ return builder.toString()
+ }
+}
+"""
+ }
+
+ private static def buildFileLine(int number) {
+ return number + 28 // Number of lines added to build script in setup
+ }
+
+ def "configure actions on deferred configurable extension are deferred until access"() {
+ when:
+ buildFile << '''
+apply plugin: CustomPlugin
+
+version = "1"
+custom {
+ append project.version
+}
+
+version = "2"
+custom {
+ append project.version
+}
+
+assert custom.string == "22"
+task test
+'''
+ then:
+ succeeds('test')
+ }
+
+ def "configure actions on deferred configurable extension are not applied if extension is not referenced"() {
+ when:
+ buildFile << '''
+apply plugin: CustomPlugin
+
+custom {
+ throw new RuntimeException()
+}
+
+task test
+'''
+ then:
+ succeeds('test')
+ }
+
+ def "reports on failure in deferred configurable that is referenced in the build"() {
+ when:
+ buildFile << '''
+apply plugin: CustomPlugin
+custom {
+ throw new RuntimeException("deferred configuration failure")
+}
+assert custom.string == "22"
+task test
+'''
+ then:
+ fails 'test'
+ failure.assertHasDescription("A problem occurred evaluating root project 'customProject'.")
+ .assertHasCause("deferred configuration failure")
+ .assertHasFileName("Build file '${buildFile.path}'")
+ .assertHasLineNumber(buildFileLine(3))
+ }
+
+ def "reports on failure in deferred configurable that is configured in plugin"() {
+ when:
+ buildFile << '''
+apply plugin: BrokenCustomPlugin
+print custom.string
+task test
+'''
+ then:
+ fails 'test'
+ failure.assertHasDescription("A problem occurred evaluating root project 'customProject'.")
+ .assertHasCause("broken configuration in plugin")
+ .assertHasFileName("Build file '${buildFile.path}'")
+ .assertHasLineNumber(12)
+ }
+
+ def "does not report on deferred configuration failure in case of another configuration failure"() {
+ when:
+ buildFile << '''
+apply plugin: BrokenCustomPlugin
+custom {
+ throw new RuntimeException("deferred configuration failure")
+}
+task test {
+ throw new RuntimeException("task configuration failure")
+}
+afterEvaluate {
+ project.custom
+}
+'''
+ then:
+ fails 'test'
+ failure.assertHasDescription("A problem occurred evaluating root project 'customProject'.")
+ .assertHasCause("task configuration failure")
+ .assertHasFileName("Build file '${buildFile.path}'")
+ .assertHasLineNumber(buildFileLine(6))
+ }
+
+ def "cannot configure deferred configurable extension after access"() {
+ when:
+ buildFile << '''
+apply plugin: CustomPlugin
+
+version = "1"
+custom {
+ append project.version
+}
+
+assert custom.string == "1"
+
+custom {
+ append project.version
+}
+task test
+'''
+ then:
+ fails('test')
+ failure.assertHasDescription("A problem occurred evaluating root project 'customProject'.")
+ .assertHasCause("Cannot configure the 'custom' extension after it has been accessed.")
+ .assertHasFileName("Build file '${buildFile.path}'")
+ .assertHasLineNumber(buildFileLine(10))
+ }
+}
diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/ExternalScriptErrorIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/ExternalScriptErrorIntegrationTest.groovy
new file mode 100755
index 0000000..a3e0a21
--- /dev/null
+++ b/subprojects/core/src/integTest/groovy/org/gradle/api/ExternalScriptErrorIntegrationTest.groovy
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api
+import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+
+import static org.hamcrest.Matchers.containsString
+
+class ExternalScriptErrorIntegrationTest extends AbstractIntegrationSpec {
+ def externalScript
+
+ def "setup"() {
+ externalScript = file('other.gradle')
+ settingsFile << "rootProject.name = 'project'"
+ buildFile << """
+ apply { from 'other.gradle' }
+"""
+ }
+
+ def "produces reasonable error message when external script fails with Groovy exception"() {
+ externalScript << '''
+
+doStuff()
+'''
+ when:
+ fails()
+
+ then:
+ failure.assertHasDescription('A problem occurred evaluating script.')
+ .assertHasCause('Could not find method doStuff() for arguments [] on root project')
+ .assertHasFileName("Script '${externalScript}'")
+ .assertHasLineNumber(3)
+ }
+
+ def "produces reasonable error message when external script fails on compilation"() {
+ externalScript << 'import org.gradle()'
+
+ when:
+ fails()
+
+ then:
+ failure.assertHasDescription("Could not compile script '$externalScript'.")
+ .assertThatCause(containsString("script '${externalScript}': 1: unexpected token: ("))
+ .assertHasFileName("Script '$externalScript'")
+ .assertHasLineNumber(1)
+ }
+
+ def "reports missing script"() {
+ when:
+ fails()
+
+ then:
+ failure.assertHasDescription("A problem occurred evaluating root project 'project'.")
+ .assertHasCause("Could not read script '${externalScript}' as it does not exist.")
+ .assertHasFileName("Build file '${buildFile}'")
+ .assertHasLineNumber(2)
+ }
+
+ def "produces reasonable error message when task execution fails"() {
+ externalScript << '''
+task doStuff << {
+ throw new RuntimeException('fail')
+}
+'''
+ when:
+ fails 'doStuff'
+
+ then:
+ failure.assertHasDescription('Execution failed for task \':doStuff\'.')
+ .assertHasCause('fail')
+ .assertHasFileName("Script '${externalScript}'")
+ .assertHasLineNumber(3)
+ }
+}
+
diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/FinalizerTaskIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/FinalizerTaskIntegrationTest.groovy
new file mode 100644
index 0000000..f9806f4
--- /dev/null
+++ b/subprojects/core/src/integTest/groovy/org/gradle/api/FinalizerTaskIntegrationTest.groovy
@@ -0,0 +1,248 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api
+
+import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+import org.gradle.util.TextUtil
+import spock.lang.Ignore
+import spock.lang.Unroll
+
+class FinalizerTaskIntegrationTest extends AbstractIntegrationSpec {
+ @Unroll
+ void 'finalizer tasks are scheduled as expected'() {
+ setupProject()
+
+ when:
+ succeeds(*requestedTasks)
+
+ then:
+ executedTasks == expectedExecutedTasks
+
+ where:
+ requestedTasks | expectedExecutedTasks
+ ['a'] | [':c', ':a', ':d', ':b']
+ ['a', 'b'] | [':c', ':a', ':d', ':b']
+ ['d', 'a'] | [':d', ':c', ':a', ':b']
+ }
+
+ @Unroll
+ void 'finalizer tasks work with task excluding'() {
+ setupProject()
+ executer.withArguments('-x', excludedTask)
+
+ tasksNotInGraph.each { task ->
+ buildFile << """
+ gradle.taskGraph.whenReady { graph ->
+ assert !graph.hasTask('$task')
+ }
+ """
+ }
+
+ when:
+ succeeds 'a'
+
+ then:
+ executedTasks == expectedExecutedTasks
+
+ where:
+ excludedTask | expectedExecutedTasks
+ 'b' | [':c', ':a']
+ 'd' | [':c', ':a', ':b']
+ 'a' | []
+
+
+ tasksNotInGraph = [':a', ':b', ':c', ':d'] - expectedExecutedTasks
+ }
+
+ @Unroll
+ void 'finalizer tasks work with --continue'() {
+ setupProject()
+ executer.withArguments('--continue')
+
+ buildFile << """
+ ${failingTask}.doLast { throw new RuntimeException() }
+ """
+
+ when:
+ fails(*requestedTasks)
+
+ then:
+ executedTasks == expectedExecutedTasks
+
+ where:
+ requestedTasks | failingTask | expectedExecutedTasks
+ ['a'] | 'c' | [':c']
+ ['a', 'b'] | 'a' | [':c', ':a', ':d', ':b']
+ ['a', 'b'] | 'c' | [':c', ':d', ':b']
+ }
+
+ @Ignore
+ @Unroll
+ void 'finalizer tasks work with task disabling'() {
+ setupProject()
+ buildFile << """
+ $taskDisablingStatement
+
+ gradle.taskGraph.whenReady { graph ->
+ assert [a, b, c, d].every { graph.hasTask(it) }
+ }
+ """
+
+ when:
+ succeeds 'a'
+
+ then:
+ executedTasks == [':c']
+
+ where:
+ taskDisablingStatement << ['a.enabled = false', 'a.onlyIf {false}']
+ }
+
+ @Ignore
+ void 'requesting to run finalizer task before finalized results in a circular dependency failure'() {
+ setupProject()
+
+ expect:
+ fails 'b', 'a'
+ }
+
+ void 'finalizer tasks are executed as expected in parallel builds'() {
+ setupMultipleProjects()
+ executer.withArguments('--parallel')
+
+ when:
+ succeeds 'a'
+
+ then:
+ executedTasks == [':a:c', ':a:a', ':b:d', ':b:b']
+ }
+
+ void 'finalizers for finalizers are executed when finalized is executed'() {
+ buildFile << """
+ task a {
+ finalizedBy 'b'
+ }
+ task b {
+ finalizedBy 'c'
+ }
+ task c
+ """
+
+ when:
+ succeeds 'a'
+
+ then:
+ executedTasks == [':a', ':b', ':c']
+ }
+
+ void 'finalizer tasks are executed after their dependencies'() {
+ buildFile << """
+ task a {
+ dependsOn 'b', 'c'
+ }
+ task b
+ task c {
+ finalizedBy 'b'
+ }
+ """
+
+ when:
+ succeeds 'a'
+
+ then:
+ executedTasks == [':c', ':b', ':a']
+ }
+
+ void 'circular dependency errors are detected for finalizer tasks'() {
+ buildFile << """
+ task a {
+ finalizedBy 'b'
+ dependsOn 'c'
+ }
+ task b
+ task c {
+ mustRunAfter 'b'
+ }
+ """
+
+ when:
+ fails 'a'
+
+ then:
+ failure.assertHasDescription TextUtil.toPlatformLineSeparators("""Circular dependency between the following tasks:
+:a
+\\--- :c
+ \\--- :b
+ \\--- :a (*)
+
+(*) - details omitted (listed previously)""")
+ }
+
+ void 'finalizer task can be used by multiple tasks that depend on one another'(){
+ buildFile << """
+ task a {
+ finalizedBy 'c'
+ }
+ task b {
+ dependsOn 'a'
+ finalizedBy 'c'
+ }
+ task c
+ """
+
+ when:
+ succeeds 'b'
+
+ then:
+ executedTasks == [':a', ':b', ':c']
+ }
+
+ private void setupProject() {
+ buildFile << """
+ task a {
+ finalizedBy 'b'
+ dependsOn 'c'
+ }
+ task b {
+ dependsOn 'd'
+ }
+ task c
+ task d
+ """
+ }
+
+ private void setupMultipleProjects() {
+ settingsFile << """
+ include 'a', 'b'
+ """
+
+ file('a/build.gradle') << """
+ task a {
+ finalizedBy ':b:b'
+ dependsOn 'c'
+ }
+ task c
+ """
+
+ file('b/build.gradle') << """
+ task b {
+ dependsOn 'd'
+ }
+ task d
+ """
+ }
+}
diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/GradlePluginIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/GradlePluginIntegrationTest.groovy
new file mode 100644
index 0000000..01c22e8
--- /dev/null
+++ b/subprojects/core/src/integTest/groovy/org/gradle/api/GradlePluginIntegrationTest.groovy
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api
+
+import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+
+class GradlePluginIntegrationTest extends AbstractIntegrationSpec {
+ File initFile;
+
+ def setup() {
+ initFile = temporaryFolder.createFile("initscripts/init.gradle")
+ executer.usingInitScript(initFile);
+ }
+
+ def "can apply binary plugin from init script"() {
+ when:
+ initFile << """
+ apply plugin:SimpleGradlePlugin
+
+ class SimpleGradlePlugin implements Plugin<Gradle> {
+ void apply(Gradle aGradle) {
+ aGradle.buildFinished {
+ println "Gradle Plugin received build finished!"
+ }
+ }
+ }
+ """
+ then:
+ def executed = succeeds('tasks')
+ executed.output.contains("Gradle Plugin received build finished!")
+ }
+
+ def "can apply script with relative path"() {
+ setup:
+ def externalInitFile = temporaryFolder.createFile("initscripts/somePath/anInit.gradle")
+ externalInitFile << """
+ buildFinished {
+ println "Gradle Plugin received build finished!"
+ }
+ """
+ when:
+ initFile << """
+ apply from: "somePath/anInit.gradle"
+ """
+ then:
+ def executed = succeeds('tasks')
+ executed.output.contains("Gradle Plugin received build finished!")
+ }
+
+ def "cannot apply script with relative path on Gradle instance"() {
+ when:
+ initFile << """
+ gradle.apply(from: "somePath/anInit.gradle")
+ """
+ then:
+ fails('tasks')
+ failure.assertHasCause("Cannot convert relative path somePath${File.separator}anInit.gradle to an absolute file")
+ }
+
+ def "path to script is interpreted relative to the applying script"() {
+ setup:
+ def externalInitFile = temporaryFolder.createFile("initscripts/path1/anInit.gradle")
+ externalInitFile << """
+ buildFinished {
+ println "Gradle Plugin received build finished!"
+ }
+ """
+ def anotherExternalInitFile = temporaryFolder.createFile("initscripts/path2/anotherInit.gradle")
+ anotherExternalInitFile << """
+ apply from: '../path1/anInit.gradle'
+ """
+
+ when:
+ initFile << """
+ apply from: "path2/anotherInit.gradle"
+ """
+ then:
+ def executed = succeeds('tasks')
+ executed.output.contains("Gradle Plugin received build finished!")
+ }
+}
\ No newline at end of file
diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/InitScriptErrorIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/InitScriptErrorIntegrationTest.groovy
new file mode 100644
index 0000000..3d1f7d6
--- /dev/null
+++ b/subprojects/core/src/integTest/groovy/org/gradle/api/InitScriptErrorIntegrationTest.groovy
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api
+import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+
+import static org.hamcrest.Matchers.containsString
+
+public class InitScriptErrorIntegrationTest extends AbstractIntegrationSpec {
+ def initScript
+
+ def "setup"() {
+ initScript = file('init.gradle')
+ executer.usingInitScript(initScript)
+ }
+
+ def "produces reasonable error message when init script evaluation fails with GroovyException"() {
+ initScript << """
+ createTakk('do-stuff')
+"""
+ when:
+ fails()
+
+ then:
+ failure.assertHasDescription("A problem occurred evaluating initialization script.")
+ .assertHasCause("Could not find method createTakk() for arguments [do-stuff] on build.")
+ .assertHasFileName("Initialization script '$initScript'")
+ .assertHasLineNumber(2)
+ }
+
+ def "produces reasonable error message when init script compilation fails"() {
+ initScript << """
+ // a comment
+ import org.gradle.unknown.Unknown
+ new Unknown()
+"""
+ when:
+ fails()
+
+ then:
+ failure.assertHasDescription("Could not compile initialization script '$initScript'.")
+ .assertThatCause(containsString("initialization script '$initScript': 3: unable to resolve class org.gradle.unknown.Unknown"))
+ .assertHasFileName("Initialization script '$initScript'")
+ .assertHasLineNumber(3)
+ }
+}
diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/ProfilingIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/ProfilingIntegrationTest.groovy
new file mode 100644
index 0000000..0f301ca
--- /dev/null
+++ b/subprojects/core/src/integTest/groovy/org/gradle/api/ProfilingIntegrationTest.groovy
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api
+
+import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+import org.jsoup.Jsoup
+import org.jsoup.nodes.Document
+
+class ProfilingIntegrationTest extends AbstractIntegrationSpec {
+
+ def "can generate profiling report"() {
+ file('settings.gradle') << 'include "a", "b", "c"'
+ buildFile << '''
+allprojects {
+ apply plugin: 'java'
+ task fooTask
+ task barTask
+}
+'''
+ when:
+ executer.withArguments("--profile").withTasks("build", "fooTask", "-x", "barTask").run()
+
+ then:
+ def reportFile = file('build/reports/profile').listFiles().find { it.name ==~ /profile-.+.html/ }
+ Document document = Jsoup.parse(reportFile, null);
+ !document.select("TD:contains(:jar)").isEmpty()
+ !document.select("TD:contains(:a:jar)").isEmpty()
+ !document.select("TD:contains(:b:jar)").isEmpty()
+ !document.select("TD:contains(:c:jar)").isEmpty()
+ document.text().contains("build fooTask")
+ document.text().contains("-x barTask")
+ }
+}
\ No newline at end of file
diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/ProjectConfigurationIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/ProjectConfigurationIntegrationTest.groovy
index 88b916a..adc2e86 100644
--- a/subprojects/core/src/integTest/groovy/org/gradle/api/ProjectConfigurationIntegrationTest.groovy
+++ b/subprojects/core/src/integTest/groovy/org/gradle/api/ProjectConfigurationIntegrationTest.groovy
@@ -18,9 +18,6 @@ package org.gradle.api
import org.gradle.integtests.fixtures.AbstractIntegrationSpec
-/**
- * by Szczepan Faber, created at: 11/21/12
- */
class ProjectConfigurationIntegrationTest extends AbstractIntegrationSpec {
def "accessing the task by path from containing project is safe"() {
diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/ProjectConfigureEventsErrorIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/ProjectConfigureEventsErrorIntegrationTest.groovy
new file mode 100755
index 0000000..66ffa9a
--- /dev/null
+++ b/subprojects/core/src/integTest/groovy/org/gradle/api/ProjectConfigureEventsErrorIntegrationTest.groovy
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api
+import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+import spock.lang.Ignore
+
+public class ProjectConfigureEventsErrorIntegrationTest extends AbstractIntegrationSpec {
+
+ def "setup"() {
+ settingsFile << "rootProject.name = 'projectConfigure'"
+ }
+
+ def "produces reasonable error message when beforeProject action fails"() {
+ when:
+ settingsFile << """
+ gradle.beforeProject {
+ throw new RuntimeException("beforeProject failure")
+ }
+"""
+ buildFile << """
+ task test
+"""
+ then:
+ fails('test')
+ failure.assertHasDescription("A problem occurred configuring root project 'projectConfigure'.")
+ .assertHasCause("beforeProject failure")
+ .assertHasFileName("Settings file '${settingsFile.path}'")
+ .assertHasLineNumber(3)
+ }
+
+ def "produces reasonable error message when afterProject action fails"() {
+ when:
+ settingsFile << """
+ gradle.afterProject {
+ throw new RuntimeException("afterProject failure")
+ }
+"""
+ buildFile << """
+ task test
+"""
+ then:
+ fails('test')
+ failure.assertHasDescription("A problem occurred configuring root project 'projectConfigure'.")
+ .assertHasCause("afterProject failure")
+ .assertHasFileName("Settings file '${settingsFile.path}'")
+ .assertHasLineNumber(3)
+ }
+
+ def "produces reasonable error message when afterEvaluate action fails"() {
+ when:
+ buildFile << """
+ project.afterEvaluate {
+ throw new RuntimeException("afterEvaluate failure")
+ }
+ task test
+"""
+ then:
+ fails('test')
+ failure.assertHasDescription("A problem occurred configuring root project 'projectConfigure'.")
+ .assertHasCause("afterEvaluate failure")
+ .assertHasFileName("Build file '${buildFile.path}'")
+ .assertHasLineNumber(3)
+ }
+
+ def "produces reasonable error message when taskGraph.whenReady action fails"() {
+ buildFile << """
+ gradle.taskGraph.whenReady {
+ throw new RuntimeException('broken closure')
+ }
+ task a
+"""
+
+ when:
+ fails()
+
+ then:
+ failure.assertHasDescription("broken closure")
+ .assertHasNoCause()
+ .assertHasFileName("Build file '$buildFile'")
+ .assertHasLineNumber(3);
+ }
+
+ @Ignore
+ def "produces reasonable error message when task dependency closure throws exception"() {
+ buildFile << """
+ task a
+ a.dependsOn {
+ throw new RuntimeException('broken')
+ }
+"""
+ when:
+ fails "a"
+
+ then:
+ failure.assertHasDescription("Could not determine the dependencies of task ':a'.")
+ .assertHasCause('broken')
+ .assertHasFileName("Build file '$buildFile'")
+ .assertHasLineNumber(4)
+ }
+}
diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/SettingsPluginIntegrationSpec.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/SettingsPluginIntegrationSpec.groovy
new file mode 100644
index 0000000..d67aafa
--- /dev/null
+++ b/subprojects/core/src/integTest/groovy/org/gradle/api/SettingsPluginIntegrationSpec.groovy
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api
+
+import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+import org.gradle.test.fixtures.file.TestFile
+
+class SettingsPluginIntegrationSpec extends AbstractIntegrationSpec {
+
+ def setup(){
+ executer.usingSettingsFile(settingsFile)
+ settingsFile << "rootProject.projectDir = file('..')\n"
+ }
+
+ def "can apply plugin class from settings.gradle"() {
+ when:
+ settingsFile << """
+ apply plugin: SimpleSettingsPlugin
+
+ class SimpleSettingsPlugin implements Plugin<Settings> {
+ void apply(Settings mySettings) {
+ mySettings.include("moduleA");
+ }
+ }
+ """
+
+ then:
+ succeeds(':moduleA:dependencies')
+ }
+
+ def "can apply plugin class from buildSrc"() {
+ setup:
+ file("settings/buildSrc/src/main/java/test/SimpleSettingsPlugin.java").createFile().text = """
+ package test;
+
+ import org.gradle.api.Plugin;
+ import org.gradle.api.initialization.Settings;
+
+ public class SimpleSettingsPlugin implements Plugin<Settings> {
+ public void apply(Settings settings) {
+ settings.include(new String[]{"moduleA"});
+ }
+ }
+
+ """
+
+ when:
+ settingsFile << "apply plugin: test.SimpleSettingsPlugin"
+
+ then:
+ succeeds(':moduleA:dependencies')
+ }
+
+ def "can apply script with relative path"() {
+ setup:
+ testDirectory.createFile("settings/somePath/settingsPlugin.gradle") << "apply from: 'path2/settings.gradle'";
+ testDirectory.createFile("settings/somePath/path2/settings.gradle") << "include 'moduleA'";
+
+ when:
+ settingsFile << "apply from: 'somePath/settingsPlugin.gradle'"
+
+ then:
+ succeeds(':moduleA:dependencies')
+ }
+
+ protected TestFile getSettingsFile() {
+ testDirectory.file('settings/settings.gradle')
+ }
+}
diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/SettingsScriptErrorIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/SettingsScriptErrorIntegrationTest.groovy
new file mode 100755
index 0000000..e28304f
--- /dev/null
+++ b/subprojects/core/src/integTest/groovy/org/gradle/api/SettingsScriptErrorIntegrationTest.groovy
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api
+import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+
+public class SettingsScriptErrorIntegrationTest extends AbstractIntegrationSpec {
+
+ def "setup"() {
+ settingsFile << "rootProject.name = 'ProjectError'"
+ }
+
+ def "produces reasonable error message when settings file evaluation fails"() {
+ settingsFile << """
+
+throw new RuntimeException('<failure message>')
+"""
+ when:
+ fails()
+
+ then:
+ failure.assertHasDescription("A problem occurred evaluating settings 'ProjectError'.")
+ .assertHasCause("<failure message>")
+ .assertHasFileName("Settings file '$settingsFile'")
+ .assertHasLineNumber(3)
+
+ }
+}
diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/dsl/ConcurrentClassDecorationSpec.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/dsl/ConcurrentClassDecorationSpec.groovy
new file mode 100644
index 0000000..836b0b8
--- /dev/null
+++ b/subprojects/core/src/integTest/groovy/org/gradle/api/dsl/ConcurrentClassDecorationSpec.groovy
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.dsl
+
+import org.gradle.api.plugins.ExtensionAware
+import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+import org.gradle.internal.reflect.Instantiator
+import spock.lang.Issue
+
+class ConcurrentClassDecorationSpec extends AbstractIntegrationSpec {
+
+ @Issue("http://issues.gradle.org/browse/GRADLE-2836")
+ def "can decorate classes concurrently"() {
+ given:
+ file("buildSrc/src/main/java/Thing.java") << "public class Thing {}"
+ ("a".."d").each { name ->
+ settingsFile << "include '$name'\n"
+ file("$name/build.gradle") << """
+ task decorateClass << {
+ def instantiator = project.services.get(${Instantiator.name})
+ def thing = instantiator.newInstance(Thing)
+ assert thing instanceof ${ExtensionAware.name}
+ }
+ """
+ }
+
+ when:
+ args "--parallel"
+
+ then:
+ succeeds "decorateClass"
+ }
+
+}
diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/ArchiveIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/ArchiveIntegrationTest.groovy
index 6aa4069..9637d29 100644
--- a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/ArchiveIntegrationTest.groovy
+++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/ArchiveIntegrationTest.groovy
@@ -13,16 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-
-
-
package org.gradle.api.tasks
import org.apache.commons.lang.RandomStringUtils
-import org.apache.commons.lang.StringUtils
import org.gradle.integtests.fixtures.AbstractIntegrationSpec
import org.gradle.integtests.fixtures.TestResources
+import org.gradle.test.fixtures.archive.TarTestFixture
import org.gradle.test.fixtures.file.TestFile
import org.junit.Rule
@@ -71,8 +67,6 @@ public class ArchiveIntegrationTest extends AbstractIntegrationSpec {
file('build/test.tar').assertDoesNotExist()
}
-
-
def canCopyFromATar() {
given:
createTar('test.tar') {
@@ -222,7 +216,8 @@ public class ArchiveIntegrationTest extends AbstractIntegrationSpec {
file('dest').assertHasDescendants('someDir/1.txt')
}
- @Rule public final TestResources resources = new TestResources(temporaryFolder)
+ @Rule
+ public final TestResources resources = new TestResources(temporaryFolder)
def "tarTreeFailsGracefully"() {
given:
@@ -344,11 +339,11 @@ public class ArchiveIntegrationTest extends AbstractIntegrationSpec {
run 'uncompressedZip'
run 'compressedZip'
then:
- def uncompressedSize = file('build/uncompressedTest.zip').length()
- def compressedSize = file('build/compressedTest.zip').length()
- println "uncompressed" + uncompressedSize
- println "compressed" + compressedSize
- assert compressedSize < uncompressedSize
+ def uncompressedSize = file('build/uncompressedTest.zip').length()
+ def compressedSize = file('build/compressedTest.zip').length()
+ println "uncompressed" + uncompressedSize
+ println "compressed" + compressedSize
+ assert compressedSize < uncompressedSize
def expandDir = file('expandedUncompressed')
file('build/uncompressedTest.zip').unzipTo(expandDir)
@@ -598,10 +593,67 @@ public class ArchiveIntegrationTest extends AbstractIntegrationSpec {
expandDir.assertHasDescendants('shared/zip.txt', 'zipdir1/file1.txt', 'shared/tar.txt', 'tardir1/file1.txt', 'shared/dir.txt', 'dir1/file1.txt')
}
- def createTar(String name, Closure cl) {
+
+ def ensureDuplicatesIncludedInTarByDefault() {
+ given:
+ createFilesStructureForDupeTests();
+ buildFile << '''
+ task tar(type: Tar) {
+ from 'dir1'
+ from 'dir2'
+ from 'dir3'
+ destinationDir = buildDir
+ archiveName = 'test.tar'
+ }
+ '''
+ when:
+ run 'tar'
+
+ then:
+ def tar = new TarTestFixture(file("build/test.tar"))
+ tar.assertContainsFile('file1.txt', 2)
+ tar.assertContainsFile('file2.txt')
+ }
+
+ def ensureDuplicatesCanBeExcludedFromTar() {
+ given:
+ createFilesStructureForDupeTests()
+ buildFile << '''
+ task tar(type: Tar) {
+ from 'dir1'
+ from 'dir2'
+ from 'dir3'
+ destinationDir = buildDir
+ archiveName = 'test.tar'
+ eachFile { it.duplicatesStrategy = 'exclude' }
+ }
+ '''
+ when:
+ run 'tar'
+
+ then:
+ def tar = new TarTestFixture(file("build/test.tar"))
+ tar.assertContainsFile('file1.txt')
+ tar.assertContainsFile('file2.txt')
+ tar.content("file1.txt") == "dir1/file1.txt"
+ }
+
+ private def createTar(String name, Closure cl) {
TestFile tarRoot = file("${name}.root")
TestFile tar = file(name)
tarRoot.create(cl)
tarRoot.tarTo(tar)
}
+
+ private def createFilesStructureForDupeTests() {
+ createDir('dir1', {
+ file('file1.txt').text = "dir1/file1.txt"
+ })
+ createDir('dir2', {
+ file 'file2.txt'
+ })
+ createDir('dir3', {
+ file('file1.txt').text = "dir3/file1.txt"
+ })
+ }
}
diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/CopyTaskIntegrationSpec.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/CopyTaskIntegrationSpec.groovy
index afb84fb..5ee38a9 100644
--- a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/CopyTaskIntegrationSpec.groovy
+++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/CopyTaskIntegrationSpec.groovy
@@ -16,6 +16,7 @@
package org.gradle.api.tasks
+import org.gradle.api.plugins.ExtensionAware
import org.gradle.integtests.fixtures.AbstractIntegrationSpec
import spock.lang.Issue
@@ -67,4 +68,92 @@ class CopyTaskIntegrationSpec extends AbstractIntegrationSpec {
then:
file("build/resources", weirdFileName).exists()
}
+
+ def "nested specs and details arent extensible objects"() {
+ given:
+ file("a/a.txt").touch()
+
+ buildScript """
+ task copy(type: Copy) {
+ assert delegate instanceof ${ExtensionAware.name}
+ into "out"
+ from "a", {
+ assert !(delegate instanceof ${ExtensionAware.name})
+ eachFile {
+ it.name = "rename"
+ assert !(delegate instanceof ${ExtensionAware.name})
+ }
+ }
+ }
+ """
+
+ when:
+ succeeds "copy"
+
+ then:
+ file("out/rename").exists()
+ }
+
+ @Issue("http://issues.gradle.org/browse/GRADLE-2838")
+ def "include empty dirs works when nested"() {
+ given:
+ file("a/a.txt") << "foo"
+ file("a/dirA").createDir()
+ file("b/b.txt") << "foo"
+ file("b/dirB").createDir()
+
+ buildScript """
+ task copyTask(type: Copy) {
+ into "out"
+ from "b", {
+ includeEmptyDirs = false
+ }
+ from "a"
+ from "c", {}
+ }
+ """
+
+ when:
+ succeeds "copyTask"
+
+ then:
+ ":copyTask" in nonSkippedTasks
+ def destinationDir = file("out")
+ destinationDir.assertHasDescendants("a.txt", "b.txt")
+ destinationDir.listFiles().findAll { it.directory }*.name.toSet() == ["dirA"].toSet()
+ }
+
+ def "include empty dirs is overridden by subsequent"() {
+ given:
+ file("a/a.txt") << "foo"
+ file("a/dirA").createDir()
+ file("b/b.txt") << "foo"
+ file("b/dirB").createDir()
+
+
+ buildScript """
+ task copyTask(type: Copy) {
+ into "out"
+ from "b", {
+ includeEmptyDirs = false
+ }
+ from "a"
+ from "c", {}
+ from "b", {
+ includeEmptyDirs = true
+ }
+ }
+ """
+
+ when:
+ succeeds "copyTask"
+
+ then:
+ ":copyTask" in nonSkippedTasks
+
+ def destinationDir = file("out")
+ destinationDir.assertHasDescendants("a.txt", "b.txt")
+ destinationDir.listFiles().findAll { it.directory }*.name.toSet() == ["dirA", "dirB"].toSet()
+ }
+
}
diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/CopyTaskIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/CopyTaskIntegrationTest.groovy
index 2c420e1..9d43b3d 100644
--- a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/CopyTaskIntegrationTest.groovy
+++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/CopyTaskIntegrationTest.groovy
@@ -18,11 +18,13 @@ package org.gradle.api.tasks
import org.gradle.integtests.fixtures.AbstractIntegrationTest
import org.gradle.integtests.fixtures.TestResources
import org.gradle.test.fixtures.file.TestFile
+import org.gradle.util.Matchers
import org.junit.Rule
import org.junit.Test
import static org.hamcrest.Matchers.equalTo
import static org.hamcrest.Matchers.startsWith
+import static org.junit.Assert.assertFalse
import static org.junit.Assert.assertThat
public class CopyTaskIntegrationTest extends AbstractIntegrationTest {
@@ -435,4 +437,76 @@ public class CopyTaskIntegrationTest extends AbstractIntegrationTest {
assert !file("dest", "emptyDir").exists()
assert !file("dest", "yet", "another", "veryEmptyDir").exists()
}
+
+ @Test
+ public void testCopyExcludeDuplicates() {
+ file('dir1', 'path', 'file.txt').createFile() << "f1"
+ file('dir2', 'path', 'file.txt').createFile() << "f2"
+
+
+ def buildFile = testFile('build.gradle') <<
+ '''
+ task copy(type: Copy) {
+ from 'dir1'
+ from 'dir2'
+ into 'dest'
+
+ eachFile { it.duplicatesStrategy = 'exclude' }
+ }
+
+ '''
+
+ def result = usingBuildFile(buildFile).withTasks("copy").run()
+ file('dest').assertHasDescendants('path/file.txt')
+ file('dest/path/file.txt').assertContents(Matchers.containsText("f1"))
+ assertFalse(result.output.contains('deprecated'))
+ }
+
+ @Test
+ public void renamedFileCanBeTreatedAsDuplicate() {
+ File file1 = file('dir1', 'path', 'file.txt').createFile()
+ File file2 = file('dir2', 'path', 'file2.txt').createFile()
+ file1.text = "file1"
+ file2.text = "file2"
+
+ def buildFile = testFile('build.gradle') <<
+ '''
+ task copy(type: Copy) {
+ from 'dir1'
+ from 'dir2'
+ rename 'file2.txt', 'file.txt'
+ into 'dest'
+
+ eachFile { it.duplicatesStrategy = 'exclude' }
+ }
+ '''
+ def result = usingBuildFile(buildFile).withTasks("copy").run()
+ file('dest').assertHasDescendants('path/file.txt')
+ file('dest/path/file.txt').assertContents(Matchers.containsText("file1"))
+ assertFalse(result.output.contains('deprecated'))
+ }
+
+ @Test
+ public void testChainMatchingRules() {
+ file('path/abc.txt').createFile().write('test file with $attr')
+ file('path/bcd.txt').createFile()
+
+ def buildFile = testFile('build.gradle') <<
+ '''
+ task copy(type: Copy) {
+ from 'path'
+ into 'dest'
+ filesMatching ('**/a*') {
+ path = path + '.template'
+ }
+ filesMatching ('**/*.template') {
+ expand(attr: 'some value')
+ path = path.replace('template', 'concrete')
+ }
+ }'''
+
+ usingBuildFile(buildFile).withTasks('copy').run();
+ file('dest').assertHasDescendants('bcd.txt', 'abc.txt.concrete')
+ file('dest/abc.txt.concrete').text = 'test file with some value'
+ }
}
diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/TaskCommandLineConfigurationIntegrationSpec.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/TaskCommandLineConfigurationIntegrationSpec.groovy
new file mode 100644
index 0000000..6a2c0ae
--- /dev/null
+++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/TaskCommandLineConfigurationIntegrationSpec.groovy
@@ -0,0 +1,249 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.tasks
+
+import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+import spock.lang.Ignore
+
+class TaskCommandLineConfigurationIntegrationSpec extends AbstractIntegrationSpec {
+
+ final String someConfigurableTaskType = """
+ import org.gradle.api.internal.tasks.CommandLineOption
+
+ class SomeTask extends DefaultTask {
+ boolean first
+ String second
+
+ @CommandLineOption(options = "first", description = "configures 'first' field")
+ void setFirst(boolean first) {
+ this.first = first
+ }
+
+ @CommandLineOption(options = "second", description = "configures 'second' field")
+ void setSecond(String second) {
+ this.second = second
+ }
+
+ //more stress
+ void setSecond(Object second) {
+ this.second = second.toString()
+ }
+
+ @TaskAction
+ void renderFields() {
+ println "first=" + first + ",second=" + second
+ }
+ }"""
+
+ def "can configure task from command line in multiple projects"() {
+ given:
+ file("settings.gradle") << "include 'project2'"
+ file("build.gradle") << """
+ allprojects {
+ task someTask(type: SomeTask)
+ }
+ task task1 //extra stress
+ task task2
+
+ $someConfigurableTaskType
+"""
+
+ when:
+ run 'someTask'
+
+ then:
+ output.contains 'first=false,second=null'
+
+ when:
+ run 'task1', 'someTask', '--first', '--second', 'hey buddy', 'task2'
+
+ then:
+ output.count('first=true,second=hey buddy') == 2
+ result.assertTasksExecuted(":task1", ":someTask", ":project2:someTask", ":task2")
+ }
+
+ def "tasks can be configured with different options"() {
+ given:
+ file("settings.gradle") << "include 'project2'"
+ file("build.gradle") << """
+ allprojects {
+ task someTask(type: SomeTask)
+ }
+
+ $someConfigurableTaskType
+"""
+
+ when:
+ run ':someTask', '--second', 'one', ':project2:someTask', '--second', 'two'
+
+ then:
+ result.assertTasksExecuted(":someTask", ":project2:someTask")
+ output.count('second=one') == 1
+ output.count('second=two') == 1
+ }
+
+ def "tasks are configured exclusively with their options"() {
+ given:
+ file("settings.gradle") << "include 'project2'"
+ file("build.gradle") << """
+ allprojects {
+ task someTask(type: SomeTask)
+ }
+
+ $someConfigurableTaskType
+"""
+
+ when:
+ run ':someTask', '--second', 'one', ':project2:someTask', '--first'
+
+ then:
+ result.assertTasksExecuted(":someTask", ":project2:someTask")
+ output.count('first=false,second=one') == 1 //--first flag was set only on the :project2:someTask
+ output.count('first=true,second=null') == 1 //--second option was set only on the :someTask
+ }
+
+ def "task name that matches command value is not included in execution"() {
+ given:
+ file("build.gradle") << """
+ task foo
+ task someTask(type: SomeTask)
+
+ $someConfigurableTaskType
+"""
+
+ when:
+ run 'someTask', '--second', 'foo'
+
+ then:
+ output.contains 'second=foo'
+ result.assertTasksExecuted(":someTask") //no 'foo' task
+ }
+
+ def "multiple different tasks configured at single command line"() {
+ given:
+ file("build.gradle") << """
+ task foo
+ task someTask(type: SomeTask)
+
+ $someConfigurableTaskType
+"""
+
+ when:
+ run 'someTask', '--second', 'foo', 'tasks', '--all'
+
+ then:
+ output.contains 'second=foo'
+ result.assertTasksExecuted(":someTask", ":tasks")
+ }
+
+ def "different tasks match name but only one accepts the option"() {
+ given:
+ file("settings.gradle") << "include 'other'"
+ file("build.gradle") << """
+ task someTask(type: SomeTask)
+ project(":other") {
+ task someTask
+ }
+
+ $someConfigurableTaskType
+"""
+
+ when:
+ def failure = runAndFail 'someTask', '--first'
+
+ then:
+ failure.assertHasDescription("Problem configuring task :other:someTask from command line. Unknown command-line option '--first'.")
+ }
+
+ def "using an unknown option yields decent error message"() {
+ given:
+ file("build.gradle") << """
+ task foo
+ task someTask(type: SomeTask)
+ task someTask2(type: SomeTask)
+
+ $someConfigurableTaskType
+"""
+
+ when:
+ runAndFail 'someTask', '--second', 'foo', 'someTask2', '--secon', 'bar'
+
+ then:
+ failure.assertHasDescription("Problem configuring task :someTask2 from command line. Unknown command-line option '--secon'.")
+
+ //TODO it's not fixable easily we would need to change some stuff in options parsing. See also ignored test method below.
+// when:
+// runAndFail 'someTask', '-second', 'foo'
+//
+// then:
+// failure.assertHasDescription("Problem configuring task :someTask from command line. Unknown command-line option '-second'.")
+
+ when:
+ runAndFail 'someTask', '--second'
+
+ then:
+ failure.assertHasDescription("Problem configuring task :someTask from command line. No argument was provided for command-line option '--second'.")
+
+ when:
+ runAndFail 'someTask', '--second', 'hey', '--second', 'buddy'
+
+ then:
+ failure.assertHasDescription("Problem configuring task :someTask from command line. Multiple arguments were provided for command-line option '--second'.")
+ }
+
+ def "single dash user error yields decent error message"() {
+ when:
+ runAndFail 'tasks', '-all'
+
+ then:
+ failure.assertHasDescription("Problem configuring task :tasks from command line. Unknown command-line option '-l'.")
+ }
+
+ @Ignore
+ //more work & design decisions needed
+ def "single dash error is detected in the subsequent option"() {
+ given:
+ file("build.gradle") << """
+ task someTask(type: SomeTask)
+
+ $someConfigurableTaskType
+"""
+
+ when:
+ runAndFail 'someTask', '--first', '-second', 'foo'
+
+ then:
+ failure.assertHasDescription("Incorrect command line arguments: [-l, -l]. Task options require double dash, for example: 'gradle tasks --all'.")
+ }
+
+ @Ignore
+ //some existing problems with command line interface
+ def "unfriendly behavior of command line parsing"() {
+ when:
+ run '-all'
+
+ then:
+ "should fail with a decent error, not internal error (applies to all CommandLineArgumentExceptions)"
+ "should complain that there's no '-all' option"
+
+ when:
+ run 'tasks', '-refresh-dependenciess'
+
+ then:
+ "should fail in a consistent way as with '--refresh-dependenciess'"
+ }
+}
diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/bundling/ZipIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/bundling/ZipIntegrationTest.groovy
new file mode 100644
index 0000000..b421456
--- /dev/null
+++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/bundling/ZipIntegrationTest.groovy
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.tasks.bundling
+
+import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+import org.gradle.test.fixtures.archive.ZipTestFixture
+
+class ZipIntegrationTest extends AbstractIntegrationSpec {
+
+ def ensureDuplicatesIncludedWithoutWarning() {
+ given:
+ createTestFiles()
+ buildFile << '''
+ task zip(type: Zip) {
+ from 'dir1'
+ from 'dir2'
+ from 'dir3'
+ destinationDir = buildDir
+ archiveName = 'test.zip'
+ }
+ '''
+ when:
+ run 'zip'
+
+ then:
+ def theZip = new ZipTestFixture(file('build/test.zip'))
+ theZip.hasDescendants('file1.txt', 'file1.txt', 'file2.txt')
+ }
+
+ def ensureDuplicatesCanBeExcluded() {
+ given:
+ createTestFiles()
+ buildFile << '''
+ task zip(type: Zip) {
+ from 'dir1'
+ from 'dir2'
+ from 'dir3'
+ destinationDir = buildDir
+ archiveName = 'test.zip'
+ eachFile { it.duplicatesStrategy = 'exclude' }
+ }
+ '''
+ when:
+ run 'zip'
+
+ then:
+ def theZip = new ZipTestFixture(file('build/test.zip'))
+ theZip.hasDescendants('file1.txt', 'file2.txt')
+ }
+
+ def renamedFileWillBeTreatedAsDuplicateZip() {
+ given:
+ createTestFiles()
+ buildFile << '''
+ task zip(type: Zip) {
+ from 'dir1'
+ from 'dir2'
+ destinationDir = buildDir
+ rename 'file2.txt', 'file1.txt'
+ archiveName = 'test.zip'
+ eachFile { it.duplicatesStrategy = 'exclude' }
+ }
+ '''
+ when:
+ run 'zip'
+
+ then:
+ def theZip = new ZipTestFixture(file('build/test.zip'))
+ theZip.hasDescendants('file1.txt')
+ theZip.assertFileContent('file1.txt', "dir1/file1.txt")
+ }
+
+
+ private def createTestFiles() {
+ createDir('dir1', {
+ file('file1.txt').text = "dir1/file1.txt"
+ })
+ createDir('dir2', {
+ file('file2.txt').text = "dir2/file2.txt"
+ })
+ createDir('dir3', {
+ file('file1.txt').text = "dir3/file1.txt"
+ })
+ }
+
+}
diff --git a/subprojects/core/src/integTest/groovy/org/gradle/process/internal/PathLimitationIntegTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/process/internal/PathLimitationIntegTest.groovy
new file mode 100644
index 0000000..b82d3c1
--- /dev/null
+++ b/subprojects/core/src/integTest/groovy/org/gradle/process/internal/PathLimitationIntegTest.groovy
@@ -0,0 +1,277 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.process.internal
+
+import org.apache.commons.lang.RandomStringUtils
+import org.gradle.CacheUsage
+import org.gradle.api.Action
+import org.gradle.api.internal.ClassPathRegistry
+import org.gradle.api.internal.DefaultClassPathProvider
+import org.gradle.api.internal.DefaultClassPathRegistry
+import org.gradle.api.internal.classpath.DefaultModuleRegistry
+import org.gradle.api.internal.classpath.ModuleRegistry
+import org.gradle.api.internal.file.TestFiles
+import org.gradle.api.logging.LogLevel
+import org.gradle.cache.CacheRepository
+import org.gradle.cache.internal.*
+import org.gradle.cache.internal.locklistener.NoOpFileLockContentionHandler
+import org.gradle.internal.id.LongIdGenerator
+import org.gradle.internal.jvm.Jvm
+import org.gradle.internal.nativeplatform.services.NativeServices
+import org.gradle.internal.os.OperatingSystem
+import org.gradle.listener.ListenerBroadcast
+import org.gradle.messaging.dispatch.Dispatch
+import org.gradle.messaging.dispatch.MethodInvocation
+import org.gradle.messaging.remote.MessagingServer
+import org.gradle.messaging.remote.ObjectConnection
+import org.gradle.messaging.remote.internal.MessagingServices
+import org.gradle.process.internal.child.WorkerProcessClassPathProvider
+import org.gradle.test.fixtures.file.TestFile
+import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
+import org.junit.Rule
+import spock.lang.Ignore
+import spock.lang.IgnoreIf
+import spock.lang.Specification
+import spock.lang.Unroll
+
+import static org.junit.Assert.assertFalse
+import static org.junit.Assert.assertTrue
+
+class PathLimitationIntegTest extends Specification {
+ private final TestListenerInterface listenerMock = Mock(TestListenerInterface.class);
+ private final MessagingServices messagingServices = new MessagingServices(getClass().getClassLoader());
+ private final MessagingServer server = messagingServices.get(MessagingServer.class);
+
+ @Rule
+ public final TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider();
+ private final ProcessMetaDataProvider metaDataProvider = new DefaultProcessMetaDataProvider(NativeServices.getInstance().get(org.gradle.internal.nativeplatform.ProcessEnvironment.class));
+ private final CacheFactory factory = new DefaultCacheFactory(new DefaultFileLockManager(metaDataProvider, new NoOpFileLockContentionHandler())).create();
+ private final CacheRepository cacheRepository = new DefaultCacheRepository(tmpDir.getTestDirectory(), null, CacheUsage.ON, factory);
+ private final ModuleRegistry moduleRegistry = new DefaultModuleRegistry();
+ private final ClassPathRegistry classPathRegistry = new DefaultClassPathRegistry(new DefaultClassPathProvider(moduleRegistry), new WorkerProcessClassPathProvider(cacheRepository, moduleRegistry));
+ private final DefaultWorkerProcessFactory workerFactory = new DefaultWorkerProcessFactory(LogLevel.INFO, server, classPathRegistry, TestFiles.resolver(tmpDir.getTestDirectory()), new LongIdGenerator());
+ private final ListenerBroadcast<TestListenerInterface> broadcast = new ListenerBroadcast<TestListenerInterface>(
+ TestListenerInterface.class);
+ private final RemoteExceptionListener exceptionListener = new RemoteExceptionListener(broadcast);
+
+ public void setup() {
+ broadcast.add(listenerMock);
+ }
+
+ public void after() {
+ messagingServices.stop();
+ }
+
+ @IgnoreIf({OperatingSystem.current().isWindows()})
+ @Unroll
+ def "WorkerProcessBuilder handles workingDir with absolute path length #absolutePathLength"() throws Throwable {
+ when:
+ def testWorkingDir = generateTestWorkingDirectory(absolutePathLength)
+ then:
+ assert testWorkingDir.exists()
+ execute(worker(new HelloWorldRemoteProcess(), testWorkingDir))
+ where:
+ absolutePathLength << [258, 259, 260]
+ }
+
+ @IgnoreIf({OperatingSystem.current().isWindows()})
+ @Unroll
+ def "JavaProcessBuilder handles workingDir with absolute path length #absolutePathLength"() throws Throwable {
+ when:
+ def testWorkingDir = generateTestWorkingDirectory(absolutePathLength)
+
+ assert testWorkingDir.exists()
+
+ ProcessBuilder processBuilder = new ProcessBuilder();
+ processBuilder.directory(testWorkingDir)
+
+ processBuilder.command(Jvm.current().getJavaExecutable().absolutePath, "-version")
+ then:
+ Process process = processBuilder.start()
+
+ process.waitFor() == 0
+ process.exitValue() == 0
+ and:
+ process.errorStream.text.contains("java version")
+
+ where:
+ absolutePathLength << [258, 259, 260]
+ }
+
+ @Ignore
+ @Unroll
+ def "OS handles workingDir with absolute path length #absolutePathLength"() throws Throwable {
+ setup:
+ def testWorkingDir = generateTestWorkingDirectory(absolutePathLength)
+ TestFile testBatchScript = tmpDir.getTestDirectory().createFile("testBatch.cmd")
+ testBatchScript.text = """
+ cd ${testWorkingDir.name}
+ java -version > o.txt 2>&1
+"""
+
+ when:
+
+ assert testWorkingDir.exists()
+ ProcessBuilder processBuilder = new ProcessBuilder();
+ processBuilder.directory(tmpDir.getTestDirectory())
+ processBuilder.command("CMD", "/C", "testBatch.cmd")
+
+ and:
+ Process process = processBuilder.start()
+
+ then:
+ process.waitFor() == 0
+ process.exitValue() == 0
+ and:
+ def outputText = new File(testWorkingDir, "o.txt").text
+ println outputText
+ assert outputText.contains("java version")
+ where:
+ absolutePathLength << [250, 255, 260] // 250 succeeds
+ // 255 fails because path + "/o.txt" >= 260
+ // 260 fails different because path >= 260
+ }
+
+
+ TestFile generateTestWorkingDirectory(int absolutePathLength) {
+ // windows can handle a path up to 260 characters (259 + NUL)
+ // we create a path that is 260 +1 (absolutePathLength + "/" + randompath)
+ def testDirectory = tmpDir.getTestDirectory()
+ def pathoffset = absolutePathLength - 1 - testDirectory.getAbsolutePath().length()
+ def alphanumeric = RandomStringUtils.randomAlphanumeric(pathoffset)
+ return testDirectory.createDir("$alphanumeric")
+ }
+
+ public static class HelloWorldRemoteProcess implements Action<WorkerProcessContext>, Serializable {
+ public void execute(WorkerProcessContext workerProcessContext) {
+ println "hello World!"
+ }
+ }
+
+ private ChildProcess worker(Action<? super WorkerProcessContext> action, File workingDirectory = tmpDir.getTestDirectory()) {
+
+ return new ChildProcess(action, workingDirectory);
+ }
+
+ void execute(ChildProcess... processes) throws Throwable {
+ for (ChildProcess process : processes) {
+ process.start();
+ }
+ for (ChildProcess process : processes) {
+ process.waitForStop();
+ }
+ messagingServices.stop();
+ exceptionListener.rethrow();
+ }
+
+ private class ChildProcess {
+ private boolean stopFails;
+ private boolean startFails;
+ private WorkerProcess proc;
+ private Action<? super WorkerProcessContext> action;
+ private List<String> jvmArgs = Collections.emptyList();
+ private Action<ObjectConnection> serverAction;
+ private final File workingDirectory
+
+ public ChildProcess(Action<? super WorkerProcessContext> action, File workingDirectory) {
+ this.workingDirectory = workingDirectory
+ this.action = action;
+ }
+
+ ChildProcess expectStopFailure() {
+ stopFails = true;
+ return this;
+ }
+
+ ChildProcess expectStartFailure() {
+ startFails = true;
+ return this;
+ }
+
+ public void start() {
+ WorkerProcessBuilder builder = workerFactory.create();
+ builder.worker(action);
+ builder.getJavaCommand().jvmArgs(jvmArgs);
+ builder.getJavaCommand().setWorkingDir(workingDirectory)
+
+ proc = builder.build();
+ try {
+ proc.start();
+ assertFalse(startFails);
+ } catch (ExecException e) {
+ println e
+ e.printStackTrace()
+ assertTrue(startFails);
+ return;
+ }
+ proc.getConnection().addIncoming(TestListenerInterface.class, exceptionListener);
+ if (serverAction != null) {
+ serverAction.execute(proc.getConnection());
+ }
+ }
+
+ public void waitForStop() {
+ if (startFails) {
+ return;
+ }
+ try {
+ proc.waitForStop();
+ assertFalse("Expected process to fail", stopFails);
+ } catch (ExecException e) {
+ assertTrue("Unexpected failure in worker process", stopFails);
+ }
+ }
+
+ public ChildProcess onServer(Action<ObjectConnection> action) {
+ this.serverAction = action;
+ return this;
+ }
+
+ public ChildProcess jvmArgs(String... jvmArgs) {
+ this.jvmArgs = Arrays.asList(jvmArgs);
+ return this;
+ }
+ }
+
+
+ public static class RemoteExceptionListener implements Dispatch<MethodInvocation> {
+ Throwable ex;
+ final Dispatch<MethodInvocation> dispatch;
+
+ public RemoteExceptionListener(Dispatch<MethodInvocation> dispatch) {
+ this.dispatch = dispatch;
+ }
+
+ public void dispatch(MethodInvocation message) {
+ try {
+ dispatch.dispatch(message);
+ } catch (Throwable e) {
+ ex = e;
+ }
+ }
+
+ public void rethrow() throws Throwable {
+ if (ex != null) {
+ throw ex;
+ }
+ }
+ }
+
+ public interface TestListenerInterface {
+ public void send(String message, int count);
+ }
+}
diff --git a/subprojects/core/src/integTest/groovy/org/gradle/process/internal/WorkerProcessIntegrationTest.java b/subprojects/core/src/integTest/groovy/org/gradle/process/internal/WorkerProcessIntegrationTest.java
index ad73aa9..6cb2c63 100644
--- a/subprojects/core/src/integTest/groovy/org/gradle/process/internal/WorkerProcessIntegrationTest.java
+++ b/subprojects/core/src/integTest/groovy/org/gradle/process/internal/WorkerProcessIntegrationTest.java
@@ -29,6 +29,7 @@ import org.gradle.api.internal.file.TestFiles;
import org.gradle.api.logging.LogLevel;
import org.gradle.cache.CacheRepository;
import org.gradle.cache.internal.*;
+import org.gradle.cache.internal.locklistener.NoOpFileLockContentionHandler;
import org.gradle.internal.id.LongIdGenerator;
import org.gradle.internal.nativeplatform.ProcessEnvironment;
import org.gradle.internal.nativeplatform.services.NativeServices;
@@ -71,7 +72,7 @@ public class WorkerProcessIntegrationTest {
@Rule
public final TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider();
private final ProcessMetaDataProvider metaDataProvider = new DefaultProcessMetaDataProvider(NativeServices.getInstance().get(ProcessEnvironment.class));
- private final CacheFactory factory = new DefaultCacheFactory(new DefaultFileLockManager(metaDataProvider)).create();
+ private final CacheFactory factory = new DefaultCacheFactory(new DefaultFileLockManager(metaDataProvider, new NoOpFileLockContentionHandler())).create();
private final CacheRepository cacheRepository = new DefaultCacheRepository(tmpDir.getTestDirectory(), null, CacheUsage.ON, factory);
private final ModuleRegistry moduleRegistry = new DefaultModuleRegistry();
private final ClassPathRegistry classPathRegistry = new DefaultClassPathRegistry(new DefaultClassPathProvider(moduleRegistry), new WorkerProcessClassPathProvider(cacheRepository, moduleRegistry));
diff --git a/subprojects/core/src/main/groovy/org/gradle/BuildListener.java b/subprojects/core/src/main/groovy/org/gradle/BuildListener.java
index a27aaad..3bb5583 100644
--- a/subprojects/core/src/main/groovy/org/gradle/BuildListener.java
+++ b/subprojects/core/src/main/groovy/org/gradle/BuildListener.java
@@ -19,10 +19,8 @@ import org.gradle.api.initialization.Settings;
import org.gradle.api.invocation.Gradle;
/**
- * <p>A {@code BuildListener} is notified of the major lifecycle events as a {@link GradleLauncher} instance executes a
- * build.</p>
+ * <p>A {@code BuildListener} is notified of the major lifecycle events as a build is executed.</p>
*
- * @author Hans Dockter
* @see org.gradle.api.invocation.Gradle#addListener(Object)
*/
public interface BuildListener {
diff --git a/subprojects/core/src/main/groovy/org/gradle/CacheUsage.java b/subprojects/core/src/main/groovy/org/gradle/CacheUsage.java
index 913c4af..0d044a9 100644
--- a/subprojects/core/src/main/groovy/org/gradle/CacheUsage.java
+++ b/subprojects/core/src/main/groovy/org/gradle/CacheUsage.java
@@ -21,7 +21,6 @@ import org.gradle.api.InvalidUserDataException;
* <p>{@code CacheUsage} specifies how compiled scripts should be cached.</p>
*
* @deprecated This enum has been deprecated. Use {@link StartParameter#isRerunTasks()} and {@link StartParameter#isRecompileScripts()} instead.
- * @author Hans Dockter
*/
@Deprecated
public enum CacheUsage {
diff --git a/subprojects/core/src/main/groovy/org/gradle/GradleLauncher.java b/subprojects/core/src/main/groovy/org/gradle/GradleLauncher.java
index 7d58db8..1214dae 100644
--- a/subprojects/core/src/main/groovy/org/gradle/GradleLauncher.java
+++ b/subprojects/core/src/main/groovy/org/gradle/GradleLauncher.java
@@ -15,16 +15,19 @@
*/
package org.gradle;
+import org.gradle.internal.service.scopes.GlobalScopeServices;
import org.gradle.api.logging.StandardOutputListener;
-import org.gradle.initialization.DefaultGradleLauncherFactory;
import org.gradle.initialization.GradleLauncherFactory;
+import org.gradle.util.DeprecationLogger;
/**
- * <p>{@code GradleLauncher} is mildly deprecated. It is being replaced by the Tooling API.
- * If you're interested in embedding Gradle you should read the new user guide chapter on embedding Gradle.
+ * <p>Executes a Gradle build.
+ *
+ * <p>{@code GradleLauncher} is deprecated. It has been replaced by the Tooling API.
+ * If you're interested in embedding Gradle you should read the user guide chapter on embedding Gradle.
* The main entry point to the Tooling API (and embedding Gradle) is {@code org.gradle.tooling.GradleConnector}.
*
- * <p>You should try using the Tooling API ({@code GradleConnector}) instead of {@code GradleLauncher}.
+ * <p>You should try using the Tooling API (via {@code GradleConnector}) instead of {@code GradleLauncher}.
* However, if you need some capability that isn't yet implemented in the Tooling API here is how you use {@code GradleLauncher}:
*
* <ol>
@@ -46,8 +49,9 @@ import org.gradle.initialization.GradleLauncherFactory;
*
* </ol>
*
- * @author Hans Dockter
+ * @deprecated Use the tooling API instead.
*/
+ at Deprecated
public abstract class GradleLauncher {
private static GradleLauncherFactory factory;
@@ -82,14 +86,23 @@ public abstract class GradleLauncher {
*
* @param startParameter The start parameter object the GradleLauncher instance is initialized with
* @return The {@code GradleLauncher}. Never returns null.
+ * @deprecated Use the tooling API instead.
*/
- public static GradleLauncher newInstance(final StartParameter startParameter) {
- return getFactory().newInstance(startParameter);
+ @Deprecated
+ public static GradleLauncher newInstance(StartParameter startParameter) {
+ DeprecationLogger.nagUserOfDiscontinuedMethod("GradleLauncher.newInstance()");
+ return doGetFactory().newInstance(startParameter);
+ }
+
+ @Deprecated
+ public static GradleLauncherFactory getFactory() {
+ DeprecationLogger.nagUserOfDiscontinuedMethod("GradleLauncher.getFactory()");
+ return doGetFactory();
}
- public static synchronized GradleLauncherFactory getFactory() {
+ private static synchronized GradleLauncherFactory doGetFactory() {
if (factory == null) {
- factory = new DefaultGradleLauncherFactory();
+ factory = new GlobalScopeServices().get(GradleLauncherFactory.class);
}
return factory;
}
@@ -99,9 +112,13 @@ public abstract class GradleLauncher {
*
* @param commandLineArgs A String array where each element denotes an entry of the Gradle command line syntax
* @return The {@code GradleLauncher}. Never returns null.
+ * @deprecated Use the tooling API instead.
*/
+ @Deprecated
public static GradleLauncher newInstance(String... commandLineArgs) {
- return newInstance(createStartParameter(commandLineArgs));
+ DeprecationLogger.nagUserOfDiscontinuedMethod("GradleLauncher.newInstance()");
+ GradleLauncherFactory gradleLauncherFactory = doGetFactory();
+ return gradleLauncherFactory.newInstance(gradleLauncherFactory.createStartParameter(commandLineArgs));
}
/**
@@ -110,11 +127,15 @@ public abstract class GradleLauncher {
*
* @param commandLineArgs A String array where each element denotes an entry of the Gradle command line syntax
* @return The {@code GradleLauncher}. Never returns null.
+ * @deprecated No replacement.
*/
- public static StartParameter createStartParameter(final String... commandLineArgs) {
- return getFactory().createStartParameter(commandLineArgs);
+ @Deprecated
+ public static StartParameter createStartParameter(String... commandLineArgs) {
+ DeprecationLogger.nagUserOfDiscontinuedMethod("GradleLauncher.createStartParameter()");
+ return doGetFactory().createStartParameter(commandLineArgs);
}
+ @Deprecated
public static synchronized void injectCustomFactory(GradleLauncherFactory gradleLauncherFactory) {
factory = gradleLauncherFactory;
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/StartParameter.java b/subprojects/core/src/main/groovy/org/gradle/StartParameter.java
index ab9741d..2557618 100644
--- a/subprojects/core/src/main/groovy/org/gradle/StartParameter.java
+++ b/subprojects/core/src/main/groovy/org/gradle/StartParameter.java
@@ -22,11 +22,13 @@ import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.gradle.api.Incubating;
import org.gradle.api.internal.classpath.DefaultModuleRegistry;
+import org.gradle.initialization.BuildLayoutParameters;
import org.gradle.initialization.CompositeInitScriptFinder;
import org.gradle.initialization.DistributionInitScriptFinder;
import org.gradle.initialization.UserHomeInitScriptFinder;
import org.gradle.internal.SystemProperties;
import org.gradle.logging.LoggingConfiguration;
+import org.gradle.util.DeprecationLogger;
import org.gradle.util.GFileUtils;
import java.io.File;
@@ -34,12 +36,13 @@ import java.io.Serializable;
import java.util.*;
/**
- * <p>{@code StartParameter} defines the configuration used by a {@link GradleLauncher} instance to execute a build. The properties of {@code StartParameter} generally correspond to the command-line
- * options of Gradle. You pass a {@code StartParameter} instance to {@link GradleLauncher#newInstance(StartParameter)} when you create a new {@code Gradle} instance.</p>
+ * <p>{@code StartParameter} defines the configuration used by a Gradle instance to execute a build. The properties of {@code StartParameter} generally
+ * correspond to the command-line options of Gradle.
+ *
+ * <p>You pass a {@code StartParameter} instance to {@link GradleLauncher#newInstance(StartParameter)} when you create a new Gradle instance.</p>
*
* <p>You can obtain an instance of a {@code StartParameter} by either creating a new one, or duplicating an existing one using {@link #newInstance} or {@link #newBuild}.</p>
*
- * @author Hans Dockter
* @see GradleLauncher
*/
public class StartParameter extends LoggingConfiguration implements Serializable {
@@ -50,11 +53,11 @@ public class StartParameter extends LoggingConfiguration implements Serializable
public static final File DEFAULT_GRADLE_USER_HOME = new File(SystemProperties.getUserHome() + "/.gradle");
private List<String> taskNames = new ArrayList<String>();
- private Set<String> excludedTaskNames = new HashSet<String>();
+ private Set<String> excludedTaskNames = new LinkedHashSet<String>();
private boolean buildProjectDependencies = true;
private File currentDir;
private File projectDir;
- private boolean searchUpwards = true;
+ private boolean searchUpwards;
private Map<String, String> projectProperties = new HashMap<String, String>();
private Map<String, String> systemPropertiesArgs = new HashMap<String, String>();
private File gradleUserHomeDir;
@@ -74,7 +77,6 @@ public class StartParameter extends LoggingConfiguration implements Serializable
private boolean recompileScripts;
private int parallelThreadCount;
private boolean configureOnDemand;
- private boolean parallelThreadCountConfigured;
/**
* Sets the project's cache location. Set to null to use the default location.
@@ -96,18 +98,12 @@ public class StartParameter extends LoggingConfiguration implements Serializable
* Creates a {@code StartParameter} with default values. This is roughly equivalent to running Gradle on the command-line with no arguments.
*/
public StartParameter() {
- String gradleUserHome = System.getProperty(GRADLE_USER_HOME_PROPERTY_KEY);
- if (gradleUserHome == null) {
- gradleUserHome = System.getenv("GRADLE_USER_HOME");
- if (gradleUserHome == null) {
- gradleUserHome = DEFAULT_GRADLE_USER_HOME.getAbsolutePath();
- }
- }
-
- gradleUserHomeDir = GFileUtils.canonicalise(new File(gradleUserHome));
gradleHomeDir = new DefaultModuleRegistry().getGradleHome();
- setCurrentDir(null);
+ BuildLayoutParameters layoutDefaults = new BuildLayoutParameters();
+ searchUpwards = layoutDefaults.getSearchUpwards();
+ currentDir = layoutDefaults.getProjectDir();
+ gradleUserHomeDir = layoutDefaults.getGradleUserHomeDir();
}
/**
@@ -123,7 +119,7 @@ public class StartParameter extends LoggingConfiguration implements Serializable
p.settingsFile = settingsFile;
p.useEmptySettings = useEmptySettings;
p.taskNames = new ArrayList<String>(taskNames);
- p.excludedTaskNames = new HashSet<String>(excludedTaskNames);
+ p.excludedTaskNames = new LinkedHashSet<String>(excludedTaskNames);
p.buildProjectDependencies = buildProjectDependencies;
p.currentDir = currentDir;
p.searchUpwards = searchUpwards;
@@ -138,7 +134,7 @@ public class StartParameter extends LoggingConfiguration implements Serializable
}
/**
- * <p>Creates the parameters for a new build, using these parameters as a template. Copies the environmental properties from this parameter (eg gradle user home dir, etc), but does not copy the
+ * <p>Creates the parameters for a new build, using these parameters as a template. Copies the environmental properties from this parameter (eg Gradle user home dir, etc), but does not copy the
* build specific properties (eg task names).</p>
*
* @return The new parameters.
@@ -285,7 +281,7 @@ public class StartParameter extends LoggingConfiguration implements Serializable
if (currentDir != null) {
this.currentDir = GFileUtils.canonicalise(currentDir);
} else {
- this.currentDir = GFileUtils.canonicalise(SystemProperties.getCurrentDir());
+ this.currentDir = new BuildLayoutParameters().getProjectDir();
}
}
@@ -314,11 +310,17 @@ public class StartParameter extends LoggingConfiguration implements Serializable
}
/**
+ * Deprecated. It is no longer used internally and there's no good reason to keep it.
+ * There is no replacement method.
+ *
* Returns a newly constructed map that is the JVM system properties merged with the system property args. <p> System property args take precedence over JVM system properties.
*
* @return The merged system properties
+ * @deprecated No replacement
*/
+ @Deprecated
public Map<String, String> getMergedSystemProperties() {
+ DeprecationLogger.nagUserOfDiscontinuedMethod("StartParameter.getMergedSystemProperties()");
Map<String, String> merged = new HashMap<String, String>();
merged.putAll((Map) System.getProperties());
merged.putAll(getSystemPropertiesArgs());
@@ -363,7 +365,7 @@ public class StartParameter extends LoggingConfiguration implements Serializable
/**
* Returns the configured CacheUsage.
* @deprecated Use {@link #isRecompileScripts} and/or {@link #isRerunTasks} instead.
- * */
+ */
@Deprecated
public CacheUsage getCacheUsage() {
return cacheUsage;
@@ -372,7 +374,7 @@ public class StartParameter extends LoggingConfiguration implements Serializable
/**
* Sets the Cache usage.
* @deprecated Use {@link #setRecompileScripts} and/or {@link #setRerunTasks} instead.
- * */
+ */
@Deprecated
public void setCacheUsage(CacheUsage cacheUsage) {
this.cacheUsage = cacheUsage;
@@ -390,7 +392,7 @@ public class StartParameter extends LoggingConfiguration implements Serializable
* Returns task optimization disabled flag.
*
* @deprecated Use {@link #isRerunTasks} instead.
- * */
+ */
@Deprecated
public boolean isNoOpt() {
return rerunTasks;
@@ -400,7 +402,7 @@ public class StartParameter extends LoggingConfiguration implements Serializable
* Get task optimization disabled.
*
* @param noOpt The boolean value for disabling task optimization.
- * @deprecated Use {@link #setRefreshDependencies(boolean)} instead.
+ * @deprecated Use {@link #setRerunTasks(boolean)} instead.
*/
@Deprecated
public void setNoOpt(boolean noOpt) {
@@ -626,7 +628,6 @@ public class StartParameter extends LoggingConfiguration implements Serializable
* @see #getParallelThreadCount()
*/
public void setParallelThreadCount(int parallelThreadCount) {
- this.parallelThreadCountConfigured = true;
this.parallelThreadCount = parallelThreadCount;
}
@@ -638,14 +639,6 @@ public class StartParameter extends LoggingConfiguration implements Serializable
return configureOnDemand;
}
- @Incubating
- public boolean isParallelThreadCountConfigured() {
- //This is not beautiful. As the number of gradle properties grows we may something like:
- //1. Make StartParameter an interface
- //2. StartParameter (StartParameterInternal) needs to inform if certain property was configured or not
- return parallelThreadCountConfigured;
- }
-
@Override
public String toString() {
return "StartParameter{"
diff --git a/subprojects/core/src/main/groovy/org/gradle/TaskExecutionLogger.java b/subprojects/core/src/main/groovy/org/gradle/TaskExecutionLogger.java
index af71a38..a47d39a 100644
--- a/subprojects/core/src/main/groovy/org/gradle/TaskExecutionLogger.java
+++ b/subprojects/core/src/main/groovy/org/gradle/TaskExecutionLogger.java
@@ -31,7 +31,7 @@ import java.util.Map;
* A listener which logs the execution of tasks.
*/
public class TaskExecutionLogger implements TaskExecutionListener {
- // TODO:PARALLEL Seems to be some thread-safety issues here (get 'failed' logged for wrong task)
+
private final Map<Task, ProgressLogger> currentTasks = new HashMap<Task, ProgressLogger>();
private final ProgressLoggerFactory progressLoggerFactory;
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/CircularReferenceException.java b/subprojects/core/src/main/groovy/org/gradle/api/CircularReferenceException.java
index 34b7d5c..a7f9244 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/CircularReferenceException.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/CircularReferenceException.java
@@ -19,8 +19,6 @@ package org.gradle.api;
/**
* <p>A <code>CircularReferenceException</code> is thrown if circular references exists between tasks, the project
* evaluation order or the project dependsOn order.</p>
- *
- * @author Hans Dockter
*/
public class CircularReferenceException extends GradleException {
public CircularReferenceException(String message) {
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/DefaultTask.java b/subprojects/core/src/main/groovy/org/gradle/api/DefaultTask.java
index e34301e..b0a7605 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/DefaultTask.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/DefaultTask.java
@@ -23,8 +23,6 @@ import org.gradle.api.internal.NoConventionMapping;
/**
* {@code DefaultTask} is the standard {@link Task} implementation. You can extend this to implement your own task types.
- *
- * @author Hans Dockter
*/
@NoConventionMapping
public class DefaultTask extends AbstractTask {
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/ExtensiblePolymorphicDomainObjectContainer.java b/subprojects/core/src/main/groovy/org/gradle/api/ExtensiblePolymorphicDomainObjectContainer.java
index 5df7fe2..39ebe9c 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/ExtensiblePolymorphicDomainObjectContainer.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/ExtensiblePolymorphicDomainObjectContainer.java
@@ -15,6 +15,8 @@
*/
package org.gradle.api;
+import groovy.lang.Closure;
+
/**
* A {@link org.gradle.api.PolymorphicDomainObjectContainer} that can be extended at runtime to
* create elements of new types.
@@ -34,4 +36,30 @@ public interface ExtensiblePolymorphicDomainObjectContainer<T> extends Polymorph
* @throws IllegalArgumentException if the specified type is not a subtype of the container element type
*/
public <U extends T> void registerFactory(Class<U> type, NamedDomainObjectFactory<? extends U> factory);
+
+ /**
+ * Registers a factory for creating elements of the specified type.
+ * Typically, the specified type is an interface type.
+ *
+ * @param type the type of objects created by the factory
+ * @param factory the factory to register
+ * @param <U> the type of objects created by the factory
+ *
+ * @throws IllegalArgumentException if the specified type is not a subtype of the container element type
+ */
+ public <U extends T> void registerFactory(Class<U> type, final Closure<? extends U> factory);
+
+ /**
+ * Registers a binding from the specified "public" domain object type to the specified implementation type.
+ * Whenever the container is asked to create an element with the binding's public type, it will instantiate
+ * the binding's implementation type. If the implementation type has a constructor annotated with
+ * {@link javax.inject.Inject}, its arguments will be injected.
+ *
+ * <p>In general, registering a binding is preferable over implementing and registering a factory.
+ *
+ * @param type a public domain object type
+ * @param implementationType the corresponding implementation type
+ * @param <U> a public domain object type
+ */
+ public <U extends T> void registerBinding(Class<U> type, final Class<? extends U> implementationType);
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/GradleScriptException.java b/subprojects/core/src/main/groovy/org/gradle/api/GradleScriptException.java
index 544a249..249926d 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/GradleScriptException.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/GradleScriptException.java
@@ -20,8 +20,6 @@ import org.gradle.api.internal.Contextual;
/**
* <p>A <code>GradleScriptException</code> is thrown when an exception occurs in the compilation or execution of a
* script.</p>
- *
- * @author Hans Dockter
*/
@Contextual
public class GradleScriptException extends GradleException {
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/IllegalDependencyNotation.java b/subprojects/core/src/main/groovy/org/gradle/api/IllegalDependencyNotation.java
index 8d965a8..569babf 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/IllegalDependencyNotation.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/IllegalDependencyNotation.java
@@ -17,8 +17,6 @@ package org.gradle.api;
/**
* This exceptions is thrown, if a dependency is declared with a illegal notation.
- *
- * @author Hans Dockter
*/
public class IllegalDependencyNotation extends GradleException {
public IllegalDependencyNotation() {
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/IllegalOperationAtExecutionTimeException.java b/subprojects/core/src/main/groovy/org/gradle/api/IllegalOperationAtExecutionTimeException.java
index 412c520..8391b3f 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/IllegalOperationAtExecutionTimeException.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/IllegalOperationAtExecutionTimeException.java
@@ -19,8 +19,9 @@ package org.gradle.api;
* A <code>IllegalOperationAtExecutionTimeException</code> is thrown if you try to trigger an operation at runtime,
* which is only allowed at configuration time.
*
- * @author Hans Dockter
+ * @deprecated No replacement
*/
+ at Deprecated
public class IllegalOperationAtExecutionTimeException extends InvalidUserDataException {
public IllegalOperationAtExecutionTimeException(String message) {
super(message);
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/InvalidUserDataException.java b/subprojects/core/src/main/groovy/org/gradle/api/InvalidUserDataException.java
index f166d61..0c5865f 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/InvalidUserDataException.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/InvalidUserDataException.java
@@ -18,8 +18,6 @@ package org.gradle.api;
/**
* A <code>InvalidUserDataException</code> is thrown, if a user is providing illegal data for the build.
- *
- * @author Hans Dockter
*/
public class InvalidUserDataException extends GradleException {
public InvalidUserDataException() {
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/NamedDomainObjectCollection.java b/subprojects/core/src/main/groovy/org/gradle/api/NamedDomainObjectCollection.java
index aabc1a6..d5d5e82 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/NamedDomainObjectCollection.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/NamedDomainObjectCollection.java
@@ -21,6 +21,7 @@ import org.gradle.api.specs.Spec;
import java.util.Collection;
import java.util.List;
import java.util.SortedMap;
+import java.util.SortedSet;
/**
* <p>A {@code NamedDomainObjectCollection} represents a collection of domain objects that have an inherent, constant, name.</p>
@@ -102,6 +103,15 @@ public interface NamedDomainObjectCollection<T> extends DomainObjectCollection<T
SortedMap<String, T> getAsMap();
/**
+ * <p>Returns the names of the objects in this collection as a Set of Strings.</p>
+ *
+ * <p>The set of names is in <em>natural ordering</em>.</p>
+ *
+ * @return The names. Returns an empty set if this collection is empty.
+ */
+ SortedSet<String> getNames();
+
+ /**
* Locates an object by name, returning null if there is no such object.
*
* @param name The object name
@@ -120,7 +130,7 @@ public interface NamedDomainObjectCollection<T> extends DomainObjectCollection<T
/**
* Locates an object by name, failing if there is no such object. The given configure closure is executed against
- * the object before it is returned from this method. The object is passed to the closure as it's delegate.
+ * the object before it is returned from this method. The object is passed to the closure as its delegate.
*
* @param name The object name
* @param configureClosure The closure to use to configure the object.
@@ -179,4 +189,4 @@ public interface NamedDomainObjectCollection<T> extends DomainObjectCollection<T
*/
NamedDomainObjectCollection<T> matching(Closure spec);
-}
\ No newline at end of file
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/NamedDomainObjectContainer.java b/subprojects/core/src/main/groovy/org/gradle/api/NamedDomainObjectContainer.java
index fa836d8..8532bfb 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/NamedDomainObjectContainer.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/NamedDomainObjectContainer.java
@@ -61,6 +61,16 @@ public interface NamedDomainObjectContainer<T> extends NamedDomainObjectSet<T>,
T create(String name, Closure configureClosure) throws InvalidUserDataException;
/**
+ * Creates a new item with the given name, adding it to this container, then configuring it with the given action.
+ *
+ * @param name The name to assign to the created object
+ * @param configureAction The action to configure the created object with
+ * @return The created object. Never null.
+ * @throws InvalidUserDataException if an object with the given name already exists in this container.
+ */
+ T create(String name, Action<? super T> configureAction) throws InvalidUserDataException;
+
+ /**
* <p>Allows the container to be configured, creating missing objects as they are referenced.</p>
*
* <p>TODO: example usage</p>
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/NonExtensible.java b/subprojects/core/src/main/groovy/org/gradle/api/NonExtensible.java
new file mode 100644
index 0000000..d927381
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/NonExtensible.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api;
+
+import java.lang.annotation.*;
+
+/**
+ * Indicates that the type, when DSL enhanced, does not support extensibility.
+ * <p>
+ * This means that it will not be enhanced with {@link org.gradle.api.plugins.ExtensionAware}.
+ */
+ at Incubating
+ at Documented
+ at Retention(RetentionPolicy.RUNTIME)
+ at Inherited
+ at Target({ElementType.TYPE})
+public @interface NonExtensible {}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/Plugin.java b/subprojects/core/src/main/groovy/org/gradle/api/Plugin.java
index 67e207f..6ed1d38 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/Plugin.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/Plugin.java
@@ -20,8 +20,7 @@ package org.gradle.api;
* Usually, this target object is a {@link org.gradle.api.Project}, but plugins can be applied to any type of
* objects.</p>
*
- * @author Hans Dockter
- * @param <T> The type of object which this plugin can configure.
+ * @param <T> The type of object which this plugin can configure.
*/
public interface Plugin<T> {
/**
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/Project.java b/subprojects/core/src/main/groovy/org/gradle/api/Project.java
index 8d97a1e..a9d998c 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/Project.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/Project.java
@@ -32,10 +32,7 @@ import org.gradle.api.internal.HasInternalProtocol;
import org.gradle.api.invocation.Gradle;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.LoggingManager;
-import org.gradle.api.plugins.Convention;
-import org.gradle.api.plugins.ExtensionAware;
-import org.gradle.api.plugins.ExtensionContainer;
-import org.gradle.api.plugins.PluginContainer;
+import org.gradle.api.plugins.*;
import org.gradle.api.resources.ResourceHandler;
import org.gradle.api.tasks.TaskContainer;
import org.gradle.api.tasks.WorkResult;
@@ -190,11 +187,9 @@ import java.util.Set;
* <li>The parent project, recursively up to the root project.</li>
*
* </ul>
- *
- * @author Hans Dockter
*/
@HasInternalProtocol
-public interface Project extends Comparable<Project>, ExtensionAware {
+public interface Project extends Comparable<Project>, ExtensionAware, PluginAware {
/**
* The default project build file name.
*/
@@ -973,7 +968,7 @@ public interface Project extends Comparable<Project>, ExtensionAware {
* </target>
* </pre>
*
- * Here's how it would look like in gradle. Observe how the ant xml is represented in groovy by the ant builder
+ * Here's how it would look like in gradle. Observe how the ant XML is represented in groovy by the ant builder
* <pre autoTested=''>
* task printChecksum {
* doLast {
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/ProjectConfigurationException.java b/subprojects/core/src/main/groovy/org/gradle/api/ProjectConfigurationException.java
new file mode 100644
index 0000000..ffbd0ec
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/ProjectConfigurationException.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api;
+
+import org.gradle.api.internal.Contextual;
+
+/**
+ * Indicates a problem that occurs during project configuration (evaluation) phase.
+ */
+ at Contextual
+public class ProjectConfigurationException extends GradleException {
+ public ProjectConfigurationException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/ProjectEvaluationListener.java b/subprojects/core/src/main/groovy/org/gradle/api/ProjectEvaluationListener.java
index f91cdff..f5e9f74 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/ProjectEvaluationListener.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/ProjectEvaluationListener.java
@@ -19,8 +19,6 @@ package org.gradle.api;
* <p>An {@code ProjectEvaluationListener} is notified when a project is evaluated. You add can add an {@code
* ProjectEvaluationListener} to a {@link org.gradle.api.invocation.Gradle} using {@link
* org.gradle.api.invocation.Gradle#addProjectEvaluationListener(ProjectEvaluationListener)}.</p>
- *
- * @author Hans Dockter
*/
public interface ProjectEvaluationListener {
/**
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/ProjectState.java b/subprojects/core/src/main/groovy/org/gradle/api/ProjectState.java
index 5fb4a1d..230552f 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/ProjectState.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/ProjectState.java
@@ -16,9 +16,12 @@
package org.gradle.api;
+import org.gradle.api.internal.HasInternalProtocol;
+
/**
* {@code ProjectState} provides information about the execution state of a project.
*/
+ at HasInternalProtocol
public interface ProjectState {
/**
* <p>Returns true if this project has been evaluated.</p>
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/Rule.java b/subprojects/core/src/main/groovy/org/gradle/api/Rule.java
index b589e76..34d6e91 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/Rule.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/Rule.java
@@ -18,8 +18,6 @@ package org.gradle.api;
/**
* <p>A {@code Rule} represents some action to perform when an unknown domain object is referenced. The rule can use the
* domain object name to add an implicit domain object.</p>
- *
- * @author Hans Dockter
*/
public interface Rule {
/**
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/Task.java b/subprojects/core/src/main/groovy/org/gradle/api/Task.java
index 6d24910..47c271c 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/Task.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/Task.java
@@ -69,12 +69,15 @@ import java.util.Set;
* next task by throwing a {@link org.gradle.api.tasks.StopExecutionException}. Using these exceptions allows you to
* have precondition actions which skip execution of the task, or part of the task, if not true.</p>
*
- * <a name="dependencies"/><h3>Dependencies</h3>
+ * <a name="dependencies"/><h3>Task Dependencies and Task Ordering</h3>
*
- * <p>A task may have dependencies on other tasks. Gradle ensures that tasks are executed in dependency order, so that
- * the dependencies of a task are executed before the task is executed. You can add dependencies to a task using {@link
- * #dependsOn(Object...)} or {@link #setDependsOn(Iterable)}. You can add objects of any of the following types as a
- * dependency:</p>
+ * <p>A task may have dependencies on other tasks or might be scheduled to always run after another task.
+ * Gradle ensures that all task dependencies and ordering rules are honored when executing tasks, so that the task is executed after
+ * all of its dependencies and any "must run after" tasks have been executed.</p>
+ *
+ * <p>Dependencies to a task are controlled using {@link #dependsOn(Object...)} or {@link #setDependsOn(Iterable)},
+ * and {@link #mustRunAfter(Object...)} or {@link #setMustRunAfter(Iterable)} are used to specify ordering between tasks. You can use objects
+ * of any of the following types to specify dependencies and ordering:</p>
*
* <ul>
*
@@ -127,8 +130,6 @@ import java.util.Set;
* <h4>Dynamic Methods</h4>
*
* <p>A {@link Plugin} may add methods to a {@code Task} using its {@link Convention} object.</p>
- *
- * @author Hans Dockter
*/
public interface Task extends Comparable<Task>, ExtensionAware {
public static final String TASK_NAME = "name";
@@ -538,5 +539,99 @@ public interface Task extends Comparable<Task>, ExtensionAware {
* @return The directory. Never returns null. The directory will already exist.
*/
File getTemporaryDir();
+
+ /**
+ * <p>Specifies that this task must run after all of the supplied tasks.</p>
+ *
+ * <pre autoTested="true">
+ * task taskY {
+ * mustRunAfter "taskX"
+ * }
+ * </pre>
+ *
+ * <p>For each supplied task, this action adds a task 'ordering', and does not specify a 'dependency' between the tasks.
+ * As such, it is still possible to execute 'taskY' without first executing the 'taskX' in the example.</p>
+ *
+ * <p>See <a href="#dependencies">here</a> for a description of the types of objects which can be used to specify
+ * an ordering relationship.</p>
+ *
+ * @param paths The tasks this task must run after.
+ *
+ * @return the task object this method is applied to
+ */
+ @Incubating
+ Task mustRunAfter(Object... paths);
+
+ /**
+ * <p>Specifies the set of tasks that this task must run after.</p>
+ *
+ * <pre autoTested="true">
+ * task taskY {
+ * mustRunAfter = ["taskX1", "taskX2"]
+ * }
+ * </pre>
+ *
+ * <p>For each supplied task, this action adds a task 'ordering', and does not specify a 'dependency' between the tasks.
+ * As such, it is still possible to execute 'taskY' without first executing the 'taskX' in the example.</p>
+ *
+ * <p>See <a href="#dependencies">here</a> for a description of the types of objects which can be used to specify
+ * an ordering relationship.</p>
+ *
+ * @param mustRunAfter The set of task paths this task must run after.
+ */
+ @Incubating
+ void setMustRunAfter(Iterable<?> mustRunAfter);
+
+ /**
+ * <p>Returns tasks that this task must run after.</p>
+ *
+ * @return The tasks that this task must run after. Returns an empty set if this task has no tasks it must run after.
+ */
+ @Incubating
+ TaskDependency getMustRunAfter();
+
+ /**
+ * <p>Adds the given finalizer tasks for this task.</p>
+ *
+ * <pre autoTested="true">
+ * task taskY {
+ * finalizedBy "taskX"
+ * }
+ * </pre>
+ *
+ * <p>See <a href="#dependencies">here</a> for a description of the types of objects which can be used to specify
+ * a finalizer task.</p>
+ *
+ * @param paths The tasks that finalize this task.
+ *
+ * @return the task object this method is applied to
+ */
+ @Incubating
+ Task finalizedBy(Object... paths);
+
+ /**
+ * <p>Specifies the set of finalizer tasks for this task.</p>
+ *
+ * <pre autoTested="true">
+ * task taskY {
+ * finalizedBy = ["taskX1", "taskX2"]
+ * }
+ * </pre>
+ *
+ * <p>See <a href="#dependencies">here</a> for a description of the types of objects which can be used to specify
+ * a finalizer task.</p>
+ *
+ * @param finalizedBy The tasks that finalize this task.
+ */
+ @Incubating
+ void setFinalizedBy(Iterable<?> finalizedBy);
+
+ /**
+ * <p>Returns tasks that finalize this task.</p>
+ *
+ * @return The tasks that finalize this task. Returns an empty set if there are no finalising tasks for this task.
+ */
+ @Incubating
+ TaskDependency getFinalizedBy();
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/UnknownProjectException.java b/subprojects/core/src/main/groovy/org/gradle/api/UnknownProjectException.java
index 1653dbb..519213a 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/UnknownProjectException.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/UnknownProjectException.java
@@ -18,8 +18,6 @@ package org.gradle.api;
/**
* <p>An <code>UnknownProjectException</code> is thrown when a project referenced by path cannot be found.</p>
- *
- * @author Hans Dockter
*/
public class UnknownProjectException extends UnknownDomainObjectException {
public UnknownProjectException(String message) {
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/UnknownTaskException.java b/subprojects/core/src/main/groovy/org/gradle/api/UnknownTaskException.java
index 70aa432..2a87031 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/UnknownTaskException.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/UnknownTaskException.java
@@ -18,8 +18,6 @@ package org.gradle.api;
/**
* <p>An <code>UnknownTaskException</code> is thrown when a task referenced by path cannot be found.</p>
- *
- * @author Hans Dockter
*/
public class UnknownTaskException extends UnknownDomainObjectException {
public UnknownTaskException(String message) {
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/XmlProvider.java b/subprojects/core/src/main/groovy/org/gradle/api/XmlProvider.java
index 7f2e961..4958ab0 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/XmlProvider.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/XmlProvider.java
@@ -20,8 +20,6 @@ import org.w3c.dom.Element;
/**
* Provides various ways to access the content of an XML document.
- *
- * @author Hans Dockter
*/
public interface XmlProvider {
/**
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ArtifactIdentifier.java b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ArtifactIdentifier.java
index 85cc620..cd02402 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ArtifactIdentifier.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ArtifactIdentifier.java
@@ -25,13 +25,13 @@ public interface ArtifactIdentifier {
ModuleVersionIdentifier getModuleVersionIdentifier();
/**
- * Returns the name of the dependency artifact.
+ * Returns the name of this artifact.
*/
String getName();
/**
- * Returns the type of the dependency artifact. Often the type is the same as the extension,
- * but sometimes this is not the case. For example for an ivy xml module descriptor, the type is
+ * Returns the type of this artifact. Often the type is the same as the extension,
+ * but sometimes this is not the case. For example for an ivy XML module descriptor, the type is
* <em>ivy</em> and the extension is <em>xml</em>.
*
* @see #getExtension()
@@ -39,8 +39,8 @@ public interface ArtifactIdentifier {
String getType();
/**
- * Returns the extension of this dependency artifact. Often the extension is the same as the type,
- * but sometimes this is not the case. For example for an ivy xml module descriptor, the type is
+ * Returns the extension of this artifact. Often the extension is the same as the type,
+ * but sometimes this is not the case. For example for an ivy XML module descriptor, the type is
* <em>ivy</em> and the extension is <em>xml</em>.
*
* @see #getType()
@@ -48,7 +48,7 @@ public interface ArtifactIdentifier {
String getExtension();
/**
- * Returns the classifier of this dependency artifact.
+ * Returns the classifier of this artifact, if any.
*/
String getClassifier();
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ArtifactRepositoryContainer.java b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ArtifactRepositoryContainer.java
index 14cbc80..9640e79 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ArtifactRepositoryContainer.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ArtifactRepositoryContainer.java
@@ -33,33 +33,37 @@ import java.util.List;
* <p>The resolvers in a container are accessible as read-only properties of the container, using the name of the
* resolver as the property name. For example:</p>
*
- * <pre>
- * resolvers.addLast(name: 'myResolver')
- * resolvers.myResolver.url = 'some-url'
+ * <pre autoTested=''>
+ * repositories.maven { name 'myResolver' }
+ * repositories.myResolver.url = 'some-url'
* </pre>
*
* <p>A dynamic method is added for each resolver which takes a configuration closure. This is equivalent to calling
* {@link #getByName(String, groovy.lang.Closure)}. For example:</p>
*
- * <pre>
- * resolvers.addLast(name: 'myResolver')
- * resolvers.myResolver {
+ * <pre autoTested=''>
+ * repositories.maven { name 'myResolver' }
+ * repositories.myResolver {
* url 'some-url'
* }
* </pre>
- *
- * @author Hans Dockter
*/
public interface ArtifactRepositoryContainer extends NamedDomainObjectList<ArtifactRepository>, Configurable<ArtifactRepositoryContainer> {
String DEFAULT_MAVEN_CENTRAL_REPO_NAME = "MavenRepo";
String DEFAULT_MAVEN_LOCAL_REPO_NAME = "MavenLocal";
String MAVEN_CENTRAL_URL = "http://repo1.maven.org/maven2/";
+ @Deprecated
String MAVEN_REPO_PATTERN = "[organisation]/[module]/[revision]/[artifact]-[revision](-[classifier]).[ext]";
+ @Deprecated
String DEFAULT_CACHE_ARTIFACT_PATTERN
= "[organisation]/[module](/[branch])/[type]s/[artifact]-[revision](-[classifier])(.[ext])";
+ @Deprecated
String DEFAULT_CACHE_IVY_PATTERN = "[organisation]/[module](/[branch])/ivy-[revision].xml";
+ @Deprecated
String INTERNAL_REPOSITORY_NAME = "internal-repository";
+ @Deprecated
String RESOLVER_NAME = "name";
+ @Deprecated
String RESOLVER_URL = "url";
/**
@@ -87,7 +91,9 @@ public interface ArtifactRepositoryContainer extends NamedDomainObjectList<Artif
* Adds a repository to this container, at the end of the repository sequence.
*
* @param resolver The repository to add, represented as an Ivy {@link DependencyResolver}.
+ * @deprecated Use one of the repository methods on {@link org.gradle.api.artifacts.dsl.RepositoryHandler} or {@link #add(ArtifactRepository)} instead.
*/
+ @Deprecated
boolean add(DependencyResolver resolver);
/**
@@ -95,7 +101,9 @@ public interface ArtifactRepositoryContainer extends NamedDomainObjectList<Artif
*
* @param resolver The repository to add, represented as an Ivy {@link DependencyResolver}.
* @param configureClosure The closure to use to configure the repository.
+ * @deprecated Use one of the repository methods on {@link org.gradle.api.artifacts.dsl.RepositoryHandler} or {@link #add(ArtifactRepository)} instead.
*/
+ @Deprecated
boolean add(DependencyResolver resolver, Closure configureClosure);
/**
@@ -104,12 +112,12 @@ public interface ArtifactRepositoryContainer extends NamedDomainObjectList<Artif
*
* <ul>
*
- * <li>A String. This is treated as a URL, and used to create a maven repository.</li>
+ * <li>A String. This is treated as a URL, and used to create a Maven repository.</li>
*
- * <li>A map. This is used to create a maven maven repository. The map must contain an {@value #RESOLVER_NAME} entry and a
+ * <li>A map. This is used to create a Maven repository. The map must contain an {@value #RESOLVER_NAME} entry and a
* {@value #RESOLVER_URL} entry.</li>
*
- * <li>A {@link org.apache.ivy.plugins.resolver.DependencyResolver}.</li>
+ * <li>A {@link DependencyResolver}.</li>
*
* <li>A {@link ArtifactRepository}.</li>
*
@@ -144,7 +152,9 @@ public interface ArtifactRepositoryContainer extends NamedDomainObjectList<Artif
* @return The added resolver.
* @throws InvalidUserDataException when a resolver with the given name already exists in this container.
* @throws UnknownRepositoryException when the given next resolver does not exist in this container.
+ * @deprecated No replacement
*/
+ @Deprecated
DependencyResolver addBefore(Object userDescription, String nextResolver) throws InvalidUserDataException;
/**
@@ -157,7 +167,9 @@ public interface ArtifactRepositoryContainer extends NamedDomainObjectList<Artif
* @return The added resolver.
* @throws InvalidUserDataException when a resolver with the given name already exists in this container.
* @throws UnknownRepositoryException when the given next resolver does not exist in this container.
+ * @deprecated No replacement
*/
+ @Deprecated
DependencyResolver addBefore(Object userDescription, String nextResolver, Closure configureClosure)
throws InvalidUserDataException;
@@ -169,7 +181,9 @@ public interface ArtifactRepositoryContainer extends NamedDomainObjectList<Artif
* @return The added resolver.
* @throws InvalidUserDataException when a resolver with the given name already exists in this container.
* @throws UnknownRepositoryException when the given previous resolver does not exist in this container.
+ * @deprecated No replacement
*/
+ @Deprecated
DependencyResolver addAfter(Object userDescription, String previousResolver) throws InvalidUserDataException;
/**
@@ -182,7 +196,9 @@ public interface ArtifactRepositoryContainer extends NamedDomainObjectList<Artif
* @return The added resolver.
* @throws InvalidUserDataException when a resolver with the given name already exists in this container.
* @throws UnknownRepositoryException when the given previous resolver does not exist in this container.
+ * @deprecated No replacement
*/
+ @Deprecated
DependencyResolver addAfter(Object userDescription, String previousResolver, Closure configureClosure)
throws InvalidUserDataException;
@@ -192,7 +208,9 @@ public interface ArtifactRepositoryContainer extends NamedDomainObjectList<Artif
* @param userDescription The resolver definition. See {@link #addLast(Object)} for details of this parameter.
* @return The added resolver.
* @throws InvalidUserDataException when a resolver with the given name already exists in this container.
+ * @deprecated Use {@link #addFirst(ArtifactRepository)} instead.
*/
+ @Deprecated
DependencyResolver addFirst(Object userDescription) throws InvalidUserDataException;
/**
@@ -203,7 +221,9 @@ public interface ArtifactRepositoryContainer extends NamedDomainObjectList<Artif
* @param configureClosure The closure to use to configure the resolver.
* @return The added resolver.
* @throws InvalidUserDataException when a resolver with the given name already exists in this container.
+ * @deprecated Use {@link #addFirst(ArtifactRepository)} instead.
*/
+ @Deprecated
DependencyResolver addFirst(Object userDescription, Closure configureClosure) throws InvalidUserDataException;
/**
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ClientModule.java b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ClientModule.java
index e4869e6..198c13d 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ClientModule.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ClientModule.java
@@ -22,8 +22,6 @@ import java.util.Set;
* artifact or you declare a module dependency that depends on a module descriptor in a repository. With
* a client module you can declare a module dependency without the need of a module descriptor in a
* remote repository.
- *
- * @author Hans Dockter
*/
public interface ClientModule extends ExternalDependency {
/**
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ComponentMetadataDetails.java b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ComponentMetadataDetails.java
new file mode 100644
index 0000000..2dd34c3
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ComponentMetadataDetails.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.artifacts;
+
+import org.gradle.api.Incubating;
+import org.gradle.api.NonExtensible;
+
+import java.util.List;
+
+/**
+ * Describes a resolved component's metadata, which typically originates from
+ * a component descriptor (Ivy file, Maven POM). Some parts of the metadata can be changed
+ * via metadata rules (see {@link org.gradle.api.artifacts.dsl.ComponentMetadataHandler}.
+ *
+ * @since 1.8
+ */
+ at Incubating
+ at NonExtensible
+public interface ComponentMetadataDetails {
+ /**
+ * Returns the identifier of the component.
+ *
+ * @return the identifier of the component.
+ */
+ ModuleVersionIdentifier getId();
+
+ /**
+ * Tells whether the component is changing or immutable.
+ *
+ * @return whether the component is changing or immutable.
+ */
+ boolean isChanging();
+
+ /**
+ * Returns the status of the component. Must
+ * match one of the values in {@link #getStatusScheme()}.
+ *
+ * @return the status of the component
+ */
+ String getStatus();
+
+ /**
+ * Returns the status scheme of the component. Values are
+ * ordered from least to most mature status.
+ * Defaults to {@code ["integration", "milestone", "release"]}.
+ *
+ * @return the status scheme of the component
+ */
+ List<String> getStatusScheme();
+
+ /**
+ * Sets whether the component is changing or immutable.
+ *
+ * @param changing whether the component is changing or immutable
+ */
+ void setChanging(boolean changing);
+
+ /**
+ * Sets the status of the component. Must
+ * match one of the values in {@link #getStatusScheme()}.
+ *
+ * @param status the status of the component
+ */
+ void setStatus(String status);
+
+ /**
+ * Sets the status scheme of the component. Values are ordered
+ * from least to most mature status.
+ *
+ * @param statusScheme the status scheme of the component
+ */
+ void setStatusScheme(List<String> statusScheme);
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ConfigurationContainer.java b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ConfigurationContainer.java
index db1890f..8257eac 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ConfigurationContainer.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ConfigurationContainer.java
@@ -29,16 +29,16 @@ import org.gradle.api.internal.HasInternalProtocol;
* <p>The configurations in a container are accessible as read-only properties of the container, using the name of the
* configuration as the property name. For example:</p>
*
- * <pre>
- * configurations.add('myConfiguration')
+ * <pre autoTested='true'>
+ * configurations.create('myConfiguration')
* configurations.myConfiguration.transitive = false
* </pre>
*
* <p>A dynamic method is added for each configuration which takes a configuration closure. This is equivalent to
* calling {@link #getByName(String, groovy.lang.Closure)}. For example:</p>
*
- * <pre>
- * configurations.add('myConfiguration')
+ * <pre autoTested='true'>
+ * configurations.create('myConfiguration')
* configurations.myConfiguration {
* transitive = false
* }
@@ -79,8 +79,6 @@ import org.gradle.api.internal.HasInternalProtocol;
* </pre>
*
* Examples on configuring the <b>resolution strategy</b> - see docs for {@link ResolutionStrategy}
- *
- * @author Hans Dockter
*/
@HasInternalProtocol
public interface ConfigurationContainer extends NamedDomainObjectContainer<Configuration> {
@@ -105,7 +103,9 @@ public interface ConfigurationContainer extends NamedDomainObjectContainer<Confi
* @param name The name of the new configuration.
* @return The newly added configuration.
* @throws InvalidUserDataException when a configuration with the given name already exists in this container.
+ * @deprecated use {@link #create(String)} instead
*/
+ @Deprecated
Configuration add(String name) throws InvalidUserDataException;
/**
@@ -116,7 +116,9 @@ public interface ConfigurationContainer extends NamedDomainObjectContainer<Confi
* @param configureClosure The closure to use to configure the configuration.
* @return The newly added configuration.
* @throws InvalidUserDataException when a configuration with the given name already exists in this container.
+ * @deprecated use {@link #create(String, groovy.lang.Closure)} instead
*/
+ @Deprecated
Configuration add(String name, Closure configureClosure) throws InvalidUserDataException;
/**
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/Dependency.java b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/Dependency.java
index bdcf798..267a13c 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/Dependency.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/Dependency.java
@@ -17,14 +17,11 @@ package org.gradle.api.artifacts;
/**
* A {@code Dependency} represents a dependency on the artifacts from a particular source. A source can be an Ivy
- * module, a Maven pom, another Gradle project, a collection of Files, etc... A source can have zero or more artifacts.
- *
- * @author Hans Dockter
+ * module, a Maven POM, another Gradle project, a collection of Files, etc... A source can have zero or more artifacts.
*/
public interface Dependency {
String DEFAULT_CONFIGURATION = "default";
String ARCHIVES_CONFIGURATION = "archives";
- // todo Remove to ivy layer in 1.0
String CLASSIFIER = "m:classifier";
/**
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/DependencyArtifact.java b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/DependencyArtifact.java
index 9e8c9c9..4c89482 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/DependencyArtifact.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/DependencyArtifact.java
@@ -18,8 +18,6 @@ package org.gradle.api.artifacts;
/**
* <p>An {@code Artifact} represents an artifact included in a {@link org.gradle.api.artifacts.Dependency}.</p>
* An artifact is an (immutable) value object.
- *
- * @author Hans Dockter
*/
public interface DependencyArtifact {
String DEFAULT_TYPE = "jar";
@@ -31,7 +29,7 @@ public interface DependencyArtifact {
/**
* Returns the type of the dependency artifact. Often the type is the same as the extension,
- * but sometimes this is not the case. For example for an ivy xml module descriptor, the type is
+ * but sometimes this is not the case. For example for an ivy XML module descriptor, the type is
* <em>ivy</em> and the extension is <em>xml</em>.
*
* @see #getExtension()
@@ -40,7 +38,7 @@ public interface DependencyArtifact {
/**
* Returns the extension of this dependency artifact. Often the extension is the same as the type,
- * but sometimes this is not the case. For example for an ivy xml module descriptor, the type is
+ * but sometimes this is not the case. For example for an ivy XML module descriptor, the type is
* <em>ivy</em> and the extension is <em>xml</em>.
*
* @see #getType()
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ExcludeRule.java b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ExcludeRule.java
index 9262a7a..bbd4f38 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ExcludeRule.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ExcludeRule.java
@@ -20,8 +20,6 @@ import java.util.Map;
/**
* An {@code ExcludeRule} is used to describe transitive dependencies that should be excluded when resolving
* dependencies.
- *
- * @author Hans Dockter
*/
public interface ExcludeRule {
String GROUP_KEY = "group";
@@ -29,7 +27,7 @@ public interface ExcludeRule {
/**
* The exact name of the organization or group that should be excluded.
- * */
+ */
String getGroup();
/**
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ExcludeRuleContainer.java b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ExcludeRuleContainer.java
index 58e0425..aef1b20 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ExcludeRuleContainer.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ExcludeRuleContainer.java
@@ -20,8 +20,6 @@ import java.util.Set;
/**
* <p>A container for adding exclude rules for dependencies.</p>
- *
- * @author Hans Dockter
*/
public interface ExcludeRuleContainer {
/**
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ExternalDependency.java b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ExternalDependency.java
index f403492..0a68c02 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ExternalDependency.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ExternalDependency.java
@@ -17,8 +17,6 @@ package org.gradle.api.artifacts;
/**
* <p>An {@code ExternalDependency} is a {@link Dependency} on a source outside the current project hierarchy.</p>
- *
- * @author Hans Dockter
*/
public interface ExternalDependency extends ModuleDependency, ModuleVersionSelector {
/**
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ExternalModuleDependency.java b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ExternalModuleDependency.java
index 356be1c..8759431 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ExternalModuleDependency.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ExternalModuleDependency.java
@@ -17,8 +17,6 @@ package org.gradle.api.artifacts;
/**
* <p>A {@code ModuleDependency} is a {@link Dependency} on a module outside the current project hierarchy.</p>
- *
- * @author Hans Dockter
*/
public interface ExternalModuleDependency extends ExternalDependency {
/**
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/Module.java b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/Module.java
index 484ca60..9bf97ca 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/Module.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/Module.java
@@ -18,8 +18,6 @@ package org.gradle.api.artifacts;
/**
* <p>A {@code Module} represents the meta-information about a project which should be used when publishing the
* module.</p>
- *
- * @author Hans Dockter
*/
public interface Module {
public static final String DEFAULT_STATUS = "integration";
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ProjectDependency.java b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ProjectDependency.java
index 364da14..1e27198 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ProjectDependency.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ProjectDependency.java
@@ -16,12 +16,12 @@
package org.gradle.api.artifacts;
import org.gradle.api.Project;
+import org.gradle.api.internal.HasInternalProtocol;
/**
* <p>A {@code ProjectDependency} is a {@link Dependency} on another project in the current project hierarchy.</p>
- *
- * @author Hans Dockter
*/
+ at HasInternalProtocol
public interface ProjectDependency extends ModuleDependency, SelfResolvingDependency {
/**
* Returns the project associated with this project dependency.
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/PublishArtifact.java b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/PublishArtifact.java
index 0bc99d4..117285b 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/PublishArtifact.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/PublishArtifact.java
@@ -23,8 +23,6 @@ import java.util.Date;
/**
* <p>A {@code PublishArtifact} is an artifact produced by a project.</p>
- *
- * @author Hans Dockter
*/
public interface PublishArtifact extends Buildable {
/**
@@ -36,7 +34,7 @@ public interface PublishArtifact extends Buildable {
/**
* Returns the extension of this published artifact. Often the extension is the same as the type,
- * but sometimes this is not the case. For example for an ivy xml module descriptor, the type is
+ * but sometimes this is not the case. For example for an ivy XML module descriptor, the type is
* <em>ivy</em> and the extension is <em>xml</em>.
*
* @return The extension. Never null.
@@ -45,7 +43,7 @@ public interface PublishArtifact extends Buildable {
/**
* Returns the type of the published artifact. Often the type is the same as the extension,
- * but sometimes this is not the case. For example for an ivy xml module descriptor, the type is
+ * but sometimes this is not the case. For example for an ivy XML module descriptor, the type is
* <em>ivy</em> and the extension is <em>xml</em>.
*
* @return The type. Never null.
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ResolveException.java b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ResolveException.java
index 553395e..d98d975 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ResolveException.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ResolveException.java
@@ -21,8 +21,6 @@ import org.gradle.api.internal.Contextual;
/**
* <p>A <code>ResolveException</code> is thrown when a dependency configuration cannot be resolved for some reason.</p>
- *
- * @author Hans Dockter
*/
@Contextual
public class ResolveException extends AbstractMultiCauseException {
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ResolvedArtifact.java b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ResolvedArtifact.java
index 486fa6f..13d50ce 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ResolvedArtifact.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ResolvedArtifact.java
@@ -19,8 +19,6 @@ import java.io.File;
/**
* Information about a resolved artifact.
- *
- * @author Hans Dockter
*/
public interface ResolvedArtifact {
File getFile();
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ResolvedDependency.java b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ResolvedDependency.java
index 2fc35c4..22fc196 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ResolvedDependency.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/ResolvedDependency.java
@@ -19,8 +19,6 @@ import java.util.Set;
/**
* Information about a resolved dependency.
- *
- * @author Hans Dockter
*/
public interface ResolvedDependency {
/**
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/UnknownRepositoryException.java b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/UnknownRepositoryException.java
index 7908ced..120b6bc 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/UnknownRepositoryException.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/UnknownRepositoryException.java
@@ -19,8 +19,6 @@ import org.gradle.api.UnknownDomainObjectException;
/**
* An {@code UnknownRepositoryException} is thrown when a repository referenced by name cannot be found.
- *
- * @author Hans Dockter
*/
public class UnknownRepositoryException extends UnknownDomainObjectException {
public UnknownRepositoryException(String message) {
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/dsl/ArtifactHandler.java b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/dsl/ArtifactHandler.java
index 376cb32..ed74047 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/dsl/ArtifactHandler.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/dsl/ArtifactHandler.java
@@ -67,8 +67,6 @@ import org.gradle.api.artifacts.PublishArtifact;
* schema schemaJar
* }
* </pre>
- *
- * @author Hans Dockter
*/
public interface ArtifactHandler {
/**
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/dsl/ComponentMetadataHandler.java b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/dsl/ComponentMetadataHandler.java
new file mode 100644
index 0000000..39f21af
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/dsl/ComponentMetadataHandler.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.artifacts.dsl;
+
+import org.gradle.api.Action;
+import org.gradle.api.Incubating;
+import org.gradle.api.artifacts.ComponentMetadataDetails;
+
+/**
+ * Allows to modify the metadata of depended-on software components.
+ *
+ * <p> Example:
+ * <pre autoTested=''>
+ * dependencies {
+ * components {
+ * eachComponent { ComponentMetadataDetails details ->
+ * if (details.id.group == "org.foo") {
+ * def version = details.id.version
+ * // assuming status is last part of version string
+ * details.status = version.substring(version.lastIndexOf("-") + 1)
+ * details.statusScheme = ["bronze", "silver", "gold", "platinum"]
+ * }
+ * }
+ * }
+ * }
+ * </pre>
+ *
+ * @since 1.8
+ */
+ at Incubating
+public interface ComponentMetadataHandler {
+ /**
+ * Adds a rule to modify the metadata of depended-on software components.
+ * For example, this allows to set a component's status and status scheme
+ * from within the build script, overriding any value specified in the
+ * component descriptor.
+ *
+ * @param rule the rule to be added
+ */
+ void eachComponent(Action<? super ComponentMetadataDetails> rule);
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/dsl/DependencyHandler.java b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/dsl/DependencyHandler.java
index 1cef039..b25b3f1 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/dsl/DependencyHandler.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/dsl/DependencyHandler.java
@@ -16,6 +16,7 @@
package org.gradle.api.artifacts.dsl;
import groovy.lang.Closure;
+import org.gradle.api.Incubating;
import org.gradle.api.artifacts.Dependency;
import java.util.Map;
@@ -111,8 +112,10 @@ import java.util.Map;
* compile(group: 'org.myorg', name: 'someLib', version:'1.0') {
* //explicitly adding the dependency artifact:
* artifact {
+ * //useful when some artifact properties unconventional
* name = 'someArtifact' //artifact name different than module name
- * type = 'jar'
+ * extension = 'someExt'
+ * type = 'someType'
* classifier = 'someClassifier'
* }
* }
@@ -213,11 +216,11 @@ import java.util.Map;
* <pre autoTested=''>
* //Our Gradle plugin is written in groovy
* apply plugin: 'groovy'
- * //now we can use 'groovy' and 'compile' configuration for declaring dependencies
+ * //now we can use the 'compile' configuration for declaring dependencies
*
* dependencies {
- * //we will use groovy that ships with Gradle:
- * groovy localGroovy()
+ * //we will use the Groovy version that ships with Gradle:
+ * compile localGroovy()
*
* //our plugin requires Gradle API interfaces and classes to compile:
* compile gradleApi()
@@ -236,8 +239,6 @@ import java.util.Map;
*
* The module notation is the same as the dependency notations described above, except that the classifier property is
* not available. Client modules are represented using a {@link org.gradle.api.artifacts.ClientModule}.
- *
- * @author Hans Dockter
*/
public interface DependencyHandler {
/**
@@ -318,4 +319,26 @@ public interface DependencyHandler {
* @return The dependency.
*/
Dependency localGroovy();
+
+ /**
+ * Returns the component metadata handler for this project. The returned handler can be used for adding rules
+ * that modify the metadata of depended-on software components.
+ *
+ * @return the component metadata handler for this project
+ * @since 1.8
+ */
+ @Incubating
+ ComponentMetadataHandler getComponents();
+
+ /**
+ * Configures module metadata for this project.
+ *
+ * <p>This method executes the given closure against the {@link org.gradle.api.artifacts.dsl.ComponentMetadataHandler} for this project. The {@link
+ * org.gradle.api.artifacts.dsl.ComponentMetadataHandler} is passed to the closure as the closure's delegate.
+ *
+ * @param configureClosure the closure to use to configure module metadata
+ * @since 1.8
+ */
+ @Incubating
+ void components(Closure configureClosure);
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/dsl/RepositoryHandler.java b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/dsl/RepositoryHandler.java
index 1c0c851..1e777ea 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/dsl/RepositoryHandler.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/dsl/RepositoryHandler.java
@@ -18,6 +18,7 @@ package org.gradle.api.artifacts.dsl;
import groovy.lang.Closure;
import org.apache.ivy.plugins.resolver.DependencyResolver;
import org.gradle.api.Action;
+import org.gradle.api.Incubating;
import org.gradle.api.artifacts.ArtifactRepositoryContainer;
import org.gradle.api.artifacts.repositories.FlatDirectoryArtifactRepository;
import org.gradle.api.artifacts.repositories.IvyArtifactRepository;
@@ -27,8 +28,6 @@ import java.util.Map;
/**
* A {@code RepositoryHandler} manages a set of repositories, allowing repositories to be defined and queried.
- *
- * @author Hans Dockter
*/
public interface RepositoryHandler extends ArtifactRepositoryContainer {
@@ -52,7 +51,7 @@ public interface RepositoryHandler extends ArtifactRepositoryContainer {
* </table>
*
* <p>Examples:
- * <pre>
+ * <pre autoTested=''>
* repositories {
* flatDir name: 'libs', dirs: "$projectDir/libs"
* flatDir dirs: ["$projectDir/libs1", "$projectDir/libs2"]
@@ -84,6 +83,50 @@ public interface RepositoryHandler extends ArtifactRepositoryContainer {
FlatDirectoryArtifactRepository flatDir(Action<? super FlatDirectoryArtifactRepository> action);
/**
+ * Adds a repository which looks in Bintray's JCenter repository for dependencies.
+ * <p>
+ * The URL used to access this repository is {@literal "http://jcenter.bintray.com/"}.
+ * The behavior of this resolver is otherwise the same as the ones added by {@link #maven(org.gradle.api.Action)}.
+ * <p>
+ * Examples:
+ * <pre autoTested="">
+ * repositories {
+ * jcenter {
+ * artifactUrls = ["http://www.mycompany.com/artifacts1", "http://www.mycompany.com/artifacts2"]
+ * }
+ * jcenter {
+ * name = "nonDefaultName"
+ * artifactUrls = ["http://www.mycompany.com/artifacts1"]
+ * }
+ * }
+ * </pre>
+ *
+ * @param action a configuration action
+ * @return the added repository
+ */
+ @Incubating
+ MavenArtifactRepository jcenter(Action<? super MavenArtifactRepository> action);
+
+ /**
+ * Adds a repository which looks in Bintray's JCenter repository for dependencies.
+ * <p>
+ * The URL used to access this repository is {@literal "http://jcenter.bintray.com/"}.
+ * The behavior of this resolver is otherwise the same as the ones added by {@link #mavenCentral()}.
+ * <p>
+ * Examples:
+ * <pre autoTested="">
+ * repositories {
+ * jcenter()
+ * }
+ * </pre>
+ *
+ * @return the added resolver
+ * @see #jcenter(Action)
+ */
+ @Incubating
+ MavenArtifactRepository jcenter();
+
+ /**
* Adds a repository which looks in the Maven central repository for dependencies. The URL used to access this repository is
* {@value org.gradle.api.artifacts.ArtifactRepositoryContainer#MAVEN_CENTRAL_URL}. The behavior of this resolver
* is otherwise the same as the ones added by {@link #mavenRepo(java.util.Map)}.
@@ -99,13 +142,13 @@ public interface RepositoryHandler extends ArtifactRepositoryContainer {
* must be unique amongst a repository group.
* </td></tr>
* <tr><td><code>artifactUrls</code></td>
- * <td>A single jar repository or a collection of jar repositories containing additional artifacts not found in the maven central repository.
- * But be aware that the POM must exist in maven central.
+ * <td>A single jar repository or a collection of jar repositories containing additional artifacts not found in the Maven central repository.
+ * But be aware that the POM must exist in Maven central.
* The provided values are evaluated as per {@link org.gradle.api.Project#uri(Object)}.</td></tr>
* </table>
*
* <p>Examples:
- * <pre>
+ * <pre autoTested="">
* repositories {
* mavenCentral artifactUrls: ["http://www.mycompany.com/artifacts1", "http://www.mycompany.com/artifacts2"]
* mavenCentral name: "nonDefaultName", artifactUrls: ["http://www.mycompany.com/artifacts1"]
@@ -124,7 +167,7 @@ public interface RepositoryHandler extends ArtifactRepositoryContainer {
* {@value org.gradle.api.artifacts.ArtifactRepositoryContainer#DEFAULT_MAVEN_CENTRAL_REPO_NAME}.
*
* <p>Examples:
- * <pre>
+ * <pre autoTested="">
* repositories {
* mavenCentral()
* }
@@ -141,7 +184,7 @@ public interface RepositoryHandler extends ArtifactRepositoryContainer {
* {@value org.gradle.api.artifacts.ArtifactRepositoryContainer#DEFAULT_MAVEN_LOCAL_REPO_NAME}.
*
* <p>Examples:
- * <pre>
+ * <pre autoTested="">
* repositories {
* mavenLocal()
* }
@@ -158,10 +201,10 @@ public interface RepositoryHandler extends ArtifactRepositoryContainer {
* to a Maven repository, have a look at {@link org.gradle.api.plugins.MavenRepositoryHandlerConvention#mavenDeployer(java.util.Map)} or
* {@link org.gradle.api.plugins.MavenRepositoryHandlerConvention#mavenInstaller(java.util.Map)}.
*
- * By default the repository accepts to resolve artifacts without a pom. The repository always looks first for the pom
+ * By default the repository accepts to resolve artifacts without a POM. The repository always looks first for the POM
* in the root repository. It then looks for the artifact in the root repository. Sometimes the artifact
- * lives in a different repository than the pom. In such a case you can specify further locations to look for an artifact.
- * But be aware that the pom is only looked up in the root repository.
+ * lives in a different repository than the POM. In such a case you can specify further locations to look for an artifact.
+ * But be aware that the POM is only looked up in the root repository.
*
* The following parameter are accepted as keys for the map:
*
@@ -197,18 +240,22 @@ public interface RepositoryHandler extends ArtifactRepositoryContainer {
*
* @param args The argument to create the repository
* @return the added repository
+ * @deprecated Use {@link #maven(groovy.lang.Closure)} instead.
*/
@SuppressWarnings("JavadocReference")
+ @Deprecated
DependencyResolver mavenRepo(Map<String, ?> args);
/**
* Adds a repository which is Maven compatible.
- *
+ *
* @param args The argument to create the repository
* @param configClosure Further configuration of the dependency resolver
* @return The created dependency resolver
* @see #mavenRepo(java.util.Map)
+ * @deprecated Use {@link #maven(groovy.lang.Closure)} instead.
*/
+ @Deprecated
DependencyResolver mavenRepo(Map<String, ?> args, Closure configClosure);
/**
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/repositories/IvyArtifactRepository.java b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/repositories/IvyArtifactRepository.java
index 9eb30de..bf92523 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/artifacts/repositories/IvyArtifactRepository.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/artifacts/repositories/IvyArtifactRepository.java
@@ -106,7 +106,7 @@ public interface IvyArtifactRepository extends ArtifactRepository, Authenticatio
* <li>Artifacts: <code>$baseUri/{@value #MAVEN_ARTIFACT_PATTERN}</code></li>
* <li>Ivy: <code>$baseUri/{@value #MAVEN_IVY_PATTERN}</code></li>
* </ul>
- * Following the maven convention, the 'organisation' value is further processed by replacing '.' with '/'.
+ * Following the Maven convention, the 'organisation' value is further processed by replacing '.' with '/'.
*
* <h4>'pattern'</h4>
* A repository layout that allows custom patterns to be defined. eg:
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/component/SoftwareComponent.java b/subprojects/core/src/main/groovy/org/gradle/api/component/SoftwareComponent.java
index a83c2d2..8bac404 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/component/SoftwareComponent.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/component/SoftwareComponent.java
@@ -18,10 +18,11 @@ package org.gradle.api.component;
import org.gradle.api.Incubating;
import org.gradle.api.Named;
+import org.gradle.api.internal.HasInternalProtocol;
/**
* A software component produced by a Gradle software project.
*/
- at Incubating
+ at Incubating @HasInternalProtocol
public interface SoftwareComponent extends Named {
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/dsl/ConventionProperty.java b/subprojects/core/src/main/groovy/org/gradle/api/dsl/ConventionProperty.java
index 12c0569..c33a103 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/dsl/ConventionProperty.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/dsl/ConventionProperty.java
@@ -70,7 +70,5 @@ package org.gradle.api.dsl;
* Thanks to the 'lazy' evaluation of the convention properties
* the user can reconfigure the sourceSets anywhere in the gradle script -
* and still the test.testClassesDir will point to the right folder.
- *
- * @author Szczepan Faber, created at: 4/19/11
*/
public class ConventionProperty {}
\ No newline at end of file
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/execution/TaskExecutionAdapter.java b/subprojects/core/src/main/groovy/org/gradle/api/execution/TaskExecutionAdapter.java
index c4091c1..3f4ecce 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/execution/TaskExecutionAdapter.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/execution/TaskExecutionAdapter.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2009 the original author or authors.
+ * Copyright 2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/file/CopySourceSpec.java b/subprojects/core/src/main/groovy/org/gradle/api/file/CopySourceSpec.java
index 2ef2794..4ca0cca 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/file/CopySourceSpec.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/file/CopySourceSpec.java
@@ -19,8 +19,6 @@ import groovy.lang.Closure;
/**
* Specifies sources for a file copy.
- *
- * @author Steve Appling
*/
public interface CopySourceSpec {
/**
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/file/CopySpec.java b/subprojects/core/src/main/groovy/org/gradle/api/file/CopySpec.java
index 256a4a0..03f5891 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/file/CopySpec.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/file/CopySpec.java
@@ -17,11 +17,14 @@ package org.gradle.api.file;
import groovy.lang.Closure;
import org.gradle.api.Action;
-import org.gradle.api.tasks.util.PatternFilterable;
+import org.gradle.api.Incubating;
+import org.gradle.api.Nullable;
+import org.gradle.api.internal.HasInternalProtocol;
import org.gradle.api.specs.Spec;
+import org.gradle.api.tasks.util.PatternFilterable;
-import java.util.Map;
import java.io.FilterReader;
+import java.util.Map;
import java.util.regex.Pattern;
/**
@@ -62,10 +65,10 @@ import java.util.regex.Pattern;
* In this example, the <code>into</code> and <code>exclude</code> specifications at the root level are inherited by the
* two child CopySpecs.
*
- * @author Steve Appling
* @see org.gradle.api.tasks.Copy Copy Task
* @see org.gradle.api.Project#copy(groovy.lang.Closure) Project.copy()
*/
+ at HasInternalProtocol
public interface CopySpec extends CopySourceSpec, CopyProcessingSpec, PatternFilterable {
/**
* Specifies whether case-sensitive pattern matching should be used.
@@ -96,7 +99,51 @@ public interface CopySpec extends CopySourceSpec, CopyProcessingSpec, PatternFil
void setIncludeEmptyDirs(boolean includeEmptyDirs);
/**
+ * Returns the strategy to use when trying to copy more than one file to the same destination.
+ * <p>
+ * The value can be set with a case insensitive string of the enum value (e.g. {@code 'exclude'} for {@link DuplicatesStrategy#EXCLUDE}).
+ * <p>
+ * This strategy can be overridden for individual files by using {@link #eachFile(org.gradle.api.Action)} or {@link #filesMatching(String, org.gradle.api.Action)}.
+ *
+ * @return the strategy to use for files included by this copy spec.
+ * @see DuplicatesStrategy
+ */
+ @Incubating
+ DuplicatesStrategy getDuplicatesStrategy();
+
+ /**
+ * The strategy to use when trying to copy more than one file to the same destination. Set to {@code null} to use the default strategy, which is inherited
+ * from the parent copy spec, if any, or {@link DuplicatesStrategy#INCLUDE} if this copy spec has no parent.
+ */
+ @Incubating
+ void setDuplicatesStrategy(@Nullable DuplicatesStrategy strategy);
+
+ /**
+ * Configure the {@link org.gradle.api.file.FileCopyDetails} for each file whose path matches the specified Ant-style pattern.
+ * This is equivalent to using eachFile() and selectively applying a configuration based on the file's path.
+ *
+ * @param pattern Ant-style pattern used to match against files' relative paths
+ * @param action action called for the FileCopyDetails of each file matching pattern
+ * @return this
+ */
+ @Incubating
+ CopySpec filesMatching(String pattern, Action<? super FileCopyDetails> action);
+
+ /**
+ * Configure the {@link org.gradle.api.file.FileCopyDetails} for each file whose path does not match the specified
+ * Ant-style pattern. This is equivalent to using eachFile() and selectively applying a configuration based on the
+ * file's path.
+ *
+ * @param pattern Ant-style pattern used to match against files' relative paths
+ * @param action action called for the FileCopyDetails of each file that does not match pattern
+ * @return this
+ */
+ @Incubating
+ CopySpec filesNotMatching(String pattern, Action<? super FileCopyDetails> action);
+
+ /**
* Adds the given specs as a child of this spec.
+ *
* @param sourceSpecs The specs to add
* @return this
*/
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/file/DeleteAction.java b/subprojects/core/src/main/groovy/org/gradle/api/file/DeleteAction.java
index 4be5015..0a70840 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/file/DeleteAction.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/file/DeleteAction.java
@@ -17,8 +17,6 @@ package org.gradle.api.file;
/**
* Deletes files and directories.
- *
- * @author Hans Dockter
*/
public interface DeleteAction {
/**
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/file/DuplicateFileCopyingException.java b/subprojects/core/src/main/groovy/org/gradle/api/file/DuplicateFileCopyingException.java
new file mode 100644
index 0000000..9aa08d3
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/file/DuplicateFileCopyingException.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.file;
+
+import org.gradle.api.GradleException;
+
+/**
+ * Thrown when more than one file with the same relative path name is to be copied
+ * and the {@link DuplicatesStrategy} is set to DuplicatesStrategy.FAIL
+ */
+public class DuplicateFileCopyingException extends GradleException {
+
+ public DuplicateFileCopyingException() {
+
+ }
+
+ public DuplicateFileCopyingException(String desc) {
+ super(desc);
+ }
+
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/file/DuplicatesStrategy.java b/subprojects/core/src/main/groovy/org/gradle/api/file/DuplicatesStrategy.java
new file mode 100644
index 0000000..c36600c
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/file/DuplicatesStrategy.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.file;
+
+import org.gradle.api.Incubating;
+
+/**
+ * Strategies for dealing with the potential creation of duplicate files for or archive entries.
+ */
+ at Incubating
+public enum DuplicatesStrategy {
+
+ /**
+ * Do not attempt to prevent duplicates.
+ * <p>
+ * If the destination of the operation supports duplicates (e.g. zip files) then a duplicate entry will be created.
+ * If the destination does not support duplicates, the existing destination entry will be overridden with the duplicate.
+ */
+ INCLUDE,
+
+ /**
+ * Do not allow duplicates by ignoring subsequent items to be created at the same path.
+ * <p>
+ * If an attempt is made to create a duplicate file/entry during an operation, ignore the item.
+ * This will leave the file/entry that was first copied/created in place.
+ */
+ EXCLUDE,
+
+ /**
+ * Do not attempt to prevent duplicates, but log a warning message when multiple items
+ * are to be created at the same path.
+ * <p>
+ * This behaves exactly as INCLUDE otherwise.
+ */
+ WARN,
+
+ /**
+ * Throw a {@link DuplicateFileCopyingException} when subsequent items are to be created at the same path.
+ * <p>
+ * Use this strategy when duplicates are an error condition that should cause the build to fail.
+ */
+ FAIL
+
+
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/file/EmptyFileVisitor.java b/subprojects/core/src/main/groovy/org/gradle/api/file/EmptyFileVisitor.java
index 4c386df..1dd32e9 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/file/EmptyFileVisitor.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/file/EmptyFileVisitor.java
@@ -18,8 +18,6 @@ package org.gradle.api.file;
/**
* The EmptyFileVisitor can be extends by implementations that only require to implement one of the 2 visit methods
* (dir or file). This is just to limit the amount of code clutter when not both visit methods need to be implemented.
- *
- * @author Tom Eyckmans
*/
public class EmptyFileVisitor implements FileVisitor {
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/file/FileCopyDetails.java b/subprojects/core/src/main/groovy/org/gradle/api/file/FileCopyDetails.java
index 59a2ab9..a458328 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/file/FileCopyDetails.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/file/FileCopyDetails.java
@@ -15,6 +15,10 @@
*/
package org.gradle.api.file;
+import org.gradle.api.Incubating;
+import org.gradle.api.internal.HasInternalProtocol;
+import org.gradle.api.NonExtensible;
+
/**
* <p>Provides details about a file or directory about to be copied, and allows some aspects of the destination file to
* be modified.</p>
@@ -22,6 +26,8 @@ package org.gradle.api.file;
* <p>Using this interface, you can change the destination path of the file, filter the content of the file, or exclude
* the file from the result entirely.</p>
*/
+ at HasInternalProtocol
+ at NonExtensible
public interface FileCopyDetails extends FileTreeElement, ContentFilterable {
/**
* Excludes this file from the copy.
@@ -55,4 +61,22 @@ public interface FileCopyDetails extends FileTreeElement, ContentFilterable {
* @param mode the Unix permissions, e.g. {@code 0644}.
*/
void setMode(int mode);
+
+ /**
+ * The strategy to use if there is already a file at this file's destination.
+ */
+ @Incubating
+ void setDuplicatesStrategy(DuplicatesStrategy strategy);
+
+ /**
+ * The strategy to use if there is already a file at this file's destination.
+ * <p>
+ * The value can be set with a case insensitive string of the enum value (e.g. {@code 'exclude'} for {@link DuplicatesStrategy#EXCLUDE}).
+ *
+ * @see DuplicatesStrategy
+ * @return the strategy to use for this file.
+ */
+ @Incubating
+ DuplicatesStrategy getDuplicatesStrategy();
+
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/file/FileTree.java b/subprojects/core/src/main/groovy/org/gradle/api/file/FileTree.java
index 92ba383..b9b1764 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/file/FileTree.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/file/FileTree.java
@@ -33,7 +33,7 @@ public interface FileTree extends FileCollection {
* that any changes to this tree are reflected in the filtered tree.</p>
*
* <p>The given closure is used to configure the filter. A {@link org.gradle.api.tasks.util.PatternFilterable} is
- * passed to the closure as it's delegate. Only files which match the specified include patterns will be included in
+ * passed to the closure as its delegate. Only files which match the specified include patterns will be included in
* the filtered tree. Any files which match the specified exclude patterns will be excluded from the filtered
* tree.</p>
*
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/file/FileVisitor.java b/subprojects/core/src/main/groovy/org/gradle/api/file/FileVisitor.java
index 0972d74..e789709 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/file/FileVisitor.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/file/FileVisitor.java
@@ -17,8 +17,6 @@ package org.gradle.api.file;
/**
* <p>A {@code FileVisitor} is used to visit each of the files in a {@link FileTree}.</p>
- *
- * @author Steve Appling
*/
public interface FileVisitor {
/**
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/file/RelativePath.java b/subprojects/core/src/main/groovy/org/gradle/api/file/RelativePath.java
index 7fa733f..f91e4fb 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/file/RelativePath.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/file/RelativePath.java
@@ -29,8 +29,6 @@ import java.util.ListIterator;
* and target file path when copying files.</p>
*
* <p>{@code RelativePath} instances are immutable.</p>
- *
- * @author Steve Appling
*/
public class RelativePath implements Serializable {
private final boolean endsWithFile;
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/initialization/ProjectDescriptor.java b/subprojects/core/src/main/groovy/org/gradle/api/initialization/ProjectDescriptor.java
index cffbe5e..7e763bd 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/initialization/ProjectDescriptor.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/initialization/ProjectDescriptor.java
@@ -25,8 +25,6 @@ import java.util.Set;
* <p> A {@code ProjectDescriptor} is created when you add a project to the build from the settings script, using {@link
* Settings#include(String[])} or {@link Settings#includeFlat(String[])}. You can access the descriptors using one of
* the lookup methods on the {@link Settings} object.</p>
- *
- * @author Hans Dockter
*/
public interface ProjectDescriptor {
/**
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/initialization/Settings.java b/subprojects/core/src/main/groovy/org/gradle/api/initialization/Settings.java
index ad79d28..97ffeb2 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/initialization/Settings.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/initialization/Settings.java
@@ -19,6 +19,7 @@ package org.gradle.api.initialization;
import org.gradle.StartParameter;
import org.gradle.api.UnknownProjectException;
import org.gradle.api.invocation.Gradle;
+import org.gradle.api.plugins.PluginAware;
import java.io.File;
@@ -59,10 +60,8 @@ import java.io.File;
* <li>Provided on the command-line using the -P option.</li>
*
* </ul>
- *
- * @author Hans Dockter
*/
-public interface Settings {
+public interface Settings extends PluginAware {
/**
* <p>The default name for the settings file.</p>
*/
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/AbstractClassGenerator.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/AbstractClassGenerator.java
index 897c0a7..ad488f7 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/AbstractClassGenerator.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/AbstractClassGenerator.java
@@ -31,9 +31,12 @@ import org.gradle.internal.reflect.Instantiator;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.util.*;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
public abstract class AbstractClassGenerator implements ClassGenerator {
private static final Map<Class<?>, Map<Class<?>, Class<?>>> GENERATED_CLASSES = new HashMap<Class<?>, Map<Class<?>, Class<?>>>();
+ private static final Lock CACHE_LOCK = new ReentrantLock();
public <T> T newInstance(Class<T> type, Object... parameters) {
Instantiator instantiator = new DirectInstantiator();
@@ -41,6 +44,15 @@ public abstract class AbstractClassGenerator implements ClassGenerator {
}
public <T> Class<? extends T> generate(Class<T> type) {
+ try {
+ CACHE_LOCK.lock();
+ return generateUnderLock(type);
+ } finally {
+ CACHE_LOCK.unlock();
+ }
+ }
+
+ private <T> Class<? extends T> generateUnderLock(Class<T> type) {
Map<Class<?>, Class<?>> cache = GENERATED_CLASSES.get(getClass());
if (cache == null) {
// WeakHashMap won't work here. It keeps a strong reference to the mapping value, which is the generated class in this case
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/AbstractNamedDomainObjectContainer.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/AbstractNamedDomainObjectContainer.java
index 2d64cb1..87e0717 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/AbstractNamedDomainObjectContainer.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/AbstractNamedDomainObjectContainer.java
@@ -16,9 +16,7 @@
package org.gradle.api.internal;
import groovy.lang.Closure;
-import org.gradle.api.Named;
-import org.gradle.api.NamedDomainObjectContainer;
-import org.gradle.api.Namer;
+import org.gradle.api.*;
import org.gradle.internal.reflect.Instantiator;
import org.gradle.util.ConfigureUtil;
@@ -38,7 +36,7 @@ public abstract class AbstractNamedDomainObjectContainer<T> extends DefaultNamed
protected abstract T doCreate(String name);
public T create(String name) {
- return create(name, null);
+ return create(name, Actions.doNothing());
}
public T maybeCreate(String name) {
@@ -50,10 +48,14 @@ public abstract class AbstractNamedDomainObjectContainer<T> extends DefaultNamed
}
public T create(String name, Closure configureClosure) {
+ return create(name, new ClosureBackedAction<T>(configureClosure));
+ }
+
+ public T create(String name, Action<? super T> configureAction) throws InvalidUserDataException {
assertCanAdd(name);
T object = doCreate(name);
add(object);
- ConfigureUtil.configure(configureClosure, object);
+ configureAction.execute(object);
return object;
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/AbstractPolymorphicDomainObjectContainer.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/AbstractPolymorphicDomainObjectContainer.java
index 1f5046e..b964534 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/AbstractPolymorphicDomainObjectContainer.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/AbstractPolymorphicDomainObjectContainer.java
@@ -123,7 +123,12 @@ public abstract class AbstractPolymorphicDomainObjectContainer<T>
@Override
public Object invokeMethod(String name, Object... arguments) throws groovy.lang.MissingMethodException {
if (isConfigureMethod(name, arguments)) {
- return ConfigureUtil.configure((Closure) arguments[arguments.length - 1], getByName(name));
+ T element = getByName(name);
+ Object lastArgument = arguments[arguments.length - 1];
+ if (lastArgument instanceof Closure) {
+ ConfigureUtil.configure((Closure) lastArgument, element);
+ }
+ return element;
} else {
return super.invokeMethod(name, arguments);
}
@@ -131,6 +136,7 @@ public abstract class AbstractPolymorphicDomainObjectContainer<T>
private boolean isConfigureMethod(String name, Object... arguments) {
return (arguments.length == 1 && arguments[0] instanceof Closure
+ || arguments.length == 1 && arguments[0] instanceof Class
|| arguments.length == 2 && arguments[0] instanceof Class && arguments[1] instanceof Closure)
&& hasProperty(name);
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/AbstractTask.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/AbstractTask.java
index 368316c..de0cd73 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/AbstractTask.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/AbstractTask.java
@@ -24,6 +24,7 @@ import org.gradle.api.*;
import org.gradle.api.internal.file.TemporaryFileProvider;
import org.gradle.api.internal.project.ProjectInternal;
import org.gradle.api.internal.tasks.*;
+import org.gradle.api.internal.tasks.execution.DefaultTaskExecutionContext;
import org.gradle.api.internal.tasks.execution.TaskValidator;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
@@ -52,9 +53,6 @@ import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
-/**
- * @author Hans Dockter
- */
public abstract class AbstractTask implements TaskInternal, DynamicObjectAware {
private static Logger buildLogger = Logging.getLogger(Task.class);
private static ThreadLocal<TaskInfo> nextInstance = new ThreadLocal<TaskInfo>();
@@ -62,7 +60,7 @@ public abstract class AbstractTask implements TaskInternal, DynamicObjectAware {
private String name;
- private List<Action<? super Task>> actions = new ArrayList<Action<? super Task>>();
+ private List<ContextAwareTaskAction> actions = new ArrayList<ContextAwareTaskAction>();
private String path;
@@ -70,6 +68,10 @@ public abstract class AbstractTask implements TaskInternal, DynamicObjectAware {
private DefaultTaskDependency dependencies;
+ private DefaultTaskDependency mustRunAfter;
+
+ private DefaultTaskDependency finalizedBy;
+
private ExtensibleDynamicObject extensibleDynamicObject;
private String description;
@@ -115,6 +117,8 @@ public abstract class AbstractTask implements TaskInternal, DynamicObjectAware {
path = project.absoluteProjectPath(name);
state = new TaskStateInternal(toString());
dependencies = new DefaultTaskDependency(project.getTasks());
+ mustRunAfter = new DefaultTaskDependency(project.getTasks());
+ finalizedBy = new DefaultTaskDependency(project.getTasks());
services = project.getServices().createFor(this);
extensibleDynamicObject = new ExtensibleDynamicObject(this, getServices().get(Instantiator.class));
taskStatusNagger = services.get(TaskStatusNagger.class);
@@ -178,6 +182,10 @@ public abstract class AbstractTask implements TaskInternal, DynamicObjectAware {
return observableActionList;
}
+ public List<ContextAwareTaskAction> getTaskActions() {
+ return observableActionList;
+ }
+
public void setActions(final List<Action<? super Task>> actions) {
taskStatusNagger.nagIfTaskNotInConfigurableState("Task.setActions(Actions<Task>)");
taskStatusNagger.whileDisabled(new Runnable() {
@@ -272,7 +280,7 @@ public abstract class AbstractTask implements TaskInternal, DynamicObjectAware {
}
public void executeWithoutThrowingTaskFailure() {
- executer.execute(this, state);
+ executer.execute(this, state, new DefaultTaskExecutionContext());
}
public TaskExecuter getExecuter() {
@@ -448,11 +456,11 @@ public abstract class AbstractTask implements TaskInternal, DynamicObjectAware {
return validators;
}
- private Action<Task> convertClosureToAction(Closure actionClosure) {
+ private ContextAwareTaskAction convertClosureToAction(Closure actionClosure) {
return new ClosureTaskAction(actionClosure);
}
- private Action<Task> wrap(final Action<? super Task> action) {
+ private ContextAwareTaskAction wrap(final Action<? super Task> action) {
return new TaskActionWrapper(action);
}
@@ -466,13 +474,16 @@ public abstract class AbstractTask implements TaskInternal, DynamicObjectAware {
}
}
- private static class ClosureTaskAction implements Action<Task> {
+ private static class ClosureTaskAction implements ContextAwareTaskAction {
private final Closure closure;
private ClosureTaskAction(Closure closure) {
this.closure = closure;
}
+ public void contextualise(TaskExecutionContext context) {
+ }
+
public void execute(Task task) {
closure.setDelegate(task);
closure.setResolveStrategy(Closure.DELEGATE_FIRST);
@@ -496,13 +507,19 @@ public abstract class AbstractTask implements TaskInternal, DynamicObjectAware {
}
}
- private static class TaskActionWrapper implements Action<Task> {
+ private static class TaskActionWrapper implements ContextAwareTaskAction {
private final Action<? super Task> action;
public TaskActionWrapper(Action<? super Task> action) {
this.action = action;
}
+ public void contextualise(TaskExecutionContext context) {
+ if (action instanceof ContextAwareTaskAction) {
+ ((ContextAwareTaskAction) action).contextualise(context);
+ }
+ }
+
public void execute(Task task) {
ClassLoader original = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(action.getClass().getClassLoader());
@@ -513,4 +530,34 @@ public abstract class AbstractTask implements TaskInternal, DynamicObjectAware {
}
}
}
+
+ public void setMustRunAfter(Iterable<?> mustRunAfterTasks) {
+ taskStatusNagger.nagIfTaskNotInConfigurableState("Task.setMustRunAfter(Iterable)");
+ mustRunAfter.setValues(mustRunAfterTasks);
+ }
+
+ public Task mustRunAfter(Object... paths) {
+ taskStatusNagger.nagIfTaskNotInConfigurableState("Task.mustRunAfter(Object...)");
+ mustRunAfter.add(paths);
+ return this;
+ }
+
+ public TaskDependency getMustRunAfter() {
+ return mustRunAfter;
+ }
+
+ public void setFinalizedBy(Iterable<?> finalizedByTasks) {
+ taskStatusNagger.nagIfTaskNotInConfigurableState("Task.setFinalizedBy(Iterable)");
+ finalizedBy.setValues(finalizedByTasks);
+ }
+
+ public Task finalizedBy(Object... paths) {
+ taskStatusNagger.nagIfTaskNotInConfigurableState("Task.finalizedBy(Object...)");
+ finalizedBy.add(paths);
+ return this;
+ }
+
+ public TaskDependency getFinalizedBy() {
+ return finalizedBy;
+ }
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/AsmBackedClassGenerator.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/AsmBackedClassGenerator.java
index 0dcb801..9976032 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/AsmBackedClassGenerator.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/AsmBackedClassGenerator.java
@@ -16,6 +16,7 @@
package org.gradle.api.internal;
import groovy.lang.*;
+import org.gradle.api.NonExtensible;
import org.gradle.api.Transformer;
import org.gradle.api.plugins.Convention;
import org.gradle.api.plugins.ExtensionAware;
@@ -34,7 +35,7 @@ import java.util.ArrayList;
import java.util.List;
public class AsmBackedClassGenerator extends AbstractClassGenerator {
- private static final JavaMethod<ClassLoader, Class> DEFINE_CLASS_METHOD = JavaMethod.create(ClassLoader.class, Class.class, "defineClass", String.class, byte[].class, Integer.TYPE, Integer.TYPE);
+ private static final JavaMethod<ClassLoader, Class> DEFINE_CLASS_METHOD = JavaReflectionUtil.method(ClassLoader.class, Class.class, "defineClass", String.class, byte[].class, Integer.TYPE, Integer.TYPE);
@Override
protected <T> ClassBuilder<T> start(Class<T> type) {
@@ -58,6 +59,10 @@ public class AsmBackedClassGenerator extends AbstractClassGenerator {
private final Type conventionMappingType = Type.getType(ConventionMapping.class);
private final Type groovyObjectType = Type.getType(GroovyObject.class);
private final Type conventionType = Type.getType(Convention.class);
+ private final Type extensibleDynamicObjectHelperType = Type.getType(MixInExtensibleDynamicObject.class);
+ private final Type nonExtensibleDynamicObjectHelperType = Type.getType(BeanDynamicObject.class);
+
+ private final boolean extensible;
private ClassBuilderImpl(Class<T> type) {
this.type = type;
@@ -66,16 +71,22 @@ public class AsmBackedClassGenerator extends AbstractClassGenerator {
typeName = type.getName() + "_Decorated";
generatedType = Type.getType("L" + typeName.replaceAll("\\.", "/") + ";");
superclassType = Type.getType(type);
+
+ extensible = JavaReflectionUtil.getAnnotation(type, NonExtensible.class) == null;
}
public void startClass(boolean isConventionAware) {
List<String> interfaceTypes = new ArrayList<String>();
- if (isConventionAware) {
+ if (isConventionAware && extensible) {
interfaceTypes.add(conventionAwareType.getInternalName());
}
+
+ if (extensible) {
+ interfaceTypes.add(extensionAwareType.getInternalName());
+ interfaceTypes.add(hasConventionType.getInternalName());
+ }
+
interfaceTypes.add(dynamicObjectAwareType.getInternalName());
- interfaceTypes.add(extensionAwareType.getInternalName());
- interfaceTypes.add(hasConventionType.getInternalName());
interfaceTypes.add(groovyObjectType.getInternalName());
visitor.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC, generatedType.getInternalName(), null,
@@ -109,7 +120,7 @@ public class AsmBackedClassGenerator extends AbstractClassGenerator {
// this.super(p0 .. pn)
methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
for (int i = 0; i < constructor.getParameterTypes().length; i++) {
- methodVisitor.visitVarInsn(Type.getType(constructor.getParameterTypes()[i]).getOpcode(Opcodes.ILOAD), i+1);
+ methodVisitor.visitVarInsn(Type.getType(constructor.getParameterTypes()[i]).getOpcode(Opcodes.ILOAD), i + 1);
}
methodVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, superclassType.getInternalName(), "<init>",
methodDescriptor);
@@ -225,108 +236,135 @@ public class AsmBackedClassGenerator extends AbstractClassGenerator {
}
public void mixInDynamicAware() throws Exception {
- final Type helperType = Type.getType(MixInExtensibleDynamicObject.class);
// GENERATE private MixInExtensibleDynamicObject dynamicObjectHelper = new MixInExtensibleDynamicObject(this, super.getAsDynamicObject())
- final String fieldSignature = "L" + MixInExtensibleDynamicObject.class.getName().replaceAll("\\.", "/") + ";";
+ Class<?> extensibleObjectFieldType = extensible ? MixInExtensibleDynamicObject.class : BeanDynamicObject.class;
+ final String fieldSignature = Type.getDescriptor(extensibleObjectFieldType);
visitor.visitField(Opcodes.ACC_PRIVATE, "dynamicObjectHelper", fieldSignature, null, null);
initDynamicObjectHelper = new MethodCodeBody() {
public void add(MethodVisitor visitor) throws Exception {
- String helperTypeConstructorDesc = Type.getMethodDescriptor(Type.VOID_TYPE, new Type[]{
- Type.getType(Object.class), dynamicObjectType
- });
-
- // GENERATE dynamicObjectHelper = new MixInExtensibleDynamicObject(this, super.getAsDynamicObject())
+ generateCreateDynamicObject(visitor);
+ visitor.visitFieldInsn(Opcodes.PUTFIELD, generatedType.getInternalName(), "dynamicObjectHelper",
+ fieldSignature);
+ // END
+ }
+ };
- visitor.visitVarInsn(Opcodes.ALOAD, 0);
+ // END
- // GENERATE new MixInExtensibleDynamicObject(this, super.getAsDynamicObject())
- visitor.visitTypeInsn(Opcodes.NEW, helperType.getInternalName());
- visitor.visitInsn(Opcodes.DUP);
+ if (extensible) {
+ // GENERATE public Convention getConvention() { return dynamicObjectHelper.getConvention(); }
- visitor.visitVarInsn(Opcodes.ALOAD, 0);
+ addGetter(HasConvention.class.getDeclaredMethod("getConvention"), new MethodCodeBody() {
+ public void add(MethodVisitor visitor) throws Exception {
- boolean useInheritedDynamicObject = GroovySystem.getMetaClassRegistry().getMetaClass(type).pickMethod("getAsDynamicObject", new Class[0]) != null;
+ // GENERATE dynamicObjectHelper.getConvention()
- if (useInheritedDynamicObject) {
- // GENERATE super.getAsDynamicObject()
visitor.visitVarInsn(Opcodes.ALOAD, 0);
- visitor.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getType(type).getInternalName(),
- "getAsDynamicObject", Type.getMethodDescriptor(dynamicObjectType, new Type[0]));
- } else {
- // GENERATE null
- visitor.visitInsn(Opcodes.ACONST_NULL);
+ visitor.visitFieldInsn(Opcodes.GETFIELD, generatedType.getInternalName(), "dynamicObjectHelper",
+ fieldSignature);
+ String getterDescriptor = Type.getMethodDescriptor(ExtensibleDynamicObject.class.getDeclaredMethod(
+ "getConvention"));
+ visitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, extensibleDynamicObjectHelperType.getInternalName(), "getConvention",
+ getterDescriptor);
}
+ });
- visitor.visitMethodInsn(Opcodes.INVOKESPECIAL, helperType.getInternalName(), "<init>",
- helperTypeConstructorDesc);
- // END
+ // END
- visitor.visitFieldInsn(Opcodes.PUTFIELD, generatedType.getInternalName(), "dynamicObjectHelper",
- fieldSignature);
- // END
- }
- };
+ // GENERATE public ExtensionContainer getExtensions() { return getConvention(); }
- // END
+ addGetter(ExtensionAware.class.getDeclaredMethod("getExtensions"), new MethodCodeBody() {
+ public void add(MethodVisitor visitor) throws Exception {
- // GENERATE public Convention getConvention() { return dynamicObjectHelper.getConvention(); }
+ // GENERATE getConvention()
- addGetter(HasConvention.class.getDeclaredMethod("getConvention"), new MethodCodeBody() {
- public void add(MethodVisitor visitor) throws Exception {
+ visitor.visitVarInsn(Opcodes.ALOAD, 0);
+ String getterDescriptor = Type.getMethodDescriptor(ExtensibleDynamicObject.class.getDeclaredMethod(
+ "getConvention"));
+ visitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, generatedType.getInternalName(), "getConvention",
+ getterDescriptor);
+ }
+ });
+ }
- // GENERATE dynamicObjectHelper.getConvention()
+ // END
+ // GENERATE public DynamicObject.getAsDynamicObject() { return dynamicObjectHelper; }
+
+ addGetter(DynamicObjectAware.class.getDeclaredMethod("getAsDynamicObject"), new MethodCodeBody() {
+ public void add(MethodVisitor visitor) {
visitor.visitVarInsn(Opcodes.ALOAD, 0);
visitor.visitFieldInsn(Opcodes.GETFIELD, generatedType.getInternalName(), "dynamicObjectHelper",
fieldSignature);
- String getterDescriptor = Type.getMethodDescriptor(ExtensibleDynamicObject.class.getDeclaredMethod(
- "getConvention"));
- visitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, helperType.getInternalName(), "getConvention",
- getterDescriptor);
}
});
// END
+ }
- // GENERATE public ExtensionContainer getExtensions() { return getConvention(); }
+ private void generateCreateDynamicObject(MethodVisitor visitor) {
+ if (extensible) {
- addGetter(ExtensionAware.class.getDeclaredMethod("getExtensions"), new MethodCodeBody() {
- public void add(MethodVisitor visitor) throws Exception {
+ String helperTypeConstructorDesc = Type.getMethodDescriptor(Type.VOID_TYPE, new Type[]{
+ Type.getType(Object.class), dynamicObjectType
+ });
- // GENERATE getConvention()
+ // GENERATE dynamicObjectHelper = new MixInExtensibleDynamicObject(this, super.getAsDynamicObject())
+
+ visitor.visitVarInsn(Opcodes.ALOAD, 0);
+
+ // GENERATE new MixInExtensibleDynamicObject(this, super.getAsDynamicObject())
+ visitor.visitTypeInsn(Opcodes.NEW, extensibleDynamicObjectHelperType.getInternalName());
+ visitor.visitInsn(Opcodes.DUP);
+ visitor.visitVarInsn(Opcodes.ALOAD, 0);
+
+ boolean useInheritedDynamicObject = GroovySystem.getMetaClassRegistry().getMetaClass(type).pickMethod("getAsDynamicObject", new Class[0]) != null;
+
+ if (useInheritedDynamicObject) {
+ // GENERATE super.getAsDynamicObject()
visitor.visitVarInsn(Opcodes.ALOAD, 0);
- String getterDescriptor = Type.getMethodDescriptor(ExtensibleDynamicObject.class.getDeclaredMethod(
- "getConvention"));
- visitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, generatedType.getInternalName(), "getConvention",
- getterDescriptor);
+ visitor.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getType(type).getInternalName(),
+ "getAsDynamicObject", Type.getMethodDescriptor(dynamicObjectType, new Type[0]));
+ } else {
+ // GENERATE null
+ visitor.visitInsn(Opcodes.ACONST_NULL);
}
- });
- // END
+ visitor.visitMethodInsn(Opcodes.INVOKESPECIAL, extensibleDynamicObjectHelperType.getInternalName(), "<init>",
+ helperTypeConstructorDesc);
+ // END
+ } else {
+ String helperTypeConstructorDesc = Type.getMethodDescriptor(Type.VOID_TYPE, new Type[]{
+ Type.getType(Object.class)
+ });
- // GENERATE public DynamicObject.getAsDynamicObject() { return dynamicObjectHelper; }
+ // GENERATE new BeanDynamicObject(this)
- addGetter(DynamicObjectAware.class.getDeclaredMethod("getAsDynamicObject"), new MethodCodeBody() {
- public void add(MethodVisitor visitor) {
+ visitor.visitVarInsn(Opcodes.ALOAD, 0);
- // GENERATE dynamicObjectHelper
+ // GENERATE new BeanDynamicObject(this)
+ visitor.visitTypeInsn(Opcodes.NEW, nonExtensibleDynamicObjectHelperType.getInternalName());
+ visitor.visitInsn(Opcodes.DUP);
- visitor.visitVarInsn(Opcodes.ALOAD, 0);
- visitor.visitFieldInsn(Opcodes.GETFIELD, generatedType.getInternalName(), "dynamicObjectHelper",
- fieldSignature);
- }
- });
+ visitor.visitVarInsn(Opcodes.ALOAD, 0);
- // END
+ visitor.visitMethodInsn(Opcodes.INVOKESPECIAL, nonExtensibleDynamicObjectHelperType.getInternalName(), "<init>",
+ helperTypeConstructorDesc);
+ // END
+ }
}
public void mixInConventionAware() throws Exception {
+ if (!extensible) {
+ return;
+ }
+
// GENERATE private ConventionMapping mapping = new ConventionAwareHelper(this, getConvention())
- final String mappingFieldSignature = "L" + ConventionMapping.class.getName().replaceAll("\\.", "/") + ";";
+ final String mappingFieldSignature = Type.getDescriptor(ConventionMapping.class);
final String getConventionDesc = Type.getMethodDescriptor(conventionType, new Type[0]);
visitor.visitField(Opcodes.ACC_PRIVATE, "mapping", mappingFieldSignature, null, null);
@@ -395,7 +433,7 @@ public class AsmBackedClassGenerator extends AbstractClassGenerator {
// GENERATE private MetaClass metaClass = GroovySystem.getMetaClassRegistry().getMetaClass(getClass())
- final String metaClassFieldSignature = "L" + MetaClass.class.getName().replaceAll("\\.", "/") + ";";
+ final String metaClassFieldSignature = Type.getDescriptor(MetaClass.class);
visitor.visitField(Opcodes.ACC_PRIVATE, "metaClass", metaClassFieldSignature, null, null);
initMetaClass = new MethodCodeBody() {
@@ -598,6 +636,9 @@ public class AsmBackedClassGenerator extends AbstractClassGenerator {
}
public void addGetter(MetaBeanProperty property) throws Exception {
+ if (!extensible) {
+ return;
+ }
MetaMethod getter = property.getGetter();
// GENERATE private boolean <prop>Set;
@@ -606,7 +647,7 @@ public class AsmBackedClassGenerator extends AbstractClassGenerator {
visitor.visitField(Opcodes.ACC_PRIVATE, flagName, Type.BOOLEAN_TYPE.getDescriptor(), null, null);
addConventionGetter(getter.getName(), flagName, property);
-
+
String getterName = getter.getName();
Class<?> returnType = getter.getReturnType();
@@ -681,6 +722,9 @@ public class AsmBackedClassGenerator extends AbstractClassGenerator {
}
public void addSetter(MetaBeanProperty property) throws Exception {
+ if (!extensible) {
+ return;
+ }
MetaMethod setter = property.getSetter();
// GENERATE public <return-type> <setter>(<type> v) { <return-type> v = super.<setter>(v); <prop>Set = true; return v; }
@@ -740,6 +784,9 @@ public class AsmBackedClassGenerator extends AbstractClassGenerator {
}
public void overrideSetMethod(MetaBeanProperty property, MetaMethod metaMethod) throws Exception {
+ if (!extensible) {
+ return;
+ }
Type paramType = Type.getType(metaMethod.getParameterTypes()[0].getTheClass());
Type returnType = Type.getType(metaMethod.getReturnType());
String methodDescriptor = Type.getMethodDescriptor(returnType, new Type[]{paramType});
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/BeanDynamicObject.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/BeanDynamicObject.java
index 01b2bc3..53e593d 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/BeanDynamicObject.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/BeanDynamicObject.java
@@ -17,8 +17,15 @@ package org.gradle.api.internal;
import groovy.lang.*;
import groovy.lang.MissingMethodException;
+import org.codehaus.groovy.reflection.ParameterTypes;
import org.codehaus.groovy.runtime.InvokerInvocationException;
+import org.gradle.api.internal.coerce.MethodArgumentsTransformer;
+import org.gradle.api.internal.coerce.TypeCoercingMethodArgumentsTransformer;
+import org.gradle.api.specs.Spec;
+import org.gradle.internal.reflect.JavaReflectionUtil;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -28,12 +35,15 @@ import java.util.Map;
* A {@link DynamicObject} which uses groovy reflection to provide access to the properties and methods of a bean.
*/
public class BeanDynamicObject extends AbstractDynamicObject {
-
+
private final Object bean;
private final boolean includeProperties;
private final DynamicObject delegate;
private final boolean implementsMissing;
+ // NOTE: If this guy starts caching internally, consider sharing an instance
+ private final MethodArgumentsTransformer argsTransformer = new TypeCoercingMethodArgumentsTransformer();
+
public BeanDynamicObject(Object bean) {
this(bean, true);
}
@@ -56,7 +66,7 @@ public class BeanDynamicObject extends AbstractDynamicObject {
return new GroovyObjectAdapter();
}
}
-
+
public BeanDynamicObject withNoProperties() {
return new BeanDynamicObject(bean, false);
}
@@ -94,7 +104,7 @@ public class BeanDynamicObject extends AbstractDynamicObject {
@Override
public boolean hasProperty(String name) {
- return delegate.hasProperty(name);
+ return delegate.hasProperty(name);
}
@Override
@@ -104,22 +114,24 @@ public class BeanDynamicObject extends AbstractDynamicObject {
@Override
public void setProperty(final String name, Object value) throws MissingPropertyException {
- delegate.setProperty(name, value);
+ delegate.setProperty(name, value);
}
@Override
public Map<String, ?> getProperties() {
- return delegate.getProperties();
+ return delegate.getProperties();
}
@Override
public boolean hasMethod(String name, Object... arguments) {
- return delegate.hasMethod(name, arguments);
+ return delegate.hasMethod(name, arguments);
}
@Override
public Object invokeMethod(String name, Object... arguments) throws MissingMethodException {
- return delegate.invokeMethod(name, arguments);
+ // Maybe transform the arguments before calling the method (e.g. type coercion)
+ arguments = argsTransformer.transform(bean, name, arguments);
+ return delegate.invokeMethod(name, arguments);
}
private class MetaClassAdapter implements DynamicObject {
@@ -160,9 +172,7 @@ public class BeanDynamicObject extends AbstractDynamicObject {
MetaClass metaClass = getMetaClass();
MetaProperty property = metaClass.hasProperty(bean, name);
if (property == null) {
- if (property == null) {
- getMetaClass().invokeMissingProperty(bean, name, null, false);
- }
+ getMetaClass().invokeMissingProperty(bean, name, null, false);
}
if (property instanceof MetaBeanProperty && ((MetaBeanProperty) property).getSetter() == null) {
@@ -175,6 +185,10 @@ public class BeanDynamicObject extends AbstractDynamicObject {
};
}
try {
+
+ // Attempt type coercion before trying to set the property
+ value = argsTransformer.transform(bean, MetaProperty.getSetterName(name), value)[0];
+
metaClass.setProperty(bean, name, value);
} catch (InvokerInvocationException e) {
if (e.getCause() instanceof RuntimeException) {
@@ -207,11 +221,27 @@ public class BeanDynamicObject extends AbstractDynamicObject {
return properties;
}
- public boolean hasMethod(String name, Object... arguments) {
- return !getMetaClass().respondsTo(bean, name, arguments).isEmpty();
+ public boolean hasMethod(final String name, final Object... arguments) {
+ boolean respondsTo = !getMetaClass().respondsTo(bean, name, arguments).isEmpty();
+ if (respondsTo) {
+ return true;
+ } else {
+ Method method = JavaReflectionUtil.findMethod(bean.getClass(), new Spec<Method>() {
+ public boolean isSatisfiedBy(Method potentialMethod) {
+ if (Modifier.isPrivate(potentialMethod.getModifiers()) && potentialMethod.getName().equals(name)) {
+ ParameterTypes parameterTypes = new ParameterTypes(potentialMethod.getParameterTypes());
+ return parameterTypes.isValidMethod(arguments);
+ } else {
+ return false;
+ }
+ }
+ });
+
+ return method != null;
+ }
}
- public Object invokeMethod(String name, Object... arguments) throws MissingMethodException {
+ public Object invokeMethod(final String name, final Object... arguments) throws MissingMethodException {
try {
return getMetaClass().invokeMethod(bean, name, arguments);
} catch (InvokerInvocationException e) {
@@ -219,8 +249,6 @@ public class BeanDynamicObject extends AbstractDynamicObject {
throw (RuntimeException) e.getCause();
}
throw e;
- } catch (MissingMethodException e) {
- throw methodMissingException(name, arguments);
}
}
@@ -242,7 +270,7 @@ public class BeanDynamicObject extends AbstractDynamicObject {
So in this case we use these methods directly on the GroovyObject in case it does implement logic at this level.
*/
private class GroovyObjectAdapter extends MetaClassAdapter {
- private final GroovyObject groovyObject = (GroovyObject)bean;
+ private final GroovyObject groovyObject = (GroovyObject) bean;
@Override
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/CachingDirectedGraphWalker.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/CachingDirectedGraphWalker.java
deleted file mode 100644
index 379a79b..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/CachingDirectedGraphWalker.java
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal;
-
-import org.gradle.util.GUtil;
-
-import java.util.*;
-
-/**
- * A graph walker which collects the values reachable from a given set of start nodes. Handles cycles in the graph. Can
- * be reused to perform multiple searches, and reuses the results of previous searches.
- *
- * Uses a variation of Tarjan's algorithm: http://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm
- */
-public class CachingDirectedGraphWalker<N, T> {
- private final DirectedGraphWithEdgeValues<N, T> graph;
- private List<N> startNodes = new LinkedList<N>();
- private final Map<N, Set<T>> cachedNodeValues = new HashMap<N, Set<T>>();
-
- public CachingDirectedGraphWalker(DirectedGraph<N, T> graph) {
- this.graph = new GraphWithEmpyEdges<N, T>(graph);
- }
-
- public CachingDirectedGraphWalker(DirectedGraphWithEdgeValues<N, T> graph) {
- this.graph = graph;
- }
-
- /**
- * Adds some start nodes.
- */
- public CachingDirectedGraphWalker<N, T> add(N... values) {
- add(Arrays.asList(values));
- return this;
- }
-
- /**
- * Adds some start nodes.
- */
- public CachingDirectedGraphWalker add(Iterable<? extends N> values) {
- GUtil.addToCollection(startNodes, values);
- return this;
- }
-
- /**
- * Calculates the set of values of nodes reachable from the start nodes.
- */
- public Set<T> findValues() {
- try {
- return doSearch();
- } finally {
- startNodes.clear();
- }
- }
-
- private Set<T> doSearch() {
- int componentCount = 0;
- Map<N, NodeDetails<N, T>> seenNodes = new HashMap<N, NodeDetails<N, T>>();
- Map<Integer, NodeDetails<N, T>> components = new HashMap<Integer, NodeDetails<N, T>>();
- LinkedList<N> queue = new LinkedList<N>(startNodes);
-
- while (!queue.isEmpty()) {
- N node = queue.getFirst();
- NodeDetails<N, T> details = seenNodes.get(node);
- if (details == null) {
- // Have not visited this node yet. Push its successors onto the queue in front of this node and visit
- // them
-
- details = new NodeDetails<N, T>(node, componentCount++);
- seenNodes.put(node, details);
- components.put(details.component, details);
-
- Set<T> cacheValues = cachedNodeValues.get(node);
- if (cacheValues != null) {
- // Already visited this node
- details.values = cacheValues;
- details.finished = true;
- queue.removeFirst();
- continue;
- }
-
- graph.getNodeValues(node, details.values, details.successors);
- for (N connectedNode : details.successors) {
- if (!seenNodes.containsKey(connectedNode)) {
- queue.add(0, connectedNode);
- }
- // Else, already visiting or have visited the successor node (we're in a cycle)
- }
- } else {
- // Have visited all of this node's successors
- queue.removeFirst();
-
- if (cachedNodeValues.containsKey(node)) {
- continue;
- }
-
- for (N connectedNode : details.successors) {
- NodeDetails<N, T> connectedNodeDetails = seenNodes.get(connectedNode);
- if (!connectedNodeDetails.finished) {
- // part of a cycle
- details.minSeen = Math.min(details.minSeen, connectedNodeDetails.minSeen);
- }
- details.values.addAll(connectedNodeDetails.values);
- graph.getEdgeValues(node, connectedNode, details.values);
- }
-
- if (details.minSeen != details.component) {
- // Part of a strongly connected component (ie cycle) - move values to root of the component
- // The root is the first node of the component we encountered
- NodeDetails<N, T> rootDetails = components.get(details.minSeen);
- rootDetails.values.addAll(details.values);
- details.values.clear();
- rootDetails.strongComponentMembers.addAll(details.strongComponentMembers);
- } else {
- // Not part of a strongly connected component or the root of a strongly connected component
- for (NodeDetails<N, T> componentMember : details.strongComponentMembers) {
- cachedNodeValues.put(componentMember.node, details.values);
- componentMember.finished = true;
- components.remove(componentMember.component);
- }
- }
- }
- }
-
- Set<T> values = new LinkedHashSet<T>();
- for (N startNode : startNodes) {
- values.addAll(cachedNodeValues.get(startNode));
- }
- return values;
- }
-
- private static class NodeDetails<N, T> {
- private final int component;
- private final N node;
- private Set<T> values = new LinkedHashSet<T>();
- private List<N> successors = new ArrayList<N>();
- private Set<NodeDetails<N, T>> strongComponentMembers = new LinkedHashSet<NodeDetails<N, T>>();
- private int minSeen;
- private boolean finished;
-
- public NodeDetails(N node, int component) {
- this.node = node;
- this.component = component;
- minSeen = component;
- strongComponentMembers.add(this);
- }
- }
-
- private static class GraphWithEmpyEdges<N, T> implements DirectedGraphWithEdgeValues<N, T> {
- private final DirectedGraph<N, T> graph;
-
- public GraphWithEmpyEdges(DirectedGraph<N, T> graph) {
- this.graph = graph;
- }
-
- public void getEdgeValues(N from, N to, Collection<T> values) {
- }
-
- public void getNodeValues(N node, Collection<T> values, Collection<N> connectedNodes) {
- graph.getNodeValues(node, values, connectedNodes);
- }
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/ClassGeneratorBackedInstantiator.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/ClassGeneratorBackedInstantiator.java
index 2a28305..4ac370e 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/ClassGeneratorBackedInstantiator.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/ClassGeneratorBackedInstantiator.java
@@ -26,7 +26,7 @@ public class ClassGeneratorBackedInstantiator implements Instantiator {
this.instantiator = instantiator;
}
- public <T> T newInstance(Class<T> type, Object... parameters) {
+ public <T> T newInstance(Class<? extends T> type, Object... parameters) {
// During the construction of the object, it will look for this global instantiator.
// This is to support ExtensionContainer.add(String, Class, Object...) which facilitates
// making extensions ExtensionAware themselves.
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/CompositeDomainObjectSet.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/CompositeDomainObjectSet.java
index 9e8f4de..dadd3f1 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/CompositeDomainObjectSet.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/CompositeDomainObjectSet.java
@@ -81,9 +81,11 @@ public class CompositeDomainObjectSet<T> extends DefaultDomainObjectSet<T> {
}
public void addCollection(DomainObjectCollection<? extends T> collection) {
- getStore().addComposited(collection);
- collection.all(getEventRegister().getAddAction());
- collection.whenObjectRemoved(getEventRegister().getRemoveAction());
+ if (!getStore().getCollections().contains(collection)) {
+ getStore().addComposited(collection);
+ collection.all(getEventRegister().getAddAction());
+ collection.whenObjectRemoved(getEventRegister().getRemoveAction());
+ }
}
public void removeCollection(DomainObjectCollection<? extends T> collection) {
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/ConventionAwareHelper.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/ConventionAwareHelper.java
index 05e5925..b80f13d 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/ConventionAwareHelper.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/ConventionAwareHelper.java
@@ -22,20 +22,17 @@ import org.gradle.api.InvalidUserDataException;
import org.gradle.api.internal.plugins.DefaultConvention;
import org.gradle.api.plugins.Convention;
import org.gradle.internal.UncheckedException;
-import org.gradle.util.ReflectionUtil;
+import org.gradle.internal.reflect.JavaReflectionUtil;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;
-/**
- * @author Hans Dockter
- */
public class ConventionAwareHelper implements ConventionMapping, HasConvention {
//prefix internal fields with _ so that they don't get into the way of propertyMissing()
private final Convention _convention;
- private IConventionAware _source;
+ private final IConventionAware _source;
private final Map<String, MappedPropertyImpl> _mappings = new HashMap<String, MappedPropertyImpl>();
/**
@@ -55,7 +52,7 @@ public class ConventionAwareHelper implements ConventionMapping, HasConvention {
}
private MappedProperty map(String propertyName, Value<?> value) {
- if (!ReflectionUtil.hasProperty(_source, propertyName)) {
+ if (!JavaReflectionUtil.propertyExists(_source, propertyName)) {
throw new InvalidUserDataException(
"You can't map a property that does not exist: propertyName=" + propertyName);
}
@@ -124,14 +121,6 @@ public class ConventionAwareHelper implements ConventionMapping, HasConvention {
return _convention;
}
- public IConventionAware getSource() {
- return _source;
- }
-
- public void setSource(IConventionAware source) {
- this._source = source;
- }
-
private static class MappedPropertyImpl implements MappedProperty {
private final Value<?> value;
private boolean haveValue;
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/ConventionTask.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/ConventionTask.java
index f79245a..c5e36de 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/ConventionTask.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/ConventionTask.java
@@ -22,9 +22,6 @@ import org.gradle.api.Task;
import java.util.concurrent.Callable;
-/**
- * @author Hans Dockter
- */
public abstract class ConventionTask extends DefaultTask implements IConventionAware {
private ConventionMapping conventionMapping;
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/DefaultNamedDomainObjectCollection.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/DefaultNamedDomainObjectCollection.java
index 5d6dfbc..77a7b2b 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/DefaultNamedDomainObjectCollection.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/DefaultNamedDomainObjectCollection.java
@@ -130,6 +130,14 @@ public class DefaultNamedDomainObjectCollection<T> extends DefaultDomainObjectCo
return map;
}
+ public SortedSet<String> getNames() {
+ SortedSet<String> set = new TreeSet<String>();
+ for (T o : getStore()) {
+ set.add(namer.determineName(o));
+ }
+ return set;
+ }
+
public <S extends T> NamedDomainObjectCollection<S> withType(Class<S> type) {
return filtered(createFilter(type));
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/DefaultPolymorphicDomainObjectContainer.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/DefaultPolymorphicDomainObjectContainer.java
index 06e2635..5d7ddaa 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/DefaultPolymorphicDomainObjectContainer.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/DefaultPolymorphicDomainObjectContainer.java
@@ -15,10 +15,15 @@
*/
package org.gradle.api.internal;
+import com.google.common.base.Joiner;
+import com.google.common.collect.Lists;
+import groovy.lang.Closure;
import org.gradle.api.*;
import org.gradle.internal.reflect.Instantiator;
+import java.util.Collections;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
public class DefaultPolymorphicDomainObjectContainer<T> extends AbstractPolymorphicDomainObjectContainer<T>
@@ -39,8 +44,9 @@ public class DefaultPolymorphicDomainObjectContainer<T> extends AbstractPolymorp
protected T doCreate(String name) {
if (defaultFactory == null) {
- throw new InvalidUserDataException("This container does not support "
- + "creating domain objects without specifying a type.");
+ throw new InvalidUserDataException(String.format("Cannot create a %s named '%s' because this container "
+ + "does not support creating elements by name alone. Please specify which subtype of %s to create. "
+ + "Known subtypes are: %s", getTypeDisplayName(), name, getTypeDisplayName(), getSupportedTypeNames()));
}
return defaultFactory.create(name);
}
@@ -49,8 +55,8 @@ public class DefaultPolymorphicDomainObjectContainer<T> extends AbstractPolymorp
@SuppressWarnings("unchecked")
NamedDomainObjectFactory<U> factory = (NamedDomainObjectFactory<U>) factories.get(type);
if (factory == null) {
- throw new InvalidUserDataException(String.format("This container does not support "
- + "creating domain objects of type '%s'.", type.getName()));
+ throw new InvalidUserDataException(String.format("Cannot create a %s because this type is not known "
+ + "to this container. Known types are: %s", type.getSimpleName(), getSupportedTypeNames()));
}
return factory.create(name);
}
@@ -61,9 +67,36 @@ public class DefaultPolymorphicDomainObjectContainer<T> extends AbstractPolymorp
public <U extends T> void registerFactory(Class<U> type, NamedDomainObjectFactory<? extends U> factory) {
if (!getType().isAssignableFrom(type)) {
- throw new IllegalArgumentException(String.format("Factory element type '%s' is not a subtype of "
- + "container element type '%s'", type.getName(), getType().getName()));
+ throw new IllegalArgumentException(String.format("Cannot register a factory for type %s because "
+ + "it is not a subtype of container element type %s.", type.getSimpleName(), getTypeDisplayName()));
}
factories.put(type, factory);
}
+
+ public <U extends T> void registerFactory(Class<U> type, final Closure<? extends U> factory) {
+ registerFactory(type, new NamedDomainObjectFactory<U>() {
+ public U create(String name) {
+ return factory.call(name);
+ }
+ });
+ }
+
+ public <U extends T> void registerBinding(Class<U> type, final Class<? extends U> implementationType) {
+ registerFactory(type, new NamedDomainObjectFactory<U>() {
+ boolean named = Named.class.isAssignableFrom(implementationType);
+ public U create(String name) {
+ return named ? getInstantiator().newInstance(implementationType, name)
+ : getInstantiator().newInstance(implementationType);
+ }
+ });
+ }
+
+ private String getSupportedTypeNames() {
+ List<String> names = Lists.newArrayList();
+ for (Class<?> clazz : factories.keySet()) {
+ names.add(clazz.getSimpleName());
+ }
+ Collections.sort(names);
+ return names.isEmpty() ? "(None)" : Joiner.on(", ").join(names);
+ }
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/DependencyInjectingInstantiator.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/DependencyInjectingInstantiator.java
index 168b46f..2d220b9 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/DependencyInjectingInstantiator.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/DependencyInjectingInstantiator.java
@@ -52,7 +52,7 @@ public class DependencyInjectingInstantiator implements Instantiator {
this.onDeprecationWarning = onDeprecationWarning;
}
- public <T> T newInstance(Class<T> type, Object... parameters) {
+ public <T> T newInstance(Class<? extends T> type, Object... parameters) {
try {
validateType(type);
Constructor<?> constructor = selectConstructor(type, parameters);
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/DirectedGraph.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/DirectedGraph.java
deleted file mode 100644
index 930dd5c..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/DirectedGraph.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal;
-
-import java.util.Collection;
-
-/**
- * A directed graph with nodes of type N. Each node has a collection of values of type V.
- */
-public interface DirectedGraph<N, V> {
- void getNodeValues(N node, Collection<V> values, Collection<N> connectedNodes);
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/DirectedGraphWithEdgeValues.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/DirectedGraphWithEdgeValues.java
deleted file mode 100644
index 16a5d0d..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/DirectedGraphWithEdgeValues.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal;
-
-import java.util.Collection;
-
-/**
- * A directed graph with nodes of type N. Each edge has a collection of values of type V
- */
-public interface DirectedGraphWithEdgeValues<N, V> extends DirectedGraph<N, V> {
- void getEdgeValues(N from, N to, Collection<V> values);
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/DocumentationRegistry.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/DocumentationRegistry.java
index ba7d428..e7182e1 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/DocumentationRegistry.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/DocumentationRegistry.java
@@ -18,45 +18,20 @@ package org.gradle.api.internal;
import org.gradle.util.GradleVersion;
-import java.io.File;
-
/**
* Locates documentation for various features.
*/
public class DocumentationRegistry {
- private final GradleDistributionLocator locator;
private final GradleVersion gradleVersion;
- public DocumentationRegistry(GradleDistributionLocator locator) {
- this(locator, GradleVersion.current());
- }
-
- public DocumentationRegistry(GradleDistributionLocator locator, GradleVersion gradleVersion) {
- this.locator = locator;
- this.gradleVersion = gradleVersion;
+ public DocumentationRegistry() {
+ this.gradleVersion = GradleVersion.current();
}
/**
* Returns the location the documentation for the given feature, referenced by id. The location may be local or remote.
*/
public String getDocumentationFor(String id) {
- if (locator.getGradleHome() != null) {
- File pageLocation = new File(locator.getGradleHome(), String.format("docs/userguide/%s.html", id));
- File userGuideLocation = new File(locator.getGradleHome(), "docs/userguide/userguide.html");
- if (pageLocation.isFile() && userGuideLocation.isFile()) {
- return pageLocation.getAbsolutePath();
- }
- if (!pageLocation.isFile() && userGuideLocation.isFile()) {
- throw new IllegalArgumentException(String.format("User guide page '%s' not found.", pageLocation));
- }
- if (pageLocation.isFile() && !userGuideLocation.isFile()) {
- throw new IllegalArgumentException(String.format("User guide page '%s' not found.", userGuideLocation));
- }
- }
return String.format("http://gradle.org/docs/%s/userguide/%s.html", gradleVersion.getVersion(), id);
}
-
- public String getFeatureLifecycle() {
- return getDocumentationFor("feature_lifecycle");
- }
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/GradleInternal.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/GradleInternal.java
index fbc439d..b840a1d 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/GradleInternal.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/GradleInternal.java
@@ -15,12 +15,13 @@
*/
package org.gradle.api.internal;
+import org.gradle.BuildListener;
import org.gradle.api.ProjectEvaluationListener;
-import org.gradle.api.internal.project.*;
+import org.gradle.api.internal.project.ProjectInternal;
+import org.gradle.api.internal.project.ProjectRegistry;
+import org.gradle.internal.service.scopes.ServiceRegistryFactory;
import org.gradle.api.invocation.Gradle;
import org.gradle.execution.TaskGraphExecuter;
-import org.gradle.BuildListener;
-import org.gradle.util.MultiParentClassLoader;
/**
* An internal interface for Gradle that exposed objects and concepts that are not intended for public
@@ -42,12 +43,7 @@ public interface GradleInternal extends Gradle {
*/
ProjectInternal getDefaultProject();
- IProjectRegistry<ProjectInternal> getProjectRegistry();
-
- /**
- * Returns the root {@code ClassLoader} to use for the scripts of this build.
- */
- MultiParentClassLoader getScriptClassLoader();
+ ProjectRegistry<ProjectInternal> getProjectRegistry();
/**
* Returns the broadcaster for {@link ProjectEvaluationListener} events for this build
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/GraphAggregator.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/GraphAggregator.java
deleted file mode 100644
index 68d5c2c..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/GraphAggregator.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal;
-
-import java.util.*;
-
-/**
- * Groups the nodes of a graph based on their reachability from a set of starting nodes.
- */
-public class GraphAggregator<N> {
- private final CachingDirectedGraphWalker<N, N> graphWalker;
-
- public GraphAggregator(DirectedGraph<N, ?> graph) {
- graphWalker = new CachingDirectedGraphWalker<N, N>(new ConnectedNodesAsValuesDirectedGraph<N>(graph));
- }
-
- public Result<N> group(Collection<? extends N> startNodes, Collection<? extends N> allNodes) {
- Map<N, Set<N>> reachableByNode = new HashMap<N, Set<N>>();
- Set<N> topLevelNodes = new LinkedHashSet<N>(allNodes);
- for (N node : allNodes) {
- Set<N> reachableNodes = graphWalker.add(node).findValues();
- reachableByNode.put(node, reachableNodes);
- topLevelNodes.removeAll(reachableNodes);
- }
- topLevelNodes.addAll(startNodes);
- Map<N, Set<N>> nodes = new HashMap<N, Set<N>>();
- for (N node : topLevelNodes) {
- nodes.put(node, calculateReachableNodes(reachableByNode, node, topLevelNodes));
- }
- return new Result<N>(nodes, topLevelNodes);
- }
-
- private Set<N> calculateReachableNodes(Map<N, Set<N>> nodes, N node, Set<N> topLevelNodes) {
- Set<N> reachableNodes = nodes.get(node);
- reachableNodes.add(node);
- Set<N> reachableStartNodes = new LinkedHashSet<N>(topLevelNodes);
- reachableStartNodes.retainAll(reachableNodes);
- reachableStartNodes.remove(node);
- for (N startNode : reachableStartNodes) {
- reachableNodes.removeAll(calculateReachableNodes(nodes, startNode, topLevelNodes));
- }
- return reachableNodes;
- }
-
- public static class Result<N> {
- private final Map<N, Set<N>> nodes;
- private final Set<N> topLevelNodes;
-
- public Result(Map<N, Set<N>> nodes, Set<N> topLevelNodes) {
- this.nodes = nodes;
- this.topLevelNodes = topLevelNodes;
- }
-
- public Set<N> getNodes(N startNode) {
- return nodes.get(startNode);
- }
-
- public Set<N> getTopLevelNodes() {
- return topLevelNodes;
- }
- }
-
- private static class ConnectedNodesAsValuesDirectedGraph<N> implements DirectedGraph<N, N> {
- private final DirectedGraph<N, ?> graph;
-
- private ConnectedNodesAsValuesDirectedGraph(DirectedGraph<N, ?> graph) {
- this.graph = graph;
- }
-
- public void getNodeValues(N node, Collection<N> values, Collection<N> connectedNodes) {
- Set<N> edges = new LinkedHashSet<N>();
- graph.getNodeValues(node, new ArrayList(), edges);
- values.addAll(edges);
- connectedNodes.addAll(edges);
- }
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/IConventionAware.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/IConventionAware.java
index a4139a7..eeb4553 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/IConventionAware.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/IConventionAware.java
@@ -22,8 +22,6 @@ package org.gradle.api.internal;
*
* <p>Each getter of an {@code IConventionAware} object should use the mappings to determine the value for the property,
* when no value has been explicitly set for the property.</p>
- *
- * @author Hans Dockter
*/
public interface IConventionAware {
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/NamedDomainObjectContainerConfigureDelegate.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/NamedDomainObjectContainerConfigureDelegate.java
index ce26dc4..c6c0a05 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/NamedDomainObjectContainerConfigureDelegate.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/NamedDomainObjectContainerConfigureDelegate.java
@@ -18,15 +18,15 @@ package org.gradle.api.internal;
import org.gradle.api.NamedDomainObjectContainer;
public class NamedDomainObjectContainerConfigureDelegate extends ConfigureDelegate {
- private final NamedDomainObjectContainer container;
+ private final NamedDomainObjectContainer _container;
public NamedDomainObjectContainerConfigureDelegate(Object owner, NamedDomainObjectContainer container) {
super(owner, container);
- this.container = container;
+ _container = container;
}
@Override
protected void _configure(String name, Object[] params) {
- container.create(name);
+ _container.create(name);
}
}
\ No newline at end of file
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/PolymorphicDomainObjectContainerConfigureDelegate.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/PolymorphicDomainObjectContainerConfigureDelegate.java
index f07befc..81bb9e1 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/PolymorphicDomainObjectContainerConfigureDelegate.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/PolymorphicDomainObjectContainerConfigureDelegate.java
@@ -20,25 +20,27 @@ import org.gradle.api.PolymorphicDomainObjectContainer;
import groovy.lang.Closure;
public class PolymorphicDomainObjectContainerConfigureDelegate extends NamedDomainObjectContainerConfigureDelegate {
- private final PolymorphicDomainObjectContainer container;
+ private final PolymorphicDomainObjectContainer _container;
public PolymorphicDomainObjectContainerConfigureDelegate(Object owner, PolymorphicDomainObjectContainer container) {
super(owner, container);
- this.container = container;
+ this._container = container;
}
@Override
protected boolean _isConfigureMethod(String name, Object[] params) {
- return super._isConfigureMethod(name, params) || params.length == 2 && params[0] instanceof Class && params[1] instanceof Closure;
+ return super._isConfigureMethod(name, params)
+ || params.length == 1 && params[0] instanceof Class
+ || params.length == 2 && params[0] instanceof Class && params[1] instanceof Closure;
}
@Override
@SuppressWarnings("unchecked")
protected void _configure(String name, Object[] params) {
- if (params.length <= 1) {
- container.create(name);
+ if (params.length > 0 && params[0] instanceof Class) {
+ _container.create(name, (Class) params[0]);
} else {
- container.create(name, (Class) params[0]);
+ _container.create(name);
}
}
}
\ No newline at end of file
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/SettingsInternal.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/SettingsInternal.java
index 04575f4..969d18e 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/SettingsInternal.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/SettingsInternal.java
@@ -18,7 +18,7 @@ package org.gradle.api.internal;
import org.gradle.StartParameter;
import org.gradle.api.initialization.Settings;
-import org.gradle.api.internal.project.IProjectRegistry;
+import org.gradle.api.internal.project.ProjectRegistry;
import org.gradle.groovy.scripts.ScriptSource;
import org.gradle.initialization.DefaultProjectDescriptor;
@@ -29,5 +29,5 @@ public interface SettingsInternal extends Settings {
ScriptSource getSettingsScript();
- IProjectRegistry<DefaultProjectDescriptor> getProjectRegistry();
+ ProjectRegistry<DefaultProjectDescriptor> getProjectRegistry();
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/TaskInternal.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/TaskInternal.java
index d062bf4..37eaaa0 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/TaskInternal.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/TaskInternal.java
@@ -17,6 +17,7 @@
package org.gradle.api.internal;
import org.gradle.api.Task;
+import org.gradle.api.internal.tasks.ContextAwareTaskAction;
import org.gradle.api.internal.tasks.TaskExecuter;
import org.gradle.api.internal.tasks.TaskStateInternal;
import org.gradle.api.internal.tasks.execution.TaskValidator;
@@ -25,10 +26,15 @@ import org.gradle.internal.Factory;
import org.gradle.logging.StandardOutputCapture;
import org.gradle.util.Configurable;
-import java.util.List;
import java.io.File;
+import java.util.List;
public interface TaskInternal extends Task, Configurable<Task> {
+
+ // Can we just override Task.getActions()?
+ // Would need to change return type on Task API to: List<? super Action<? super Task>> : not certain this is back-compatible
+ List<ContextAwareTaskAction> getTaskActions();
+
Spec<? super TaskInternal> getOnlyIf();
void execute();
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/TaskOutputsInternal.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/TaskOutputsInternal.java
index 5a079cb..1ff75d1 100755
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/TaskOutputsInternal.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/TaskOutputsInternal.java
@@ -26,4 +26,5 @@ public interface TaskOutputsInternal extends TaskOutputs {
FileCollection getPreviousFiles();
void setHistory(TaskExecutionHistory history);
+
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/ArtifactPublicationServices.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/ArtifactPublicationServices.java
index 5291a1f..52d4a7a 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/ArtifactPublicationServices.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/ArtifactPublicationServices.java
@@ -16,16 +16,9 @@
package org.gradle.api.internal.artifacts;
import org.gradle.api.artifacts.dsl.RepositoryHandler;
-import org.gradle.api.internal.artifacts.ivyservice.IvyModuleDescriptorWriter;
-import org.gradle.api.internal.artifacts.ivyservice.ModuleDescriptorConverter;
public interface ArtifactPublicationServices {
-
RepositoryHandler createRepositoryHandler();
- ModuleDescriptorConverter getDescriptorFileModuleConverter();
-
- IvyModuleDescriptorWriter getIvyModuleDescriptorWriter();
-
ArtifactPublisher createArtifactPublisher();
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/ArtifactPublisher.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/ArtifactPublisher.java
index 64f14c0..8d754ee 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/ArtifactPublisher.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/ArtifactPublisher.java
@@ -23,9 +23,6 @@ import org.gradle.api.internal.artifacts.repositories.PublicationAwareRepository
import java.io.File;
import java.util.Set;
-/**
- * @author Hans Dockter
- */
public interface ArtifactPublisher {
void publish(Iterable<? extends PublicationAwareRepository> repositories, Module module, Set<? extends Configuration> configurations, File descriptor) throws PublishException;
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/BaseRepositoryFactory.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/BaseRepositoryFactory.java
index b265e39..d8ac5a1 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/BaseRepositoryFactory.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/BaseRepositoryFactory.java
@@ -32,6 +32,8 @@ public interface BaseRepositoryFactory {
MavenArtifactRepository createMavenLocalRepository();
+ MavenArtifactRepository createJCenterRepository();
+
MavenArtifactRepository createMavenCentralRepository();
IvyArtifactRepository createIvyRepository();
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/CachingDependencyResolveContext.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/CachingDependencyResolveContext.java
index 660bca5..ce4ef94 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/CachingDependencyResolveContext.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/CachingDependencyResolveContext.java
@@ -17,8 +17,8 @@
package org.gradle.api.internal.artifacts;
import org.gradle.api.file.FileCollection;
-import org.gradle.api.internal.CachingDirectedGraphWalker;
-import org.gradle.api.internal.DirectedGraph;
+import org.gradle.internal.graph.CachingDirectedGraphWalker;
+import org.gradle.internal.graph.DirectedGraph;
import org.gradle.api.internal.file.UnionFileCollection;
import java.util.ArrayList;
@@ -52,7 +52,7 @@ public class CachingDependencyResolveContext implements DependencyResolveContext
}
private class DependencyGraph implements DirectedGraph<Object, FileCollection> {
- public void getNodeValues(Object node, Collection<FileCollection> values, Collection<Object> connectedNodes) {
+ public void getNodeValues(Object node, Collection<? super FileCollection> values, Collection<? super Object> connectedNodes) {
if (node instanceof FileCollection) {
FileCollection fileCollection = (FileCollection) node;
values.add(fileCollection);
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/DefaultArtifactIdentifier.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/DefaultArtifactIdentifier.java
deleted file mode 100644
index b9cbe72..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/DefaultArtifactIdentifier.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.artifacts;
-
-import org.gradle.api.artifacts.ArtifactIdentifier;
-import org.gradle.api.artifacts.ModuleVersionIdentifier;
-
-public class DefaultArtifactIdentifier implements ArtifactIdentifier {
- private final ModuleVersionIdentifier moduleVersionIdentifier;
- private final String name;
- private final String type;
- private final String extension;
- private final String classifier;
-
- public DefaultArtifactIdentifier(ModuleVersionIdentifier moduleVersionIdentifier, String name, String type, String extension, String classifier) {
- this.moduleVersionIdentifier = moduleVersionIdentifier;
- this.name = name;
- this.type = type;
- this.extension = extension;
- this.classifier = classifier;
- }
-
- public ModuleVersionIdentifier getModuleVersionIdentifier() {
- return moduleVersionIdentifier;
- }
-
- public String getName() {
- return name;
- }
-
- public String getType() {
- return type;
- }
-
- public String getExtension() {
- return extension;
- }
-
- public String getClassifier() {
- return classifier;
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/DefaultArtifactRepositoryContainer.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/DefaultArtifactRepositoryContainer.java
index a5badfc..eef5be5 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/DefaultArtifactRepositoryContainer.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/DefaultArtifactRepositoryContainer.java
@@ -38,9 +38,6 @@ import java.util.List;
import static org.gradle.api.internal.Cast.cast;
-/**
- * @author Hans Dockter
- */
public class DefaultArtifactRepositoryContainer extends DefaultNamedDomainObjectList<ArtifactRepository>
implements ArtifactRepositoryContainer {
@@ -85,11 +82,13 @@ public class DefaultArtifactRepositoryContainer extends DefaultNamedDomainObject
}
public boolean add(DependencyResolver resolver, Closure configureClosure) {
+ DeprecationLogger.nagUserOfDiscontinuedMethod("ArtifactRepositoryContainer.add(DependencyResolver, Closure)");
addCustomDependencyResolver(resolver, configureClosure, addLastAction);
return true;
}
public boolean add(DependencyResolver resolver) {
+ DeprecationLogger.nagUserOfDiscontinuedMethod("ArtifactRepositoryContainer.add(DependencyResolver)");
addCustomDependencyResolver(resolver, null, addLastAction);
return true;
}
@@ -99,6 +98,7 @@ public class DefaultArtifactRepositoryContainer extends DefaultNamedDomainObject
}
public DependencyResolver addFirst(Object userDescription, Closure configureClosure) {
+ DeprecationLogger.nagUserOfReplacedMethod("ArtifactRepositoryContainer.addFirst(Object)", "addFirst(ArtifactRepository");
return addCustomDependencyResolver(userDescription, configureClosure, addFirstAction);
}
@@ -122,6 +122,7 @@ public class DefaultArtifactRepositoryContainer extends DefaultNamedDomainObject
if (!GUtil.isTrue(afterResolverName)) {
throw new InvalidUserDataException("You must specify afterResolverName");
}
+ DeprecationLogger.nagUserOfDiscontinuedMethod("ArtifactRepositoryContainer.addBefore()");
final ArtifactRepository after = getByName(afterResolverName);
return addCustomDependencyResolver(userDescription, configureClosure, new Action<ArtifactRepository>() {
public void execute(ArtifactRepository repository) {
@@ -138,6 +139,7 @@ public class DefaultArtifactRepositoryContainer extends DefaultNamedDomainObject
if (!GUtil.isTrue(beforeResolverName)) {
throw new InvalidUserDataException("You must specify beforeResolverName");
}
+ DeprecationLogger.nagUserOfDiscontinuedMethod("ArtifactRepositoryContainer.addAfter()");
final ArtifactRepository before = getByName(beforeResolverName);
return addCustomDependencyResolver(userDescription, configureClosure, new Action<ArtifactRepository>() {
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/DefaultExcludeRule.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/DefaultExcludeRule.java
index 244f338..249e3bd 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/DefaultExcludeRule.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/DefaultExcludeRule.java
@@ -21,11 +21,6 @@ import org.gradle.util.DeprecationLogger;
import java.util.HashMap;
import java.util.Map;
-/**
- * @author Hans Dockter
- *
- * DefaultExcludeRule is a value object
- */
public class DefaultExcludeRule implements ExcludeRule {
private String group;
private String module;
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/DefaultExcludeRuleContainer.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/DefaultExcludeRuleContainer.java
index ebae94d..3974bb5 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/DefaultExcludeRuleContainer.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/DefaultExcludeRuleContainer.java
@@ -24,9 +24,6 @@ import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
-/**
- * @author Hans Dockter
- */
public class DefaultExcludeRuleContainer implements ExcludeRuleContainer {
private Set<ExcludeRule> addedRules = new LinkedHashSet<ExcludeRule>();
private NotationParser<ExcludeRule> notationParser = new ExcludeRuleNotationParser<ExcludeRule>();
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/DefaultModule.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/DefaultModule.java
index 5190958..a46cea5 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/DefaultModule.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/DefaultModule.java
@@ -17,9 +17,6 @@ package org.gradle.api.internal.artifacts;
import org.gradle.api.artifacts.Module;
-/**
- * @author Hans Dockter
- */
public class DefaultModule implements Module {
private String group;
private String name;
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/DependencyResolutionServices.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/DependencyResolutionServices.java
index 8aa927a..5e6493c 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/DependencyResolutionServices.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/DependencyResolutionServices.java
@@ -17,6 +17,7 @@ package org.gradle.api.internal.artifacts;
import org.gradle.api.artifacts.dsl.ArtifactHandler;
import org.gradle.api.artifacts.dsl.DependencyHandler;
+import org.gradle.api.artifacts.dsl.ComponentMetadataHandler;
import org.gradle.api.artifacts.dsl.RepositoryHandler;
import org.gradle.api.internal.artifacts.configurations.ConfigurationContainerInternal;
@@ -27,6 +28,8 @@ public interface DependencyResolutionServices {
DependencyHandler getDependencyHandler();
+ ComponentMetadataHandler getComponentMetadataHandler();
+
ArtifactHandler getArtifactHandler();
ArtifactPublicationServices createArtifactPublicationServices();
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/DependencyResolveDetailsInternal.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/DependencyResolveDetailsInternal.java
index 15738f2..89c29d2 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/DependencyResolveDetailsInternal.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/DependencyResolveDetailsInternal.java
@@ -19,9 +19,6 @@ package org.gradle.api.internal.artifacts;
import org.gradle.api.artifacts.DependencyResolveDetails;
import org.gradle.api.artifacts.result.ModuleVersionSelectionReason;
-/**
- * by Szczepan Faber, created at: 12/13/12
- */
public interface DependencyResolveDetailsInternal extends DependencyResolveDetails {
void useVersion(String version, ModuleVersionSelectionReason selectionReason);
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/ExcludeRuleNotationParser.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/ExcludeRuleNotationParser.java
index a135639..0110359 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/ExcludeRuleNotationParser.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/ExcludeRuleNotationParser.java
@@ -24,9 +24,6 @@ import org.gradle.api.tasks.Optional;
import java.util.Collection;
-/**
- * @author Rene Groeschke
- */
public class ExcludeRuleNotationParser<T extends ExcludeRule> extends MapNotationParser<T> {
@Override
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/ModuleVersionPublishMetaData.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/ModuleVersionPublishMetaData.java
new file mode 100644
index 0000000..da784fb
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/ModuleVersionPublishMetaData.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts;
+
+import org.apache.ivy.core.module.descriptor.Artifact;
+import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
+import org.gradle.api.artifacts.ModuleVersionIdentifier;
+
+import java.io.File;
+import java.util.Map;
+
+public interface ModuleVersionPublishMetaData {
+ ModuleVersionIdentifier getId();
+
+ ModuleDescriptor getModuleDescriptor();
+
+ Map<Artifact, File> getArtifacts();
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/ModuleVersionPublisher.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/ModuleVersionPublisher.java
new file mode 100644
index 0000000..cb2a955
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/ModuleVersionPublisher.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts;
+
+import org.apache.ivy.core.settings.IvySettings;
+
+import java.io.IOException;
+
+public interface ModuleVersionPublisher {
+ void publish(ModuleVersionPublishMetaData moduleVersion) throws IOException;
+
+ void setSettings(IvySettings settings);
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/ModuleVersionSelectorStrictSpec.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/ModuleVersionSelectorStrictSpec.java
index 91c395e..93f2169 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/ModuleVersionSelectorStrictSpec.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/ModuleVersionSelectorStrictSpec.java
@@ -20,9 +20,6 @@ import org.gradle.api.artifacts.ModuleVersionIdentifier;
import org.gradle.api.artifacts.ModuleVersionSelector;
import org.gradle.api.specs.Spec;
-/**
- * by Szczepan Faber, created at: 9/10/12
- */
public class ModuleVersionSelectorStrictSpec implements Spec<ModuleVersionIdentifier> {
private final ModuleVersionSelector selector;
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/configurations/ConfigurationInternal.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/configurations/ConfigurationInternal.java
index 6beda87..2995f7d 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/configurations/ConfigurationInternal.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/configurations/ConfigurationInternal.java
@@ -22,4 +22,6 @@ public interface ConfigurationInternal extends Configuration, DependencyMetaData
DependencyResolutionListener getDependencyResolutionBroadcast();
ResolutionStrategyInternal getResolutionStrategy();
+
+ String getPath();
}
\ No newline at end of file
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/configurations/DependencyMetaDataProvider.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/configurations/DependencyMetaDataProvider.java
index a5b6ef0..88bc9af 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/configurations/DependencyMetaDataProvider.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/configurations/DependencyMetaDataProvider.java
@@ -17,9 +17,6 @@ package org.gradle.api.internal.artifacts.configurations;
import org.gradle.api.artifacts.Module;
-/**
- * @author Hans Dockter
- */
public interface DependencyMetaDataProvider {
Module getModule();
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dependencies/AbstractDependency.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dependencies/AbstractDependency.java
index 07dfb00..f4d0922 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dependencies/AbstractDependency.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dependencies/AbstractDependency.java
@@ -17,12 +17,9 @@
package org.gradle.api.internal.artifacts.dependencies;
import org.gradle.api.artifacts.Dependency;
-import org.gradle.api.internal.artifacts.ResolvableDependency;
import org.gradle.api.internal.artifacts.DependencyResolveContext;
+import org.gradle.api.internal.artifacts.ResolvableDependency;
-/**
-* @author Hans Dockter
-*/
public abstract class AbstractDependency implements ResolvableDependency, Dependency {
protected void copyTo(AbstractDependency target) {
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dependencies/DefaultClientModule.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dependencies/DefaultClientModule.java
index c0cda2b..3de7134 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dependencies/DefaultClientModule.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dependencies/DefaultClientModule.java
@@ -24,9 +24,6 @@ import org.gradle.api.artifacts.ModuleDependency;
import java.util.HashSet;
import java.util.Set;
-/**
- * @author Hans Dockter
- */
public class DefaultClientModule extends AbstractExternalDependency implements ClientModule {
private String group;
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dependencies/DefaultExternalModuleDependency.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dependencies/DefaultExternalModuleDependency.java
index 9ed7976..4de8446 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dependencies/DefaultExternalModuleDependency.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dependencies/DefaultExternalModuleDependency.java
@@ -20,9 +20,6 @@ import org.gradle.api.InvalidUserDataException;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.artifacts.ExternalModuleDependency;
-/**
- * @author Hans Dockter
- */
public class DefaultExternalModuleDependency extends AbstractExternalDependency implements ExternalModuleDependency {
private String group;
private String name;
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dependencies/DefaultProjectDependency.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dependencies/DefaultProjectDependency.java
index 76f9bde..62c2acd 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dependencies/DefaultProjectDependency.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dependencies/DefaultProjectDependency.java
@@ -31,10 +31,7 @@ import org.gradle.initialization.ProjectAccessListener;
import java.io.File;
import java.util.Set;
-/**
- * @author Hans Dockter
- */
-public class DefaultProjectDependency extends AbstractModuleDependency implements ProjectDependency {
+public class DefaultProjectDependency extends AbstractModuleDependency implements ProjectDependencyInternal {
private ProjectInternal dependencyProject;
private final boolean buildProjectDependencies;
private final TaskDependencyImpl taskDependency = new TaskDependencyImpl();
@@ -89,6 +86,10 @@ public class DefaultProjectDependency extends AbstractModuleDependency implement
return context.resolve().getFiles();
}
+ public void beforeResolved() {
+ projectAccessListener.beforeResolvingProjectDependency(dependencyProject);
+ }
+
@Override
public void resolve(DependencyResolveContext context) {
boolean transitive = isTransitive() && context.isTransitive();
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dependencies/ProjectDependencyInternal.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dependencies/ProjectDependencyInternal.java
new file mode 100644
index 0000000..a1236f3
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dependencies/ProjectDependencyInternal.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.artifacts.dependencies;
+
+import org.gradle.api.artifacts.ProjectDependency;
+
+public interface ProjectDependencyInternal extends ProjectDependency {
+
+ /**
+ * This method is called when the project dependency is resolved
+ */
+ public void beforeResolved();
+
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dsl/DefaultRepositoryHandler.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dsl/DefaultRepositoryHandler.java
index a7058ad..1dde756 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dsl/DefaultRepositoryHandler.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dsl/DefaultRepositoryHandler.java
@@ -36,11 +36,11 @@ import java.util.Map;
import static org.gradle.util.CollectionUtils.flattenToList;
-/**
- * @author Hans Dockter
- */
public class DefaultRepositoryHandler extends DefaultArtifactRepositoryContainer implements RepositoryHandler {
+ public static final String DEFAULT_BINTRAY_JCENTER_REPO_NAME = "BintrayJCenter";
+ public static final String BINTRAY_JCENTER_URL = "http://jcenter.bintray.com/";
+
public static final String FLAT_DIR_DEFAULT_NAME = "flatDir";
private static final String MAVEN_REPO_DEFAULT_NAME = "maven";
private static final String IVY_REPO_DEFAULT_NAME = "ivy";
@@ -72,6 +72,14 @@ public class DefaultRepositoryHandler extends DefaultArtifactRepositoryContainer
return addRepository(repositoryFactory.createMavenCentralRepository(), DEFAULT_MAVEN_CENTRAL_REPO_NAME);
}
+ public MavenArtifactRepository jcenter() {
+ return addRepository(repositoryFactory.createJCenterRepository(), DEFAULT_BINTRAY_JCENTER_REPO_NAME);
+ }
+
+ public MavenArtifactRepository jcenter(Action<? super MavenArtifactRepository> action) {
+ return addRepository(repositoryFactory.createJCenterRepository(), DEFAULT_BINTRAY_JCENTER_REPO_NAME, action);
+ }
+
public MavenArtifactRepository mavenCentral(Map<String, ?> args) {
Map<String, Object> modifiedArgs = new HashMap<String, Object>(args);
if (modifiedArgs.containsKey("urls")) {
@@ -95,14 +103,11 @@ public class DefaultRepositoryHandler extends DefaultArtifactRepositoryContainer
}
public DependencyResolver mavenRepo(Map<String, ?> args, Closure configClosure) {
+ DeprecationLogger.nagUserOfReplacedMethod("RepositoryHandler.mavenRepo()", "maven()");
Map<String, Object> modifiedArgs = new HashMap<String, Object>(args);
if (modifiedArgs.containsKey("urls")) {
List<?> urls = flattenToList(modifiedArgs.remove("urls"));
if (!urls.isEmpty()) {
- DeprecationLogger.nagUserOfDeprecated(
- "The 'urls' property of the RepositoryHandler.mavenRepo() method",
- "You should use the 'url' property to define the core maven repository & the 'artifactUrls' property to define any additional artifact locations"
- );
modifiedArgs.put("url", urls.get(0));
List<?> extraUrls = urls.subList(1, urls.size());
modifiedArgs.put("artifactUrls", extraUrls);
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dsl/dependencies/DefaultDependencyHandler.groovy b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dsl/dependencies/DefaultDependencyHandler.groovy
index 9cb99db..c8b0528 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dsl/dependencies/DefaultDependencyHandler.groovy
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dsl/dependencies/DefaultDependencyHandler.groovy
@@ -19,23 +19,23 @@ package org.gradle.api.internal.artifacts.dsl.dependencies
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.ConfigurationContainer
import org.gradle.api.artifacts.Dependency
+import org.gradle.api.artifacts.dsl.ComponentMetadataHandler
import org.gradle.api.artifacts.dsl.DependencyHandler
import org.gradle.util.ConfigureUtil
import org.gradle.util.GUtil
-/**
- * @author Hans Dockter
- */
class DefaultDependencyHandler implements DependencyHandler {
- ConfigurationContainer configurationContainer
- DependencyFactory dependencyFactory
- ProjectFinder projectFinder
+ private final ConfigurationContainer configurationContainer
+ private final DependencyFactory dependencyFactory
+ private final ProjectFinder projectFinder
+ private final ComponentMetadataHandler metadataHandler
def DefaultDependencyHandler(ConfigurationContainer configurationContainer, DependencyFactory dependencyFactory,
- ProjectFinder projectFinder) {
+ ProjectFinder projectFinder, ComponentMetadataHandler metadataHandler) {
this.configurationContainer = configurationContainer
this.dependencyFactory = dependencyFactory
this.projectFinder = projectFinder
+ this.metadataHandler = metadataHandler
}
public Dependency add(String configurationName, Object dependencyNotation) {
@@ -106,4 +106,13 @@ class DefaultDependencyHandler implements DependencyHandler {
}
return null;
}
+
+ public void components(Closure configureClosure) {
+ ConfigureUtil.configure(configureClosure, getComponents());
+ }
+
+ public ComponentMetadataHandler getComponents() {
+ return metadataHandler;
+ }
+
}
\ No newline at end of file
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dsl/dependencies/DependencyFactory.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dsl/dependencies/DependencyFactory.java
index 890c4ec..b2ba01f 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dsl/dependencies/DependencyFactory.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dsl/dependencies/DependencyFactory.java
@@ -22,9 +22,6 @@ import org.gradle.api.artifacts.ProjectDependency;
import java.util.Map;
-/**
- * @author Hans Dockter
- */
public interface DependencyFactory {
//for gradle distribution specific dependencies
enum ClassPathNotation {
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dsl/dependencies/ModuleDescriptorDelegate.groovy b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dsl/dependencies/ModuleDescriptorDelegate.groovy
index 4ea3563..513ebb8 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dsl/dependencies/ModuleDescriptorDelegate.groovy
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dsl/dependencies/ModuleDescriptorDelegate.groovy
@@ -19,9 +19,6 @@ package org.gradle.api.internal.artifacts.dsl.dependencies
import org.gradle.api.artifacts.ClientModule
import org.gradle.util.ConfigureUtil
-/**
- * @author Hans Dockter
- */
class ModuleFactoryDelegate {
ClientModule clientModule
DependencyFactory dependencyFactory
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dsl/dependencies/ModuleFactoryHelper.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dsl/dependencies/ModuleFactoryHelper.java
index f9ce356..1946e14 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dsl/dependencies/ModuleFactoryHelper.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dsl/dependencies/ModuleFactoryHelper.java
@@ -15,13 +15,10 @@
*/
package org.gradle.api.internal.artifacts.dsl.dependencies;
-import org.gradle.api.artifacts.ExternalDependency;
import org.gradle.api.artifacts.DependencyArtifact;
+import org.gradle.api.artifacts.ExternalDependency;
import org.gradle.api.internal.artifacts.dependencies.DefaultDependencyArtifact;
-/**
- * @author Hans Dockter
- */
public class ModuleFactoryHelper {
public static void addExplicitArtifactsIfDefined(ExternalDependency moduleDependency, String artifactType, String classifier) {
String actualArtifactType = artifactType;
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dsl/dependencies/ProjectFinder.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dsl/dependencies/ProjectFinder.java
index 12f736c..440b513 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dsl/dependencies/ProjectFinder.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/dsl/dependencies/ProjectFinder.java
@@ -17,9 +17,6 @@ package org.gradle.api.internal.artifacts.dsl.dependencies;
import org.gradle.api.internal.project.ProjectInternal;
-/**
- * @author Hans Dockter
-*/
public interface ProjectFinder {
/**
*
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ModuleDescriptorConverter.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ModuleDescriptorConverter.java
deleted file mode 100644
index 4b4a995..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/ivyservice/ModuleDescriptorConverter.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2007-2008 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.artifacts.ivyservice;
-
-import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor;
-import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
-import org.gradle.api.artifacts.Configuration;
-import org.gradle.api.artifacts.Module;
-import org.gradle.api.artifacts.ModuleDependency;
-
-import java.util.Set;
-
-/**
- * @author Hans Dockter
- */
-public interface ModuleDescriptorConverter {
- ModuleDescriptor convert(Set<? extends Configuration> configurations, Module module);
-
- ModuleDescriptor createModuleDescriptor(Module module);
-
- void addDependencyDescriptor(String configuration, DefaultModuleDescriptor moduleDescriptor, ModuleDependency dependency);
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/publish/AbstractPublishArtifact.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/publish/AbstractPublishArtifact.java
index abdc592..46e8df8 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/publish/AbstractPublishArtifact.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/publish/AbstractPublishArtifact.java
@@ -19,9 +19,6 @@ import org.gradle.api.artifacts.PublishArtifact;
import org.gradle.api.internal.tasks.DefaultTaskDependency;
import org.gradle.api.tasks.TaskDependency;
-/**
- * @author Hans Dockter
- */
public abstract class AbstractPublishArtifact implements PublishArtifact {
private final DefaultTaskDependency taskDependency;
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/publish/ArchivePublishArtifact.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/publish/ArchivePublishArtifact.java
index eb4fa9a..aef35f5 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/publish/ArchivePublishArtifact.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/publish/ArchivePublishArtifact.java
@@ -21,9 +21,6 @@ import org.gradle.util.GUtil;
import java.io.File;
import java.util.Date;
-/**
- * @author Hans Dockter
- */
public class ArchivePublishArtifact extends AbstractPublishArtifact {
private String name;
private String extension;
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/publish/DefaultPublishArtifact.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/publish/DefaultPublishArtifact.java
index 8591a4c..092bd3e 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/publish/DefaultPublishArtifact.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/publish/DefaultPublishArtifact.java
@@ -21,9 +21,6 @@ import org.gradle.api.artifacts.ConfigurablePublishArtifact;
import java.io.File;
import java.util.Date;
-/**
- * @author Hans Dockter
- */
public class DefaultPublishArtifact extends AbstractPublishArtifact implements ConfigurablePublishArtifact {
private String name;
private String extension;
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/repositories/PublicationAwareRepository.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/repositories/PublicationAwareRepository.java
index 9c493a5..4bed715 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/repositories/PublicationAwareRepository.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/repositories/PublicationAwareRepository.java
@@ -16,8 +16,8 @@
package org.gradle.api.internal.artifacts.repositories;
-import org.apache.ivy.plugins.resolver.DependencyResolver;
+import org.gradle.api.internal.artifacts.ModuleVersionPublisher;
public interface PublicationAwareRepository {
- DependencyResolver createPublisher();
+ ModuleVersionPublisher createPublisher();
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/version/LatestVersionSemanticComparator.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/version/LatestVersionSemanticComparator.java
deleted file mode 100644
index 2ea8205..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/version/LatestVersionSemanticComparator.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.artifacts.version;
-
-import org.apache.ivy.plugins.latest.ArtifactInfo;
-import org.apache.ivy.plugins.latest.LatestRevisionStrategy;
-
-import java.util.Comparator;
-
-/**
- * by Szczepan Faber, created at: 10/9/12
- */
-public class LatestVersionSemanticComparator implements Comparator<String> {
-
- public int compare(String left, String right) {
- return new LatestRevisionStrategy().getComparator().compare(new SimpleArtifactInfo(left), new SimpleArtifactInfo(right));
- }
-
- private static class SimpleArtifactInfo implements ArtifactInfo {
-
- private final String version;
-
- public SimpleArtifactInfo(String version) {
- this.version = version;
- }
-
- public String getRevision() {
- return version;
- }
-
- public long getLastModified() {
- throw new UnsupportedOperationException();
- }
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/cache/BinaryStore.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/cache/BinaryStore.java
new file mode 100644
index 0000000..fe3ca3d
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/cache/BinaryStore.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.cache;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public interface BinaryStore {
+ void write(WriteAction write);
+ //done writing data, release any resources
+ BinaryData done();
+
+ public static interface WriteAction {
+ void write(DataOutputStream output) throws IOException;
+ }
+
+ public static interface ReadAction<T> {
+ T read(DataInputStream input) throws IOException;
+ }
+
+ public static interface BinaryData {
+ <T> T read(ReadAction<T> readAction);
+ //done reading data, release any resources
+ void done();
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/cache/Store.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/cache/Store.java
new file mode 100644
index 0000000..ddd0a5e
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/cache/Store.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.cache;
+
+import org.gradle.internal.Factory;
+
+public interface Store<T> {
+ T load(Factory<T> createIfNotPresent);
+}
\ No newline at end of file
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/CacheBackedFileSnapshotRepository.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/CacheBackedFileSnapshotRepository.java
deleted file mode 100644
index a93221e..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/CacheBackedFileSnapshotRepository.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.changedetection;
-
-import org.gradle.cache.PersistentIndexedCache;
-
-public class CacheBackedFileSnapshotRepository implements FileSnapshotRepository {
- private final PersistentIndexedCache<Object, Object> cache;
-
- public CacheBackedFileSnapshotRepository(TaskArtifactStateCacheAccess cacheAccess) {
- cache = cacheAccess.createCache("fileSnapshots", Object.class, Object.class);
- }
-
- public Long add(FileCollectionSnapshot snapshot) {
- Long id = (Long) cache.get("nextId");
- if (id == null) {
- id = 1L;
- }
- cache.put("nextId", id + 1);
- cache.put(id, snapshot);
- return id;
- }
-
- public FileCollectionSnapshot get(Long id) {
- return (FileCollectionSnapshot) cache.get(id);
- }
-
- public void remove(Long id) {
- cache.remove(id);
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/CacheBackedTaskHistoryRepository.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/CacheBackedTaskHistoryRepository.java
deleted file mode 100644
index ac68218..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/CacheBackedTaskHistoryRepository.java
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.changedetection;
-
-import org.gradle.internal.Factory;
-import org.gradle.api.internal.TaskInternal;
-import org.gradle.messaging.serialize.DefaultSerializer;
-import org.gradle.cache.PersistentIndexedCache;
-
-import java.io.File;
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-public class CacheBackedTaskHistoryRepository implements TaskHistoryRepository {
- private final TaskArtifactStateCacheAccess cacheAccess;
- private final FileSnapshotRepository snapshotRepository;
- private final PersistentIndexedCache<String, TaskHistory> taskHistoryCache;
- private final DefaultSerializer<TaskHistory> serializer = new DefaultSerializer<TaskHistory>();
-
- public CacheBackedTaskHistoryRepository(TaskArtifactStateCacheAccess cacheAccess, FileSnapshotRepository snapshotRepository) {
- this.cacheAccess = cacheAccess;
- this.snapshotRepository = snapshotRepository;
- taskHistoryCache = cacheAccess.createCache("taskArtifacts", String.class, TaskHistory.class, serializer);
- }
-
- public History getHistory(final TaskInternal task) {
- final TaskHistory history = loadHistory(task);
- final LazyTaskExecution currentExecution = new LazyTaskExecution();
- currentExecution.snapshotRepository = snapshotRepository;
- currentExecution.cacheAccess = cacheAccess;
- currentExecution.setOutputFiles(outputFiles(task));
- final LazyTaskExecution previousExecution = findPreviousExecution(currentExecution, history);
- if (previousExecution != null) {
- previousExecution.snapshotRepository = snapshotRepository;
- previousExecution.cacheAccess = cacheAccess;
- }
- history.configurations.add(0, currentExecution);
-
- return new History() {
- public TaskExecution getPreviousExecution() {
- return previousExecution;
- }
-
- public TaskExecution getCurrentExecution() {
- return currentExecution;
- }
-
- public void update() {
- if (currentExecution.inputFilesSnapshotId == null && currentExecution.inputFilesSnapshot != null) {
- currentExecution.inputFilesSnapshotId = snapshotRepository.add(currentExecution.inputFilesSnapshot);
- }
- if (currentExecution.outputFilesSnapshotId == null && currentExecution.outputFilesSnapshot != null) {
- currentExecution.outputFilesSnapshotId = snapshotRepository.add(currentExecution.outputFilesSnapshot);
- }
- while (history.configurations.size() > TaskHistory.MAX_HISTORY_ENTRIES) {
- LazyTaskExecution execution = history.configurations.remove(history.configurations.size() - 1);
- if (execution.inputFilesSnapshotId != null) {
- snapshotRepository.remove(execution.inputFilesSnapshotId);
- }
- if (execution.outputFilesSnapshotId != null) {
- snapshotRepository.remove(execution.outputFilesSnapshotId);
- }
- }
- taskHistoryCache.put(task.getPath(), history);
- }
- };
- }
-
- private TaskHistory loadHistory(TaskInternal task) {
- ClassLoader original = serializer.getClassLoader();
- serializer.setClassLoader(task.getClass().getClassLoader());
- try {
- TaskHistory history = taskHistoryCache.get(task.getPath());
- return history == null ? new TaskHistory() : history;
- } finally {
- serializer.setClassLoader(original);
- }
- }
-
- private static Set<String> outputFiles(TaskInternal task) {
- Set<String> outputFiles = new HashSet<String>();
- for (File file : task.getOutputs().getFiles()) {
- outputFiles.add(file.getAbsolutePath());
- }
- return outputFiles;
- }
-
- private LazyTaskExecution findPreviousExecution(TaskExecution currentExecution, TaskHistory history) {
- Set<String> outputFiles = currentExecution.getOutputFiles();
- LazyTaskExecution bestMatch = null;
- int bestMatchOverlap = 0;
- for (LazyTaskExecution configuration : history.configurations) {
- if (outputFiles.size() == 0) {
- if (configuration.getOutputFiles().size() == 0) {
- bestMatch = configuration;
- break;
- }
- }
-
- Set<String> intersection = new HashSet<String>(outputFiles);
- intersection.retainAll(configuration.getOutputFiles());
- if (intersection.size() > bestMatchOverlap) {
- bestMatch = configuration;
- bestMatchOverlap = intersection.size();
- }
- if (bestMatchOverlap == outputFiles.size()) {
- break;
- }
- }
- return bestMatch;
- }
-
- private static class TaskHistory implements Serializable {
- private static final int MAX_HISTORY_ENTRIES = 3;
- private final List<LazyTaskExecution> configurations = new ArrayList<LazyTaskExecution>();
- }
-
- private static class LazyTaskExecution extends TaskExecution {
- private Long inputFilesSnapshotId;
- private Long outputFilesSnapshotId;
- private transient FileSnapshotRepository snapshotRepository;
- private transient FileCollectionSnapshot inputFilesSnapshot;
- private transient FileCollectionSnapshot outputFilesSnapshot;
- private transient TaskArtifactStateCacheAccess cacheAccess;
-
- @Override
- public FileCollectionSnapshot getInputFilesSnapshot() {
- if (inputFilesSnapshot == null) {
- inputFilesSnapshot = snapshotRepository.get(inputFilesSnapshotId);
- }
- return inputFilesSnapshot;
- }
-
- @Override
- public void setInputFilesSnapshot(FileCollectionSnapshot inputFilesSnapshot) {
- this.inputFilesSnapshot = inputFilesSnapshot;
- this.inputFilesSnapshotId = null;
- }
-
- @Override
- public FileCollectionSnapshot getOutputFilesSnapshot() {
- if (outputFilesSnapshot == null) {
- outputFilesSnapshot = cacheAccess.useCache("fetch output files", new Factory<FileCollectionSnapshot>() {
- public FileCollectionSnapshot create() {
- return snapshotRepository.get(outputFilesSnapshotId);
- }
- });
- }
- return outputFilesSnapshot;
- }
-
- @Override
- public void setOutputFilesSnapshot(FileCollectionSnapshot outputFilesSnapshot) {
- this.outputFilesSnapshot = outputFilesSnapshot;
- outputFilesSnapshotId = null;
- }
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/CacheLockHandlingTaskExecuter.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/CacheLockHandlingTaskExecuter.java
deleted file mode 100644
index 9663558..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/CacheLockHandlingTaskExecuter.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.changedetection;
-
-import org.gradle.api.internal.TaskInternal;
-import org.gradle.api.internal.tasks.TaskExecuter;
-import org.gradle.api.internal.tasks.TaskStateInternal;
-
-public class CacheLockHandlingTaskExecuter implements TaskExecuter {
- private final TaskExecuter executer;
- private final TaskArtifactStateCacheAccess cacheAccess;
-
- public CacheLockHandlingTaskExecuter(TaskExecuter executer, TaskArtifactStateCacheAccess cacheAccess) {
- this.executer = executer;
- this.cacheAccess = cacheAccess;
- }
-
- public void execute(final TaskInternal task, final TaskStateInternal state) {
- cacheAccess.longRunningOperation(String.format("execute %s", task), new Runnable() {
- public void run() {
- executer.execute(task, state);
- }
- });
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/CachingHasher.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/CachingHasher.java
deleted file mode 100644
index f779d8d..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/CachingHasher.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.changedetection;
-
-import org.gradle.cache.PersistentIndexedCache;
-import org.gradle.messaging.serialize.DataStreamBackedSerializer;
-
-import java.io.*;
-
-public class CachingHasher implements Hasher {
- private final PersistentIndexedCache<File, FileInfo> cache;
- private final Hasher hasher;
- private long timestamp;
-
- public CachingHasher(Hasher hasher, TaskArtifactStateCacheAccess cacheAccess) {
- this.hasher = hasher;
- cache = cacheAccess.createCache("fileHashes", File.class, FileInfo.class, new FileInfoSerializer());
- }
-
- public byte[] hash(File file) {
- FileInfo info = cache.get(file);
-
- long length = file.length();
- timestamp = file.lastModified();
- if (info != null && length == info.length && timestamp == info.timestamp) {
- return info.hash;
- }
-
- byte[] hash = hasher.hash(file);
- cache.put(file, new FileInfo(hash, length, timestamp));
- return hash;
- }
-
- public static class FileInfo implements Serializable {
- private final byte[] hash;
- private final long timestamp;
- private final long length;
-
- public FileInfo(byte[] hash, long length, long timestamp) {
- this.hash = hash;
- this.length = length;
- this.timestamp = timestamp;
- }
- }
-
- private static class FileInfoSerializer extends DataStreamBackedSerializer<FileInfo> {
- @Override
- public FileInfo read(DataInput input) throws IOException {
- int hashLength = input.readInt();
- byte[] hash = new byte[hashLength];
- input.readFully(hash);
- long timestamp = input.readLong();
- long length = input.readLong();
- return new FileInfo(hash, length, timestamp);
- }
-
- @Override
- public void write(DataOutput output, FileInfo value) throws IOException {
- output.writeInt(value.hash.length);
- output.write(value.hash);
- output.writeLong(value.timestamp);
- output.writeLong(value.length);
- }
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/CompositeUpToDateRule.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/CompositeUpToDateRule.java
deleted file mode 100644
index d739b3b..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/CompositeUpToDateRule.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.changedetection;
-
-import org.gradle.api.internal.TaskInternal;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-
-public class CompositeUpToDateRule implements UpToDateRule {
- private final List<UpToDateRule> rules;
-
- public CompositeUpToDateRule(UpToDateRule... rules) {
- this.rules = new ArrayList<UpToDateRule>(Arrays.asList(rules));
- }
-
- public TaskUpToDateState create(TaskInternal task, TaskExecution previousExecution, TaskExecution currentExecution) {
- final List<TaskUpToDateState> states = new ArrayList<TaskUpToDateState>();
- for (UpToDateRule rule : rules) {
- states.add(rule.create(task, previousExecution, currentExecution));
- }
- return new TaskUpToDateState() {
- public void checkUpToDate(Collection<String> messages) {
- for (int i = 0; messages.isEmpty() && i < states.size(); i++) {
- TaskUpToDateState state = states.get(i);
- state.checkUpToDate(messages);
- }
- }
-
- public void snapshotAfterTask() {
- for (TaskUpToDateState state : states) {
- state.snapshotAfterTask();
- }
- }
- };
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/DefaultFileCacheListener.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/DefaultFileCacheListener.java
deleted file mode 100644
index 50038d2..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/DefaultFileCacheListener.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.changedetection;
-
-import org.gradle.api.file.FileCollection;
-import org.gradle.api.internal.file.collections.DefaultFileCollectionResolveContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.List;
-
-public class DefaultFileCacheListener implements FileCacheListener {
- private static final Logger LOGGER = LoggerFactory.getLogger(DefaultFileCacheListener.class);
-
- public void cacheable(FileCollection files) {
- List<FileCollection> collections = new DefaultFileCollectionResolveContext().add(files).resolveAsFileCollections();
- for (FileCollection collection : collections) {
- LOGGER.debug("Can cache files for {}", collection);
- }
- }
-
- public void invalidate(FileCollection files) {
- List<FileCollection> collections = new DefaultFileCollectionResolveContext().add(files).resolveAsFileCollections();
- for (FileCollection collection : collections) {
- LOGGER.debug("Invalidate cached files for {}", collection);
- }
- }
-
- public void invalidateAll() {
- LOGGER.debug("Invalidate all cached files");
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/DefaultFileSnapshotter.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/DefaultFileSnapshotter.java
deleted file mode 100755
index abd727b..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/DefaultFileSnapshotter.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.changedetection;
-
-import org.gradle.api.file.FileCollection;
-import org.gradle.api.internal.file.collections.SimpleFileCollection;
-import org.gradle.util.ChangeListener;
-import org.gradle.util.NoOpChangeListener;
-
-import java.io.File;
-import java.io.Serializable;
-import java.math.BigInteger;
-import java.util.*;
-
-public class DefaultFileSnapshotter implements FileSnapshotter {
- private final Hasher hasher;
-
- public DefaultFileSnapshotter(Hasher hasher) {
- this.hasher = hasher;
- }
-
- public FileCollectionSnapshot emptySnapshot() {
- return new FileCollectionSnapshotImpl(new HashMap<String, FileSnapshot>());
- }
-
- public FileCollectionSnapshot snapshot(FileCollection sourceFiles) {
- Map<String, FileSnapshot> snapshots = new HashMap<String, FileSnapshot>();
- for (File file : sourceFiles.getAsFileTree()) {
- if (file.isFile()) {
- snapshots.put(file.getAbsolutePath(), new FileHashSnapshot(hasher.hash(file)));
- } else if (file.isDirectory()) {
- snapshots.put(file.getAbsolutePath(), new DirSnapshot());
- } else {
- snapshots.put(file.getAbsolutePath(), new MissingFileSnapshot());
- }
- }
- return new FileCollectionSnapshotImpl(snapshots);
- }
-
- private interface FileSnapshot extends Serializable {
- boolean isUpToDate(FileSnapshot snapshot);
- }
-
- private static class FileHashSnapshot implements FileSnapshot {
- private final byte[] hash;
-
- public FileHashSnapshot(byte[] hash) {
- this.hash = hash;
- }
-
- public boolean isUpToDate(FileSnapshot snapshot) {
- if (!(snapshot instanceof FileHashSnapshot)) {
- return false;
- }
-
- FileHashSnapshot other = (FileHashSnapshot) snapshot;
- return Arrays.equals(hash, other.hash);
- }
-
- @Override
- public String toString() {
- return new BigInteger(1, hash).toString(16);
- }
- }
-
- private static class DirSnapshot implements FileSnapshot {
- public boolean isUpToDate(FileSnapshot snapshot) {
- return snapshot instanceof DirSnapshot;
- }
- }
-
- private static class MissingFileSnapshot implements FileSnapshot {
- public boolean isUpToDate(FileSnapshot snapshot) {
- return snapshot instanceof MissingFileSnapshot;
- }
- }
-
- private static class FileCollectionSnapshotImpl implements FileCollectionSnapshot {
- private final Map<String, FileSnapshot> snapshots;
-
- public FileCollectionSnapshotImpl(Map<String, FileSnapshot> snapshots) {
- this.snapshots = snapshots;
- }
-
- public FileCollection getFiles() {
- List<File> files = new ArrayList<File>();
- for (Map.Entry<String, FileSnapshot> entry : snapshots.entrySet()) {
- if (entry.getValue() instanceof FileHashSnapshot) {
- files.add(new File(entry.getKey()));
- }
- }
- return new SimpleFileCollection(files);
- }
-
- public void changesSince(FileCollectionSnapshot oldSnapshot, final ChangeListener<File> listener) {
- FileCollectionSnapshotImpl other = (FileCollectionSnapshotImpl) oldSnapshot;
- diff(snapshots, other.snapshots, new ChangeListener<Map.Entry<String, FileSnapshot>>() {
- public void added(Map.Entry<String, FileSnapshot> element) {
- listener.added(new File(element.getKey()));
- }
-
- public void removed(Map.Entry<String, FileSnapshot> element) {
- listener.removed(new File(element.getKey()));
- }
-
- public void changed(Map.Entry<String, FileSnapshot> element) {
- listener.changed(new File(element.getKey()));
- }
- });
- }
-
- private void diff(Map<String, FileSnapshot> snapshots, Map<String, FileSnapshot> oldSnapshots,
- ChangeListener<Map.Entry<String, FileSnapshot>> listener) {
- Map<String, FileSnapshot> otherSnapshots = new HashMap<String, FileSnapshot>(oldSnapshots);
- for (Map.Entry<String, FileSnapshot> entry : snapshots.entrySet()) {
- FileSnapshot otherFile = otherSnapshots.remove(entry.getKey());
- if (otherFile == null) {
- listener.added(entry);
- } else if (!entry.getValue().isUpToDate(otherFile)) {
- listener.changed(entry);
- }
- }
- for (Map.Entry<String, FileSnapshot> entry : otherSnapshots.entrySet()) {
- listener.removed(entry);
- }
- }
-
- public Diff changesSince(final FileCollectionSnapshot oldSnapshot) {
- final FileCollectionSnapshotImpl other = (FileCollectionSnapshotImpl) oldSnapshot;
- return new Diff() {
- public FileCollectionSnapshot applyTo(FileCollectionSnapshot snapshot) {
- return applyTo(snapshot, new NoOpChangeListener<Merge>());
- }
-
- public FileCollectionSnapshot applyTo(FileCollectionSnapshot snapshot, final ChangeListener<Merge> listener) {
- FileCollectionSnapshotImpl target = (FileCollectionSnapshotImpl) snapshot;
- final Map<String, FileSnapshot> newSnapshots = new HashMap<String, FileSnapshot>(target.snapshots);
- diff(snapshots, other.snapshots, new MapMergeChangeListener<String, FileSnapshot>(listener, newSnapshots));
- return new FileCollectionSnapshotImpl(newSnapshots);
- }
- };
- }
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/DefaultHasher.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/DefaultHasher.java
deleted file mode 100644
index 23bfc30..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/DefaultHasher.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.changedetection;
-
-import org.gradle.util.hash.HashUtil;
-
-import java.io.File;
-
-public class DefaultHasher implements Hasher {
- public byte[] hash(File file) {
- return HashUtil.createHash(file, "MD5").asByteArray();
- }
-}
\ No newline at end of file
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/DefaultTaskArtifactStateCacheAccess.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/DefaultTaskArtifactStateCacheAccess.java
deleted file mode 100644
index 310b159..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/DefaultTaskArtifactStateCacheAccess.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.changedetection;
-
-import org.gradle.internal.Factory;
-import org.gradle.api.invocation.Gradle;
-import org.gradle.cache.CacheRepository;
-import org.gradle.cache.PersistentCache;
-import org.gradle.cache.PersistentIndexedCache;
-import org.gradle.messaging.serialize.Serializer;
-import org.gradle.cache.internal.FileLockManager;
-import org.gradle.listener.LazyCreationProxy;
-
-import java.io.File;
-
-public class DefaultTaskArtifactStateCacheAccess implements TaskArtifactStateCacheAccess {
- private final Gradle gradle;
- private final CacheRepository cacheRepository;
- private PersistentCache cache;
-
- public DefaultTaskArtifactStateCacheAccess(Gradle gradle, CacheRepository cacheRepository) {
- this.gradle = gradle;
- this.cacheRepository = cacheRepository;
- }
-
- private PersistentCache getCache() {
- if (cache == null) {
- cache = cacheRepository
- .cache("taskArtifacts")
- .forObject(gradle)
- .withDisplayName("task artifact state cache")
- .withLockMode(FileLockManager.LockMode.Exclusive)
- .open();
- }
- return cache;
- }
-
- public <K, V> PersistentIndexedCache<K, V> createCache(final String cacheName, final Class<K> keyType, final Class<V> valueType) {
- Factory<PersistentIndexedCache> factory = new Factory<PersistentIndexedCache>() {
- public PersistentIndexedCache create() {
- return getCache().createCache(cacheFile(cacheName), keyType, valueType);
- }
- };
- return new LazyCreationProxy<PersistentIndexedCache>(PersistentIndexedCache.class, factory).getSource();
- }
-
- public <K, V> PersistentIndexedCache<K, V> createCache(final String cacheName, final Class<K> keyType, final Class<V> valueType, final Serializer<V> valueSerializer) {
- Factory<PersistentIndexedCache> factory = new Factory<PersistentIndexedCache>() {
- public PersistentIndexedCache create() {
- return getCache().createCache(cacheFile(cacheName), keyType, valueSerializer);
- }
- };
- return new LazyCreationProxy<PersistentIndexedCache>(PersistentIndexedCache.class, factory).getSource();
-
- }
-
- private File cacheFile(String cacheName) {
- return new File(getCache().getBaseDir(), cacheName + ".bin");
- }
-
- public <T> T useCache(String operationDisplayName, Factory<? extends T> action) {
- return getCache().useCache(operationDisplayName, action);
- }
-
- public void useCache(String operationDisplayName, Runnable action) {
- getCache().useCache(operationDisplayName, action);
- }
-
- public void longRunningOperation(String operationDisplayName, Runnable action) {
- getCache().longRunningOperation(operationDisplayName, action);
- }
-}
\ No newline at end of file
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/DefaultTaskArtifactStateRepository.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/DefaultTaskArtifactStateRepository.java
deleted file mode 100644
index 458fb87..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/DefaultTaskArtifactStateRepository.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.changedetection;
-
-import org.gradle.api.file.FileCollection;
-import org.gradle.api.internal.TaskExecutionHistory;
-import org.gradle.api.internal.TaskInternal;
-import org.gradle.api.internal.file.collections.SimpleFileCollection;
-import org.gradle.api.logging.Logger;
-import org.gradle.api.logging.Logging;
-
-import java.util.ArrayList;
-import java.util.Formatter;
-import java.util.List;
-
-import static java.util.Collections.singletonList;
-
-public class DefaultTaskArtifactStateRepository implements TaskArtifactStateRepository {
- private static final int MAX_OUT_OF_DATE_MESSAGES = 10;
- private static final Logger LOGGER = Logging.getLogger(DefaultTaskArtifactStateRepository.class);
- private final TaskHistoryRepository taskHistoryRepository;
- private final UpToDateRule upToDateRule;
-
- public DefaultTaskArtifactStateRepository(TaskHistoryRepository taskHistoryRepository, FileSnapshotter inputFilesSnapshotter, FileSnapshotter outputFilesSnapshotter) {
- this.taskHistoryRepository = taskHistoryRepository;
- upToDateRule = new CompositeUpToDateRule(
- new TaskTypeChangedUpToDateRule(),
- new InputPropertiesChangedUpToDateRule(),
- new OutputFilesChangedUpToDateRule(outputFilesSnapshotter),
- new InputFilesChangedUpToDateRule(inputFilesSnapshotter));
- }
-
- public TaskArtifactState getStateFor(final TaskInternal task) {
- return new TaskArtifactStateImpl(task, taskHistoryRepository.getHistory(task));
- }
-
- private interface TaskExecutionState {
- List<String> isUpToDate();
-
- boolean snapshot();
-
- FileCollection getPreviousOutputFiles();
- }
-
- private static class HistoricExecution implements TaskExecutionState {
- private final TaskInternal task;
- private final TaskExecution lastExecution;
- private boolean upToDate;
- private final UpToDateRule rule;
- private TaskExecution thisExecution;
- private UpToDateRule.TaskUpToDateState upToDateState;
-
- public HistoricExecution(TaskInternal task, TaskHistoryRepository.History history, UpToDateRule rule) {
- this.task = task;
- this.lastExecution = history.getPreviousExecution();
- this.thisExecution = history.getCurrentExecution();
- this.rule = rule;
- }
-
- private void calcCurrentState() {
- if (upToDateState != null) {
- return;
- }
-
- // Calculate initial state - note this is potentially expensive
- upToDateState = rule.create(task, lastExecution, thisExecution);
- }
-
- public FileCollection getPreviousOutputFiles() {
- return lastExecution != null && lastExecution.getOutputFilesSnapshot() != null ? lastExecution.getOutputFilesSnapshot().getFiles() : new SimpleFileCollection();
- }
-
- public List<String> isUpToDate() {
- calcCurrentState();
-
- // Now determine if we're out of date
- if (lastExecution == null) {
- return singletonList(String.format("No history is available for %s.", task));
- }
-
- List<String> messages = new ArrayList<String>();
- upToDateState.checkUpToDate(messages);
-
- if (messages.isEmpty()) {
- upToDate = true;
- }
- return messages;
- }
-
- public boolean snapshot() {
- calcCurrentState();
-
- if (upToDate) {
- return false;
- }
-
- upToDateState.snapshotAfterTask();
- return true;
- }
- }
-
- private class TaskArtifactStateImpl implements TaskArtifactState, TaskExecutionHistory {
- private final TaskInternal task;
- private final TaskHistoryRepository.History history;
- private final TaskExecutionState execution;
-
- public TaskArtifactStateImpl(TaskInternal task, TaskHistoryRepository.History history) {
- this.task = task;
- this.history = history;
- execution = getExecution();
- }
-
- public boolean isUpToDate() {
- List<String> messages = execution.isUpToDate();
- if (messages == null || messages.isEmpty()) {
- LOGGER.info("Skipping {} as it is up-to-date.", task);
- return true;
- }
- if (LOGGER.isInfoEnabled()) {
- Formatter formatter = new Formatter();
- formatter.format("Executing %s due to:", task);
- for (int i = 0; i < messages.size() && i < MAX_OUT_OF_DATE_MESSAGES; i++) {
- String message = messages.get(i);
- formatter.format("%n%s", message);
- }
- if (messages.size() > MAX_OUT_OF_DATE_MESSAGES) {
- formatter.format("%n%d more ...", messages.size() - MAX_OUT_OF_DATE_MESSAGES);
- }
- LOGGER.info(formatter.toString());
- }
- return false;
- }
-
- public FileCollection getOutputFiles() {
- return execution.getPreviousOutputFiles();
- }
-
- public TaskExecutionHistory getExecutionHistory() {
- return this;
- }
-
- public TaskExecutionState getExecution() {
- return new HistoricExecution(task, history, upToDateRule);
- }
-
- public void afterTask() {
- if (execution.snapshot()) {
- history.update();
- }
- }
-
- public void beforeTask() {
- }
-
- public void finished() {
- }
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/FileCacheBroadcastTaskArtifactStateRepository.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/FileCacheBroadcastTaskArtifactStateRepository.java
deleted file mode 100644
index c23ccad..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/FileCacheBroadcastTaskArtifactStateRepository.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.changedetection;
-
-import org.gradle.api.internal.TaskExecutionHistory;
-import org.gradle.api.internal.TaskInternal;
-
-public class FileCacheBroadcastTaskArtifactStateRepository implements TaskArtifactStateRepository {
- private final TaskArtifactStateRepository repository;
- private final FileCacheListener listener;
-
- public FileCacheBroadcastTaskArtifactStateRepository(TaskArtifactStateRepository repository, FileCacheListener listener) {
- this.repository = repository;
- this.listener = listener;
- }
-
- public TaskArtifactState getStateFor(final TaskInternal task) {
- final TaskArtifactState state = repository.getStateFor(task);
- return new TaskArtifactState() {
- public boolean isUpToDate() {
- listener.cacheable(task.getInputs().getFiles());
- listener.cacheable(task.getOutputs().getFiles());
-
- return state.isUpToDate();
- }
-
- public void beforeTask() {
- if (task.getOutputs().getHasOutput()) {
- listener.invalidate(task.getOutputs().getFiles());
- } else {
- listener.invalidateAll();
- }
- state.beforeTask();
- }
-
- public void afterTask() {
- listener.cacheable(task.getOutputs().getFiles());
- state.afterTask();
- }
-
- public void finished() {
- state.finished();
- }
-
- public TaskExecutionHistory getExecutionHistory() {
- return state.getExecutionHistory();
- }
- };
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/FileCacheListener.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/FileCacheListener.java
deleted file mode 100644
index 1906d55..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/FileCacheListener.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.changedetection;
-
-import org.gradle.api.file.FileCollection;
-
-public interface FileCacheListener {
- /**
- * Indicates that the given files are cacheable, and are not expected to change until invalidated.
- */
- void cacheable(FileCollection files);
-
- /**
- * Indicates that the given files may have changed, and should no longer be considered cacheable.
- */
- void invalidate(FileCollection files);
-
- /**
- * Indicates that any file may have changed, and should no longer be considered cacheable.
- */
- void invalidateAll();
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/FileCollectionSnapshot.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/FileCollectionSnapshot.java
deleted file mode 100755
index b3f0cac..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/FileCollectionSnapshot.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.changedetection;
-
-import org.gradle.api.file.FileCollection;
-import org.gradle.util.ChangeListener;
-
-import java.io.File;
-import java.io.Serializable;
-
-/**
- * An immutable snapshot of the contents of a collection of files.
- */
-public interface FileCollectionSnapshot extends Serializable {
- void changesSince(FileCollectionSnapshot oldSnapshot, ChangeListener<File> listener);
-
- Diff changesSince(FileCollectionSnapshot oldSnapshot);
-
- FileCollection getFiles();
-
- public interface Diff {
- /**
- * Applies this diff to the given snapshot. Adds any added or changed files in this diff to the given snapshot.
- * Removes any removed files in this diff from the given snapshot.
- *
- * @param snapshot the snapshot to apply the changes to.
- * @param listener the listener to notify of changes. The listener can veto a particular change.
- * @return an updated copy of the provided snapshot
- */
- FileCollectionSnapshot applyTo(FileCollectionSnapshot snapshot, ChangeListener<Merge> listener);
-
- /**
- * Applies this diff to the given snapshot. Adds any added or changed files in this diff to the given snapshot.
- * Removes any removed files in this diff from the given snapshot.
- *
- * @param snapshot the snapshot to apply the changes to.
- * @return an updated copy of the provided snapshot
- */
- FileCollectionSnapshot applyTo(FileCollectionSnapshot snapshot);
- }
-
- public interface Merge {
- void ignore();
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/FileSnapshotRepository.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/FileSnapshotRepository.java
deleted file mode 100644
index b83e755..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/FileSnapshotRepository.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.changedetection;
-
-public interface FileSnapshotRepository {
- FileCollectionSnapshot get(Long id);
-
- Long add(FileCollectionSnapshot snapshot);
-
- void remove(Long id);
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/FileSnapshotter.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/FileSnapshotter.java
deleted file mode 100755
index fa65cfc..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/FileSnapshotter.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.changedetection;
-
-import org.gradle.api.file.FileCollection;
-
-public interface FileSnapshotter {
- /**
- * Creates an empty snapshot, which changes can be later merged into.
- *
- * @return The snapshot.
- */
- FileCollectionSnapshot emptySnapshot();
-
- /**
- * Creates a snapshot of the contents of the given collection
- *
- * @param files The files to snapshot
- * @return The snapshot.
- */
- FileCollectionSnapshot snapshot(FileCollection files);
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/Hasher.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/Hasher.java
deleted file mode 100644
index db4ac84..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/Hasher.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.changedetection;
-
-import java.io.File;
-
-public interface Hasher {
- byte[] hash(File file);
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/InMemoryIndexedCache.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/InMemoryIndexedCache.java
deleted file mode 100644
index e03e6c3..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/InMemoryIndexedCache.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.changedetection;
-
-import org.gradle.cache.PersistentIndexedCache;
-import org.gradle.internal.UncheckedException;
-import org.gradle.messaging.serialize.Serializer;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * A simple in-memory cache, used by the testing fixtures.
- */
-public class InMemoryIndexedCache<K, V> implements PersistentIndexedCache<K, V> {
- private final Map<Object, byte[]> entries = new HashMap<Object, byte[]>();
- private final Serializer<V> valueSerializer;
-
- public InMemoryIndexedCache(Serializer<V> valueSerializer) {
- this.valueSerializer = valueSerializer;
- }
-
- public V get(K key) {
- byte[] serialised = entries.get(key);
- if (serialised == null) {
- return null;
- }
- try {
- ByteArrayInputStream instr = new ByteArrayInputStream(serialised);
- return valueSerializer.read(instr);
- } catch (Exception e) {
- throw UncheckedException.throwAsUncheckedException(e);
- }
- }
-
- public void put(K key, V value) {
- ByteArrayOutputStream outstr = new ByteArrayOutputStream();
- try {
- valueSerializer.write(outstr, value);
- } catch (Exception e) {
- throw UncheckedException.throwAsUncheckedException(e);
- }
-
- entries.put(key, outstr.toByteArray());
- }
-
- public void remove(K key) {
- entries.remove(key);
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/InputFilesChangedUpToDateRule.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/InputFilesChangedUpToDateRule.java
deleted file mode 100644
index 7df4355..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/InputFilesChangedUpToDateRule.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.changedetection;
-
-import org.gradle.api.internal.TaskInternal;
-import org.gradle.util.ChangeListener;
-
-import java.io.File;
-import java.util.Collection;
-
-/**
- * A rule which marks a task out-of-date when its input files change.
- */
-public class InputFilesChangedUpToDateRule implements UpToDateRule {
- private final FileSnapshotter inputFilesSnapshotter;
-
- public InputFilesChangedUpToDateRule(FileSnapshotter inputFilesSnapshotter) {
- this.inputFilesSnapshotter = inputFilesSnapshotter;
- }
-
- public TaskUpToDateState create(final TaskInternal task, final TaskExecution previousExecution, final TaskExecution currentExecution) {
- final FileCollectionSnapshot inputFilesSnapshot = inputFilesSnapshotter.snapshot(task.getInputs().getFiles());
-
- return new TaskUpToDateState() {
- public void checkUpToDate(final Collection<String> messages) {
- if (previousExecution.getInputFilesSnapshot() == null) {
- messages.add(String.format("Input file history is not available for %s.", task));
- return;
- }
- inputFilesSnapshot.changesSince(previousExecution.getInputFilesSnapshot(), new ChangeListener<File>() {
- public void added(File file) {
- messages.add(String.format("Input file %s for %s added.", file, task));
- }
-
- public void removed(File file) {
- messages.add(String.format("Input file %s for %s removed.", file, task));
- }
-
- public void changed(File file) {
- messages.add(String.format("Input file %s for %s has changed.", file, task));
- }
- });
- }
-
- public void snapshotAfterTask() {
- currentExecution.setInputFilesSnapshot(inputFilesSnapshot);
- }
- };
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/InputPropertiesChangedUpToDateRule.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/InputPropertiesChangedUpToDateRule.java
deleted file mode 100644
index cbff546..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/InputPropertiesChangedUpToDateRule.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.changedetection;
-
-import org.gradle.api.internal.TaskInternal;
-import org.gradle.util.ChangeListener;
-import org.gradle.util.DiffUtil;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * A rule which marks a task out-of-date when its input properties change.
- */
-public class InputPropertiesChangedUpToDateRule implements UpToDateRule {
- public TaskUpToDateState create(final TaskInternal task, final TaskExecution previousExecution, final TaskExecution currentExecution) {
- final Map<String, Object> properties = new HashMap<String, Object>(task.getInputs().getProperties());
- currentExecution.setInputProperties(properties);
-
- return new TaskUpToDateState() {
- public void checkUpToDate(final Collection<String> messages) {
- DiffUtil.diff(properties, previousExecution.getInputProperties(), new ChangeListener<Map.Entry<String, Object>>() {
- public void added(Map.Entry<String, Object> element) {
- messages.add(String.format("Input property '%s' has been added for %s", element.getKey(), task));
- }
-
- public void removed(Map.Entry<String, Object> element) {
- messages.add(String.format("Input property '%s' has been removed for %s", element.getKey(), task));
- }
-
- public void changed(Map.Entry<String, Object> element) {
- messages.add(String.format("Value of input property '%s' has changed for %s", element.getKey(), task));
- }
- });
- }
-
- public void snapshotAfterTask() {
- }
- };
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/MapMergeChangeListener.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/MapMergeChangeListener.java
deleted file mode 100644
index 4c1e52e..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/MapMergeChangeListener.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.changedetection;
-
-import org.gradle.util.ChangeListener;
-
-import java.util.Map;
-
-class MapMergeChangeListener<K, V> implements ChangeListener<Map.Entry<K, V>> {
- private final ChangeListener<FileCollectionSnapshot.Merge> listener;
- private final Map<K, V> newSnapshots;
-
- public MapMergeChangeListener(ChangeListener<FileCollectionSnapshot.Merge> listener, Map<K, V> targetMap) {
- this.listener = listener;
- this.newSnapshots = targetMap;
- }
-
- public void added(Map.Entry<K, V> element) {
- DefaultMerge merge = new DefaultMerge();
- listener.added(merge);
- if (!merge.isIgnore()) {
- newSnapshots.put(element.getKey(), element.getValue());
- }
- }
-
- public void removed(Map.Entry<K, V> element) {
- DefaultMerge merge = new DefaultMerge();
- listener.removed(merge);
- if (!merge.isIgnore()) {
- newSnapshots.remove(element.getKey());
- }
- }
-
- public void changed(Map.Entry<K, V> element) {
- DefaultMerge merge = new DefaultMerge();
- listener.changed(merge);
- if (!merge.isIgnore()) {
- newSnapshots.put(element.getKey(), element.getValue());
- }
- }
-
- private static class DefaultMerge implements FileCollectionSnapshot.Merge {
- private boolean ignore;
-
- public boolean isIgnore() {
- return ignore;
- }
-
- public void ignore() {
- ignore = true;
- }
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/OutputFilesChangedUpToDateRule.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/OutputFilesChangedUpToDateRule.java
deleted file mode 100644
index 57eca84..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/OutputFilesChangedUpToDateRule.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.changedetection;
-
-import org.gradle.api.internal.TaskInternal;
-import org.gradle.util.ChangeListener;
-
-import java.io.File;
-import java.util.Collection;
-
-/**
- * A rule which marks a task out-of-date when its output files change.
- */
-public class OutputFilesChangedUpToDateRule implements UpToDateRule {
- private final FileSnapshotter outputFilesSnapshotter;
-
- public OutputFilesChangedUpToDateRule(FileSnapshotter outputFilesSnapshotter) {
- this.outputFilesSnapshotter = outputFilesSnapshotter;
- }
-
- public TaskUpToDateState create(final TaskInternal task, final TaskExecution previousExecution, final TaskExecution currentExecution) {
- final FileCollectionSnapshot outputFilesBefore = outputFilesSnapshotter.snapshot(task.getOutputs().getFiles());
-
- return new TaskUpToDateState() {
- public void checkUpToDate(final Collection<String> messages) {
- if (previousExecution.getOutputFilesSnapshot() == null) {
- messages.add(String.format("Output file history is not available for %s.", task));
- return;
- }
- outputFilesBefore.changesSince(previousExecution.getOutputFilesSnapshot(), new ChangeListener<File>() {
- public void added(File element) {
- messages.add(String.format("Output file '%s' has been added for %s.", element, task));
- }
-
- public void removed(File element) {
- messages.add(String.format("Output file %s has been removed for %s.", element.getAbsolutePath(), task));
- }
-
- public void changed(File element) {
- messages.add(String.format("Output file %s for %s has changed.", element.getAbsolutePath(), task));
- }
- });
- }
-
- public void snapshotAfterTask() {
- FileCollectionSnapshot lastExecutionOutputFiles;
- if (previousExecution == null || previousExecution.getOutputFilesSnapshot() == null) {
- lastExecutionOutputFiles = outputFilesSnapshotter.emptySnapshot();
- } else {
- lastExecutionOutputFiles = previousExecution.getOutputFilesSnapshot();
- }
- FileCollectionSnapshot newOutputFiles = outputFilesBefore.changesSince(lastExecutionOutputFiles).applyTo(
- lastExecutionOutputFiles, new ChangeListener<FileCollectionSnapshot.Merge>() {
- public void added(FileCollectionSnapshot.Merge element) {
- // Ignore added files
- element.ignore();
- }
-
- public void removed(FileCollectionSnapshot.Merge element) {
- // Discard any files removed since the task was last executed
- }
-
- public void changed(FileCollectionSnapshot.Merge element) {
- // Update any files which were change since the task was last executed
- }
- });
- FileCollectionSnapshot outputFilesAfter = outputFilesSnapshotter.snapshot(task.getOutputs().getFiles());
- currentExecution.setOutputFilesSnapshot(outputFilesAfter.changesSince(outputFilesBefore).applyTo(newOutputFiles));
- }
- };
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/OutputFilesSnapshotter.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/OutputFilesSnapshotter.java
deleted file mode 100644
index 21dfeb3..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/OutputFilesSnapshotter.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.changedetection;
-
-import org.gradle.api.file.FileCollection;
-import org.gradle.cache.PersistentIndexedCache;
-import org.gradle.internal.id.IdGenerator;
-import org.gradle.util.ChangeListener;
-import org.gradle.util.DiffUtil;
-import org.gradle.util.NoOpChangeListener;
-
-import java.io.File;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Takes a snapshot of the output files of a task. 2 parts to the algorithm:
- *
- * <ul>
- * <li>Collect the unique id for each output file and directory. The unique id is generated when we notice that
- * a file/directory has been created. The id is regenerated when the file/directory is deleted.</li>
- *
- * <li>Collect the hash of each output file and each file in each output directory.</li>
- * </ul>
- *
- */
-public class OutputFilesSnapshotter implements FileSnapshotter {
- private final FileSnapshotter snapshotter;
- private final IdGenerator<Long> idGenerator;
- private final PersistentIndexedCache<String, Long> dirIdentiferCache;
-
- public OutputFilesSnapshotter(FileSnapshotter snapshotter, IdGenerator<Long> idGenerator,
- TaskArtifactStateCacheAccess cacheAccess) {
- this.snapshotter = snapshotter;
- this.idGenerator = idGenerator;
- dirIdentiferCache = cacheAccess.createCache("outputFileStates", String.class, Long.class);
- }
-
- public FileCollectionSnapshot emptySnapshot() {
- return new OutputFilesSnapshot(new HashMap<String, Long>(), snapshotter.emptySnapshot());
- }
-
- public FileCollectionSnapshot snapshot(FileCollection files) {
- Map<String, Long> snapshotDirIds = new HashMap<String, Long>();
- for (File file : files) {
- Long dirId;
- if (file.exists()) {
- dirId = dirIdentiferCache.get(file.getAbsolutePath());
- if (dirId == null) {
- dirId = idGenerator.generateId();
- dirIdentiferCache.put(file.getAbsolutePath(), dirId);
- }
- } else {
- dirIdentiferCache.remove(file.getAbsolutePath());
- dirId = null;
- }
- snapshotDirIds.put(file.getAbsolutePath(), dirId);
- }
- return new OutputFilesSnapshot(snapshotDirIds, snapshotter.snapshot(files));
- }
-
- private static class OutputFilesSnapshot implements FileCollectionSnapshot {
- private final Map<String, Long> rootFileIds;
- private final FileCollectionSnapshot filesSnapshot;
-
- public OutputFilesSnapshot(Map<String, Long> rootFileIds, FileCollectionSnapshot filesSnapshot) {
- this.rootFileIds = rootFileIds;
- this.filesSnapshot = filesSnapshot;
- }
-
- public FileCollection getFiles() {
- return filesSnapshot.getFiles();
- }
-
- public Diff changesSince(final FileCollectionSnapshot oldSnapshot) {
- OutputFilesSnapshot other = (OutputFilesSnapshot) oldSnapshot;
- return new OutputFilesDiff(rootFileIds, other.rootFileIds, filesSnapshot.changesSince(other.filesSnapshot));
- }
-
- public void changesSince(FileCollectionSnapshot oldSnapshot, final ChangeListener<File> listener) {
- final OutputFilesSnapshot other = (OutputFilesSnapshot) oldSnapshot;
- DiffUtil.diff(rootFileIds, other.rootFileIds, new ChangeListener<Map.Entry<String, Long>>() {
- public void added(Map.Entry<String, Long> element) {
- listener.added(new File(element.getKey()));
- }
-
- public void removed(Map.Entry<String, Long> element) {
- listener.removed(new File(element.getKey()));
- }
-
- public void changed(Map.Entry<String, Long> element) {
- if (other.rootFileIds.get(element.getKey()) == null) {
- // Dir used to not exist, now does. Don't care
- return;
- }
- listener.changed(new File(element.getKey()));
- }
- });
- filesSnapshot.changesSince(other.filesSnapshot, new ChangeListener<File>() {
- public void added(File element) {
- // Ignore files added to output dirs which have been added since last time task executed
- }
-
- public void removed(File element) {
- listener.removed(element);
- }
-
- public void changed(File element) {
- listener.changed(element);
- }
- });
- }
- }
-
- private static class OutputFilesDiff implements FileCollectionSnapshot.Diff {
- private final Map<String, Long> newFileIds;
- private final Map<String, Long> oldFileIds;
- private final FileCollectionSnapshot.Diff filesDiff;
-
- public OutputFilesDiff(Map<String, Long> newFileIds, Map<String, Long> oldFileIds,
- FileCollectionSnapshot.Diff filesDiff) {
- this.newFileIds = newFileIds;
- this.oldFileIds = oldFileIds;
- this.filesDiff = filesDiff;
- }
-
- public FileCollectionSnapshot applyTo(FileCollectionSnapshot snapshot,
- ChangeListener<FileCollectionSnapshot.Merge> listener) {
- OutputFilesSnapshot other = (OutputFilesSnapshot) snapshot;
- Map<String, Long> dirIds = new HashMap<String, Long>(other.rootFileIds);
- DiffUtil.diff(newFileIds, oldFileIds, new MapMergeChangeListener<String, Long>(
- new NoOpChangeListener<FileCollectionSnapshot.Merge>(), dirIds));
- return new OutputFilesSnapshot(newFileIds, filesDiff.applyTo(other.filesSnapshot, listener));
- }
-
- public FileCollectionSnapshot applyTo(FileCollectionSnapshot snapshot) {
- return applyTo(snapshot, new NoOpChangeListener<FileCollectionSnapshot.Merge>());
- }
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/ShortCircuitTaskArtifactStateRepository.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/ShortCircuitTaskArtifactStateRepository.java
deleted file mode 100755
index 7b490be..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/ShortCircuitTaskArtifactStateRepository.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.changedetection;
-
-import org.apache.commons.lang.StringUtils;
-import org.gradle.StartParameter;
-import org.gradle.api.file.FileCollection;
-import org.gradle.api.internal.TaskExecutionHistory;
-import org.gradle.api.internal.TaskInternal;
-import org.gradle.api.logging.Logger;
-import org.gradle.api.logging.Logging;
-
-public class ShortCircuitTaskArtifactStateRepository implements TaskArtifactStateRepository {
- private static final Logger LOGGER = Logging.getLogger(ShortCircuitTaskArtifactStateRepository.class);
- private final StartParameter startParameter;
- private final TaskArtifactStateRepository repository;
-
- public ShortCircuitTaskArtifactStateRepository(StartParameter startParameter, TaskArtifactStateRepository repository) {
- this.startParameter = startParameter;
- this.repository = repository;
- }
-
- public TaskArtifactState getStateFor(final TaskInternal task) {
- if (task.getOutputs().getHasOutput()) {
- return new ShortCircuitArtifactState(task, repository.getStateFor(task));
- }
- LOGGER.info(String.format("%s has not declared any outputs, assuming that it is out-of-date.", StringUtils.capitalize(task.toString())));
- return new NoHistoryArtifactState();
- }
-
- private static class NoHistoryArtifactState implements TaskArtifactState, TaskExecutionHistory {
- public boolean isUpToDate() {
- return false;
- }
-
- public void beforeTask() {
- }
-
- public void afterTask() {
- }
-
- public void finished() {
- }
-
- public TaskExecutionHistory getExecutionHistory() {
- return this;
- }
-
- public FileCollection getOutputFiles() {
- throw new UnsupportedOperationException();
- }
- }
-
- private class ShortCircuitArtifactState implements TaskArtifactState {
- private final TaskInternal task;
- private final TaskArtifactState state;
-
- public ShortCircuitArtifactState(TaskInternal task, TaskArtifactState state) {
- this.task = task;
- this.state = state;
- }
-
- public boolean isUpToDate() {
- return !startParameter.isRerunTasks() && task.getOutputs().getUpToDateSpec().isSatisfiedBy(task) && state.isUpToDate();
- }
-
- public TaskExecutionHistory getExecutionHistory() {
- return state.getExecutionHistory();
- }
-
- public void beforeTask() {
- state.beforeTask();
- }
-
- public void afterTask() {
- state.afterTask();
- }
-
- public void finished() {
- state.finished();
- }
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/TaskArtifactState.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/TaskArtifactState.java
index 5fe4110..e095d26 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/TaskArtifactState.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/TaskArtifactState.java
@@ -16,6 +16,9 @@
package org.gradle.api.internal.changedetection;
import org.gradle.api.internal.TaskExecutionHistory;
+import org.gradle.api.tasks.incremental.IncrementalTaskInputs;
+
+import java.util.Collection;
/**
* Encapsulates the state of the task when its outputs were last generated.
@@ -23,11 +26,15 @@ import org.gradle.api.internal.TaskExecutionHistory;
public interface TaskArtifactState {
/**
* Returns true if the task outputs were generated using the given task inputs.
+ *
+ * @param messages a collection to add messages which explain why the task is out-of-date.
*/
- boolean isUpToDate();
+ boolean isUpToDate(Collection<String> messages);
+
+ IncrementalTaskInputs getInputChanges();
/**
- * Called before the task is to be executed. Note that {@link #isUpToDate()} may not necessarily have been called.
+ * Called before the task is to be executed. Note that {@link #isUpToDate(java.util.Collection)} may not necessarily have been called.
*/
void beforeTask();
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/TaskArtifactStateCacheAccess.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/TaskArtifactStateCacheAccess.java
deleted file mode 100644
index bf1525d..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/TaskArtifactStateCacheAccess.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.changedetection;
-
-import org.gradle.internal.Factory;
-import org.gradle.cache.PersistentIndexedCache;
-import org.gradle.messaging.serialize.Serializer;
-
-public interface TaskArtifactStateCacheAccess {
- /**
- * Performs some work against the cache. Acquires exclusive locks the appropriate resources, so that the given action is the only
- * action to execute across all processes (including this one). Releases the locks and all resources at the end of the action.
- *
- * <p>This method is re-entrant, so that an action can call back into this method.</p>
- */
- <T> T useCache(String operationDisplayName, Factory<? extends T> action);
-
- /**
- * Performs some work against the cache. Acquires exclusive locks the appropriate resources, so that the given action is the only
- * action to execute across all processes (including this one). Releases the locks and all resources at the end of the action.
- *
- * <p>This method is re-entrant, so that an action can call back into this method.</p>
- */
- void useCache(String operationDisplayName, Runnable action);
-
- /**
- * Performs some long running operation. Releases all locks while the operation is running, and reacquires the locks at the end of
- * the long running operation.
- *
- * <p>This method is re-entrant, so that an action can call back into this method.</p>
- */
- void longRunningOperation(String operationDisplayName, Runnable action);
-
- <K, V> PersistentIndexedCache createCache(String cacheName, Class<K> keyType, Class<V> valueType);
-
- <K, V> PersistentIndexedCache<K, V> createCache(String cacheName, Class<K> keyType, Class<V> valueType, Serializer<V> valueSerializer);
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/TaskCacheLockHandlingBuildExecuter.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/TaskCacheLockHandlingBuildExecuter.java
deleted file mode 100644
index 3dfbf20..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/TaskCacheLockHandlingBuildExecuter.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.changedetection;
-
-import org.gradle.execution.BuildExecutionAction;
-import org.gradle.execution.BuildExecutionContext;
-
-public class TaskCacheLockHandlingBuildExecuter implements BuildExecutionAction {
- private final TaskArtifactStateCacheAccess cacheAccess;
-
- public TaskCacheLockHandlingBuildExecuter(TaskArtifactStateCacheAccess cacheAccess) {
- this.cacheAccess = cacheAccess;
- }
-
- public void execute(final BuildExecutionContext context) {
- cacheAccess.useCache("execute tasks", new Runnable(){
- public void run() {
- context.proceed();
- }
- });
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/TaskExecution.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/TaskExecution.java
deleted file mode 100644
index 16aff96..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/TaskExecution.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.changedetection;
-
-import java.io.Serializable;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * The persistent state for a single task execution.
- */
-public abstract class TaskExecution implements Serializable {
- private String taskClass;
- private Map<String, Object> inputProperties;
- private Set<String> outputFiles;
-
- public Set<String> getOutputFiles() {
- return outputFiles;
- }
-
- public void setOutputFiles(Set<String> outputFiles) {
- this.outputFiles = outputFiles;
- }
-
- public String getTaskClass() {
- return taskClass;
- }
-
- public void setTaskClass(String taskClass) {
- this.taskClass = taskClass;
- }
-
- public Map<String, Object> getInputProperties() {
- return inputProperties;
- }
-
- public void setInputProperties(Map<String, Object> inputProperties) {
- this.inputProperties = inputProperties;
- }
-
- /**
- * @return May return null.
- */
- public abstract FileCollectionSnapshot getOutputFilesSnapshot();
-
- public abstract void setOutputFilesSnapshot(FileCollectionSnapshot outputFilesSnapshot);
-
- /**
- * @return May return null.
- */
- public abstract FileCollectionSnapshot getInputFilesSnapshot();
-
- public abstract void setInputFilesSnapshot(FileCollectionSnapshot inputFilesSnapshot);
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/TaskHistoryRepository.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/TaskHistoryRepository.java
deleted file mode 100644
index 9f71553..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/TaskHistoryRepository.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.changedetection;
-
-import org.gradle.api.internal.TaskInternal;
-
-public interface TaskHistoryRepository {
- History getHistory(TaskInternal task);
-
- interface History {
- TaskExecution getPreviousExecution();
-
- TaskExecution getCurrentExecution();
-
- void update();
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/TaskTypeChangedUpToDateRule.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/TaskTypeChangedUpToDateRule.java
deleted file mode 100644
index c166808..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/TaskTypeChangedUpToDateRule.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.changedetection;
-
-import org.apache.commons.lang.StringUtils;
-import org.gradle.api.internal.TaskInternal;
-
-import java.util.Collection;
-
-/**
- * A rule which marks a task out-of-date when its implementation class changes.
- */
-public class TaskTypeChangedUpToDateRule implements UpToDateRule {
- public TaskUpToDateState create(final TaskInternal task, final TaskExecution previousExecution, final TaskExecution currentExecution) {
- final String taskClass = task.getClass().getName();
- currentExecution.setTaskClass(taskClass);
-
- return new TaskUpToDateState() {
- public void checkUpToDate(Collection<String> messages) {
- if (!taskClass.equals(previousExecution.getTaskClass())) {
- messages.add(String.format("%s has changed type from '%s' to '%s'.", StringUtils.capitalize(task.toString()), previousExecution.getTaskClass(), task.getClass().getName()));
- }
- }
-
- public void snapshotAfterTask() {
- }
- };
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/UpToDateRule.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/UpToDateRule.java
deleted file mode 100644
index 2f47511..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/UpToDateRule.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.changedetection;
-
-import org.gradle.api.internal.TaskInternal;
-
-import java.util.Collection;
-
-public interface UpToDateRule {
- /**
- * Creates the transient state for the given task.
- *
- * @param task The task to be executed.
- * @param previousExecution The previous execution for this task, if any. May be null.
- * @param currentExecution The current execution. The rule may mutate this.
- * @return The state.
- */
- TaskUpToDateState create(TaskInternal task, TaskExecution previousExecution, TaskExecution currentExecution);
-
- interface TaskUpToDateState {
- /**
- * Checks if the task is up-to-date. If so, this method must add at least 1 message explaining why the task is out-of-date to the given collection. Note that this method may not be called for
- * a given execution. Also note, this method is called only when the previous execution is not null.
- *
- * @param messages The out-of-date messages.
- */
- void checkUpToDate(Collection<String> messages);
-
- /**
- * Snapshot any final state after the task has executed. This method is executed only if the task is to be executed. Any persistent state should be added to the {@link TaskExecution} object
- * passed to {@link UpToDateRule#create}.
- */
- void snapshotAfterTask();
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/changes/ChangesOnlyIncrementalTaskInputs.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/changes/ChangesOnlyIncrementalTaskInputs.java
new file mode 100644
index 0000000..590f179
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/changes/ChangesOnlyIncrementalTaskInputs.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.changes;
+
+import org.gradle.api.Action;
+import org.gradle.api.internal.changedetection.rules.TaskStateChange;
+import org.gradle.api.internal.changedetection.rules.TaskStateChanges;
+import org.gradle.api.tasks.incremental.InputFileDetails;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ChangesOnlyIncrementalTaskInputs extends StatefulIncrementalTaskInputs {
+ private final TaskStateChanges inputFilesState;
+ private List<InputFileDetails> removedFiles = new ArrayList<InputFileDetails>();
+
+ public ChangesOnlyIncrementalTaskInputs(TaskStateChanges inputFilesState) {
+ this.inputFilesState = inputFilesState;
+ }
+
+ public boolean isIncremental() {
+ return true;
+ }
+
+ @Override
+ protected void doOutOfDate(final Action<? super InputFileDetails> outOfDateAction) {
+ for (TaskStateChange change : inputFilesState) {
+ InputFileDetails fileChange = (InputFileDetails) change;
+ if (fileChange.isRemoved()) {
+ removedFiles.add(fileChange);
+ } else {
+ outOfDateAction.execute(fileChange);
+ }
+ }
+ }
+
+ @Override
+ protected void doRemoved(Action<? super InputFileDetails> removedAction) {
+ for (InputFileDetails removedFile : removedFiles) {
+ removedAction.execute(removedFile);
+ }
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/changes/DefaultTaskArtifactStateRepository.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/changes/DefaultTaskArtifactStateRepository.java
new file mode 100644
index 0000000..d7daee1
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/changes/DefaultTaskArtifactStateRepository.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.changes;
+
+import org.gradle.api.file.FileCollection;
+import org.gradle.api.internal.TaskExecutionHistory;
+import org.gradle.api.internal.TaskInternal;
+import org.gradle.api.internal.changedetection.TaskArtifactState;
+import org.gradle.api.internal.changedetection.TaskArtifactStateRepository;
+import org.gradle.api.internal.changedetection.rules.TaskStateChange;
+import org.gradle.api.internal.changedetection.rules.TaskStateChanges;
+import org.gradle.api.internal.changedetection.rules.TaskUpToDateState;
+import org.gradle.api.internal.changedetection.state.FileSnapshotter;
+import org.gradle.api.internal.changedetection.state.TaskExecution;
+import org.gradle.api.internal.changedetection.state.TaskHistoryRepository;
+import org.gradle.api.internal.file.collections.SimpleFileCollection;
+import org.gradle.api.tasks.incremental.IncrementalTaskInputs;
+import org.gradle.internal.reflect.Instantiator;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+public class DefaultTaskArtifactStateRepository implements TaskArtifactStateRepository {
+
+ private final TaskHistoryRepository taskHistoryRepository;
+ private final FileSnapshotter outputFilesSnapshotter;
+ private final FileSnapshotter inputFilesSnapshotter;
+ private final Instantiator instantiator;
+
+ public DefaultTaskArtifactStateRepository(TaskHistoryRepository taskHistoryRepository, Instantiator instantiator,
+ FileSnapshotter outputFilesSnapshotter, FileSnapshotter inputFilesSnapshotter) {
+ this.taskHistoryRepository = taskHistoryRepository;
+ this.instantiator = instantiator;
+ this.outputFilesSnapshotter = outputFilesSnapshotter;
+ this.inputFilesSnapshotter = inputFilesSnapshotter;
+ }
+
+ public TaskArtifactState getStateFor(final TaskInternal task) {
+ return new TaskArtifactStateImpl(task, taskHistoryRepository.getHistory(task));
+ }
+
+ private class TaskArtifactStateImpl implements TaskArtifactState, TaskExecutionHistory {
+ private final TaskInternal task;
+ private final TaskHistoryRepository.History history;
+ private boolean upToDate;
+ private TaskUpToDateState states;
+
+ public TaskArtifactStateImpl(TaskInternal task, TaskHistoryRepository.History history) {
+ this.task = task;
+ this.history = history;
+ }
+
+ public boolean isUpToDate(Collection<String> messages) {
+ final List<String> reasons = getChangeMessages(getStates().getAllTaskChanges());
+ messages.addAll(reasons);
+ if (reasons.isEmpty()) {
+ upToDate = true;
+ return true;
+ }
+ return false;
+ }
+
+ private List<String> getChangeMessages(TaskStateChanges stateChanges) {
+ final List<String> messages = new ArrayList<String>();
+ for (TaskStateChange stateChange : stateChanges) {
+ messages.add(stateChange.getMessage());
+ }
+ return messages;
+ }
+
+ public IncrementalTaskInputs getInputChanges() {
+ assert !upToDate : "Should not be here if the task is up-to-date";
+
+ if (canPerformIncrementalBuild()) {
+ return instantiator.newInstance(ChangesOnlyIncrementalTaskInputs.class, getStates().getInputFilesChanges());
+ }
+ return instantiator.newInstance(RebuildIncrementalTaskInputs.class, task);
+ }
+
+ private boolean canPerformIncrementalBuild() {
+ final List<String> messages = getChangeMessages(getStates().getRebuildChanges());
+ return messages.isEmpty();
+ }
+
+ public FileCollection getOutputFiles() {
+ TaskExecution lastExecution = history.getPreviousExecution();
+ return lastExecution != null && lastExecution.getOutputFilesSnapshot() != null ? lastExecution.getOutputFilesSnapshot().getFiles() : new SimpleFileCollection();
+ }
+
+ public TaskExecutionHistory getExecutionHistory() {
+ return this;
+ }
+
+ public void beforeTask() {
+ }
+
+ public void afterTask() {
+ if (upToDate) {
+ return;
+ }
+
+ getStates().getAllTaskChanges().snapshotAfterTask();
+ history.update();
+ }
+
+ public void finished() {
+ }
+
+ private TaskUpToDateState getStates() {
+ if (states == null) {
+ // Calculate initial state - note this is potentially expensive
+ states = new TaskUpToDateState(task, history, outputFilesSnapshotter, inputFilesSnapshotter);
+ }
+ return states;
+ }
+ }
+
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/changes/NoHistoryArtifactState.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/changes/NoHistoryArtifactState.java
new file mode 100644
index 0000000..3577a34
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/changes/NoHistoryArtifactState.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.changes;
+
+import org.gradle.api.file.FileCollection;
+import org.gradle.api.internal.TaskExecutionHistory;
+import org.gradle.api.internal.changedetection.TaskArtifactState;
+import org.gradle.api.tasks.incremental.IncrementalTaskInputs;
+
+import java.util.Collection;
+
+class NoHistoryArtifactState implements TaskArtifactState, TaskExecutionHistory {
+ public boolean isUpToDate(Collection<String> messages) {
+ messages.add("Task has not declared any outputs.");
+ return false;
+ }
+
+ public IncrementalTaskInputs getInputChanges() {
+ throw new UnsupportedOperationException();
+ }
+
+ public TaskExecutionHistory getExecutionHistory() {
+ return this;
+ }
+
+ public void beforeTask() {
+ }
+
+ public void afterTask() {
+ }
+
+ public void finished() {
+ }
+
+ public FileCollection getOutputFiles() {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/changes/RebuildIncrementalTaskInputs.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/changes/RebuildIncrementalTaskInputs.java
new file mode 100644
index 0000000..e227766
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/changes/RebuildIncrementalTaskInputs.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.changes;
+
+import org.gradle.api.Action;
+import org.gradle.api.Task;
+import org.gradle.api.tasks.incremental.InputFileDetails;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+
+public class RebuildIncrementalTaskInputs extends StatefulIncrementalTaskInputs {
+ private static final Logger LOGGER = LoggerFactory.getLogger(RebuildIncrementalTaskInputs.class);
+
+ private final Task task;
+
+ public RebuildIncrementalTaskInputs(Task task) {
+ LOGGER.info("All input files are considered out-of-date for incremental {}.", task);
+ this.task = task;
+ }
+
+ public boolean isIncremental() {
+ return false;
+ }
+
+ public void doOutOfDate(Action<? super InputFileDetails> outOfDateAction) {
+ for (File file : task.getInputs().getFiles()) {
+ outOfDateAction.execute(new RebuildInputFile(file));
+ }
+ }
+
+ public void doRemoved(Action<? super InputFileDetails> removedAction) {
+ }
+
+ private static class RebuildInputFile implements InputFileDetails {
+ private final File file;
+
+ private RebuildInputFile(File file) {
+ this.file = file;
+ }
+
+ public File getFile() {
+ return file;
+ }
+
+ public boolean isAdded() {
+ return false;
+ }
+
+ public boolean isModified() {
+ return false;
+ }
+
+ public boolean isRemoved() {
+ return false;
+ }
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/changes/ShortCircuitTaskArtifactStateRepository.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/changes/ShortCircuitTaskArtifactStateRepository.java
new file mode 100755
index 0000000..9bb3ad8
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/changes/ShortCircuitTaskArtifactStateRepository.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.changes;
+
+import org.gradle.StartParameter;
+import org.gradle.api.internal.TaskExecutionHistory;
+import org.gradle.api.internal.TaskInternal;
+import org.gradle.api.internal.changedetection.TaskArtifactState;
+import org.gradle.api.internal.changedetection.TaskArtifactStateRepository;
+import org.gradle.api.tasks.incremental.IncrementalTaskInputs;
+import org.gradle.internal.reflect.Instantiator;
+
+import java.util.Collection;
+
+public class ShortCircuitTaskArtifactStateRepository implements TaskArtifactStateRepository {
+
+ private final StartParameter startParameter;
+ private final TaskArtifactStateRepository repository;
+ private final Instantiator instantiator;
+
+ public ShortCircuitTaskArtifactStateRepository(StartParameter startParameter, Instantiator instantiator, TaskArtifactStateRepository repository) {
+ this.startParameter = startParameter;
+ this.instantiator = instantiator;
+ this.repository = repository;
+ }
+
+ public TaskArtifactState getStateFor(final TaskInternal task) {
+
+ if (!task.getOutputs().getHasOutput()) { // Only false if no declared outputs AND no Task.upToDateWhen spec. We force to true for incremental tasks.
+ return new NoHistoryArtifactState();
+ }
+
+ final TaskArtifactState state = repository.getStateFor(task);
+
+ if (startParameter.isRerunTasks()) {
+ return new RerunTaskArtifactState(state, task, "Executed with '--rerun-tasks'.");
+ }
+
+ if (!task.getOutputs().getUpToDateSpec().isSatisfiedBy(task)) {
+ return new RerunTaskArtifactState(state, task, "Task.upToDateWhen is false.");
+ }
+
+ return state;
+ }
+
+ private class RerunTaskArtifactState implements TaskArtifactState {
+ private final TaskArtifactState delegate;
+ private final TaskInternal task;
+ private final String reason;
+
+ private RerunTaskArtifactState(TaskArtifactState delegate, TaskInternal task, String reason) {
+ this.delegate = delegate;
+ this.task = task;
+ this.reason = reason;
+ }
+
+ public boolean isUpToDate(Collection<String> messages) {
+ messages.add(reason);
+ return false;
+ }
+
+ public IncrementalTaskInputs getInputChanges() {
+ return instantiator.newInstance(RebuildIncrementalTaskInputs.class, task);
+ }
+
+ public TaskExecutionHistory getExecutionHistory() {
+ return delegate.getExecutionHistory();
+ }
+
+ public void beforeTask() {
+ delegate.beforeTask();
+ }
+
+ public void afterTask() {
+ delegate.afterTask();
+ }
+
+ public void finished() {
+ delegate.finished();
+ }
+ }
+
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/changes/StatefulIncrementalTaskInputs.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/changes/StatefulIncrementalTaskInputs.java
new file mode 100644
index 0000000..35bca19
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/changes/StatefulIncrementalTaskInputs.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.changes;
+
+import org.gradle.api.Action;
+import org.gradle.api.tasks.incremental.IncrementalTaskInputs;
+import org.gradle.api.tasks.incremental.InputFileDetails;
+
+abstract class StatefulIncrementalTaskInputs implements IncrementalTaskInputs {
+ private boolean outOfDateProcessed;
+ private boolean removedProcessed;
+
+ public void outOfDate(final Action<? super InputFileDetails> outOfDateAction) {
+ if (outOfDateProcessed) {
+ throw new IllegalStateException("Cannot process outOfDate files multiple times");
+ }
+ doOutOfDate(outOfDateAction);
+ outOfDateProcessed = true;
+ }
+
+ protected abstract void doOutOfDate(Action<? super InputFileDetails> outOfDateAction);
+
+ public void removed(Action<? super InputFileDetails> removedAction) {
+ if (!outOfDateProcessed) {
+ throw new IllegalStateException("Must first process outOfDate files before processing removed files");
+ }
+ if (removedProcessed) {
+ throw new IllegalStateException("Cannot process removed files multiple times");
+ }
+ doRemoved(removedAction);
+ removedProcessed = true;
+ }
+
+ protected abstract void doRemoved(Action<? super InputFileDetails> removedAction);
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/CachingTaskStateChanges.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/CachingTaskStateChanges.java
new file mode 100644
index 0000000..cda5490
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/CachingTaskStateChanges.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.rules;
+
+import com.google.common.collect.AbstractIterator;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * An implementation that will cache a number of results of iteration, and make them available for subsequent iterations.
+ * This allows a single underlying iterator to be used for multiple iterations, up til the first iteration that exceeds the cache size.
+ * When the cache is overrun, it is cleared so that any subsequent iteration will require a fresh delegate iterator.
+ */
+public class CachingTaskStateChanges implements TaskStateChanges {
+ private final TaskStateChanges delegate;
+ private final List<TaskStateChange> cache = new ArrayList<TaskStateChange>();
+ private final int maxCachedChanges;
+ private Iterator<TaskStateChange> delegateIterator;
+ boolean overrun;
+
+ public CachingTaskStateChanges(int maxCachedChanges, TaskStateChanges delegate) {
+ this.maxCachedChanges = maxCachedChanges;
+ this.delegate = delegate;
+ }
+
+ public Iterator<TaskStateChange> iterator() {
+ if (delegateIterator == null || overrun) {
+ reset();
+ }
+
+ return new AbstractIterator<TaskStateChange>() {
+ final Iterator<TaskStateChange> cacheIterator = new ArrayList<TaskStateChange>(cache).iterator();
+
+ @Override
+ protected TaskStateChange computeNext() {
+ if (cacheIterator.hasNext()) {
+ return cacheIterator.next();
+ }
+ if (delegateIterator.hasNext()) {
+ TaskStateChange next = delegateIterator.next();
+ maybeCache(next);
+ return next;
+ }
+ return endOfData();
+ }
+ };
+ }
+
+ private void maybeCache(TaskStateChange next) {
+ if (overrun) {
+ return;
+ }
+
+ if (cache.size() < maxCachedChanges) {
+ cache.add(next);
+ } else {
+ overrun = true;
+ }
+ }
+
+ private void reset() {
+ cache.clear();
+ delegateIterator = delegate.iterator();
+ overrun = false;
+ }
+
+ public void snapshotAfterTask() {
+ delegate.snapshotAfterTask();
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/ChangeType.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/ChangeType.java
new file mode 100644
index 0000000..3f59e2c
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/ChangeType.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.rules;
+
+enum ChangeType {
+ ADDED("has been added"),
+ MODIFIED("has changed"),
+ REMOVED("has been removed");
+
+ private final String description;
+
+ private ChangeType(String description) {
+ this.description = description;
+ }
+
+ public String describe() {
+ return description;
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/DescriptiveChange.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/DescriptiveChange.java
new file mode 100644
index 0000000..321e392
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/DescriptiveChange.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.rules;
+
+class DescriptiveChange implements TaskStateChange {
+ private final String message;
+
+ public DescriptiveChange(String message, Object... params) {
+ this.message = String.format(message, params);
+ }
+
+ public String getMessage() {
+ return message;
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/FileChange.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/FileChange.java
new file mode 100644
index 0000000..f73a71e
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/FileChange.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.rules;
+
+import java.io.File;
+
+abstract class FileChange implements TaskStateChange {
+ private final String path;
+ private final ChangeType change;
+
+ public FileChange(String path, ChangeType change) {
+ this.path = path;
+ this.change = change;
+ }
+
+ public String getMessage() {
+ return String.format("%s file %s %s.", getFileType(), path, change.describe());
+ }
+
+ @Override
+ public String toString() {
+ return getMessage();
+ }
+
+ protected abstract String getFileType();
+
+ public String getPath() {
+ return path;
+ }
+
+ public File getFile() {
+ return new File(path);
+ }
+
+ public boolean isAdded() {
+ return change == ChangeType.ADDED;
+ }
+
+ public boolean isModified() {
+ return change == ChangeType.MODIFIED;
+ }
+
+ public boolean isRemoved() {
+ return change == ChangeType.REMOVED;
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/InputFileChange.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/InputFileChange.java
new file mode 100644
index 0000000..a67677a
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/InputFileChange.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.rules;
+
+import org.gradle.api.tasks.incremental.InputFileDetails;
+
+class InputFileChange extends FileChange implements InputFileDetails {
+
+ public InputFileChange(String path, ChangeType change) {
+ super(path, change);
+ }
+
+ @Override
+ protected String getFileType() {
+ return "Input";
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/InputFilesStateChangeRule.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/InputFilesStateChangeRule.java
new file mode 100644
index 0000000..bdb7620
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/InputFilesStateChangeRule.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.rules;
+
+import com.google.common.collect.AbstractIterator;
+import org.gradle.api.internal.TaskInternal;
+import org.gradle.api.internal.changedetection.state.FileCollectionSnapshot;
+import org.gradle.api.internal.changedetection.state.FileSnapshotter;
+import org.gradle.api.internal.changedetection.state.TaskExecution;
+import org.gradle.util.ChangeListener;
+
+import java.util.Collections;
+import java.util.Iterator;
+
+/**
+ * A rule which detects changes in the input files of a task.
+ */
+class InputFilesStateChangeRule {
+ public static TaskStateChanges create(final TaskInternal task, final TaskExecution previousExecution, final TaskExecution currentExecution, final FileSnapshotter inputFilesSnapshotter) {
+ final FileCollectionSnapshot inputFilesSnapshot = inputFilesSnapshotter.snapshot(task.getInputs().getFiles());
+
+ return new TaskStateChanges() {
+
+ public Iterator<TaskStateChange> iterator() {
+ if (previousExecution.getInputFilesSnapshot() == null) {
+ return Collections.<TaskStateChange>singleton(new DescriptiveChange("Input file history is not available.")).iterator();
+ }
+
+ return new AbstractIterator<TaskStateChange>() {
+ final FileCollectionSnapshot.ChangeIterator<String> changeIterator = inputFilesSnapshot.iterateChangesSince(previousExecution.getInputFilesSnapshot());
+ final ChangeListenerAdapter listenerAdapter = new ChangeListenerAdapter();
+
+ @Override
+ protected TaskStateChange computeNext() {
+ if (changeIterator.next(listenerAdapter)) {
+ return listenerAdapter.lastChange;
+ }
+ return endOfData();
+ }
+ };
+ }
+
+ public void snapshotAfterTask() {
+ currentExecution.setInputFilesSnapshot(inputFilesSnapshot);
+ }
+ };
+ }
+
+ private static class ChangeListenerAdapter implements ChangeListener<String> {
+ public InputFileChange lastChange;
+
+ public void added(String fileName) {
+ lastChange = new InputFileChange(fileName, ChangeType.ADDED);
+ }
+
+ public void removed(String fileName) {
+ lastChange = new InputFileChange(fileName, ChangeType.REMOVED);
+ }
+
+ public void changed(String fileName) {
+ lastChange = new InputFileChange(fileName, ChangeType.MODIFIED);
+ }
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/InputPropertiesStateChangeRule.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/InputPropertiesStateChangeRule.java
new file mode 100644
index 0000000..57d0c38
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/InputPropertiesStateChangeRule.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.rules;
+
+import org.gradle.api.internal.TaskInternal;
+import org.gradle.api.internal.changedetection.state.TaskExecution;
+import org.gradle.util.ChangeListener;
+import org.gradle.util.DiffUtil;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A rule which detects changes in the input properties of a task.
+ */
+class InputPropertiesStateChangeRule {
+ public static TaskStateChanges create(final TaskInternal task, final TaskExecution previousExecution, final TaskExecution currentExecution) {
+ final Map<String, Object> properties = new HashMap<String, Object>(task.getInputs().getProperties());
+ currentExecution.setInputProperties(properties);
+
+ return new SimpleTaskStateChanges() {
+ @Override
+ protected void addAllChanges(final List<TaskStateChange> changes) {
+ DiffUtil.diff(properties, previousExecution.getInputProperties(), new ChangeListener<Map.Entry<String, Object>>() {
+ public void added(Map.Entry<String, Object> element) {
+ changes.add(new DescriptiveChange("Input property '%s' has been added for %s", element.getKey(), task));
+ }
+
+ public void removed(Map.Entry<String, Object> element) {
+ changes.add(new DescriptiveChange("Input property '%s' has been removed for %s", element.getKey(), task));
+ }
+
+ public void changed(Map.Entry<String, Object> element) {
+ changes.add(new DescriptiveChange("Value of input property '%s' has changed for %s", element.getKey(), task));
+ }
+ });
+ }
+ };
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/NoHistoryStateChangeRule.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/NoHistoryStateChangeRule.java
new file mode 100644
index 0000000..0f27534
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/NoHistoryStateChangeRule.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.rules;
+
+import org.gradle.api.internal.TaskInternal;
+import org.gradle.api.internal.changedetection.state.TaskExecution;
+
+import java.util.List;
+
+class NoHistoryStateChangeRule {
+ public static TaskStateChanges create(final TaskInternal task, final TaskExecution previousExecution) {
+ return new SimpleTaskStateChanges() {
+ @Override
+ protected void addAllChanges(List<TaskStateChange> changes) {
+ if (previousExecution == null) {
+ changes.add(new DescriptiveChange("No history is available."));
+ }
+ }
+ };
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/OutputFileChange.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/OutputFileChange.java
new file mode 100644
index 0000000..ab4fbad
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/OutputFileChange.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.rules;
+
+class OutputFileChange extends FileChange {
+
+ public OutputFileChange(String path, ChangeType change) {
+ super(path, change);
+ }
+
+ @Override
+ protected String getFileType() {
+ return "Output";
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/OutputFilesStateChangeRule.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/OutputFilesStateChangeRule.java
new file mode 100644
index 0000000..b3b91cd
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/OutputFilesStateChangeRule.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.rules;
+
+import com.google.common.collect.AbstractIterator;
+import org.gradle.api.internal.TaskInternal;
+import org.gradle.api.internal.changedetection.state.FileCollectionSnapshot;
+import org.gradle.api.internal.changedetection.state.FileSnapshotter;
+import org.gradle.api.internal.changedetection.state.TaskExecution;
+import org.gradle.util.ChangeListener;
+
+import java.util.Collections;
+import java.util.Iterator;
+
+/**
+ * A rule which detects changes in output files.
+ */
+class OutputFilesStateChangeRule {
+
+ public static TaskStateChanges create(final TaskInternal task, final TaskExecution previousExecution, final TaskExecution currentExecution, final FileSnapshotter outputFilesSnapshotter) {
+ final FileCollectionSnapshot outputFilesBefore = outputFilesSnapshotter.snapshot(task.getOutputs().getFiles());
+
+ return new TaskStateChanges() {
+
+ public Iterator<TaskStateChange> iterator() {
+ if (previousExecution.getOutputFilesSnapshot() == null) {
+ return Collections.<TaskStateChange>singleton(new DescriptiveChange("Output file history is not available.")).iterator();
+ }
+
+ return new AbstractIterator<TaskStateChange>() {
+ final FileCollectionSnapshot.ChangeIterator<String> changeIterator = outputFilesBefore.iterateChangesSince(previousExecution.getOutputFilesSnapshot());
+ final ChangeListenerAdapter listenerAdapter = new ChangeListenerAdapter();
+
+ @Override
+ protected TaskStateChange computeNext() {
+ if (changeIterator.next(listenerAdapter)) {
+ return listenerAdapter.lastChange;
+ }
+ return endOfData();
+ }
+ };
+ }
+
+ public void snapshotAfterTask() {
+ FileCollectionSnapshot lastExecutionOutputFiles;
+ if (previousExecution == null || previousExecution.getOutputFilesSnapshot() == null) {
+ lastExecutionOutputFiles = outputFilesSnapshotter.emptySnapshot();
+ } else {
+ lastExecutionOutputFiles = previousExecution.getOutputFilesSnapshot();
+ }
+ FileCollectionSnapshot newOutputFiles = outputFilesBefore.changesSince(lastExecutionOutputFiles).applyTo(
+ lastExecutionOutputFiles, new ChangeListener<FileCollectionSnapshot.Merge>() {
+ public void added(FileCollectionSnapshot.Merge element) {
+ // Ignore added files
+ element.ignore();
+ }
+
+ public void removed(FileCollectionSnapshot.Merge element) {
+ // Discard any files removed since the task was last executed
+ }
+
+ public void changed(FileCollectionSnapshot.Merge element) {
+ // Update any files which were change since the task was last executed
+ }
+ });
+ FileCollectionSnapshot outputFilesAfter = outputFilesSnapshotter.snapshot(task.getOutputs().getFiles());
+ currentExecution.setOutputFilesSnapshot(outputFilesAfter.changesSince(outputFilesBefore).applyTo(newOutputFiles));
+ }
+ };
+ }
+
+ private static class ChangeListenerAdapter implements ChangeListener<String> {
+ public OutputFileChange lastChange;
+
+ public void added(String fileName) {
+ lastChange = new OutputFileChange(fileName, ChangeType.ADDED);
+ }
+
+ public void removed(String fileName) {
+ lastChange = new OutputFileChange(fileName, ChangeType.REMOVED);
+ }
+
+ public void changed(String fileName) {
+ lastChange = new OutputFileChange(fileName, ChangeType.MODIFIED);
+ }
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/SimpleTaskStateChanges.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/SimpleTaskStateChanges.java
new file mode 100644
index 0000000..a2488b1
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/SimpleTaskStateChanges.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.rules;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+abstract class SimpleTaskStateChanges implements TaskStateChanges {
+ private List<TaskStateChange> changes;
+
+ public Iterator<TaskStateChange> iterator() {
+ if (changes == null) {
+ changes = new ArrayList<TaskStateChange>();
+ addAllChanges(changes);
+ }
+ return changes.iterator();
+ }
+
+ protected abstract void addAllChanges(List<TaskStateChange> changes);
+
+ public void snapshotAfterTask() {
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/SummaryTaskStateChanges.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/SummaryTaskStateChanges.java
new file mode 100644
index 0000000..ba85d4b
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/SummaryTaskStateChanges.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.rules;
+
+import com.google.common.collect.AbstractIterator;
+
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+class SummaryTaskStateChanges implements TaskStateChanges {
+ private final int maxReportedChanges;
+ private final List<TaskStateChanges> sources;
+
+
+ public SummaryTaskStateChanges(int maxReportedChanges, TaskStateChanges... sources) {
+ this.maxReportedChanges = maxReportedChanges;
+ this.sources = Arrays.asList(sources);
+ }
+
+ /**
+ * Provides an efficient summary of the changes, without doing too much unnecessary work.
+ * - Will only emit changes of a single type (from a single delegate change set)
+ * - Will return no more than the specified maximum of number of changes
+ */
+ public Iterator<TaskStateChange> iterator() {
+
+ return new AbstractIterator<TaskStateChange>() {
+ Iterator<TaskStateChange> changes;
+ int count;
+
+ @Override
+ protected TaskStateChange computeNext() {
+ if (changes == null) {
+ changes = firstDirtyIterator();
+ }
+
+ if (count < maxReportedChanges && changes != null && changes.hasNext()) {
+ count++;
+ return changes.next();
+ }
+ return endOfData();
+ }
+ };
+ }
+
+ private Iterator<TaskStateChange> firstDirtyIterator() {
+ for (TaskStateChanges source : sources) {
+ Iterator<TaskStateChange> sourceIterator = source.iterator();
+ if (sourceIterator.hasNext()) {
+ return sourceIterator;
+ }
+ }
+ return null;
+ }
+
+ public void snapshotAfterTask() {
+ for (TaskStateChanges state : sources) {
+ state.snapshotAfterTask();
+ }
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/TaskStateChange.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/TaskStateChange.java
new file mode 100644
index 0000000..af2f2f4
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/TaskStateChange.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.rules;
+
+public interface TaskStateChange {
+ String getMessage();
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/TaskStateChanges.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/TaskStateChanges.java
new file mode 100644
index 0000000..d75a122
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/TaskStateChanges.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.rules;
+
+public interface TaskStateChanges extends Iterable<TaskStateChange> {
+ /**
+ * Snapshot any final state after the task has executed. This method is executed only if the task is to be executed.
+ * Any persistent state should be added to the {@link org.gradle.api.internal.changedetection.state.TaskExecution} object for the current execution.
+ */
+ void snapshotAfterTask();
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/TaskTypeStateChangeRule.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/TaskTypeStateChangeRule.java
new file mode 100644
index 0000000..182ce28
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/TaskTypeStateChangeRule.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.rules;
+
+import org.apache.commons.lang.StringUtils;
+import org.gradle.api.internal.TaskInternal;
+import org.gradle.api.internal.changedetection.state.TaskExecution;
+
+import java.util.List;
+
+/**
+ * A rule which detects changes in the task implementation class.
+ */
+class TaskTypeStateChangeRule {
+ public static TaskStateChanges create(final TaskInternal task, final TaskExecution previousExecution, final TaskExecution currentExecution) {
+ final String taskClass = task.getClass().getName();
+ currentExecution.setTaskClass(taskClass);
+
+ return new SimpleTaskStateChanges() {
+ @Override
+ protected void addAllChanges(List<TaskStateChange> changes) {
+ if (!taskClass.equals(previousExecution.getTaskClass())) {
+ changes.add(new DescriptiveChange("%s has changed type from '%s' to '%s'.",
+ StringUtils.capitalize(task.toString()), previousExecution.getTaskClass(), task.getClass().getName()));
+ }
+ }
+ };
+ }
+
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/TaskUpToDateState.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/TaskUpToDateState.java
new file mode 100644
index 0000000..15346e5
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/rules/TaskUpToDateState.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.rules;
+
+import org.gradle.api.internal.TaskInternal;
+import org.gradle.api.internal.changedetection.state.FileSnapshotter;
+import org.gradle.api.internal.changedetection.state.TaskExecution;
+import org.gradle.api.internal.changedetection.state.TaskHistoryRepository;
+
+/**
+ * Represents the complete changes in a tasks state
+ */
+public class TaskUpToDateState {
+ private static final int MAX_OUT_OF_DATE_MESSAGES = 3;
+
+ private TaskStateChanges noHistoryState;
+ private TaskStateChanges inputFilesState;
+ private TaskStateChanges inputPropertiesState;
+ private TaskStateChanges taskTypeState;
+ private TaskStateChanges outputFilesState;
+ private SummaryTaskStateChanges allTaskChanges;
+ private SummaryTaskStateChanges rebuildChanges;
+
+ public TaskUpToDateState(TaskInternal task, TaskHistoryRepository.History history, FileSnapshotter outputFilesSnapshotter, FileSnapshotter inputFilesSnapshotter) {
+ TaskExecution thisExecution = history.getCurrentExecution();
+ TaskExecution lastExecution = history.getPreviousExecution();
+
+ noHistoryState = NoHistoryStateChangeRule.create(task, lastExecution);
+ taskTypeState = TaskTypeStateChangeRule.create(task, lastExecution, thisExecution);
+ inputPropertiesState = InputPropertiesStateChangeRule.create(task, lastExecution, thisExecution);
+ outputFilesState = caching(OutputFilesStateChangeRule.create(task, lastExecution, thisExecution, outputFilesSnapshotter));
+ inputFilesState = caching(InputFilesStateChangeRule.create(task, lastExecution, thisExecution, inputFilesSnapshotter));
+ allTaskChanges = new SummaryTaskStateChanges(MAX_OUT_OF_DATE_MESSAGES, noHistoryState, taskTypeState, inputPropertiesState, outputFilesState, inputFilesState);
+ rebuildChanges = new SummaryTaskStateChanges(1, noHistoryState, taskTypeState, inputPropertiesState, outputFilesState);
+ }
+
+ private TaskStateChanges caching(TaskStateChanges wrapped) {
+ return new CachingTaskStateChanges(MAX_OUT_OF_DATE_MESSAGES, wrapped);
+ }
+
+ public TaskStateChanges getInputFilesChanges() {
+ return inputFilesState;
+ }
+
+ public TaskStateChanges getAllTaskChanges() {
+ return allTaskChanges;
+ }
+
+ public TaskStateChanges getRebuildChanges() {
+ return rebuildChanges;
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/CacheBackedFileSnapshotRepository.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/CacheBackedFileSnapshotRepository.java
new file mode 100644
index 0000000..fa95085
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/CacheBackedFileSnapshotRepository.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.state;
+
+import org.gradle.cache.PersistentIndexedCache;
+import org.gradle.internal.id.IdGenerator;
+import org.gradle.internal.id.RandomLongIdGenerator;
+
+public class CacheBackedFileSnapshotRepository implements FileSnapshotRepository {
+ private final PersistentIndexedCache<Long, FileCollectionSnapshot> cache;
+ private IdGenerator<Long> idGenerator = new RandomLongIdGenerator();
+
+ public CacheBackedFileSnapshotRepository(TaskArtifactStateCacheAccess cacheAccess, IdGenerator<Long> idGenerator) {
+ this.idGenerator = idGenerator;
+ cache = cacheAccess.createCache("fileSnapshots", Long.class, FileCollectionSnapshot.class, new FileSnapshotSerializer());
+ }
+
+ public Long add(FileCollectionSnapshot snapshot) {
+ Long id = idGenerator.generateId();
+ cache.put(id, snapshot);
+ return id;
+ }
+
+ public FileCollectionSnapshot get(Long id) {
+ return cache.get(id);
+ }
+
+ public void remove(Long id) {
+ cache.remove(id);
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/CacheBackedTaskHistoryRepository.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/CacheBackedTaskHistoryRepository.java
new file mode 100644
index 0000000..167b064
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/CacheBackedTaskHistoryRepository.java
@@ -0,0 +1,273 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.state;
+
+import org.gradle.api.internal.TaskInternal;
+import org.gradle.cache.PersistentIndexedCache;
+import org.gradle.internal.Factory;
+import org.gradle.messaging.serialize.*;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.util.*;
+
+public class CacheBackedTaskHistoryRepository implements TaskHistoryRepository {
+ private final TaskArtifactStateCacheAccess cacheAccess;
+ private final FileSnapshotRepository snapshotRepository;
+ private final PersistentIndexedCache<String, TaskHistory> taskHistoryCache;
+ private final TaskHistorySerializer serializer = new TaskHistorySerializer();
+
+ public CacheBackedTaskHistoryRepository(TaskArtifactStateCacheAccess cacheAccess, FileSnapshotRepository snapshotRepository) {
+ this.cacheAccess = cacheAccess;
+ this.snapshotRepository = snapshotRepository;
+ taskHistoryCache = cacheAccess.createCache("taskArtifacts", String.class, TaskHistory.class, serializer);
+ }
+
+ public History getHistory(final TaskInternal task) {
+ final TaskHistory history = loadHistory(task);
+ final LazyTaskExecution currentExecution = new LazyTaskExecution();
+ currentExecution.snapshotRepository = snapshotRepository;
+ currentExecution.cacheAccess = cacheAccess;
+ currentExecution.setOutputFiles(outputFiles(task));
+ final LazyTaskExecution previousExecution = findPreviousExecution(currentExecution, history);
+ if (previousExecution != null) {
+ previousExecution.snapshotRepository = snapshotRepository;
+ previousExecution.cacheAccess = cacheAccess;
+ }
+ history.configurations.add(0, currentExecution);
+
+ return new History() {
+ public TaskExecution getPreviousExecution() {
+ return previousExecution;
+ }
+
+ public TaskExecution getCurrentExecution() {
+ return currentExecution;
+ }
+
+ public void update() {
+ cacheAccess.useCache("Update task history", new Runnable() {
+ public void run() {
+ if (currentExecution.inputFilesSnapshotId == null && currentExecution.inputFilesSnapshot != null) {
+ currentExecution.inputFilesSnapshotId = snapshotRepository.add(currentExecution.inputFilesSnapshot);
+ }
+ if (currentExecution.outputFilesSnapshotId == null && currentExecution.outputFilesSnapshot != null) {
+ currentExecution.outputFilesSnapshotId = snapshotRepository.add(currentExecution.outputFilesSnapshot);
+ }
+ while (history.configurations.size() > TaskHistory.MAX_HISTORY_ENTRIES) {
+ LazyTaskExecution execution = history.configurations.remove(history.configurations.size() - 1);
+ if (execution.inputFilesSnapshotId != null) {
+ snapshotRepository.remove(execution.inputFilesSnapshotId);
+ }
+ if (execution.outputFilesSnapshotId != null) {
+ snapshotRepository.remove(execution.outputFilesSnapshotId);
+ }
+ }
+ taskHistoryCache.put(task.getPath(), history);
+ }
+ });
+ }
+ };
+ }
+
+ private TaskHistory loadHistory(final TaskInternal task) {
+ return cacheAccess.useCache("Load task history", new Factory<TaskHistory>() {
+ public TaskHistory create() {
+ ClassLoader original = serializer.getClassLoader();
+ serializer.setClassLoader(task.getClass().getClassLoader());
+ try {
+ TaskHistory history = taskHistoryCache.get(task.getPath());
+ return history == null ? new TaskHistory() : history;
+ } finally {
+ serializer.setClassLoader(original);
+ }
+ }
+ });
+ }
+
+ private static Set<String> outputFiles(TaskInternal task) {
+ Set<String> outputFiles = new HashSet<String>();
+ for (File file : task.getOutputs().getFiles()) {
+ outputFiles.add(file.getAbsolutePath());
+ }
+ return outputFiles;
+ }
+
+ private LazyTaskExecution findPreviousExecution(TaskExecution currentExecution, TaskHistory history) {
+ Set<String> outputFiles = currentExecution.getOutputFiles();
+ LazyTaskExecution bestMatch = null;
+ int bestMatchOverlap = 0;
+ for (LazyTaskExecution configuration : history.configurations) {
+ if (outputFiles.size() == 0) {
+ if (configuration.getOutputFiles().size() == 0) {
+ bestMatch = configuration;
+ break;
+ }
+ }
+
+ Set<String> intersection = new HashSet<String>(outputFiles);
+ intersection.retainAll(configuration.getOutputFiles());
+ if (intersection.size() > bestMatchOverlap) {
+ bestMatch = configuration;
+ bestMatchOverlap = intersection.size();
+ }
+ if (bestMatchOverlap == outputFiles.size()) {
+ break;
+ }
+ }
+ return bestMatch;
+ }
+
+ private static class TaskHistorySerializer implements Serializer<TaskHistory> {
+
+ private ClassLoader classLoader;
+
+ public TaskHistory read(Decoder decoder) throws Exception {
+ byte executions = decoder.readByte();
+ TaskHistory history = new TaskHistory();
+ LazyTaskExecution.TaskHistorySerializer executionSerializer = new LazyTaskExecution.TaskHistorySerializer(classLoader);
+ for (int i = 0; i < executions; i++) {
+ LazyTaskExecution exec = executionSerializer.read(decoder);
+ history.configurations.add(exec);
+ }
+ return history;
+ }
+
+ public void write(Encoder encoder, TaskHistory value) throws Exception {
+ int size = value.configurations.size();
+ encoder.writeByte((byte) size);
+ LazyTaskExecution.TaskHistorySerializer executionSerializer = new LazyTaskExecution.TaskHistorySerializer(classLoader);
+ for (LazyTaskExecution execution : value.configurations) {
+ executionSerializer.write(encoder, execution);
+ }
+ }
+
+ public ClassLoader getClassLoader() {
+ return classLoader;
+ }
+
+ public void setClassLoader(ClassLoader classLoader) {
+ this.classLoader = classLoader;
+ }
+ }
+
+ private static class TaskHistory {
+ private static final int MAX_HISTORY_ENTRIES = 3;
+ private final List<LazyTaskExecution> configurations = new ArrayList<LazyTaskExecution>();
+ }
+
+ //TODO SF extract & unit test
+ private static class LazyTaskExecution extends TaskExecution {
+ private Long inputFilesSnapshotId;
+ private Long outputFilesSnapshotId;
+ private transient FileSnapshotRepository snapshotRepository;
+ private transient FileCollectionSnapshot inputFilesSnapshot;
+ private transient FileCollectionSnapshot outputFilesSnapshot;
+ private transient TaskArtifactStateCacheAccess cacheAccess;
+
+ @Override
+ public FileCollectionSnapshot getInputFilesSnapshot() {
+ if (inputFilesSnapshot == null) {
+ inputFilesSnapshot = cacheAccess.useCache("fetch input files", new Factory<FileCollectionSnapshot>() {
+ public FileCollectionSnapshot create() {
+ return snapshotRepository.get(inputFilesSnapshotId);
+ }
+ });
+ }
+ return inputFilesSnapshot;
+ }
+
+ @Override
+ public void setInputFilesSnapshot(FileCollectionSnapshot inputFilesSnapshot) {
+ this.inputFilesSnapshot = inputFilesSnapshot;
+ this.inputFilesSnapshotId = null;
+ }
+
+ @Override
+ public FileCollectionSnapshot getOutputFilesSnapshot() {
+ if (outputFilesSnapshot == null) {
+ outputFilesSnapshot = cacheAccess.useCache("fetch output files", new Factory<FileCollectionSnapshot>() {
+ public FileCollectionSnapshot create() {
+ return snapshotRepository.get(outputFilesSnapshotId);
+ }
+ });
+ }
+ return outputFilesSnapshot;
+ }
+
+ @Override
+ public void setOutputFilesSnapshot(FileCollectionSnapshot outputFilesSnapshot) {
+ this.outputFilesSnapshot = outputFilesSnapshot;
+ outputFilesSnapshotId = null;
+ }
+
+ static class TaskHistorySerializer implements Serializer<LazyTaskExecution> {
+ private ClassLoader classLoader;
+
+ public TaskHistorySerializer(ClassLoader classLoader) {
+ this.classLoader = classLoader;
+ }
+
+ public LazyTaskExecution read(Decoder decoder) throws Exception {
+ LazyTaskExecution execution = new LazyTaskExecution();
+ execution.inputFilesSnapshotId = decoder.readLong();
+ execution.outputFilesSnapshotId = decoder.readLong();
+ execution.setTaskClass(decoder.readString());
+ int outputFiles = decoder.readInt();
+ Set<String> files = new HashSet<String>();
+ for (int j = 0; j < outputFiles; j++) {
+ files.add(decoder.readString());
+ }
+ execution.setOutputFiles(files);
+
+ int inputProperties = decoder.readInt();
+ if (inputProperties > 0) {
+ byte[] serializedMap = new byte[inputProperties];
+ decoder.readBytes(serializedMap);
+ DefaultSerializer<Map> defaultSerializer = new DefaultSerializer<Map>(classLoader);
+ Map<String, Object> map = defaultSerializer.read(new InputStreamBackedDecoder(new ByteArrayInputStream(serializedMap)));
+ execution.setInputProperties(map);
+ } else {
+ execution.setInputProperties(new HashMap<String, Object>());
+ }
+ return execution;
+ }
+
+ public void write(Encoder encoder, LazyTaskExecution execution) throws Exception {
+ encoder.writeLong(execution.inputFilesSnapshotId);
+ encoder.writeLong(execution.outputFilesSnapshotId);
+ encoder.writeString(execution.getTaskClass());
+ encoder.writeInt(execution.getOutputFiles().size());
+ for (String outputFile : execution.getOutputFiles()) {
+ encoder.writeString(outputFile);
+ }
+ if (execution.getInputProperties() == null) {
+ encoder.writeInt(0);
+ } else {
+ DefaultSerializer<Map> defaultSerializer = new DefaultSerializer<Map>(classLoader);
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ OutputStreamBackedEncoder propsEncoder = new OutputStreamBackedEncoder(outputStream);
+ defaultSerializer.write(propsEncoder, execution.getInputProperties());
+ propsEncoder.flush();
+ byte[] serializedMap = outputStream.toByteArray();
+ encoder.writeInt(serializedMap.length);
+ encoder.writeBytes(serializedMap);
+ }
+ }
+ }
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/CachingHasher.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/CachingHasher.java
new file mode 100644
index 0000000..f51b2e7
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/CachingHasher.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.state;
+
+import org.gradle.cache.PersistentIndexedCache;
+import org.gradle.messaging.serialize.Decoder;
+import org.gradle.messaging.serialize.Encoder;
+import org.gradle.messaging.serialize.Serializer;
+
+import java.io.File;
+import java.io.Serializable;
+
+public class CachingHasher implements Hasher {
+ private final PersistentIndexedCache<File, FileInfo> cache;
+ private final Hasher hasher;
+ private long timestamp;
+
+ public CachingHasher(Hasher hasher, TaskArtifactStateCacheAccess cacheAccess) {
+ this.hasher = hasher;
+ cache = cacheAccess.createCache("fileHashes", File.class, FileInfo.class, new FileInfoSerializer());
+ }
+
+ public byte[] hash(File file) {
+ FileInfo info = cache.get(file);
+
+ long length = file.length();
+ timestamp = file.lastModified();
+ if (info != null && length == info.length && timestamp == info.timestamp) {
+ return info.hash;
+ }
+
+ byte[] hash = hasher.hash(file);
+ cache.put(file, new FileInfo(hash, length, timestamp));
+ return hash;
+ }
+
+ public static class FileInfo implements Serializable {
+ private final byte[] hash;
+ private final long timestamp;
+ private final long length;
+
+ public FileInfo(byte[] hash, long length, long timestamp) {
+ this.hash = hash;
+ this.length = length;
+ this.timestamp = timestamp;
+ }
+ }
+
+ private static class FileInfoSerializer implements Serializer<FileInfo> {
+ public FileInfo read(Decoder decoder) throws Exception {
+ byte[] hash = decoder.readBinary();
+ long timestamp = decoder.readLong();
+ long length = decoder.readLong();
+ return new FileInfo(hash, length, timestamp);
+ }
+
+ public void write(Encoder encoder, FileInfo value) throws Exception {
+ encoder.writeBinary(value.hash);
+ encoder.writeLong(value.timestamp);
+ encoder.writeLong(value.length);
+ }
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/DefaultFileSnapshotter.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/DefaultFileSnapshotter.java
new file mode 100755
index 0000000..d4c6131
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/DefaultFileSnapshotter.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.state;
+
+import org.gradle.api.file.FileCollection;
+import org.gradle.api.internal.file.collections.SimpleFileCollection;
+import org.gradle.util.ChangeListener;
+import org.gradle.util.NoOpChangeListener;
+
+import java.io.File;
+import java.math.BigInteger;
+import java.util.*;
+
+public class DefaultFileSnapshotter implements FileSnapshotter {
+ private final Hasher hasher;
+ private TaskArtifactStateCacheAccess cacheAccess;
+
+ public DefaultFileSnapshotter(Hasher hasher, TaskArtifactStateCacheAccess cacheAccess) {
+ this.hasher = hasher;
+ this.cacheAccess = cacheAccess;
+ }
+
+ public FileCollectionSnapshot emptySnapshot() {
+ return new FileCollectionSnapshotImpl(new HashMap<String, FileSnapshot>());
+ }
+
+ public FileCollectionSnapshot snapshot(FileCollection sourceFiles) {
+ final Map<String, FileSnapshot> snapshots = new HashMap<String, FileSnapshot>();
+ final Set<File> theFiles = sourceFiles.getAsFileTree().getFiles();
+ cacheAccess.useCache("Create file snapshot", new Runnable() {
+ public void run() {
+ for (File file : theFiles) {
+ if (file.isFile()) {
+ snapshots.put(file.getAbsolutePath(), new FileHashSnapshot(hasher.hash(file)));
+ } else if (file.isDirectory()) {
+ snapshots.put(file.getAbsolutePath(), new DirSnapshot());
+ } else {
+ snapshots.put(file.getAbsolutePath(), new MissingFileSnapshot());
+ }
+ }
+ }
+ });
+ return new FileCollectionSnapshotImpl(snapshots);
+ }
+
+ static interface FileSnapshot {
+ boolean isUpToDate(FileSnapshot snapshot);
+ }
+
+ static class FileHashSnapshot implements FileSnapshot {
+ final byte[] hash;
+
+ public FileHashSnapshot(byte[] hash) {
+ this.hash = hash;
+ }
+
+ public boolean isUpToDate(FileSnapshot snapshot) {
+ if (!(snapshot instanceof FileHashSnapshot)) {
+ return false;
+ }
+
+ FileHashSnapshot other = (FileHashSnapshot) snapshot;
+ return Arrays.equals(hash, other.hash);
+ }
+
+ @Override
+ public String toString() {
+ return new BigInteger(1, hash).toString(16);
+ }
+ }
+
+ static class DirSnapshot implements FileSnapshot {
+ public boolean isUpToDate(FileSnapshot snapshot) {
+ return snapshot instanceof DirSnapshot;
+ }
+ }
+
+ static class MissingFileSnapshot implements FileSnapshot {
+ public boolean isUpToDate(FileSnapshot snapshot) {
+ return snapshot instanceof MissingFileSnapshot;
+ }
+ }
+
+ static class FileCollectionSnapshotImpl implements FileCollectionSnapshot {
+ final Map<String, FileSnapshot> snapshots;
+
+ public FileCollectionSnapshotImpl(Map<String, FileSnapshot> snapshots) {
+ this.snapshots = snapshots;
+ }
+
+ public FileCollection getFiles() {
+ List<File> files = new ArrayList<File>();
+ for (Map.Entry<String, FileSnapshot> entry : snapshots.entrySet()) {
+ if (entry.getValue() instanceof FileHashSnapshot) {
+ files.add(new File(entry.getKey()));
+ }
+ }
+ return new SimpleFileCollection(files);
+ }
+
+ public ChangeIterator<String> iterateChangesSince(FileCollectionSnapshot oldSnapshot) {
+ FileCollectionSnapshotImpl other = (FileCollectionSnapshotImpl) oldSnapshot;
+ final Map<String, FileSnapshot> otherSnapshots = new HashMap<String, FileSnapshot>(other.snapshots);
+ final Iterator<String> currentFiles = snapshots.keySet().iterator();
+
+ return new ChangeIterator<String>() {
+ private Iterator<String> removedFiles;
+
+ public boolean next(ChangeListener<String> listener) {
+ while (currentFiles.hasNext()) {
+ String currentFile = currentFiles.next();
+ FileSnapshot otherFile = otherSnapshots.remove(currentFile);
+
+ if (otherFile == null) {
+ listener.added(currentFile);
+ return true;
+ } else if (!snapshots.get(currentFile).isUpToDate(otherFile)) {
+ listener.changed(currentFile);
+ return true;
+ }
+ }
+
+ // Create a single iterator to use for all of the removed files
+ if (removedFiles == null) {
+ removedFiles = otherSnapshots.keySet().iterator();
+ }
+
+ if (removedFiles.hasNext()) {
+ listener.removed(removedFiles.next());
+ return true;
+ }
+
+ return false;
+ }
+ };
+ }
+
+ public Diff changesSince(final FileCollectionSnapshot oldSnapshot) {
+ final FileCollectionSnapshotImpl other = (FileCollectionSnapshotImpl) oldSnapshot;
+ return new Diff() {
+ public FileCollectionSnapshot applyTo(FileCollectionSnapshot snapshot) {
+ return applyTo(snapshot, new NoOpChangeListener<Merge>());
+ }
+
+ public FileCollectionSnapshot applyTo(FileCollectionSnapshot snapshot, final ChangeListener<Merge> listener) {
+ FileCollectionSnapshotImpl target = (FileCollectionSnapshotImpl) snapshot;
+ final Map<String, FileSnapshot> newSnapshots = new HashMap<String, FileSnapshot>(target.snapshots);
+ diff(snapshots, other.snapshots, new MapMergeChangeListener<String, FileSnapshot>(listener, newSnapshots));
+ return new FileCollectionSnapshotImpl(newSnapshots);
+ }
+ };
+ }
+
+ private void diff(Map<String, FileSnapshot> snapshots, Map<String, FileSnapshot> oldSnapshots,
+ ChangeListener<Map.Entry<String, FileSnapshot>> listener) {
+ Map<String, FileSnapshot> otherSnapshots = new HashMap<String, FileSnapshot>(oldSnapshots);
+ for (Map.Entry<String, FileSnapshot> entry : snapshots.entrySet()) {
+ FileSnapshot otherFile = otherSnapshots.remove(entry.getKey());
+ if (otherFile == null) {
+ listener.added(entry);
+ } else if (!entry.getValue().isUpToDate(otherFile)) {
+ listener.changed(entry);
+ }
+ }
+ for (Map.Entry<String, FileSnapshot> entry : otherSnapshots.entrySet()) {
+ listener.removed(entry);
+ }
+ }
+
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/DefaultFileSnapshotterSerializer.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/DefaultFileSnapshotterSerializer.java
new file mode 100644
index 0000000..777810b
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/DefaultFileSnapshotterSerializer.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.state;
+
+import org.gradle.messaging.serialize.Decoder;
+import org.gradle.messaging.serialize.Encoder;
+import org.gradle.messaging.serialize.Serializer;
+
+import java.util.HashMap;
+import java.util.Map;
+
+class DefaultFileSnapshotterSerializer implements Serializer<FileCollectionSnapshot> {
+ public FileCollectionSnapshot read(Decoder decoder) throws Exception {
+ Map<String, DefaultFileSnapshotter.FileSnapshot> snapshots = new HashMap<String, DefaultFileSnapshotter.FileSnapshot>();
+ DefaultFileSnapshotter.FileCollectionSnapshotImpl snapshot = new DefaultFileSnapshotter.FileCollectionSnapshotImpl(snapshots);
+ int snapshotsCount = decoder.readInt();
+ for (int i = 0; i < snapshotsCount; i++) {
+ String key = decoder.readString();
+ byte fileSnapshotKind = decoder.readByte();
+ if (fileSnapshotKind == 1) {
+ snapshots.put(key, new DefaultFileSnapshotter.DirSnapshot());
+ } else if (fileSnapshotKind == 2) {
+ snapshots.put(key, new DefaultFileSnapshotter.MissingFileSnapshot());
+ } else if (fileSnapshotKind == 3) {
+ byte hashSize = decoder.readByte();
+ byte[] hash = new byte[hashSize];
+ decoder.readBytes(hash);
+ snapshots.put(key, new DefaultFileSnapshotter.FileHashSnapshot(hash));
+ } else {
+ throw new RuntimeException("Unable to read serialized file collection snapshot. Unrecognized value found in the data stream.");
+ }
+ }
+ return snapshot;
+ }
+
+ public void write(Encoder encoder, FileCollectionSnapshot value) throws Exception {
+ DefaultFileSnapshotter.FileCollectionSnapshotImpl cached = (DefaultFileSnapshotter.FileCollectionSnapshotImpl) value;
+ encoder.writeInt(cached.snapshots.size());
+ for (String key : cached.snapshots.keySet()) {
+ encoder.writeString(key);
+ DefaultFileSnapshotter.FileSnapshot fileSnapshot = cached.snapshots.get(key);
+ if (fileSnapshot instanceof DefaultFileSnapshotter.DirSnapshot) {
+ encoder.writeByte((byte) 1);
+ } else if (fileSnapshot instanceof DefaultFileSnapshotter.MissingFileSnapshot) {
+ encoder.writeByte((byte) 2);
+ } else if (fileSnapshot instanceof DefaultFileSnapshotter.FileHashSnapshot) {
+ encoder.writeByte((byte) 3);
+ byte[] hash = ((DefaultFileSnapshotter.FileHashSnapshot) fileSnapshot).hash;
+ encoder.writeByte((byte) hash.length);
+ encoder.writeBytes(hash);
+ }
+ }
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/DefaultHasher.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/DefaultHasher.java
new file mode 100644
index 0000000..a9c9c57
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/DefaultHasher.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.state;
+
+import org.gradle.util.hash.HashUtil;
+
+import java.io.File;
+
+public class DefaultHasher implements Hasher {
+ public byte[] hash(File file) {
+ return HashUtil.createHash(file, "MD5").asByteArray();
+ }
+}
\ No newline at end of file
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/DefaultTaskArtifactStateCacheAccess.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/DefaultTaskArtifactStateCacheAccess.java
new file mode 100644
index 0000000..d120e81
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/DefaultTaskArtifactStateCacheAccess.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.state;
+
+import org.gradle.internal.Factory;
+import org.gradle.api.invocation.Gradle;
+import org.gradle.cache.CacheRepository;
+import org.gradle.cache.PersistentCache;
+import org.gradle.cache.PersistentIndexedCache;
+import org.gradle.messaging.serialize.Serializer;
+import org.gradle.cache.internal.FileLockManager;
+import org.gradle.listener.LazyCreationProxy;
+
+import java.io.File;
+
+public class DefaultTaskArtifactStateCacheAccess implements TaskArtifactStateCacheAccess {
+ private final Gradle gradle;
+ private final CacheRepository cacheRepository;
+ private PersistentCache cache;
+ private final Object lock = new Object();
+
+ public DefaultTaskArtifactStateCacheAccess(Gradle gradle, CacheRepository cacheRepository) {
+ this.gradle = gradle;
+ this.cacheRepository = cacheRepository;
+ }
+
+ private PersistentCache getCache() {
+ //TODO SF just do it in the constructor
+ synchronized (lock) {
+ if (cache == null) {
+ cache = cacheRepository
+ .cache("taskArtifacts")
+ .forObject(gradle)
+ .withDisplayName("task artifact state cache")
+ .withLockMode(FileLockManager.LockMode.Exclusive)
+ .open();
+ }
+ return cache;
+ }
+ }
+
+ public <K, V> PersistentIndexedCache<K, V> createCache(final String cacheName, final Class<K> keyType, final Class<V> valueType, final Serializer<V> valueSerializer) {
+ Factory<PersistentIndexedCache> factory = new Factory<PersistentIndexedCache>() {
+ public PersistentIndexedCache create() {
+ return getCache().createCache(cacheFile(cacheName), keyType, valueSerializer);
+ }
+ };
+ return new LazyCreationProxy<PersistentIndexedCache>(PersistentIndexedCache.class, factory).getSource();
+
+ }
+
+ private File cacheFile(String cacheName) {
+ return new File(getCache().getBaseDir(), cacheName + ".bin");
+ }
+
+ public <T> T useCache(String operationDisplayName, Factory<? extends T> action) {
+ return getCache().useCache(operationDisplayName, action);
+ }
+
+ public void useCache(String operationDisplayName, Runnable action) {
+ getCache().useCache(operationDisplayName, action);
+ }
+
+ public void longRunningOperation(String operationDisplayName, Runnable action) {
+ getCache().longRunningOperation(operationDisplayName, action);
+ }
+}
\ No newline at end of file
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/FileCollectionSnapshot.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/FileCollectionSnapshot.java
new file mode 100755
index 0000000..e5bbf38
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/FileCollectionSnapshot.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.state;
+
+import org.gradle.api.file.FileCollection;
+import org.gradle.util.ChangeListener;
+
+/**
+ * An immutable snapshot of the contents of a collection of files.
+ */
+public interface FileCollectionSnapshot {
+
+ ChangeIterator<String> iterateChangesSince(FileCollectionSnapshot oldSnapshot);
+
+ Diff changesSince(FileCollectionSnapshot oldSnapshot);
+
+ FileCollection getFiles();
+
+ public interface Diff {
+ /**
+ * Applies this diff to the given snapshot. Adds any added or changed files in this diff to the given snapshot.
+ * Removes any removed files in this diff from the given snapshot.
+ *
+ * @param snapshot the snapshot to apply the changes to.
+ * @param listener the listener to notify of changes. The listener can veto a particular change.
+ * @return an updated copy of the provided snapshot
+ */
+ FileCollectionSnapshot applyTo(FileCollectionSnapshot snapshot, ChangeListener<Merge> listener);
+
+ /**
+ * Applies this diff to the given snapshot. Adds any added or changed files in this diff to the given snapshot.
+ * Removes any removed files in this diff from the given snapshot.
+ *
+ * @param snapshot the snapshot to apply the changes to.
+ * @return an updated copy of the provided snapshot
+ */
+ FileCollectionSnapshot applyTo(FileCollectionSnapshot snapshot);
+ }
+
+ public interface Merge {
+ void ignore();
+ }
+
+ interface ChangeIterator<T> {
+ boolean next(ChangeListener<T> listener);
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/FileSnapshotRepository.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/FileSnapshotRepository.java
new file mode 100644
index 0000000..bd0fca2
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/FileSnapshotRepository.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.state;
+
+public interface FileSnapshotRepository {
+ FileCollectionSnapshot get(Long id);
+
+ Long add(FileCollectionSnapshot snapshot);
+
+ void remove(Long id);
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/FileSnapshotSerializer.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/FileSnapshotSerializer.java
new file mode 100644
index 0000000..33b3e1e
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/FileSnapshotSerializer.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.state;
+
+import org.gradle.messaging.serialize.Decoder;
+import org.gradle.messaging.serialize.Encoder;
+import org.gradle.messaging.serialize.Serializer;
+
+class FileSnapshotSerializer implements Serializer<FileCollectionSnapshot> {
+
+ private final DefaultFileSnapshotterSerializer defaultSnapshotSerializer = new DefaultFileSnapshotterSerializer();
+ private final OutputFilesSnapshotSerializer outputSnapshotSerializer = new OutputFilesSnapshotSerializer();
+
+ public FileCollectionSnapshot read(Decoder decoder) throws Exception {
+ byte kind = decoder.readByte();
+ if (kind == 1) {
+ return defaultSnapshotSerializer.read(decoder);
+ } else if (kind == 2) {
+ return outputSnapshotSerializer.read(decoder);
+ } else {
+ throw new RuntimeException("Unable to read from file snapshot cache. Unexpected value found in the data stream.");
+ }
+ }
+
+ public void write(Encoder encoder, FileCollectionSnapshot value) throws Exception {
+ if (value instanceof DefaultFileSnapshotter.FileCollectionSnapshotImpl) {
+ encoder.writeByte((byte) 1);
+ DefaultFileSnapshotter.FileCollectionSnapshotImpl cached = (DefaultFileSnapshotter.FileCollectionSnapshotImpl) value;
+ defaultSnapshotSerializer.write(encoder, cached);
+ } else if (value instanceof OutputFilesSnapshotter.OutputFilesSnapshot) {
+ encoder.writeByte((byte) 2);
+ OutputFilesSnapshotter.OutputFilesSnapshot cached = (OutputFilesSnapshotter.OutputFilesSnapshot) value;
+ outputSnapshotSerializer.write(encoder, cached);
+ } else {
+ throw new RuntimeException("Unable to write to file snapshot cache. Unexpected type to write: " + value);
+ }
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/FileSnapshotter.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/FileSnapshotter.java
new file mode 100755
index 0000000..92f26db
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/FileSnapshotter.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.state;
+
+import org.gradle.api.file.FileCollection;
+
+public interface FileSnapshotter {
+ /**
+ * Creates an empty snapshot, which changes can be later merged into.
+ *
+ * @return The snapshot.
+ */
+ FileCollectionSnapshot emptySnapshot();
+
+ /**
+ * Creates a snapshot of the contents of the given collection
+ *
+ * @param files The files to snapshot
+ * @return The snapshot.
+ */
+ FileCollectionSnapshot snapshot(FileCollection files);
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/Hasher.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/Hasher.java
new file mode 100644
index 0000000..8d1975f
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/Hasher.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.state;
+
+import java.io.File;
+
+public interface Hasher {
+ byte[] hash(File file);
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/MapMergeChangeListener.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/MapMergeChangeListener.java
new file mode 100644
index 0000000..bdd0917
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/MapMergeChangeListener.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.state;
+
+import org.gradle.util.ChangeListener;
+
+import java.util.Map;
+
+class MapMergeChangeListener<K, V> implements ChangeListener<Map.Entry<K, V>> {
+ private final ChangeListener<FileCollectionSnapshot.Merge> listener;
+ private final Map<K, V> newSnapshots;
+
+ public MapMergeChangeListener(ChangeListener<FileCollectionSnapshot.Merge> listener, Map<K, V> targetMap) {
+ this.listener = listener;
+ this.newSnapshots = targetMap;
+ }
+
+ public void added(Map.Entry<K, V> element) {
+ DefaultMerge merge = new DefaultMerge();
+ listener.added(merge);
+ if (!merge.isIgnore()) {
+ newSnapshots.put(element.getKey(), element.getValue());
+ }
+ }
+
+ public void removed(Map.Entry<K, V> element) {
+ DefaultMerge merge = new DefaultMerge();
+ listener.removed(merge);
+ if (!merge.isIgnore()) {
+ newSnapshots.remove(element.getKey());
+ }
+ }
+
+ public void changed(Map.Entry<K, V> element) {
+ DefaultMerge merge = new DefaultMerge();
+ listener.changed(merge);
+ if (!merge.isIgnore()) {
+ newSnapshots.put(element.getKey(), element.getValue());
+ }
+ }
+
+ private static class DefaultMerge implements FileCollectionSnapshot.Merge {
+ private boolean ignore;
+
+ public boolean isIgnore() {
+ return ignore;
+ }
+
+ public void ignore() {
+ ignore = true;
+ }
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/OutputFilesSnapshotSerializer.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/OutputFilesSnapshotSerializer.java
new file mode 100644
index 0000000..988cab9
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/OutputFilesSnapshotSerializer.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.state;
+
+import org.gradle.messaging.serialize.Decoder;
+import org.gradle.messaging.serialize.Encoder;
+import org.gradle.messaging.serialize.Serializer;
+
+import java.util.HashMap;
+import java.util.Map;
+
+class OutputFilesSnapshotSerializer implements Serializer<FileCollectionSnapshot> {
+
+ public FileCollectionSnapshot read(Decoder decoder) throws Exception {
+ Map<String, Long> rootFileIds = new HashMap<String, Long>();
+ int rootFileIdsCount = decoder.readInt();
+ for (int i = 0; i < rootFileIdsCount; i++) {
+ String key = decoder.readString();
+ boolean notNull = decoder.readBoolean();
+ Long value = notNull? decoder.readLong() : null;
+ rootFileIds.put(key, value);
+ }
+ FileSnapshotSerializer serializer = new FileSnapshotSerializer();
+ FileCollectionSnapshot snapshot = serializer.read(decoder);
+
+ return new OutputFilesSnapshotter.OutputFilesSnapshot(rootFileIds, snapshot);
+ }
+
+ public void write(Encoder encoder, FileCollectionSnapshot currentValue) throws Exception {
+ OutputFilesSnapshotter.OutputFilesSnapshot value = (OutputFilesSnapshotter.OutputFilesSnapshot) currentValue;
+ int rootFileIds = value.rootFileIds.size();
+ encoder.writeInt(rootFileIds);
+ for (String key : value.rootFileIds.keySet()) {
+ Long id = value.rootFileIds.get(key);
+ encoder.writeString(key);
+ if (id == null) {
+ encoder.writeBoolean(false);
+ } else {
+ encoder.writeBoolean(true);
+ encoder.writeLong(id);
+ }
+ }
+
+ FileSnapshotSerializer serializer = new FileSnapshotSerializer();
+ serializer.write(encoder, value.filesSnapshot);
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/OutputFilesSnapshotter.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/OutputFilesSnapshotter.java
new file mode 100644
index 0000000..2378429
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/OutputFilesSnapshotter.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.state;
+
+import org.gradle.api.file.FileCollection;
+import org.gradle.cache.PersistentIndexedCache;
+import org.gradle.internal.id.IdGenerator;
+import org.gradle.messaging.serialize.LongSerializer;
+import org.gradle.util.ChangeListener;
+import org.gradle.util.DiffUtil;
+import org.gradle.util.NoOpChangeListener;
+
+import java.io.File;
+import java.util.*;
+
+/**
+ * Takes a snapshot of the output files of a task. 2 parts to the algorithm:
+ *
+ * <ul>
+ * <li>Collect the unique id for each output file and directory. The unique id is generated when we notice that
+ * a file/directory has been created. The id is regenerated when the file/directory is deleted.</li>
+ *
+ * <li>Collect the hash of each output file and each file in each output directory.</li>
+ * </ul>
+ *
+ */
+public class OutputFilesSnapshotter implements FileSnapshotter {
+ private final FileSnapshotter snapshotter;
+ private final IdGenerator<Long> idGenerator;
+ private TaskArtifactStateCacheAccess cacheAccess;
+ private final PersistentIndexedCache<String, Long> dirIdentiferCache;
+
+ public OutputFilesSnapshotter(FileSnapshotter snapshotter, IdGenerator<Long> idGenerator,
+ TaskArtifactStateCacheAccess cacheAccess) {
+ this.snapshotter = snapshotter;
+ this.idGenerator = idGenerator;
+ this.cacheAccess = cacheAccess;
+ dirIdentiferCache = cacheAccess.createCache("outputFileStates", String.class, Long.class, new LongSerializer());
+ }
+
+ public FileCollectionSnapshot emptySnapshot() {
+ return new OutputFilesSnapshot(new HashMap<String, Long>(), snapshotter.emptySnapshot());
+ }
+
+ public OutputFilesSnapshot snapshot(final FileCollection files) {
+ final Map<String, Long> snapshotDirIds = new HashMap<String, Long>();
+ final Set<File> theFiles = files.getFiles();
+ cacheAccess.useCache("create dir snapshots", new Runnable() {
+ public void run() {
+ for (File file : theFiles) {
+ Long dirId;
+ if (file.exists()) {
+ dirId = dirIdentiferCache.get(file.getAbsolutePath());
+ if (dirId == null) {
+ dirId = idGenerator.generateId();
+ dirIdentiferCache.put(file.getAbsolutePath(), dirId);
+ }
+ } else {
+ dirIdentiferCache.remove(file.getAbsolutePath());
+ dirId = null;
+ }
+ snapshotDirIds.put(file.getAbsolutePath(), dirId);
+ }
+
+ }
+ });
+ return new OutputFilesSnapshot(snapshotDirIds, snapshotter.snapshot(files));
+ }
+
+ static class OutputFilesSnapshot implements FileCollectionSnapshot {
+ final Map<String, Long> rootFileIds;
+ final FileCollectionSnapshot filesSnapshot;
+
+ public OutputFilesSnapshot(Map<String, Long> rootFileIds, FileCollectionSnapshot filesSnapshot) {
+ this.rootFileIds = rootFileIds;
+ this.filesSnapshot = filesSnapshot;
+ }
+
+ public FileCollection getFiles() {
+ return filesSnapshot.getFiles();
+ }
+
+ public Diff changesSince(final FileCollectionSnapshot oldSnapshot) {
+ OutputFilesSnapshot other = (OutputFilesSnapshot) oldSnapshot;
+ return new OutputFilesDiff(rootFileIds, other.rootFileIds, filesSnapshot.changesSince(other.filesSnapshot));
+ }
+
+ public ChangeIterator<String> iterateChangesSince(FileCollectionSnapshot oldSnapshot) {
+ final OutputFilesSnapshot other = (OutputFilesSnapshot) oldSnapshot;
+ final ChangeIterator<String> rootFileIdIterator = iterateRootFileIdChanges(other);
+ final ChangeIterator<String> fileIterator = filesSnapshot.iterateChangesSince(other.filesSnapshot);
+
+ final AddIgnoreChangeListenerAdapter listenerAdapter = new AddIgnoreChangeListenerAdapter();
+ return new ChangeIterator<String>() {
+ public boolean next(final ChangeListener<String> listener) {
+ listenerAdapter.withDelegate(listener);
+ if (rootFileIdIterator.next(listener)) {
+ return true;
+ }
+
+ while (fileIterator.next(listenerAdapter)) {
+ if (!listenerAdapter.wasIgnored) {
+ return true;
+ }
+ }
+ return false;
+ }
+ };
+ }
+
+ private ChangeIterator<String> iterateRootFileIdChanges(final OutputFilesSnapshot other) {
+ // Inlining DiffUtil.diff makes the inefficiencies here a bit more explicit
+ Map<String, Long> added = new HashMap<String, Long>(rootFileIds);
+ added.keySet().removeAll(other.rootFileIds.keySet());
+ final Iterator<String> addedIterator = added.keySet().iterator();
+
+ Map<String, Long> removed = new HashMap<String, Long>(other.rootFileIds);
+ removed.keySet().removeAll(rootFileIds.keySet());
+ final Iterator<String> removedIterator = removed.keySet().iterator();
+
+ Set<String> changed = new HashSet<String>();
+ for (Map.Entry<String, Long> current : rootFileIds.entrySet()) {
+ // Only care about rootIds that used to exist, and have changed or been removed
+ Long otherValue = other.rootFileIds.get(current.getKey());
+ if (otherValue != null && !otherValue.equals(current.getValue())) {
+ changed.add(current.getKey());
+ }
+ }
+ final Iterator<String> changedIterator = changed.iterator();
+
+ return new ChangeIterator<String>() {
+ public boolean next(ChangeListener<String> listener) {
+ if (addedIterator.hasNext()) {
+ listener.added(addedIterator.next());
+ return true;
+ }
+ if (removedIterator.hasNext()) {
+ listener.removed(removedIterator.next());
+ return true;
+ }
+ if (changedIterator.hasNext()) {
+ listener.changed(changedIterator.next());
+ return true;
+ }
+
+ return false;
+ }
+ };
+ }
+ }
+
+ /**
+ * A flyweight wrapper that is used to ignore any added files called.
+ */
+ private static class AddIgnoreChangeListenerAdapter implements ChangeListener<String> {
+ private ChangeListener<String> delegate;
+ boolean wasIgnored;
+
+ private void withDelegate(ChangeListener<String> delegate) {
+ this.delegate = delegate;
+ }
+
+ public void added(String element) {
+ wasIgnored = true;
+ }
+
+ public void removed(String element) {
+ delegate.removed(element);
+ wasIgnored = false;
+ }
+
+ public void changed(String element) {
+ delegate.changed(element);
+ wasIgnored = false;
+ }
+ }
+
+ private static class OutputFilesDiff implements FileCollectionSnapshot.Diff {
+ private final Map<String, Long> newFileIds;
+ private final Map<String, Long> oldFileIds;
+ private final FileCollectionSnapshot.Diff filesDiff;
+
+ public OutputFilesDiff(Map<String, Long> newFileIds, Map<String, Long> oldFileIds,
+ FileCollectionSnapshot.Diff filesDiff) {
+ this.newFileIds = newFileIds;
+ this.oldFileIds = oldFileIds;
+ this.filesDiff = filesDiff;
+ }
+
+ public FileCollectionSnapshot applyTo(FileCollectionSnapshot snapshot,
+ ChangeListener<FileCollectionSnapshot.Merge> listener) {
+ OutputFilesSnapshot other = (OutputFilesSnapshot) snapshot;
+ Map<String, Long> dirIds = new HashMap<String, Long>(other.rootFileIds);
+ DiffUtil.diff(newFileIds, oldFileIds, new MapMergeChangeListener<String, Long>(
+ new NoOpChangeListener<FileCollectionSnapshot.Merge>(), dirIds));
+ return new OutputFilesSnapshot(newFileIds, filesDiff.applyTo(other.filesSnapshot, listener));
+ }
+
+ public FileCollectionSnapshot applyTo(FileCollectionSnapshot snapshot) {
+ return applyTo(snapshot, new NoOpChangeListener<FileCollectionSnapshot.Merge>());
+ }
+ }
+
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/TaskArtifactStateCacheAccess.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/TaskArtifactStateCacheAccess.java
new file mode 100644
index 0000000..82f36df
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/TaskArtifactStateCacheAccess.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.state;
+
+import org.gradle.internal.Factory;
+import org.gradle.cache.PersistentIndexedCache;
+import org.gradle.messaging.serialize.Serializer;
+
+public interface TaskArtifactStateCacheAccess {
+ /**
+ * Performs some work against the cache. Acquires exclusive locks the appropriate resources, so that the given action is the only
+ * action to execute across all processes (including this one). Releases the locks and all resources at the end of the action.
+ *
+ * <p>This method is re-entrant, so that an action can call back into this method.</p>
+ */
+ <T> T useCache(String operationDisplayName, Factory<? extends T> action);
+
+ /**
+ * Performs some work against the cache. Acquires exclusive locks the appropriate resources, so that the given action is the only
+ * action to execute across all processes (including this one). Releases the locks and all resources at the end of the action.
+ *
+ * <p>This method is re-entrant, so that an action can call back into this method.</p>
+ */
+ void useCache(String operationDisplayName, Runnable action);
+
+ /**
+ * Performs some long running operation. Releases all locks while the operation is running, and reacquires the locks at the end of
+ * the long running operation.
+ *
+ * <p>This method is re-entrant, so that an action can call back into this method.</p>
+ */
+ void longRunningOperation(String operationDisplayName, Runnable runnable);
+
+ <K, V> PersistentIndexedCache<K, V> createCache(String cacheName, Class<K> keyType, Class<V> valueType, Serializer<V> valueSerializer);
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/TaskExecution.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/TaskExecution.java
new file mode 100644
index 0000000..7d70ecb
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/TaskExecution.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.state;
+
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * The persistent state for a single task execution.
+ */
+public abstract class TaskExecution {
+ private String taskClass;
+ private Map<String, Object> inputProperties;
+ private Set<String> outputFiles;
+
+ public Set<String> getOutputFiles() {
+ return outputFiles;
+ }
+
+ public void setOutputFiles(Set<String> outputFiles) {
+ this.outputFiles = outputFiles;
+ }
+
+ public String getTaskClass() {
+ return taskClass;
+ }
+
+ public void setTaskClass(String taskClass) {
+ this.taskClass = taskClass;
+ }
+
+ public Map<String, Object> getInputProperties() {
+ return inputProperties;
+ }
+
+ public void setInputProperties(Map<String, Object> inputProperties) {
+ this.inputProperties = inputProperties;
+ }
+
+ /**
+ * @return May return null.
+ */
+ public abstract FileCollectionSnapshot getOutputFilesSnapshot();
+
+ public abstract void setOutputFilesSnapshot(FileCollectionSnapshot outputFilesSnapshot);
+
+ /**
+ * @return May return null.
+ */
+ public abstract FileCollectionSnapshot getInputFilesSnapshot();
+
+ public abstract void setInputFilesSnapshot(FileCollectionSnapshot inputFilesSnapshot);
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/TaskHistoryRepository.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/TaskHistoryRepository.java
new file mode 100644
index 0000000..4d6cfc9
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/changedetection/state/TaskHistoryRepository.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.state;
+
+import org.gradle.api.internal.TaskInternal;
+
+public interface TaskHistoryRepository {
+ History getHistory(TaskInternal task);
+
+ interface History {
+ TaskExecution getPreviousExecution();
+
+ TaskExecution getCurrentExecution();
+
+ void update();
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/classpath/DefaultModuleRegistry.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/classpath/DefaultModuleRegistry.java
index 0ba1e15..9edcde8 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/classpath/DefaultModuleRegistry.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/classpath/DefaultModuleRegistry.java
@@ -19,7 +19,7 @@ import org.gradle.api.UncheckedIOException;
import org.gradle.api.internal.GradleDistributionLocator;
import org.gradle.internal.classpath.ClassPath;
import org.gradle.internal.classpath.DefaultClassPath;
-import org.gradle.util.ClasspathUtil;
+import org.gradle.internal.classloader.ClasspathUtil;
import org.gradle.util.GUtil;
import java.io.File;
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/classpath/EffectiveClassPath.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/classpath/EffectiveClassPath.java
index e95b9ed..fe14cc8 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/classpath/EffectiveClassPath.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/classpath/EffectiveClassPath.java
@@ -18,7 +18,7 @@ package org.gradle.api.internal.classpath;
import org.gradle.api.UncheckedIOException;
import org.gradle.internal.classpath.DefaultClassPath;
-import org.gradle.util.ClasspathUtil;
+import org.gradle.internal.classloader.ClasspathUtil;
import java.io.File;
import java.net.URI;
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/classpath/ManifestUtil.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/classpath/ManifestUtil.java
index 3c121c8..193f910 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/classpath/ManifestUtil.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/classpath/ManifestUtil.java
@@ -43,7 +43,6 @@ public class ManifestUtil {
return CollectionUtils.join(" ", paths);
}
- // TODO:DAZ The returned URI will only be relative if the file is contained in the jarfile directory. Otherwise, an absolute URI is returned.
private static String constructRelativeClasspathUri(File jarFile, File file) {
URI jarFileUri = jarFile.getParentFile().toURI();
URI fileUri = file.toURI();
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/coerce/MethodArgumentsTransformer.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/coerce/MethodArgumentsTransformer.java
new file mode 100644
index 0000000..54ad179
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/coerce/MethodArgumentsTransformer.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.coerce;
+
+/**
+ * Potentially transforms arguments to call a method with.
+ */
+public interface MethodArgumentsTransformer {
+
+ /**
+ * Transforms an argument list to call a method with.
+ *
+ * May return {@code args} if no transform is necessary.
+ *
+ * @param target The object to call the method on
+ * @param methodName The name of the method to call
+ * @param args The args to call the method with
+ * @return The args transformed, or args. Never null.
+ */
+ Object[] transform(Object target, String methodName, Object... args);
+
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/coerce/TypeCoercingMethodArgumentsTransformer.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/coerce/TypeCoercingMethodArgumentsTransformer.java
new file mode 100644
index 0000000..1d82229
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/coerce/TypeCoercingMethodArgumentsTransformer.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.coerce;
+
+import org.gradle.api.Transformer;
+import org.gradle.api.specs.Spec;
+import org.gradle.internal.reflect.JavaReflectionUtil;
+import org.gradle.util.CollectionUtils;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/*
+ This guy is hardcoded to just deal with coercing calls to one arg enum methods, from char sequence values.
+ It will need to be made pluggable as more coercions come online.
+
+ Also need to consider some caching in here as there's potentially a lot of repetitive reflection.
+ */
+public class TypeCoercingMethodArgumentsTransformer implements MethodArgumentsTransformer {
+
+ public Object[] transform(Object target, String methodName, Object... args) {
+ return maybeTransformForEnum(target, methodName, args);
+ }
+
+ private Object[] maybeTransformForEnum(Object target, final String methodName, Object... args) {
+ if (args.length != 1 || !(args[0] instanceof CharSequence)) {
+ return args;
+ }
+
+ final CharSequence charSequenceArg = (CharSequence) args[0];
+
+ final List<Method> enumMethodHolder = new ArrayList<Method>(2);
+ final List<Method> stringMethodHolder = new ArrayList<Method>(1);
+
+ JavaReflectionUtil.searchMethods(target.getClass(), new Transformer<Boolean, Method>() {
+ public Boolean transform(Method method) {
+ Class<?>[] parameterTypes = method.getParameterTypes();
+ if (method.getName().equals(methodName) && parameterTypes.length == 1) {
+ Class<?> parameterType = parameterTypes[0];
+
+ if (parameterType.isAssignableFrom(charSequenceArg.getClass())) {
+ stringMethodHolder.add(method);
+ return true; // stop searching
+ } else if (parameterType.isEnum()) {
+ enumMethodHolder.add(method);
+ if (enumMethodHolder.size() > 1) {
+ return true; // stop searching
+ }
+ }
+ }
+
+ return false;
+ }
+ });
+
+ // There's a method that takes the uncoerced type
+ if (!stringMethodHolder.isEmpty()) {
+ return args;
+ }
+
+ // There's either no enum method, or more than one
+ if (enumMethodHolder.size() != 1) {
+ return args;
+ }
+
+ // Match, we can try and coerce
+ Method match = enumMethodHolder.get(0);
+ @SuppressWarnings("unchecked")
+ Class<? extends Enum> enumType = (Class<? extends Enum>) match.getParameterTypes()[0];
+ return new Object[]{toEnumValue(enumType, charSequenceArg)};
+ }
+
+ private <T extends Enum<T>> T toEnumValue(Class<T> enumType, CharSequence charSequence) {
+ final String enumString = charSequence.toString();
+ List<T> enumConstants = Arrays.asList(enumType.getEnumConstants());
+ T match = CollectionUtils.findFirst(enumConstants, new Spec<T>() {
+ public boolean isSatisfiedBy(T enumValue) {
+ return enumValue.name().equalsIgnoreCase(enumString);
+ }
+ });
+
+ if (match == null) {
+ throw new TypeCoercionException(
+ String.format("Cannot coerce string value '%s' to an enum value of type '%s' (valid case insensitive values: %s)",
+ enumString, enumType.getName(), CollectionUtils.toStringList(Arrays.asList(enumType.getEnumConstants()))
+ )
+ );
+ } else {
+ return match;
+ }
+ }
+
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/coerce/TypeCoercionException.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/coerce/TypeCoercionException.java
new file mode 100644
index 0000000..25a6be9
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/coerce/TypeCoercionException.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.coerce;
+
+import org.gradle.api.GradleException;
+
+// TODO - this is usually a user error, might need a better name
+public class TypeCoercionException extends GradleException {
+
+ public TypeCoercionException(String message) {
+ super(message);
+ }
+
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/AbstractFileResolver.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/AbstractFileResolver.java
index c43f0bd..6e102db 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/AbstractFileResolver.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/AbstractFileResolver.java
@@ -52,6 +52,10 @@ public abstract class AbstractFileResolver implements FileResolver {
return new BaseDirFileResolver(fileSystem, resolve(path));
}
+ public FileResolver withNoBaseDir() {
+ return new IdentityFileResolver(fileSystem);
+ }
+
public File resolve(Object path) {
return resolve(path, PathValidation.NONE);
}
@@ -244,6 +248,10 @@ public abstract class AbstractFileResolver implements FileResolver {
return resolveFiles(paths).getAsFileTree();
}
+ public FileTree compositeFileTree(List<FileTree> fileTrees) {
+ return new DefaultCompositeFileTree(fileTrees);
+ }
+
public ReadableResource resolveResource(Object path) {
if (path instanceof ReadableResource) {
return (ReadableResource) path;
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/AbstractFileResource.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/AbstractFileResource.java
index 2bc0f45..731611a 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/AbstractFileResource.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/AbstractFileResource.java
@@ -21,9 +21,6 @@ import org.gradle.api.resources.ReadableResource;
import java.io.File;
import java.net.URI;
-/**
- * by Szczepan Faber, created at: 11/23/11
- */
public abstract class AbstractFileResource implements ReadableResource {
protected final File file;
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/AntFileCollectionBuilder.groovy b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/AntFileCollectionBuilder.groovy
index f7d47cf..931fee7 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/AntFileCollectionBuilder.groovy
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/AntFileCollectionBuilder.groovy
@@ -16,12 +16,9 @@
package org.gradle.api.internal.file
-import org.gradle.api.tasks.AntBuilderAware
import org.gradle.api.file.FileCollection
+import org.gradle.api.tasks.AntBuilderAware
-/**
- * @author Hans Dockter
- */
class AntFileCollectionBuilder implements AntBuilderAware {
private final FileCollection files
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/BaseDirFileResolver.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/BaseDirFileResolver.java
index 49c4394..e67d58c 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/BaseDirFileResolver.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/BaseDirFileResolver.java
@@ -26,9 +26,6 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-/**
- * @author Hans Dockter
- */
public class BaseDirFileResolver extends AbstractFileResolver {
private final File baseDir;
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/CopyActionProcessingStreamAction.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/CopyActionProcessingStreamAction.java
new file mode 100644
index 0000000..a8fb36c
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/CopyActionProcessingStreamAction.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.file;
+
+import org.gradle.api.internal.file.copy.FileCopyDetailsInternal;
+
+public interface CopyActionProcessingStreamAction {
+
+ void processFile(FileCopyDetailsInternal details);
+
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/DefaultCompositeFileTree.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/DefaultCompositeFileTree.java
new file mode 100644
index 0000000..19aa306
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/DefaultCompositeFileTree.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.file;
+
+import org.gradle.api.file.FileTree;
+import org.gradle.api.internal.file.collections.FileCollectionResolveContext;
+
+import java.util.List;
+
+public class DefaultCompositeFileTree extends CompositeFileTree {
+ private final List<FileTree> fileTrees;
+
+ public DefaultCompositeFileTree(List<FileTree> fileTrees) {
+ this.fileTrees = fileTrees;
+ }
+
+ @Override
+ public void resolve(FileCollectionResolveContext context) {
+ context.add(fileTrees);
+ }
+
+ @Override
+ protected List<FileTree> getSourceCollections() {
+ return fileTrees;
+ }
+
+ @Override
+ public String getDisplayName() {
+ return "file tree";
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/DefaultFileOperations.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/DefaultFileOperations.java
index 7a19cbf..a370a9e 100755
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/DefaultFileOperations.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/DefaultFileOperations.java
@@ -16,20 +16,26 @@
package org.gradle.api.internal.file;
import groovy.lang.Closure;
+import org.gradle.api.Action;
import org.gradle.api.InvalidUserDataException;
import org.gradle.api.PathValidation;
import org.gradle.api.file.*;
+import org.gradle.api.internal.ClosureBackedAction;
import org.gradle.api.internal.ProcessOperations;
import org.gradle.api.internal.file.archive.TarFileTree;
import org.gradle.api.internal.file.archive.ZipFileTree;
import org.gradle.api.internal.file.collections.DefaultConfigurableFileCollection;
import org.gradle.api.internal.file.collections.DefaultConfigurableFileTree;
import org.gradle.api.internal.file.collections.FileTreeAdapter;
-import org.gradle.api.internal.file.copy.*;
+import org.gradle.api.internal.file.copy.CopySpecInternal;
+import org.gradle.api.internal.file.copy.DefaultCopySpec;
+import org.gradle.api.internal.file.copy.DeleteActionImpl;
+import org.gradle.api.internal.file.copy.FileCopier;
import org.gradle.api.internal.resources.DefaultResourceHandler;
import org.gradle.api.internal.tasks.TaskResolver;
import org.gradle.api.resources.ReadableResource;
import org.gradle.api.tasks.WorkResult;
+import org.gradle.internal.reflect.Instantiator;
import org.gradle.process.ExecResult;
import org.gradle.process.internal.DefaultExecAction;
import org.gradle.process.internal.DefaultJavaExecAction;
@@ -49,13 +55,15 @@ public class DefaultFileOperations implements FileOperations, ProcessOperations
private final FileResolver fileResolver;
private final TaskResolver taskResolver;
private final TemporaryFileProvider temporaryFileProvider;
+ private final Instantiator instantiator;
private DeleteAction deleteAction;
private final DefaultResourceHandler resourceHandler;
- public DefaultFileOperations(FileResolver fileResolver, TaskResolver taskResolver, TemporaryFileProvider temporaryFileProvider) {
+ public DefaultFileOperations(FileResolver fileResolver, TaskResolver taskResolver, TemporaryFileProvider temporaryFileProvider, Instantiator instantiator) {
this.fileResolver = fileResolver;
this.taskResolver = taskResolver;
this.temporaryFileProvider = temporaryFileProvider;
+ this.instantiator = instantiator;
this.deleteAction = new DeleteActionImpl(fileResolver);
this.resourceHandler = new DefaultResourceHandler(fileResolver);
}
@@ -81,7 +89,7 @@ public class DefaultFileOperations implements FileOperations, ProcessOperations
}
public ConfigurableFileTree fileTree(Object baseDir) {
- return new DefaultConfigurableFileTree(baseDir, fileResolver, taskResolver);
+ return new DefaultConfigurableFileTree(baseDir, fileResolver, taskResolver, instantiator);
}
public ConfigurableFileTree fileTree(Object baseDir, Closure closure) {
@@ -89,12 +97,12 @@ public class DefaultFileOperations implements FileOperations, ProcessOperations
}
public ConfigurableFileTree fileTree(Map<String, ?> args) {
- return new DefaultConfigurableFileTree(args, fileResolver, taskResolver);
+ return new DefaultConfigurableFileTree(args, fileResolver, taskResolver, instantiator);
}
public ConfigurableFileTree fileTree(Closure closure) {
// This method is deprecated, but the deprecation warning is added on public classes that delegate to this.
- return configure(closure, new DefaultConfigurableFileTree(Collections.emptyMap(), fileResolver, taskResolver));
+ return configure(closure, new DefaultConfigurableFileTree(Collections.emptyMap(), fileResolver, taskResolver, instantiator));
}
public FileTree zipTree(Object zipPath) {
@@ -130,13 +138,23 @@ public class DefaultFileOperations implements FileOperations, ProcessOperations
}
public WorkResult copy(Closure closure) {
- CopyActionImpl action = configure(closure, new FileCopyActionImpl(fileResolver, new FileCopySpecVisitor()));
- action.execute();
- return action;
+ FileCopier copyAction = new FileCopier(instantiator, fileResolver);
+ return copyAction.copy(new ClosureBackedAction<CopySpec>(closure));
}
- public CopySpec copySpec(Closure closure) {
- return configure(closure, new CopySpecImpl(fileResolver));
+ public WorkResult sync(Action<? super CopySpec> action) {
+ FileCopier copyAction = new FileCopier(instantiator, fileResolver);
+ return copyAction.sync(action);
+ }
+
+ public CopySpecInternal copySpec(Closure closure) {
+ return copySpec(new ClosureBackedAction<CopySpec>(closure));
+ }
+
+ public CopySpecInternal copySpec(Action<? super CopySpec> action) {
+ DefaultCopySpec copySpec = instantiator.newInstance(DefaultCopySpec.class, fileResolver, instantiator);
+ action.execute(copySpec);
+ return copySpec;
}
public FileResolver getFileResolver() {
@@ -152,12 +170,12 @@ public class DefaultFileOperations implements FileOperations, ProcessOperations
}
public ExecResult javaexec(Closure cl) {
- JavaExecAction javaExecAction = ConfigureUtil.configure(cl, new DefaultJavaExecAction(fileResolver));
+ JavaExecAction javaExecAction = ConfigureUtil.configure(cl, instantiator.newInstance(DefaultJavaExecAction.class, fileResolver));
return javaExecAction.execute();
}
public ExecResult exec(Closure cl) {
- ExecAction execAction = ConfigureUtil.configure(cl, new DefaultExecAction(fileResolver));
+ ExecAction execAction = ConfigureUtil.configure(cl, instantiator.newInstance(DefaultExecAction.class, fileResolver));
return execAction.execute();
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/DefaultTemporaryFileProvider.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/DefaultTemporaryFileProvider.java
index 5e0d564..96311f5 100755
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/DefaultTemporaryFileProvider.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/DefaultTemporaryFileProvider.java
@@ -24,8 +24,9 @@ import org.gradle.util.GFileUtils;
import java.io.File;
import java.io.IOException;
+import java.io.Serializable;
-public class DefaultTemporaryFileProvider implements TemporaryFileProvider {
+public class DefaultTemporaryFileProvider implements TemporaryFileProvider, Serializable {
private final Factory<File> baseDirFactory;
public DefaultTemporaryFileProvider(final Factory<File> fileFactory) {
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/FileOperations.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/FileOperations.java
index 30ec18b..0197e27 100755
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/FileOperations.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/FileOperations.java
@@ -16,11 +16,13 @@
package org.gradle.api.internal.file;
import groovy.lang.Closure;
+import org.gradle.api.Action;
import org.gradle.api.PathValidation;
import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.file.ConfigurableFileTree;
import org.gradle.api.file.CopySpec;
import org.gradle.api.file.FileTree;
+import org.gradle.api.internal.file.copy.CopySpecInternal;
import org.gradle.api.resources.ResourceHandler;
import org.gradle.api.tasks.WorkResult;
@@ -58,8 +60,12 @@ public interface FileOperations {
CopySpec copySpec(Closure closure);
+ CopySpecInternal copySpec(Action<? super CopySpec> action);
+
WorkResult copy(Closure closure);
+ WorkResult sync(Action<? super CopySpec> action);
+
File mkdir(Object path);
boolean delete(Object... paths);
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/FileResolver.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/FileResolver.java
index 0d5c954..0f4eae7 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/FileResolver.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/FileResolver.java
@@ -24,6 +24,7 @@ import org.gradle.internal.Factory;
import java.io.File;
import java.net.URI;
+import java.util.List;
public interface FileResolver {
File resolve(Object path);
@@ -38,6 +39,8 @@ public interface FileResolver {
FileTree resolveFilesAsTree(Object... paths);
+ FileTree compositeFileTree(List<FileTree> fileTrees);
+
URI resolveUri(Object path);
String resolveAsRelativePath(Object path);
@@ -48,5 +51,10 @@ public interface FileResolver {
*/
FileResolver withBaseDir(Object path);
+ /**
+ * Creates a new resolver with no base directory.
+ */
+ FileResolver withNoBaseDir();
+
NotationParser<File> asNotationParser();
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/FileResource.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/FileResource.java
index 55c0a62..35472cf 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/FileResource.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/FileResource.java
@@ -21,9 +21,6 @@ import org.gradle.api.resources.MissingResourceException;
import java.io.*;
-/**
- * by Szczepan Faber, created at: 11/22/11
- */
public class FileResource extends AbstractFileResource {
public FileResource(File file) {
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/IdentityFileResolver.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/IdentityFileResolver.java
index 3f1068d..8cfc63c 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/IdentityFileResolver.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/IdentityFileResolver.java
@@ -15,6 +15,7 @@
*/
package org.gradle.api.internal.file;
+import org.gradle.internal.nativeplatform.filesystem.FileSystem;
import org.gradle.internal.nativeplatform.filesystem.FileSystems;
import java.io.File;
@@ -22,14 +23,16 @@ import java.io.File;
/**
* FileResolver that uses the file provided to it or constructs one from the toString of the provided object. Used in cases where a FileResolver is needed by the infrastructure, but no base directory
* can be known.
- *
- * @author Steve Appling
*/
public class IdentityFileResolver extends AbstractFileResolver {
public IdentityFileResolver() {
super(FileSystems.getDefault());
}
+ public IdentityFileResolver(FileSystem fileSystem) {
+ super(fileSystem);
+ }
+
@Override
protected File doResolve(Object path) {
File file = convertObjectToFile(path);
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/MaybeCompressedFileResource.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/MaybeCompressedFileResource.java
index cbc1a15..27fee31 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/MaybeCompressedFileResource.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/MaybeCompressedFileResource.java
@@ -26,9 +26,6 @@ import org.gradle.api.tasks.bundling.Compression;
import java.io.InputStream;
import java.net.URI;
-/**
- * by Szczepan Faber, created at: 11/23/11
- */
public class MaybeCompressedFileResource implements ReadableResource {
private final ReadableResource resource;
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/archive/TarCopyAction.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/archive/TarCopyAction.java
new file mode 100644
index 0000000..b00d7c8
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/archive/TarCopyAction.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.file.archive;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.tools.tar.TarEntry;
+import org.apache.tools.tar.TarOutputStream;
+import org.apache.tools.zip.UnixStat;
+import org.gradle.api.GradleException;
+import org.gradle.api.file.FileCopyDetails;
+import org.gradle.api.internal.file.CopyActionProcessingStreamAction;
+import org.gradle.api.internal.file.archive.compression.ArchiveOutputStreamFactory;
+import org.gradle.api.internal.file.copy.CopyAction;
+import org.gradle.api.internal.file.copy.CopyActionProcessingStream;
+import org.gradle.api.internal.file.copy.FileCopyDetailsInternal;
+import org.gradle.api.internal.tasks.SimpleWorkResult;
+import org.gradle.api.tasks.WorkResult;
+import org.gradle.internal.UncheckedException;
+
+import java.io.File;
+import java.io.OutputStream;
+
+public class TarCopyAction implements CopyAction {
+ private final File tarFile;
+ private final ArchiveOutputStreamFactory compressor;
+
+ public TarCopyAction(File tarFile, ArchiveOutputStreamFactory compressor) {
+ this.tarFile = tarFile;
+ this.compressor = compressor;
+ }
+
+ public WorkResult execute(CopyActionProcessingStream stream) {
+ final TarOutputStream tarOutStr;
+
+ OutputStream outStr;
+ try {
+ outStr = compressor.createArchiveOutputStream(tarFile);
+ } catch (Exception e) {
+ throw new GradleException(String.format("Could not create TAR '%s'.", tarFile), e);
+ }
+
+ try {
+ tarOutStr = new TarOutputStream(outStr);
+ } catch (Exception e) {
+ IOUtils.closeQuietly(outStr);
+ throw new GradleException(String.format("Could not create TAR '%s'.", tarFile), e);
+ }
+
+ tarOutStr.setLongFileMode(TarOutputStream.LONGFILE_GNU);
+
+ try {
+ stream.process(new StreamAction(tarOutStr));
+ } catch (Exception e) {
+ UncheckedException.throwAsUncheckedException(e);
+ } finally {
+ IOUtils.closeQuietly(tarOutStr);
+ }
+
+ return new SimpleWorkResult(true);
+ }
+
+ private class StreamAction implements CopyActionProcessingStreamAction {
+ private final TarOutputStream tarOutStr;
+
+ public StreamAction(TarOutputStream tarOutStr) {
+ this.tarOutStr = tarOutStr;
+ }
+
+ public void processFile(FileCopyDetailsInternal details) {
+ if (details.isDirectory()) {
+ visitDir(details);
+ } else {
+ visitFile(details);
+ }
+ }
+
+ private void visitFile(FileCopyDetails fileDetails) {
+ try {
+ TarEntry archiveEntry = new TarEntry(fileDetails.getRelativePath().getPathString());
+ archiveEntry.setModTime(fileDetails.getLastModified());
+ archiveEntry.setSize(fileDetails.getSize());
+ archiveEntry.setMode(UnixStat.FILE_FLAG | fileDetails.getMode());
+ tarOutStr.putNextEntry(archiveEntry);
+ fileDetails.copyTo(tarOutStr);
+ tarOutStr.closeEntry();
+ } catch (Exception e) {
+ throw new GradleException(String.format("Could not add %s to TAR '%s'.", fileDetails, tarFile), e);
+ }
+ }
+
+ private void visitDir(FileCopyDetails dirDetails) {
+ try {
+ // Trailing slash on name indicates entry is a directory
+ TarEntry archiveEntry = new TarEntry(dirDetails.getRelativePath().getPathString() + '/');
+ archiveEntry.setModTime(dirDetails.getLastModified());
+ archiveEntry.setMode(UnixStat.DIR_FLAG | dirDetails.getMode());
+ tarOutStr.putNextEntry(archiveEntry);
+ tarOutStr.closeEntry();
+ } catch (Exception e) {
+ throw new GradleException(String.format("Could not add %s to TAR '%s'.", dirDetails, tarFile), e);
+ }
+ }
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/archive/TarCopySpecVisitor.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/archive/TarCopySpecVisitor.java
deleted file mode 100644
index 506dc4c..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/archive/TarCopySpecVisitor.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.file.archive;
-
-import org.apache.tools.tar.TarEntry;
-import org.apache.tools.tar.TarOutputStream;
-import org.apache.tools.zip.UnixStat;
-import org.gradle.api.GradleException;
-import org.gradle.api.UncheckedIOException;
-import org.gradle.api.file.FileVisitDetails;
-import org.gradle.api.internal.file.copy.ArchiveCopyAction;
-import org.gradle.api.internal.file.copy.CopyAction;
-import org.gradle.api.internal.file.copy.EmptyCopySpecVisitor;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.OutputStream;
-
-public class TarCopySpecVisitor extends EmptyCopySpecVisitor {
- private TarOutputStream tarOutStr;
- private File tarFile;
-
- public void startVisit(CopyAction action) {
- ArchiveCopyAction archiveAction = (ArchiveCopyAction) action;
- try {
- tarFile = archiveAction.getArchivePath();
- OutputStream outStr = archiveAction.getCompressor().createArchiveOutputStream(tarFile);
- tarOutStr = new TarOutputStream(outStr);
- tarOutStr.setLongFileMode(TarOutputStream.LONGFILE_GNU);
- } catch (Exception e) {
- throw new GradleException(String.format("Could not create TAR '%s'.", tarFile), e);
- }
- }
-
- public void endVisit() {
- try {
- tarOutStr.close();
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- } finally {
- tarOutStr = null;
- }
- }
-
- public void visitFile(FileVisitDetails fileDetails) {
- try {
- TarEntry archiveEntry = new TarEntry(fileDetails.getRelativePath().getPathString());
- archiveEntry.setModTime(fileDetails.getLastModified());
- archiveEntry.setSize(fileDetails.getSize());
- archiveEntry.setMode(UnixStat.FILE_FLAG | fileDetails.getMode());
- tarOutStr.putNextEntry(archiveEntry);
- fileDetails.copyTo(tarOutStr);
- tarOutStr.closeEntry();
- } catch (Exception e) {
- throw new GradleException(String.format("Could not add %s to TAR '%s'.", fileDetails, tarFile), e);
- }
- }
-
- public void visitDir(FileVisitDetails dirDetails) {
- try {
- // Trailing slash on name indicates entry is a directory
- TarEntry archiveEntry = new TarEntry(dirDetails.getRelativePath().getPathString() + '/');
- archiveEntry.setModTime(dirDetails.getLastModified());
- archiveEntry.setMode(UnixStat.DIR_FLAG | dirDetails.getMode());
- tarOutStr.putNextEntry(archiveEntry);
- tarOutStr.closeEntry();
- } catch (Exception e) {
- throw new GradleException(String.format("Could not add %s to TAR '%s'.", dirDetails, tarFile), e);
- }
- }
-
- public boolean getDidWork() {
- return true;
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/archive/ZipCopyAction.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/archive/ZipCopyAction.java
index 14ebd22..cad830c 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/archive/ZipCopyAction.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/archive/ZipCopyAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2009 the original author or authors.
+ * Copyright 2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,10 +15,91 @@
*/
package org.gradle.api.internal.file.archive;
-import org.gradle.api.internal.file.copy.ArchiveCopyAction;
+import org.apache.commons.io.IOUtils;
+import org.apache.tools.zip.UnixStat;
+import org.apache.tools.zip.ZipEntry;
+import org.apache.tools.zip.ZipOutputStream;
+import org.gradle.api.GradleException;
+import org.gradle.api.file.FileCopyDetails;
+import org.gradle.api.internal.file.CopyActionProcessingStreamAction;
+import org.gradle.api.internal.file.copy.CopyAction;
+import org.gradle.api.internal.file.copy.CopyActionProcessingStream;
+import org.gradle.api.internal.file.copy.FileCopyDetailsInternal;
import org.gradle.api.internal.file.copy.ZipCompressor;
+import org.gradle.api.internal.tasks.SimpleWorkResult;
+import org.gradle.api.tasks.WorkResult;
+import org.gradle.internal.UncheckedException;
-public interface ZipCopyAction extends ArchiveCopyAction {
+import java.io.File;
- public ZipCompressor getCompressor();
+public class ZipCopyAction implements CopyAction {
+ private final File zipFile;
+ private final ZipCompressor compressor;
+
+ public ZipCopyAction(File zipFile, ZipCompressor compressor) {
+ this.zipFile = zipFile;
+ this.compressor = compressor;
+ }
+
+ public WorkResult execute(CopyActionProcessingStream stream) {
+ final ZipOutputStream zipOutStr;
+
+ try {
+ zipOutStr = compressor.createArchiveOutputStream(zipFile);
+ } catch (Exception e) {
+ throw new GradleException(String.format("Could not create ZIP '%s'.", zipFile), e);
+ }
+
+ try {
+ stream.process(new StreamAction(zipOutStr));
+ } catch (Exception e) {
+ UncheckedException.throwAsUncheckedException(e);
+ } finally {
+ IOUtils.closeQuietly(zipOutStr);
+ }
+
+ return new SimpleWorkResult(true);
+ }
+
+ private class StreamAction implements CopyActionProcessingStreamAction {
+ private final ZipOutputStream zipOutStr;
+
+ public StreamAction(ZipOutputStream zipOutStr) {
+ this.zipOutStr = zipOutStr;
+ }
+
+ public void processFile(FileCopyDetailsInternal details) {
+ if (details.isDirectory()) {
+ visitDir(details);
+ } else {
+ visitFile(details);
+ }
+ }
+
+ private void visitFile(FileCopyDetails fileDetails) {
+ try {
+ ZipEntry archiveEntry = new ZipEntry(fileDetails.getRelativePath().getPathString());
+ archiveEntry.setTime(fileDetails.getLastModified());
+ archiveEntry.setUnixMode(UnixStat.FILE_FLAG | fileDetails.getMode());
+ zipOutStr.putNextEntry(archiveEntry);
+ fileDetails.copyTo(zipOutStr);
+ zipOutStr.closeEntry();
+ } catch (Exception e) {
+ throw new GradleException(String.format("Could not add %s to ZIP '%s'.", fileDetails, zipFile), e);
+ }
+ }
+
+ private void visitDir(FileCopyDetails dirDetails) {
+ try {
+ // Trailing slash in name indicates that entry is a directory
+ ZipEntry archiveEntry = new ZipEntry(dirDetails.getRelativePath().getPathString() + '/');
+ archiveEntry.setTime(dirDetails.getLastModified());
+ archiveEntry.setUnixMode(UnixStat.DIR_FLAG | dirDetails.getMode());
+ zipOutStr.putNextEntry(archiveEntry);
+ zipOutStr.closeEntry();
+ } catch (Exception e) {
+ throw new GradleException(String.format("Could not add %s to ZIP '%s'.", dirDetails, zipFile), e);
+ }
+ }
+ }
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/archive/ZipCopySpecVisitor.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/archive/ZipCopySpecVisitor.java
deleted file mode 100644
index 1491f4b..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/archive/ZipCopySpecVisitor.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.file.archive;
-
-import org.apache.tools.zip.*;
-import org.gradle.api.GradleException;
-import org.gradle.api.UncheckedIOException;
-import org.gradle.api.internal.file.copy.CopyAction;
-import org.gradle.api.file.FileVisitDetails;
-import org.gradle.api.internal.file.copy.EmptyCopySpecVisitor;
-
-import java.io.File;
-import java.io.IOException;
-
-public class ZipCopySpecVisitor extends EmptyCopySpecVisitor {
- private ZipOutputStream zipOutStr;
- private File zipFile;
-
- public void startVisit(CopyAction action) {
- ZipCopyAction archiveAction = (ZipCopyAction) action;
- zipFile = archiveAction.getArchivePath();
- try {
- zipOutStr = archiveAction.getCompressor().createArchiveOutputStream(zipFile);
- } catch (Exception e) {
- throw new GradleException(String.format("Could not create ZIP '%s'.", zipFile), e);
- }
- }
-
- public void endVisit() {
- try {
- zipOutStr.close();
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- } finally {
- zipOutStr = null;
- }
- }
-
- public void visitFile(FileVisitDetails fileDetails) {
- try {
- ZipEntry archiveEntry = new ZipEntry(fileDetails.getRelativePath().getPathString());
- archiveEntry.setTime(fileDetails.getLastModified());
- archiveEntry.setUnixMode(UnixStat.FILE_FLAG | fileDetails.getMode());
- zipOutStr.putNextEntry(archiveEntry);
- fileDetails.copyTo(zipOutStr);
- zipOutStr.closeEntry();
- } catch (Exception e) {
- throw new GradleException(String.format("Could not add %s to ZIP '%s'.", fileDetails, zipFile), e);
- }
- }
-
- public void visitDir(FileVisitDetails dirDetails) {
- try {
- // Trailing slash in name indicates that entry is a directory
- ZipEntry archiveEntry = new ZipEntry(dirDetails.getRelativePath().getPathString() + '/');
- archiveEntry.setTime(dirDetails.getLastModified());
- archiveEntry.setUnixMode(UnixStat.DIR_FLAG | dirDetails.getMode());
- zipOutStr.putNextEntry(archiveEntry);
- zipOutStr.closeEntry();
- } catch (Exception e) {
- throw new GradleException(String.format("Could not add %s to ZIP '%s'.", dirDetails, zipFile), e);
- }
- }
-
- public boolean getDidWork() {
- return true;
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/archive/compression/Bzip2Archiver.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/archive/compression/Bzip2Archiver.java
index b923418..fb4f1d6 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/archive/compression/Bzip2Archiver.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/archive/compression/Bzip2Archiver.java
@@ -28,9 +28,6 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
-/**
- * by Szczepan Faber, created at: 11/16/11
- */
public class Bzip2Archiver implements ReadableResource {
private final ReadableResource resource;
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/archive/compression/GzipArchiver.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/archive/compression/GzipArchiver.java
index 619d812..4cef989 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/archive/compression/GzipArchiver.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/archive/compression/GzipArchiver.java
@@ -28,9 +28,6 @@ import java.net.URI;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
-/**
- * by Szczepan Faber, created at: 11/16/11
- */
public class GzipArchiver implements ReadableResource {
private ReadableResource resource;
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/archive/compression/SimpleCompressor.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/archive/compression/SimpleCompressor.java
index c47a5df..f886266 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/archive/compression/SimpleCompressor.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/archive/compression/SimpleCompressor.java
@@ -20,9 +20,6 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
-/**
- * by Szczepan Faber, created at: 11/16/11
- */
public class SimpleCompressor implements ArchiveOutputStreamFactory {
public OutputStream createArchiveOutputStream(File destination) {
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/collections/DefaultConfigurableFileTree.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/collections/DefaultConfigurableFileTree.java
index 21acdcf..ee9b559 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/collections/DefaultConfigurableFileTree.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/collections/DefaultConfigurableFileTree.java
@@ -16,21 +16,21 @@
package org.gradle.api.internal.file.collections;
import groovy.lang.Closure;
+import org.gradle.api.Action;
import org.gradle.api.InvalidUserDataException;
import org.gradle.api.file.ConfigurableFileTree;
+import org.gradle.api.file.CopySpec;
import org.gradle.api.file.FileTreeElement;
import org.gradle.api.internal.file.CompositeFileTree;
import org.gradle.api.internal.file.FileResolver;
-import org.gradle.api.internal.file.IdentityFileResolver;
-import org.gradle.api.internal.file.copy.CopyActionImpl;
-import org.gradle.api.internal.file.copy.FileCopyActionImpl;
-import org.gradle.api.internal.file.copy.FileCopySpecVisitor;
+import org.gradle.api.internal.file.copy.FileCopier;
import org.gradle.api.internal.tasks.DefaultTaskDependency;
import org.gradle.api.internal.tasks.TaskResolver;
import org.gradle.api.specs.Spec;
import org.gradle.api.tasks.TaskDependency;
import org.gradle.api.tasks.WorkResult;
import org.gradle.api.tasks.util.PatternSet;
+import org.gradle.internal.reflect.Instantiator;
import org.gradle.util.ConfigureUtil;
import java.io.File;
@@ -38,23 +38,22 @@ import java.util.Collections;
import java.util.Map;
import java.util.Set;
-/**
- * @author Hans Dockter
- */
public class DefaultConfigurableFileTree extends CompositeFileTree implements ConfigurableFileTree {
private PatternSet patternSet = new PatternSet();
private Object dir;
private final FileResolver resolver;
private final DefaultTaskDependency buildDependency;
+ private final Instantiator instantiator;
- public DefaultConfigurableFileTree(Object dir, FileResolver resolver, TaskResolver taskResolver) {
- this(Collections.singletonMap("dir", dir), resolver, taskResolver);
+ public DefaultConfigurableFileTree(Object dir, FileResolver resolver, TaskResolver taskResolver, Instantiator instantiator) {
+ this(Collections.singletonMap("dir", dir), resolver, taskResolver, instantiator);
}
- public DefaultConfigurableFileTree(Map<String, ?> args, FileResolver resolver, TaskResolver taskResolver) {
- this.resolver = resolver != null ? resolver : new IdentityFileResolver();
+ public DefaultConfigurableFileTree(Map<String, ?> args, FileResolver resolver, TaskResolver taskResolver, Instantiator instantiator) {
+ this.resolver = resolver;
ConfigureUtil.configureByMap(args, this);
buildDependency = new DefaultTaskDependency(taskResolver);
+ this.instantiator = instantiator;
}
public PatternSet getPatterns() {
@@ -82,12 +81,14 @@ public class DefaultConfigurableFileTree extends CompositeFileTree implements Co
return String.format("directory '%s'", dir);
}
- public WorkResult copy(Closure closure) {
- CopyActionImpl action = new FileCopyActionImpl(resolver, new FileCopySpecVisitor());
- action.from(this);
- ConfigureUtil.configure(closure, action);
- action.execute();
- return action;
+ public WorkResult copy(final Closure closure) {
+ FileCopier copyAction = new FileCopier(instantiator, resolver);
+ return copyAction.copy(new Action<CopySpec>() {
+ public void execute(CopySpec copySpec) {
+ copySpec.from(DefaultConfigurableFileTree.this);
+ ConfigureUtil.configure(closure, copySpec);
+ }
+ });
}
public Set<String> getIncludes() {
@@ -108,7 +109,7 @@ public class DefaultConfigurableFileTree extends CompositeFileTree implements Co
return this;
}
- public DefaultConfigurableFileTree include(String ... includes) {
+ public DefaultConfigurableFileTree include(String... includes) {
patternSet.include(includes);
return this;
}
@@ -128,7 +129,7 @@ public class DefaultConfigurableFileTree extends CompositeFileTree implements Co
return this;
}
- public DefaultConfigurableFileTree exclude(String ... excludes) {
+ public DefaultConfigurableFileTree exclude(String... excludes) {
patternSet.exclude(excludes);
return this;
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/collections/DelegatingFileCollection.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/collections/DelegatingFileCollection.java
new file mode 100644
index 0000000..ac291ce
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/collections/DelegatingFileCollection.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.file.collections;
+
+import groovy.lang.Closure;
+import org.gradle.api.file.FileCollection;
+import org.gradle.api.file.FileTree;
+import org.gradle.api.specs.Spec;
+import org.gradle.api.tasks.StopExecutionException;
+import org.gradle.api.tasks.TaskDependency;
+
+import java.io.File;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * A file collection that delegates each method call to the
+ * file collection returned by {@link #getDelegate()}.
+ */
+public abstract class DelegatingFileCollection implements FileCollection, MinimalFileSet {
+ public abstract FileCollection getDelegate();
+
+ public File getSingleFile() throws IllegalStateException {
+ return getDelegate().getSingleFile();
+ }
+
+ public Set<File> getFiles() {
+ return getDelegate().getFiles();
+ }
+
+ public boolean contains(File file) {
+ return getDelegate().contains(file);
+ }
+
+ public String getAsPath() {
+ return getDelegate().getAsPath();
+ }
+
+ public FileCollection plus(FileCollection collection) {
+ return getDelegate().plus(collection);
+ }
+
+ public FileCollection minus(FileCollection collection) {
+ return getDelegate().minus(collection);
+ }
+
+ public FileCollection filter(Closure filterClosure) {
+ return getDelegate().filter(filterClosure);
+ }
+
+ public FileCollection filter(Spec<? super File> filterSpec) {
+ return getDelegate().filter(filterSpec);
+ }
+
+ public Object asType(Class<?> type) throws UnsupportedOperationException {
+ return getDelegate().asType(type);
+ }
+
+ public FileCollection add(FileCollection collection) throws UnsupportedOperationException {
+ return getDelegate().add(collection);
+ }
+
+ public boolean isEmpty() {
+ return getDelegate().isEmpty();
+ }
+
+ public FileCollection stopExecutionIfEmpty() throws StopExecutionException {
+ return getDelegate().stopExecutionIfEmpty();
+ }
+
+ public FileTree getAsFileTree() {
+ return getDelegate().getAsFileTree();
+ }
+
+ public void addToAntBuilder(Object builder, String nodeName, AntType type) {
+ getDelegate().addToAntBuilder(builder, nodeName, type);
+ }
+
+ public Object addToAntBuilder(Object builder, String nodeName) {
+ return getDelegate().addToAntBuilder(builder, nodeName);
+ }
+
+ public TaskDependency getBuildDependencies() {
+ return getDelegate().getBuildDependencies();
+ }
+
+ public Iterator<File> iterator() {
+ return getDelegate().iterator();
+ }
+
+ public String getDisplayName() {
+ FileCollection delegate = getDelegate();
+ if (delegate instanceof MinimalFileSet) {
+ return ((MinimalFileSet) delegate).getDisplayName();
+ }
+ return getDelegate().toString();
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/collections/DirectoryFileTree.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/collections/DirectoryFileTree.java
index 157cb4e..8922388 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/collections/DirectoryFileTree.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/collections/DirectoryFileTree.java
@@ -43,8 +43,6 @@ import java.util.regex.Pattern;
*
* A file or directory will only be visited if it matches all includes and no
* excludes.
- *
- * @author Steve Appling
*/
public class DirectoryFileTree implements MinimalFileTree, PatternFilterableFileTree, RandomAccessFileCollection, LocalFileTree, DirectoryTree {
private static final Logger LOGGER = Logging.getLogger(DirectoryFileTree.class);
@@ -106,7 +104,7 @@ public class DirectoryFileTree implements MinimalFileTree, PatternFilterableFile
/**
* Process the specified file or directory. Note that the startFile parameter
- * may be either a directory or a file. If it is a directory, then it's contents
+ * may be either a directory or a file. If it is a directory, then its contents
* (but not the directory itself) will be checked with isAllowed and notified to
* the listener. If it is a file, the file will be checked and notified.
*/
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/collections/LazilyInitializedFileCollection.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/collections/LazilyInitializedFileCollection.java
new file mode 100644
index 0000000..cef9e92
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/collections/LazilyInitializedFileCollection.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.file.collections;
+
+import org.gradle.api.file.FileCollection;
+
+/**
+ * A {@link DelegatingFileCollection} whose delegate is created lazily.
+ */
+public abstract class LazilyInitializedFileCollection extends DelegatingFileCollection {
+ private FileCollection delegate;
+
+ public abstract FileCollection createDelegate();
+
+ @Override
+ public final synchronized FileCollection getDelegate() {
+ if (delegate == null) {
+ delegate = createDelegate();
+ }
+ return delegate;
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/collections/SingleIncludePatternFileTree.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/collections/SingleIncludePatternFileTree.java
index 04daa6e..f9d047d 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/collections/SingleIncludePatternFileTree.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/collections/SingleIncludePatternFileTree.java
@@ -59,7 +59,6 @@ public class SingleIncludePatternFileTree implements MinimalFileTree {
this.excludeSpec = excludeSpec;
}
- // TODO: important to visit files in prefix order? (contract says breadth-wise but probably means prefix.)
public void visit(FileVisitor visitor) {
doVisit(visitor, baseDir, new LinkedList<String>(), 0, new AtomicBoolean());
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/AbstractZipCompressor.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/AbstractZipCompressor.java
index 4d1667a..8dc5cda 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/AbstractZipCompressor.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/AbstractZipCompressor.java
@@ -15,6 +15,7 @@
*/
package org.gradle.api.internal.file.copy;
+import org.apache.tools.zip.Zip64Mode;
import org.apache.tools.zip.ZipOutputStream;
import org.gradle.api.UncheckedIOException;
@@ -27,6 +28,7 @@ abstract class AbstractZipCompressor implements ZipCompressor {
public ZipOutputStream createArchiveOutputStream(File destination) {
try {
ZipOutputStream outStream = new ZipOutputStream(destination);
+ outStream.setUseZip64(Zip64Mode.Never);
outStream.setMethod(getCompressedMethod());
return outStream;
} catch (Exception e) {
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/ArchiveCopyAction.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/ArchiveCopyAction.java
deleted file mode 100644
index bccdf42..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/ArchiveCopyAction.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.file.copy;
-
-import java.io.File;
-
-import org.gradle.api.internal.file.archive.compression.ArchiveOutputStreamFactory;
-
-public interface ArchiveCopyAction extends CopyAction {
- File getArchivePath();
- ArchiveOutputStreamFactory getCompressor();
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/CopyAction.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/CopyAction.java
index 5c3a686..55bdcac 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/CopyAction.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/CopyAction.java
@@ -1,25 +1,24 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.file.copy;
-
-import org.gradle.api.file.CopySpec;
-import org.gradle.api.tasks.WorkResult;
-
-/**
- * @author Steve Appling
- */
-public interface CopyAction extends CopySpec, WorkResult {
-}
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.file.copy;
+
+import org.gradle.api.tasks.WorkResult;
+
+public interface CopyAction {
+
+ public WorkResult execute(CopyActionProcessingStream stream);
+
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/CopyActionExecuter.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/CopyActionExecuter.java
new file mode 100644
index 0000000..fecd33f
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/CopyActionExecuter.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.file.copy;
+
+import org.gradle.api.tasks.WorkResult;
+import org.gradle.internal.nativeplatform.filesystem.FileSystem;
+import org.gradle.internal.reflect.Instantiator;
+
+public class CopyActionExecuter {
+
+ private final Instantiator instantiator;
+ private final FileSystem fileSystem;
+
+ public CopyActionExecuter(Instantiator instantiator, FileSystem fileSystem) {
+ this.instantiator = instantiator;
+ this.fileSystem = fileSystem;
+ }
+
+ public WorkResult execute(final CopySpecInternal spec, CopyAction action) {
+ final CopyAction effectiveVisitor = new DuplicateHandlingCopyActionDecorator(
+ new NormalizingCopyActionDecorator(action)
+ );
+
+ CopyActionProcessingStream processingStream = new CopySpecBackedCopyActionProcessingStream(spec, instantiator, fileSystem);
+ return effectiveVisitor.execute(processingStream);
+ }
+
+}
\ No newline at end of file
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/CopyActionImpl.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/CopyActionImpl.java
index 36bf5ce..b108479 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/CopyActionImpl.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/CopyActionImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2010 the original author or authors.
+ * Copyright 2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,233 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.gradle.api.internal.file.copy;
-
-import groovy.lang.Closure;
-import org.gradle.api.Action;
-import org.gradle.api.file.*;
-import org.gradle.api.internal.file.FileResolver;
-import org.gradle.api.specs.Spec;
-import org.gradle.internal.nativeplatform.filesystem.FileSystems;
-import java.io.FilterReader;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.regex.Pattern;
+package org.gradle.api.internal.file.copy;
/**
- * @author Steve Appling
+ * DO NOT REMOVE.
+ *
+ * Prior to 1.8, Copy leaked this as a parameter type on one of its methods.
+ * Has to exist to maintain binary compatibility.
*/
-public class CopyActionImpl implements CopyAction, CopySpecSource {
- private final CopySpecVisitor visitor;
- private final CopySpecImpl root;
- private final CopySpecImpl mainContent;
- private final FileResolver resolver;
-
- public CopyActionImpl(FileResolver resolver, CopySpecVisitor visitor) {
- this.resolver = resolver;
- root = new CopySpecImpl(resolver);
- mainContent = root.addChild();
- this.visitor = new MappingCopySpecVisitor(new NormalizingCopySpecVisitor(visitor), FileSystems.getDefault());
- }
-
- public FileResolver getResolver() {
- return resolver;
- }
-
- public CopySpecImpl getRootSpec() {
- return root;
- }
-
- public CopySpecImpl getMainSpec() {
- return mainContent;
- }
-
- public void execute() {
- visitor.startVisit(this);
- for (ReadableCopySpec spec : root.getAllSpecs()) {
- visitor.visitSpec(spec);
- spec.getSource().visit(visitor);
- }
- visitor.endVisit();
- }
-
- public boolean getDidWork() {
- return visitor.getDidWork();
- }
-
- public FileTree getAllSource() {
- List<FileTree> sources = new ArrayList<FileTree>();
- for (ReadableCopySpec spec : root.getAllSpecs()) {
- FileTree source = spec.getSource();
- sources.add(source);
- }
- return resolver.resolveFilesAsTree(sources);
- }
-
- public boolean hasSource() {
- return root.hasSource();
- }
-
- public CopySpec eachFile(Action<? super FileCopyDetails> action) {
- mainContent.eachFile(action);
- return this;
- }
-
- public CopySpec eachFile(Closure closure) {
- mainContent.eachFile(closure);
- return this;
- }
-
- public CopySpec exclude(Iterable<String> excludes) {
- mainContent.exclude(excludes);
- return this;
- }
-
- public CopySpec exclude(String... excludes) {
- mainContent.exclude(excludes);
- return this;
- }
-
- public CopySpec exclude(Closure excludeSpec) {
- mainContent.exclude(excludeSpec);
- return this;
- }
-
- public CopySpec exclude(Spec<FileTreeElement> excludeSpec) {
- mainContent.exclude(excludeSpec);
- return this;
- }
-
- public CopySpec expand(Map<String, ?> properties) {
- mainContent.expand(properties);
- return this;
- }
-
- public CopySpec filter(Closure closure) {
- mainContent.filter(closure);
- return this;
- }
-
- public CopySpec filter(Class<? extends FilterReader> filterType) {
- mainContent.filter(filterType);
- return this;
- }
-
- public CopySpec filter(Map<String, ?> properties, Class<? extends FilterReader> filterType) {
- mainContent.filter(properties, filterType);
- return this;
- }
-
- public CopySpec from(Object sourcePath, Closure c) {
- return mainContent.from(sourcePath, c);
- }
-
- public CopySpec from(Object... sourcePaths) {
- mainContent.from(sourcePaths);
- return this;
- }
-
- public Set<String> getExcludes() {
- return mainContent.getExcludes();
- }
-
- public Set<String> getIncludes() {
- return mainContent.getIncludes();
- }
-
- public CopySpec include(Iterable<String> includes) {
- mainContent.include(includes);
- return this;
- }
-
- public CopySpec include(String... includes) {
- mainContent.include(includes);
- return this;
- }
-
- public CopySpec include(Closure includeSpec) {
- mainContent.include(includeSpec);
- return this;
- }
-
- public CopySpec include(Spec<FileTreeElement> includeSpec) {
- mainContent.include(includeSpec);
- return this;
- }
-
- public CopySpec into(Object destDir) {
- mainContent.into(destDir);
- return this;
- }
-
- public CopySpec into(Object destPath, Closure configureClosure) {
- return mainContent.into(destPath, configureClosure);
- }
-
- public boolean isCaseSensitive() {
- return mainContent.isCaseSensitive();
- }
-
- public boolean getIncludeEmptyDirs() {
- return mainContent.getIncludeEmptyDirs();
- }
-
- public void setIncludeEmptyDirs(boolean includeEmptyDirs) {
- mainContent.setIncludeEmptyDirs(includeEmptyDirs);
- }
-
- public CopySpec rename(Closure closure) {
- mainContent.rename(closure);
- return this;
- }
-
- public CopySpec rename(Pattern sourceRegEx, String replaceWith) {
- mainContent.rename(sourceRegEx, replaceWith);
- return this;
- }
-
- public CopySpec rename(String sourceRegEx, String replaceWith) {
- mainContent.rename(sourceRegEx, replaceWith);
- return this;
- }
-
- public void setCaseSensitive(boolean caseSensitive) {
- mainContent.setCaseSensitive(caseSensitive);
- }
-
- public Integer getDirMode() {
- return mainContent.getDirMode();
- }
-
- public CopyProcessingSpec setDirMode(Integer mode) {
- mainContent.setDirMode(mode);
- return this;
- }
-
- public CopySpec setExcludes(Iterable<String> excludes) {
- mainContent.setExcludes(excludes);
- return this;
- }
-
- public Integer getFileMode() {
- return mainContent.getFileMode();
- }
-
- public CopyProcessingSpec setFileMode(Integer mode) {
- mainContent.setFileMode(mode);
- return this;
- }
-
- public CopySpec setIncludes(Iterable<String> includes) {
- mainContent.setIncludes(includes);
- return this;
- }
-
- public CopySpec with(CopySpec... copySpecs) {
- mainContent.with(copySpecs);
- return this;
- }
+ at SuppressWarnings("UnusedDeclaration")
+ at Deprecated
+public interface CopyActionImpl {
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/CopyActionProcessingStream.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/CopyActionProcessingStream.java
new file mode 100644
index 0000000..f94eab7
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/CopyActionProcessingStream.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.file.copy;
+
+import org.gradle.api.internal.file.CopyActionProcessingStreamAction;
+
+public interface CopyActionProcessingStream {
+
+ void process(CopyActionProcessingStreamAction action);
+
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/CopySpecBackedCopyActionProcessingStream.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/CopySpecBackedCopyActionProcessingStream.java
new file mode 100644
index 0000000..0306ad3
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/CopySpecBackedCopyActionProcessingStream.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.file.copy;
+
+import org.gradle.api.Action;
+import org.gradle.api.file.FileCopyDetails;
+import org.gradle.api.file.FileTree;
+import org.gradle.api.file.FileVisitDetails;
+import org.gradle.api.file.FileVisitor;
+import org.gradle.api.internal.file.CopyActionProcessingStreamAction;
+import org.gradle.internal.nativeplatform.filesystem.FileSystem;
+import org.gradle.internal.reflect.Instantiator;
+
+public class CopySpecBackedCopyActionProcessingStream implements CopyActionProcessingStream {
+
+ private final CopySpecInternal spec;
+ private final Instantiator instantiator;
+ private final FileSystem fileSystem;
+
+ public CopySpecBackedCopyActionProcessingStream(CopySpecInternal spec, Instantiator instantiator, FileSystem fileSystem) {
+ this.spec = spec;
+ this.instantiator = instantiator;
+ this.fileSystem = fileSystem;
+ }
+
+ public void process(final CopyActionProcessingStreamAction action) {
+ spec.walk(new Action<CopySpecInternal>() {
+ public void execute(final CopySpecInternal spec) {
+ FileTree source = spec.getSource();
+ source.visit(new FileVisitor() {
+ public void visitDir(FileVisitDetails dirDetails) {
+ visit(dirDetails);
+ }
+
+ public void visitFile(FileVisitDetails fileDetails) {
+ visit(fileDetails);
+ }
+
+ private void visit(FileVisitDetails visitDetails) {
+ DefaultFileCopyDetails details = instantiator.newInstance(DefaultFileCopyDetails.class, visitDetails, spec, fileSystem);
+ for (Action<? super FileCopyDetails> action : spec.getAllCopyActions()) {
+ action.execute(details);
+ if (details.isExcluded()) {
+ return;
+ }
+ }
+ action.processFile(details);
+ }
+ });
+ }
+ });
+
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/CopySpecImpl.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/CopySpecImpl.java
deleted file mode 100644
index 6d0d428..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/CopySpecImpl.java
+++ /dev/null
@@ -1,461 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.file.copy;
-
-import groovy.lang.Closure;
-import org.gradle.api.Action;
-import org.gradle.api.file.*;
-import org.gradle.api.internal.ChainingTransformer;
-import org.gradle.api.internal.ClosureBackedAction;
-import org.gradle.api.internal.file.FileResolver;
-import org.gradle.api.specs.Spec;
-import org.gradle.api.tasks.util.PatternSet;
-import org.gradle.util.ConfigureUtil;
-
-import java.io.File;
-import java.io.FilterReader;
-import java.util.*;
-import java.util.regex.Pattern;
-
-/**
- * @author Steve Appling
- */
-public class CopySpecImpl implements CopySpec, ReadableCopySpec {
- private final FileResolver resolver;
- private final Set<Object> sourcePaths;
- private Object destDir;
- private final PatternSet patternSet;
- private final List<ReadableCopySpec> childSpecs;
- private final CopySpecImpl parentSpec;
- private final List<Action<? super FileCopyDetails>> actions = new ArrayList<Action<? super FileCopyDetails>>();
- private Integer dirMode;
- private Integer fileMode;
- private Boolean caseSensitive;
- private Boolean includeEmptyDirs;
- private PathNotationParser<String> pathNotationParser;
-
- private CopySpecImpl(FileResolver resolver, CopySpecImpl parentSpec) {
- this.parentSpec = parentSpec;
- this.resolver = resolver;
- this.pathNotationParser = new PathNotationParser<String>();
- sourcePaths = new LinkedHashSet<Object>();
- childSpecs = new ArrayList<ReadableCopySpec>();
- patternSet = new PatternSet();
- }
-
- public CopySpecImpl(FileResolver resolver) {
- this(resolver, null);
- }
-
- protected FileResolver getResolver() {
- return resolver;
- }
-
- public CopySpec with(CopySpec... copySpecs) {
- for (CopySpec copySpec : copySpecs) {
- ReadableCopySpec readableCopySpec;
- if (copySpec instanceof CopySpecSource) {
- CopySpecSource copySpecSource = (CopySpecSource) copySpec;
- readableCopySpec = copySpecSource.getRootSpec();
- } else {
- readableCopySpec = (ReadableCopySpec) copySpec;
- }
- childSpecs.add(new WrapperCopySpec(this, readableCopySpec));
- }
- return this;
- }
-
- public CopySpec from(Object... sourcePaths) {
- for (Object sourcePath : sourcePaths) {
- this.sourcePaths.add(sourcePath);
- }
- return this;
- }
-
- public CopySpec from(Object sourcePath, Closure c) {
- if (c == null) {
- from(sourcePath);
- return this;
- } else {
- CopySpecImpl child = addChild();
- child.from(sourcePath);
- ConfigureUtil.configure(c, child);
- return child;
- }
- }
-
- public CopySpecImpl addFirst() {
- CopySpecImpl child = new CopySpecImpl(resolver, this);
- childSpecs.add(0, child);
- return child;
- }
-
- public CopySpecImpl addChild() {
- CopySpecImpl child = new CopySpecImpl(resolver, this);
- childSpecs.add(child);
- return child;
- }
-
- public Set<Object> getSourcePaths() {
- return sourcePaths;
- }
-
- public FileTree getSource() {
- return resolver.resolveFilesAsTree(sourcePaths).matching(getPatternSet());
- }
-
- public List<ReadableCopySpec> getAllSpecs() {
- List<ReadableCopySpec> result = new ArrayList<ReadableCopySpec>();
- result.add(this);
- for (ReadableCopySpec childSpec : childSpecs) {
- result.addAll(childSpec.getAllSpecs());
- }
- return result;
- }
-
- public CopySpecImpl into(Object destDir) {
- this.destDir = destDir;
- return this;
- }
-
- public CopySpecImpl into(Object destPath, Closure configureClosure) {
- if (configureClosure == null) {
- into(destPath);
- return this;
- } else {
- CopySpecImpl child = addChild();
- child.into(destPath);
- ConfigureUtil.configure(configureClosure, child);
- return child;
- }
- }
-
- public RelativePath getDestPath() {
- RelativePath parentPath;
- if (parentSpec == null) {
- parentPath = new RelativePath(false);
- } else {
- parentPath = parentSpec.getDestPath();
- }
- if (destDir == null) {
- return parentPath;
- }
-
- String path = resolveToPath(destDir);
- if (path.startsWith("/") || path.startsWith(File.separator)) {
- return RelativePath.parse(false, path);
- }
-
- return RelativePath.parse(false, parentPath, path);
- }
-
- private String resolveToPath(Object destDir) {
- return pathNotationParser.parseNotation(destDir);
- }
-
- public PatternSet getPatternSet() {
- PatternSet patterns = new PatternSet();
- patterns.setCaseSensitive(isCaseSensitive());
- patterns.include(getAllIncludes());
- patterns.includeSpecs(getAllIncludeSpecs());
- patterns.exclude(getAllExcludes());
- patterns.excludeSpecs(getAllExcludeSpecs());
- return patterns;
- }
-
- public boolean isCaseSensitive() {
- if (caseSensitive != null) {
- return caseSensitive;
- }
- if (parentSpec != null) {
- return parentSpec.isCaseSensitive();
- }
- return true;
- }
-
- public void setCaseSensitive(boolean caseSensitive) {
- this.caseSensitive = caseSensitive;
- }
-
- public boolean getIncludeEmptyDirs() {
- if (includeEmptyDirs != null) {
- return includeEmptyDirs;
- }
- if (parentSpec != null) {
- return parentSpec.getIncludeEmptyDirs();
- }
- return true;
- }
-
- public void setIncludeEmptyDirs(boolean includeEmptyDirs) {
- this.includeEmptyDirs = includeEmptyDirs;
- }
-
- public CopySpec include(String... includes) {
- patternSet.include(includes);
- return this;
- }
-
- public CopySpec include(Iterable<String> includes) {
- patternSet.include(includes);
- return this;
- }
-
- public CopySpec include(Spec<FileTreeElement> includeSpec) {
- patternSet.include(includeSpec);
- return this;
- }
-
- public CopySpec include(Closure includeSpec) {
- patternSet.include(includeSpec);
- return this;
- }
-
- public Set<String> getIncludes() {
- return patternSet.getIncludes();
- }
-
- public CopySpec setIncludes(Iterable<String> includes) {
- patternSet.setIncludes(includes);
- return this;
- }
-
- public List<String> getAllIncludes() {
- List<String> result = new ArrayList<String>();
- if (parentSpec != null) {
- result.addAll(parentSpec.getAllIncludes());
- }
- result.addAll(getIncludes());
- return result;
- }
-
- public List<Spec<FileTreeElement>> getAllIncludeSpecs() {
- List<Spec<FileTreeElement>> result = new ArrayList<Spec<FileTreeElement>>();
- if (parentSpec != null) {
- result.addAll(parentSpec.getAllIncludeSpecs());
- }
- result.addAll(patternSet.getIncludeSpecs());
- return result;
- }
-
- public CopySpec exclude(String... excludes) {
- patternSet.exclude(excludes);
- return this;
- }
-
- public CopySpec exclude(Iterable<String> excludes) {
- patternSet.exclude(excludes);
- return this;
- }
-
- public CopySpec exclude(Spec<FileTreeElement> excludeSpec) {
- patternSet.exclude(excludeSpec);
- return this;
- }
-
- public CopySpec exclude(Closure excludeSpec) {
- patternSet.exclude(excludeSpec);
- return this;
- }
-
- public Set<String> getExcludes() {
- return patternSet.getExcludes();
- }
-
- public CopySpecImpl setExcludes(Iterable<String> excludes) {
- patternSet.setExcludes(excludes);
- return this;
- }
-
- public CopySpec rename(String sourceRegEx, String replaceWith) {
- actions.add(new RenamingCopyAction(new RegExpNameMapper(sourceRegEx, replaceWith)));
- return this;
- }
-
- public CopySpec rename(Pattern sourceRegEx, String replaceWith) {
- actions.add(new RenamingCopyAction(new RegExpNameMapper(sourceRegEx, replaceWith)));
- return this;
- }
-
- public CopySpec filter(final Class<? extends FilterReader> filterType) {
- actions.add(new Action<FileCopyDetails>() {
- public void execute(FileCopyDetails fileCopyDetails) {
- fileCopyDetails.filter(filterType);
- }
- });
- return this;
- }
-
- public CopySpec filter(final Closure closure) {
- actions.add(new Action<FileCopyDetails>() {
- public void execute(FileCopyDetails fileCopyDetails) {
- fileCopyDetails.filter(closure);
- }
- });
- return this;
- }
-
- public CopySpec filter(final Map<String, ?> properties, final Class<? extends FilterReader> filterType) {
- actions.add(new Action<FileCopyDetails>() {
- public void execute(FileCopyDetails fileCopyDetails) {
- fileCopyDetails.filter(properties, filterType);
- }
- });
- return this;
- }
-
- public CopySpec expand(final Map<String, ?> properties) {
- actions.add(new Action<FileCopyDetails>() {
- public void execute(FileCopyDetails fileCopyDetails) {
- fileCopyDetails.expand(properties);
- }
- });
- return this;
- }
-
- public CopySpec rename(Closure closure) {
- ChainingTransformer<String> transformer = new ChainingTransformer<String>(String.class);
- transformer.add(closure);
- actions.add(new RenamingCopyAction(transformer));
- return this;
- }
-
- public Integer getDirMode() {
- if (dirMode != null) {
- return dirMode;
- }
- if (parentSpec != null) {
- return parentSpec.getDirMode();
- }
- return null;
- }
-
- public Integer getFileMode() {
- if (fileMode != null) {
- return fileMode;
- }
- if (parentSpec != null) {
- return parentSpec.getFileMode();
- }
- return null;
- }
-
- public CopyProcessingSpec setDirMode(Integer mode) {
- dirMode = mode;
- return this;
- }
-
- public CopyProcessingSpec setFileMode(Integer mode) {
- fileMode = mode;
- return this;
- }
-
- public CopySpec eachFile(Action<? super FileCopyDetails> action) {
- actions.add(action);
- return this;
- }
-
- public CopySpec eachFile(Closure closure) {
- actions.add(new ClosureBackedAction<FileCopyDetails>(closure));
- return this;
- }
-
- public List<String> getAllExcludes() {
- List<String> result = new ArrayList<String>();
- if (parentSpec != null) {
- result.addAll(parentSpec.getAllExcludes());
- }
- result.addAll(getExcludes());
- return result;
- }
-
- public List<Spec<FileTreeElement>> getAllExcludeSpecs() {
- List<Spec<FileTreeElement>> result = new ArrayList<Spec<FileTreeElement>>();
- if (parentSpec != null) {
- result.addAll(parentSpec.getAllExcludeSpecs());
- }
- result.addAll(patternSet.getExcludeSpecs());
- return result;
- }
-
- public List<Action<? super FileCopyDetails>> getAllCopyActions() {
- if (parentSpec == null) {
- return actions;
- }
- List<Action<? super FileCopyDetails>> allActions = new ArrayList<Action<? super FileCopyDetails>>();
- allActions.addAll(parentSpec.getAllCopyActions());
- allActions.addAll(actions);
- return allActions;
- }
-
- public boolean hasSource() {
- if (!sourcePaths.isEmpty()) {
- return true;
- }
- for (ReadableCopySpec spec : childSpecs) {
- if (spec.hasSource()) {
- return true;
- }
- }
- return false;
- }
-
- private static class WrapperCopySpec implements ReadableCopySpec {
- private final ReadableCopySpec root;
- private final ReadableCopySpec spec;
-
- public WrapperCopySpec(ReadableCopySpec root, ReadableCopySpec spec) {
- this.root = root;
- this.spec = spec;
- }
-
- public RelativePath getDestPath() {
- return root.getDestPath().append(spec.getDestPath());
- }
-
- public Integer getFileMode() {
- return spec.getFileMode();
- }
-
- public Integer getDirMode() {
- return spec.getDirMode();
- }
-
- public FileTree getSource() {
- return spec.getSource();
- }
-
- public Collection<? extends ReadableCopySpec> getAllSpecs() {
- List<WrapperCopySpec> specs = new ArrayList<WrapperCopySpec>();
- for (ReadableCopySpec child : spec.getAllSpecs()) {
- specs.add(new WrapperCopySpec(root, child));
- }
- return specs;
- }
-
- public boolean hasSource() {
- return spec.hasSource();
- }
-
- public Collection<? extends Action<? super FileCopyDetails>> getAllCopyActions() {
- return spec.getAllCopyActions();
- }
-
- public boolean getIncludeEmptyDirs() {
- return spec.getIncludeEmptyDirs();
- }
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/CopySpecInternal.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/CopySpecInternal.java
new file mode 100644
index 0000000..58ab4eb
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/CopySpecInternal.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.file.copy;
+
+import org.gradle.api.Action;
+import org.gradle.api.file.CopySpec;
+import org.gradle.api.file.FileCopyDetails;
+import org.gradle.api.file.FileTree;
+import org.gradle.api.file.RelativePath;
+
+import java.util.Collection;
+
+public interface CopySpecInternal extends CopySpec {
+
+ RelativePath getDestPath();
+
+ FileTree getSource();
+
+ FileTree getAllSource();
+
+ boolean hasSource();
+
+ Collection<? extends Action<? super FileCopyDetails>> getAllCopyActions();
+
+ Iterable<CopySpecInternal> getChildren();
+
+ void walk(Action<? super CopySpecInternal> action);
+
+ DefaultCopySpec addChild();
+
+ DefaultCopySpec addFirst();
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/CopySpecSource.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/CopySpecSource.java
index 38f27a2..381b9a9 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/CopySpecSource.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/CopySpecSource.java
@@ -16,5 +16,5 @@
package org.gradle.api.internal.file.copy;
public interface CopySpecSource {
- ReadableCopySpec getRootSpec();
+ CopySpecInternal getRootSpec();
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/CopySpecVisitor.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/CopySpecVisitor.java
deleted file mode 100644
index 46f2cf9..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/CopySpecVisitor.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.file.copy;
-
-import org.gradle.api.file.FileVisitor;
-import org.gradle.api.tasks.WorkResult;
-
-public interface CopySpecVisitor extends FileVisitor, WorkResult {
- /**
- * Called at the start of the visit.
- */
- void startVisit(CopyAction action);
-
- /**
- * Called at the end of the visit.
- */
- void endVisit();
-
- /**
- * Visits a spec. Called before any of the files or directories of the spec are visited.
- */
- void visitSpec(ReadableCopySpec spec);
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/DefaultCopySpec.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/DefaultCopySpec.java
new file mode 100644
index 0000000..33e9451
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/DefaultCopySpec.java
@@ -0,0 +1,462 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.file.copy;
+
+import com.google.common.collect.ImmutableList;
+import groovy.lang.Closure;
+import org.gradle.api.Action;
+import org.gradle.api.NonExtensible;
+import org.gradle.api.file.*;
+import org.gradle.api.internal.ChainingTransformer;
+import org.gradle.api.internal.ClosureBackedAction;
+import org.gradle.api.internal.file.FileResolver;
+import org.gradle.api.internal.file.pattern.PatternMatcherFactory;
+import org.gradle.api.specs.NotSpec;
+import org.gradle.api.specs.Spec;
+import org.gradle.api.tasks.util.PatternSet;
+import org.gradle.internal.reflect.Instantiator;
+import org.gradle.util.ConfigureUtil;
+
+import java.io.File;
+import java.io.FilterReader;
+import java.util.*;
+import java.util.regex.Pattern;
+
+ at NonExtensible
+public class DefaultCopySpec implements CopySpecInternal {
+ private final FileResolver resolver;
+ private final Set<Object> sourcePaths;
+ private Object destDir;
+ private final PatternSet patternSet;
+ private final List<CopySpecInternal> childSpecs;
+ private final Instantiator instantiator;
+ private final DefaultCopySpec parentSpec;
+ private final List<Action<? super FileCopyDetails>> actions = new ArrayList<Action<? super FileCopyDetails>>();
+ private Integer dirMode;
+ private Integer fileMode;
+ private Boolean caseSensitive;
+ private Boolean includeEmptyDirs;
+ private PathNotationParser<String> pathNotationParser;
+ private DuplicatesStrategy duplicatesStrategy;
+
+ public DefaultCopySpec(FileResolver resolver, Instantiator instantiator, DefaultCopySpec parentSpec) {
+ this.parentSpec = parentSpec;
+ this.resolver = resolver;
+ this.instantiator = instantiator;
+ this.pathNotationParser = new PathNotationParser<String>();
+ sourcePaths = new LinkedHashSet<Object>();
+ childSpecs = new ArrayList<CopySpecInternal>();
+ patternSet = new PatternSet();
+ duplicatesStrategy = null; //inherit from parent
+ }
+
+ public DefaultCopySpec(FileResolver resolver, Instantiator instantiator) {
+ this(resolver, instantiator, null);
+ }
+
+ protected FileResolver getResolver() {
+ return resolver;
+ }
+
+ public CopySpec with(CopySpec... copySpecs) {
+ for (CopySpec copySpec : copySpecs) {
+ CopySpecInternal copySpecInternal;
+ if (copySpec instanceof CopySpecSource) {
+ CopySpecSource copySpecSource = (CopySpecSource) copySpec;
+ copySpecInternal = copySpecSource.getRootSpec();
+ } else {
+ copySpecInternal = (CopySpecInternal) copySpec;
+ }
+ childSpecs.add(new RelativizedCopySpec(this, copySpecInternal));
+ }
+ return this;
+ }
+
+ public CopySpec from(Object... sourcePaths) {
+ for (Object sourcePath : sourcePaths) {
+ this.sourcePaths.add(sourcePath);
+ }
+ return this;
+ }
+
+ public CopySpec from(Object sourcePath, Closure c) {
+ if (c == null) {
+ from(sourcePath);
+ return this;
+ } else {
+ DefaultCopySpec child = addChild();
+ child.from(sourcePath);
+ ConfigureUtil.configure(c, child);
+ return child;
+ }
+ }
+
+ public DefaultCopySpec addFirst() {
+ DefaultCopySpec child = instantiator.newInstance(DefaultCopySpec.class, resolver, instantiator, this);
+ childSpecs.add(0, child);
+ return child;
+ }
+
+ public DefaultCopySpec addChild() {
+ DefaultCopySpec child = instantiator.newInstance(DefaultCopySpec.class, resolver, instantiator, this);
+ childSpecs.add(child);
+ return child;
+ }
+
+ public Set<Object> getSourcePaths() {
+ return sourcePaths;
+ }
+
+ public FileTree getSource() {
+ return resolver.resolveFilesAsTree(sourcePaths).matching(getPatternSet());
+ }
+
+ public FileTree getAllSource() {
+ final ImmutableList.Builder<FileTree> builder = ImmutableList.builder();
+ walk(new Action<CopySpecInternal>() {
+ public void execute(CopySpecInternal copySpecInternal) {
+ builder.add(copySpecInternal.getSource());
+ }
+ });
+
+ return resolver.compositeFileTree(builder.build());
+ }
+
+ public DefaultCopySpec into(Object destDir) {
+ this.destDir = destDir;
+ return this;
+ }
+
+ public DefaultCopySpec into(Object destPath, Closure configureClosure) {
+ if (configureClosure == null) {
+ into(destPath);
+ return this;
+ } else {
+ DefaultCopySpec child = addChild();
+ child.into(destPath);
+ ConfigureUtil.configure(configureClosure, child);
+ return child;
+ }
+ }
+
+ public RelativePath getDestPath() {
+ RelativePath parentPath;
+ if (parentSpec == null) {
+ parentPath = new RelativePath(false);
+ } else {
+ parentPath = parentSpec.getDestPath();
+ }
+ if (destDir == null) {
+ return parentPath;
+ }
+
+ String path = resolveToPath(destDir);
+ if (path.startsWith("/") || path.startsWith(File.separator)) {
+ return RelativePath.parse(false, path);
+ }
+
+ return RelativePath.parse(false, parentPath, path);
+ }
+
+ private String resolveToPath(Object destDir) {
+ return pathNotationParser.parseNotation(destDir);
+ }
+
+ public PatternSet getPatternSet() {
+ PatternSet patterns = new PatternSet();
+ patterns.setCaseSensitive(isCaseSensitive());
+ patterns.include(getAllIncludes());
+ patterns.includeSpecs(getAllIncludeSpecs());
+ patterns.exclude(getAllExcludes());
+ patterns.excludeSpecs(getAllExcludeSpecs());
+ return patterns;
+ }
+
+ public boolean isCaseSensitive() {
+ if (caseSensitive != null) {
+ return caseSensitive;
+ }
+ if (parentSpec != null) {
+ return parentSpec.isCaseSensitive();
+ }
+ return true;
+ }
+
+ public void setCaseSensitive(boolean caseSensitive) {
+ this.caseSensitive = caseSensitive;
+ }
+
+ public boolean getIncludeEmptyDirs() {
+ if (includeEmptyDirs != null) {
+ return includeEmptyDirs;
+ }
+ if (parentSpec != null) {
+ return parentSpec.getIncludeEmptyDirs();
+ }
+ return true;
+ }
+
+ public void setIncludeEmptyDirs(boolean includeEmptyDirs) {
+ this.includeEmptyDirs = includeEmptyDirs;
+ }
+
+ public DuplicatesStrategy getDuplicatesStrategy() {
+ if (duplicatesStrategy != null) {
+ return duplicatesStrategy;
+ }
+ if (parentSpec != null) {
+ return parentSpec.getDuplicatesStrategy();
+ }
+ return DuplicatesStrategy.INCLUDE;
+ }
+
+ public void setDuplicatesStrategy(DuplicatesStrategy strategy) {
+ this.duplicatesStrategy = strategy;
+ }
+
+ public CopySpec filesMatching(String pattern, Action<? super FileCopyDetails> action) {
+ Spec<RelativePath> matcher = PatternMatcherFactory.getPatternMatcher(true, isCaseSensitive(), pattern);
+ return eachFile(
+ new MatchingCopyAction(matcher, action));
+ }
+
+ public CopySpec filesNotMatching(String pattern, Action<? super FileCopyDetails> action) {
+ Spec<RelativePath> matcher = PatternMatcherFactory.getPatternMatcher(true, isCaseSensitive(), pattern);
+ return eachFile(
+ new MatchingCopyAction(new NotSpec<RelativePath>(matcher), action));
+ }
+
+ public CopySpec include(String... includes) {
+ patternSet.include(includes);
+ return this;
+ }
+
+ public CopySpec include(Iterable<String> includes) {
+ patternSet.include(includes);
+ return this;
+ }
+
+ public CopySpec include(Spec<FileTreeElement> includeSpec) {
+ patternSet.include(includeSpec);
+ return this;
+ }
+
+ public CopySpec include(Closure includeSpec) {
+ patternSet.include(includeSpec);
+ return this;
+ }
+
+ public Set<String> getIncludes() {
+ return patternSet.getIncludes();
+ }
+
+ public CopySpec setIncludes(Iterable<String> includes) {
+ patternSet.setIncludes(includes);
+ return this;
+ }
+
+ public List<String> getAllIncludes() {
+ List<String> result = new ArrayList<String>();
+ if (parentSpec != null) {
+ result.addAll(parentSpec.getAllIncludes());
+ }
+ result.addAll(getIncludes());
+ return result;
+ }
+
+ public List<Spec<FileTreeElement>> getAllIncludeSpecs() {
+ List<Spec<FileTreeElement>> result = new ArrayList<Spec<FileTreeElement>>();
+ if (parentSpec != null) {
+ result.addAll(parentSpec.getAllIncludeSpecs());
+ }
+ result.addAll(patternSet.getIncludeSpecs());
+ return result;
+ }
+
+ public CopySpec exclude(String... excludes) {
+ patternSet.exclude(excludes);
+ return this;
+ }
+
+ public CopySpec exclude(Iterable<String> excludes) {
+ patternSet.exclude(excludes);
+ return this;
+ }
+
+ public CopySpec exclude(Spec<FileTreeElement> excludeSpec) {
+ patternSet.exclude(excludeSpec);
+ return this;
+ }
+
+ public CopySpec exclude(Closure excludeSpec) {
+ patternSet.exclude(excludeSpec);
+ return this;
+ }
+
+ public Set<String> getExcludes() {
+ return patternSet.getExcludes();
+ }
+
+ public DefaultCopySpec setExcludes(Iterable<String> excludes) {
+ patternSet.setExcludes(excludes);
+ return this;
+ }
+
+ public CopySpec rename(String sourceRegEx, String replaceWith) {
+ actions.add(new RenamingCopyAction(new RegExpNameMapper(sourceRegEx, replaceWith)));
+ return this;
+ }
+
+ public CopySpec rename(Pattern sourceRegEx, String replaceWith) {
+ actions.add(new RenamingCopyAction(new RegExpNameMapper(sourceRegEx, replaceWith)));
+ return this;
+ }
+
+ public CopySpec filter(final Class<? extends FilterReader> filterType) {
+ actions.add(new Action<FileCopyDetails>() {
+ public void execute(FileCopyDetails fileCopyDetails) {
+ fileCopyDetails.filter(filterType);
+ }
+ });
+ return this;
+ }
+
+ public CopySpec filter(final Closure closure) {
+ actions.add(new Action<FileCopyDetails>() {
+ public void execute(FileCopyDetails fileCopyDetails) {
+ fileCopyDetails.filter(closure);
+ }
+ });
+ return this;
+ }
+
+ public CopySpec filter(final Map<String, ?> properties, final Class<? extends FilterReader> filterType) {
+ actions.add(new Action<FileCopyDetails>() {
+ public void execute(FileCopyDetails fileCopyDetails) {
+ fileCopyDetails.filter(properties, filterType);
+ }
+ });
+ return this;
+ }
+
+ public CopySpec expand(final Map<String, ?> properties) {
+ actions.add(new Action<FileCopyDetails>() {
+ public void execute(FileCopyDetails fileCopyDetails) {
+ fileCopyDetails.expand(properties);
+ }
+ });
+ return this;
+ }
+
+ public CopySpec rename(Closure closure) {
+ ChainingTransformer<String> transformer = new ChainingTransformer<String>(String.class);
+ transformer.add(closure);
+ actions.add(new RenamingCopyAction(transformer));
+ return this;
+ }
+
+ public Integer getDirMode() {
+ if (dirMode != null) {
+ return dirMode;
+ }
+ if (parentSpec != null) {
+ return parentSpec.getDirMode();
+ }
+ return null;
+ }
+
+ public Integer getFileMode() {
+ if (fileMode != null) {
+ return fileMode;
+ }
+ if (parentSpec != null) {
+ return parentSpec.getFileMode();
+ }
+ return null;
+ }
+
+ public CopyProcessingSpec setDirMode(Integer mode) {
+ dirMode = mode;
+ return this;
+ }
+
+ public CopyProcessingSpec setFileMode(Integer mode) {
+ fileMode = mode;
+ return this;
+ }
+
+ public CopySpec eachFile(Action<? super FileCopyDetails> action) {
+ actions.add(action);
+ return this;
+ }
+
+ public CopySpec eachFile(Closure closure) {
+ actions.add(new ClosureBackedAction<FileCopyDetails>(closure));
+ return this;
+ }
+
+ public List<String> getAllExcludes() {
+ List<String> result = new ArrayList<String>();
+ if (parentSpec != null) {
+ result.addAll(parentSpec.getAllExcludes());
+ }
+ result.addAll(getExcludes());
+ return result;
+ }
+
+ public List<Spec<FileTreeElement>> getAllExcludeSpecs() {
+ List<Spec<FileTreeElement>> result = new ArrayList<Spec<FileTreeElement>>();
+ if (parentSpec != null) {
+ result.addAll(parentSpec.getAllExcludeSpecs());
+ }
+ result.addAll(patternSet.getExcludeSpecs());
+ return result;
+ }
+
+ public List<Action<? super FileCopyDetails>> getAllCopyActions() {
+ if (parentSpec == null) {
+ return actions;
+ }
+ List<Action<? super FileCopyDetails>> allActions = new ArrayList<Action<? super FileCopyDetails>>();
+ allActions.addAll(parentSpec.getAllCopyActions());
+ allActions.addAll(actions);
+ return allActions;
+ }
+
+ public Iterable<CopySpecInternal> getChildren() {
+ return childSpecs;
+ }
+
+ public void walk(Action<? super CopySpecInternal> action) {
+ action.execute(this);
+ for (CopySpecInternal child : getChildren()) {
+ child.walk(action);
+ }
+ }
+
+ public boolean hasSource() {
+ if (!sourcePaths.isEmpty()) {
+ return true;
+ }
+ for (CopySpecInternal spec : childSpecs) {
+ if (spec.hasSource()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/DefaultFileCopyDetails.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/DefaultFileCopyDetails.java
new file mode 100644
index 0000000..9c7b1d1
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/DefaultFileCopyDetails.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.file.copy;
+
+import groovy.lang.Closure;
+import org.gradle.api.GradleException;
+import org.gradle.api.file.ContentFilterable;
+import org.gradle.api.file.DuplicatesStrategy;
+import org.gradle.api.file.FileVisitDetails;
+import org.gradle.api.file.RelativePath;
+import org.gradle.api.internal.file.AbstractFileTreeElement;
+import org.gradle.internal.nativeplatform.filesystem.FileSystem;
+
+import java.io.*;
+import java.util.Map;
+
+public class DefaultFileCopyDetails extends AbstractFileTreeElement implements FileVisitDetails, FileCopyDetailsInternal {
+ private final FileVisitDetails fileDetails;
+ private final CopySpecInternal spec;
+ private FileSystem fileSystem;
+ private final FilterChain filterChain = new FilterChain();
+ private RelativePath relativePath;
+ private boolean excluded;
+ private Integer mode;
+ private DuplicatesStrategy duplicatesStrategy;
+
+ public DefaultFileCopyDetails(FileVisitDetails fileDetails, CopySpecInternal spec, FileSystem fileSystem) {
+ this.fileDetails = fileDetails;
+ this.spec = spec;
+ this.fileSystem = fileSystem;
+ this.duplicatesStrategy = spec.getDuplicatesStrategy();
+ }
+
+ public boolean isIncludeEmptyDirs() {
+ return spec.getIncludeEmptyDirs();
+ }
+
+ public String getDisplayName() {
+ return fileDetails.toString();
+ }
+
+ public void stopVisiting() {
+ fileDetails.stopVisiting();
+ }
+
+ public File getFile() {
+ if (filterChain.hasFilters()) {
+ throw new UnsupportedOperationException();
+ } else {
+ return fileDetails.getFile();
+ }
+ }
+
+ public boolean isDirectory() {
+ return fileDetails.isDirectory();
+ }
+
+ public long getLastModified() {
+ return fileDetails.getLastModified();
+ }
+
+ public long getSize() {
+ if (filterChain.hasFilters()) {
+ ByteCountingOutputStream outputStream = new ByteCountingOutputStream();
+ copyTo(outputStream);
+ return outputStream.size;
+ } else {
+ return fileDetails.getSize();
+ }
+ }
+
+ public InputStream open() {
+ if (filterChain.hasFilters()) {
+ return filterChain.transform(fileDetails.open());
+ } else {
+ return fileDetails.open();
+ }
+ }
+
+ public void copyTo(OutputStream outstr) {
+ if (filterChain.hasFilters()) {
+ super.copyTo(outstr);
+ } else {
+ fileDetails.copyTo(outstr);
+ }
+ }
+
+ public boolean copyTo(File target) {
+ if (filterChain.hasFilters()) {
+ return super.copyTo(target);
+ } else {
+ final boolean copied = fileDetails.copyTo(target);
+ adaptPermissions(target);
+ return copied;
+ }
+ }
+
+ private void adaptPermissions(File target) {
+ final Integer specMode = getMode();
+ if(specMode !=null){
+ try {
+ fileSystem.chmod(target, specMode);
+ } catch (IOException e) {
+ throw new GradleException(String.format("Could not set permission %s on '%s'.", specMode, target), e);
+ }
+ }
+ }
+
+ public RelativePath getRelativePath() {
+ if (relativePath == null) {
+ RelativePath path = fileDetails.getRelativePath();
+ relativePath = spec.getDestPath().append(path.isFile(), path.getSegments());
+ }
+ return relativePath;
+ }
+
+ public int getMode() {
+ if (mode != null) {
+ return mode;
+ }
+
+ Integer specMode = getSpecMode();
+ if (specMode != null) {
+ return specMode;
+ }
+
+ return fileDetails.getMode();
+ }
+
+ private Integer getSpecMode() {
+ return fileDetails.isDirectory() ? spec.getDirMode() : spec.getFileMode();
+ }
+
+ public void setRelativePath(RelativePath path) {
+ this.relativePath = path;
+ }
+
+ public void setName(String name) {
+ relativePath = getRelativePath().replaceLastName(name);
+ }
+
+ public void setPath(String path) {
+ relativePath = RelativePath.parse(getRelativePath().isFile(), path);
+ }
+
+ boolean isExcluded() {
+ return excluded;
+ }
+
+ public void exclude() {
+ excluded = true;
+ }
+
+ public void setMode(int mode) {
+ this.mode = mode;
+ }
+
+ public ContentFilterable filter(Closure closure) {
+ filterChain.add(closure);
+ return this;
+ }
+
+ public ContentFilterable filter(Map<String, ?> properties, Class<? extends FilterReader> filterType) {
+ filterChain.add(filterType, properties);
+ return this;
+ }
+
+ public ContentFilterable filter(Class<? extends FilterReader> filterType) {
+ filterChain.add(filterType);
+ return this;
+ }
+
+ public ContentFilterable expand(Map<String, ?> properties) {
+ filterChain.expand(properties);
+ return this;
+ }
+
+ public void setDuplicatesStrategy(DuplicatesStrategy strategy) {
+ this.duplicatesStrategy = strategy;
+ }
+
+ public DuplicatesStrategy getDuplicatesStrategy() {
+ return this.duplicatesStrategy;
+ }
+
+ private static class ByteCountingOutputStream extends OutputStream {
+ long size;
+
+ @Override
+ public void write(int b) throws IOException {
+ size++;
+ }
+
+ @Override
+ public void write(byte[] b) throws IOException {
+ size += b.length;
+ }
+
+ @Override
+ public void write(byte[] b, int off, int len) throws IOException {
+ size += len;
+ }
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/DelegatingCopySpec.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/DelegatingCopySpec.java
new file mode 100644
index 0000000..fc924d7
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/DelegatingCopySpec.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.file.copy;
+
+import groovy.lang.Closure;
+import org.gradle.api.Action;
+import org.gradle.api.file.*;
+import org.gradle.api.specs.Spec;
+
+import java.io.FilterReader;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+abstract public class DelegatingCopySpec implements CopySpecInternal {
+
+ abstract protected CopySpecInternal getDelegateCopySpec();
+
+ public RelativePath getDestPath() {
+ return getDelegateCopySpec().getDestPath();
+ }
+
+ public FileTree getSource() {
+ return getDelegateCopySpec().getSource();
+ }
+
+ public boolean hasSource() {
+ return getDelegateCopySpec().hasSource();
+ }
+
+ public Collection<? extends Action<? super FileCopyDetails>> getAllCopyActions() {
+ return getDelegateCopySpec().getAllCopyActions();
+ }
+
+ public boolean isCaseSensitive() {
+ return getDelegateCopySpec().isCaseSensitive();
+ }
+
+ public void setCaseSensitive(boolean caseSensitive) {
+ getDelegateCopySpec().setCaseSensitive(caseSensitive);
+ }
+
+ public boolean getIncludeEmptyDirs() {
+ return getDelegateCopySpec().getIncludeEmptyDirs();
+ }
+
+ public void setIncludeEmptyDirs(boolean includeEmptyDirs) {
+ getDelegateCopySpec().setIncludeEmptyDirs(includeEmptyDirs);
+ }
+
+ public DuplicatesStrategy getDuplicatesStrategy() {
+ return getDelegateCopySpec().getDuplicatesStrategy();
+ }
+
+ public void setDuplicatesStrategy(DuplicatesStrategy strategy) {
+ getDelegateCopySpec().setDuplicatesStrategy(strategy);
+ }
+
+ public CopySpec filesMatching(String pattern, Action<? super FileCopyDetails> action) {
+ return getDelegateCopySpec().filesMatching(pattern, action);
+ }
+
+ public CopySpec filesNotMatching(String pattern, Action<? super FileCopyDetails> action) {
+ return getDelegateCopySpec().filesNotMatching(pattern, action);
+ }
+
+ public CopySpec with(CopySpec... sourceSpecs) {
+ return getDelegateCopySpec().with(sourceSpecs);
+ }
+
+ public CopySpec from(Object... sourcePaths) {
+ return getDelegateCopySpec().from(sourcePaths);
+ }
+
+ public CopySpec from(Object sourcePath, Closure c) {
+ return getDelegateCopySpec().from(sourcePath, c);
+ }
+
+ public CopySpec setIncludes(Iterable<String> includes) {
+ return getDelegateCopySpec().setIncludes(includes);
+ }
+
+ public CopySpec setExcludes(Iterable<String> excludes) {
+ return getDelegateCopySpec().setExcludes(excludes);
+ }
+
+ public CopySpec include(String... includes) {
+ return getDelegateCopySpec().include(includes);
+ }
+
+ public CopySpec include(Iterable<String> includes) {
+ return getDelegateCopySpec().include(includes);
+ }
+
+ public CopySpec include(Spec<FileTreeElement> includeSpec) {
+ return getDelegateCopySpec().include(includeSpec);
+ }
+
+ public CopySpec include(Closure includeSpec) {
+ return getDelegateCopySpec().include(includeSpec);
+ }
+
+ public CopySpec exclude(String... excludes) {
+ return getDelegateCopySpec().exclude(excludes);
+ }
+
+ public CopySpec exclude(Iterable<String> excludes) {
+ return getDelegateCopySpec().exclude(excludes);
+ }
+
+ public CopySpec exclude(Spec<FileTreeElement> excludeSpec) {
+ return getDelegateCopySpec().exclude(excludeSpec);
+ }
+
+ public CopySpec exclude(Closure excludeSpec) {
+ return getDelegateCopySpec().exclude(excludeSpec);
+ }
+
+ public CopySpec into(Object destPath) {
+ return getDelegateCopySpec().into(destPath);
+ }
+
+ public CopySpec into(Object destPath, Closure configureClosure) {
+ return getDelegateCopySpec().into(destPath, configureClosure);
+ }
+
+ public CopySpec rename(Closure closure) {
+ return getDelegateCopySpec().rename(closure);
+ }
+
+ public CopySpec rename(String sourceRegEx, String replaceWith) {
+ return getDelegateCopySpec().rename(sourceRegEx, replaceWith);
+ }
+
+ public CopyProcessingSpec rename(Pattern sourceRegEx, String replaceWith) {
+ return getDelegateCopySpec().rename(sourceRegEx, replaceWith);
+ }
+
+ public CopySpec filter(Map<String, ?> properties, Class<? extends FilterReader> filterType) {
+ return getDelegateCopySpec().filter(properties, filterType);
+ }
+
+ public CopySpec filter(Class<? extends FilterReader> filterType) {
+ return getDelegateCopySpec().filter(filterType);
+ }
+
+ public CopySpec filter(Closure closure) {
+ return getDelegateCopySpec().filter(closure);
+ }
+
+ public CopySpec expand(Map<String, ?> properties) {
+ return getDelegateCopySpec().expand(properties);
+ }
+
+ public CopySpec eachFile(Action<? super FileCopyDetails> action) {
+ return getDelegateCopySpec().eachFile(action);
+ }
+
+ public CopySpec eachFile(Closure closure) {
+ return getDelegateCopySpec().eachFile(closure);
+ }
+
+ public Integer getFileMode() {
+ return getDelegateCopySpec().getFileMode();
+ }
+
+ public CopyProcessingSpec setFileMode(Integer mode) {
+ return getDelegateCopySpec().setFileMode(mode);
+ }
+
+ public Integer getDirMode() {
+ return getDelegateCopySpec().getDirMode();
+ }
+
+ public CopyProcessingSpec setDirMode(Integer mode) {
+ return getDelegateCopySpec().setDirMode(mode);
+ }
+
+ public Set<String> getIncludes() {
+ return getDelegateCopySpec().getIncludes();
+ }
+
+ public Set<String> getExcludes() {
+ return getDelegateCopySpec().getExcludes();
+ }
+
+ public Iterable<CopySpecInternal> getChildren() {
+ return getDelegateCopySpec().getChildren();
+ }
+
+ public FileTree getAllSource() {
+ return getDelegateCopySpec().getAllSource();
+ }
+
+ public DefaultCopySpec addChild() {
+ return getDelegateCopySpec().addChild();
+ }
+
+ public DefaultCopySpec addFirst() {
+ return getDelegateCopySpec().addFirst();
+ }
+
+ public void walk(Action<? super CopySpecInternal> action) {
+ action.execute(this);
+ for (CopySpecInternal child : getChildren()) {
+ child.walk(action);
+ }
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/DelegatingCopySpecVisitor.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/DelegatingCopySpecVisitor.java
deleted file mode 100644
index 0a5ee3a..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/DelegatingCopySpecVisitor.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.file.copy;
-
-import org.gradle.api.file.FileVisitDetails;
-
-public class DelegatingCopySpecVisitor implements CopySpecVisitor {
- private final CopySpecVisitor visitor;
-
- public DelegatingCopySpecVisitor(CopySpecVisitor visitor) {
- this.visitor = visitor;
- }
-
- protected CopySpecVisitor getVisitor() {
- return visitor;
- }
-
- public void startVisit(CopyAction action) {
- getVisitor().startVisit(action);
- }
-
- public void endVisit() {
- getVisitor().endVisit();
- }
-
- public void visitSpec(ReadableCopySpec spec) {
- getVisitor().visitSpec(spec);
- }
-
- public void visitDir(FileVisitDetails dirDetails) {
- getVisitor().visitDir(dirDetails);
- }
-
- public void visitFile(FileVisitDetails fileDetails) {
- getVisitor().visitFile(fileDetails);
- }
-
- public boolean getDidWork() {
- return getVisitor().getDidWork();
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/DeleteActionImpl.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/DeleteActionImpl.java
index 923fc72..f3c72c9 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/DeleteActionImpl.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/DeleteActionImpl.java
@@ -24,9 +24,6 @@ import org.slf4j.LoggerFactory;
import java.io.File;
-/**
- * @author Hans Dockter
- */
public class DeleteActionImpl implements DeleteAction {
private static Logger logger = LoggerFactory.getLogger(DeleteActionImpl.class);
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/DestinationRootCopySpec.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/DestinationRootCopySpec.java
new file mode 100644
index 0000000..d26fe2d
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/DestinationRootCopySpec.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.file.copy;
+
+import org.gradle.api.file.CopySpec;
+import org.gradle.api.internal.file.FileResolver;
+
+import java.io.File;
+
+public class DestinationRootCopySpec extends DelegatingCopySpec {
+
+ private final FileResolver fileResolver;
+ private final CopySpecInternal delegate;
+
+ private Object destinationDir;
+
+ public DestinationRootCopySpec(FileResolver fileResolver, CopySpecInternal delegate) {
+ this.fileResolver = fileResolver;
+ this.delegate = delegate;
+ }
+
+ @Override
+ protected CopySpecInternal getDelegateCopySpec() {
+ return delegate;
+ }
+
+ @Override
+ public CopySpec into(Object destinationDir) {
+ this.destinationDir = destinationDir;
+ return this;
+ }
+
+ public File getDestinationDir() {
+ return destinationDir == null ? null : fileResolver.resolve(destinationDir);
+ }
+
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/DuplicateHandlingCopyActionDecorator.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/DuplicateHandlingCopyActionDecorator.java
new file mode 100644
index 0000000..d53a048
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/DuplicateHandlingCopyActionDecorator.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.file.copy;
+
+import org.gradle.api.file.DuplicateFileCopyingException;
+import org.gradle.api.file.DuplicatesStrategy;
+import org.gradle.api.file.RelativePath;
+import org.gradle.api.internal.file.CopyActionProcessingStreamAction;
+import org.gradle.api.logging.Logger;
+import org.gradle.api.logging.Logging;
+import org.gradle.api.tasks.WorkResult;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class DuplicateHandlingCopyActionDecorator implements CopyAction {
+
+ private final static Logger LOGGER = Logging.getLogger(DuplicateHandlingCopyActionDecorator.class);
+ private final CopyAction delegate;
+
+ public DuplicateHandlingCopyActionDecorator(CopyAction delegate) {
+ this.delegate = delegate;
+ }
+
+ public WorkResult execute(final CopyActionProcessingStream stream) {
+ final Set<RelativePath> visitedFiles = new HashSet<RelativePath>();
+
+ return delegate.execute(new CopyActionProcessingStream() {
+ public void process(final CopyActionProcessingStreamAction action) {
+ stream.process(new CopyActionProcessingStreamAction() {
+ public void processFile(FileCopyDetailsInternal details) {
+ if (!details.isDirectory()) {
+ DuplicatesStrategy strategy = details.getDuplicatesStrategy();
+
+ if (!visitedFiles.add(details.getRelativePath())) {
+ if (strategy == DuplicatesStrategy.EXCLUDE) {
+ return;
+ } else if (strategy == DuplicatesStrategy.FAIL) {
+ throw new DuplicateFileCopyingException(String.format("Encountered duplicate path \"%s\" during copy operation configured with DuplicatesStrategy.FAIL", details.getRelativePath()));
+ } else if (strategy == DuplicatesStrategy.WARN) {
+ LOGGER.warn("Encountered duplicate path \"{}\" during copy operation configured with DuplicatesStrategy.WARN", details.getRelativePath());
+ }
+ }
+ }
+
+ action.processFile(details);
+ }
+ });
+ }
+ });
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/EmptyCopySpecVisitor.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/EmptyCopySpecVisitor.java
deleted file mode 100644
index 0c9dbce..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/EmptyCopySpecVisitor.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.file.copy;
-
-import org.gradle.api.file.FileVisitDetails;
-
-public class EmptyCopySpecVisitor implements CopySpecVisitor {
- public boolean getDidWork() {
- return false;
- }
-
- public void startVisit(CopyAction action) {
- }
-
- public void visitDir(FileVisitDetails dirDetails) {
- }
-
- public void endVisit() {
- }
-
- public void visitFile(FileVisitDetails fileDetails) {
- }
-
- public void visitSpec(ReadableCopySpec spec) {
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/FileCopier.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/FileCopier.java
new file mode 100644
index 0000000..cb4c813
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/FileCopier.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.file.copy;
+
+import org.gradle.api.Action;
+import org.gradle.api.file.CopySpec;
+import org.gradle.api.internal.file.BaseDirFileResolver;
+import org.gradle.api.internal.file.FileResolver;
+import org.gradle.api.tasks.WorkResult;
+import org.gradle.internal.nativeplatform.filesystem.FileSystems;
+import org.gradle.internal.reflect.Instantiator;
+
+import java.io.File;
+
+public class FileCopier {
+
+ private final Instantiator instantiator;
+ private final FileResolver fileResolver;
+
+ public FileCopier(Instantiator instantiator, FileResolver fileResolver) {
+ this.instantiator = instantiator;
+ this.fileResolver = fileResolver;
+ }
+
+ private DestinationRootCopySpec createCopySpec(Action<? super CopySpec> action) {
+ DefaultCopySpec copySpec = instantiator.newInstance(DefaultCopySpec.class, this.fileResolver, instantiator);
+ DestinationRootCopySpec destinationRootCopySpec = instantiator.newInstance(DestinationRootCopySpec.class, fileResolver, copySpec);
+ action.execute(destinationRootCopySpec);
+ return destinationRootCopySpec;
+ }
+
+ public WorkResult copy(Action<? super CopySpec> action) {
+ DestinationRootCopySpec copySpec = createCopySpec(action);
+ File destinationDir = copySpec.getDestinationDir();
+ return doCopy(copySpec, getCopyVisitor(destinationDir));
+ }
+
+ public WorkResult sync(Action<? super CopySpec> action) {
+ DestinationRootCopySpec copySpec = createCopySpec(action);
+ File destinationDir = copySpec.getDestinationDir();
+ return doCopy(copySpec, new SyncCopyActionDecorator(destinationDir, getCopyVisitor(destinationDir)));
+ }
+
+ private FileCopyAction getCopyVisitor(File destination) {
+ return new FileCopyAction(new BaseDirFileResolver(FileSystems.getDefault(), destination));
+ }
+
+ private WorkResult doCopy(CopySpecInternal copySpec, CopyAction visitor) {
+ CopyActionExecuter visitorDriver = new CopyActionExecuter(instantiator, FileSystems.getDefault());
+ return visitorDriver.execute(copySpec, visitor);
+ }
+
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/FileCopyAction.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/FileCopyAction.java
index 7040c9d..00e8b1c 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/FileCopyAction.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/FileCopyAction.java
@@ -15,8 +15,36 @@
*/
package org.gradle.api.internal.file.copy;
+import org.gradle.api.internal.file.CopyActionProcessingStreamAction;
+import org.gradle.api.internal.file.FileResolver;
+import org.gradle.api.internal.tasks.SimpleWorkResult;
+import org.gradle.api.tasks.WorkResult;
+
import java.io.File;
-public interface FileCopyAction extends CopyAction {
- File getDestinationDir();
+public class FileCopyAction implements CopyAction {
+
+ private final FileResolver fileResolver;
+
+ public FileCopyAction(FileResolver fileResolver) {
+ this.fileResolver = fileResolver;
+ }
+
+ public WorkResult execute(CopyActionProcessingStream stream) {
+ FileCopyDetailsInternalAction action = new FileCopyDetailsInternalAction();
+ stream.process(action);
+ return new SimpleWorkResult(action.didWork);
+ }
+
+ private class FileCopyDetailsInternalAction implements CopyActionProcessingStreamAction {
+ private boolean didWork;
+
+ public void processFile(FileCopyDetailsInternal details) {
+ File target = fileResolver.resolve(details.getRelativePath().getPathString());
+ boolean copied = details.copyTo(target);
+ if (copied) {
+ didWork = true;
+ }
+ }
+ }
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/FileCopyActionImpl.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/FileCopyActionImpl.java
index 1a35e8c..659fc1e 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/FileCopyActionImpl.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/FileCopyActionImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2009 the original author or authors.
+ * Copyright 2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,27 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.gradle.api.internal.file.copy;
-
-import org.gradle.api.file.CopySpec;
-import org.gradle.api.internal.file.FileResolver;
-
-import java.io.File;
-
-public class FileCopyActionImpl extends CopyActionImpl implements FileCopyAction {
- private Object destDir;
- public FileCopyActionImpl(FileResolver resolver, CopySpecVisitor visitor) {
- super(resolver, visitor);
- }
-
- @Override
- public CopySpec into(Object destDir) {
- this.destDir = destDir;
- return this;
- }
+package org.gradle.api.internal.file.copy;
- public File getDestinationDir() {
- return destDir == null ? null : getResolver().resolve(destDir);
- }
+/**
+ * DO NOT REMOVE.
+ *
+ * Prior to 1.8, Copy leaked this as a parameter type on one of its methods.
+ * Has to exist to maintain binary compatibility.
+ */
+ at SuppressWarnings("UnusedDeclaration")
+ at Deprecated
+public class FileCopyActionImpl {
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/FileCopyDetailsInternal.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/FileCopyDetailsInternal.java
new file mode 100644
index 0000000..8de9bfd
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/FileCopyDetailsInternal.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.file.copy;
+
+import org.gradle.api.file.FileCopyDetails;
+
+public interface FileCopyDetailsInternal extends FileCopyDetails {
+
+ boolean isIncludeEmptyDirs();
+
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/FileCopySpecVisitor.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/FileCopySpecVisitor.java
deleted file mode 100644
index 712e986..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/FileCopySpecVisitor.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.file.copy;
-
-import org.gradle.api.InvalidUserDataException;
-import org.gradle.api.file.FileTreeElement;
-import org.gradle.api.file.FileVisitDetails;
-
-import java.io.File;
-
-/**
- * @author Steve Appling
- */
-public class FileCopySpecVisitor extends EmptyCopySpecVisitor {
- private File baseDestDir;
- private boolean didWork;
-
- public void startVisit(CopyAction action) {
- baseDestDir = ((FileCopyAction) action).getDestinationDir();
- if (baseDestDir == null) {
- throw new InvalidUserDataException("No copy destination directory has been specified, use 'into' to specify a target directory.");
- }
- }
-
- public void visitFile(FileVisitDetails source) {
- visitFileOrDir(source);
- }
-
- public void visitDir(FileVisitDetails source) {
- visitFileOrDir(source);
- }
-
- public boolean getDidWork() {
- return didWork;
- }
-
- private void visitFileOrDir(FileVisitDetails source) {
- File target = source.getRelativePath().getFile(baseDestDir);
- copyFile(source, target);
- }
-
- private void copyFile(FileTreeElement srcFile, File destFile) {
- boolean copied = srcFile.copyTo(destFile);
- if (copied) {
- didWork = true;
- }
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/MappingCopySpecVisitor.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/MappingCopySpecVisitor.java
deleted file mode 100644
index a662c9d..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/MappingCopySpecVisitor.java
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.file.copy;
-
-import groovy.lang.Closure;
-import org.gradle.api.Action;
-import org.gradle.api.GradleException;
-import org.gradle.api.file.ContentFilterable;
-import org.gradle.api.file.FileCopyDetails;
-import org.gradle.api.file.FileVisitDetails;
-import org.gradle.api.file.RelativePath;
-import org.gradle.api.internal.file.AbstractFileTreeElement;
-import org.gradle.internal.nativeplatform.filesystem.FileSystem;
-
-import java.io.*;
-import java.util.Map;
-
-public class MappingCopySpecVisitor extends DelegatingCopySpecVisitor {
- private ReadableCopySpec spec;
- private FileSystem fileSystem;
-
- public MappingCopySpecVisitor(CopySpecVisitor visitor, FileSystem fileSystem) {
- super(visitor);
- this.fileSystem = fileSystem;
- }
-
- public void visitSpec(ReadableCopySpec spec) {
- this.spec = spec;
- getVisitor().visitSpec(spec);
- }
-
- public void visitDir(FileVisitDetails dirDetails) {
- getVisitor().visitDir(new FileVisitDetailsImpl(dirDetails, spec, fileSystem));
- }
-
- public void visitFile(final FileVisitDetails fileDetails) {
- FileVisitDetailsImpl details = new FileVisitDetailsImpl(fileDetails, spec, fileSystem);
- for (Action<? super FileCopyDetails> action : spec.getAllCopyActions()) {
- action.execute(details);
- if (details.excluded) {
- return;
- }
- }
- getVisitor().visitFile(details);
- }
-
- private static class FileVisitDetailsImpl extends AbstractFileTreeElement implements FileVisitDetails, FileCopyDetails {
- private final FileVisitDetails fileDetails;
- private final ReadableCopySpec spec;
- private FileSystem fileSystem;
- private final FilterChain filterChain = new FilterChain();
- private RelativePath relativePath;
- private boolean excluded;
- private Integer mode;
-
- public FileVisitDetailsImpl(FileVisitDetails fileDetails, ReadableCopySpec spec, FileSystem fileSystem) {
- this.fileDetails = fileDetails;
- this.spec = spec;
- this.fileSystem = fileSystem;
- }
-
- public String getDisplayName() {
- return fileDetails.toString();
- }
-
- public void stopVisiting() {
- fileDetails.stopVisiting();
- }
-
- public File getFile() {
- if (filterChain.hasFilters()) {
- throw new UnsupportedOperationException();
- } else {
- return fileDetails.getFile();
- }
- }
-
- public boolean isDirectory() {
- return fileDetails.isDirectory();
- }
-
- public long getLastModified() {
- return fileDetails.getLastModified();
- }
-
- public long getSize() {
- if (filterChain.hasFilters()) {
- ByteCountingOutputStream outputStream = new ByteCountingOutputStream();
- copyTo(outputStream);
- return outputStream.size;
- } else {
- return fileDetails.getSize();
- }
- }
-
- public InputStream open() {
- if (filterChain.hasFilters()) {
- return filterChain.transform(fileDetails.open());
- } else {
- return fileDetails.open();
- }
- }
-
- public void copyTo(OutputStream outstr) {
- if (filterChain.hasFilters()) {
- super.copyTo(outstr);
- } else {
- fileDetails.copyTo(outstr);
- }
- }
-
- public boolean copyTo(File target) {
- if (filterChain.hasFilters()) {
- return super.copyTo(target);
- } else {
- final boolean copied = fileDetails.copyTo(target);
- adaptPermissions(target);
- return copied;
- }
- }
-
- private void adaptPermissions(File target) {
- final Integer specMode = getMode();
- if(specMode !=null){
- try {
- fileSystem.chmod(target, specMode);
- } catch (IOException e) {
- throw new GradleException(String.format("Could not set permission %s on '%s'.", specMode, target), e);
- }
- }
- }
-
- public RelativePath getRelativePath() {
- if (relativePath == null) {
- RelativePath path = fileDetails.getRelativePath();
- relativePath = spec.getDestPath().append(path.isFile(), path.getSegments());
- }
- return relativePath;
- }
-
- public int getMode() {
- if (mode != null) {
- return mode;
- }
-
- Integer specMode = getSpecMode();
- if (specMode != null) {
- return specMode;
- }
-
- return fileDetails.getMode();
- }
-
- private Integer getSpecMode() {
- return fileDetails.isDirectory() ? spec.getDirMode() : spec.getFileMode();
- }
-
- public void setRelativePath(RelativePath path) {
- this.relativePath = path;
- }
-
- public void setName(String name) {
- relativePath = getRelativePath().replaceLastName(name);
- }
-
- public void setPath(String path) {
- relativePath = RelativePath.parse(getRelativePath().isFile(), path);
- }
-
- public void exclude() {
- excluded = true;
- }
-
- public void setMode(int mode) {
- this.mode = mode;
- }
-
- public ContentFilterable filter(Closure closure) {
- filterChain.add(closure);
- return this;
- }
-
- public ContentFilterable filter(Map<String, ?> properties, Class<? extends FilterReader> filterType) {
- filterChain.add(filterType, properties);
- return this;
- }
-
- public ContentFilterable filter(Class<? extends FilterReader> filterType) {
- filterChain.add(filterType);
- return this;
- }
-
- public ContentFilterable expand(Map<String, ?> properties) {
- filterChain.expand(properties);
- return this;
- }
- }
-
- private static class ByteCountingOutputStream extends OutputStream {
- long size;
-
- @Override
- public void write(int b) throws IOException {
- size++;
- }
-
- @Override
- public void write(byte[] b) throws IOException {
- size += b.length;
- }
-
- @Override
- public void write(byte[] b, int off, int len) throws IOException {
- size += len;
- }
- }
-}
\ No newline at end of file
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/MatchingCopyAction.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/MatchingCopyAction.java
new file mode 100644
index 0000000..74329be
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/MatchingCopyAction.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.file.copy;
+
+import org.gradle.api.Action;
+import org.gradle.api.file.FileCopyDetails;
+import org.gradle.api.file.RelativePath;
+import org.gradle.api.specs.Spec;
+
+public class MatchingCopyAction implements Action<FileCopyDetails> {
+
+ private final Spec<RelativePath> matchSpec;
+
+ private final Action<? super FileCopyDetails> toApply;
+
+ public MatchingCopyAction(Spec<RelativePath> matchSpec, Action<? super FileCopyDetails> toApply) {
+ this.matchSpec = matchSpec;
+ this.toApply = toApply;
+ }
+
+ public void execute(FileCopyDetails details) {
+ if (matchSpec.isSatisfiedBy(details.getRelativePath())) {
+ toApply.execute(details);
+ }
+ }
+
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/NormalizingCopyActionDecorator.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/NormalizingCopyActionDecorator.java
new file mode 100644
index 0000000..ab51d92
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/NormalizingCopyActionDecorator.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.file.copy;
+
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.ListMultimap;
+import groovy.lang.Closure;
+import org.gradle.api.file.ContentFilterable;
+import org.gradle.api.file.DuplicatesStrategy;
+import org.gradle.api.file.RelativePath;
+import org.gradle.api.internal.file.AbstractFileTreeElement;
+import org.gradle.api.internal.file.CopyActionProcessingStreamAction;
+import org.gradle.api.tasks.WorkResult;
+
+import java.io.File;
+import java.io.FilterReader;
+import java.io.InputStream;
+import java.util.*;
+
+/**
+ * A {@link CopyAction} which cleans up the tree as it is visited. Removes duplicate directories and adds in missing directories. Removes empty directories if instructed to do so by copy
+ * spec.
+ */
+public class NormalizingCopyActionDecorator implements CopyAction {
+
+ private final CopyAction delegate;
+
+ public NormalizingCopyActionDecorator(CopyAction delegate) {
+ this.delegate = delegate;
+ }
+
+ public WorkResult execute(final CopyActionProcessingStream stream) {
+ final Set<RelativePath> visitedDirs = new HashSet<RelativePath>();
+ final ListMultimap<RelativePath, FileCopyDetailsInternal> pendingDirs = ArrayListMultimap.create();
+
+ WorkResult result = delegate.execute(new CopyActionProcessingStream() {
+ public void process(final CopyActionProcessingStreamAction action) {
+
+
+ stream.process(new CopyActionProcessingStreamAction() {
+ public void processFile(FileCopyDetailsInternal details) {
+ if (details.isDirectory()) {
+ RelativePath path = details.getRelativePath();
+ if (!visitedDirs.contains(path)) {
+ pendingDirs.put(path, details);
+ }
+ } else {
+ maybeVisit(details.getRelativePath().getParent(), details.isIncludeEmptyDirs(), action);
+ action.processFile(details);
+ }
+ }
+ });
+
+ for (RelativePath path : new LinkedHashSet<RelativePath>(pendingDirs.keySet())) {
+ List<FileCopyDetailsInternal> detailsList = new ArrayList<FileCopyDetailsInternal>(pendingDirs.get(path));
+ for (FileCopyDetailsInternal details : detailsList) {
+ if (details.isIncludeEmptyDirs()) {
+ maybeVisit(path, details.isIncludeEmptyDirs(), action);
+ }
+ }
+ }
+
+ visitedDirs.clear();
+ pendingDirs.clear();
+ }
+
+ private void maybeVisit(RelativePath path, boolean includeEmptyDirs, CopyActionProcessingStreamAction delegateAction) {
+ if (path == null || path.getParent() == null || !visitedDirs.add(path)) {
+ return;
+ }
+ maybeVisit(path.getParent(), includeEmptyDirs, delegateAction);
+ List<FileCopyDetailsInternal> detailsForPath = pendingDirs.removeAll(path);
+
+ FileCopyDetailsInternal dir;
+ if (detailsForPath.isEmpty()) {
+ // TODO - this is pretty nasty, look at avoiding using a time bomb stub here
+ dir = new StubbedFileCopyDetails(path, includeEmptyDirs);
+ } else {
+ dir = detailsForPath.get(0);
+ }
+ delegateAction.processFile(dir);
+ }
+ });
+
+ return result;
+ }
+
+
+ private static class StubbedFileCopyDetails extends AbstractFileTreeElement implements FileCopyDetailsInternal {
+ private final RelativePath path;
+ private final boolean includeEmptyDirs;
+ private long lastModified = System.currentTimeMillis();
+
+ private StubbedFileCopyDetails(RelativePath path, boolean includeEmptyDirs) {
+ this.path = path;
+ this.includeEmptyDirs = includeEmptyDirs;
+ }
+
+ public boolean isIncludeEmptyDirs() {
+ return includeEmptyDirs;
+ }
+
+ @Override
+ public String getDisplayName() {
+ return path.toString();
+ }
+
+ public File getFile() {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean isDirectory() {
+ return !path.isFile();
+ }
+
+ public long getLastModified() {
+ return lastModified;
+ }
+
+ public long getSize() {
+ throw new UnsupportedOperationException();
+ }
+
+ public InputStream open() {
+ throw new UnsupportedOperationException();
+ }
+
+ public RelativePath getRelativePath() {
+ return path;
+ }
+
+ public void exclude() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void setName(String name) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void setPath(String path) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void setRelativePath(RelativePath path) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void setMode(int mode) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void setDuplicatesStrategy(DuplicatesStrategy strategy) {
+ throw new UnsupportedOperationException();
+ }
+
+ public DuplicatesStrategy getDuplicatesStrategy() {
+ throw new UnsupportedOperationException();
+ }
+
+ public ContentFilterable filter(Map<String, ?> properties, Class<? extends FilterReader> filterType) {
+ throw new UnsupportedOperationException();
+ }
+
+ public ContentFilterable filter(Class<? extends FilterReader> filterType) {
+ throw new UnsupportedOperationException();
+ }
+
+ public ContentFilterable filter(Closure closure) {
+ throw new UnsupportedOperationException();
+ }
+
+ public ContentFilterable expand(Map<String, ?> properties) {
+ throw new UnsupportedOperationException();
+ }
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/NormalizingCopySpecVisitor.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/NormalizingCopySpecVisitor.java
deleted file mode 100644
index f35c3e6..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/NormalizingCopySpecVisitor.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.file.copy;
-
-import org.gradle.api.file.FileVisitDetails;
-import org.gradle.api.file.RelativePath;
-import org.gradle.api.internal.file.AbstractFileTreeElement;
-
-import java.io.File;
-import java.io.InputStream;
-import java.util.*;
-
-/**
- * A {@link CopySpecVisitor} which cleans up the tree as it is visited. Removes duplicate directories and
- * adds in missing directories. Removes empty directories if instructed to do so by copy spec.
- */
-public class NormalizingCopySpecVisitor extends DelegatingCopySpecVisitor {
- private ReadableCopySpec spec;
- private final Set<RelativePath> visitedDirs = new HashSet<RelativePath>();
- private final Map<RelativePath, FileVisitDetails> pendingDirs = new HashMap<RelativePath, FileVisitDetails>();
-
- public NormalizingCopySpecVisitor(CopySpecVisitor visitor) {
- super(visitor);
- }
-
- @Override
- public void visitSpec(ReadableCopySpec spec) {
- this.spec = spec;
- getVisitor().visitSpec(spec);
- }
-
- public void endVisit() {
- if (spec.getIncludeEmptyDirs()) {
- for (RelativePath path : new ArrayList<RelativePath>(pendingDirs.keySet())) {
- maybeVisit(path);
- }
- }
- visitedDirs.clear();
- pendingDirs.clear();
- getVisitor().endVisit();
- }
-
- private void maybeVisit(RelativePath path) {
- if (path == null || path.getParent() == null || !visitedDirs.add(path)) {
- return;
- }
- maybeVisit(path.getParent());
- FileVisitDetails dir = pendingDirs.remove(path);
- if (dir == null) {
- dir = new FileVisitDetailsImpl(path);
- }
- getVisitor().visitDir(dir);
- }
-
- public void visitFile(FileVisitDetails fileDetails) {
- maybeVisit(fileDetails.getRelativePath().getParent());
- getVisitor().visitFile(fileDetails);
- }
-
- public void visitDir(FileVisitDetails dirDetails) {
- RelativePath path = dirDetails.getRelativePath();
- if (!visitedDirs.contains(path)) {
- pendingDirs.put(path, dirDetails);
- }
- }
-
- private static class FileVisitDetailsImpl extends AbstractFileTreeElement implements FileVisitDetails {
- private final RelativePath path;
- private long lastModified = System.currentTimeMillis();
-
- private FileVisitDetailsImpl(RelativePath path) {
- this.path = path;
- }
-
- @Override
- public String getDisplayName() {
- return path.toString();
- }
-
- public void stopVisiting() {
- throw new UnsupportedOperationException();
- }
-
- public File getFile() {
- throw new UnsupportedOperationException();
- }
-
- public boolean isDirectory() {
- return !path.isFile();
- }
-
- public long getLastModified() {
- return lastModified;
- }
-
- public long getSize() {
- throw new UnsupportedOperationException();
- }
-
- public InputStream open() {
- throw new UnsupportedOperationException();
- }
-
- public RelativePath getRelativePath() {
- return path;
- }
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/ReadableCopySpec.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/ReadableCopySpec.java
index 6a623b8..82334d8 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/ReadableCopySpec.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/ReadableCopySpec.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2009 the original author or authors.
+ * Copyright 2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,29 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.gradle.api.internal.file.copy;
-
-import org.gradle.api.Action;
-import org.gradle.api.file.FileCopyDetails;
-import org.gradle.api.file.FileTree;
-import org.gradle.api.file.RelativePath;
-import java.util.Collection;
+package org.gradle.api.internal.file.copy;
+/**
+ * DO NOT REMOVE.
+ *
+ * Prior to 1.8, Copy implemented this so it is needed to keep backwards compatibility.
+ */
+ at SuppressWarnings("UnusedDeclaration")
+ at Deprecated
public interface ReadableCopySpec {
- RelativePath getDestPath();
-
- Integer getFileMode();
-
- Integer getDirMode();
-
- FileTree getSource();
-
- Collection<? extends ReadableCopySpec> getAllSpecs();
-
- boolean hasSource();
-
- Collection<? extends Action<? super FileCopyDetails>> getAllCopyActions();
-
- boolean getIncludeEmptyDirs();
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/RegExpNameMapper.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/RegExpNameMapper.java
index c871185..55df249 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/RegExpNameMapper.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/RegExpNameMapper.java
@@ -20,9 +20,6 @@ import org.gradle.api.Transformer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-/**
- * @author Steve Appling
- */
public class RegExpNameMapper implements Transformer<String, String> {
private Matcher matcher;
private String replacement;
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/RelativizedCopySpec.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/RelativizedCopySpec.java
new file mode 100644
index 0000000..5a945bf
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/RelativizedCopySpec.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.file.copy;
+
+import org.gradle.api.Transformer;
+import org.gradle.api.file.RelativePath;
+
+import static org.gradle.util.CollectionUtils.collect;
+
+public class RelativizedCopySpec extends DelegatingCopySpec {
+
+ private final CopySpecInternal parent;
+ private final CopySpecInternal child;
+
+ public RelativizedCopySpec(CopySpecInternal parent, CopySpecInternal child) {
+ this.parent = parent;
+ this.child = child;
+ }
+
+ @Override
+ protected CopySpecInternal getDelegateCopySpec() {
+ return child;
+ }
+
+ public RelativePath getDestPath() {
+ return parent.getDestPath().append(child.getDestPath());
+ }
+
+ @Override
+ public Iterable<CopySpecInternal> getChildren() {
+ return collect(super.getChildren(), new Transformer<CopySpecInternal, CopySpecInternal>() {
+ public CopySpecInternal transform(CopySpecInternal original) {
+ return new RelativizedCopySpec(parent, original);
+ }
+ });
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/SyncCopyActionDecorator.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/SyncCopyActionDecorator.java
new file mode 100644
index 0000000..68a12b1
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/SyncCopyActionDecorator.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.file.copy;
+
+import org.gradle.api.file.FileVisitDetails;
+import org.gradle.api.file.FileVisitor;
+import org.gradle.api.file.RelativePath;
+import org.gradle.api.internal.file.CopyActionProcessingStreamAction;
+import org.gradle.api.internal.file.collections.DirectoryFileTree;
+import org.gradle.api.internal.file.collections.MinimalFileTree;
+import org.gradle.api.internal.tasks.SimpleWorkResult;
+import org.gradle.api.tasks.WorkResult;
+import org.gradle.util.GFileUtils;
+
+import java.io.File;
+import java.util.HashSet;
+import java.util.Set;
+
+public class SyncCopyActionDecorator implements CopyAction {
+ private final File baseDestDir;
+ private final CopyAction delegate;
+
+ public SyncCopyActionDecorator(File baseDestDir, CopyAction delegate) {
+ this.baseDestDir = baseDestDir;
+ this.delegate = delegate;
+ }
+
+ public WorkResult execute(final CopyActionProcessingStream stream) {
+ final Set<RelativePath> visited = new HashSet<RelativePath>();
+
+ WorkResult didWork = delegate.execute(new CopyActionProcessingStream() {
+ public void process(final CopyActionProcessingStreamAction action) {
+ stream.process(new CopyActionProcessingStreamAction() {
+ public void processFile(FileCopyDetailsInternal details) {
+ visited.add(details.getRelativePath());
+ action.processFile(details);
+ }
+ });
+ }
+ });
+
+ SyncCopyActionDecoratorFileVisitor fileVisitor = new SyncCopyActionDecoratorFileVisitor(visited);
+
+ MinimalFileTree walker = new DirectoryFileTree(baseDestDir).postfix();
+ walker.visit(fileVisitor);
+ visited.clear();
+
+ return new SimpleWorkResult(didWork.getDidWork() || fileVisitor.didWork);
+ }
+
+ private static class SyncCopyActionDecoratorFileVisitor implements FileVisitor {
+ private final Set<RelativePath> visited;
+ private boolean didWork;
+
+ private SyncCopyActionDecoratorFileVisitor(Set<RelativePath> visited) {
+ this.visited = visited;
+ }
+
+ public void visitDir(FileVisitDetails dirDetails) {
+ maybeDelete(dirDetails, true);
+ }
+
+ public void visitFile(FileVisitDetails fileDetails) {
+ maybeDelete(fileDetails, false);
+ }
+
+ private void maybeDelete(FileVisitDetails fileDetails, boolean isDir) {
+ RelativePath path = fileDetails.getRelativePath();
+ if (!visited.contains(path)) {
+ if (isDir) {
+ GFileUtils.deleteDirectory(fileDetails.getFile());
+ } else {
+ GFileUtils.deleteQuietly(fileDetails.getFile());
+ }
+ didWork = true;
+ }
+ }
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/SyncCopySpecVisitor.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/SyncCopySpecVisitor.java
deleted file mode 100644
index 74783f3..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/copy/SyncCopySpecVisitor.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.file.copy;
-
-import org.gradle.api.file.FileVisitDetails;
-import org.gradle.api.file.FileVisitor;
-import org.gradle.api.file.RelativePath;
-import org.gradle.api.internal.file.collections.DirectoryFileTree;
-import org.gradle.api.internal.file.collections.MinimalFileTree;
-import org.gradle.util.GFileUtils;
-
-import java.io.File;
-import java.util.HashSet;
-import java.util.Set;
-
-public class SyncCopySpecVisitor extends DelegatingCopySpecVisitor {
- private final Set<RelativePath> visited = new HashSet<RelativePath>();
- private File baseDestDir;
- private boolean didWork;
-
- public SyncCopySpecVisitor(CopySpecVisitor visitor) {
- super(visitor);
- }
-
- public void startVisit(CopyAction action) {
- baseDestDir = ((FileCopyAction) action).getDestinationDir();
- getVisitor().startVisit(action);
- }
-
- @Override
- public void visitDir(FileVisitDetails dirDetails) {
- visited.add(dirDetails.getRelativePath());
- getVisitor().visitDir(dirDetails);
- }
-
- @Override
- public void visitFile(FileVisitDetails fileDetails) {
- visited.add(fileDetails.getRelativePath());
- getVisitor().visitFile(fileDetails);
- }
-
- @Override
- public void endVisit() {
- FileVisitor visitor = new FileVisitor() {
- public void visitDir(FileVisitDetails dirDetails) {
- maybeDelete(dirDetails, true);
- }
-
- public void visitFile(FileVisitDetails fileDetails) {
- maybeDelete(fileDetails, false);
- }
-
- private void maybeDelete(FileVisitDetails fileDetails, boolean isDir) {
- RelativePath path = fileDetails.getRelativePath();
- if (!visited.contains(path)) {
- if (isDir) {
- GFileUtils.deleteDirectory(fileDetails.getFile());
- } else {
- GFileUtils.deleteQuietly(fileDetails.getFile());
- }
- didWork = true;
- }
- }
- };
-
- MinimalFileTree walker = new DirectoryFileTree(baseDestDir).postfix();
- walker.visit(visitor);
- visited.clear();
-
- getVisitor().endVisit();
- }
-
- @Override
- public boolean getDidWork() {
- return didWork || getVisitor().getDidWork();
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/pattern/DefaultPatternMatcher.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/pattern/DefaultPatternMatcher.java
index 53dd653..3835636 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/pattern/DefaultPatternMatcher.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/pattern/DefaultPatternMatcher.java
@@ -18,13 +18,10 @@ package org.gradle.api.internal.file.pattern;
import org.gradle.api.file.RelativePath;
import org.gradle.api.specs.Spec;
-import java.util.List;
import java.util.ArrayList;
+import java.util.List;
import java.util.ListIterator;
-/**
- * @author Steve Appling
- */
public class DefaultPatternMatcher implements Spec<RelativePath> {
private List<PatternStep> steps;
private boolean partialMatchDirs;
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/pattern/GreedyPatternStep.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/pattern/GreedyPatternStep.java
index 7903443..e3a162d 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/pattern/GreedyPatternStep.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/pattern/GreedyPatternStep.java
@@ -15,9 +15,6 @@
*/
package org.gradle.api.internal.file.pattern;
-/**
- * @author Steve Appling
- */
public class GreedyPatternStep implements PatternStep{
public boolean matches(String candidate, boolean isFile) {
return true;
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/pattern/NameOnlyPatternMatcher.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/pattern/NameOnlyPatternMatcher.java
index 5092754..f29ba81 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/pattern/NameOnlyPatternMatcher.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/pattern/NameOnlyPatternMatcher.java
@@ -24,7 +24,6 @@ import org.gradle.api.specs.Spec;
*
* This will only match against the last part of a relative path and this only if
* the RelativePath is a File.
- * @author Steve Appling
*/
public class NameOnlyPatternMatcher implements Spec<RelativePath> {
private boolean partialMatchDirs;
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/pattern/PatternMatcherFactory.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/pattern/PatternMatcherFactory.java
index 9a8670f..cced12b 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/pattern/PatternMatcherFactory.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/pattern/PatternMatcherFactory.java
@@ -18,9 +18,6 @@ package org.gradle.api.internal.file.pattern;
import org.gradle.api.file.RelativePath;
import org.gradle.api.specs.Spec;
-/**
- * @author Steve Appling
- */
public class PatternMatcherFactory {
public static Spec<RelativePath> getPatternMatcher(boolean partialMatchDirs, boolean caseSensitive, String pattern) {
// trailing / or \ assumes **
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/pattern/PatternStep.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/pattern/PatternStep.java
index ddc46af..938eca4 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/pattern/PatternStep.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/pattern/PatternStep.java
@@ -15,9 +15,6 @@
*/
package org.gradle.api.internal.file.pattern;
-/**
- * @author Steve Appling
- */
public interface PatternStep {
public boolean matches(String candidate, boolean isFile);
public boolean isGreedy();
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/pattern/RegExpPatternStep.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/pattern/RegExpPatternStep.java
index ae80553..39dc6c8 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/file/pattern/RegExpPatternStep.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/file/pattern/RegExpPatternStep.java
@@ -18,9 +18,6 @@ package org.gradle.api.internal.file.pattern;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-/**
- * @author Steve Appling
- */
public class RegExpPatternStep implements PatternStep {
private static final String ESCAPE_CHARS = "\\[]^-&.{}()$+|<=!";
private static final String PATTERN_CHARS = "*?";
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/filestore/AbstractFileStoreEntry.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/filestore/AbstractFileStoreEntry.java
deleted file mode 100644
index 00bf480..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/filestore/AbstractFileStoreEntry.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.filestore;
-
-import org.gradle.util.hash.HashUtil;
-import org.gradle.util.hash.HashValue;
-
-public abstract class AbstractFileStoreEntry implements FileStoreEntry {
-
- public HashValue getSha1() {
- return HashUtil.createHash(getFile(), "SHA1");
- }
-
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/filestore/FileStore.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/filestore/FileStore.java
deleted file mode 100644
index bdf2339..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/filestore/FileStore.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.filestore;
-
-import org.gradle.api.Action;
-
-import java.io.File;
-
-public interface FileStore<K> {
-
- FileStoreEntry move(K key, File source);
-
- FileStoreEntry copy(K key, File source);
-
- void moveFilestore(File destination);
-
- FileStoreEntry add(K key, Action<File> addAction);
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/filestore/FileStoreEntry.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/filestore/FileStoreEntry.java
deleted file mode 100644
index 76298a5..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/filestore/FileStoreEntry.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.filestore;
-
-import org.gradle.util.hash.HashValue;
-
-import java.io.File;
-
-public interface FileStoreEntry {
-
- File getFile();
-
- HashValue getSha1();
-
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/filestore/FileStoreSearcher.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/filestore/FileStoreSearcher.java
deleted file mode 100644
index b23bdfd..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/filestore/FileStoreSearcher.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.filestore;
-
-import java.util.Set;
-
-public interface FileStoreSearcher<S> {
-
- Set<? extends FileStoreEntry> search(S key);
-
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/filestore/GroupedAndNamedUniqueFileStore.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/filestore/GroupedAndNamedUniqueFileStore.java
index 8127a95..ef9d545 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/filestore/GroupedAndNamedUniqueFileStore.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/filestore/GroupedAndNamedUniqueFileStore.java
@@ -18,6 +18,9 @@ package org.gradle.api.internal.filestore;
import org.gradle.api.Action;
import org.gradle.api.Transformer;
import org.gradle.api.internal.file.TemporaryFileProvider;
+import org.gradle.internal.filestore.FileStore;
+import org.gradle.internal.filestore.FileStoreSearcher;
+import org.gradle.internal.resource.local.LocallyAvailableResource;
import org.gradle.util.hash.HashUtil;
import java.io.File;
@@ -38,15 +41,15 @@ public class GroupedAndNamedUniqueFileStore<K> implements FileStore<K>, FileStor
this.namer = namer;
}
- public FileStoreEntry move(K key, File source) {
+ public LocallyAvailableResource move(K key, File source) {
return delegate.move(toPath(key, getChecksum(source)), source);
}
- public FileStoreEntry copy(K key, File source) {
+ public LocallyAvailableResource copy(K key, File source) {
return delegate.copy(toPath(key, getChecksum(source)), source);
}
- public Set<? extends FileStoreEntry> search(K key) {
+ public Set<? extends LocallyAvailableResource> search(K key) {
return delegate.search(toPath(key, "*"));
}
@@ -69,7 +72,7 @@ public class GroupedAndNamedUniqueFileStore<K> implements FileStore<K>, FileStor
delegate.moveFilestore(destination);
}
- public FileStoreEntry add(K key, Action<File> addAction) {
+ public LocallyAvailableResource add(K key, Action<File> addAction) {
//We cannot just delegate to the add method as we need the file content for checksum calculation here
//and reexecuting the action isn't acceptable
final File tempFile = getTempFile();
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/filestore/PathKeyFileStore.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/filestore/PathKeyFileStore.java
index e8f0be9..e5b8556 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/filestore/PathKeyFileStore.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/filestore/PathKeyFileStore.java
@@ -24,6 +24,10 @@ import org.gradle.api.internal.file.IdentityFileResolver;
import org.gradle.api.internal.file.collections.MinimalFileTree;
import org.gradle.api.internal.file.collections.SingleIncludePatternFileTree;
import org.gradle.api.internal.file.copy.DeleteActionImpl;
+import org.gradle.internal.filestore.FileStore;
+import org.gradle.internal.filestore.FileStoreSearcher;
+import org.gradle.internal.resource.local.AbstractLocallyAvailableResource;
+import org.gradle.internal.resource.local.LocallyAvailableResource;
import org.gradle.util.GFileUtils;
import java.io.File;
@@ -64,11 +68,11 @@ public class PathKeyFileStore implements FileStore<String>, FileStoreSearcher<St
return baseDir;
}
- public FileStoreEntry move(String path, File source) {
+ public LocallyAvailableResource move(String path, File source) {
return saveIntoFileStore(source, getFile(path), true);
}
- public FileStoreEntry copy(String path, File source) {
+ public LocallyAvailableResource copy(String path, File source) {
return saveIntoFileStore(source, getFile(path), false);
}
@@ -93,12 +97,12 @@ public class PathKeyFileStore implements FileStore<String>, FileStoreSearcher<St
baseDir = destination;
}
- public FileStoreEntry add(String path, Action<File> addAction) {
+ public LocallyAvailableResource add(String path, Action<File> addAction) {
String error = String.format("Failed to add into filestore '%s' at '%s' ", getBaseDir().getAbsolutePath(), path);
return doAdd(getFile(path), error, addAction);
}
- protected FileStoreEntry saveIntoFileStore(final File source, final File destination, final boolean isMove) {
+ protected LocallyAvailableResource saveIntoFileStore(final File source, final File destination, final boolean isMove) {
String verb = isMove ? "move" : "copy";
if (!source.exists()) {
@@ -118,7 +122,7 @@ public class PathKeyFileStore implements FileStore<String>, FileStoreSearcher<St
});
}
- protected FileStoreEntry doAdd(File destination, String failureDescription, Action<File> action) {
+ protected LocallyAvailableResource doAdd(File destination, String failureDescription, Action<File> action) {
try {
GFileUtils.parentMkdirs(destination);
File inProgressMarkerFile = getInProgressMarkerFile(destination);
@@ -138,12 +142,12 @@ public class PathKeyFileStore implements FileStore<String>, FileStoreSearcher<St
return entryAt(destination);
}
- public Set<? extends FileStoreEntry> search(String pattern) {
+ public Set<? extends LocallyAvailableResource> search(String pattern) {
if (!getBaseDir().exists()) {
return Collections.emptySet();
}
- final Set<FileStoreEntry> entries = new HashSet<FileStoreEntry>();
+ final Set<LocallyAvailableResource> entries = new HashSet<LocallyAvailableResource>();
findFiles(pattern).visit(new EmptyFileVisitor() {
public void visitFile(FileVisitDetails fileDetails) {
final File file = fileDetails.getFile();
@@ -174,19 +178,19 @@ public class PathKeyFileStore implements FileStore<String>, FileStoreSearcher<St
return new SingleIncludePatternFileTree(baseDir, pattern);
}
- protected FileStoreEntry entryAt(File file) {
+ protected LocallyAvailableResource entryAt(File file) {
return entryAt(GFileUtils.relativePath(baseDir, file));
}
- protected FileStoreEntry entryAt(final String path) {
- return new AbstractFileStoreEntry() {
+ protected LocallyAvailableResource entryAt(final String path) {
+ return new AbstractLocallyAvailableResource() {
public File getFile() {
return new File(baseDir, path);
}
};
}
- public FileStoreEntry get(String key) {
+ public LocallyAvailableResource get(String key) {
final File file = getFileWhileCleaningInProgress(key);
if (file.exists()) {
return entryAt(file);
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/filestore/PathNormalisingKeyFileStore.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/filestore/PathNormalisingKeyFileStore.java
index ab03a5a..be47d6e 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/filestore/PathNormalisingKeyFileStore.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/filestore/PathNormalisingKeyFileStore.java
@@ -17,6 +17,9 @@
package org.gradle.api.internal.filestore;
import org.gradle.api.Action;
+import org.gradle.internal.filestore.FileStore;
+import org.gradle.internal.filestore.FileStoreSearcher;
+import org.gradle.internal.resource.local.LocallyAvailableResource;
import java.io.File;
import java.util.Set;
@@ -33,11 +36,11 @@ public class PathNormalisingKeyFileStore implements FileStore<String>, FileStore
this.delegate = delegate;
}
- public FileStoreEntry move(String key, File source) {
+ public LocallyAvailableResource move(String key, File source) {
return delegate.move(normalizePath(key), source);
}
- public FileStoreEntry copy(String key, File source) {
+ public LocallyAvailableResource copy(String key, File source) {
return delegate.copy(key, source);
}
@@ -53,11 +56,11 @@ public class PathNormalisingKeyFileStore implements FileStore<String>, FileStore
delegate.moveFilestore(destination);
}
- public FileStoreEntry add(String key, Action<File> addAction) {
+ public LocallyAvailableResource add(String key, Action<File> addAction) {
return delegate.add(normalizePath(key), addAction);
}
- public Set<? extends FileStoreEntry> search(String key) {
+ public Set<? extends LocallyAvailableResource> search(String key) {
return delegate.search(normalizeSearchPath(key));
}
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/filestore/UniquePathKeyFileStore.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/filestore/UniquePathKeyFileStore.java
index 21c759c..4ba34b0 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/filestore/UniquePathKeyFileStore.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/filestore/UniquePathKeyFileStore.java
@@ -17,6 +17,7 @@
package org.gradle.api.internal.filestore;
import org.gradle.api.Action;
+import org.gradle.internal.resource.local.LocallyAvailableResource;
import org.gradle.util.GFileUtils;
import java.io.File;
@@ -33,8 +34,8 @@ public class UniquePathKeyFileStore extends PathKeyFileStore {
}
@Override
- public FileStoreEntry move(String path, File source) {
- FileStoreEntry entry = super.move(path, source);
+ public LocallyAvailableResource move(String path, File source) {
+ LocallyAvailableResource entry = super.move(path, source);
if (source.exists()) {
GFileUtils.deleteQuietly(source);
}
@@ -42,7 +43,7 @@ public class UniquePathKeyFileStore extends PathKeyFileStore {
}
@Override
- protected FileStoreEntry doAdd(File destination, String failureDescription, Action<File> action) {
+ protected LocallyAvailableResource doAdd(File destination, String failureDescription, Action<File> action) {
if (destination.exists()) {
return entryAt(destination);
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/initialization/AbstractScriptHandler.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/initialization/AbstractScriptHandler.java
index 27c19f6..8595bcd 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/initialization/AbstractScriptHandler.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/initialization/AbstractScriptHandler.java
@@ -22,7 +22,7 @@ import org.gradle.api.artifacts.dsl.DependencyHandler;
import org.gradle.api.artifacts.dsl.RepositoryHandler;
import org.gradle.groovy.scripts.ScriptSource;
import org.gradle.util.ConfigureUtil;
-import org.gradle.util.MutableURLClassLoader;
+import org.gradle.internal.classloader.MutableURLClassLoader;
import java.io.File;
import java.net.URI;
@@ -43,7 +43,7 @@ public abstract class AbstractScriptHandler implements ScriptHandlerInternal {
this.dependencyHandler = dependencyHandler;
this.scriptSource = scriptSource;
this.configContainer = configContainer;
- classpathConfiguration = configContainer.add(CLASSPATH_CONFIGURATION);
+ classpathConfiguration = configContainer.create(CLASSPATH_CONFIGURATION);
}
public void dependencies(Closure configureClosure) {
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/initialization/DefaultScriptHandler.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/initialization/DefaultScriptHandler.java
index a801482..ea95c72 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/initialization/DefaultScriptHandler.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/initialization/DefaultScriptHandler.java
@@ -19,7 +19,7 @@ import org.gradle.api.artifacts.ConfigurationContainer;
import org.gradle.api.artifacts.dsl.DependencyHandler;
import org.gradle.api.artifacts.dsl.RepositoryHandler;
import org.gradle.groovy.scripts.ScriptSource;
-import org.gradle.util.MutableURLClassLoader;
+import org.gradle.internal.classloader.MutableURLClassLoader;
import java.io.File;
import java.net.MalformedURLException;
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/initialization/DefaultScriptHandlerFactory.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/initialization/DefaultScriptHandlerFactory.java
index da94f98..aa18738 100755
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/initialization/DefaultScriptHandlerFactory.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/initialization/DefaultScriptHandlerFactory.java
@@ -28,7 +28,7 @@ import org.gradle.api.internal.artifacts.dsl.dependencies.ProjectFinder;
import org.gradle.api.internal.file.FileResolver;
import org.gradle.api.internal.project.ProjectInternal;
import org.gradle.groovy.scripts.ScriptSource;
-import org.gradle.util.MutableURLClassLoader;
+import org.gradle.internal.classloader.MutableURLClassLoader;
import java.util.Arrays;
import java.util.Collection;
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/initialization/NoClassLoaderUpdateScriptHandler.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/initialization/NoClassLoaderUpdateScriptHandler.java
index 5a596f6..5eb2060 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/initialization/NoClassLoaderUpdateScriptHandler.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/initialization/NoClassLoaderUpdateScriptHandler.java
@@ -19,7 +19,7 @@ import org.gradle.api.artifacts.ConfigurationContainer;
import org.gradle.api.artifacts.dsl.DependencyHandler;
import org.gradle.api.artifacts.dsl.RepositoryHandler;
import org.gradle.groovy.scripts.ScriptSource;
-import org.gradle.util.MutableURLClassLoader;
+import org.gradle.internal.classloader.MutableURLClassLoader;
public class NoClassLoaderUpdateScriptHandler extends AbstractScriptHandler {
public NoClassLoaderUpdateScriptHandler(MutableURLClassLoader classLoader, RepositoryHandler repositoryHandler,
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/NotationParserBuilder.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/NotationParserBuilder.java
index 94906af..53c70b3 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/NotationParserBuilder.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/NotationParserBuilder.java
@@ -28,9 +28,6 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Set;
-/**
- * by Szczepan Faber, created at: 11/8/11
- */
public class NotationParserBuilder<T> {
private TypeInfo<T> resultingType;
private String invalidNotationMessage;
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/TypeInfo.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/TypeInfo.java
index 89993b5..4ccc491 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/TypeInfo.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/TypeInfo.java
@@ -18,8 +18,6 @@ package org.gradle.api.internal.notations;
/**
* Type literal, useful for nested Generics.
- *
- * by Szczepan Faber, created at: 10/12/12
*/
public class TypeInfo<T> {
private final Class<T> targetType;
@@ -29,7 +27,7 @@ public class TypeInfo<T> {
this.targetType = targetType;
}
- Class<T> getTargetType() {
+ public Class<T> getTargetType() {
return targetType;
}
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/api/NotationParser.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/api/NotationParser.java
index e93ab7a..5ab149c 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/api/NotationParser.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/api/NotationParser.java
@@ -18,9 +18,6 @@ package org.gradle.api.internal.notations.api;
import java.util.Collection;
-/**
- * by Szczepan Faber, created at: 11/8/11
- */
public interface NotationParser<T> {
T parseNotation(Object notation) throws UnsupportedNotationException;
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/parsers/ClosureToSpecNotationParser.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/parsers/ClosureToSpecNotationParser.java
index 6f9cefd..2d43edb 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/parsers/ClosureToSpecNotationParser.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/parsers/ClosureToSpecNotationParser.java
@@ -24,9 +24,6 @@ import org.gradle.api.specs.Specs;
import java.util.Collection;
-/**
- * by Szczepan Faber, created at: 10/12/12
- */
public class ClosureToSpecNotationParser<T> implements NotationParser<Spec<T>> {
public Spec<T> parseNotation(Object notation) throws UnsupportedNotationException {
if (notation instanceof Closure) {
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/parsers/CompositeNotationParser.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/parsers/CompositeNotationParser.java
index db00741..9b0d35a 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/parsers/CompositeNotationParser.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/parsers/CompositeNotationParser.java
@@ -21,9 +21,6 @@ import org.gradle.api.internal.notations.api.UnsupportedNotationException;
import java.util.Collection;
-/**
- * by Szczepan Faber, created at: 11/10/11
- */
public class CompositeNotationParser<T> implements NotationParser<T> {
private final Collection<NotationParser<? extends T>> delegates;
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/parsers/ErrorHandlingNotationParser.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/parsers/ErrorHandlingNotationParser.java
index 527c1d4..74c8cb2 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/parsers/ErrorHandlingNotationParser.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/parsers/ErrorHandlingNotationParser.java
@@ -26,9 +26,6 @@ import java.util.Collection;
import java.util.Formatter;
import java.util.List;
-/**
- * by Szczepan Faber, created at: 11/8/11
- */
public class ErrorHandlingNotationParser<T> implements NotationParser<T> {
private final String targetTypeDisplayName;
private final String invalidNotationMessage;
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/parsers/JustReturningParser.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/parsers/JustReturningParser.java
index 7b7efc6..a159a64 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/parsers/JustReturningParser.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/parsers/JustReturningParser.java
@@ -20,9 +20,6 @@ import org.gradle.api.internal.notations.api.UnsupportedNotationException;
import java.util.Collection;
-/**
- * by Szczepan Faber, created at: 11/8/11
- */
public class JustReturningParser<T> implements NotationParser<T> {
private final Class<T> passThroughType;
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/parsers/MapNotationParser.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/parsers/MapNotationParser.java
index 834cbeb..e0b2619 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/parsers/MapNotationParser.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/parsers/MapNotationParser.java
@@ -85,7 +85,7 @@ public abstract class MapNotationParser<T> extends TypedNotationParser<Map, T> i
params[i] = value;
}
if (!missing.isEmpty()) {
- //TODO SF below could be better.
+ //below could be better.
//Throwing InvalidUserDataException here means that useful context information (including candidate formats, etc.) is not presented to the user
throw new InvalidUserDataException(String.format("Required keys %s are missing from map %s.", missing, values));
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/parsers/NormalizedTimeUnit.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/parsers/NormalizedTimeUnit.java
index 0cf3327..8fba2e4 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/parsers/NormalizedTimeUnit.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/parsers/NormalizedTimeUnit.java
@@ -18,9 +18,6 @@ package org.gradle.api.internal.notations.parsers;
import java.util.concurrent.TimeUnit;
-/**
- * by Szczepan Faber, created at: 2/18/13
- */
public class NormalizedTimeUnit {
private int value;
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/parsers/TimeUnitsParser.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/parsers/TimeUnitsParser.java
index e37616f..3fa4b4c 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/parsers/TimeUnitsParser.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/parsers/TimeUnitsParser.java
@@ -22,9 +22,6 @@ import java.util.concurrent.TimeUnit;
import static org.gradle.api.internal.notations.parsers.NormalizedTimeUnit.millis;
-/**
- * by Szczepan Faber, created at: 2/12/13
- */
public class TimeUnitsParser {
public NormalizedTimeUnit parseNotation(CharSequence notation, int value) {
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/parsers/TypedNotationParser.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/parsers/TypedNotationParser.java
index 627c6a5..e1689ad 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/parsers/TypedNotationParser.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/notations/parsers/TypedNotationParser.java
@@ -16,14 +16,12 @@
package org.gradle.api.internal.notations.parsers;
+import org.gradle.api.internal.notations.TypeInfo;
import org.gradle.api.internal.notations.api.NotationParser;
import org.gradle.api.internal.notations.api.UnsupportedNotationException;
import java.util.Collection;
-/**
- * by Szczepan Faber, created at: 11/9/11
- */
public abstract class TypedNotationParser<N, T> implements NotationParser<T> {
private final Class<N> typeToken;
@@ -33,6 +31,11 @@ public abstract class TypedNotationParser<N, T> implements NotationParser<T> {
this.typeToken = typeToken;
}
+ public TypedNotationParser(TypeInfo<N> typeToken) {
+ assert typeToken != null : "typeToken cannot be null";
+ this.typeToken = typeToken.getTargetType();
+ }
+
public void describe(Collection<String> candidateFormats) {
candidateFormats.add(String.format("Instances of %s.", typeToken.getSimpleName()));
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/plugins/DefaultConvention.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/plugins/DefaultConvention.java
index 5584d4c..f0c8e26 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/plugins/DefaultConvention.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/plugins/DefaultConvention.java
@@ -22,17 +22,14 @@ import org.gradle.api.Action;
import org.gradle.api.GradleException;
import org.gradle.api.internal.BeanDynamicObject;
import org.gradle.api.internal.DynamicObject;
-import org.gradle.internal.reflect.Instantiator;
import org.gradle.api.plugins.Convention;
import org.gradle.api.plugins.ExtraPropertiesExtension;
+import org.gradle.internal.reflect.Instantiator;
import org.gradle.util.DeprecationLogger;
import java.util.*;
-/**
- * @author Hans Dockter
- */
-public class DefaultConvention implements Convention {
+public class DefaultConvention implements Convention, ExtensionContainerInternal {
private final Map<String, Object> plugins = new LinkedHashMap<String, Object>();
private final DefaultConvention.ExtensionsDynamicObject extensionsDynamicObject = new ExtensionsDynamicObject();
@@ -141,6 +138,10 @@ public class DefaultConvention implements Convention {
extensionsStorage.configureExtension(type, action);
}
+ public Map<String, Object> getAsMap() {
+ return extensionsStorage.getAsMap();
+ }
+
public Object propertyMissing(String name) {
return getByName(name);
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/plugins/DefaultObjectConfigurationAction.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/plugins/DefaultObjectConfigurationAction.java
index 31f7524..90a345a 100755
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/plugins/DefaultObjectConfigurationAction.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/plugins/DefaultObjectConfigurationAction.java
@@ -17,9 +17,9 @@
package org.gradle.api.internal.plugins;
import org.gradle.api.Plugin;
-import org.gradle.api.Project;
import org.gradle.api.internal.file.FileResolver;
import org.gradle.api.plugins.ObjectConfigurationAction;
+import org.gradle.api.plugins.PluginAware;
import org.gradle.configuration.ScriptPlugin;
import org.gradle.configuration.ScriptPluginFactory;
import org.gradle.groovy.scripts.UriScriptSource;
@@ -85,22 +85,22 @@ public class DefaultObjectConfigurationAction implements ObjectConfigurationActi
private void applyPlugin(Class<? extends Plugin> pluginClass) {
for (Object target : targets) {
- if (target instanceof Project) {
- Project project = (Project) target;
- project.getPlugins().apply(pluginClass);
+ if (target instanceof PluginAware) {
+ PluginAware pluginAware = (PluginAware) target;
+ pluginAware.getPlugins().apply(pluginClass);
} else {
- throw new UnsupportedOperationException(String.format("Cannot apply plugin of class '%s' to '%s' (class: %s) as it is not a Project", pluginClass.getName(), target.toString(), target.getClass().getName()));
+ throw new UnsupportedOperationException(String.format("Cannot apply plugin of class '%s' to '%s' (class: %s) as it does not implement PluginAware", pluginClass.getName(), target.toString(), target.getClass().getName()));
}
}
}
private void applyPlugin(String pluginId) {
for (Object target : targets) {
- if (target instanceof Project) {
- Project project = (Project) target;
- project.getPlugins().apply(pluginId);
+ if (target instanceof PluginAware) {
+ PluginAware pluginAware = (PluginAware) target;
+ pluginAware.getPlugins().apply(pluginId);
} else {
- throw new UnsupportedOperationException(String.format("Cannot apply plugin with id '%s' to '%s' (class: %s) as it is not a Project", pluginId, target.toString(), target.getClass().getName()));
+ throw new UnsupportedOperationException(String.format("Cannot apply plugin with id '%s' to '%s' (class: %s) as it does not implement PluginAware", pluginId, target.toString(), target.getClass().getName()));
}
}
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/plugins/DefaultPluginContainer.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/plugins/DefaultPluginContainer.java
new file mode 100644
index 0000000..1e88e9c
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/plugins/DefaultPluginContainer.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.plugins;
+
+import org.gradle.api.Plugin;
+import org.gradle.api.plugins.PluginAware;
+import org.gradle.api.plugins.PluginContainer;
+import org.gradle.api.plugins.UnknownPluginException;
+
+public class DefaultPluginContainer<T extends PluginAware> extends DefaultPluginCollection<Plugin> implements PluginContainer {
+ private PluginRegistry pluginRegistry;
+ private final T pluginAware;
+
+ public DefaultPluginContainer(PluginRegistry pluginRegistry, T pluginAware) {
+ super(Plugin.class);
+ this.pluginRegistry = pluginRegistry;
+ this.pluginAware = pluginAware;
+ }
+
+ public Plugin apply(String id) {
+ return addPluginInternal(getTypeForId(id));
+ }
+
+ public <T extends Plugin> T apply(Class<T> type) {
+ return addPluginInternal(type);
+ }
+
+ public boolean hasPlugin(String id) {
+ return findPlugin(id) != null;
+ }
+
+ public boolean hasPlugin(Class<? extends Plugin> type) {
+ return findPlugin(type) != null;
+ }
+
+ public Plugin findPlugin(String id) {
+ try {
+ return findPlugin(getTypeForId(id));
+ } catch (UnknownPluginException e) {
+ return null;
+ }
+ }
+
+ public <T extends Plugin> T findPlugin(Class<T> type) {
+ for (Plugin plugin : this) {
+ if (plugin.getClass().equals(type)) {
+ return type.cast(plugin);
+ }
+ }
+ return null;
+ }
+
+ private <T extends Plugin> T addPluginInternal(Class<T> type) {
+ if (findPlugin(type) == null) {
+ Plugin plugin = providePlugin(type);
+ add(plugin);
+ }
+ return type.cast(findPlugin(type));
+ }
+
+ public Plugin getPlugin(String id) {
+ Plugin plugin = findPlugin(id);
+ if (plugin == null) {
+ throw new UnknownPluginException("Plugin with id " + id + " has not been used.");
+ }
+ return plugin;
+ }
+
+ public Plugin getAt(String id) throws UnknownPluginException {
+ return getPlugin(id);
+ }
+
+ public <T extends Plugin> T getAt(Class<T> type) throws UnknownPluginException {
+ return getPlugin(type);
+ }
+
+ public <T extends Plugin> T getPlugin(Class<T> type) throws UnknownPluginException {
+ Plugin plugin = findPlugin(type);
+ if (plugin == null) {
+ throw new UnknownPluginException("Plugin with type " + type + " has not been used.");
+ }
+ return type.cast(plugin);
+ }
+
+ protected Class<? extends Plugin> getTypeForId(String id) {
+ return pluginRegistry.getTypeForId(id);
+ }
+
+ private Plugin<T> providePlugin(Class<? extends Plugin> type) {
+ Plugin<T> plugin = pluginRegistry.loadPlugin(type);
+ plugin.apply(pluginAware);
+ return plugin;
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/plugins/DefaultPluginRegistry.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/plugins/DefaultPluginRegistry.java
index fc0c279..cb72ee5 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/plugins/DefaultPluginRegistry.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/plugins/DefaultPluginRegistry.java
@@ -29,10 +29,6 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
-/**
- * @author Hans Dockter
- */
-
public class DefaultPluginRegistry implements PluginRegistry {
private final Map<String, Class<? extends Plugin>> idMappings = new HashMap<String, Class<? extends Plugin>>();
private final DefaultPluginRegistry parent;
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/plugins/DefaultProjectsPluginContainer.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/plugins/DefaultProjectsPluginContainer.java
deleted file mode 100644
index a6fe69a..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/plugins/DefaultProjectsPluginContainer.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.plugins;
-
-import org.gradle.api.Plugin;
-import org.gradle.api.Project;
-import org.gradle.api.plugins.PluginContainer;
-import org.gradle.api.plugins.UnknownPluginException;
-
-/**
- * @author Hans Dockter
- */
-public class DefaultProjectsPluginContainer extends DefaultPluginCollection<Plugin> implements PluginContainer {
- private PluginRegistry pluginRegistry;
- private final Project project;
-
- public DefaultProjectsPluginContainer(PluginRegistry pluginRegistry, Project project) {
- super(Plugin.class);
- this.pluginRegistry = pluginRegistry;
- this.project = project;
- }
-
- public Plugin apply(String id) {
- return addPluginInternal(getTypeForId(id));
- }
-
- public <T extends Plugin> T apply(Class<T> type) {
- return addPluginInternal(type);
- }
-
- public boolean hasPlugin(String id) {
- return findPlugin(id) != null;
- }
-
- public boolean hasPlugin(Class<? extends Plugin> type) {
- return findPlugin(type) != null;
- }
-
- public Plugin findPlugin(String id) {
- try {
- return findPlugin(getTypeForId(id));
- } catch (UnknownPluginException e) {
- return null;
- }
- }
-
- public <T extends Plugin> T findPlugin(Class<T> type) {
- for (Plugin plugin : this) {
- if (plugin.getClass().equals(type)) {
- return type.cast(plugin);
- }
- }
- return null;
- }
-
- private <T extends Plugin> T addPluginInternal(Class<T> type) {
- if (findPlugin(type) == null) {
- Plugin plugin = providePlugin(type);
- add(plugin);
- }
- return type.cast(findPlugin(type));
- }
-
- public Plugin getPlugin(String id) {
- Plugin plugin = findPlugin(id);
- if (plugin == null) {
- throw new UnknownPluginException("Plugin with id " + id + " has not been used.");
- }
- return plugin;
- }
-
- public Plugin getAt(String id) throws UnknownPluginException {
- return getPlugin(id);
- }
-
- public <T extends Plugin> T getAt(Class<T> type) throws UnknownPluginException {
- return getPlugin(type);
- }
-
- public <T extends Plugin> T getPlugin(Class<T> type) throws UnknownPluginException {
- Plugin plugin = findPlugin(type);
- if (plugin == null) {
- throw new UnknownPluginException("Plugin with type " + type + " has not been used.");
- }
- return type.cast(plugin);
- }
-
- protected Class<? extends Plugin> getTypeForId(String id) {
- return pluginRegistry.getTypeForId(id);
- }
-
- private Plugin<Project> providePlugin(Class<? extends Plugin> type) {
- Plugin<Project> plugin = pluginRegistry.loadPlugin(type);
- plugin.apply(project);
- return plugin;
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/plugins/ExtensionContainerInternal.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/plugins/ExtensionContainerInternal.java
new file mode 100644
index 0000000..1236d4d
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/plugins/ExtensionContainerInternal.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.plugins;
+
+import org.gradle.api.plugins.ExtensionContainer;
+
+import java.util.Map;
+
+public interface ExtensionContainerInternal extends ExtensionContainer {
+ /**
+ * Provides access to all known extensions.
+ * @return A map of extensions, keyed by name.
+ */
+ Map<String, Object> getAsMap();
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/plugins/ExtensionsStorage.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/plugins/ExtensionsStorage.java
index 00372ba..e3a4026 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/plugins/ExtensionsStorage.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/plugins/ExtensionsStorage.java
@@ -22,6 +22,7 @@ import org.gradle.api.InvalidUserDataException;
import org.gradle.api.UnknownDomainObjectException;
import org.gradle.api.internal.ClosureBackedAction;
import org.gradle.api.plugins.DeferredConfigurable;
+import org.gradle.internal.UncheckedException;
import org.gradle.listener.ActionBroadcast;
import org.gradle.listener.ListenerNotificationException;
@@ -30,9 +31,6 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
-/**
- * @author Szczepan Faber, created at: 6/24/11
- */
public class ExtensionsStorage {
private final Map<String, ExtensionHolder> extensions = new LinkedHashMap<String, ExtensionHolder>();
@@ -40,7 +38,7 @@ public class ExtensionsStorage {
if (extensions.containsKey(name)) {
throw new IllegalArgumentException(String.format("Cannot add extension with name '%s', as there is an extension already registered with that name.", name));
}
- extensions.put(name, wrap(extension));
+ extensions.put(name, wrap(name, extension));
}
public boolean hasExtension(String name) {
@@ -81,11 +79,13 @@ public class ExtensionsStorage {
}
public <T> T findByType(Class<T> type) {
+ ExtensionHolder<T> holder;
try {
- return getHolderByType(type).get();
+ holder = getHolderByType(type);
} catch (UnknownDomainObjectException e) {
return null;
}
+ return holder.get();
}
private <T> ExtensionHolder<T> getHolderByType(Class<T> type) {
@@ -112,9 +112,9 @@ public class ExtensionsStorage {
return extensionHolder == null ? null : extensionHolder.get();
}
- private <T> ExtensionHolder<T> wrap(T extension) {
+ private <T> ExtensionHolder<T> wrap(String name, T extension) {
if (isDeferredConfigurable(extension)) {
- return new DeferredConfigurableExtensionHolder<T>(extension);
+ return new DeferredConfigurableExtensionHolder<T>(name, extension);
}
return new ExtensionHolder<T>(extension);
}
@@ -149,11 +149,14 @@ public class ExtensionsStorage {
}
private static class DeferredConfigurableExtensionHolder<T> extends ExtensionHolder<T> {
+ private final String name;
private ActionBroadcast<T> actions = new ActionBroadcast<T>();
private boolean configured;
+ private Throwable configureFailure;
- private DeferredConfigurableExtensionHolder(T extension) {
+ public DeferredConfigurableExtensionHolder(String name, T extension) {
super(extension);
+ this.name = name;
}
public T get() {
@@ -169,7 +172,7 @@ public class ExtensionsStorage {
private void configureLater(Action<? super T> action) {
if (configured) {
- throw new IllegalStateException("The 'publishing' extension is already configured");
+ throw new InvalidUserDataException(String.format("Cannot configure the '%s' extension after it has been accessed.", name));
}
actions.add(action);
}
@@ -180,8 +183,13 @@ public class ExtensionsStorage {
try {
actions.execute(extension);
} catch (ListenerNotificationException e) {
- throw new InvalidUserDataException("A problem occurred configuring the 'publishing' extension", e.getCause());
+ configureFailure = e.getCause();
}
+ actions = null;
+ }
+
+ if (configureFailure != null) {
+ throw UncheckedException.throwAsUncheckedException(configureFailure);
}
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/plugins/PluginRegistry.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/plugins/PluginRegistry.java
index b14bd5f..45d0277 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/plugins/PluginRegistry.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/plugins/PluginRegistry.java
@@ -21,9 +21,6 @@ import org.gradle.api.plugins.PluginInstantiationException;
import org.gradle.api.plugins.UnknownPluginException;
import org.gradle.internal.reflect.Instantiator;
-/**
- * @author Hans Dockter
- */
public interface PluginRegistry {
<T extends Plugin> T loadPlugin(Class<T> pluginClass) throws PluginInstantiationException;
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/AbstractPluginAware.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/project/AbstractPluginAware.java
new file mode 100644
index 0000000..b1e2630
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/project/AbstractPluginAware.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.project;
+
+import groovy.lang.Closure;
+import org.gradle.api.internal.file.FileResolver;
+import org.gradle.api.internal.plugins.DefaultObjectConfigurationAction;
+import org.gradle.api.plugins.PluginAware;
+import org.gradle.configuration.ScriptPluginFactory;
+import org.gradle.util.ConfigureUtil;
+
+import java.util.Map;
+
+abstract public class AbstractPluginAware implements PluginAware {
+
+ public void apply(Closure closure) {
+ DefaultObjectConfigurationAction action = new DefaultObjectConfigurationAction(getFileResolver(), getScriptPluginFactory(), this);
+ ConfigureUtil.configure(closure, action);
+ action.execute();
+ }
+
+ public void apply(Map<String, ?> options) {
+ DefaultObjectConfigurationAction action = new DefaultObjectConfigurationAction(getFileResolver(), getScriptPluginFactory(), this);
+ ConfigureUtil.configureByMap(options, action);
+ action.execute();
+ }
+
+ protected abstract FileResolver getFileResolver();
+
+ protected abstract ScriptPluginFactory getScriptPluginFactory();
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/AbstractProject.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/project/AbstractProject.java
index 4162959..1676cb5 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/AbstractProject.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/project/AbstractProject.java
@@ -35,24 +35,26 @@ import org.gradle.api.internal.artifacts.configurations.ConfigurationContainerIn
import org.gradle.api.internal.artifacts.configurations.DependencyMetaDataProvider;
import org.gradle.api.internal.file.FileOperations;
import org.gradle.api.internal.file.FileResolver;
+import org.gradle.api.internal.file.copy.CopySpecInternal;
import org.gradle.api.internal.initialization.ScriptClassLoaderProvider;
-import org.gradle.api.internal.plugins.DefaultObjectConfigurationAction;
+import org.gradle.api.internal.plugins.ExtensionContainerInternal;
import org.gradle.api.internal.tasks.TaskContainerInternal;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
import org.gradle.api.logging.LoggingManager;
import org.gradle.api.plugins.Convention;
-import org.gradle.api.plugins.ExtensionContainer;
import org.gradle.api.plugins.PluginContainer;
import org.gradle.api.resources.ResourceHandler;
import org.gradle.api.tasks.Directory;
import org.gradle.api.tasks.WorkResult;
-import org.gradle.configuration.ProjectEvaluator;
import org.gradle.configuration.ScriptPlugin;
import org.gradle.configuration.ScriptPluginFactory;
+import org.gradle.configuration.project.ProjectConfigurationActionContainer;
+import org.gradle.configuration.project.ProjectEvaluator;
import org.gradle.groovy.scripts.ScriptSource;
import org.gradle.internal.Factory;
import org.gradle.internal.reflect.Instantiator;
+import org.gradle.internal.service.scopes.ServiceRegistryFactory;
import org.gradle.listener.ClosureBackedMethodInvocationDispatch;
import org.gradle.listener.ListenerBroadcast;
import org.gradle.logging.LoggingManagerInternal;
@@ -71,10 +73,7 @@ import static java.util.Collections.singletonMap;
import static org.gradle.util.GUtil.addMaps;
import static org.gradle.util.GUtil.isTrue;
-/**
- * @author Hans Dockter
- */
-public abstract class AbstractProject implements ProjectInternal, DynamicObjectAware {
+public abstract class AbstractProject extends AbstractPluginAware implements ProjectInternal, DynamicObjectAware {
private static Logger buildLogger = Logging.getLogger(Project.class);
private ServiceRegistryFactory services;
@@ -124,7 +123,7 @@ public abstract class AbstractProject implements ProjectInternal, DynamicObjectA
private TaskContainerInternal implicitTasksContainer;
- private IProjectRegistry<ProjectInternal> projectRegistry;
+ private ProjectRegistry<ProjectInternal> projectRegistry;
private DependencyHandler dependencyHandler;
@@ -146,9 +145,12 @@ public abstract class AbstractProject implements ProjectInternal, DynamicObjectA
private ExtensibleDynamicObject extensibleDynamicObject;
+ private ProjectConfigurationActionContainer configurationActions;
+
private String description;
private final Path path;
+ private ScriptPluginFactory scriptPluginFactory;
public AbstractProject(String name,
ProjectInternal parent,
@@ -189,9 +191,11 @@ public abstract class AbstractProject implements ProjectInternal, DynamicObjectA
dependencyHandler = services.get(DependencyHandler.class);
scriptHandler = services.get(ScriptHandler.class);
scriptClassLoaderProvider = services.get(ScriptClassLoaderProvider.class);
- projectRegistry = services.get(IProjectRegistry.class);
+ projectRegistry = services.get(ProjectRegistry.class);
loggingManager = services.get(LoggingManagerInternal.class);
softwareComponentContainer = services.get(SoftwareComponentContainer.class);
+ scriptPluginFactory = services.get(ScriptPluginFactory.class);
+ configurationActions = services.get(ProjectConfigurationActionContainer.class);
extensibleDynamicObject = new ExtensibleDynamicObject(this, services.get(Instantiator.class));
if (parent != null) {
@@ -379,7 +383,7 @@ public abstract class AbstractProject implements ProjectInternal, DynamicObjectA
return depth;
}
- public IProjectRegistry<ProjectInternal> getProjectRegistry() {
+ public ProjectRegistry<ProjectInternal> getProjectRegistry() {
return projectRegistry;
}
@@ -492,7 +496,7 @@ public abstract class AbstractProject implements ProjectInternal, DynamicObjectA
Map<String, Object> allArgs = new HashMap<String, Object>(args);
allArgs.put(Task.TASK_NAME, name);
allArgs.put(Task.TASK_ACTION, action);
- return taskContainer.add(allArgs);
+ return taskContainer.create(allArgs);
}
public Task createTask(Map<String, ?> args, String name, Action<? super Task> action) {
@@ -502,7 +506,7 @@ public abstract class AbstractProject implements ProjectInternal, DynamicObjectA
if (action != null) {
allArgs.put(Task.TASK_ACTION, action);
}
- return taskContainer.add(allArgs);
+ return taskContainer.create(allArgs);
}
private void warnCreateTaskDeprecated() {
@@ -726,7 +730,7 @@ public abstract class AbstractProject implements ProjectInternal, DynamicObjectA
} else if (task != null) {
throw new InvalidUserDataException(String.format("Cannot add directory task '%s' as a non-directory task with this name already exists.", name));
} else {
- dirTask = taskContainer.add(name, Directory.class);
+ dirTask = taskContainer.create(name, Directory.class);
}
}
return dirTask;
@@ -812,10 +816,18 @@ public abstract class AbstractProject implements ProjectInternal, DynamicObjectA
return fileOperations.copy(closure);
}
+ public WorkResult sync(Action<? super CopySpec> action) {
+ return fileOperations.sync(action);
+ }
+
public CopySpec copySpec(Closure closure) {
return fileOperations.copySpec(closure);
}
+ public CopySpecInternal copySpec(Action<? super CopySpec> action) {
+ return fileOperations.copySpec(action);
+ }
+
public ExecResult javaexec(Closure closure) {
return processOperations.javaexec(closure);
}
@@ -832,20 +844,6 @@ public abstract class AbstractProject implements ProjectInternal, DynamicObjectA
return getServices().get(DependencyMetaDataProvider.class).getModule();
}
- public void apply(Closure closure) {
- DefaultObjectConfigurationAction action = new DefaultObjectConfigurationAction(fileResolver, services.get(
- ScriptPluginFactory.class), this);
- configure(action, closure);
- action.execute();
- }
-
- public void apply(Map<String, ?> options) {
- DefaultObjectConfigurationAction action = new DefaultObjectConfigurationAction(fileResolver, services.get(
- ScriptPluginFactory.class), this);
- ConfigureUtil.configureByMap(options, action);
- action.execute();
- }
-
public AntBuilder ant(Closure configureClosure) {
return ConfigureUtil.configure(configureClosure, getAnt());
}
@@ -894,15 +892,15 @@ public abstract class AbstractProject implements ProjectInternal, DynamicObjectA
}
public Task task(String task) {
- return taskContainer.add(task);
+ return taskContainer.create(task);
}
public Task task(Object task) {
- return taskContainer.add(task.toString());
+ return taskContainer.create(task.toString());
}
public Task task(String task, Closure configureClosure) {
- return taskContainer.add(task).configure(configureClosure);
+ return taskContainer.create(task).configure(configureClosure);
}
public Task task(Object task, Closure configureClosure) {
@@ -910,7 +908,7 @@ public abstract class AbstractProject implements ProjectInternal, DynamicObjectA
}
public Task task(Map options, String task) {
- return taskContainer.add(addMaps(options, singletonMap(Task.TASK_NAME, task)));
+ return taskContainer.create(addMaps(options, singletonMap(Task.TASK_NAME, task)));
}
public Task task(Map options, Object task) {
@@ -918,13 +916,22 @@ public abstract class AbstractProject implements ProjectInternal, DynamicObjectA
}
public Task task(Map options, String task, Closure configureClosure) {
- return taskContainer.add(addMaps(options, singletonMap(Task.TASK_NAME, task))).configure(configureClosure);
+ return taskContainer.create(addMaps(options, singletonMap(Task.TASK_NAME, task))).configure(configureClosure);
}
public Task task(Map options, Object task, Closure configureClosure) {
return task(options, task.toString(), configureClosure);
}
+ public ProjectConfigurationActionContainer getConfigurationActions() {
+ return configurationActions;
+ }
+
+ @Override
+ protected ScriptPluginFactory getScriptPluginFactory() {
+ return scriptPluginFactory;
+ }
+
/**
* This is called by the task creation DSL. Need to find a cleaner way to do this...
*/
@@ -947,7 +954,8 @@ public abstract class AbstractProject implements ProjectInternal, DynamicObjectA
return instantiator.newInstance(FactoryNamedDomainObjectContainer.class, type, instantiator, new DynamicPropertyNamer(), factoryClosure);
}
- public ExtensionContainer getExtensions() {
- return getConvention();
+ public ExtensionContainerInternal getExtensions() {
+ return (ExtensionContainerInternal) getConvention();
}
+
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/DefaultAntBuilder.groovy b/subprojects/core/src/main/groovy/org/gradle/api/internal/project/DefaultAntBuilder.groovy
index 9cd1aa6..956df16 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/DefaultAntBuilder.groovy
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/project/DefaultAntBuilder.groovy
@@ -88,7 +88,7 @@ public class DefaultAntBuilder extends BasicAntBuilder {
newAntTargets.removeAll(existingAntTargets)
newAntTargets.each {name ->
Target target = antProject.targets[name]
- AntTarget task = gradleProject.tasks.add(target.name, AntTarget)
+ AntTarget task = gradleProject.tasks.create(target.name, AntTarget)
task.target = target
task.baseDir = baseDir
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/DefaultAntBuilderFactory.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/project/DefaultAntBuilderFactory.java
index 6b39102..fc9ef43 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/DefaultAntBuilderFactory.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/project/DefaultAntBuilderFactory.java
@@ -20,9 +20,6 @@ import org.gradle.api.AntBuilder;
import org.gradle.api.Project;
import org.gradle.internal.Factory;
-/**
- * @author Hans Dockter
- */
public class DefaultAntBuilderFactory implements Factory<AntBuilder> {
private final BuildListener buildListener;
private final Project project;
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/DefaultIsolatedAntBuilder.groovy b/subprojects/core/src/main/groovy/org/gradle/api/internal/project/DefaultIsolatedAntBuilder.groovy
index 9782958..ce7ebd0 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/DefaultIsolatedAntBuilder.groovy
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/project/DefaultIsolatedAntBuilder.groovy
@@ -18,6 +18,10 @@ package org.gradle.api.internal.project
import org.gradle.api.internal.ClassPathRegistry
import org.gradle.api.internal.project.ant.AntLoggingAdapter
import org.gradle.api.internal.project.ant.BasicAntBuilder
+import org.gradle.internal.classloader.ClassLoaderFactory
+import org.gradle.internal.classloader.FilteringClassLoader
+import org.gradle.internal.classloader.MultiParentClassLoader
+import org.gradle.internal.classloader.MutableURLClassLoader
import org.gradle.util.*
import org.gradle.internal.jvm.Jvm
import org.gradle.internal.classpath.DefaultClassPath
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/DefaultProject.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/project/DefaultProject.java
index 9981c87..5148f39 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/DefaultProject.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/project/DefaultProject.java
@@ -19,6 +19,7 @@ package org.gradle.api.internal.project;
import org.gradle.api.internal.GradleInternal;
import org.gradle.api.internal.NoConventionMapping;
import org.gradle.groovy.scripts.ScriptSource;
+import org.gradle.internal.service.scopes.ServiceRegistryFactory;
import java.io.File;
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/DefaultProjectAccessListener.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/project/DefaultProjectAccessListener.java
index ab2c723..7583d3c 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/DefaultProjectAccessListener.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/project/DefaultProjectAccessListener.java
@@ -18,9 +18,6 @@ package org.gradle.api.internal.project;
import org.gradle.initialization.ProjectAccessListener;
-/**
-* by Szczepan Faber, created at: 2/11/13
-*/
public class DefaultProjectAccessListener implements ProjectAccessListener {
public void beforeRequestingTaskByPath(ProjectInternal targetProject) {
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/DefaultProjectRegistry.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/project/DefaultProjectRegistry.java
index 38e6870..d4c0918 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/DefaultProjectRegistry.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/project/DefaultProjectRegistry.java
@@ -20,15 +20,12 @@ import org.gradle.api.specs.Spec;
import org.gradle.util.GUtil;
import java.io.File;
-import java.util.Map;
import java.util.HashMap;
-import java.util.Set;
import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
-/**
- * @author Hans Dockter
- */
-public class DefaultProjectRegistry<T extends ProjectIdentifier> implements IProjectRegistry<T> {
+public class DefaultProjectRegistry<T extends ProjectIdentifier> implements ProjectRegistry<T> {
private Map<String, T> projects = new HashMap<String, T>();
private Map<String, Set<T>> subProjects = new HashMap<String, Set<T>>();
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/GlobalServicesRegistry.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/project/GlobalServicesRegistry.java
deleted file mode 100755
index 1f4c673..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/GlobalServicesRegistry.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.project;
-
-import org.gradle.StartParameter;
-import org.gradle.api.internal.*;
-import org.gradle.api.internal.classpath.DefaultModuleRegistry;
-import org.gradle.api.internal.classpath.DefaultPluginModuleRegistry;
-import org.gradle.api.internal.classpath.ModuleRegistry;
-import org.gradle.api.internal.classpath.PluginModuleRegistry;
-import org.gradle.cache.internal.*;
-import org.gradle.cli.CommandLineConverter;
-import org.gradle.initialization.ClassLoaderRegistry;
-import org.gradle.initialization.DefaultClassLoaderRegistry;
-import org.gradle.initialization.DefaultCommandLineConverter;
-import org.gradle.internal.Factory;
-import org.gradle.internal.nativeplatform.ProcessEnvironment;
-import org.gradle.internal.nativeplatform.services.NativeServices;
-import org.gradle.internal.reflect.DirectInstantiator;
-import org.gradle.internal.reflect.Instantiator;
-import org.gradle.internal.service.DefaultServiceRegistry;
-import org.gradle.internal.service.ServiceRegistry;
-import org.gradle.listener.DefaultListenerManager;
-import org.gradle.listener.ListenerManager;
-import org.gradle.logging.LoggingServiceRegistry;
-import org.gradle.messaging.remote.MessagingServer;
-import org.gradle.messaging.remote.internal.MessagingServices;
-import org.gradle.util.ClassLoaderFactory;
-import org.gradle.util.DefaultClassLoaderFactory;
-
-/**
- * Contains the services shared by all builds in a given process.
- */
-public class GlobalServicesRegistry extends DefaultServiceRegistry {
- public GlobalServicesRegistry() {
- this(LoggingServiceRegistry.newProcessLogging());
- }
-
- public GlobalServicesRegistry(ServiceRegistry loggingServices) {
- super(loggingServices);
- add(NativeServices.getInstance());
- }
-
- protected CommandLineConverter<StartParameter> createCommandLine2StartParameterConverter() {
- return new DefaultCommandLineConverter();
- }
-
- protected ClassPathRegistry createClassPathRegistry() {
- return new DefaultClassPathRegistry(new DefaultClassPathProvider(get(ModuleRegistry.class)), new DynamicModulesClassPathProvider(get(ModuleRegistry.class), get(PluginModuleRegistry.class)));
- }
-
- protected DefaultModuleRegistry createModuleRegistry() {
- return new DefaultModuleRegistry();
- }
-
- protected DocumentationRegistry createDocumentationRegistry() {
- return new DocumentationRegistry(get(GradleDistributionLocator.class));
- }
-
- protected PluginModuleRegistry createPluginModuleRegistry() {
- return new DefaultPluginModuleRegistry(get(ModuleRegistry.class));
- }
-
- protected Factory<CacheFactory> createCacheFactory() {
- return new DefaultCacheFactory(get(FileLockManager.class));
- }
-
- protected ClassLoaderRegistry createClassLoaderRegistry() {
- return new DefaultClassLoaderRegistry(get(ClassPathRegistry.class), get(ClassLoaderFactory.class));
- }
-
- protected ListenerManager createListenerManager() {
- return new DefaultListenerManager();
- }
-
- protected ClassLoaderFactory createClassLoaderFactory() {
- return new DefaultClassLoaderFactory();
- }
-
- protected MessagingServices createMessagingServices() {
- return new MessagingServices(get(ClassLoaderRegistry.class).getPluginsClassLoader());
- }
-
- protected MessagingServer createMessagingServer() {
- return get(MessagingServices.class).get(MessagingServer.class);
- }
-
- protected ClassGenerator createClassGenerator() {
- return new AsmBackedClassGenerator();
- }
-
- protected Instantiator createInstantiator() {
- return new ClassGeneratorBackedInstantiator(get(ClassGenerator.class), new DirectInstantiator());
- }
-
- protected FileLockManager createFileLockManager() {
- return new DefaultFileLockManager(new DefaultProcessMetaDataProvider(get(ProcessEnvironment.class)));
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/GradleInternalServiceRegistry.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/project/GradleInternalServiceRegistry.java
deleted file mode 100644
index 996720f..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/GradleInternalServiceRegistry.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.project;
-
-import org.gradle.StartParameter;
-import org.gradle.api.internal.DependencyInjectingInstantiator;
-import org.gradle.api.internal.GradleInternal;
-import org.gradle.api.internal.artifacts.dsl.dependencies.ProjectFinder;
-import org.gradle.api.internal.changedetection.TaskArtifactStateCacheAccess;
-import org.gradle.api.internal.changedetection.TaskCacheLockHandlingBuildExecuter;
-import org.gradle.api.internal.plugins.DefaultPluginRegistry;
-import org.gradle.api.internal.plugins.PluginRegistry;
-import org.gradle.execution.*;
-import org.gradle.execution.taskgraph.DefaultTaskGraphExecuter;
-import org.gradle.execution.taskgraph.TaskPlanExecutor;
-import org.gradle.internal.service.DefaultServiceRegistry;
-import org.gradle.internal.service.ServiceRegistry;
-import org.gradle.listener.ListenerManager;
-
-import java.util.LinkedList;
-import java.util.List;
-
-import static java.util.Arrays.asList;
-
-/**
- * Contains the services for a given {@link GradleInternal} instance.
- */
-public class GradleInternalServiceRegistry extends DefaultServiceRegistry implements ServiceRegistryFactory {
- private final GradleInternal gradle;
-
- public GradleInternalServiceRegistry(ServiceRegistry parent, final GradleInternal gradle) {
- super(parent);
- this.gradle = gradle;
- add(new TaskExecutionServices(parent, gradle));
- }
-
- protected BuildExecuter createBuildExecuter() {
- List<BuildConfigurationAction> configs = new LinkedList<BuildConfigurationAction>();
- if (get(StartParameter.class).isConfigureOnDemand()) {
- configs.add(new ProjectEvaluatingAction());
- }
- configs.add(new DefaultTasksBuildExecutionAction());
- configs.add(new ExcludedTaskFilteringBuildConfigurationAction());
- configs.add(new TaskNameResolvingBuildConfigurationAction());
-
- return new DefaultBuildExecuter(
- configs,
- asList(new DryRunBuildExecutionAction(),
- new TaskCacheLockHandlingBuildExecuter(get(TaskArtifactStateCacheAccess.class)),
- new SelectedTaskExecutionAction()));
- }
-
- protected ProjectFinder createProjectFinder() {
- return new ProjectFinder() {
- public ProjectInternal getProject(String path) {
- return gradle.getRootProject().project(path);
- }
- };
- }
-
- protected IProjectRegistry createIProjectRegistry() {
- return new DefaultProjectRegistry<ProjectInternal>();
- }
-
- protected TaskGraphExecuter createTaskGraphExecuter() {
- return new DefaultTaskGraphExecuter(get(ListenerManager.class), get(TaskPlanExecutor.class));
- }
-
- protected PluginRegistry createPluginRegistry() {
- return new DefaultPluginRegistry(gradle.getScriptClassLoader(), new DependencyInjectingInstantiator(this));
- }
-
- public ServiceRegistryFactory createFor(Object domainObject) {
- if (domainObject instanceof ProjectInternal) {
- return new ProjectInternalServiceRegistry(this, (ProjectInternal) domainObject);
- }
- throw new UnsupportedOperationException();
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/IProjectFactory.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/project/IProjectFactory.java
index aaa8a91..7a16d04 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/IProjectFactory.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/project/IProjectFactory.java
@@ -20,8 +20,6 @@ import org.gradle.api.internal.GradleInternal;
/**
* Creates a {@link ProjectInternal} implementation.
- *
- * @author Hans Dockter
*/
public interface IProjectFactory {
ProjectInternal createProject(ProjectDescriptor projectDescriptor, ProjectInternal parent, GradleInternal gradle);
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/IProjectRegistry.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/project/IProjectRegistry.java
deleted file mode 100644
index 7136df8..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/IProjectRegistry.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2007-2008 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.project;
-
-import org.gradle.api.specs.Spec;
-
-import java.util.Set;
-import java.io.File;
-
-/**
- * @author Hans Dockter
- */
-public interface IProjectRegistry<T extends ProjectIdentifier> {
- void addProject(T project);
-
- T getProject(String path);
-
- T getProject(File projectDir);
-
- Set<T> getAllProjects();
-
- Set<T> getAllProjects(String path);
-
- Set<T> getSubProjects(String path);
-
- Set<T> findAll(Spec<? super T> constraint);
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/ProjectFactory.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/project/ProjectFactory.java
index 3fe76da..c3579a9 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/ProjectFactory.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/project/ProjectFactory.java
@@ -18,16 +18,13 @@ package org.gradle.api.internal.project;
import org.gradle.api.initialization.ProjectDescriptor;
import org.gradle.api.internal.GradleInternal;
-import org.gradle.internal.reflect.Instantiator;
import org.gradle.groovy.scripts.ScriptSource;
import org.gradle.groovy.scripts.StringScriptSource;
import org.gradle.groovy.scripts.UriScriptSource;
+import org.gradle.internal.reflect.Instantiator;
import java.io.File;
-/**
- * @author Hans Dockter
- */
public class ProjectFactory implements IProjectFactory {
private final Instantiator instantiator;
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/ProjectInternal.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/project/ProjectInternal.java
index b5a0fbd..b743906 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/ProjectInternal.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/project/ProjectInternal.java
@@ -27,9 +27,12 @@ import org.gradle.api.internal.artifacts.configurations.ConfigurationContainerIn
import org.gradle.api.internal.artifacts.configurations.DependencyMetaDataProvider;
import org.gradle.api.internal.file.FileOperations;
import org.gradle.api.internal.file.FileResolver;
+import org.gradle.api.internal.plugins.ExtensionContainerInternal;
import org.gradle.api.internal.tasks.TaskContainerInternal;
+import org.gradle.configuration.project.ProjectConfigurationActionContainer;
import org.gradle.groovy.scripts.ScriptAware;
import org.gradle.groovy.scripts.ScriptSource;
+import org.gradle.internal.service.scopes.ServiceRegistryFactory;
import org.gradle.logging.StandardOutputCapture;
public interface ProjectInternal extends Project, ProjectIdentifier, ScriptAware, FileOperations, ProcessOperations, DomainObjectContext, DependencyMetaDataProvider {
@@ -53,7 +56,7 @@ public interface ProjectInternal extends Project, ProjectIdentifier, ScriptAware
ProjectInternal findProject(String path);
- IProjectRegistry<ProjectInternal> getProjectRegistry();
+ ProjectRegistry<ProjectInternal> getProjectRegistry();
DynamicObject getInheritedScope();
@@ -68,4 +71,8 @@ public interface ProjectInternal extends Project, ProjectIdentifier, ScriptAware
StandardOutputCapture getStandardOutputCapture();
ProjectStateInternal getState();
+
+ ExtensionContainerInternal getExtensions();
+
+ ProjectConfigurationActionContainer getConfigurationActions();
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/ProjectInternalServiceRegistry.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/project/ProjectInternalServiceRegistry.java
deleted file mode 100644
index 712e621..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/ProjectInternalServiceRegistry.java
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.project;
-
-import org.gradle.api.AntBuilder;
-import org.gradle.api.artifacts.Module;
-import org.gradle.api.artifacts.dsl.ArtifactHandler;
-import org.gradle.api.artifacts.dsl.DependencyHandler;
-import org.gradle.api.artifacts.dsl.RepositoryHandler;
-import org.gradle.api.component.SoftwareComponentContainer;
-import org.gradle.api.internal.ClassGenerator;
-import org.gradle.api.internal.ClassGeneratorBackedInstantiator;
-import org.gradle.api.internal.DependencyInjectingInstantiator;
-import org.gradle.api.internal.TaskInternal;
-import org.gradle.api.internal.artifacts.ArtifactPublicationServices;
-import org.gradle.api.internal.artifacts.DependencyManagementServices;
-import org.gradle.api.internal.artifacts.DependencyResolutionServices;
-import org.gradle.api.internal.artifacts.ProjectBackedModule;
-import org.gradle.api.internal.artifacts.configurations.ConfigurationContainerInternal;
-import org.gradle.api.internal.artifacts.configurations.DependencyMetaDataProvider;
-import org.gradle.api.internal.artifacts.dsl.dependencies.ProjectFinder;
-import org.gradle.api.internal.component.DefaultSoftwareComponentContainer;
-import org.gradle.api.internal.file.*;
-import org.gradle.api.internal.initialization.DefaultScriptHandlerFactory;
-import org.gradle.api.internal.initialization.ScriptClassLoaderProvider;
-import org.gradle.api.internal.initialization.ScriptHandlerFactory;
-import org.gradle.api.internal.initialization.ScriptHandlerInternal;
-import org.gradle.api.internal.plugins.DefaultProjectsPluginContainer;
-import org.gradle.api.internal.plugins.PluginRegistry;
-import org.gradle.api.internal.project.ant.AntLoggingAdapter;
-import org.gradle.api.internal.project.taskfactory.ITaskFactory;
-import org.gradle.api.internal.tasks.DefaultTaskContainerFactory;
-import org.gradle.api.internal.tasks.TaskContainerInternal;
-import org.gradle.api.plugins.PluginContainer;
-import org.gradle.initialization.ProjectAccessListener;
-import org.gradle.internal.Factory;
-import org.gradle.internal.nativeplatform.filesystem.FileSystem;
-import org.gradle.internal.reflect.Instantiator;
-import org.gradle.internal.service.DefaultServiceRegistry;
-import org.gradle.internal.service.ServiceRegistry;
-import org.gradle.logging.LoggingManagerInternal;
-
-import java.io.File;
-
-/**
- * Contains the services for a given project.
- */
-public class ProjectInternalServiceRegistry extends DefaultServiceRegistry implements ServiceRegistryFactory {
- private final ProjectInternal project;
-
- public ProjectInternalServiceRegistry(ServiceRegistry parent, final ProjectInternal project) {
- super(parent);
- this.project = project;
- }
-
- protected PluginRegistry createPluginRegistry(PluginRegistry parentRegistry) {
- return parentRegistry.createChild(get(ScriptClassLoaderProvider.class).getClassLoader(), new DependencyInjectingInstantiator(this));
- }
-
- protected FileResolver createFileResolver() {
- return new BaseDirFileResolver(get(FileSystem.class), project.getProjectDir());
- }
-
- protected LoggingManagerInternal createLoggingManager() {
- return getFactory(LoggingManagerInternal.class).create();
- }
-
- protected DefaultFileOperations createFileOperations() {
- return new DefaultFileOperations(get(FileResolver.class), project.getTasks(), get(TemporaryFileProvider.class));
- }
-
- protected TemporaryFileProvider createTemporaryFileProvider() {
- return new DefaultTemporaryFileProvider(new Factory<File>() {
- public File create() {
- return new File(project.getBuildDir(), "tmp");
- }
- });
- }
-
- protected Factory<AntBuilder> createAntBuilderFactory() {
- return new DefaultAntBuilderFactory(new AntLoggingAdapter(), project);
- }
-
- protected PluginContainer createPluginContainer() {
- return new DefaultProjectsPluginContainer(get(PluginRegistry.class), project);
- }
-
- protected ITaskFactory createTaskFactory(ITaskFactory parentFactory) {
- return parentFactory.createChild(project, new ClassGeneratorBackedInstantiator(get(ClassGenerator.class), new DependencyInjectingInstantiator(this)));
- }
-
- protected Factory<TaskContainerInternal> createTaskContainerInternal() {
- return new DefaultTaskContainerFactory(get(Instantiator.class), get(ITaskFactory.class), project, get(ProjectAccessListener.class));
- }
-
- protected ArtifactPublicationServices createArtifactPublicationServices() {
- return get(DependencyResolutionServices.class).createArtifactPublicationServices();
- }
-
- protected RepositoryHandler createRepositoryHandler() {
- return get(DependencyResolutionServices.class).getResolveRepositoryHandler();
- }
-
- protected ConfigurationContainerInternal createConfigurationContainer() {
- return get(DependencyResolutionServices.class).getConfigurationContainer();
- }
-
- protected SoftwareComponentContainer createSoftwareComponentContainer() {
- Instantiator instantiator = get(Instantiator.class);
- return instantiator.newInstance(DefaultSoftwareComponentContainer.class, instantiator);
- }
-
- protected DependencyResolutionServices createDependencyResolutionServices() {
- return newDependencyResolutionServices();
- }
-
- private DependencyResolutionServices newDependencyResolutionServices() {
- return get(DependencyManagementServices.class).create(get(FileResolver.class), get(DependencyMetaDataProvider.class), get(ProjectFinder.class), project);
- }
-
- protected ArtifactHandler createArtifactHandler() {
- return get(DependencyResolutionServices.class).getArtifactHandler();
- }
-
- protected ProjectFinder createProjectFinder() {
- return new ProjectFinder() {
- public ProjectInternal getProject(String path) {
- return project.project(path);
- }
- };
- }
-
- protected DependencyHandler createDependencyHandler() {
- return get(DependencyResolutionServices.class).getDependencyHandler();
- }
-
- protected ScriptHandlerInternal createScriptHandler() {
- ScriptHandlerFactory factory = new DefaultScriptHandlerFactory(
- get(DependencyManagementServices.class),
- get(FileResolver.class),
- get(DependencyMetaDataProvider.class));
- ClassLoader parentClassLoader;
- if (project.getParent() != null) {
- parentClassLoader = project.getParent().getBuildscript().getClassLoader();
- } else {
- parentClassLoader = project.getGradle().getScriptClassLoader();
- }
- return factory.create(project.getBuildScriptSource(), parentClassLoader, project);
- }
-
- protected DependencyMetaDataProvider createDependencyMetaDataProvider() {
- return new DependencyMetaDataProvider() {
- public Module getModule() {
- return new ProjectBackedModule(project);
- }
- };
- }
-
- public ServiceRegistryFactory createFor(Object domainObject) {
- if (domainObject instanceof TaskInternal) {
- return new TaskInternalServiceRegistry(this, project, (TaskInternal)domainObject);
- }
- throw new UnsupportedOperationException();
- }
-
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/ProjectRegistry.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/project/ProjectRegistry.java
new file mode 100644
index 0000000..f0daee3
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/project/ProjectRegistry.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2007-2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.project;
+
+import org.gradle.api.specs.Spec;
+
+import java.io.File;
+import java.util.Set;
+
+public interface ProjectRegistry<T extends ProjectIdentifier> {
+ void addProject(T project);
+
+ T getProject(String path);
+
+ T getProject(File projectDir);
+
+ Set<T> getAllProjects();
+
+ Set<T> getAllProjects(String path);
+
+ Set<T> getSubProjects(String path);
+
+ Set<T> findAll(Spec<? super T> constraint);
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/ProjectStateInternal.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/project/ProjectStateInternal.java
index badaac5..14aa925 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/ProjectStateInternal.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/project/ProjectStateInternal.java
@@ -46,6 +46,10 @@ public class ProjectStateInternal implements ProjectState {
this.executing = executing;
}
+ public boolean hasFailure() {
+ return failure != null;
+ }
+
public Throwable getFailure() {
return failure;
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/ServiceRegistryFactory.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/project/ServiceRegistryFactory.java
deleted file mode 100644
index 1b3e36f..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/ServiceRegistryFactory.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.project;
-
-import org.gradle.internal.service.ServiceRegistry;
-
-/**
- * A hierarchical service registry.
- */
-public interface ServiceRegistryFactory extends ServiceRegistry {
- /**
- * Creates the services for the given domain object.
- *
- * @param domainObject The domain object.
- * @return The registry containing the services for the domain object.
- */
- ServiceRegistryFactory createFor(Object domainObject);
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/TaskExecutionServices.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/project/TaskExecutionServices.java
deleted file mode 100644
index 146f248..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/TaskExecutionServices.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.project;
-
-import org.gradle.StartParameter;
-import org.gradle.api.execution.TaskActionListener;
-import org.gradle.api.internal.changedetection.*;
-import org.gradle.api.internal.tasks.TaskExecuter;
-import org.gradle.api.internal.tasks.execution.*;
-import org.gradle.api.invocation.Gradle;
-import org.gradle.cache.CacheRepository;
-import org.gradle.execution.taskgraph.TaskPlanExecutor;
-import org.gradle.execution.taskgraph.TaskPlanExecutorFactory;
-import org.gradle.internal.id.RandomLongIdGenerator;
-import org.gradle.internal.service.DefaultServiceRegistry;
-import org.gradle.internal.service.ServiceRegistry;
-import org.gradle.listener.ListenerManager;
-
-public class TaskExecutionServices extends DefaultServiceRegistry {
- private final Gradle gradle;
-
- public TaskExecutionServices(ServiceRegistry parent, Gradle gradle) {
- super(parent);
- this.gradle = gradle;
- }
-
- protected TaskExecuter createTaskExecuter() {
- return new ExecuteAtMostOnceTaskExecuter(
- new SkipOnlyIfTaskExecuter(
- new SkipTaskWithNoActionsExecuter(
- new SkipEmptySourceFilesTaskExecuter(
- new ValidatingTaskExecuter(
- new SkipUpToDateTaskExecuter(
- new CacheLockHandlingTaskExecuter(
- new PostExecutionAnalysisTaskExecuter(
- new ExecuteActionsTaskExecuter(
- get(ListenerManager.class).getBroadcaster(TaskActionListener.class))),
- get(TaskArtifactStateCacheAccess.class)),
- get(TaskArtifactStateRepository.class)))))));
- }
-
- protected TaskArtifactStateCacheAccess createCacheAccess() {
- return new DefaultTaskArtifactStateCacheAccess(gradle, get(CacheRepository.class));
- }
-
- protected TaskArtifactStateRepository createTaskArtifactStateRepository() {
- TaskArtifactStateCacheAccess cacheAccess = get(TaskArtifactStateCacheAccess.class);
-
- FileSnapshotter fileSnapshotter = new DefaultFileSnapshotter(
- new CachingHasher(
- new DefaultHasher(),
- cacheAccess));
-
- FileSnapshotter outputFilesSnapshotter = new OutputFilesSnapshotter(fileSnapshotter, new RandomLongIdGenerator(), cacheAccess);
-
- TaskHistoryRepository taskHistoryRepository = new CacheBackedTaskHistoryRepository(cacheAccess, new CacheBackedFileSnapshotRepository(cacheAccess));
-
- return new FileCacheBroadcastTaskArtifactStateRepository(
- new ShortCircuitTaskArtifactStateRepository(
- get(StartParameter.class),
- new DefaultTaskArtifactStateRepository(
- taskHistoryRepository,
- fileSnapshotter,
- outputFilesSnapshotter)),
- new DefaultFileCacheListener());
- }
-
- protected TaskPlanExecutor createTaskExecutorFactory() {
- StartParameter startParameter = gradle.getStartParameter();
- TaskArtifactStateCacheAccess cacheAccess = get(TaskArtifactStateCacheAccess.class);
- return new TaskPlanExecutorFactory(cacheAccess, startParameter.getParallelThreadCount()).create();
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/TaskInternalServiceRegistry.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/project/TaskInternalServiceRegistry.java
deleted file mode 100644
index 95bbca0..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/TaskInternalServiceRegistry.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.project;
-
-import org.gradle.api.internal.TaskInternal;
-import org.gradle.api.internal.TaskOutputsInternal;
-import org.gradle.api.internal.tasks.DefaultTaskInputs;
-import org.gradle.api.internal.tasks.DefaultTaskOutputs;
-import org.gradle.api.internal.tasks.TaskStatusNagger;
-import org.gradle.api.tasks.TaskInputs;
-import org.gradle.internal.service.DefaultServiceRegistry;
-import org.gradle.internal.service.ServiceRegistry;
-import org.gradle.logging.LoggingManagerInternal;
-
-/**
- * Contains the services for a given task.
- */
-public class TaskInternalServiceRegistry extends DefaultServiceRegistry implements ServiceRegistryFactory {
- private final ProjectInternal project;
- private final TaskInternal taskInternal;
-
- public TaskInternalServiceRegistry(ServiceRegistry parent, final ProjectInternal project, TaskInternal taskInternal) {
- super(parent);
- this.project = project;
- this.taskInternal = taskInternal;
- }
-
- protected TaskInputs createTaskInputs() {
- return new DefaultTaskInputs(project.getFileResolver(), taskInternal, get(TaskStatusNagger.class));
- }
-
- protected TaskOutputsInternal createTaskOutputs() {
- return new DefaultTaskOutputs(project.getFileResolver(), taskInternal, get(TaskStatusNagger.class));
- }
-
- protected TaskStatusNagger createTaskStatusNagger() {
- return new TaskStatusNagger(taskInternal);
- }
-
- protected LoggingManagerInternal createLoggingManager() {
- return getFactory(LoggingManagerInternal.class).create();
- }
-
- public ServiceRegistryFactory createFor(Object domainObject) {
- throw new UnsupportedOperationException();
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/TopLevelBuildServiceRegistry.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/project/TopLevelBuildServiceRegistry.java
deleted file mode 100644
index d5b18f4..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/TopLevelBuildServiceRegistry.java
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.project;
-
-import org.gradle.StartParameter;
-import org.gradle.api.Project;
-import org.gradle.api.artifacts.Module;
-import org.gradle.api.internal.*;
-import org.gradle.api.internal.artifacts.DefaultModule;
-import org.gradle.api.internal.artifacts.DependencyManagementServices;
-import org.gradle.api.internal.artifacts.configurations.DependencyMetaDataProvider;
-import org.gradle.api.internal.classpath.ModuleRegistry;
-import org.gradle.api.internal.classpath.PluginModuleRegistry;
-import org.gradle.api.internal.file.FileResolver;
-import org.gradle.api.internal.file.IdentityFileResolver;
-import org.gradle.api.internal.initialization.DefaultScriptHandlerFactory;
-import org.gradle.api.internal.initialization.ScriptHandlerFactory;
-import org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory;
-import org.gradle.api.internal.project.taskfactory.DependencyAutoWireTaskFactory;
-import org.gradle.api.internal.project.taskfactory.ITaskFactory;
-import org.gradle.api.internal.project.taskfactory.TaskFactory;
-import org.gradle.cache.CacheRepository;
-import org.gradle.cache.CacheValidator;
-import org.gradle.cache.internal.CacheFactory;
-import org.gradle.cache.internal.DefaultCacheRepository;
-import org.gradle.configuration.*;
-import org.gradle.groovy.scripts.DefaultScriptCompilerFactory;
-import org.gradle.groovy.scripts.ScriptCompilerFactory;
-import org.gradle.groovy.scripts.ScriptExecutionListener;
-import org.gradle.groovy.scripts.internal.*;
-import org.gradle.initialization.*;
-import org.gradle.internal.Factory;
-import org.gradle.internal.TimeProvider;
-import org.gradle.internal.TrueTimeProvider;
-import org.gradle.internal.concurrent.DefaultExecutorFactory;
-import org.gradle.internal.concurrent.ExecutorFactory;
-import org.gradle.internal.id.LongIdGenerator;
-import org.gradle.internal.reflect.Instantiator;
-import org.gradle.internal.service.DefaultServiceRegistry;
-import org.gradle.internal.service.ServiceLocator;
-import org.gradle.internal.service.ServiceRegistry;
-import org.gradle.listener.ListenerManager;
-import org.gradle.logging.LoggingManagerInternal;
-import org.gradle.messaging.actor.ActorFactory;
-import org.gradle.messaging.actor.internal.DefaultActorFactory;
-import org.gradle.messaging.remote.MessagingServer;
-import org.gradle.process.internal.DefaultWorkerProcessFactory;
-import org.gradle.process.internal.WorkerProcessBuilder;
-import org.gradle.process.internal.child.WorkerProcessClassPathProvider;
-import org.gradle.profile.ProfileEventAdapter;
-import org.gradle.profile.ProfileListener;
-import org.gradle.util.ClassLoaderFactory;
-import org.gradle.util.MultiParentClassLoader;
-
-/**
- * Contains the singleton services which are shared by all builds executed by a single {@link org.gradle.GradleLauncher} invocation.
- */
-public class TopLevelBuildServiceRegistry extends DefaultServiceRegistry implements ServiceRegistryFactory {
- private final StartParameter startParameter;
-
- public TopLevelBuildServiceRegistry(final ServiceRegistry parent, final StartParameter startParameter) {
- super(parent);
- this.startParameter = startParameter;
- add(StartParameter.class, startParameter);
- }
-
- protected ImportsReader createImportsReader() {
- return new ImportsReader();
- }
-
- protected TimeProvider createTimeProvider() {
- return new TrueTimeProvider();
- }
-
- protected ExecutorFactory createExecutorFactory() {
- return new DefaultExecutorFactory();
- }
-
- protected IProjectFactory createProjectFactory() {
- return new ProjectFactory(get(Instantiator.class));
- }
-
- protected ListenerManager createListenerManager(ListenerManager listenerManager) {
- return listenerManager.createChild();
- }
-
- protected ClassPathRegistry createClassPathRegistry() {
- return new DefaultClassPathRegistry(
- new DefaultClassPathProvider(get(ModuleRegistry.class)),
- new DependencyClassPathProvider(get(ModuleRegistry.class), get(PluginModuleRegistry.class)),
- new WorkerProcessClassPathProvider(get(CacheRepository.class), get(ModuleRegistry.class)));
- }
-
- protected IsolatedAntBuilder createIsolatedAntBuilder() {
- return new DefaultIsolatedAntBuilder(get(ClassPathRegistry.class), get(ClassLoaderFactory.class));
- }
-
- protected ActorFactory createActorFactory() {
- return new DefaultActorFactory(get(ExecutorFactory.class));
- }
-
- protected IGradlePropertiesLoader createGradlePropertiesLoader() {
- return new DefaultGradlePropertiesLoader(startParameter);
- }
-
- protected BuildLoader createBuildLoader() {
- return new ProjectPropertySettingBuildLoader(
- get(IGradlePropertiesLoader.class),
- new InstantiatingBuildLoader(get(IProjectFactory.class)));
- }
-
- protected CacheFactory createCacheFactory() {
- return getFactory(CacheFactory.class).create();
- }
-
- protected CacheRepository createCacheRepository() {
- CacheFactory factory = get(CacheFactory.class);
- return new DefaultCacheRepository(startParameter.getGradleUserHomeDir(), startParameter.getProjectCacheDir(),
- startParameter.getCacheUsage(), factory);
- }
-
- protected ProjectEvaluator createProjectEvaluator() {
- return new LifecycleProjectEvaluator(
- new BuildScriptProcessor(
- get(ScriptPluginFactory.class)));
- }
-
- protected ITaskFactory createITaskFactory() {
- return new DependencyAutoWireTaskFactory(
- new AnnotationProcessingTaskFactory(
- new TaskFactory(
- get(ClassGenerator.class))));
- }
-
- protected ScriptCompilerFactory createScriptCompileFactory() {
- ScriptExecutionListener scriptExecutionListener = get(ListenerManager.class).getBroadcaster(ScriptExecutionListener.class);
- EmptyScriptGenerator emptyScriptGenerator = new AsmBackedEmptyScriptGenerator();
- CacheValidator scriptCacheInvalidator = new CacheValidator() {
- public boolean isValid() {
- return !get(StartParameter.class).isRecompileScripts();
- }
- };
- return new DefaultScriptCompilerFactory(
- new CachingScriptClassCompiler(
- new ShortCircuitEmptyScriptCompiler(
- new FileCacheBackedScriptClassCompiler(
- get(CacheRepository.class),
- scriptCacheInvalidator,
- new DefaultScriptCompilationHandler(
- emptyScriptGenerator)),
- emptyScriptGenerator)),
- new DefaultScriptRunnerFactory(scriptExecutionListener));
- }
-
- protected ScriptPluginFactory createScriptObjectConfigurerFactory() {
- return new DefaultScriptPluginFactory(
- get(ScriptCompilerFactory.class),
- get(ImportsReader.class),
- get(ScriptHandlerFactory.class),
- get(ClassLoader.class),
- getFactory(LoggingManagerInternal.class));
- }
-
- protected MultiParentClassLoader createRootClassLoader() {
- return get(ClassLoaderRegistry.class).createScriptClassLoader();
- }
-
- protected InitScriptHandler createInitScriptHandler() {
- return new InitScriptHandler(
- new DefaultInitScriptProcessor(get(ScriptPluginFactory.class))
- );
- }
-
- protected SettingsProcessor createSettingsProcessor() {
- return new PropertiesLoadingSettingsProcessor(
- new ScriptEvaluatingSettingsProcessor(
- get(ScriptPluginFactory.class),
- new SettingsFactory(
- new DefaultProjectDescriptorRegistry(),
- get(Instantiator.class)
- ),
- get(IGradlePropertiesLoader.class)),
- get(IGradlePropertiesLoader.class));
- }
-
- protected ExceptionAnalyser createExceptionAnalyser() {
- return new MultipleBuildFailuresExceptionAnalyser(new DefaultExceptionAnalyser(get(ListenerManager.class)));
- }
-
- protected ScriptHandlerFactory createScriptHandlerFactory() {
- return new DefaultScriptHandlerFactory(
- get(DependencyManagementServices.class),
- get(FileResolver.class),
- new DependencyMetaDataProviderImpl());
- }
-
- protected FileResolver createFileResolver() {
- return new IdentityFileResolver();
- }
-
- protected Factory<WorkerProcessBuilder> createWorkerProcessFactory() {
- ClassPathRegistry classPathRegistry = get(ClassPathRegistry.class);
- return new DefaultWorkerProcessFactory(startParameter.getLogLevel(), get(MessagingServer.class), classPathRegistry,
- new IdentityFileResolver(), new LongIdGenerator());
- }
-
- protected BuildConfigurer createBuildConfigurer() {
- return new DefaultBuildConfigurer();
- }
-
- protected ProjectAccessListener createProjectAccessListener() {
- return new DefaultProjectAccessListener();
- }
-
- protected ProfileEventAdapter createProfileEventAdapter() {
- return new ProfileEventAdapter(get(BuildRequestMetaData.class), get(TimeProvider.class), get(ListenerManager.class).getBroadcaster(ProfileListener.class));
- }
-
- protected DependencyManagementServices createDependencyManagementServices() {
- ClassLoader coreImplClassLoader = get(ClassLoaderRegistry.class).getCoreImplClassLoader();
- ServiceLocator serviceLocator = new ServiceLocator(coreImplClassLoader);
- return serviceLocator.getFactory(DependencyManagementServices.class).newInstance(this);
- }
-
- public ServiceRegistryFactory createFor(Object domainObject) {
- if (domainObject instanceof GradleInternal) {
- return new GradleInternalServiceRegistry(this, (GradleInternal) domainObject);
- }
- throw new IllegalArgumentException(String.format("Cannot create services for unknown domain object of type %s.",
- domainObject.getClass().getSimpleName()));
- }
-
- private class DependencyMetaDataProviderImpl implements DependencyMetaDataProvider {
-
- public Module getModule() {
- return new DefaultModule("unspecified", "unspecified", Project.DEFAULT_VERSION, Project.DEFAULT_STATUS);
- }
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/ant/AntLoggingAdapter.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/project/ant/AntLoggingAdapter.java
index ada6e6d..fe274da 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/ant/AntLoggingAdapter.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/project/ant/AntLoggingAdapter.java
@@ -23,9 +23,6 @@ import org.gradle.api.logging.Logging;
import java.io.PrintStream;
-/**
- * @author Hans Dockter
- */
public class AntLoggingAdapter implements BuildLogger {
private final Logger logger = Logging.getLogger(AntLoggingAdapter.class);
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/taskfactory/AnnotationProcessingTaskFactory.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/project/taskfactory/AnnotationProcessingTaskFactory.java
index eedcb7d..28059ef 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/taskfactory/AnnotationProcessingTaskFactory.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/project/taskfactory/AnnotationProcessingTaskFactory.java
@@ -16,16 +16,22 @@
package org.gradle.api.internal.project.taskfactory;
import org.apache.commons.lang.StringUtils;
-import org.gradle.api.Action;
-import org.gradle.api.GradleException;
-import org.gradle.api.Task;
-import org.gradle.api.Transformer;
+import org.gradle.api.*;
+import org.gradle.api.internal.AbstractTask;
+import org.gradle.api.internal.ConventionTask;
import org.gradle.api.internal.TaskInternal;
+import org.gradle.api.internal.changedetection.TaskArtifactState;
import org.gradle.api.internal.project.ProjectInternal;
+import org.gradle.api.internal.tasks.ContextAwareTaskAction;
+import org.gradle.api.internal.tasks.TaskExecutionContext;
import org.gradle.api.internal.tasks.execution.TaskValidator;
+import org.gradle.api.specs.Spec;
import org.gradle.api.tasks.*;
+import org.gradle.api.tasks.incremental.IncrementalTaskInputs;
+import org.gradle.internal.Factory;
import org.gradle.internal.reflect.Instantiator;
-import org.gradle.util.ReflectionUtil;
+import org.gradle.internal.reflect.JavaReflectionUtil;
+import org.gradle.util.DeprecationLogger;
import java.io.File;
import java.lang.annotation.Annotation;
@@ -41,8 +47,8 @@ import java.util.concurrent.Callable;
*/
public class AnnotationProcessingTaskFactory implements ITaskFactory {
private final ITaskFactory taskFactory;
- private final Map<Class, List<Action<Task>>> actionsForType;
-
+ private final Map<Class, TaskClassInfo> classInfos;
+
private final Transformer<Iterable<File>, Object> filePropertyTransformer = new Transformer<Iterable<File>, Object>() {
public Iterable<File> transform(Object original) {
File file = (File) original;
@@ -56,7 +62,7 @@ public class AnnotationProcessingTaskFactory implements ITaskFactory {
return original != null ? (Iterable<File>) original : Collections.<File>emptyList();
}
};
-
+
private final List<? extends PropertyAnnotationHandler> handlers = Arrays.asList(
new InputFilePropertyAnnotationHandler(),
new InputDirectoryPropertyAnnotationHandler(),
@@ -77,66 +83,71 @@ public class AnnotationProcessingTaskFactory implements ITaskFactory {
public AnnotationProcessingTaskFactory(ITaskFactory taskFactory) {
this.taskFactory = taskFactory;
- this.actionsForType = new HashMap<Class, List<Action<Task>>>();
+ this.classInfos = new HashMap<Class, TaskClassInfo>();
}
- private AnnotationProcessingTaskFactory(Map<Class, List<Action<Task>>> actionsForType, ITaskFactory taskFactory) {
- this.actionsForType = actionsForType;
+ private AnnotationProcessingTaskFactory(Map<Class, TaskClassInfo> classInfos, ITaskFactory taskFactory) {
+ this.classInfos = classInfos;
this.taskFactory = taskFactory;
}
public ITaskFactory createChild(ProjectInternal project, Instantiator instantiator) {
- return new AnnotationProcessingTaskFactory(actionsForType, taskFactory.createChild(project, instantiator));
+ return new AnnotationProcessingTaskFactory(classInfos, taskFactory.createChild(project, instantiator));
}
public TaskInternal createTask(Map<String, ?> args) {
TaskInternal task = taskFactory.createTask(args);
+ TaskClassInfo taskClassInfo = getTaskClassInfo(task.getClass());
+
+ // TODO:DAZ Make this more general purpose, and support IncrementalTaskActions added via another mechanism.
+ if (taskClassInfo.incremental) {
+ // Add a dummy upToDateWhen spec: this will for TaskOutputs.hasOutputs() to be true.
+ task.getOutputs().upToDateWhen(new Spec<Task>() {
+ public boolean isSatisfiedBy(Task element) {
+ return true;
+ }
+ });
+ }
- Class<? extends Task> type = task.getClass();
- List<Action<Task>> actions = actionsForType.get(type);
- if (actions == null) {
- actions = createActionsForType(type);
- actionsForType.put(type, actions);
+ for (Factory<Action<Task>> actionFactory : taskClassInfo.taskActions) {
+ task.doFirst(actionFactory.create());
}
- for (Action<Task> action : actions) {
- task.doFirst(action);
- if (action instanceof Validator) {
- Validator validator = (Validator) action;
- validator.addInputsAndOutputs(task);
- }
+ if (taskClassInfo.validator != null) {
+ task.doFirst(taskClassInfo.validator);
+ taskClassInfo.validator.addInputsAndOutputs(task);
}
return task;
}
- private List<Action<Task>> createActionsForType(Class<? extends Task> type) {
- List<Action<Task>> actions = new ArrayList<Action<Task>>();
- findTaskActions(type, actions);
- findProperties(type, actions);
- return actions;
- }
-
- private void findProperties(Class<? extends Task> type, List<Action<Task>> actions) {
- Validator validator = new Validator();
+ private TaskClassInfo getTaskClassInfo(Class<? extends Task> type) {
+ TaskClassInfo taskClassInfo = classInfos.get(type);
+ if (taskClassInfo == null) {
+ taskClassInfo = new TaskClassInfo();
+ findTaskActions(type, taskClassInfo);
- validator.attachActions(null, type);
+ Validator validator = new Validator();
+ validator.attachActions(null, type);
- if (!validator.properties.isEmpty()) {
- actions.add(validator);
+ if (!validator.properties.isEmpty()) {
+ taskClassInfo.validator = validator;
+ }
+ classInfos.put(type, taskClassInfo);
}
+ return taskClassInfo;
}
- private void findTaskActions(Class<? extends Task> type, List<Action<Task>> actions) {
+ private void findTaskActions(Class<? extends Task> type, TaskClassInfo taskClassInfo) {
Set<String> methods = new HashSet<String>();
for (Class current = type; current != null; current = current.getSuperclass()) {
for (Method method : current.getDeclaredMethods()) {
- attachTaskAction(method, actions, methods);
+ attachTaskAction(method, taskClassInfo, methods);
}
}
}
- private void attachTaskAction(final Method method, Collection<Action<Task>> actions, Collection<String> methods) {
+ private void attachTaskAction(final Method method, TaskClassInfo taskClassInfo, Collection<String> processedMethods) {
if (method.getAnnotation(TaskAction.class) == null) {
return;
}
@@ -144,33 +155,95 @@ public class AnnotationProcessingTaskFactory implements ITaskFactory {
throw new GradleException(String.format("Cannot use @TaskAction annotation on static method %s.%s().",
method.getDeclaringClass().getSimpleName(), method.getName()));
}
- if (method.getParameterTypes().length > 0) {
+ final Class<?>[] parameterTypes = method.getParameterTypes();
+ if (parameterTypes.length > 1) {
throw new GradleException(String.format(
- "Cannot use @TaskAction annotation on method %s.%s() as this method takes parameters.",
+ "Cannot use @TaskAction annotation on method %s.%s() as this method takes multiple parameters.",
method.getDeclaringClass().getSimpleName(), method.getName()));
}
- if (methods.contains(method.getName())) {
+
+ if (parameterTypes.length == 1) {
+ if (!parameterTypes[0].equals(IncrementalTaskInputs.class)) {
+ throw new GradleException(String.format(
+ "Cannot use @TaskAction annotation on method %s.%s() because %s is not a valid parameter to an action method.",
+ method.getDeclaringClass().getSimpleName(), method.getName(), parameterTypes[0]));
+ }
+ if (taskClassInfo.incremental) {
+ throw new GradleException(String.format("Cannot have multiple @TaskAction methods accepting an %s parameter.", IncrementalTaskInputs.class.getSimpleName()));
+ }
+ taskClassInfo.incremental = true;
+ }
+ if (processedMethods.contains(method.getName())) {
return;
}
- methods.add(method.getName());
- actions.add(new Action<Task>() {
- public void execute(Task task) {
- ClassLoader original = Thread.currentThread().getContextClassLoader();
- Thread.currentThread().setContextClassLoader(method.getDeclaringClass().getClassLoader());
- try {
- ReflectionUtil.invoke(task, method.getName());
- } finally {
- Thread.currentThread().setContextClassLoader(original);
+ taskClassInfo.taskActions.add(createActionFactory(method, parameterTypes));
+ processedMethods.add(method.getName());
+ }
+
+ private Factory<Action<Task>> createActionFactory(final Method method, final Class<?>[] parameterTypes) {
+ return new Factory<Action<Task>>() {
+ public Action<Task> create() {
+ if (parameterTypes.length == 1) {
+ return new IncrementalTaskAction(method);
+ } else {
+ return new StandardTaskAction(method);
}
}
- });
+ };
}
private static boolean isGetter(Method method) {
- return method.getName().startsWith("get") && method.getReturnType() != Void.TYPE
+ return ((method.getName().startsWith("get") && method.getReturnType() != Void.TYPE)
+ || (method.getName().startsWith("is") && method.getReturnType().equals(boolean.class)))
&& method.getParameterTypes().length == 0 && !Modifier.isStatic(method.getModifiers());
}
+ private static class StandardTaskAction implements Action<Task> {
+ private final Method method;
+
+ public StandardTaskAction(Method method) {
+ this.method = method;
+ }
+
+ public void execute(Task task) {
+ ClassLoader original = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(method.getDeclaringClass().getClassLoader());
+ try {
+ doExecute(task, method.getName());
+ } finally {
+ Thread.currentThread().setContextClassLoader(original);
+ }
+ }
+
+ protected void doExecute(Task task, String methodName) {
+ JavaReflectionUtil.method(task, Object.class, methodName).invoke(task);
+ }
+ }
+
+ public static class IncrementalTaskAction extends StandardTaskAction implements ContextAwareTaskAction {
+
+ private TaskArtifactState taskArtifactState;
+
+ public IncrementalTaskAction(Method method) {
+ super(method);
+ }
+
+ public void contextualise(TaskExecutionContext context) {
+ this.taskArtifactState = context == null ? null : context.getTaskArtifactState();
+ }
+
+ protected void doExecute(Task task, String methodName) {
+ JavaReflectionUtil.method(task, Object.class, methodName, IncrementalTaskInputs.class).invoke(task, taskArtifactState.getInputChanges());
+ taskArtifactState = null;
+ }
+ }
+
+ private static class TaskClassInfo {
+ public Validator validator;
+ public List<Factory<Action<Task>>> taskActions = new ArrayList<Factory<Action<Task>>>();
+ public boolean incremental;
+ }
+
private class Validator implements Action<Task>, TaskValidator {
private Set<PropertyInfo> properties = new LinkedHashSet<PropertyInfo>();
@@ -204,15 +277,23 @@ public class AnnotationProcessingTaskFactory implements ITaskFactory {
}
public void attachActions(PropertyInfo parent, Class<?> type) {
- if (type.getSuperclass() != null) {
- attachActions(parent, type.getSuperclass());
+ Class<?> superclass = type.getSuperclass();
+ if (!(superclass == null
+ // Avoid reflecting on classes we know we don't need to look at
+ || superclass.equals(ConventionTask.class) || superclass.equals(DefaultTask.class)
+ || superclass.equals(AbstractTask.class) || superclass.equals(Object.class)
+ )) {
+ attachActions(parent, superclass);
}
+
for (Method method : type.getDeclaredMethods()) {
if (!isGetter(method)) {
continue;
}
- String fieldName = StringUtils.uncapitalize(method.getName().substring(3));
+ String name = method.getName();
+ int prefixLength = name.startsWith("is") ? 2 : 3; // it's 'get' if not 'is'.
+ String fieldName = StringUtils.uncapitalize(name.substring(prefixLength));
String propertyName = fieldName;
if (parent != null) {
propertyName = parent.getName() + '.' + propertyName;
@@ -307,7 +388,7 @@ public class AnnotationProcessingTaskFactory implements ITaskFactory {
this.validator = validator;
this.parent = parent;
this.propertyName = propertyName;
- this.method = method;
+ this.method = method;
}
@Override
@@ -366,7 +447,12 @@ public class AnnotationProcessingTaskFactory implements ITaskFactory {
bean = parentValue.getValue();
}
- final Object value = ReflectionUtil.invoke(bean, method.getName());
+ final Object finalBean = bean;
+ final Object value = DeprecationLogger.whileDisabled(new Factory<Object>() {
+ public Object create() {
+ return JavaReflectionUtil.method(finalBean, Object.class, method).invoke(finalBean);
+ }
+ });
return new PropertyValue() {
public Object getValue() {
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/taskfactory/ITaskFactory.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/project/taskfactory/ITaskFactory.java
index f2dc175..c18d79a 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/taskfactory/ITaskFactory.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/project/taskfactory/ITaskFactory.java
@@ -21,9 +21,6 @@ import org.gradle.internal.reflect.Instantiator;
import java.util.Map;
-/**
- * @author Hans Dockter
- */
public interface ITaskFactory {
public ITaskFactory createChild(ProjectInternal project, Instantiator instantiator);
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/taskfactory/TaskFactory.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/project/taskfactory/TaskFactory.java
index 16874d6..e3fef78 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/project/taskfactory/TaskFactory.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/project/taskfactory/TaskFactory.java
@@ -30,17 +30,17 @@ import org.gradle.internal.reflect.ObjectInstantiationException;
import org.gradle.util.GUtil;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.Callable;
-/**
- * @author Hans Dockter
- */
public class TaskFactory implements ITaskFactory {
public static final String GENERATE_SUBCLASS = "generateSubclass";
private final ClassGenerator generator;
private final ProjectInternal project;
private final Instantiator instantiator;
+ private final Set<String> validTaskArguments;
public TaskFactory(ClassGenerator generator) {
this(generator, null, null);
@@ -50,6 +50,17 @@ public class TaskFactory implements ITaskFactory {
this.generator = generator;
this.project = project;
this.instantiator = instantiator;
+
+
+ validTaskArguments = new HashSet<String>();
+ validTaskArguments.add(Task.TASK_ACTION);
+ validTaskArguments.add(Task.TASK_DEPENDS_ON);
+ validTaskArguments.add(Task.TASK_DESCRIPTION);
+ validTaskArguments.add(Task.TASK_GROUP);
+ validTaskArguments.add(Task.TASK_NAME);
+ validTaskArguments.add(Task.TASK_OVERWRITE);
+ validTaskArguments.add(Task.TASK_TYPE);
+
}
public ITaskFactory createChild(ProjectInternal project, Instantiator instantiator) {
@@ -120,6 +131,7 @@ public class TaskFactory implements ITaskFactory {
}
private void checkTaskArgsAndCreateDefaultValues(Map<String, Object> args) {
+ validateArgs(args);
setIfNull(args, Task.TASK_NAME, "");
setIfNull(args, Task.TASK_TYPE, DefaultTask.class);
if (((Class) args.get(Task.TASK_TYPE)).isAssignableFrom(DefaultTask.class)) {
@@ -128,6 +140,15 @@ public class TaskFactory implements ITaskFactory {
setIfNull(args, GENERATE_SUBCLASS, "true");
}
+ private void validateArgs(Map<String, Object> args) {
+ if (!validTaskArguments.containsAll(args.keySet())) {
+ Map unknownArguments = new HashMap<String, Object>(args);
+ unknownArguments.keySet().removeAll(validTaskArguments);
+ throw new InvalidUserDataException(String.format("Could not create task '%s': Unknown argument(s) in task definition: %s",
+ args.get(Task.TASK_NAME), unknownArguments.keySet()));
+ }
+ }
+
private void setIfNull(Map<String, Object> map, String key, Object defaultValue) {
if (map.get(key) == null) {
map.put(key, defaultValue);
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/resources/DefaultResourceHandler.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/resources/DefaultResourceHandler.java
index 453c454..450cf92 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/resources/DefaultResourceHandler.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/resources/DefaultResourceHandler.java
@@ -23,9 +23,6 @@ import org.gradle.api.internal.file.archive.compression.GzipArchiver;
import org.gradle.api.resources.ReadableResource;
import org.gradle.api.resources.ResourceHandler;
-/**
- * by Szczepan Faber, created at: 11/24/11
- */
public class DefaultResourceHandler implements ResourceHandler {
private final FileResolver resolver;
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/resources/URIBuilder.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/resources/URIBuilder.java
index 288ca63..2059269 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/resources/URIBuilder.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/resources/URIBuilder.java
@@ -20,9 +20,6 @@ import org.gradle.util.GUtil;
import java.net.URI;
-/**
- * by Szczepan Faber, created at: 12/13/11
- */
public class URIBuilder {
private final URI uri;
private String schemePrefix = "";
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/specs/ExplainingSpecs.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/specs/ExplainingSpecs.java
index 8747618..e4a03d0 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/specs/ExplainingSpecs.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/specs/ExplainingSpecs.java
@@ -16,9 +16,6 @@
package org.gradle.api.internal.specs;
-/**
- * by Szczepan Faber, created at: 5/14/12
- */
public class ExplainingSpecs {
private static final ExplainingSpec<Object> SATISFIES_ALL = new ExplainingSpec<Object>() {
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/CachingTaskDependencyResolveContext.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/CachingTaskDependencyResolveContext.java
index e235a3a..c993c4f 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/CachingTaskDependencyResolveContext.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/CachingTaskDependencyResolveContext.java
@@ -19,8 +19,8 @@ package org.gradle.api.internal.tasks;
import org.gradle.api.Buildable;
import org.gradle.api.GradleException;
import org.gradle.api.Task;
-import org.gradle.api.internal.CachingDirectedGraphWalker;
-import org.gradle.api.internal.DirectedGraph;
+import org.gradle.internal.graph.CachingDirectedGraphWalker;
+import org.gradle.internal.graph.DirectedGraph;
import org.gradle.api.tasks.TaskDependency;
import java.util.*;
@@ -79,7 +79,7 @@ public class CachingTaskDependencyResolveContext implements TaskDependencyResolv
}
private class TaskGraphImpl implements DirectedGraph<Object, Task> {
- public void getNodeValues(Object node, Collection<Task> values, Collection<Object> connectedNodes) {
+ public void getNodeValues(Object node, Collection<? super Task> values, Collection<? super Object> connectedNodes) {
if (node instanceof TaskDependencyInternal) {
TaskDependencyInternal taskDependency = (TaskDependencyInternal) node;
queue.clear();
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/ContextAwareTaskAction.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/ContextAwareTaskAction.java
new file mode 100644
index 0000000..1b77f0c
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/ContextAwareTaskAction.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.tasks;
+
+import org.gradle.api.Action;
+import org.gradle.api.Task;
+
+public interface ContextAwareTaskAction extends Action<Task> {
+ void contextualise(TaskExecutionContext context);
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/DefaultTaskContainer.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/DefaultTaskContainer.java
index eb4cbde..4ea86f2 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/DefaultTaskContainer.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/DefaultTaskContainer.java
@@ -17,29 +17,25 @@ package org.gradle.api.internal.tasks;
import groovy.lang.Closure;
import org.apache.commons.lang.StringUtils;
-import org.gradle.api.InvalidUserDataException;
-import org.gradle.api.Project;
-import org.gradle.api.Task;
-import org.gradle.api.UnknownTaskException;
-import org.gradle.api.internal.CachingDirectedGraphWalker;
-import org.gradle.api.internal.DirectedGraph;
+import org.gradle.api.*;
import org.gradle.api.internal.DynamicObject;
import org.gradle.api.internal.NamedDomainObjectContainerConfigureDelegate;
import org.gradle.api.internal.project.ProjectInternal;
import org.gradle.api.internal.project.taskfactory.ITaskFactory;
import org.gradle.initialization.ProjectAccessListener;
+import org.gradle.internal.graph.CachingDirectedGraphWalker;
+import org.gradle.internal.graph.DirectedGraph;
import org.gradle.internal.reflect.Instantiator;
import org.gradle.util.ConfigureUtil;
import org.gradle.util.DeprecationLogger;
import org.gradle.util.GUtil;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.*;
public class DefaultTaskContainer extends DefaultTaskCollection<Task> implements TaskContainerInternal {
private final ITaskFactory taskFactory;
private final ProjectAccessListener projectAccessListener;
+ private Map<String, Runnable> placeholders = new HashMap<String, Runnable>();
public DefaultTaskContainer(ProjectInternal project, Instantiator instantiator, ITaskFactory taskFactory, ProjectAccessListener projectAccessListener) {
super(Task.class, instantiator, project);
@@ -47,7 +43,7 @@ public class DefaultTaskContainer extends DefaultTaskCollection<Task> implements
this.projectAccessListener = projectAccessListener;
}
- public Task add(Map<String, ?> options) {
+ public Task create(Map<String, ?> options) {
Map<String, Object> mutableOptions = new HashMap<String, Object>(options);
Object replaceStr = mutableOptions.remove(Task.TASK_OVERWRITE);
@@ -71,16 +67,37 @@ public class DefaultTaskContainer extends DefaultTaskCollection<Task> implements
return task;
}
+ public Task add(Map<String, ?> options) {
+ DeprecationLogger.nagUserOfReplacedMethod("TaskContainer.add()", "create()");
+ return create(options);
+ }
+
+ public Task create(Map<String, ?> options, Closure configureClosure) throws InvalidUserDataException {
+ return create(options).configure(configureClosure);
+ }
+
public Task add(Map<String, ?> options, Closure configureClosure) throws InvalidUserDataException {
- return add(options).configure(configureClosure);
+ DeprecationLogger.nagUserOfReplacedMethod("TaskContainer.add()", "create()");
+ return create(options, configureClosure);
+ }
+
+ public <T extends Task> T create(String name, Class<T> type) {
+ return type.cast(create(GUtil.map(Task.TASK_NAME, name, Task.TASK_TYPE, type)));
}
public <T extends Task> T add(String name, Class<T> type) {
- return type.cast(add(GUtil.map(Task.TASK_NAME, name, Task.TASK_TYPE, type)));
+ DeprecationLogger.nagUserOfReplacedMethod("TaskContainer.add()", "create()");
+ return create(name, type);
}
public Task create(String name) {
- return add(name);
+ return create(GUtil.map(Task.TASK_NAME, name));
+ }
+
+ public Task create(String name, Action<? super Task> configureAction) throws InvalidUserDataException {
+ Task task = create(name);
+ configureAction.execute(task);
+ return task;
}
public Task maybeCreate(String name) {
@@ -92,23 +109,31 @@ public class DefaultTaskContainer extends DefaultTaskCollection<Task> implements
}
public Task add(String name) {
- return add(GUtil.map(Task.TASK_NAME, name));
+ DeprecationLogger.nagUserOfReplacedMethod("TaskContainer.add()", "create()");
+ return create(name);
}
public Task replace(String name) {
- return add(GUtil.map(Task.TASK_NAME, name, Task.TASK_OVERWRITE, true));
+ return create(GUtil.map(Task.TASK_NAME, name, Task.TASK_OVERWRITE, true));
}
public Task create(String name, Closure configureClosure) {
- return add(name, configureClosure);
+ return create(name).configure(configureClosure);
}
public Task add(String name, Closure configureClosure) {
- return add(GUtil.map(Task.TASK_NAME, name)).configure(configureClosure);
+ DeprecationLogger.nagUserOfReplacedMethod("TaskContainer.add()", "create()");
+ return create(name, configureClosure);
+ }
+
+ public <T extends Task> T create(String name, Class<T> type, Action<? super T> configuration) throws InvalidUserDataException {
+ T task = create(name, type);
+ configuration.execute(task);
+ return task;
}
public <T extends Task> T replace(String name, Class<T> type) {
- return type.cast(add(GUtil.map(Task.TASK_NAME, name, Task.TASK_TYPE, type, Task.TASK_OVERWRITE, true)));
+ return type.cast(create(GUtil.map(Task.TASK_NAME, name, Task.TASK_TYPE, type, Task.TASK_OVERWRITE, true)));
}
public Task findByPath(String path) {
@@ -133,7 +158,7 @@ public class DefaultTaskContainer extends DefaultTaskCollection<Task> implements
if (!GUtil.isTrue(path)) {
throw new InvalidUserDataException("A path must be specified!");
}
- if(!(path instanceof CharSequence)) {
+ if (!(path instanceof CharSequence)) {
DeprecationLogger.nagUserOfDeprecated(
String.format("Converting class %s to a task dependency using toString()", path.getClass().getName()),
"Please use org.gradle.api.Task, java.lang.String, org.gradle.api.Buildable, org.gradle.tasks.TaskDependency or a Closure to declare your task dependencies"
@@ -163,11 +188,55 @@ public class DefaultTaskContainer extends DefaultTaskCollection<Task> implements
return getElementsAsDynamicObject();
}
+ public SortedSet<String> getNames() {
+ SortedSet<String> set = new TreeSet<String>();
+ for (Task o : getStore()) {
+ set.add(o.getName());
+ }
+ for (String placeHolderName : placeholders.keySet()) {
+ set.add(placeHolderName);
+ }
+ return set;
+ }
+
public void actualize() {
new CachingDirectedGraphWalker<Task, Void>(new DirectedGraph<Task, Void>() {
- public void getNodeValues(Task node, Collection<Void> values, Collection<Task> connectedNodes) {
+ public void getNodeValues(Task node, Collection<? super Void> values, Collection<? super Task> connectedNodes) {
connectedNodes.addAll(node.getTaskDependencies().getDependencies(node));
}
}).add(this).findValues();
+
+
+ final HashSet<String> placeholderNames = new HashSet<String>(placeholders.keySet());
+ for (String placeholder : placeholderNames) {
+ maybeMaterializePlaceholder(placeholder);
+ }
+
+ }
+
+ public Map<String, Runnable> getPlaceholderActions() {
+ return placeholders;
+ }
+
+ public Task findByName(String name) {
+ Task task = super.findByName(name);
+ if (task != null) {
+ return task;
+ }
+ maybeMaterializePlaceholder(name);
+ return super.findByName(name);
+ }
+
+ private void maybeMaterializePlaceholder(String name) {
+ if (placeholders.containsKey(name)) {
+ if (super.findByName(name) == null) {
+ final Runnable placeholderAction = placeholders.remove(name);
+ placeholderAction.run();
+ }
+ }
+ }
+
+ public void addPlaceholderAction(String placeholderName, Runnable runnable) {
+ placeholders.put(placeholderName, runnable);
}
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/SimpleWorkResult.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/SimpleWorkResult.java
new file mode 100644
index 0000000..5d52b22
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/SimpleWorkResult.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.tasks;
+
+import org.gradle.api.tasks.WorkResult;
+
+public class SimpleWorkResult implements WorkResult {
+ private final boolean didWork;
+
+ public SimpleWorkResult(boolean didWork) {
+ this.didWork = didWork;
+ }
+
+ public boolean getDidWork() {
+ return didWork;
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/TaskContainerInternal.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/TaskContainerInternal.java
index 5a4e57c..c2ceef0 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/TaskContainerInternal.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/TaskContainerInternal.java
@@ -18,15 +18,31 @@ package org.gradle.api.internal.tasks;
import org.gradle.api.internal.DynamicObject;
import org.gradle.api.tasks.TaskContainer;
+import java.util.Map;
+
public interface TaskContainerInternal extends TaskContainer, TaskResolver {
DynamicObject getTasksAsDynamicObject();
/**
+ * <p>Add placeholder action if task is referenced by name that does not (yet) exist.
+ * If a task is referenced by name and not listed as task, the provided action is executed and the task name is looked up again before proceeding
+ * This allows lazy application of plugins if task is referenced but not yet part of the taskcontainer.</p>
+ *
+ * @param placeholderName the placeholderName that references the placeholder action.
+ * @param runnable the Runnable executed when referencing a task that does not exist, but a placeholder with the given name is defined.
+ */
+ void addPlaceholderAction(String placeholderName, Runnable runnable);
+
+ /**
* Force the entire graph to come into existence.
*
- * Tasks may have dependencies that are abstract (e.g. a dependency on a task _name_). Calling this method
- * will force all task dependencies to be actualised, which may mean new tasks are created because of things
- * like task rules etc.
+ * Tasks may have dependencies that are abstract (e.g. a dependency on a task _name_).
+ * Calling this method will force all task dependencies to be actualised, which may mean new tasks are
+ * created because of things like task rules etc.
+ *
+ * As part of this, all placeholder actions are materialized to show up in 'tasks' and 'tasks --all' overview.
*/
void actualize();
+
+ Map<String, Runnable> getPlaceholderActions();
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/TaskExecuter.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/TaskExecuter.java
index 08aa32a..56a0310 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/TaskExecuter.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/TaskExecuter.java
@@ -22,5 +22,5 @@ public interface TaskExecuter {
* Executes the given task. If the task fails with an exception, the exception is packaged in the provided task
* state.
*/
- void execute(TaskInternal task, TaskStateInternal state);
+ void execute(TaskInternal task, TaskStateInternal state, TaskExecutionContext context);
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/TaskExecutionContext.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/TaskExecutionContext.java
new file mode 100644
index 0000000..972c919
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/TaskExecutionContext.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.tasks;
+
+import org.gradle.api.internal.changedetection.TaskArtifactState;
+
+public interface TaskExecutionContext {
+ TaskArtifactState getTaskArtifactState();
+ void setTaskArtifactState(TaskArtifactState taskArtifactState);
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/TaskStatusNagger.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/TaskStatusNagger.java
index d9602f1..74533c0 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/TaskStatusNagger.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/TaskStatusNagger.java
@@ -17,7 +17,6 @@
package org.gradle.api.internal.tasks;
import groovy.util.ObservableList;
-import org.gradle.api.Action;
import org.gradle.api.Task;
import org.gradle.api.internal.TaskInternal;
import org.gradle.util.DeprecationLogger;
@@ -70,8 +69,8 @@ public class TaskStatusNagger {
}
}
- public Action<Task> leftShift(final Action<? super Task> action) {
- return new Action<Task>() {
+ public ContextAwareTaskAction leftShift(final ContextAwareTaskAction action) {
+ return new ContextAwareTaskAction() {
public void execute(Task task) {
executingleftShiftAction = true;
try {
@@ -80,6 +79,10 @@ public class TaskStatusNagger {
executingleftShiftAction = false;
}
}
+
+ public void contextualise(TaskExecutionContext context) {
+ action.contextualise(context);
+ }
};
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/execution/DefaultTaskExecutionContext.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/execution/DefaultTaskExecutionContext.java
new file mode 100644
index 0000000..8727b82
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/execution/DefaultTaskExecutionContext.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.tasks.execution;
+
+import org.gradle.api.internal.changedetection.TaskArtifactState;
+import org.gradle.api.internal.tasks.TaskExecutionContext;
+
+public class DefaultTaskExecutionContext implements TaskExecutionContext {
+ private TaskArtifactState taskArtifactState;
+
+ public TaskArtifactState getTaskArtifactState() {
+ return taskArtifactState;
+ }
+
+ public void setTaskArtifactState(TaskArtifactState taskArtifactState) {
+ this.taskArtifactState = taskArtifactState;
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java
index d3b4dc5..7bad7bf 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java
@@ -15,13 +15,10 @@
*/
package org.gradle.api.internal.tasks.execution;
-import org.gradle.api.Action;
import org.gradle.api.GradleException;
-import org.gradle.api.Task;
import org.gradle.api.execution.TaskActionListener;
import org.gradle.api.internal.TaskInternal;
-import org.gradle.api.internal.tasks.TaskExecuter;
-import org.gradle.api.internal.tasks.TaskStateInternal;
+import org.gradle.api.internal.tasks.*;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
import org.gradle.api.tasks.StopActionException;
@@ -42,11 +39,11 @@ public class ExecuteActionsTaskExecuter implements TaskExecuter {
this.listener = listener;
}
- public void execute(TaskInternal task, TaskStateInternal state) {
+ public void execute(TaskInternal task, TaskStateInternal state, TaskExecutionContext context) {
listener.beforeActions(task);
state.setExecuting(true);
try {
- GradleException failure = executeActions(task, state);
+ GradleException failure = executeActions(task, state, context);
state.executed(failure);
} finally {
state.setExecuting(false);
@@ -54,14 +51,14 @@ public class ExecuteActionsTaskExecuter implements TaskExecuter {
}
}
- private GradleException executeActions(TaskInternal task, TaskStateInternal state) {
+ private GradleException executeActions(TaskInternal task, TaskStateInternal state, TaskExecutionContext context) {
logger.debug("Executing actions for {}.", task);
- final List<Action<? super Task>> actions = new ArrayList<Action<? super Task>>(task.getActions());
- for (Action<? super Task> action : actions) {
+ final List<ContextAwareTaskAction> actions = new ArrayList<ContextAwareTaskAction>(task.getTaskActions());
+ for (ContextAwareTaskAction action : actions) {
state.setDidWork(true);
task.getStandardOutputCapture().start();
try {
- action.execute(task);
+ executeAction(task, action, context);
} catch (StopActionException e) {
// Ignore
logger.debug("Action stopped by some action with message: {}", e.getMessage());
@@ -76,4 +73,13 @@ public class ExecuteActionsTaskExecuter implements TaskExecuter {
}
return null;
}
+
+ private void executeAction(TaskInternal task, ContextAwareTaskAction action, TaskExecutionContext context) {
+ action.contextualise(context);
+ try {
+ action.execute(task);
+ } finally {
+ action.contextualise(null);
+ }
+ }
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/execution/ExecuteAtMostOnceTaskExecuter.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/execution/ExecuteAtMostOnceTaskExecuter.java
index 9744ee5..a51fa5a 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/execution/ExecuteAtMostOnceTaskExecuter.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/execution/ExecuteAtMostOnceTaskExecuter.java
@@ -18,6 +18,7 @@ package org.gradle.api.internal.tasks.execution;
import org.gradle.api.internal.TaskInternal;
import org.gradle.api.internal.tasks.TaskExecuter;
+import org.gradle.api.internal.tasks.TaskExecutionContext;
import org.gradle.api.internal.tasks.TaskStateInternal;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
@@ -33,13 +34,13 @@ public class ExecuteAtMostOnceTaskExecuter implements TaskExecuter {
this.executer = executer;
}
- public void execute(TaskInternal task, TaskStateInternal state) {
+ public void execute(TaskInternal task, TaskStateInternal state, TaskExecutionContext context) {
if (state.getExecuted()) {
return;
}
LOGGER.debug("Starting to execute {}", task);
try {
- executer.execute(task, state);
+ executer.execute(task, state, context);
} finally {
state.executed();
LOGGER.debug("Finished executing {}", task);
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/execution/PostExecutionAnalysisTaskExecuter.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/execution/PostExecutionAnalysisTaskExecuter.java
index e866788..022448f 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/execution/PostExecutionAnalysisTaskExecuter.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/execution/PostExecutionAnalysisTaskExecuter.java
@@ -18,6 +18,7 @@ package org.gradle.api.internal.tasks.execution;
import org.gradle.api.internal.TaskInternal;
import org.gradle.api.internal.tasks.TaskExecuter;
+import org.gradle.api.internal.tasks.TaskExecutionContext;
import org.gradle.api.internal.tasks.TaskStateInternal;
/**
@@ -30,8 +31,8 @@ public class PostExecutionAnalysisTaskExecuter implements TaskExecuter {
this.executer = executer;
}
- public void execute(TaskInternal task, TaskStateInternal state) {
- executer.execute(task, state);
+ public void execute(TaskInternal task, TaskStateInternal state, TaskExecutionContext context) {
+ executer.execute(task, state, context);
if (!state.getDidWork()) {
state.upToDate();
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/execution/SkipEmptySourceFilesTaskExecuter.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/execution/SkipEmptySourceFilesTaskExecuter.java
index e847392..b6ecff7 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/execution/SkipEmptySourceFilesTaskExecuter.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/execution/SkipEmptySourceFilesTaskExecuter.java
@@ -17,6 +17,7 @@ package org.gradle.api.internal.tasks.execution;
import org.gradle.api.internal.TaskInternal;
import org.gradle.api.internal.tasks.TaskExecuter;
+import org.gradle.api.internal.tasks.TaskExecutionContext;
import org.gradle.api.internal.tasks.TaskStateInternal;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
@@ -32,12 +33,12 @@ public class SkipEmptySourceFilesTaskExecuter implements TaskExecuter {
this.executer = executer;
}
- public void execute(TaskInternal task, TaskStateInternal state) {
+ public void execute(TaskInternal task, TaskStateInternal state, TaskExecutionContext context) {
if (task.getInputs().getHasSourceFiles() && task.getInputs().getSourceFiles().isEmpty()) {
LOGGER.info("Skipping {} as it has no source files.", task);
state.upToDate();
return;
}
- executer.execute(task, state);
+ executer.execute(task, state, context);
}
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/execution/SkipOnlyIfTaskExecuter.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/execution/SkipOnlyIfTaskExecuter.java
index e56584d..8549818 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/execution/SkipOnlyIfTaskExecuter.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/execution/SkipOnlyIfTaskExecuter.java
@@ -19,6 +19,7 @@ package org.gradle.api.internal.tasks.execution;
import org.gradle.api.GradleException;
import org.gradle.api.internal.TaskInternal;
import org.gradle.api.internal.tasks.TaskExecuter;
+import org.gradle.api.internal.tasks.TaskExecutionContext;
import org.gradle.api.internal.tasks.TaskStateInternal;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
@@ -34,7 +35,7 @@ public class SkipOnlyIfTaskExecuter implements TaskExecuter {
this.executer = executer;
}
- public void execute(TaskInternal task, TaskStateInternal state) {
+ public void execute(TaskInternal task, TaskStateInternal state, TaskExecutionContext context) {
boolean skip;
try {
skip = !task.getOnlyIf().isSatisfiedBy(task);
@@ -49,6 +50,6 @@ public class SkipOnlyIfTaskExecuter implements TaskExecuter {
return;
}
- executer.execute(task, state);
+ executer.execute(task, state, context);
}
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/execution/SkipTaskWithNoActionsExecuter.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/execution/SkipTaskWithNoActionsExecuter.java
index 088b2b6..5cf62a3 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/execution/SkipTaskWithNoActionsExecuter.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/execution/SkipTaskWithNoActionsExecuter.java
@@ -18,6 +18,7 @@ package org.gradle.api.internal.tasks.execution;
import org.gradle.api.Task;
import org.gradle.api.internal.TaskInternal;
import org.gradle.api.internal.tasks.TaskExecuter;
+import org.gradle.api.internal.tasks.TaskExecutionContext;
import org.gradle.api.internal.tasks.TaskStateInternal;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
@@ -33,7 +34,7 @@ public class SkipTaskWithNoActionsExecuter implements TaskExecuter {
this.executer = executer;
}
- public void execute(TaskInternal task, TaskStateInternal state) {
+ public void execute(TaskInternal task, TaskStateInternal state, TaskExecutionContext context) {
if (task.getActions().isEmpty()) {
LOGGER.info("Skipping {} as it has no actions.", task);
boolean upToDate = true;
@@ -48,6 +49,6 @@ public class SkipTaskWithNoActionsExecuter implements TaskExecuter {
}
return;
}
- executer.execute(task, state);
+ executer.execute(task, state, context);
}
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/execution/SkipUpToDateTaskExecuter.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/execution/SkipUpToDateTaskExecuter.java
index e478e61..297eaac 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/execution/SkipUpToDateTaskExecuter.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/execution/SkipUpToDateTaskExecuter.java
@@ -20,10 +20,16 @@ import org.gradle.api.internal.TaskInternal;
import org.gradle.api.internal.changedetection.TaskArtifactState;
import org.gradle.api.internal.changedetection.TaskArtifactStateRepository;
import org.gradle.api.internal.tasks.TaskExecuter;
+import org.gradle.api.internal.tasks.TaskExecutionContext;
import org.gradle.api.internal.tasks.TaskStateInternal;
+import org.gradle.util.Clock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.ArrayList;
+import java.util.Formatter;
+import java.util.List;
+
/**
* A {@link TaskExecuter} which skips tasks whose outputs are up-to-date.
*/
@@ -32,35 +38,52 @@ public class SkipUpToDateTaskExecuter implements TaskExecuter {
private final TaskExecuter executer;
private final TaskArtifactStateRepository repository;
- public SkipUpToDateTaskExecuter(TaskExecuter executer, TaskArtifactStateRepository repository) {
+ public SkipUpToDateTaskExecuter(TaskArtifactStateRepository repository, TaskExecuter executer) {
this.executer = executer;
this.repository = repository;
}
- public void execute(TaskInternal task, TaskStateInternal state) {
+ public void execute(TaskInternal task, TaskStateInternal state, TaskExecutionContext context) {
LOGGER.debug("Determining if {} is up-to-date", task);
+ Clock clock = new Clock();
TaskArtifactState taskArtifactState = repository.getStateFor(task);
try {
- if (taskArtifactState.isUpToDate()) {
- LOGGER.info("Skipping {} as it is up-to-date", task);
+ List<String> messages = new ArrayList<String>();
+ if (taskArtifactState.isUpToDate(messages)) {
+ LOGGER.info("Skipping {} as it is up-to-date (took {}).", task, clock.getTime());
state.upToDate();
return;
-
}
- LOGGER.debug("{} is not up-to-date", task);
+ logOutOfDateMessages(messages, task, clock.getTime());
- taskArtifactState.beforeTask();
task.getOutputs().setHistory(taskArtifactState.getExecutionHistory());
+ context.setTaskArtifactState(taskArtifactState);
+
+ taskArtifactState.beforeTask();
try {
- executer.execute(task, state);
+ executer.execute(task, state, context);
if (state.getFailure() == null) {
taskArtifactState.afterTask();
}
} finally {
task.getOutputs().setHistory(null);
+ context.setTaskArtifactState(null);
}
} finally {
taskArtifactState.finished();
}
}
+
+
+ private void logOutOfDateMessages(List<String> messages, TaskInternal task, String took) {
+ if (LOGGER.isInfoEnabled()) {
+ Formatter formatter = new Formatter();
+ formatter.format("Executing %s (up-to-date check took %s) due to:", task, took);
+ for (String message : messages) {
+ formatter.format("%n %s", message);
+ }
+ LOGGER.info(formatter.toString());
+ }
+ }
+
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/execution/ValidatingTaskExecuter.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/execution/ValidatingTaskExecuter.java
index 67927c2..63ca339 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/execution/ValidatingTaskExecuter.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/tasks/execution/ValidatingTaskExecuter.java
@@ -18,6 +18,7 @@ package org.gradle.api.internal.tasks.execution;
import org.gradle.api.InvalidUserDataException;
import org.gradle.api.internal.TaskInternal;
import org.gradle.api.internal.tasks.TaskExecuter;
+import org.gradle.api.internal.tasks.TaskExecutionContext;
import org.gradle.api.internal.tasks.TaskStateInternal;
import org.gradle.api.tasks.TaskValidationException;
@@ -34,7 +35,7 @@ public class ValidatingTaskExecuter implements TaskExecuter {
this.executer = executer;
}
- public void execute(TaskInternal task, TaskStateInternal state) {
+ public void execute(TaskInternal task, TaskStateInternal state, TaskExecutionContext context) {
List<String> messages = new ArrayList<String>();
for (TaskValidator validator : task.getValidators()) {
validator.validate(task, messages);
@@ -54,6 +55,6 @@ public class ValidatingTaskExecuter implements TaskExecuter {
state.executed(new TaskValidationException(errorMessage, causes));
return;
}
- executer.execute(task, state);
+ executer.execute(task, state, context);
}
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/internal/xml/SimpleXmlWriter.java b/subprojects/core/src/main/groovy/org/gradle/api/internal/xml/SimpleXmlWriter.java
index 73bf959..38cee90 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/internal/xml/SimpleXmlWriter.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/internal/xml/SimpleXmlWriter.java
@@ -23,8 +23,6 @@ import java.io.Writer;
/**
* <p>A streaming XML writer.</p>
- *
- * by Szczepan Faber, created at: 12/3/12
*/
public class SimpleXmlWriter extends SimpleMarkupWriter {
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/invocation/Gradle.java b/subprojects/core/src/main/groovy/org/gradle/api/invocation/Gradle.java
index 2588fad..47576e8 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/invocation/Gradle.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/invocation/Gradle.java
@@ -23,6 +23,7 @@ import org.gradle.api.Project;
import org.gradle.api.ProjectEvaluationListener;
import org.gradle.api.execution.TaskExecutionGraph;
import org.gradle.api.internal.HasInternalProtocol;
+import org.gradle.api.plugins.PluginAware;
import java.io.File;
@@ -32,7 +33,7 @@ import java.io.File;
* <p>You can obtain a {@code Gradle} instance by calling {@link Project#getGradle()}.</p>
*/
@HasInternalProtocol
-public interface Gradle {
+public interface Gradle extends PluginAware {
/**
* Returns the current Gradle version.
*
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/logging/LogLevel.java b/subprojects/core/src/main/groovy/org/gradle/api/logging/LogLevel.java
index 4107c32..1935167 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/logging/LogLevel.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/logging/LogLevel.java
@@ -17,8 +17,6 @@ package org.gradle.api.logging;
/**
* The log levels supported by Gradle.
- *
- * @author Hans Dockter
*/
public enum LogLevel {
DEBUG {
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/logging/Logging.java b/subprojects/core/src/main/groovy/org/gradle/api/logging/Logging.java
index 0d60dc2..7d2b455 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/logging/Logging.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/logging/Logging.java
@@ -27,8 +27,6 @@ import java.util.Map;
/**
* <p>The main entry point for Gradle's logging system. Gradle routes all logging via SLF4J. You can use either an SLF4J
* {@link org.slf4j.Logger} or a Gradle {@link Logger} to perform logging.</p>
- *
- * @author Hans Dockter
*/
public class Logging {
public static final Marker LIFECYCLE = MarkerFactory.getDetachedMarker("LIFECYCLE");
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/plugins/Convention.java b/subprojects/core/src/main/groovy/org/gradle/api/plugins/Convention.java
index b38dad3..7256711 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/plugins/Convention.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/plugins/Convention.java
@@ -24,8 +24,6 @@ import java.util.Map;
* Convention}, and the properties and methods of the convention object become available as properties and methods of
* the object which the convention is associated to. A convention object is simply a POJO or POGO. Usually, a {@code
* Convention} is used by plugins to extend a {@link org.gradle.api.Project} or a {@link org.gradle.api.Task}.</p>
- *
- * @author Hans Dockter
*/
public interface Convention extends ExtensionContainer {
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/plugins/ExtensionContainer.java b/subprojects/core/src/main/groovy/org/gradle/api/plugins/ExtensionContainer.java
index 0c8edbb..9835707 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/plugins/ExtensionContainer.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/plugins/ExtensionContainer.java
@@ -19,10 +19,12 @@ package org.gradle.api.plugins;
import org.gradle.api.Action;
import org.gradle.api.Incubating;
import org.gradle.api.UnknownDomainObjectException;
+import org.gradle.api.internal.HasInternalProtocol;
/**
* Allows adding 'namespaced' DSL extensions to a target object.
*/
+ at HasInternalProtocol
public interface ExtensionContainer {
/**
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/plugins/PluginAware.java b/subprojects/core/src/main/groovy/org/gradle/api/plugins/PluginAware.java
new file mode 100644
index 0000000..2dd774b
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/plugins/PluginAware.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.plugins;
+
+import groovy.lang.Closure;
+
+import java.util.Map;
+
+/**
+ * Objects a {@link org.gradle.api.Plugin} can be applied to.
+ *
+ * <p>
+ * For more on writing and applying plugins, see {@link org.gradle.api.Plugin}.
+ * </p>
+ */
+public interface PluginAware {
+ /**
+ * Returns the plugins container for this object. The returned container can be used to manage the plugins which
+ * are used by this object.
+ *
+ * @return the plugin container. Never returns null.
+ */
+ PluginContainer getPlugins();
+
+ /**
+ * <p>Configures this object using plugins or scripts. The given closure is used to configure an {@link
+ * ObjectConfigurationAction} which is then used to configure this object.</p>
+ *
+ * @param closure The closure to configure the {@code ObjectConfigurationAction}.
+ */
+ void apply(Closure closure);
+
+ /**
+ * <p>Configures this Object using plugins or scripts. The following options are available:</p>
+ *
+ * <ul><li>{@code from}: A script to apply to the object. Accepts any path supported by {@link org.gradle.api.Project#uri(Object)}.</li>
+ *
+ * <li>{@code plugin}: The id or implementation class of the plugin to apply to the object.</li>
+ *
+ * <li>{@code to}: The target delegate object or objects. Use this to configure objects other than this
+ * object.</li></ul>
+ *
+ * <p>For more detail, see {@link ObjectConfigurationAction}.</p>
+ *
+ * @param options The options to use to configure the {@code ObjectConfigurationAction}.
+ */
+ void apply(Map<String, ?> options);
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/plugins/PluginCollection.java b/subprojects/core/src/main/groovy/org/gradle/api/plugins/PluginCollection.java
index 1430c64..99e5b24 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/plugins/PluginCollection.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/plugins/PluginCollection.java
@@ -15,17 +15,15 @@
*/
package org.gradle.api.plugins;
-import org.gradle.api.DomainObjectSet;
-import org.gradle.api.specs.Spec;
+import groovy.lang.Closure;
import org.gradle.api.Action;
+import org.gradle.api.DomainObjectSet;
import org.gradle.api.Plugin;
-
-import groovy.lang.Closure;
+import org.gradle.api.specs.Spec;
/**
* <p>A {@code PluginCollection} represents a collection of {@link org.gradle.api.Plugin} instances.</p>
*
- * @author Hans Dockter
* @param <T> The type of plugins which this collection contains.
*/
public interface PluginCollection<T extends Plugin> extends DomainObjectSet<T> {
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/plugins/PluginContainer.java b/subprojects/core/src/main/groovy/org/gradle/api/plugins/PluginContainer.java
index c90d288..ef8025f 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/plugins/PluginContainer.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/plugins/PluginContainer.java
@@ -24,8 +24,6 @@ import org.gradle.api.Plugin;
*
* <p>Plugins can be specified using either an id or type. The id of a plugin is specified using a
* META-INF/gradle-plugins/${id}.properties classpath resource.</p>
- *
- * @author Hans Dockter
*/
public interface PluginContainer extends PluginCollection<Plugin> {
/**
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/plugins/PluginInstantiationException.java b/subprojects/core/src/main/groovy/org/gradle/api/plugins/PluginInstantiationException.java
index 914d3fd..9d5cc54 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/plugins/PluginInstantiationException.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/plugins/PluginInstantiationException.java
@@ -19,8 +19,6 @@ import org.gradle.api.GradleException;
/**
* A {@code PluginInstantiationException} is thrown when a plugin cannot be instantiated.
- *
- * @author Hans Dockter
*/
public class PluginInstantiationException extends GradleException {
public PluginInstantiationException(String message) {
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/plugins/UnknownPluginException.java b/subprojects/core/src/main/groovy/org/gradle/api/plugins/UnknownPluginException.java
index fce0920..a0c1c19 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/plugins/UnknownPluginException.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/plugins/UnknownPluginException.java
@@ -19,8 +19,6 @@ import org.gradle.api.InvalidUserDataException;
/**
* A {@code UnknownPluginException} is thrown when an unknown plugin id is provided.
- *
- * @author Hans Dockter
*/
public class UnknownPluginException extends InvalidUserDataException {
public UnknownPluginException(String message) {
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/specs/Specs.java b/subprojects/core/src/main/groovy/org/gradle/api/specs/Specs.java
index bf6c8d8..0430238 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/specs/Specs.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/specs/Specs.java
@@ -25,8 +25,6 @@ import java.util.Set;
/**
* Provides a number of {@link org.gradle.api.specs.Spec} implementations.
- *
- * @author Hans Dockter
*/
public class Specs {
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/tasks/AbstractCopyTask.java b/subprojects/core/src/main/groovy/org/gradle/api/tasks/AbstractCopyTask.java
index 6b610b8..cb3630f 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/tasks/AbstractCopyTask.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/tasks/AbstractCopyTask.java
@@ -19,11 +19,12 @@ import groovy.lang.Closure;
import org.gradle.api.Action;
import org.gradle.api.file.*;
import org.gradle.api.internal.ConventionTask;
-import org.gradle.api.internal.file.copy.CopyActionImpl;
-import org.gradle.api.internal.file.copy.CopySpecSource;
-import org.gradle.api.internal.file.copy.ReadableCopySpec;
+import org.gradle.api.internal.file.FileResolver;
+import org.gradle.api.internal.file.copy.*;
import org.gradle.api.specs.Spec;
import org.gradle.internal.Factory;
+import org.gradle.internal.nativeplatform.filesystem.FileSystem;
+import org.gradle.internal.reflect.Instantiator;
import org.gradle.util.DeprecationLogger;
import java.io.FilterReader;
@@ -36,15 +37,37 @@ import java.util.regex.Pattern;
*/
public abstract class AbstractCopyTask extends ConventionTask implements CopySpec, CopySpecSource {
+ private final CopySpecInternal rootSpec;
+ private final CopySpecInternal mainSpec;
+
+ protected AbstractCopyTask() {
+ this.rootSpec = createRootSpec();
+ this.mainSpec = rootSpec.addChild();
+ }
+
+ protected CopySpecInternal createRootSpec() {
+ Instantiator instantiator = getServices().get(Instantiator.class);
+ FileResolver fileResolver = getServices().get(FileResolver.class);
+ return instantiator.newInstance(DefaultCopySpec.class, fileResolver, instantiator);
+ }
+
+ protected abstract CopyAction createCopyAction();
+
@TaskAction
protected void copy() {
configureRootSpec();
- getCopyAction().execute();
- setDidWork(getCopyAction().getDidWork());
+
+ Instantiator instantiator = getServices().get(Instantiator.class);
+ FileSystem fileSystem = getServices().get(FileSystem.class);
+
+ CopyActionExecuter copyActionExecuter = new CopyActionExecuter(instantiator, fileSystem);
+ CopyAction copyAction = createCopyAction();
+ WorkResult didWork = copyActionExecuter.execute(rootSpec, copyAction);
+ setDidWork(didWork.getDidWork());
}
protected void configureRootSpec() {
- if (!getCopyAction().hasSource()) {
+ if (!rootSpec.hasSource()) {
Object srcDirs = getDefaultSource();
if (srcDirs != null) {
from(srcDirs);
@@ -68,8 +91,8 @@ public abstract class AbstractCopyTask extends ConventionTask implements CopySpe
*/
@InputFiles @SkipWhenEmpty @Optional
public FileCollection getSource() {
- if(getCopyAction().hasSource()){
- return getCopyAction().getAllSource();
+ if (rootSpec.hasSource()){
+ return rootSpec.getAllSource();
}else{
return DeprecationLogger.whileDisabled(new Factory<FileCollection>() {
public FileCollection create() {
@@ -78,19 +101,18 @@ public abstract class AbstractCopyTask extends ConventionTask implements CopySpe
});
}
}
-
- protected abstract CopyActionImpl getCopyAction();
- public ReadableCopySpec getRootSpec() {
- return getCopyAction().getRootSpec();
+
+ public CopySpecInternal getRootSpec() {
+ return rootSpec;
}
// -----------------------------------------------
// ---- Delegate CopySpec methods to rootSpec ----
// -----------------------------------------------
- protected CopySpec getMainSpec() {
- return getCopyAction();
+ protected CopySpecInternal getMainSpec() {
+ return mainSpec;
}
/**
@@ -124,6 +146,20 @@ public abstract class AbstractCopyTask extends ConventionTask implements CopySpe
/**
* {@inheritDoc}
*/
+ public void setDuplicatesStrategy(DuplicatesStrategy strategy) {
+ getRootSpec().setDuplicatesStrategy(strategy);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public DuplicatesStrategy getDuplicatesStrategy() {
+ return getRootSpec().getDuplicatesStrategy();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public AbstractCopyTask from(Object... sourcePaths) {
getMainSpec().from(sourcePaths);
return this;
@@ -132,6 +168,22 @@ public abstract class AbstractCopyTask extends ConventionTask implements CopySpe
/**
* {@inheritDoc}
*/
+ public AbstractCopyTask filesMatching(String pattern, Action<? super FileCopyDetails> action) {
+ getMainSpec().filesMatching(pattern, action);
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public AbstractCopyTask filesNotMatching(String pattern, Action<? super FileCopyDetails> action) {
+ getMainSpec().filesNotMatching(pattern, action);
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public AbstractCopyTask from(Object sourcePath, Closure c) {
getMainSpec().from(sourcePath, c);
return this;
@@ -149,7 +201,7 @@ public abstract class AbstractCopyTask extends ConventionTask implements CopySpe
* {@inheritDoc}
*/
public AbstractCopyTask into(Object destDir) {
- getMainSpec().into(destDir);
+ getRootSpec().into(destDir);
return this;
}
@@ -356,4 +408,5 @@ public abstract class AbstractCopyTask extends ConventionTask implements CopySpe
getMainSpec().eachFile(closure);
return this;
}
+
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/tasks/AntBuilderAware.groovy b/subprojects/core/src/main/groovy/org/gradle/api/tasks/AntBuilderAware.groovy
index d1a9b5b..9031780 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/tasks/AntBuilderAware.groovy
+++ b/subprojects/core/src/main/groovy/org/gradle/api/tasks/AntBuilderAware.groovy
@@ -19,8 +19,6 @@ package org.gradle.api.tasks
/**
* An {@code AntBuilderAware} represents an object which can add itself to Ant tasks, using an
* {@link org.gradle.api.AntBuilder}.
- *
- * @author Hans Dockter
*/
interface AntBuilderAware {
def addToAntBuilder(node, String childNodeName)
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/tasks/ConventionValue.java b/subprojects/core/src/main/groovy/org/gradle/api/tasks/ConventionValue.java
index 4db9eb5..7cd2625 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/tasks/ConventionValue.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/tasks/ConventionValue.java
@@ -23,7 +23,6 @@ import org.gradle.api.plugins.Convention;
* A ConventionValue can be assigned to a {@link org.gradle.api.internal.IConventionAware} task. If a property of such an object is not set internally, a ConventionValue is used to calculate the value
* for the property.
*
- * @author Hans Dockter
* @deprecated Use {@link groovy.lang.Closure} or {@link java.util.concurrent.Callable} instead.
*/
@Deprecated
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/tasks/Copy.java b/subprojects/core/src/main/groovy/org/gradle/api/tasks/Copy.java
index 1cdf48b..295d77d 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/tasks/Copy.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/tasks/Copy.java
@@ -16,9 +16,15 @@
package org.gradle.api.tasks;
+import org.gradle.api.InvalidUserDataException;
+import org.gradle.api.internal.file.BaseDirFileResolver;
import org.gradle.api.internal.file.FileResolver;
-import org.gradle.api.internal.file.copy.FileCopyActionImpl;
-import org.gradle.api.internal.file.copy.FileCopySpecVisitor;
+import org.gradle.api.internal.file.copy.CopyAction;
+import org.gradle.api.internal.file.copy.CopySpecInternal;
+import org.gradle.api.internal.file.copy.DestinationRootCopySpec;
+import org.gradle.api.internal.file.copy.FileCopyAction;
+import org.gradle.internal.nativeplatform.filesystem.FileSystems;
+import org.gradle.internal.reflect.Instantiator;
import java.io.File;
@@ -29,58 +35,54 @@ import java.io.File;
* <p> Examples:
* <pre autoTested=''>
* task mydoc(type:Copy) {
- * from 'src/main/doc'
- * into 'build/target/doc'
+ * from 'src/main/doc'
+ * into 'build/target/doc'
* }
*
* //for ant filter
* import org.apache.tools.ant.filters.ReplaceTokens
*
* task initconfig(type:Copy) {
- * from('src/main/config') {
- * include '**/*.properties'
- * include '**/*.xml'
- * filter(ReplaceTokens, tokens:[version:'2.3.1'])
- * }
- * from('src/main/config') {
- * exclude '**/*.properties', '**/*.xml'
- * }
- * from('src/main/languages') {
- * rename 'EN_US_(.*)', '$1'
- * }
- * into 'build/target/config'
- * exclude '**/*.bak'
+ * from('src/main/config') {
+ * include '**/*.properties'
+ * include '**/*.xml'
+ * filter(ReplaceTokens, tokens:[version:'2.3.1'])
+ * }
+ * from('src/main/config') {
+ * exclude '**/*.properties', '**/*.xml'
+ * }
+ * from('src/main/languages') {
+ * rename 'EN_US_(.*)', '$1'
+ * }
+ * into 'build/target/config'
+ * exclude '**/*.bak'
*
- * includeEmptyDirs = false
+ * includeEmptyDirs = false
* }
* </pre>
- *
- * @author Steve Appling
*/
public class Copy extends AbstractCopyTask {
- private FileCopyActionImpl copyAction;
-
- public Copy() {
- FileResolver fileResolver = getServices().get(FileResolver.class);
- copyAction = new FileCopyActionImpl(fileResolver, new FileCopySpecVisitor());
- }
- protected void configureRootSpec() {
- super.configureRootSpec();
- if (getCopyAction().getDestinationDir() == null) {
- File destDir = getDestinationDir();
- if (destDir != null) {
- into(destDir);
- }
+ @Override
+ protected CopyAction createCopyAction() {
+ File destinationDir = getDestinationDir();
+ if (destinationDir == null) {
+ throw new InvalidUserDataException("No copy destination directory has been specified, use 'into' to specify a target directory.");
}
+ return new FileCopyAction(new BaseDirFileResolver(FileSystems.getDefault(), destinationDir));
}
- public FileCopyActionImpl getCopyAction() {
- return copyAction;
+ @Override
+ protected CopySpecInternal createRootSpec() {
+ Instantiator instantiator = getServices().get(Instantiator.class);
+ FileResolver fileResolver = getServices().get(FileResolver.class);
+
+ return instantiator.newInstance(DestinationRootCopySpec.class, fileResolver, super.createRootSpec());
}
- public void setCopyAction(FileCopyActionImpl copyAction) {
- this.copyAction = copyAction;
+ @Override
+ public DestinationRootCopySpec getRootSpec() {
+ return (DestinationRootCopySpec) super.getRootSpec();
}
/**
@@ -90,7 +92,7 @@ public class Copy extends AbstractCopyTask {
*/
@OutputDirectory
public File getDestinationDir() {
- return getCopyAction().getDestinationDir();
+ return getRootSpec().getDestinationDir();
}
/**
@@ -101,4 +103,5 @@ public class Copy extends AbstractCopyTask {
public void setDestinationDir(File destinationDir) {
into(destinationDir);
}
+
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/tasks/Delete.java b/subprojects/core/src/main/groovy/org/gradle/api/tasks/Delete.java
index 531ec76..f09ef9d 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/tasks/Delete.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/tasks/Delete.java
@@ -29,8 +29,6 @@ import java.util.Set;
* delete 'uglyFolder', 'uglyFile'
* }
* </pre>
- *
- * @author Hans Dockter
*/
public class Delete extends ConventionTask {
private Set<Object> delete = new LinkedHashSet<Object>();
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/tasks/Exec.java b/subprojects/core/src/main/groovy/org/gradle/api/tasks/Exec.java
index 13b2e11..e679f10 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/tasks/Exec.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/tasks/Exec.java
@@ -50,8 +50,6 @@ import java.util.Map;
* }
* }
* </pre>
- *
- * @author Hans Dockter
*/
public class Exec extends ConventionTask implements ExecSpec {
private ExecAction execAction;
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/tasks/GradleBuild.java b/subprojects/core/src/main/groovy/org/gradle/api/tasks/GradleBuild.java
index ecde020..06fc04c 100755
--- a/subprojects/core/src/main/groovy/org/gradle/api/tasks/GradleBuild.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/tasks/GradleBuild.java
@@ -15,10 +15,11 @@
*/
package org.gradle.api.tasks;
-import org.gradle.GradleLauncher;
import org.gradle.StartParameter;
import org.gradle.api.internal.ConventionTask;
+import org.gradle.initialization.GradleLauncherFactory;
+import javax.inject.Inject;
import java.io.File;
import java.util.Collection;
import java.util.List;
@@ -27,10 +28,13 @@ import java.util.List;
* Executes a Gradle build.
*/
public class GradleBuild extends ConventionTask {
+ private final GradleLauncherFactory gradleLauncherFactory;
private StartParameter startParameter;
- public GradleBuild() {
- this.startParameter = getProject().getGradle().getStartParameter().newBuild();
+ @Inject
+ public GradleBuild(StartParameter currentBuild, GradleLauncherFactory gradleLauncherFactory) {
+ this.gradleLauncherFactory = gradleLauncherFactory;
+ this.startParameter = currentBuild.newBuild();
startParameter.setCurrentDir(getProject().getProjectDir());
}
@@ -109,6 +113,6 @@ public class GradleBuild extends ConventionTask {
@TaskAction
void build() {
- GradleLauncher.newInstance(getStartParameter()).run().rethrowFailure();
+ gradleLauncherFactory.newInstance(getStartParameter()).run().rethrowFailure();
}
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/tasks/JavaExec.java b/subprojects/core/src/main/groovy/org/gradle/api/tasks/JavaExec.java
index 541830d..f8c496c 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/tasks/JavaExec.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/tasks/JavaExec.java
@@ -33,8 +33,6 @@ import java.util.Map;
/**
* Executes a Java application in a child process.
- *
- * @author Hans Dockter
*/
public class JavaExec extends ConventionTask implements JavaExecSpec {
private JavaExecAction javaExecHandleBuilder;
@@ -46,7 +44,8 @@ public class JavaExec extends ConventionTask implements JavaExecSpec {
@TaskAction
public void exec() {
- setMain(getMain()); // make convention mapping work (at least for 'main')
+ setMain(getMain()); // make convention mapping work (at least for 'main'...
+ setJvmArgs(getJvmArgs()); // ...and for 'jvmArgs')
javaExecHandleBuilder.execute();
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/tasks/StopActionException.java b/subprojects/core/src/main/groovy/org/gradle/api/tasks/StopActionException.java
index 3def548..7eb97ea 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/tasks/StopActionException.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/tasks/StopActionException.java
@@ -32,8 +32,6 @@ import org.gradle.api.GradleException;
* need the if statement.</p>
*
* <p>Note that throwing this exception does not fail the execution of the task or the build.</p>
- *
- * @author Hans Dockter
*/
public class StopActionException extends GradleException {
public StopActionException() {
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/tasks/StopExecutionException.java b/subprojects/core/src/main/groovy/org/gradle/api/tasks/StopExecutionException.java
index 233e3f1..9900845 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/tasks/StopExecutionException.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/tasks/StopExecutionException.java
@@ -22,8 +22,6 @@ package org.gradle.api.tasks;
* actions to be added to a task which abort execution of the task if the preconditions are not met.</p>
*
* <p>Note that throwing this exception does not fail the execution of the task or the build.</p>
- *
- * @author Hans Dockter
*/
public class StopExecutionException extends RuntimeException {
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/tasks/Sync.java b/subprojects/core/src/main/groovy/org/gradle/api/tasks/Sync.java
index 7f4e22a..60773aa 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/tasks/Sync.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/tasks/Sync.java
@@ -16,10 +16,12 @@
package org.gradle.api.tasks;
+import org.gradle.api.InvalidUserDataException;
+import org.gradle.api.internal.file.BaseDirFileResolver;
import org.gradle.api.internal.file.FileResolver;
-import org.gradle.api.internal.file.copy.FileCopyActionImpl;
-import org.gradle.api.internal.file.copy.FileCopySpecVisitor;
-import org.gradle.api.internal.file.copy.SyncCopySpecVisitor;
+import org.gradle.api.internal.file.copy.*;
+import org.gradle.internal.nativeplatform.filesystem.FileSystems;
+import org.gradle.internal.reflect.Instantiator;
import java.io.File;
@@ -27,16 +29,27 @@ import java.io.File;
* Synchronises the contents of a destination directory with some source directories and files.
*/
public class Sync extends AbstractCopyTask {
- private FileCopyActionImpl action;
- public Sync() {
+ @Override
+ protected CopyAction createCopyAction() {
+ File destinationDir = getDestinationDir();
+ if (destinationDir == null) {
+ throw new InvalidUserDataException("No copy destination directory has been specified, use 'into' to specify a target directory.");
+ }
+ return new SyncCopyActionDecorator(destinationDir, new FileCopyAction(new BaseDirFileResolver(FileSystems.getDefault(), destinationDir)));
+ }
+
+ @Override
+ protected CopySpecInternal createRootSpec() {
+ Instantiator instantiator = getServices().get(Instantiator.class);
FileResolver fileResolver = getServices().get(FileResolver.class);
- action = new FileCopyActionImpl(fileResolver, new SyncCopySpecVisitor(new FileCopySpecVisitor()));
+
+ return instantiator.newInstance(DestinationRootCopySpec.class, fileResolver, super.createRootSpec());
}
@Override
- protected FileCopyActionImpl getCopyAction() {
- return action;
+ public DestinationRootCopySpec getRootSpec() {
+ return (DestinationRootCopySpec) super.getRootSpec();
}
/**
@@ -46,7 +59,7 @@ public class Sync extends AbstractCopyTask {
*/
@OutputDirectory
public File getDestinationDir() {
- return getCopyAction().getDestinationDir();
+ return getRootSpec().getDestinationDir();
}
/**
@@ -57,4 +70,5 @@ public class Sync extends AbstractCopyTask {
public void setDestinationDir(File destinationDir) {
into(destinationDir);
}
+
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/tasks/TaskContainer.java b/subprojects/core/src/main/groovy/org/gradle/api/tasks/TaskContainer.java
index 266042e..f7168aa 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/tasks/TaskContainer.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/tasks/TaskContainer.java
@@ -26,7 +26,7 @@ import java.util.Map;
* <p>You can obtain a {@code TaskContainer} instance by calling {@link org.gradle.api.Project#getTasks()}, or using the
* {@code tasks} property in your build script.</p>
*/
-public interface TaskContainer extends TaskCollection<Task>, NamedDomainObjectContainer<Task> {
+public interface TaskContainer extends TaskCollection<Task>, PolymorphicDomainObjectContainer<Task> {
/**
* <p>Locates a task by path. You can supply a task name, a relative path, or an absolute path. Relative paths are
* interpreted relative to the project for this container. This method returns null if no task with the given path
@@ -62,7 +62,7 @@ public interface TaskContainer extends TaskCollection<Task>, NamedDomainObjectCo
* <tr><td><code>{@value org.gradle.api.Task#TASK_TYPE}</code></td><td>The class of the task to
* create.</td><td>{@link org.gradle.api.DefaultTask}</td></tr>
*
- * <tr><td><code>{@value org.gradle.api.Task#TASK_ACTION}</code></td><td>The closure or {@link TaskAction} to
+ * <tr><td><code>{@value org.gradle.api.Task#TASK_ACTION}</code></td><td>The closure or {@link Action} to
* execute when the task executes. See {@link Task#doFirst(Action)}.</td><td><code>null</code></td></tr>
*
* <tr><td><code>{@value org.gradle.api.Task#TASK_OVERWRITE}</code></td><td>Replace an existing
@@ -76,13 +76,52 @@ public interface TaskContainer extends TaskCollection<Task>, NamedDomainObjectCo
* <p>After the task is added, it is made available as a property of the project, so that you can reference the task
* by name in your build file. See <a href="../Project.html#properties">here</a> for more details.</p>
*
- * <p>If a task with the given name already exists in this container and the <code>overwrite</code> option is not set
- * to true, an exception is thrown.</p>
+ * <p>If a task with the given name already exists in this container and the <code>{@value org.gradle.api.Task#TASK_OVERWRITE}</code>
+ * option is not set to true, an exception is thrown.</p>
*
* @param options The task creation options.
* @return The newly created task object
* @throws InvalidUserDataException If a task with the given name already exists in this project.
*/
+ Task create(Map<String, ?> options) throws InvalidUserDataException;
+
+ /**
+ * <p>Creates a {@link Task} and adds it to this container. A map of creation options can be passed to this method
+ * to control how the task is created. The following options are available:</p>
+ *
+ * <table>
+ *
+ * <tr><th>Option</th><th>Description</th><th>Default Value</th></tr>
+ *
+ * <tr><td><code>{@value org.gradle.api.Task#TASK_NAME}</code></td><td>The name of the task to create.</td><td>None.
+ * Must be specified.</td></tr>
+ *
+ * <tr><td><code>{@value org.gradle.api.Task#TASK_TYPE}</code></td><td>The class of the task to
+ * create.</td><td>{@link org.gradle.api.DefaultTask}</td></tr>
+ *
+ * <tr><td><code>{@value org.gradle.api.Task#TASK_ACTION}</code></td><td>The closure or {@link Action} to
+ * execute when the task executes. See {@link Task#doFirst(Action)}.</td><td><code>null</code></td></tr>
+ *
+ * <tr><td><code>{@value org.gradle.api.Task#TASK_OVERWRITE}</code></td><td>Replace an existing
+ * task?</td><td><code>false</code></td></tr>
+ *
+ * <tr><td><code>{@value org.gradle.api.Task#TASK_DEPENDS_ON}</code></td><td>The dependencies of the task. See <a
+ * href="../Task.html#dependencies">here</a> for more details.</td><td><code>[]</code></td></tr>
+ *
+ * </table>
+ *
+ * <p>After the task is added, it is made available as a property of the project, so that you can reference the task
+ * by name in your build file. See <a href="../Project.html#properties">here</a> for more details.</p>
+ *
+ * <p>If a task with the given name already exists in this container and the <code>{@value org.gradle.api.Task#TASK_OVERWRITE}</code>
+ * option is not set to true, an exception is thrown.</p>
+ *
+ * @param options The task creation options.
+ * @return The newly created task object
+ * @throws InvalidUserDataException If a task with the given name already exists in this project.
+ * @deprecated use {@link #create(java.util.Map)} instead
+ */
+ @Deprecated
Task add(Map<String, ?> options) throws InvalidUserDataException;
/**
@@ -98,6 +137,23 @@ public interface TaskContainer extends TaskCollection<Task>, NamedDomainObjectCo
* @return The newly created task object
* @throws InvalidUserDataException If a task with the given name already exists in this project.
*/
+ Task create(Map<String, ?> options, Closure configureClosure) throws InvalidUserDataException;
+
+ /**
+ * <p>Creates a {@link Task} adds it to this container. A map of creation options can be passed to this method to
+ * control how the task is created. See {@link #add(java.util.Map)} for the list of options available. The given
+ * closure is used to configure the task before it is returned by this method.</p>
+ *
+ * <p>After the task is added, it is made available as a property of the project, so that you can reference the task
+ * by name in your build file. See <a href="../Project.html#properties">here</a> for more details.</p>
+ *
+ * @param options The task creation options.
+ * @param configureClosure The closure to use to configure the task.
+ * @return The newly created task object
+ * @throws InvalidUserDataException If a task with the given name already exists in this project.
+ * @deprecated use {@link #create(java.util.Map, groovy.lang.Closure)} instead
+ */
+ @Deprecated
Task add(Map<String, ?> options, Closure configureClosure) throws InvalidUserDataException;
/**
@@ -112,6 +168,22 @@ public interface TaskContainer extends TaskCollection<Task>, NamedDomainObjectCo
* @return The newly created task object
* @throws InvalidUserDataException If a task with the given name already exists in this project.
*/
+ Task create(String name, Closure configureClosure) throws InvalidUserDataException;
+
+ /**
+ * <p>Creates a {@link Task} with the given name adds it to this container. The given closure is used to configure
+ * the task before it is returned by this method.</p>
+ *
+ * <p>After the task is added, it is made available as a property of the project, so that you can reference the task
+ * by name in your build file. See <a href="../Project.html#properties">here</a> for more details.</p>
+ *
+ * @param name The name of the task to be created
+ * @param configureClosure The closure to use to configure the task.
+ * @return The newly created task object
+ * @throws InvalidUserDataException If a task with the given name already exists in this project.
+ * @deprecated use {@link #create(String, groovy.lang.Closure)} instead
+ */
+ @Deprecated
Task add(String name, Closure configureClosure) throws InvalidUserDataException;
/**
@@ -124,6 +196,20 @@ public interface TaskContainer extends TaskCollection<Task>, NamedDomainObjectCo
* @return The newly created task object
* @throws InvalidUserDataException If a task with the given name already exists in this project.
*/
+ Task create(String name) throws InvalidUserDataException;
+
+ /**
+ * <p>Creates a {@link Task} with the given name and adds it to this container.</p>
+ *
+ * <p>After the task is added, it is made available as a property of the project, so that you can reference the task
+ * by name in your build file. See <a href="../Project.html#properties">here</a> for more details.</p>
+ *
+ * @param name The name of the task to be created
+ * @return The newly created task object
+ * @throws InvalidUserDataException If a task with the given name already exists in this project.
+ * @deprecated use {@link #create(String)} instead
+ */
+ @Deprecated
Task add(String name) throws InvalidUserDataException;
/**
@@ -137,9 +223,38 @@ public interface TaskContainer extends TaskCollection<Task>, NamedDomainObjectCo
* @return The newly created task object
* @throws InvalidUserDataException If a task with the given name already exists in this project.
*/
+ <T extends Task> T create(String name, Class<T> type) throws InvalidUserDataException;
+
+ /**
+ * <p>Creates a {@link Task} with the given name and type, and adds it to this container.</p>
+ *
+ * <p>After the task is added, it is made available as a property of the project, so that you can reference the task
+ * by name in your build file. See <a href="../Project.html#properties">here</a> for more details.</p>
+ *
+ * @param name The name of the task to be created.
+ * @param type The type of task to create.
+ * @return The newly created task object
+ * @throws InvalidUserDataException If a task with the given name already exists in this project.
+ * @deprecated use {@link #create(String, Class)} instead
+ */
+ @Deprecated
<T extends Task> T add(String name, Class<T> type) throws InvalidUserDataException;
/**
+ * <p>Creates a {@link Task} with the given name and type, configures it with the given action, and adds it to this container.</p>
+ *
+ * <p>After the task is added, it is made available as a property of the project, so that you can reference the task
+ * by name in your build file. See <a href="../Project.html#properties">here</a> for more details.</p>
+ *
+ * @param name The name of the task to be created.
+ * @param type The type of task to create.
+ * @param configuration The action to configure the task with.
+ * @return The newly created task object.
+ * @throws InvalidUserDataException If a task with the given name already exists in this project.
+ */
+ <T extends Task> T create(String name, Class<T> type, Action<? super T> configuration) throws InvalidUserDataException;
+
+ /**
* <p>Creates a {@link Task} with the given name and adds it to this container, replacing any existing task with the
* same name.</p>
*
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/tasks/Upload.java b/subprojects/core/src/main/groovy/org/gradle/api/tasks/Upload.java
index 926975c..922186f 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/tasks/Upload.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/tasks/Upload.java
@@ -17,7 +17,6 @@
package org.gradle.api.tasks;
import groovy.lang.Closure;
-import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.Module;
import org.gradle.api.artifacts.PublishException;
@@ -28,8 +27,6 @@ import org.gradle.api.internal.Transformers;
import org.gradle.api.internal.artifacts.ArtifactPublicationServices;
import org.gradle.api.internal.artifacts.ArtifactPublisher;
import org.gradle.api.internal.artifacts.configurations.ConfigurationInternal;
-import org.gradle.api.internal.artifacts.ivyservice.IvyModuleDescriptorWriter;
-import org.gradle.api.internal.artifacts.ivyservice.ModuleDescriptorConverter;
import org.gradle.api.internal.artifacts.repositories.PublicationAwareRepository;
import org.gradle.util.ConfigureUtil;
@@ -42,8 +39,6 @@ import static org.gradle.util.CollectionUtils.collect;
/**
* Uploads the artifacts of a {@link Configuration} to a set of repositories.
- *
- * @author Hans Dockter
*/
public class Upload extends ConventionTask {
@@ -67,19 +62,11 @@ public class Upload extends ConventionTask {
Set<Configuration> configurationsToPublish = configuration.getHierarchy();
ArtifactPublisher artifactPublisher = publicationServices.createArtifactPublisher();
+ File descriptorDestination = isUploadDescriptor() ? getDescriptorDestination() : null;
+ List<PublicationAwareRepository> publishRepositories = collect(repositories, Transformers.cast(PublicationAwareRepository.class));
try {
- File descriptorDestination = isUploadDescriptor() ? getDescriptorDestination() : null;
- if (descriptorDestination != null) {
- Set<Configuration> allConfigurations = configurationsToPublish.iterator().next().getAll();
- ModuleDescriptorConverter moduleDescriptorConverter = publicationServices.getDescriptorFileModuleConverter();
- ModuleDescriptor moduleDescriptor = moduleDescriptorConverter.convert(allConfigurations, module);
- IvyModuleDescriptorWriter ivyModuleDescriptorWriter = publicationServices.getIvyModuleDescriptorWriter();
- ivyModuleDescriptorWriter.write(moduleDescriptor, descriptorDestination);
- }
-
- List<PublicationAwareRepository> publishRepositories = collect(repositories, Transformers.cast(PublicationAwareRepository.class));
- artifactPublisher.publish(publishRepositories, module, configurationsToPublish, descriptorDestination);
+ artifactPublisher.publish(publishRepositories, module, configurationsToPublish, descriptorDestination);
} catch (Exception e) {
throw new PublishException(String.format("Could not publish configuration '%s'", configuration.getName()), e);
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/tasks/bundling/AbstractArchiveTask.java b/subprojects/core/src/main/groovy/org/gradle/api/tasks/bundling/AbstractArchiveTask.java
index fd88ab9..3058b41 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/tasks/bundling/AbstractArchiveTask.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/tasks/bundling/AbstractArchiveTask.java
@@ -24,8 +24,6 @@ import java.io.File;
/**
* {@code AbstractArchiveTask} is the base class for all archive tasks.
- *
- * @author Hans Dockter
*/
public abstract class AbstractArchiveTask extends AbstractCopyTask {
private File destinationDir;
@@ -185,4 +183,5 @@ public abstract class AbstractArchiveTask extends AbstractCopyTask {
super.into(destPath, configureClosure);
return this;
}
+
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/tasks/bundling/Compression.java b/subprojects/core/src/main/groovy/org/gradle/api/tasks/bundling/Compression.java
index f8b04db..863fe28 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/tasks/bundling/Compression.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/tasks/bundling/Compression.java
@@ -23,8 +23,6 @@ import java.util.List;
/**
* Specifies the compression which should be applied to a TAR archive.
- *
- * @author Hans Dockter
*/
public enum Compression {
NONE("tar"),
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/tasks/bundling/Tar.java b/subprojects/core/src/main/groovy/org/gradle/api/tasks/bundling/Tar.java
index f8af439..396cbef 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/tasks/bundling/Tar.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/tasks/bundling/Tar.java
@@ -16,29 +16,22 @@
package org.gradle.api.tasks.bundling;
-import org.gradle.api.internal.file.FileResolver;
-import org.gradle.api.internal.file.archive.TarCopySpecVisitor;
-import org.gradle.api.internal.file.archive.compression.Bzip2Archiver;
+import org.gradle.api.internal.file.archive.TarCopyAction;
import org.gradle.api.internal.file.archive.compression.ArchiveOutputStreamFactory;
+import org.gradle.api.internal.file.archive.compression.Bzip2Archiver;
import org.gradle.api.internal.file.archive.compression.GzipArchiver;
import org.gradle.api.internal.file.archive.compression.SimpleCompressor;
-import org.gradle.api.internal.file.copy.ArchiveCopyAction;
-import org.gradle.api.internal.file.copy.CopyActionImpl;
+import org.gradle.api.internal.file.copy.CopyAction;
-import java.io.File;
import java.util.concurrent.Callable;
/**
* Assembles a TAR archive.
- *
- * @author Hans Dockter
*/
public class Tar extends AbstractArchiveTask {
- private final CopyActionImpl action;
private Compression compression = Compression.NONE;
public Tar() {
- action = new TarCopyActionImpl(getServices().get(FileResolver.class));
getConventionMapping().map("extension", new Callable<Object>(){
public Object call() throws Exception {
return getCompression().getDefaultExtension();
@@ -46,10 +39,18 @@ public class Tar extends AbstractArchiveTask {
});
}
- protected CopyActionImpl getCopyAction() {
- return action;
+ @Override
+ protected CopyAction createCopyAction() {
+ return new TarCopyAction(getArchivePath(), getCompressor());
}
+ private ArchiveOutputStreamFactory getCompressor() {
+ switch(compression) {
+ case BZIP2: return Bzip2Archiver.getCompressor();
+ case GZIP: return GzipArchiver.getCompressor();
+ default: return new SimpleCompressor();
+ }
+ }
/**
* Returns the compression that is used for this archive.
*
@@ -68,21 +69,4 @@ public class Tar extends AbstractArchiveTask {
this.compression = compression;
}
- private class TarCopyActionImpl extends CopyActionImpl implements ArchiveCopyAction {
- public TarCopyActionImpl(FileResolver fileResolver) {
- super(fileResolver, new TarCopySpecVisitor());
- }
-
- public File getArchivePath() {
- return Tar.this.getArchivePath();
- }
-
- public ArchiveOutputStreamFactory getCompressor() {
- switch(compression) {
- case BZIP2: return Bzip2Archiver.getCompressor();
- case GZIP: return GzipArchiver.getCompressor();
- default: return new SimpleCompressor();
- }
- }
- }
}
\ No newline at end of file
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/tasks/bundling/Zip.java b/subprojects/core/src/main/groovy/org/gradle/api/tasks/bundling/Zip.java
index e7c515f..9b43610 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/tasks/bundling/Zip.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/tasks/bundling/Zip.java
@@ -15,31 +15,39 @@
*/
package org.gradle.api.tasks.bundling;
-import org.gradle.api.internal.file.FileResolver;
import org.gradle.api.internal.file.archive.ZipCopyAction;
-import org.gradle.api.internal.file.archive.ZipCopySpecVisitor;
-import org.gradle.api.internal.file.copy.CopyActionImpl;
-import org.gradle.api.internal.file.copy.ZipDeflatedCompressor;
+import org.gradle.api.internal.file.copy.CopyAction;
import org.gradle.api.internal.file.copy.ZipCompressor;
+import org.gradle.api.internal.file.copy.ZipDeflatedCompressor;
import org.gradle.api.internal.file.copy.ZipStoredCompressor;
-import java.io.File;
-
/**
* Assembles a ZIP archive.
*
* The default is to compress the contents of the zip.
- *
- * @author Hans Dockter
*/
public class Zip extends AbstractArchiveTask {
public static final String ZIP_EXTENSION = "zip";
- private final ZipCopyActionImpl action;
private ZipEntryCompression entryCompression = ZipEntryCompression.DEFLATED;
public Zip() {
setExtension(ZIP_EXTENSION);
- action = new ZipCopyActionImpl(getServices().get(FileResolver.class));
+ }
+
+ protected ZipCompressor getCompressor() {
+ switch(entryCompression) {
+ case DEFLATED:
+ return ZipDeflatedCompressor.INSTANCE;
+ case STORED:
+ return ZipStoredCompressor.INSTANCE;
+ default:
+ throw new IllegalArgumentException(String.format("Unknown Compression type %s", entryCompression));
+ }
+ }
+
+ @Override
+ protected CopyAction createCopyAction() {
+ return new ZipCopyAction(getArchivePath(), getCompressor());
}
/**
@@ -62,31 +70,12 @@ public class Zip extends AbstractArchiveTask {
this.entryCompression = entryCompression;
}
- protected ZipCopyActionImpl getCopyAction() {
- return action;
- }
-
/**
- * Zip compress action implementation.
+ * DO NOT REMOVE.
+ *
+ * Do not use - kept for binary compatibility.
*/
- protected class ZipCopyActionImpl extends CopyActionImpl implements ZipCopyAction {
- public ZipCopyActionImpl(FileResolver fileResolver) {
- super(fileResolver, new ZipCopySpecVisitor());
- }
-
- public File getArchivePath() {
- return Zip.this.getArchivePath();
- }
-
- public ZipCompressor getCompressor() {
- switch(entryCompression) {
- case DEFLATED:
- return ZipDeflatedCompressor.INSTANCE;
- case STORED:
- return ZipStoredCompressor.INSTANCE;
- default:
- throw new IllegalArgumentException(String.format("Unknown Compression type %s", entryCompression));
- }
- }
- }
+ @SuppressWarnings("UnusedDeclaration")
+ @Deprecated
+ protected class ZipCopyActionImpl {}
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/tasks/incremental/IncrementalTaskInputs.java b/subprojects/core/src/main/groovy/org/gradle/api/tasks/incremental/IncrementalTaskInputs.java
new file mode 100644
index 0000000..fc97522
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/tasks/incremental/IncrementalTaskInputs.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.tasks.incremental;
+
+import org.gradle.api.Action;
+import org.gradle.api.Incubating;
+import org.gradle.api.NonExtensible;
+
+/**
+ * Provides access to any input files that need to be processed by an incremental task.
+ * <p>
+ * An incremental task action is one that accepts a single {@link IncrementalTaskInputs} parameter.
+ * The task can then provide an action to execute for all input files that are out of date with respect to the previous execution of the task,
+ * and a separate action for all input files that have been removed since the previous execution.
+ *
+ * <pre autoTested="true">
+ * class IncrementalReverseTask extends DefaultTask {
+ * @InputDirectory
+ * def File inputDir
+ *
+ * @OutputDirectory
+ * def File outputDir
+ *
+ * @TaskAction
+ * void execute(IncrementalTaskInputs inputs) {
+ * inputs.outOfDate { change ->
+ * def targetFile = project.file("$outputDir/${change.file.name}")
+ * targetFile.text = change.file.text.reverse()
+ * }
+ *
+ * inputs.removed { change ->
+ * def targetFile = project.file("$outputDir/${change.file.name}")
+ * if (targetFile.exists()) {
+ * targetFile.delete()
+ * }
+ * }
+ * }
+ * }
+ * </pre>
+ *
+ * <p>
+ * In the case where Gradle is unable to determine which input files need to be reprocessed, then all of the input files will be reported as {@link #outOfDate}.
+ * Cases where this occurs include:
+ * <ul>
+ * <li>There is no history available from a previous execution.</li>
+ * <li>An {@link org.gradle.api.tasks.TaskOutputs#upToDateWhen(groovy.lang.Closure)} criteria added to the task returns <code>false</code>.</li>
+ * <li>An {@link org.gradle.api.tasks.Input} property has changed since the previous execution.</li>
+ * <li>One or more output files have changed since the previous execution.</li>
+ * </ul>
+ *
+ * Note that this is a stateful API:
+ * <ul>
+ * <li>{@link #outOfDate} and {@link #removed} can each only be executed a single time per {@link IncrementalTaskInputs} instance.</li>
+ * <li>{@link #outOfDate} must be executed before {@link #removed} is called.</li>
+ * </ul>
+ */
+ at Incubating
+ at NonExtensible
+public interface IncrementalTaskInputs {
+ /**
+ * Indicates if it was possible for Gradle to determine which exactly which input files were out of date compared to a previous execution.
+ * This is <em>not</em> possible in the case of no previous execution, changed Input Properties, Output Files, etc.
+ * <p>
+ * When <code>true</code>:
+ * <ul>
+ * <li>Any input file that has been added or modified since previous execution will be considered 'out-of-date' and reported to {@link #outOfDate}.</li>
+ * <li>Any input files that has been removed since previous execution will be reported to {@link #removed}.</li>
+ * </ul>
+ * </p>
+ * <p>
+ * When <code>false</code>:
+ * <ul>
+ * <li>Every input file will be considered to be 'out-of-date' and will be reported to {@link #outOfDate}.</li>
+ * <li>No input files will be reported to {@link #removed}.</li>
+ * </ul>
+ * </p>
+ */
+ boolean isIncremental();
+
+ /**
+ * Executes the action for all of the input files that are out-of-date since the previous task execution. The action may also be supplied as a {@link groovy.lang.Closure}.
+ * <ul>
+ * <li>When {@link #isIncremental()} == <code>true</code>, the action will be executed for any added or modified input file.</li>
+ * <li>When {@link #isIncremental()} == <code>false</code>, the action will be executed for every input file for the task.</li>
+ * </ul>
+ * <p>
+ * This method may only be called a single time for a single {@link IncrementalTaskInputs} instance.
+ * </p>
+ * @throws IllegalStateException on second and subsequent invocations.
+ */
+ void outOfDate(Action<? super InputFileDetails> outOfDateAction);
+
+ /**
+ * Executes the action for all of the input files that were removed since the previous task execution. The action may also be supplied as a {@link groovy.lang.Closure}.
+ * <ul>
+ * <li>When {@link #isIncremental()} == <code>true</code>, the action will be executed for any removed input file.</li>
+ * <li>When {@link #isIncremental()} == <code>false</code>, the action will not be executed.</li>
+ * </ul>
+ * <p>
+ * This method may only be called a single time for a single {@link IncrementalTaskInputs} instance.
+ * </p><p>
+ * This method may only be called after {@link #outOfDate} has been called.
+ * </p>
+ * @throws IllegalStateException if invoked prior to {@link #outOfDate}, or if invoked more than once.
+ */
+ void removed(Action<? super InputFileDetails> removedAction);
+
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/tasks/incremental/InputFileDetails.java b/subprojects/core/src/main/groovy/org/gradle/api/tasks/incremental/InputFileDetails.java
new file mode 100644
index 0000000..bb59cd3
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/tasks/incremental/InputFileDetails.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.tasks.incremental;
+
+import org.gradle.api.Incubating;
+
+import java.io.File;
+
+/**
+ * A change to an input file.
+ */
+ at Incubating
+public interface InputFileDetails {
+ /**
+ * Was the file added?
+ * @return true if the file was added since the last execution
+ */
+ boolean isAdded();
+
+ /**
+ * Was the file modified?
+ * @return if the file was modified
+ */
+ boolean isModified();
+
+ /**
+ * Was the file removed?
+ * @return true if the file was removed since the last execution
+ */
+ boolean isRemoved();
+
+ /**
+ * The input file, which may no longer exist.
+ * @return the input file
+ */
+ File getFile();
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/tasks/incremental/package-info.java b/subprojects/core/src/main/groovy/org/gradle/api/tasks/incremental/package-info.java
new file mode 100644
index 0000000..59d40ba
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/api/tasks/incremental/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+/**
+ * API classes for implementing incremental tasks.
+ */
+package org.gradle.api.tasks.incremental;
\ No newline at end of file
diff --git a/subprojects/core/src/main/groovy/org/gradle/api/tasks/util/PatternSet.java b/subprojects/core/src/main/groovy/org/gradle/api/tasks/util/PatternSet.java
index 5379eff..690ac50 100644
--- a/subprojects/core/src/main/groovy/org/gradle/api/tasks/util/PatternSet.java
+++ b/subprojects/core/src/main/groovy/org/gradle/api/tasks/util/PatternSet.java
@@ -25,6 +25,8 @@ import org.gradle.api.file.FileTreeElement;
import org.gradle.api.file.RelativePath;
import org.gradle.api.internal.file.RelativePathSpec;
import org.gradle.api.internal.file.pattern.PatternMatcherFactory;
+import org.gradle.api.internal.notations.NotationParserBuilder;
+import org.gradle.api.internal.notations.api.NotationParser;
import org.gradle.api.internal.notations.parsers.CharSequenceNotationParser;
import org.gradle.api.specs.*;
import org.gradle.api.tasks.AntBuilderAware;
@@ -162,7 +164,10 @@ public class PatternSet implements AntBuilderAware, PatternFilterable {
}
public PatternSet include(Iterable includes) {
- CharSequenceNotationParser parser = new CharSequenceNotationParser();
+ NotationParser<String> parser = new NotationParserBuilder<String>()
+ .resultingType(String.class)
+ .parser(new CharSequenceNotationParser())
+ .toComposite();
for (Object include : includes) {
this.includes.add(parser.parseNotation(include));
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/cache/CacheValidator.java b/subprojects/core/src/main/groovy/org/gradle/cache/CacheValidator.java
index af53db8..0f6c743 100644
--- a/subprojects/core/src/main/groovy/org/gradle/cache/CacheValidator.java
+++ b/subprojects/core/src/main/groovy/org/gradle/cache/CacheValidator.java
@@ -18,7 +18,7 @@ package org.gradle.cache;
/**
* CacheValidator interface can be used for specify a particular cache validation logic.
- * */
+ */
public interface CacheValidator {
boolean isValid();
diff --git a/subprojects/core/src/main/groovy/org/gradle/cache/internal/DefaultCacheAccess.java b/subprojects/core/src/main/groovy/org/gradle/cache/internal/DefaultCacheAccess.java
index 9ce31a2..8a8b99c 100644
--- a/subprojects/core/src/main/groovy/org/gradle/cache/internal/DefaultCacheAccess.java
+++ b/subprojects/core/src/main/groovy/org/gradle/cache/internal/DefaultCacheAccess.java
@@ -16,28 +16,33 @@
package org.gradle.cache.internal;
import net.jcip.annotations.ThreadSafe;
+import org.gradle.api.logging.Logger;
+import org.gradle.api.logging.Logging;
import org.gradle.cache.CacheAccess;
-import org.gradle.messaging.serialize.DefaultSerializer;
import org.gradle.cache.PersistentIndexedCache;
import org.gradle.cache.internal.btree.BTreePersistentIndexedCache;
+import org.gradle.cache.internal.cacheops.CacheAccessOperationsStack;
import org.gradle.internal.Factories;
import org.gradle.internal.Factory;
import org.gradle.internal.UncheckedException;
+import org.gradle.messaging.serialize.DefaultSerializer;
import org.gradle.messaging.serialize.Serializer;
import java.io.File;
-import java.util.ArrayList;
import java.util.HashSet;
-import java.util.List;
import java.util.Set;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import static org.gradle.cache.internal.FileLockManager.LockMode.Exclusive;
+import static org.gradle.cache.internal.FileLockManager.LockMode.Shared;
@ThreadSafe
public class DefaultCacheAccess implements CacheAccess {
+
+ private final static Logger LOG = Logging.getLogger(DefaultCacheAccess.class);
+
private final String cacheDiplayName;
private final File lockFile;
private final FileLockManager lockManager;
@@ -48,23 +53,24 @@ public class DefaultCacheAccess implements CacheAccess {
private Thread owner;
private FileLockManager.LockMode lockMode;
private FileLock fileLock;
- private final ThreadLocal<CacheOperationStack> operationStack = new ThreadLocal<CacheOperationStack>() {
- @Override
- protected CacheOperationStack initialValue() {
- return new CacheOperationStack();
- }
- };
+ private boolean contended;
+ private final CacheAccessOperationsStack operations;
+ private int cacheClosedCount;
public DefaultCacheAccess(String cacheDisplayName, File lockFile, FileLockManager lockManager) {
+ this(cacheDisplayName, lockFile, lockManager, new CacheAccessOperationsStack());
+ }
+
+ public DefaultCacheAccess(String cacheDisplayName, File lockFile, FileLockManager lockManager, CacheAccessOperationsStack operations) {
this.cacheDiplayName = cacheDisplayName;
this.lockFile = lockFile;
this.lockManager = lockManager;
+ this.operations = operations;
}
/**
- * Opens this cache access with the given lock mode. Calling this with {@link org.gradle.cache.internal.FileLockManager.LockMode#Exclusive} will
- * lock the cache for exclusive access from all other threads (including those in this process and all other processes), until
- * {@link #close()} is called.
+ * Opens this cache access with the given lock mode. Calling this with {@link org.gradle.cache.internal.FileLockManager.LockMode#Exclusive} will lock the cache for exclusive access from all other
+ * threads (including those in this process and all other processes), until {@link #close()} is called.
*/
public void open(FileLockManager.LockMode lockMode) {
lock.lock();
@@ -76,30 +82,43 @@ public class DefaultCacheAccess implements CacheAccess {
if (lockMode == FileLockManager.LockMode.None) {
return;
}
+ if (fileLock != null) {
+ throw new IllegalStateException("File lock " + lockFile + " is already open.");
+ }
fileLock = lockManager.lock(lockFile, lockMode, cacheDiplayName);
takeOwnership(String.format("Access %s", cacheDiplayName));
+ lockManager.allowContention(fileLock, whenContended());
} finally {
lock.unlock();
}
}
- public void close() {
- lock.lock();
+ private void closeFileLock() {
try {
+ cacheClosedCount++;
for (MultiProcessSafePersistentIndexedCache<?, ?> cache : caches) {
cache.close();
}
- operationStack.remove();
- lockMode = null;
- owner = null;
+ fileLock.close();
+ } finally {
+ fileLock = null;
+ contended = false;
+ }
+ }
+
+ public void close() {
+ lock.lock();
+ try {
+ operations.close();
if (fileLock != null) {
- try {
- fileLock.close();
- } finally {
- fileLock = null;
- }
+ closeFileLock();
+ }
+ if (cacheClosedCount != 1) {
+ LOG.debug("Cache {} was closed {} times.", cacheDiplayName, cacheClosedCount);
}
} finally {
+ lockMode = null;
+ owner = null;
lock.unlock();
}
}
@@ -118,17 +137,21 @@ public class DefaultCacheAccess implements CacheAccess {
}
takeOwnership(operationDisplayName);
+ boolean wasStarted = false;
try {
- boolean wasStarted = onStartWork();
+ wasStarted = onStartWork();
+ return factory.create();
+ } finally {
+ lock.lock();
try {
- return factory.create();
- } finally {
if (wasStarted) {
- onEndWork();
+ onEndWork(operationDisplayName);
+ } else {
+ releaseOwnership(operationDisplayName);
}
+ } finally {
+ lock.unlock();
}
- } finally {
- releaseOwnership(operationDisplayName);
}
}
@@ -143,7 +166,7 @@ public class DefaultCacheAccess implements CacheAccess {
}
}
owner = Thread.currentThread();
- operationStack.get().pushCacheAction(operationDisplayName);
+ operations.pushCacheAction(operationDisplayName);
} finally {
lock.unlock();
}
@@ -152,8 +175,8 @@ public class DefaultCacheAccess implements CacheAccess {
private void releaseOwnership(String operationDisplayName) {
lock.lock();
try {
- operationStack.get().popCacheAction(operationDisplayName);
- if (!operationStack.get().isInCacheAction()) {
+ operations.popCacheAction(operationDisplayName);
+ if (!operations.isInCacheAction()) {
owner = null;
condition.signalAll();
}
@@ -163,18 +186,30 @@ public class DefaultCacheAccess implements CacheAccess {
}
public <T> T longRunningOperation(String operationDisplayName, Factory<? extends T> action) {
- if (operationStack.get().isInLongRunningOperation()) {
- operationStack.get().pushLongRunningOperation(operationDisplayName);
+ boolean isReentrant;
+ lock.lock();
+ try {
+ isReentrant = operations.maybeReentrantLongRunningOperation(operationDisplayName);
+ } finally {
+ lock.unlock();
+ }
+ if (isReentrant) {
try {
return action.create();
} finally {
- operationStack.get().popLongRunningOperation(operationDisplayName);
+ popLongRunningOperation(operationDisplayName);
}
}
- checkThreadIsOwner();
- boolean wasEnded = onEndWork();
- parkOwner(operationDisplayName);
+ lock.lock();
+ boolean wasEnded;
+ try {
+ checkThreadIsOwner();
+ wasEnded = onEndWork();
+ parkOwner(operationDisplayName);
+ } finally {
+ lock.unlock();
+ }
try {
return action.create();
} finally {
@@ -185,6 +220,15 @@ public class DefaultCacheAccess implements CacheAccess {
}
}
+ private void popLongRunningOperation(String operationDisplayName) {
+ lock.lock();
+ try {
+ operations.popLongRunningOperation(operationDisplayName);
+ } finally {
+ lock.unlock();
+ }
+ }
+
private void checkThreadIsOwner() {
lock.lock();
try {
@@ -205,7 +249,7 @@ public class DefaultCacheAccess implements CacheAccess {
owner = null;
condition.signalAll();
- operationStack.get().pushLongRunningOperation(operationDisplayName);
+ operations.pushLongRunningOperation(operationDisplayName);
} finally {
lock.unlock();
}
@@ -222,7 +266,7 @@ public class DefaultCacheAccess implements CacheAccess {
}
}
owner = Thread.currentThread();
- operationStack.get().popLongRunningOperation(description);
+ popLongRunningOperation(description);
} finally {
lock.unlock();
}
@@ -251,7 +295,7 @@ public class DefaultCacheAccess implements CacheAccess {
try {
caches.add(indexedCache);
if (fileLock != null) {
- indexedCache.onStartWork(operationStack.get().getDescription());
+ indexedCache.onStartWork(operations.getDescription());
}
} finally {
lock.unlock();
@@ -267,11 +311,14 @@ public class DefaultCacheAccess implements CacheAccess {
if (fileLock != null) {
return false;
}
+ fileLock = lockManager.lock(lockFile, Exclusive, cacheDiplayName, operations.getDescription());
- fileLock = lockManager.lock(lockFile, Exclusive, cacheDiplayName, operationStack.get().getDescription());
for (MultiProcessSafePersistentIndexedCache<?, ?> cache : caches) {
- cache.onStartWork(operationStack.get().getDescription());
+ cache.onStartWork(operations.getDescription());
}
+
+ lockManager.allowContention(fileLock, whenContended());
+
return true;
}
@@ -279,23 +326,25 @@ public class DefaultCacheAccess implements CacheAccess {
if (fileLock == null) {
return false;
}
+ if (contended || fileLock.getMode() == Shared) {
+ closeFileLock();
+ }
+ return true;
+ }
+ private void onEndWork(String operationToRelease) {
try {
- for (MultiProcessSafePersistentIndexedCache<?, ?> cache : caches) {
- cache.onEndWork();
- }
- fileLock.close();
+ onEndWork();
} finally {
- fileLock = null;
+ releaseOwnership(operationToRelease);
}
- return true;
}
private FileLock getLock() {
lock.lock();
try {
- if (Thread.currentThread() != owner || fileLock == null) {
- throw new IllegalStateException(String.format("The %s has not been locked.", cacheDiplayName));
+ if ((Thread.currentThread() != owner && owner != null) || fileLock == null) {
+ throw new IllegalStateException(String.format("The %s has not been locked for this thread. File lock: %s, owner: %s", cacheDiplayName, fileLock != null, owner));
}
} finally {
lock.unlock();
@@ -317,61 +366,39 @@ public class DefaultCacheAccess implements CacheAccess {
}
}
- private class CacheOperationStack {
- private final List<CacheOperation> operations = new ArrayList<CacheOperation>();
-
- public String getDescription() {
- checkNotEmpty();
- return operations.get(0).description;
- }
-
- public boolean isInLongRunningOperation() {
- return !operations.isEmpty() && operations.get(0).longRunningOperation;
- }
-
- public void pushLongRunningOperation(String description) {
- operations.add(0, new CacheOperation(description, true));
- }
-
- public void popLongRunningOperation(String description) {
- pop(description, true);
- }
-
- public boolean isInCacheAction() {
- return !operations.isEmpty() && !operations.get(0).longRunningOperation;
- }
-
- public void pushCacheAction(String description) {
- operations.add(0, new CacheOperation(description, false));
- }
-
- public void popCacheAction(String description) {
- pop(description, false);
- }
-
- private CacheOperation pop(String description, boolean longRunningOperation) {
- checkNotEmpty();
- CacheOperation operation = operations.remove(0);
- if (operation.description.equals(description) && operation.longRunningOperation == longRunningOperation) {
- return operation;
- }
- throw new IllegalStateException();
- }
-
- private void checkNotEmpty() {
- if (operations.isEmpty()) {
- throw new IllegalStateException();
+ Runnable whenContended() {
+ return new Runnable() {
+ public void run() {
+ lock.lock();
+ try {
+ LOG.debug("Detected file lock contention of {} (fileLock={}, contended={}, owner={})", cacheDiplayName, fileLock != null, contended, owner);
+ if (fileLock == null) {
+ //the lock may have been closed
+ return;
+ }
+ if (owner != null) {
+ contended = true;
+ return;
+ }
+
+ takeOwnership("Other process requested access to " + cacheDiplayName);
+ try {
+ closeFileLock();
+ } finally {
+ releaseOwnership("Other process requested access to " + cacheDiplayName);
+ }
+ } finally {
+ lock.unlock();
+ }
}
- }
+ };
}
- private class CacheOperation {
- final String description;
- final boolean longRunningOperation;
+ Thread getOwner() {
+ return owner;
+ }
- private CacheOperation(String description, boolean longRunningOperation) {
- this.description = description;
- this.longRunningOperation = longRunningOperation;
- }
+ FileAccess getFileAccess() {
+ return fileAccess;
}
-}
+}
\ No newline at end of file
diff --git a/subprojects/core/src/main/groovy/org/gradle/cache/internal/DefaultFileLockManager.java b/subprojects/core/src/main/groovy/org/gradle/cache/internal/DefaultFileLockManager.java
index a328e8a..18fa3f6 100644
--- a/subprojects/core/src/main/groovy/org/gradle/cache/internal/DefaultFileLockManager.java
+++ b/subprojects/core/src/main/groovy/org/gradle/cache/internal/DefaultFileLockManager.java
@@ -15,11 +15,15 @@
*/
package org.gradle.cache.internal;
+import org.gradle.api.logging.Logger;
+import org.gradle.api.logging.Logging;
+import org.gradle.cache.internal.locklistener.FileLockContentionHandler;
+import org.gradle.internal.CompositeStoppable;
import org.gradle.internal.Factory;
-import org.gradle.internal.UncheckedException;
+import org.gradle.internal.Stoppable;
+import org.gradle.internal.id.IdGenerator;
+import org.gradle.internal.id.RandomLongIdGenerator;
import org.gradle.util.GFileUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import java.io.EOFException;
import java.io.File;
@@ -28,33 +32,46 @@ import java.io.RandomAccessFile;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
+import static org.gradle.internal.UncheckedException.throwAsUncheckedException;
+
/**
* Uses file system locks on a lock file per target file. Each lock file is made up of 2 regions:
*
- * <ul> <li>State region: 1 byte version field, 1 byte clean flag.</li> <li>Owner information region: 1 byte version field, utf-8 encoded owner process id, utf-8 encoded owner operation display
- * name.</li> </ul>
+ * <ul>
+ * <li>State region: 1 byte version field, 1 byte clean flag.</li>
+ * <li>Owner information region: 1 byte version field, bunch of other fields, see the code below for more info</li>
+ * </ul>
*/
public class DefaultFileLockManager implements FileLockManager {
- private static final Logger LOGGER = LoggerFactory.getLogger(DefaultFileLockManager.class);
+ private static final Logger LOGGER = Logging.getLogger(DefaultFileLockManager.class);
private static final int DEFAULT_LOCK_TIMEOUT = 60000;
private static final byte STATE_REGION_PROTOCOL = 1;
private static final int STATE_REGION_SIZE = 2;
private static final int STATE_REGION_POS = 0;
- private static final byte INFORMATION_REGION_PROTOCOL = 2;
+ private static final byte INFORMATION_REGION_PROTOCOL = 3;
private static final int INFORMATION_REGION_POS = STATE_REGION_POS + STATE_REGION_SIZE;
- public static final int INFORMATION_REGION_SIZE = 2048;
+ public static final int INFORMATION_REGION_SIZE = 2052;
public static final int INFORMATION_REGION_DESCR_CHUNK_LIMIT = 340;
private final Set<File> lockedFiles = new CopyOnWriteArraySet<File>();
private final ProcessMetaDataProvider metaDataProvider;
private final int lockTimeoutMs;
+ private final IdGenerator<Long> generator;
+ private FileLockContentionHandler fileLockContentionHandler;
+ private final long shortTimeoutMs = 10000;
+
+ public DefaultFileLockManager(ProcessMetaDataProvider metaDataProvider, FileLockContentionHandler fileLockContentionHandler) {
+ this(metaDataProvider, DEFAULT_LOCK_TIMEOUT, fileLockContentionHandler);
+ }
- public DefaultFileLockManager(ProcessMetaDataProvider metaDataProvider) {
- this(metaDataProvider, DEFAULT_LOCK_TIMEOUT);
+ public DefaultFileLockManager(ProcessMetaDataProvider metaDataProvider, int lockTimeoutMs, FileLockContentionHandler fileLockContentionHandler) {
+ this(metaDataProvider, lockTimeoutMs, fileLockContentionHandler, new RandomLongIdGenerator());
}
- public DefaultFileLockManager(ProcessMetaDataProvider metaDataProvider, int lockTimeoutMs) {
+ public DefaultFileLockManager(ProcessMetaDataProvider metaDataProvider, int lockTimeoutMs, FileLockContentionHandler fileLockContentionHandler, IdGenerator<Long> generator) {
this.metaDataProvider = metaDataProvider;
this.lockTimeoutMs = lockTimeoutMs;
+ this.fileLockContentionHandler = fileLockContentionHandler;
+ this.generator = generator;
}
public FileLock lock(File target, LockMode mode, String targetDisplayName) throws LockTimeoutException {
@@ -70,13 +87,25 @@ public class DefaultFileLockManager implements FileLockManager {
throw new IllegalStateException(String.format("Cannot lock %s as it has already been locked by this process.", targetDisplayName));
}
try {
- return new DefaultFileLock(canonicalTarget, mode, targetDisplayName, operationDisplayName);
+ int port = fileLockContentionHandler.reservePort();
+ return new DefaultFileLock(canonicalTarget, mode, targetDisplayName, operationDisplayName, port);
} catch (Throwable t) {
lockedFiles.remove(canonicalTarget);
- throw UncheckedException.throwAsUncheckedException(t);
+ throw throwAsUncheckedException(t);
}
}
+ public void allowContention(FileLock fileLock, Runnable whenContended) {
+ fileLockContentionHandler.start(fileLock.getLockId(), whenContended);
+ }
+
+ private class OwnerInfo {
+ int port;
+ long lockId;
+ String pid;
+ String operation;
+ }
+
private class DefaultFileLock extends AbstractFileAccess implements FileLock {
private final File lockFile;
private final File target;
@@ -86,8 +115,12 @@ public class DefaultFileLockManager implements FileLockManager {
private java.nio.channels.FileLock lock;
private RandomAccessFile lockFileAccess;
private boolean integrityViolated;
+ private int port;
+ private final long lockId;
- public DefaultFileLock(File target, LockMode mode, String displayName, String operationDisplayName) throws Throwable {
+ public DefaultFileLock(File target, LockMode mode, String displayName, String operationDisplayName, int port) throws Throwable {
+ this.port = port;
+ this.lockId = generator.generateId();
if (mode == LockMode.None) {
throw new UnsupportedOperationException("Locking mode None is not supported.");
}
@@ -133,7 +166,7 @@ public class DefaultFileLockManager implements FileLockManager {
// Process has crashed writing to lock file
return false;
} catch (Exception e) {
- throw UncheckedException.throwAsUncheckedException(e);
+ throw throwAsUncheckedException(e);
}
return true;
@@ -166,7 +199,7 @@ public class DefaultFileLockManager implements FileLockManager {
markClean();
integrityViolated = false;
} catch (Throwable t) {
- throw UncheckedException.throwAsUncheckedException(t);
+ throw throwAsUncheckedException(t);
}
}
@@ -198,65 +231,76 @@ public class DefaultFileLockManager implements FileLockManager {
}
public void close() {
- if (lockFileAccess == null) {
- return;
- }
- try {
- LOGGER.debug("Releasing lock on {}.", displayName);
- lockedFiles.remove(target);
- // Also releases any locks
- try {
- if (lock != null && !lock.isShared()) {
- // Discard information region
- lockFileAccess.setLength(INFORMATION_REGION_POS);
+ CompositeStoppable stoppable = new CompositeStoppable();
+ stoppable.add(new Stoppable() {
+ public void stop() {
+ try {
+ fileLockContentionHandler.stop(lockId);
+ } catch (Exception e) {
+ throw new RuntimeException("Unable to stop listening for file lock requests for " + displayName, e);
}
- } finally {
- lockFileAccess.close();
}
- } catch (IOException e) {
- LOGGER.warn("Error releasing lock on {}: {}", displayName, e);
- } finally {
- lock = null;
- lockFileAccess = null;
- }
+ });
+ stoppable.add(new Stoppable() {
+ public void stop() {
+ if (lockFileAccess == null) {
+ return;
+ }
+ try {
+ LOGGER.debug("Releasing lock on {}.", displayName);
+ try {
+ if (lock != null && !lock.isShared()) {
+ // Discard information region
+ java.nio.channels.FileLock info;
+ try {
+ info = lockInformationRegion(LockMode.Exclusive, System.currentTimeMillis() + shortTimeoutMs);
+ } catch (InterruptedException e) {
+ throw throwAsUncheckedException(e);
+ }
+ if (info != null) {
+ try {
+ lockFileAccess.setLength(INFORMATION_REGION_POS);
+ } finally {
+ info.release();
+ }
+ }
+ }
+ } finally {
+ lockFileAccess.close();
+ }
+ } catch (Exception e) {
+ throw new RuntimeException("Failed to release lock on " + displayName, e);
+ }
+ }
+ });
+ stoppable.add(new Stoppable() {
+ public void stop() {
+ lock = null;
+ lockFileAccess = null;
+ lockedFiles.remove(target);
+ }
+ });
+ stoppable.stop();
}
public LockMode getMode() {
return mode;
}
+ public long getLockId() {
+ return lockId;
+ }
+
private java.nio.channels.FileLock lock(FileLockManager.LockMode lockMode) throws Throwable {
LOGGER.debug("Waiting to acquire {} lock on {}.", lockMode.toString().toLowerCase(), displayName);
- long timeout = System.currentTimeMillis() + lockTimeoutMs;
+ long waitUntil = System.currentTimeMillis() + lockTimeoutMs;
// Lock the state region, with the requested mode
- java.nio.channels.FileLock stateRegionLock = lockStateRegion(lockMode, timeout);
+ java.nio.channels.FileLock stateRegionLock = lockStateRegion(lockMode, waitUntil);
if (stateRegionLock == null) {
- // Can't acquire lock, get details of owner to include in the error message
- String ownerPid = "unknown";
- String ownerOperation = "unknown";
- java.nio.channels.FileLock informationRegionLock = lockInformationRegion(LockMode.Shared, timeout);
- if (informationRegionLock == null) {
- LOGGER.debug("Could not lock information region for {}. Ignoring.", displayName);
- } else {
- try {
- if (lockFileAccess.length() <= INFORMATION_REGION_POS) {
- LOGGER.debug("Lock file for {} is too short to contain information region. Ignoring.", displayName);
- } else {
- lockFileAccess.seek(INFORMATION_REGION_POS);
- if (lockFileAccess.readByte() != INFORMATION_REGION_PROTOCOL) {
- throw new IllegalStateException(String.format("Unexpected lock protocol found in lock file '%s' for %s.", lockFile, displayName));
- }
- ownerPid = lockFileAccess.readUTF();
- ownerOperation = lockFileAccess.readUTF();
- }
- } finally {
- informationRegionLock.release();
- }
- }
-
+ OwnerInfo ownerInfo = readInformationRegion(System.currentTimeMillis() + shortTimeoutMs);
throw new LockTimeoutException(String.format("Timeout waiting to lock %s. It is currently in use by another Gradle instance.%nOwner PID: %s%nOur PID: %s%nOwner Operation: %s%nOur operation: %s%nLock file: %s",
- displayName, ownerPid, metaDataProvider.getProcessIdentifier(), ownerOperation, operationDisplayName, lockFile));
+ displayName, ownerInfo.pid, metaDataProvider.getProcessIdentifier(), ownerInfo.operation, operationDisplayName, lockFile));
}
try {
@@ -277,14 +321,16 @@ public class DefaultFileLockManager implements FileLockManager {
lockFileAccess.writeBoolean(false);
}
// Acquire an exclusive lock on the information region and write our details there
- java.nio.channels.FileLock informationRegionLock = lockInformationRegion(LockMode.Exclusive, timeout);
+ java.nio.channels.FileLock informationRegionLock = lockInformationRegion(LockMode.Exclusive, System.currentTimeMillis() + shortTimeoutMs);
if (informationRegionLock == null) {
- throw new IllegalStateException(String.format("Timeout waiting to lock the information region for lock %s", displayName));
+ throw new IllegalStateException(String.format("Unable to lock the information region for %s", displayName));
}
// check that the length of the reserved region is enough for storing our content
try {
lockFileAccess.seek(INFORMATION_REGION_POS);
lockFileAccess.writeByte(INFORMATION_REGION_PROTOCOL);
+ lockFileAccess.writeInt(port);
+ lockFileAccess.writeLong(lockId);
lockFileAccess.writeUTF(trimIfNecessary(metaDataProvider.getProcessIdentifier()));
lockFileAccess.writeUTF(trimIfNecessary(operationDisplayName));
lockFileAccess.setLength(lockFileAccess.getFilePointer());
@@ -301,31 +347,81 @@ public class DefaultFileLockManager implements FileLockManager {
return stateRegionLock;
}
+ private OwnerInfo readInformationRegion(long waitUntil) throws IOException, InterruptedException {
+ // Can't acquire lock, get details of owner to include in the error message
+ OwnerInfo out = new OwnerInfo();
+ out.pid = "unknown";
+ out.operation = "unknown";
+ out.port = -1;
+ java.nio.channels.FileLock informationRegionLock = lockInformationRegion(LockMode.Shared, waitUntil);
+ if (informationRegionLock == null) {
+ LOGGER.debug("Could not lock information region for {}. Ignoring.", displayName);
+ } else {
+ try {
+ if (lockFileAccess.length() <= INFORMATION_REGION_POS) {
+ LOGGER.debug("Lock file for {} is too short to contain information region. Ignoring.", displayName);
+ } else {
+ lockFileAccess.seek(INFORMATION_REGION_POS);
+ if (lockFileAccess.readByte() != INFORMATION_REGION_PROTOCOL) {
+ throw new IllegalStateException(String.format("Unexpected lock protocol found in lock file '%s' for %s.", lockFile, displayName));
+ }
+ out.port = lockFileAccess.readInt();
+ out.lockId = lockFileAccess.readLong();
+ out.pid = lockFileAccess.readUTF();
+ out.operation = lockFileAccess.readUTF();
+ LOGGER.debug("Read following information from the file lock info region. Port: {}, owner: {}, operation: {}", out.port, out.pid, out.operation);
+ }
+ } finally {
+ informationRegionLock.release();
+ }
+ }
+ return out;
+ }
+
private String trimIfNecessary(String inputString) {
if(inputString.length() > INFORMATION_REGION_DESCR_CHUNK_LIMIT){
return inputString.substring(0, INFORMATION_REGION_DESCR_CHUNK_LIMIT);
- }else{
+ } else {
return inputString;
}
}
- private java.nio.channels.FileLock lockStateRegion(LockMode lockMode, long timeout) throws IOException, InterruptedException {
- return lockRegion(lockMode, timeout, STATE_REGION_POS, STATE_REGION_SIZE);
- }
-
- private java.nio.channels.FileLock lockInformationRegion(LockMode lockMode, long timeout) throws IOException, InterruptedException {
- return lockRegion(lockMode, timeout, INFORMATION_REGION_POS, INFORMATION_REGION_SIZE - INFORMATION_REGION_POS);
+ private java.nio.channels.FileLock lockStateRegion(LockMode lockMode, final long waitUntil) throws IOException, InterruptedException {
+ do {
+ java.nio.channels.FileLock fileLock = lockRegion(lockMode, STATE_REGION_POS, STATE_REGION_SIZE);
+ if (fileLock != null) {
+ return fileLock;
+ }
+ if (port != -1) { //we don't like the assumption about the port very much
+ OwnerInfo ownerInfo = readInformationRegion(System.currentTimeMillis()); //no need for timeout here, as we're already looping with timeout
+ if (ownerInfo.port != -1) {
+ LOGGER.debug("The file lock is held by a different Gradle process (pid: {}, operation: {}). Will attempt to ping owner at port {}", ownerInfo.pid, ownerInfo.operation, ownerInfo.port);
+ fileLockContentionHandler.pingOwner(ownerInfo.port, ownerInfo.lockId, displayName);
+ } else {
+ LOGGER.debug("The file lock is held by a different Gradle process. I was unable to read on which port the owner listens for lock access requests.");
+ }
+ }
+ //TODO SF it would really nice to print some message to the user after say 2 seconds of waiting
+ //saying what gradle is doing, and why we're waiting.
+ Thread.sleep(200L);
+ } while (System.currentTimeMillis() < waitUntil);
+ return null;
}
- private java.nio.channels.FileLock lockRegion(FileLockManager.LockMode lockMode, long timeout, long start, long size) throws IOException, InterruptedException {
+ private java.nio.channels.FileLock lockInformationRegion(LockMode lockMode, long waitUntil) throws IOException, InterruptedException {
do {
- java.nio.channels.FileLock fileLock = lockFileAccess.getChannel().tryLock(start, size, lockMode == LockMode.Shared);
+ java.nio.channels.FileLock fileLock = lockRegion(lockMode, INFORMATION_REGION_POS, INFORMATION_REGION_SIZE - INFORMATION_REGION_POS);
if (fileLock != null) {
return fileLock;
}
Thread.sleep(200L);
- } while (System.currentTimeMillis() < timeout);
+ }
+ while (System.currentTimeMillis() < waitUntil);
return null;
}
+
+ private java.nio.channels.FileLock lockRegion(LockMode lockMode, long start, long size) throws IOException, InterruptedException {
+ return lockFileAccess.getChannel().tryLock(start, size, lockMode == LockMode.Shared);
+ }
}
}
\ No newline at end of file
diff --git a/subprojects/core/src/main/groovy/org/gradle/cache/internal/FileAccess.java b/subprojects/core/src/main/groovy/org/gradle/cache/internal/FileAccess.java
index 892941b..cbfb4e2 100644
--- a/subprojects/core/src/main/groovy/org/gradle/cache/internal/FileAccess.java
+++ b/subprojects/core/src/main/groovy/org/gradle/cache/internal/FileAccess.java
@@ -54,7 +54,7 @@ public interface FileAccess {
void updateFile(Runnable action) throws LockTimeoutException, FileIntegrityViolationException, InsufficientLockModeException;
/**
- * Runs the given action under an exclusive lock on the target file, without checking it's integrity. If the given action fails, the lock is marked as uncleanly unlocked.
+ * Runs the given action under an exclusive lock on the target file, without checking its integrity. If the given action fails, the lock is marked as uncleanly unlocked.
*
* <p>This method should be used when it is of no consequence if the target was not previously unlocked, e.g. the content is being replaced.
*
diff --git a/subprojects/core/src/main/groovy/org/gradle/cache/internal/FileLock.java b/subprojects/core/src/main/groovy/org/gradle/cache/internal/FileLock.java
index 04896e6..7345741 100644
--- a/subprojects/core/src/main/groovy/org/gradle/cache/internal/FileLock.java
+++ b/subprojects/core/src/main/groovy/org/gradle/cache/internal/FileLock.java
@@ -41,4 +41,9 @@ public interface FileLock extends Closeable, FileAccess {
* The actual mode of the lock. May be different to what was requested.
*/
FileLockManager.LockMode getMode();
+
+ /**
+ * @return unique id of this lock
+ */
+ long getLockId();
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/cache/internal/FileLockCommunicator.java b/subprojects/core/src/main/groovy/org/gradle/cache/internal/FileLockCommunicator.java
new file mode 100644
index 0000000..b78974d
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/cache/internal/FileLockCommunicator.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.cache.internal;
+
+import org.gradle.messaging.remote.internal.inet.InetAddressFactory;
+
+import java.io.*;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.SocketException;
+
+import static org.gradle.internal.UncheckedException.throwAsUncheckedException;
+
+public class FileLockCommunicator {
+ private final DatagramSocket socket;
+ private final InetAddressFactory addressFactory;
+ private boolean stopped;
+
+ public FileLockCommunicator(InetAddressFactory addressFactory) {
+ this.addressFactory = addressFactory;
+ try {
+ socket = new DatagramSocket();
+ } catch (SocketException e) {
+ throw throwAsUncheckedException(e);
+ }
+ }
+
+ public void pingOwner(int ownerPort, long lockId, String displayName) {
+ try {
+ byte[] bytesToSend = encode(lockId);
+ // Ping the owner via all available local addresses
+ for (InetAddress address : addressFactory.findLocalAddresses()) {
+ socket.send(new DatagramPacket(bytesToSend, bytesToSend.length, address, ownerPort));
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(String.format("Failed to ping owner of lock for %s (lock id: %s, port: %s)", displayName, lockId, ownerPort), e);
+ }
+ }
+
+ public long receive() throws GracefullyStoppedException {
+ try {
+ byte[] bytes = new byte[8];
+ DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
+ socket.receive(packet);
+ return decode(bytes);
+ } catch (IOException e) {
+ if (!stopped) {
+ throw new RuntimeException(e);
+ }
+ throw new GracefullyStoppedException();
+ }
+ }
+
+ public void stop() {
+ stopped = true;
+ socket.close();
+ }
+
+ private static byte[] encode(long lockId) throws IOException {
+ ByteArrayOutputStream packet = new ByteArrayOutputStream();
+ new DataOutputStream(packet).writeLong(lockId);
+ return packet.toByteArray();
+ }
+
+ private static long decode(byte[] bytes) throws IOException {
+ return new DataInputStream(new ByteArrayInputStream(bytes)).readLong();
+ }
+
+ public int getPort() {
+ return socket.getLocalPort();
+ }
+}
\ No newline at end of file
diff --git a/subprojects/core/src/main/groovy/org/gradle/cache/internal/FileLockManager.java b/subprojects/core/src/main/groovy/org/gradle/cache/internal/FileLockManager.java
index fab7db9..8d6738c 100644
--- a/subprojects/core/src/main/groovy/org/gradle/cache/internal/FileLockManager.java
+++ b/subprojects/core/src/main/groovy/org/gradle/cache/internal/FileLockManager.java
@@ -39,6 +39,15 @@ public interface FileLockManager {
*/
FileLock lock(File target, LockMode mode, String targetDisplayName, String operationDisplayName) throws LockTimeoutException;
+ /**
+ * Enables other processes to request access to the provided lock. Provided action runs when the lock access request is received
+ * (it means that the lock is contended).
+ *
+ * @param fileLock the lock
+ * @param whenContended will be called asynchronously by the thread that listens for cache access requests, when such request is received
+ */
+ void allowContention(FileLock fileLock, Runnable whenContended);
+
enum LockMode {
/**
* No synchronisation is done.
diff --git a/subprojects/core/src/main/groovy/org/gradle/cache/internal/GracefullyStoppedException.java b/subprojects/core/src/main/groovy/org/gradle/cache/internal/GracefullyStoppedException.java
new file mode 100644
index 0000000..35f2b19
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/cache/internal/GracefullyStoppedException.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.cache.internal;
+
+public class GracefullyStoppedException extends Exception {
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/cache/internal/MultiProcessSafePersistentIndexedCache.java b/subprojects/core/src/main/groovy/org/gradle/cache/internal/MultiProcessSafePersistentIndexedCache.java
index 8006d0e..8bfcd55 100644
--- a/subprojects/core/src/main/groovy/org/gradle/cache/internal/MultiProcessSafePersistentIndexedCache.java
+++ b/subprojects/core/src/main/groovy/org/gradle/cache/internal/MultiProcessSafePersistentIndexedCache.java
@@ -15,9 +15,9 @@
*/
package org.gradle.cache.internal;
-import org.gradle.internal.Factory;
import org.gradle.cache.PersistentIndexedCache;
import org.gradle.cache.internal.btree.BTreePersistentIndexedCache;
+import org.gradle.internal.Factory;
import java.io.Closeable;
diff --git a/subprojects/core/src/main/groovy/org/gradle/cache/internal/OnDemandFileAccess.java b/subprojects/core/src/main/groovy/org/gradle/cache/internal/OnDemandFileAccess.java
index 1e70c09..8f999f4 100644
--- a/subprojects/core/src/main/groovy/org/gradle/cache/internal/OnDemandFileAccess.java
+++ b/subprojects/core/src/main/groovy/org/gradle/cache/internal/OnDemandFileAccess.java
@@ -39,6 +39,10 @@ public class OnDemandFileAccess extends AbstractFileAccess {
}
}
+ private Runnable doNothing() {
+ return new Runnable() { public void run() {} };
+ }
+
public void updateFile(Runnable action) throws LockTimeoutException, FileIntegrityViolationException {
FileLock lock = manager.lock(targetFile, FileLockManager.LockMode.Exclusive, displayName);
try {
diff --git a/subprojects/core/src/main/groovy/org/gradle/cache/internal/SimpleStateCache.java b/subprojects/core/src/main/groovy/org/gradle/cache/internal/SimpleStateCache.java
index fcd415d..370b61e 100644
--- a/subprojects/core/src/main/groovy/org/gradle/cache/internal/SimpleStateCache.java
+++ b/subprojects/core/src/main/groovy/org/gradle/cache/internal/SimpleStateCache.java
@@ -19,6 +19,8 @@ package org.gradle.cache.internal;
import org.gradle.api.GradleException;
import org.gradle.internal.Factory;
import org.gradle.cache.PersistentStateCache;
+import org.gradle.messaging.serialize.InputStreamBackedDecoder;
+import org.gradle.messaging.serialize.OutputStreamBackedEncoder;
import org.gradle.messaging.serialize.Serializer;
import java.io.*;
@@ -62,11 +64,11 @@ public class SimpleStateCache<T> implements PersistentStateCache<T> {
private void serialize(T newValue) {
try {
- OutputStream outStr = new BufferedOutputStream(new FileOutputStream(cacheFile));
+ OutputStreamBackedEncoder encoder = new OutputStreamBackedEncoder(new BufferedOutputStream(new FileOutputStream(cacheFile)));
try {
- serializer.write(outStr, newValue);
+ serializer.write(encoder, newValue);
} finally {
- outStr.close();
+ encoder.close();
}
} catch (Exception e) {
throw new GradleException(String.format("Could not write cache value to '%s'.", cacheFile), e);
@@ -78,11 +80,11 @@ public class SimpleStateCache<T> implements PersistentStateCache<T> {
return null;
}
try {
- InputStream inStr = new BufferedInputStream(new FileInputStream(cacheFile));
+ InputStreamBackedDecoder decoder = new InputStreamBackedDecoder(new BufferedInputStream(new FileInputStream(cacheFile)));
try {
- return serializer.read(inStr);
+ return serializer.read(decoder);
} finally {
- inStr.close();
+ decoder.close();
}
} catch (Exception e) {
throw new GradleException(String.format("Could not read cache value from '%s'.", cacheFile), e);
diff --git a/subprojects/core/src/main/groovy/org/gradle/cache/internal/btree/BTreePersistentIndexedCache.java b/subprojects/core/src/main/groovy/org/gradle/cache/internal/btree/BTreePersistentIndexedCache.java
index 061f283..f84dc47 100644
--- a/subprojects/core/src/main/groovy/org/gradle/cache/internal/btree/BTreePersistentIndexedCache.java
+++ b/subprojects/core/src/main/groovy/org/gradle/cache/internal/btree/BTreePersistentIndexedCache.java
@@ -17,6 +17,8 @@ package org.gradle.cache.internal.btree;
import org.gradle.api.UncheckedIOException;
import org.gradle.cache.PersistentIndexedCache;
+import org.gradle.messaging.serialize.InputStreamBackedDecoder;
+import org.gradle.messaging.serialize.OutputStreamBackedEncoder;
import org.gradle.messaging.serialize.Serializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -131,7 +133,9 @@ public class BTreePersistentIndexedCache<K, V> implements PersistentIndexedCache
public void put(K key, V value) {
try {
MessageDigestStream digestStream = new MessageDigestStream();
- keySerializer.write(digestStream, key);
+ OutputStreamBackedEncoder encoder = new OutputStreamBackedEncoder(digestStream);
+ keySerializer.write(encoder, key);
+ encoder.flush();
long hashCode = digestStream.getChecksum();
Lookup lookup = header.getRoot().find(hashCode);
boolean needNewBlock = true;
@@ -447,7 +451,9 @@ public class BTreePersistentIndexedCache<K, V> implements PersistentIndexedCache
public Lookup find(K key) throws Exception {
MessageDigestStream digestStream = new MessageDigestStream();
- keySerializer.write(digestStream, key);
+ OutputStreamBackedEncoder encoder = new OutputStreamBackedEncoder(digestStream);
+ keySerializer.write(encoder, key);
+ encoder.flush();
long checksum = digestStream.getChecksum();
return find(checksum);
}
@@ -645,13 +651,15 @@ public class BTreePersistentIndexedCache<K, V> implements PersistentIndexedCache
public void setValue(V value) throws Exception {
ByteArrayOutputStream outStr = new ByteArrayOutputStream();
- serializer.write(outStr, value);
+ OutputStreamBackedEncoder encoder = new OutputStreamBackedEncoder(outStr);
+ serializer.write(encoder, value);
+ encoder.flush();
this.serialisedValue = outStr.toByteArray();
}
public V getValue() throws Exception {
if (value == null) {
- value = serializer.read(new ByteArrayInputStream(serialisedValue));
+ value = serializer.read(new InputStreamBackedDecoder(new ByteArrayInputStream(serialisedValue)));
}
return value;
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/cache/internal/cacheops/CacheAccessOperationsStack.java b/subprojects/core/src/main/groovy/org/gradle/cache/internal/cacheops/CacheAccessOperationsStack.java
new file mode 100644
index 0000000..938e3c4
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/cache/internal/cacheops/CacheAccessOperationsStack.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.cache.internal.cacheops;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static java.lang.Thread.currentThread;
+
+public class CacheAccessOperationsStack {
+
+ private final Map<Thread, CacheOperationStack> perThreadStacks = new HashMap<Thread, CacheOperationStack>();
+
+ public void close() {
+ perThreadStacks.remove(currentThread());
+ }
+
+ public void pushCacheAction(String operationDisplayName) {
+ if (perThreadStacks.containsKey(currentThread())) {
+ getCurrentStack().pushCacheAction(operationDisplayName);
+ } else {
+ perThreadStacks.put(currentThread(), new CacheOperationStack().pushCacheAction(operationDisplayName));
+ }
+ }
+
+ public void popCacheAction(String operationDisplayName) {
+ getCurrentStack().popCacheAction(operationDisplayName);
+ }
+
+ public boolean isInCacheAction() {
+ return perThreadStacks.containsKey(currentThread()) && getCurrentStack().isInCacheAction();
+ }
+
+ public void pushLongRunningOperation(String operationDisplayName) {
+ if (perThreadStacks.containsKey(currentThread())) {
+ getCurrentStack().pushLongRunningOperation(operationDisplayName);
+ } else {
+ perThreadStacks.put(currentThread(), new CacheOperationStack().pushLongRunningOperation(operationDisplayName));
+ }
+ }
+
+ public void popLongRunningOperation(String operationDisplayName) {
+ getCurrentStack().popLongRunningOperation(operationDisplayName);
+ }
+
+ public String getDescription() {
+ return getCurrentStack().getDescription();
+ }
+
+ private CacheOperationStack getCurrentStack() {
+ if (!perThreadStacks.containsKey(currentThread())) {
+ throw new IllegalStateException("operations stack not ready. Was push action invoked?");
+ }
+ return perThreadStacks.get(currentThread());
+ }
+
+ public boolean maybeReentrantLongRunningOperation(String operationDisplayName) {
+ boolean atLeastOneLongRunning = false;
+ for (Thread thread : perThreadStacks.keySet()) {
+ if(perThreadStacks.get(thread).isInCacheAction()) {
+ //if any operation is in cache it means we're in cache operation and it isn't a reentrant long running operation
+ return false;
+ }
+ if (perThreadStacks.get(thread).isInLongRunningOperation()) {
+ atLeastOneLongRunning = true;
+ }
+ }
+
+ if (atLeastOneLongRunning) {
+ pushLongRunningOperation(operationDisplayName);
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/subprojects/core/src/main/groovy/org/gradle/cache/internal/cacheops/CacheOperation.java b/subprojects/core/src/main/groovy/org/gradle/cache/internal/cacheops/CacheOperation.java
new file mode 100644
index 0000000..4df99a9
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/cache/internal/cacheops/CacheOperation.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.cache.internal.cacheops;
+
+class CacheOperation {
+ final String description;
+ final boolean longRunningOperation;
+
+ CacheOperation(String description, boolean longRunningOperation) {
+ this.description = description;
+ this.longRunningOperation = longRunningOperation;
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/cache/internal/cacheops/CacheOperationStack.java b/subprojects/core/src/main/groovy/org/gradle/cache/internal/cacheops/CacheOperationStack.java
new file mode 100644
index 0000000..52f5522
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/cache/internal/cacheops/CacheOperationStack.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.cache.internal.cacheops;
+
+import java.util.ArrayList;
+import java.util.List;
+
+class CacheOperationStack {
+ private final List<CacheOperation> operations = new ArrayList<CacheOperation>();
+
+ public String getDescription() {
+ checkNotEmpty();
+ return operations.get(0).description;
+ }
+
+ public CacheOperationStack pushLongRunningOperation(String description) {
+ operations.add(0, new CacheOperation(description, true));
+ return this;
+ }
+
+ public void popLongRunningOperation(String description) {
+ pop(description, true);
+ }
+
+ public boolean isInCacheAction() {
+ return !operations.isEmpty() && !operations.get(0).longRunningOperation;
+ }
+
+ public boolean isInLongRunningOperation() {
+ return !operations.isEmpty() && !isInCacheAction();
+ }
+
+ public CacheOperationStack pushCacheAction(String description) {
+ operations.add(0, new CacheOperation(description, false));
+ return this;
+ }
+
+ public void popCacheAction(String description) {
+ pop(description, false);
+ }
+
+ private CacheOperation pop(String description, boolean longRunningOperation) {
+ checkNotEmpty();
+ CacheOperation operation = operations.remove(0);
+ if (operation.description.equals(description) && operation.longRunningOperation == longRunningOperation) {
+ return operation;
+ }
+ throw new IllegalStateException("Cannot pop operation '" + description + "'. It is not at the top of the stack");
+ }
+
+ private void checkNotEmpty() {
+ if (operations.isEmpty()) {
+ throw new IllegalStateException();
+ }
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/cache/internal/locklistener/DefaultFileLockContentionHandler.java b/subprojects/core/src/main/groovy/org/gradle/cache/internal/locklistener/DefaultFileLockContentionHandler.java
new file mode 100644
index 0000000..89e3b7f
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/cache/internal/locklistener/DefaultFileLockContentionHandler.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.cache.internal.locklistener;
+
+import org.gradle.api.logging.Logger;
+import org.gradle.api.logging.Logging;
+import org.gradle.cache.internal.FileLockCommunicator;
+import org.gradle.cache.internal.GracefullyStoppedException;
+import org.gradle.internal.concurrent.ExecutorFactory;
+import org.gradle.internal.concurrent.StoppableExecutor;
+import org.gradle.messaging.remote.internal.inet.InetAddressFactory;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+public class DefaultFileLockContentionHandler implements FileLockContentionHandler {
+ private static final Logger LOGGER = Logging.getLogger(DefaultFileLockContentionHandler.class);
+ private final Lock lock = new ReentrantLock();
+ private final Map<Long, Runnable> contendedActions = new HashMap<Long, Runnable>();
+ private final ExecutorFactory executorFactory;
+ private final InetAddressFactory addressFactory;
+
+ private FileLockCommunicator communicator;
+ private StoppableExecutor executor;
+ private boolean stopped;
+
+ public DefaultFileLockContentionHandler(ExecutorFactory executorFactory, InetAddressFactory addressFactory) {
+ this.executorFactory = executorFactory;
+ this.addressFactory = addressFactory;
+ }
+
+ private Runnable listener() {
+ return new Runnable() {
+ public void run() {
+ try {
+ LOGGER.info("Starting file lock listener thread.");
+ doRun();
+ } catch (Throwable t) {
+ //Logging exception here is only needed because by default Gradle does not show the stack trace
+ LOGGER.error("Problems handling incoming cache access requests.", t);
+ } finally {
+ LOGGER.info("File lock listener thread completed.");
+ }
+ }
+
+ private void doRun() {
+ while (true) {
+ long lockId;
+ try {
+ lockId = communicator.receive();
+ } catch (GracefullyStoppedException e) {
+ return;
+ }
+ lock.lock();
+ Runnable action;
+ try {
+ action = contendedActions.get(lockId);
+ if (action == null) {
+ //received access request for lock that is already closed
+ continue;
+ }
+ } finally {
+ lock.unlock();
+ }
+ action.run();
+ }
+ }
+ };
+ }
+
+ public void start(long lockId, Runnable whenContended) {
+ lock.lock();
+ try {
+ assertNotStopped();
+ if (communicator == null) {
+ throw new IllegalStateException("Must initialize the handler by reserving the port first.");
+ }
+ if (executor == null) {
+ executor = executorFactory.create("File lock request listener");
+ executor.execute(listener());
+ }
+ contendedActions.put(lockId, whenContended);
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public void pingOwner(int port, long lockId, String displayName) {
+ getCommunicator().pingOwner(port, lockId, displayName);
+ }
+
+ private void assertNotStopped() {
+ if (stopped) {
+ throw new IllegalStateException(
+ "Cannot start managing file contention because this handler has been closed.");
+ }
+ }
+
+ public void stop(long lockId) {
+ lock.lock();
+ try {
+ contendedActions.remove(lockId);
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public void stop() {
+ //Down the road this method should be used to clean up,
+ //when the Gradle process is about to complete (not gradle build).
+ //Ideally in future, this is happens during the clean-up/stopping of the global services
+ // (at the moment we never stop the global services)
+ lock.lock();
+ try {
+ stopped = true;
+ contendedActions.clear();
+ if (communicator != null) {
+ communicator.stop();
+ }
+ } finally {
+ lock.unlock();
+ }
+ if (executor != null) {
+ executor.stop();
+ }
+ }
+
+ public int reservePort() {
+ return getCommunicator().getPort();
+ }
+
+ private FileLockCommunicator getCommunicator() {
+ lock.lock();
+ try {
+ assertNotStopped();
+ if (communicator == null) {
+ communicator = new FileLockCommunicator(addressFactory);
+ }
+ return communicator;
+ } finally {
+ lock.unlock();
+ }
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/cache/internal/locklistener/FileLockContentionHandler.java b/subprojects/core/src/main/groovy/org/gradle/cache/internal/locklistener/FileLockContentionHandler.java
new file mode 100644
index 0000000..28a37a0
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/cache/internal/locklistener/FileLockContentionHandler.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.cache.internal.locklistener;
+
+public interface FileLockContentionHandler {
+ void start(long lockId, Runnable whenContended);
+
+ void stop(long lockId);
+
+ int reservePort();
+
+ void pingOwner(int port, long lockId, String displayName);
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/cache/internal/locklistener/NoOpFileLockContentionHandler.java b/subprojects/core/src/main/groovy/org/gradle/cache/internal/locklistener/NoOpFileLockContentionHandler.java
new file mode 100644
index 0000000..8d81bb7
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/cache/internal/locklistener/NoOpFileLockContentionHandler.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.cache.internal.locklistener;
+
+public class NoOpFileLockContentionHandler implements FileLockContentionHandler {
+
+ public void start(long lockId, Runnable whenContended) {}
+
+ public void stop(long lockId) {}
+
+ public int reservePort() {
+ return -1;
+ }
+
+ public void pingOwner(int port, long lockId, String displayName) {
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/configuration/BuildScriptProcessor.java b/subprojects/core/src/main/groovy/org/gradle/configuration/BuildScriptProcessor.java
deleted file mode 100644
index 9d7ffcc..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/configuration/BuildScriptProcessor.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.configuration;
-
-import org.gradle.api.internal.project.ProjectInternal;
-import org.gradle.api.internal.project.ProjectStateInternal;
-import org.gradle.util.Clock;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class BuildScriptProcessor implements ProjectEvaluator {
- private static final Logger LOGGER = LoggerFactory.getLogger(BuildScriptProcessor.class);
- private final ScriptPluginFactory configurerFactory;
-
- public BuildScriptProcessor(ScriptPluginFactory configurerFactory) {
- this.configurerFactory = configurerFactory;
- }
-
- public void evaluate(ProjectInternal project, ProjectStateInternal state) {
- LOGGER.info(String.format("Evaluating %s using %s.", project, project.getBuildScriptSource().getDisplayName()));
- Clock clock = new Clock();
-
- try {
- ScriptPlugin configurer = configurerFactory.create(project.getBuildScriptSource());
- configurer.apply(project);
- } catch (Exception e) {
- state.executed(e);
- }
-
- LOGGER.debug("Timing: Running the build script took " + clock.getTime());
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/configuration/DefaultBuildConfigurer.java b/subprojects/core/src/main/groovy/org/gradle/configuration/DefaultBuildConfigurer.java
index a6e02fa..d14c7eb 100644
--- a/subprojects/core/src/main/groovy/org/gradle/configuration/DefaultBuildConfigurer.java
+++ b/subprojects/core/src/main/groovy/org/gradle/configuration/DefaultBuildConfigurer.java
@@ -15,27 +15,31 @@
*/
package org.gradle.configuration;
-import org.gradle.api.Action;
+import org.gradle.StartParameter;
+import org.gradle.api.Project;
import org.gradle.api.internal.GradleInternal;
import org.gradle.api.internal.project.ProjectInternal;
import org.gradle.util.SingleMessageLogger;
public class DefaultBuildConfigurer implements BuildConfigurer {
-
public void configure(GradleInternal gradle) {
- gradle.addProjectEvaluationListener(new ImplicitTasksConfigurer());
- gradle.addProjectEvaluationListener(new ProjectDependencies2TaskResolver());
+ maybeInformAboutIncubatingMode(gradle.getStartParameter());
if (gradle.getStartParameter().isConfigureOnDemand()) {
- SingleMessageLogger.informAboutIncubating("Configuration on demand");
gradle.getRootProject().evaluate();
} else {
- gradle.getRootProject().allprojects((Action) new ConfigureProject());
+ for (Project project : gradle.getRootProject().getAllprojects()) {
+ ((ProjectInternal) project).evaluate();
+ }
}
}
- static class ConfigureProject implements Action<ProjectInternal> {
- public void execute(ProjectInternal projectInternal) {
- projectInternal.evaluate();
+ private void maybeInformAboutIncubatingMode(StartParameter startParameter) {
+ if (startParameter.getParallelThreadCount() != 0 && startParameter.isConfigureOnDemand()) {
+ SingleMessageLogger.incubatingFeatureUsed("Parallel execution with configuration on demand");
+ } else if (startParameter.getParallelThreadCount() != 0) {
+ SingleMessageLogger.incubatingFeatureUsed("Parallel execution");
+ } else if (startParameter.isConfigureOnDemand()) {
+ SingleMessageLogger.incubatingFeatureUsed("Configuration on demand");
}
}
}
\ No newline at end of file
diff --git a/subprojects/core/src/main/groovy/org/gradle/configuration/DefaultScriptPluginFactory.java b/subprojects/core/src/main/groovy/org/gradle/configuration/DefaultScriptPluginFactory.java
index 8ee6e7c..4acd25b 100755
--- a/subprojects/core/src/main/groovy/org/gradle/configuration/DefaultScriptPluginFactory.java
+++ b/subprojects/core/src/main/groovy/org/gradle/configuration/DefaultScriptPluginFactory.java
@@ -16,14 +16,15 @@
package org.gradle.configuration;
-import org.gradle.internal.Factory;
-import org.gradle.internal.service.DefaultServiceRegistry;
-import org.gradle.groovy.scripts.internal.BuildScriptClasspathScriptTransformer;
-import org.gradle.groovy.scripts.internal.BuildScriptTransformer;
import org.gradle.api.internal.initialization.ScriptClassLoaderProvider;
import org.gradle.api.internal.initialization.ScriptHandlerFactory;
import org.gradle.api.internal.initialization.ScriptHandlerInternal;
import org.gradle.groovy.scripts.*;
+import org.gradle.groovy.scripts.internal.BuildScriptClasspathScriptTransformer;
+import org.gradle.groovy.scripts.internal.BuildScriptTransformer;
+import org.gradle.internal.Factory;
+import org.gradle.internal.reflect.Instantiator;
+import org.gradle.internal.service.DefaultServiceRegistry;
import org.gradle.logging.LoggingManagerInternal;
public class DefaultScriptPluginFactory implements ScriptPluginFactory {
@@ -32,17 +33,20 @@ public class DefaultScriptPluginFactory implements ScriptPluginFactory {
private final ScriptHandlerFactory scriptHandlerFactory;
private final ClassLoader defaultClassLoader;
private final Factory<LoggingManagerInternal> loggingManagerFactory;
+ private final Instantiator instantiator;
public DefaultScriptPluginFactory(ScriptCompilerFactory scriptCompilerFactory,
- ImportsReader importsReader,
- ScriptHandlerFactory scriptHandlerFactory,
- ClassLoader defaultClassLoader,
- Factory<LoggingManagerInternal> loggingManagerFactory) {
+ ImportsReader importsReader,
+ ScriptHandlerFactory scriptHandlerFactory,
+ ClassLoader defaultClassLoader,
+ Factory<LoggingManagerInternal> loggingManagerFactory,
+ Instantiator instantiator) {
this.scriptCompilerFactory = scriptCompilerFactory;
this.importsReader = importsReader;
this.scriptHandlerFactory = scriptHandlerFactory;
this.defaultClassLoader = defaultClassLoader;
this.loggingManagerFactory = loggingManagerFactory;
+ this.instantiator = instantiator;
}
public ScriptPlugin create(ScriptSource scriptSource) {
@@ -88,6 +92,7 @@ public class DefaultScriptPluginFactory implements ScriptPluginFactory {
DefaultServiceRegistry services = new DefaultServiceRegistry();
services.add(ScriptPluginFactory.class, DefaultScriptPluginFactory.this);
services.add(LoggingManagerInternal.class, loggingManagerFactory.create());
+ services.add(Instantiator.class, instantiator);
ScriptAware scriptAware = null;
if (target instanceof ScriptAware) {
diff --git a/subprojects/core/src/main/groovy/org/gradle/configuration/ImplicitTasksConfigurer.java b/subprojects/core/src/main/groovy/org/gradle/configuration/ImplicitTasksConfigurer.java
index cab2353..600d78f 100644
--- a/subprojects/core/src/main/groovy/org/gradle/configuration/ImplicitTasksConfigurer.java
+++ b/subprojects/core/src/main/groovy/org/gradle/configuration/ImplicitTasksConfigurer.java
@@ -15,12 +15,7 @@
*/
package org.gradle.configuration;
-import org.gradle.api.Project;
-import org.gradle.api.ProjectEvaluationListener;
-import org.gradle.api.ProjectState;
-
-//This one should go away once we complete the auto-apply plugins
-public class ImplicitTasksConfigurer implements ProjectEvaluationListener {
+public class ImplicitTasksConfigurer {
public static final String HELP_GROUP = "help";
public static final String HELP_TASK = "help";
public static final String PROJECTS_TASK = "projects";
@@ -28,10 +23,4 @@ public class ImplicitTasksConfigurer implements ProjectEvaluationListener {
public static final String PROPERTIES_TASK = "properties";
public static final String DEPENDENCIES_TASK = "dependencies";
public static final String DEPENDENCY_INSIGHT_TASK = "dependencyInsight";
-
- public void beforeEvaluate(Project project) {}
-
- public void afterEvaluate(Project project, ProjectState state) {
- project.getPlugins().apply("help-tasks");
- }
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/configuration/ImportsReader.java b/subprojects/core/src/main/groovy/org/gradle/configuration/ImportsReader.java
index 2ed96f4..b01f074 100644
--- a/subprojects/core/src/main/groovy/org/gradle/configuration/ImportsReader.java
+++ b/subprojects/core/src/main/groovy/org/gradle/configuration/ImportsReader.java
@@ -19,13 +19,10 @@ package org.gradle.configuration;
import org.gradle.groovy.scripts.ScriptSource;
import org.gradle.internal.UncheckedException;
-import java.net.URL;
-import java.io.InputStreamReader;
import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URL;
-/**
- * @author Hans Dockter
- */
public class ImportsReader {
private String importsText;
@@ -33,20 +30,23 @@ public class ImportsReader {
public String getImports() {
if (importsText == null) {
try {
- URL url = getClass().getResource("default-imports.txt");
+ URL url = getClass().getResource("/default-imports.txt");
InputStreamReader reader = new InputStreamReader(url.openStream(), "UTF8");
-
- int bufferSize = 2048; // at time of writing, the file was about 1k so this should cover in one read
- StringBuilder imports = new StringBuilder(bufferSize);
- char[] chars = new char[bufferSize];
-
- int numRead = reader.read(chars, 0, bufferSize);
- while (numRead != -1) {
- imports.append(chars, 0, numRead);
- numRead = reader.read(chars, 0, bufferSize);
+ try {
+ int bufferSize = 2048; // at time of writing, the file was about 1k so this should cover in one read
+ StringBuilder imports = new StringBuilder(bufferSize);
+ char[] chars = new char[bufferSize];
+
+ int numRead = reader.read(chars, 0, bufferSize);
+ while (numRead != -1) {
+ imports.append(chars, 0, numRead);
+ numRead = reader.read(chars, 0, bufferSize);
+ }
+
+ importsText = imports.toString();
+ } finally {
+ reader.close();
}
-
- importsText = imports.toString();
} catch (IOException e) {
throw UncheckedException.throwAsUncheckedException(e);
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/configuration/LifecycleProjectEvaluator.java b/subprojects/core/src/main/groovy/org/gradle/configuration/LifecycleProjectEvaluator.java
deleted file mode 100644
index 5d0ee20..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/configuration/LifecycleProjectEvaluator.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.configuration;
-
-import org.gradle.api.ProjectEvaluationListener;
-import org.gradle.api.internal.project.ProjectInternal;
-import org.gradle.api.internal.project.ProjectStateInternal;
-
-/**
- * Manages lifecycle concerns while delegating actual evaluation to another evaluator
- *
- * @see org.gradle.api.internal.project.TopLevelBuildServiceRegistry#createProjectEvaluator()
- */
-public class LifecycleProjectEvaluator implements ProjectEvaluator {
- private final ProjectEvaluator evaluator;
-
- public LifecycleProjectEvaluator(ProjectEvaluator evaluator) {
- this.evaluator = evaluator;
- }
-
- public void evaluate(ProjectInternal project, ProjectStateInternal state) {
- //TODO this is one of the places to look into thread safety when we implement parallel configuration
- if (state.getExecuted() || state.getExecuting()) {
- return;
- }
-
- ProjectEvaluationListener listener = project.getProjectEvaluationBroadcaster();
- listener.beforeEvaluate(project);
- state.setExecuting(true);
- try {
- evaluator.evaluate(project, state);
- } finally {
- state.setExecuting(false);
- state.executed();
- listener.afterEvaluate(project, state);
- }
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/configuration/ProjectDependencies2TaskResolver.java b/subprojects/core/src/main/groovy/org/gradle/configuration/ProjectDependencies2TaskResolver.java
deleted file mode 100644
index 9ab5cd5..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/configuration/ProjectDependencies2TaskResolver.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.configuration;
-
-import org.gradle.api.Project;
-import org.gradle.api.ProjectEvaluationListener;
-import org.gradle.api.ProjectState;
-import org.gradle.api.Task;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * @author Hans Dockter
- */
-public class ProjectDependencies2TaskResolver implements ProjectEvaluationListener {
- private static Logger logger = LoggerFactory.getLogger(ProjectDependencies2TaskResolver.class);
-
- public void beforeEvaluate(Project project) {}
-
- public void afterEvaluate(Project project, ProjectState state) {
- for (Project dependsOnProject : project.getDependsOnProjects()) {
- logger.debug("Checking task dependencies for project: {} dependsOn: {}", project, dependsOnProject);
- for (Task task : project.getTasks()) {
- String taskName = task.getName();
- Task dependentTask = dependsOnProject.getTasks().findByName(taskName);
- if (dependentTask != null) {
- logger.debug("Setting task dependencies for task: {}", taskName);
- task.dependsOn(dependentTask);
- }
- }
- }
- }
-}
\ No newline at end of file
diff --git a/subprojects/core/src/main/groovy/org/gradle/configuration/ProjectEvaluator.java b/subprojects/core/src/main/groovy/org/gradle/configuration/ProjectEvaluator.java
deleted file mode 100644
index 677cc61..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/configuration/ProjectEvaluator.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.configuration;
-
-import org.gradle.api.internal.project.ProjectInternal;
-import org.gradle.api.internal.project.ProjectStateInternal;
-
-public interface ProjectEvaluator {
- void evaluate(ProjectInternal project, ProjectStateInternal state);
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/configuration/project/BuildScriptProcessor.java b/subprojects/core/src/main/groovy/org/gradle/configuration/project/BuildScriptProcessor.java
new file mode 100644
index 0000000..93b4cf2
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/configuration/project/BuildScriptProcessor.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.configuration.project;
+
+import org.gradle.api.internal.project.ProjectInternal;
+import org.gradle.configuration.ScriptPlugin;
+import org.gradle.configuration.ScriptPluginFactory;
+import org.gradle.util.Clock;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class BuildScriptProcessor implements ProjectConfigureAction {
+ private static final Logger LOGGER = LoggerFactory.getLogger(BuildScriptProcessor.class);
+ private final ScriptPluginFactory configurerFactory;
+
+ public BuildScriptProcessor(ScriptPluginFactory configurerFactory) {
+ this.configurerFactory = configurerFactory;
+ }
+
+ public void execute(ProjectInternal project) {
+ LOGGER.info(String.format("Evaluating %s using %s.", project, project.getBuildScriptSource().getDisplayName()));
+ Clock clock = new Clock();
+ try {
+ ScriptPlugin configurer = configurerFactory.create(project.getBuildScriptSource());
+ configurer.apply(project);
+ } finally {
+ LOGGER.debug("Timing: Running the build script took " + clock.getTime());
+ }
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/configuration/project/ConfigureActionsProjectEvaluator.java b/subprojects/core/src/main/groovy/org/gradle/configuration/project/ConfigureActionsProjectEvaluator.java
new file mode 100644
index 0000000..e4d4c3e
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/configuration/project/ConfigureActionsProjectEvaluator.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.configuration.project;
+
+import org.gradle.api.internal.project.ProjectInternal;
+import org.gradle.api.internal.project.ProjectStateInternal;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class ConfigureActionsProjectEvaluator implements ProjectEvaluator {
+ private final List<ProjectConfigureAction> configureActions;
+
+ public ConfigureActionsProjectEvaluator(ProjectConfigureAction... configureActions) {
+ this.configureActions = Arrays.asList(configureActions);
+ }
+
+ public void evaluate(ProjectInternal project, ProjectStateInternal state) {
+ for (ProjectConfigureAction configureAction : configureActions) {
+ configureAction.execute(project);
+ }
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/configuration/project/DefaultProjectConfigurationActionContainer.java b/subprojects/core/src/main/groovy/org/gradle/configuration/project/DefaultProjectConfigurationActionContainer.java
new file mode 100644
index 0000000..03e7879
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/configuration/project/DefaultProjectConfigurationActionContainer.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.configuration.project;
+
+import groovy.lang.Closure;
+import org.gradle.api.Action;
+import org.gradle.api.internal.ClosureBackedAction;
+import org.gradle.api.internal.project.ProjectInternal;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class DefaultProjectConfigurationActionContainer implements ProjectConfigurationActionContainer {
+ private final List<Action<? super ProjectInternal>> actions = new ArrayList<Action<? super ProjectInternal>>();
+
+ public void finished() {
+ actions.clear();
+ }
+
+ public List<Action<? super ProjectInternal>> getActions() {
+ return actions;
+ }
+
+ public void add(Action<? super ProjectInternal> action) {
+ actions.add(action);
+ }
+
+ public void add(Closure action) {
+ add(new ClosureBackedAction<ProjectInternal>(action));
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/configuration/project/DelayedConfigurationActions.java b/subprojects/core/src/main/groovy/org/gradle/configuration/project/DelayedConfigurationActions.java
new file mode 100644
index 0000000..9af016c
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/configuration/project/DelayedConfigurationActions.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.configuration.project;
+
+import org.gradle.api.Action;
+import org.gradle.api.internal.project.ProjectInternal;
+
+public class DelayedConfigurationActions implements ProjectConfigureAction {
+ public void execute(ProjectInternal projectInternal) {
+ ProjectConfigurationActionContainer actions = projectInternal.getConfigurationActions();
+ try {
+ for (Action<? super ProjectInternal> action : actions.getActions()) {
+ action.execute(projectInternal);
+ }
+ } finally {
+ actions.finished();
+ }
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/configuration/project/LifecycleProjectEvaluator.java b/subprojects/core/src/main/groovy/org/gradle/configuration/project/LifecycleProjectEvaluator.java
new file mode 100644
index 0000000..1a1547a
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/configuration/project/LifecycleProjectEvaluator.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.configuration.project;
+
+import org.gradle.api.ProjectConfigurationException;
+import org.gradle.api.ProjectEvaluationListener;
+import org.gradle.api.internal.project.ProjectInternal;
+import org.gradle.api.internal.project.ProjectStateInternal;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Manages lifecycle concerns while delegating actual evaluation to another evaluator
+ *
+ * @see org.gradle.internal.service.scopes.BuildScopeServices#createProjectEvaluator()
+ */
+public class LifecycleProjectEvaluator implements ProjectEvaluator {
+ private static final Logger LOGGER = LoggerFactory.getLogger(LifecycleProjectEvaluator.class);
+
+ private final ProjectEvaluator delegate;
+
+ public LifecycleProjectEvaluator(ProjectEvaluator delegate) {
+ this.delegate = delegate;
+ }
+
+ public void evaluate(ProjectInternal project, ProjectStateInternal state) {
+ //TODO this is one of the places to look into thread safety when we implement parallel configuration
+ if (state.getExecuted() || state.getExecuting()) {
+ return;
+ }
+
+ ProjectEvaluationListener listener = project.getProjectEvaluationBroadcaster();
+ try {
+ listener.beforeEvaluate(project);
+ } catch (Exception e) {
+ addConfigurationFailure(project, state, e);
+ return;
+ }
+
+ state.setExecuting(true);
+ try {
+ delegate.evaluate(project, state);
+ } catch (Exception e) {
+ addConfigurationFailure(project, state, e);
+ } finally {
+ state.setExecuting(false);
+ state.executed();
+ notifyAfterEvaluate(listener, project, state);
+ }
+ }
+
+ private void notifyAfterEvaluate(ProjectEvaluationListener listener, ProjectInternal project, ProjectStateInternal state) {
+ try {
+ listener.afterEvaluate(project, state);
+ } catch (Exception e) {
+ if (state.hasFailure()) {
+ // Just log this failure, and pass the existing failure out in the project state
+ LOGGER.error("Failed to notify ProjectEvaluationListener.afterEvaluate(), but primary configuration failure takes precedence.", e);
+ return;
+ }
+ addConfigurationFailure(project, state, e);
+ }
+ }
+
+ private void addConfigurationFailure(ProjectInternal project, ProjectStateInternal state, Exception e) {
+ ProjectConfigurationException failure = new ProjectConfigurationException(String.format("A problem occurred configuring %s.", project), e);
+ state.executed(failure);
+ }
+}
\ No newline at end of file
diff --git a/subprojects/core/src/main/groovy/org/gradle/configuration/project/PluginsProjectConfigureActions.java b/subprojects/core/src/main/groovy/org/gradle/configuration/project/PluginsProjectConfigureActions.java
new file mode 100644
index 0000000..834f60b
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/configuration/project/PluginsProjectConfigureActions.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.configuration.project;
+
+import org.gradle.api.internal.project.ProjectInternal;
+import org.gradle.internal.service.ServiceLocator;
+
+public class PluginsProjectConfigureActions implements ProjectConfigureAction {
+ private final ServiceLocator serviceLocator;
+
+ public PluginsProjectConfigureActions(ClassLoader pluginsClassLoader) {
+ this.serviceLocator = new ServiceLocator(pluginsClassLoader);
+ }
+
+ public void execute(ProjectInternal project) {
+ for (ProjectConfigureAction configureAction : serviceLocator.getAll(ProjectConfigureAction.class)) {
+ configureAction.execute(project);
+ }
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/configuration/project/ProjectConfigurationActionContainer.java b/subprojects/core/src/main/groovy/org/gradle/configuration/project/ProjectConfigurationActionContainer.java
new file mode 100644
index 0000000..1cbf77c
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/configuration/project/ProjectConfigurationActionContainer.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.configuration.project;
+
+import groovy.lang.Closure;
+import org.gradle.api.Action;
+import org.gradle.api.internal.project.ProjectInternal;
+
+/**
+ * A container responsible for managing the configuration of a project.
+ */
+public interface ProjectConfigurationActionContainer {
+ void finished();
+
+ Iterable<Action<? super ProjectInternal>> getActions();
+
+ /**
+ * Registers an action to execute to configure the project. Actions are executed in an arbitrary order.
+ */
+ void add(Action<? super ProjectInternal> action);
+
+ /**
+ * Registers an action to execute to configure the project. Actions are executed in an arbitrary order.
+ */
+ void add(Closure action);
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/configuration/project/ProjectConfigureAction.java b/subprojects/core/src/main/groovy/org/gradle/configuration/project/ProjectConfigureAction.java
new file mode 100644
index 0000000..416d1ce
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/configuration/project/ProjectConfigureAction.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.configuration.project;
+
+import org.gradle.api.Action;
+import org.gradle.api.internal.project.ProjectInternal;
+
+/**
+ * Can be implemented by plugins to auto-configure each project.
+ *
+ * <p>Implementations are discovered using the JAR service locator mechanism (see {@link org.gradle.internal.service.ServiceLocator}).
+ * Each action is invoked for each project that is to be configured, before the project has been configured. Actions are executed
+ * in an arbitrary order.
+ */
+public interface ProjectConfigureAction extends Action<ProjectInternal> {
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/configuration/project/ProjectDependencies2TaskResolver.java b/subprojects/core/src/main/groovy/org/gradle/configuration/project/ProjectDependencies2TaskResolver.java
new file mode 100644
index 0000000..688b698
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/configuration/project/ProjectDependencies2TaskResolver.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.configuration.project;
+
+import org.gradle.api.Project;
+import org.gradle.api.Task;
+import org.gradle.api.internal.project.ProjectInternal;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ProjectDependencies2TaskResolver implements ProjectConfigureAction {
+ private static Logger logger = LoggerFactory.getLogger(ProjectDependencies2TaskResolver.class);
+
+ public void execute(ProjectInternal project) {
+ for (Project dependsOnProject : project.getDependsOnProjects()) {
+ logger.debug("Checking task dependencies for project: {} dependsOn: {}", project, dependsOnProject);
+ for (Task task : project.getTasks()) {
+ String taskName = task.getName();
+ Task dependentTask = dependsOnProject.getTasks().findByName(taskName);
+ if (dependentTask != null) {
+ logger.debug("Setting task dependencies for task: {}", taskName);
+ task.dependsOn(dependentTask);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/subprojects/core/src/main/groovy/org/gradle/configuration/project/ProjectEvaluator.java b/subprojects/core/src/main/groovy/org/gradle/configuration/project/ProjectEvaluator.java
new file mode 100644
index 0000000..79c1c4a
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/configuration/project/ProjectEvaluator.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.configuration.project;
+
+import org.gradle.api.internal.project.ProjectInternal;
+import org.gradle.api.internal.project.ProjectStateInternal;
+
+public interface ProjectEvaluator {
+ void evaluate(ProjectInternal project, ProjectStateInternal state);
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/execution/ProjectEvaluatingAction.java b/subprojects/core/src/main/groovy/org/gradle/execution/ProjectEvaluatingAction.java
index d036dec..81b82e8 100644
--- a/subprojects/core/src/main/groovy/org/gradle/execution/ProjectEvaluatingAction.java
+++ b/subprojects/core/src/main/groovy/org/gradle/execution/ProjectEvaluatingAction.java
@@ -23,8 +23,6 @@ import java.util.List;
/**
* Ensures that projects resolved from the command line task names are evaluated.
- *
- * by Szczepan Faber, created at: 11/22/12
*/
public class ProjectEvaluatingAction implements BuildConfigurationAction {
diff --git a/subprojects/core/src/main/groovy/org/gradle/execution/TaskNameResolver.java b/subprojects/core/src/main/groovy/org/gradle/execution/TaskNameResolver.java
index 424ae41..30d5c37 100644
--- a/subprojects/core/src/main/groovy/org/gradle/execution/TaskNameResolver.java
+++ b/subprojects/core/src/main/groovy/org/gradle/execution/TaskNameResolver.java
@@ -20,54 +20,71 @@ import com.google.common.collect.SetMultimap;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.internal.project.ProjectInternal;
+import org.gradle.api.tasks.TaskContainer;
import java.util.Collections;
public class TaskNameResolver {
-
- public SetMultimap<String, Task> select(String name, Project project) {
+
+ public SetMultimap<String, TaskSelectionResult> select(String name, Project project) {
return select(name, (ProjectInternal) project, Collections.<Project>emptySet());
}
- public SetMultimap<String, Task> selectAll(String name, Project project) {
+ public SetMultimap<String, TaskSelectionResult> selectAll(String name, Project project) {
return select(name, (ProjectInternal) project, project.getSubprojects());
}
- private SetMultimap<String, Task> select(String name, ProjectInternal project, Iterable<Project> additionalProjects) {
- SetMultimap<String, Task> selected = LinkedHashMultimap.create();
+ private SetMultimap<String, TaskSelectionResult> select(String name, ProjectInternal project, Iterable<Project> additionalProjects) {
+ SetMultimap<String, TaskSelectionResult> selected = LinkedHashMultimap.create();
Task task = project.getTasks().findByName(name);
if (task != null) {
- selected.put(task.getName(), task);
+ selected.put(task.getName(), new LazyTaskSelectionResult(task.getName(), project.getTasks()));
} else {
task = project.getImplicitTasks().findByName(name);
if (task != null) {
- selected.put(task.getName(), task);
+ selected.put(task.getName(), new LazyTaskSelectionResult(task.getName(), project.getImplicitTasks()));
}
}
for (Project additionalProject : additionalProjects) {
task = additionalProject.getTasks().findByName(name);
if (task != null) {
- selected.put(task.getName(), task);
+ selected.put(task.getName(), new LazyTaskSelectionResult(task.getName(), additionalProject.getTasks()));
}
}
if (!selected.isEmpty()) {
return selected;
}
- for (Task t : project.getTasks()) {
- selected.put(t.getName(), t);
+ for (String taskName : project.getTasks().getNames()) {
+ selected.put(taskName, new LazyTaskSelectionResult(taskName, project.getTasks()));
}
- for (Task t : project.getImplicitTasks()) {
- if (!selected.containsKey(t.getName())) {
- selected.put(t.getName(), t);
+ for (String taskName : project.getImplicitTasks().getNames()) {
+ if (!selected.containsKey(taskName)) {
+ selected.put(taskName, new LazyTaskSelectionResult(taskName, project.getImplicitTasks()));
}
}
+
for (Project additionalProject : additionalProjects) {
- for (Task t : additionalProject.getTasks()) {
- selected.put(t.getName(), t);
+ for (String taskName : additionalProject.getTasks().getNames()) {
+ selected.put(taskName, new LazyTaskSelectionResult(taskName, additionalProject.getTasks()));
}
}
return selected;
}
+
+
+ public static class LazyTaskSelectionResult implements TaskSelectionResult {
+ private final TaskContainer taskContainer;
+ private final String taskName;
+
+ public LazyTaskSelectionResult(String taskName, TaskContainer tasksContainer) {
+ this.taskContainer = tasksContainer;
+ this.taskName = taskName;
+ }
+
+ public Task getTask() {
+ return taskContainer.getByName(taskName);
+ }
+ }
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/execution/TaskPathProjectEvaluator.java b/subprojects/core/src/main/groovy/org/gradle/execution/TaskPathProjectEvaluator.java
index 45139f3..d1bc839 100644
--- a/subprojects/core/src/main/groovy/org/gradle/execution/TaskPathProjectEvaluator.java
+++ b/subprojects/core/src/main/groovy/org/gradle/execution/TaskPathProjectEvaluator.java
@@ -21,9 +21,6 @@ import org.gradle.api.internal.project.ProjectInternal;
import org.gradle.execution.taskpath.ResolvedTaskPath;
import org.gradle.execution.taskpath.TaskPathResolver;
-/**
- * by Szczepan Faber, created at: 1/8/13
- */
public class TaskPathProjectEvaluator {
private final TaskPathResolver taskPathResolver;
diff --git a/subprojects/core/src/main/groovy/org/gradle/execution/TaskSelectionResult.java b/subprojects/core/src/main/groovy/org/gradle/execution/TaskSelectionResult.java
new file mode 100644
index 0000000..4946a48
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/execution/TaskSelectionResult.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.execution;
+
+import org.gradle.api.Task;
+
+public interface TaskSelectionResult {
+ Task getTask();
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/execution/TaskSelector.java b/subprojects/core/src/main/groovy/org/gradle/execution/TaskSelector.java
index 56a186b..28d8db0 100644
--- a/subprojects/core/src/main/groovy/org/gradle/execution/TaskSelector.java
+++ b/subprojects/core/src/main/groovy/org/gradle/execution/TaskSelector.java
@@ -17,12 +17,16 @@ package org.gradle.execution;
import com.google.common.collect.SetMultimap;
import org.gradle.api.Task;
+import org.gradle.api.Transformer;
import org.gradle.api.internal.GradleInternal;
import org.gradle.api.internal.project.ProjectInternal;
import org.gradle.execution.taskpath.ResolvedTaskPath;
import org.gradle.execution.taskpath.TaskPathResolver;
+import org.gradle.util.CollectionUtils;
import org.gradle.util.NameMatcher;
+import java.util.Collection;
+import java.util.HashSet;
import java.util.Set;
public class TaskSelector {
@@ -40,7 +44,7 @@ public class TaskSelector {
}
public TaskSelection getSelection(String path) {
- SetMultimap<String, Task> tasksByName;
+ SetMultimap<String, TaskSelectionResult> tasksByName;
ProjectInternal project = gradle.getDefaultProject();
ResolvedTaskPath taskPath = taskPathResolver.resolvePath(path, project);
@@ -50,7 +54,7 @@ public class TaskSelector {
tasksByName = taskNameResolver.selectAll(path, project);
}
- Set<Task> tasks = tasksByName.get(taskPath.getTaskName());
+ Set<TaskSelectionResult> tasks = tasksByName.get(taskPath.getTaskName());
if (!tasks.isEmpty()) {
// An exact match
return new TaskSelection(path, tasks);
@@ -58,9 +62,7 @@ public class TaskSelector {
NameMatcher matcher = new NameMatcher();
String actualName = matcher.find(taskPath.getTaskName(), tasksByName.keySet());
-
if (actualName != null) {
- // A partial match
return new TaskSelection(taskPath.getPrefix() + actualName, tasksByName.get(actualName));
}
@@ -69,11 +71,10 @@ public class TaskSelector {
public static class TaskSelection {
private String taskName;
- private Set<Task> tasks;
-
- public TaskSelection(String taskName, Set<Task> tasks) {
+ private Collection<TaskSelectionResult> taskSelectionResult;
+ public TaskSelection(String taskName, Set<TaskSelectionResult> tasks) {
this.taskName = taskName;
- this.tasks = tasks;
+ taskSelectionResult = tasks;
}
public String getTaskName() {
@@ -81,7 +82,11 @@ public class TaskSelector {
}
public Set<Task> getTasks() {
- return tasks;
+ return new HashSet<Task>(CollectionUtils.collect(taskSelectionResult, new Transformer<Task, TaskSelectionResult>() {
+ public Task transform(TaskSelectionResult original) {
+ return original.getTask();
+ }
+ }));
}
}
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/execution/commandline/CommandLineTaskConfigurer.java b/subprojects/core/src/main/groovy/org/gradle/execution/commandline/CommandLineTaskConfigurer.java
index e7139cb..a0fa0fd 100644
--- a/subprojects/core/src/main/groovy/org/gradle/execution/commandline/CommandLineTaskConfigurer.java
+++ b/subprojects/core/src/main/groovy/org/gradle/execution/commandline/CommandLineTaskConfigurer.java
@@ -23,6 +23,7 @@ import org.gradle.cli.CommandLineArgumentException;
import org.gradle.cli.CommandLineParser;
import org.gradle.cli.ParsedCommandLine;
import org.gradle.cli.ParsedCommandLineOption;
+import org.gradle.internal.reflect.JavaReflectionUtil;
import org.gradle.util.JavaMethod;
import java.lang.reflect.Method;
@@ -31,9 +32,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
-/**
- * by Szczepan Faber, created at: 9/5/12
- */
public class CommandLineTaskConfigurer {
public List<String> configureTasks(Collection<Task> tasks, List<String> arguments) {
@@ -59,7 +57,7 @@ public class CommandLineTaskConfigurer {
if (method.getParameterTypes().length > 0 && !hasSingleBooleanParameter(method)) {
option.hasArgument();
}
- options.put(optionName, JavaMethod.create(Object.class, Object.class, method));
+ options.put(optionName, JavaReflectionUtil.method(Object.class, Object.class, method));
}
}
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/execution/commandline/CommandLineTaskParser.java b/subprojects/core/src/main/groovy/org/gradle/execution/commandline/CommandLineTaskParser.java
index 291b5d7..dd181ca 100644
--- a/subprojects/core/src/main/groovy/org/gradle/execution/commandline/CommandLineTaskParser.java
+++ b/subprojects/core/src/main/groovy/org/gradle/execution/commandline/CommandLineTaskParser.java
@@ -26,9 +26,6 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Set;
-/**
- * by Szczepan Faber, created at: 10/8/12
- */
public class CommandLineTaskParser {
CommandLineTaskConfigurer taskConfigurer = new CommandLineTaskConfigurer();
diff --git a/subprojects/core/src/main/groovy/org/gradle/execution/taskgraph/AbstractTaskPlanExecutor.java b/subprojects/core/src/main/groovy/org/gradle/execution/taskgraph/AbstractTaskPlanExecutor.java
new file mode 100644
index 0000000..fbc86c3
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/execution/taskgraph/AbstractTaskPlanExecutor.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.execution.taskgraph;
+
+import org.gradle.api.execution.TaskExecutionListener;
+import org.gradle.api.internal.TaskInternal;
+import org.gradle.api.logging.Logger;
+import org.gradle.api.logging.Logging;
+
+import static org.gradle.util.Clock.prettyTime;
+
+abstract class AbstractTaskPlanExecutor implements TaskPlanExecutor {
+ private static final Logger LOGGER = Logging.getLogger(AbstractTaskPlanExecutor.class);
+ private final Object lock = new Object();
+
+ protected Runnable taskWorker(TaskExecutionPlan taskExecutionPlan, TaskExecutionListener taskListener) {
+ return new TaskExecutorWorker(taskExecutionPlan, taskListener);
+ }
+
+ private class TaskExecutorWorker implements Runnable {
+ private final TaskExecutionPlan taskExecutionPlan;
+ private final TaskExecutionListener taskListener;
+
+ private TaskExecutorWorker(TaskExecutionPlan taskExecutionPlan, TaskExecutionListener taskListener) {
+ this.taskExecutionPlan = taskExecutionPlan;
+ this.taskListener = taskListener;
+ }
+
+ public void run() {
+ long busy = 0;
+ long start = System.currentTimeMillis();
+ TaskInfo task;
+ while ((task = taskExecutionPlan.getTaskToExecute()) != null) {
+ final String taskPath = task.getTask().getPath();
+ LOGGER.info("{} ({}) started.", taskPath, Thread.currentThread());
+ long startTask = System.currentTimeMillis();
+ processTask(task);
+ long taskDuration = System.currentTimeMillis() - startTask;
+ busy += taskDuration;
+ LOGGER.info("{} ({}) completed. Took {}.", taskPath, Thread.currentThread(), prettyTime(taskDuration));
+ }
+ long total = System.currentTimeMillis() - start;
+ //TODO SF it would be nice to print one-line statement that concludes the utilisation of the worker threads
+ LOGGER.debug("Task worker [{}] finished, busy: {}, idle: {}", Thread.currentThread(), prettyTime(busy), prettyTime(total - busy));
+ }
+
+ protected void processTask(TaskInfo taskInfo) {
+ try {
+ executeTask(taskInfo);
+ } catch (Throwable e) {
+ taskInfo.setExecutionFailure(e);
+ } finally {
+ taskExecutionPlan.taskComplete(taskInfo);
+ }
+ }
+
+ // TODO:PARALLEL It would be good to move this logic into a TaskExecuter wrapper, but we'd need a way to give it a TaskExecutionListener that
+ // is wired to the various add/remove listener methods on TaskExecutionGraph
+ private void executeTask(TaskInfo taskInfo) {
+ TaskInternal task = taskInfo.getTask();
+ synchronized (lock) {
+ taskListener.beforeExecute(task);
+ }
+ try {
+ task.executeWithoutThrowingTaskFailure();
+ } finally {
+ synchronized (lock) {
+ taskListener.afterExecute(task, task.getState());
+ }
+ }
+ }
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/execution/taskgraph/DefaultTaskExecutionPlan.java b/subprojects/core/src/main/groovy/org/gradle/execution/taskgraph/DefaultTaskExecutionPlan.java
index 912c5da..cfbc7d4 100644
--- a/subprojects/core/src/main/groovy/org/gradle/execution/taskgraph/DefaultTaskExecutionPlan.java
+++ b/subprojects/core/src/main/groovy/org/gradle/execution/taskgraph/DefaultTaskExecutionPlan.java
@@ -18,6 +18,7 @@ package org.gradle.execution.taskgraph;
import org.gradle.api.CircularReferenceException;
import org.gradle.api.Task;
+import org.gradle.api.Transformer;
import org.gradle.api.internal.TaskInternal;
import org.gradle.api.internal.tasks.CachingTaskDependencyResolveContext;
import org.gradle.api.specs.Spec;
@@ -25,7 +26,14 @@ import org.gradle.api.specs.Specs;
import org.gradle.execution.MultipleBuildFailures;
import org.gradle.execution.TaskFailureHandler;
import org.gradle.internal.UncheckedException;
-
+import org.gradle.internal.graph.CachingDirectedGraphWalker;
+import org.gradle.internal.graph.DirectedGraph;
+import org.gradle.internal.graph.DirectedGraphRenderer;
+import org.gradle.internal.graph.GraphNodeRenderer;
+import org.gradle.logging.StyledTextOutput;
+import org.gradle.util.CollectionUtils;
+
+import java.io.StringWriter;
import java.util.*;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
@@ -38,6 +46,9 @@ import java.util.concurrent.locks.ReentrantLock;
class DefaultTaskExecutionPlan implements TaskExecutionPlan {
private final Lock lock = new ReentrantLock();
private final Condition condition = lock.newCondition();
+ private final Set<TaskInfo> tasksInUnknownState = new LinkedHashSet<TaskInfo>();
+ private final Set<TaskInfo> entryTasks = new LinkedHashSet<TaskInfo>();
+ private final TaskDependencyGraph graph = new TaskDependencyGraph();
private final LinkedHashMap<Task, TaskInfo> executionPlan = new LinkedHashMap<Task, TaskInfo>();
private final List<Throwable> failures = new ArrayList<Throwable>();
private Spec<? super Task> filter = Specs.satisfyAll();
@@ -46,57 +57,227 @@ class DefaultTaskExecutionPlan implements TaskExecutionPlan {
private final List<String> runningProjects = new ArrayList<String>();
public void addToTaskGraph(Collection<? extends Task> tasks) {
- List<Task> queue = new ArrayList<Task>(tasks);
- Collections.sort(queue);
+ List<TaskInfo> queue = new ArrayList<TaskInfo>();
+
+ List<Task> sortedTasks = new ArrayList<Task>(tasks);
+ Collections.sort(sortedTasks);
+ for (Task task : sortedTasks) {
+ TaskInfo node = graph.addNode(task);
+ if (node.getMustNotRun()) {
+ requireWithDependencies(node);
+ } else {
+ node.require();
+ }
+ entryTasks.add(node);
+ queue.add(node);
+ }
- Set<Task> visiting = new HashSet<Task>();
+ Set<TaskInfo> visiting = new HashSet<TaskInfo>();
CachingTaskDependencyResolveContext context = new CachingTaskDependencyResolveContext();
while (!queue.isEmpty()) {
- Task task = queue.get(0);
- if (!filter.isSatisfiedBy(task)) {
- // Filtered - skip
+ TaskInfo node = queue.get(0);
+ if (node.getDependenciesProcessed()) {
+ // Have already visited this task - skip it
queue.remove(0);
continue;
}
- if (executionPlan.containsKey(task)) {
- // Already in plan - skip
+
+ TaskInternal task = node.getTask();
+ boolean filtered = !filter.isSatisfiedBy(task);
+ if (filtered) {
+ // Task is not required - skip it
queue.remove(0);
+ node.dependenciesProcessed();
+ node.doNotRequire();
continue;
}
- if (visiting.add(task)) {
+ if (visiting.add(node)) {
// Have not seen this task before - add its dependencies to the head of the queue and leave this
// task in the queue
- Set<Task> dependsOnTasks = new TreeSet<Task>(Collections.reverseOrder());
- dependsOnTasks.addAll(context.getDependencies(task));
+ Set<? extends Task> dependsOnTasks = context.getDependencies(task);
for (Task dependsOnTask : dependsOnTasks) {
- if (visiting.contains(dependsOnTask)) {
- throw new CircularReferenceException(String.format(
- "Circular dependency between tasks. Cycle includes [%s, %s].", task, dependsOnTask));
+ TaskInfo targetNode = graph.addNode(dependsOnTask);
+ node.addHardSuccessor(targetNode);
+ if (!visiting.contains(targetNode)) {
+ queue.add(0, targetNode);
+ }
+ }
+ for (Task finalizerTask : task.getFinalizedBy().getDependencies(task)) {
+ TaskInfo targetNode = graph.addNode(finalizerTask);
+ addFinalizerNode(node, targetNode);
+ if (!visiting.contains(targetNode)) {
+ queue.add(0, targetNode);
+ }
+ }
+ for (Task mustRunAfter : task.getMustRunAfter().getDependencies(task)) {
+ TaskInfo targetNode = graph.addNode(mustRunAfter);
+ node.addSoftSuccessor(targetNode);
+ }
+ if (node.isRequired()) {
+ for (TaskInfo hardSuccessor : node.getHardSuccessors()) {
+ hardSuccessor.require();
+ }
+ } else {
+ tasksInUnknownState.add(node);
+ }
+ } else {
+ // Have visited this task's dependencies - add it to the graph
+ queue.remove(0);
+ visiting.remove(node);
+ node.dependenciesProcessed();
+ }
+ }
+ resolveTasksInUnknownState();
+ }
+
+ private void resolveTasksInUnknownState() {
+ List<TaskInfo> queue = new ArrayList<TaskInfo>(tasksInUnknownState);
+ Set<TaskInfo> visiting = new HashSet<TaskInfo>();
+
+ while (!queue.isEmpty()) {
+ TaskInfo task = queue.get(0);
+ if (task.isInKnownState()) {
+ queue.remove(0);
+ continue;
+ }
+
+ if (visiting.add(task)) {
+ for (TaskInfo hardPredecessor : task.getHardPredecessors()) {
+ if (!visiting.contains(hardPredecessor)) {
+ queue.add(0, hardPredecessor);
}
- queue.add(0, dependsOnTask);
}
} else {
- // Have visited this task's dependencies - add it to the end of the plan
queue.remove(0);
visiting.remove(task);
- Set<TaskInfo> dependencies = new HashSet<TaskInfo>();
- for (Task dependency : context.getDependencies(task)) {
- TaskInfo dependencyInfo = executionPlan.get(dependency);
- if (dependencyInfo != null) {
- dependencies.add(dependencyInfo);
+ task.mustNotRun();
+ for (TaskInfo predecessor : task.getHardPredecessors()) {
+ assert predecessor.isRequired() || predecessor.getMustNotRun();
+ if (predecessor.isRequired()) {
+ task.require();
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ private void addFinalizerNode(TaskInfo node, TaskInfo finalizerNode) {
+ if (filter.isSatisfiedBy(finalizerNode.getTask())) {
+ node.addFinalizer(finalizerNode);
+ if (!finalizerNode.isInKnownState()) {
+ finalizerNode.mustNotRun();
+ }
+ finalizerNode.addSoftSuccessor(node);
+ }
+ }
+
+ private <T> void addAllReversed(List<T> list, TreeSet<T> set) {
+ List<T> elements = CollectionUtils.toList(set);
+ Collections.reverse(elements);
+ list.addAll(elements);
+ }
+
+ private void requireWithDependencies(TaskInfo taskInfo) {
+ if (taskInfo.getMustNotRun() && filter.isSatisfiedBy(taskInfo.getTask())) {
+ taskInfo.require();
+ for (TaskInfo dependency : taskInfo.getHardSuccessors()) {
+ requireWithDependencies(dependency);
+ }
+ }
+ }
+
+ public void determineExecutionPlan() {
+ List<TaskInfo> nodeQueue = new ArrayList<TaskInfo>(entryTasks);
+ Set<TaskInfo> visitingNodes = new HashSet<TaskInfo>();
+ while (!nodeQueue.isEmpty()) {
+ TaskInfo taskNode = nodeQueue.get(0);
+
+ if (taskNode.isIncludeInGraph() || executionPlan.containsKey(taskNode.getTask())) {
+ nodeQueue.remove(0);
+ continue;
+ }
+
+ if (visitingNodes.add(taskNode)) {
+ // Have not seen this task before - add its dependencies to the head of the queue and leave this
+ // task in the queue
+ ArrayList<TaskInfo> dependsOnTasks = new ArrayList<TaskInfo>();
+ addAllReversed(dependsOnTasks, taskNode.getHardSuccessors());
+ addAllReversed(dependsOnTasks, taskNode.getSoftSuccessors());
+ for (TaskInfo dependsOnTask : dependsOnTasks) {
+ if (visitingNodes.contains(dependsOnTask)) {
+ onOrderingCycle();
+ }
+ nodeQueue.add(0, dependsOnTask);
+ }
+ } else {
+ // Have visited this task's dependencies - add it to the end of the plan
+ nodeQueue.remove(0);
+ visitingNodes.remove(taskNode);
+ executionPlan.put(taskNode.getTask(), taskNode);
+ ArrayList<TaskInfo> finalizerTasks = new ArrayList<TaskInfo>();
+ addAllReversed(finalizerTasks, taskNode.getFinalizers());
+ for (TaskInfo finalizer : finalizerTasks) {
+ if (!visitingNodes.contains(finalizer)) {
+ nodeQueue.add(finalizerTaskPosition(finalizer, nodeQueue), finalizer);
}
- // else - the dependency has been filtered, so ignore it
}
- executionPlan.put(task, new TaskInfo((TaskInternal) task, dependencies));
}
}
}
+ private int finalizerTaskPosition(TaskInfo finalizer, final List<TaskInfo> nodeQueue) {
+ if (nodeQueue.size() == 0) {
+ return 0;
+ }
+
+ ArrayList<TaskInfo> dependsOnTasks = new ArrayList<TaskInfo>();
+ dependsOnTasks.addAll(finalizer.getHardSuccessors());
+ dependsOnTasks.addAll(finalizer.getSoftSuccessors());
+ List<Integer> dependsOnTaskIndexes = CollectionUtils.collect(dependsOnTasks, new Transformer<Integer, TaskInfo>() {
+ public Integer transform(TaskInfo dependsOnTask) {
+ return nodeQueue.indexOf(dependsOnTask);
+ }
+ });
+ return Collections.max(dependsOnTaskIndexes) + 1;
+ }
+
+ private void onOrderingCycle() {
+ CachingDirectedGraphWalker<TaskInfo, Void> graphWalker = new CachingDirectedGraphWalker<TaskInfo, Void>(new DirectedGraph<TaskInfo, Void>() {
+ public void getNodeValues(TaskInfo node, Collection<? super Void> values, Collection<? super TaskInfo> connectedNodes) {
+ connectedNodes.addAll(node.getHardSuccessors());
+ connectedNodes.addAll(node.getSoftSuccessors());
+ }
+ });
+ graphWalker.add(entryTasks);
+ final List<TaskInfo> firstCycle = new ArrayList<TaskInfo>(graphWalker.findCycles().get(0));
+ Collections.sort(firstCycle);
+
+ DirectedGraphRenderer<TaskInfo> graphRenderer = new DirectedGraphRenderer<TaskInfo>(new GraphNodeRenderer<TaskInfo>() {
+ public void renderTo(TaskInfo node, StyledTextOutput output) {
+ output.withStyle(StyledTextOutput.Style.Identifier).text(node.getTask().getPath());
+ }
+ }, new DirectedGraph<TaskInfo, Object>() {
+ public void getNodeValues(TaskInfo node, Collection<? super Object> values, Collection<? super TaskInfo> connectedNodes) {
+ for (TaskInfo dependency : firstCycle) {
+ if (node.getHardSuccessors().contains(dependency) || node.getSoftSuccessors().contains(dependency)) {
+ connectedNodes.add(dependency);
+ }
+ }
+ }
+ });
+ StringWriter writer = new StringWriter();
+ graphRenderer.renderTo(firstCycle.get(0), writer);
+ throw new CircularReferenceException(String.format("Circular dependency between the following tasks:%n%s", writer.toString()));
+ }
+
public void clear() {
lock.lock();
try {
+ graph.clear();
+ entryTasks.clear();
executionPlan.clear();
failures.clear();
runningProjects.clear();
@@ -117,45 +298,10 @@ class DefaultTaskExecutionPlan implements TaskExecutionPlan {
this.failureHandler = handler;
}
- public TaskInfo getTaskToExecute(Spec<TaskInfo> criteria) {
- lock.lock();
- try {
-
- TaskInfo nextMatching;
- while ((nextMatching = getNextReadyAndMatching(criteria)) != null) {
- while (!nextMatching.allDependenciesComplete()) {
- try {
- condition.await();
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- }
-
- // The task state could have been modified while we waited for dependency completion. Check that it is still 'ready'.
- if (!nextMatching.isReady()) {
- continue;
- }
-
- if (nextMatching.allDependenciesSuccessful()) {
- nextMatching.startExecution();
- return nextMatching;
- } else {
- nextMatching.skipExecution();
- condition.signalAll();
- }
- }
-
- return null;
-
- } finally {
- lock.unlock();
- }
- }
-
public TaskInfo getTaskToExecute() {
lock.lock();
try {
- while(true) {
+ while (true) {
TaskInfo nextMatching = null;
boolean allTasksComplete = true;
for (TaskInfo taskInfo : executionPlan.values()) {
@@ -190,18 +336,10 @@ class DefaultTaskExecutionPlan implements TaskExecutionPlan {
}
}
- private TaskInfo getNextReadyAndMatching(Spec<TaskInfo> criteria) {
- for (TaskInfo taskInfo : executionPlan.values()) {
- if (taskInfo.isReady() && criteria.isSatisfiedBy(taskInfo)) {
- return taskInfo;
- }
- }
- return null;
- }
-
public void taskComplete(TaskInfo taskInfo) {
lock.lock();
try {
+ enforceFinalizerTasks(taskInfo);
if (taskInfo.isFailed()) {
handleFailure(taskInfo);
}
@@ -214,6 +352,23 @@ class DefaultTaskExecutionPlan implements TaskExecutionPlan {
}
}
+ private void enforceFinalizerTasks(TaskInfo taskInfo) {
+ for (TaskInfo finalizerNode : taskInfo.getFinalizers()) {
+ if (finalizerNode.isRequired() || finalizerNode.getMustNotRun()) {
+ enforceWithDependencies(finalizerNode);
+ }
+ }
+ }
+
+ private void enforceWithDependencies(TaskInfo node) {
+ for (TaskInfo dependencyNode : node.getHardSuccessors()) {
+ enforceWithDependencies(dependencyNode);
+ }
+ if (node.getMustNotRun() || node.isRequired()) {
+ node.enforceRun();
+ }
+ }
+
private void handleFailure(TaskInfo taskInfo) {
Throwable executionFailure = taskInfo.getExecutionFailure();
if (executionFailure != null) {
@@ -235,9 +390,9 @@ class DefaultTaskExecutionPlan implements TaskExecutionPlan {
}
private void abortExecution() {
- // Allow currently executing tasks to complete, but skip everything else.
+ // Allow currently executing and enforced tasks to complete, but skip everything else.
for (TaskInfo taskInfo : executionPlan.values()) {
- if (taskInfo.isReady()) {
+ if (taskInfo.isRequired()) {
taskInfo.skipExecution();
}
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/execution/taskgraph/DefaultTaskGraphExecuter.java b/subprojects/core/src/main/groovy/org/gradle/execution/taskgraph/DefaultTaskGraphExecuter.java
index dddbae7..5b319e8 100644
--- a/subprojects/core/src/main/groovy/org/gradle/execution/taskgraph/DefaultTaskGraphExecuter.java
+++ b/subprojects/core/src/main/groovy/org/gradle/execution/taskgraph/DefaultTaskGraphExecuter.java
@@ -34,17 +34,18 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
-/**
- * @author Hans Dockter
- */
public class DefaultTaskGraphExecuter implements TaskGraphExecuter {
private static Logger logger = LoggerFactory.getLogger(DefaultTaskGraphExecuter.class);
+ private enum TaskGraphState {
+ EMPTY, DIRTY, POPULATED
+ }
+
private final TaskPlanExecutor taskPlanExecutor;
private final ListenerBroadcast<TaskExecutionGraphListener> graphListeners;
private final ListenerBroadcast<TaskExecutionListener> taskListeners;
private final DefaultTaskExecutionPlan taskExecutionPlan = new DefaultTaskExecutionPlan();
- private boolean populated;
+ private TaskGraphState taskGraphState = TaskGraphState.EMPTY;
public DefaultTaskGraphExecuter(ListenerManager listenerManager, TaskPlanExecutor taskPlanExecutor) {
this.taskPlanExecutor = taskPlanExecutor;
@@ -52,14 +53,15 @@ public class DefaultTaskGraphExecuter implements TaskGraphExecuter {
taskListeners = listenerManager.createAnonymousBroadcaster(TaskExecutionListener.class);
}
- public void useFilter(Spec<? super Task> filter) {
- taskExecutionPlan.useFilter(filter);
- }
-
public void useFailureHandler(TaskFailureHandler handler) {
taskExecutionPlan.useFailureHandler(handler);
}
+ public void useFilter(Spec<? super Task> filter) {
+ taskExecutionPlan.useFilter(filter);
+ taskGraphState = TaskGraphState.DIRTY;
+ }
+
public void addTasks(Iterable<? extends Task> tasks) {
assert tasks != null;
@@ -70,14 +72,14 @@ public class DefaultTaskGraphExecuter implements TaskGraphExecuter {
taskSet.add(task);
}
taskExecutionPlan.addToTaskGraph(taskSet);
- populated = true;
+ taskGraphState = TaskGraphState.DIRTY;
logger.debug("Timing: Creating the DAG took " + clock.getTime());
}
public void execute() {
- assertPopulated();
Clock clock = new Clock();
+ ensurePopulated();
graphListeners.getSource().graphPopulated(this);
try {
@@ -117,12 +119,12 @@ public class DefaultTaskGraphExecuter implements TaskGraphExecuter {
}
public boolean hasTask(Task task) {
- assertPopulated();
+ ensurePopulated();
return taskExecutionPlan.getTasks().contains(task);
}
public boolean hasTask(String path) {
- assertPopulated();
+ ensurePopulated();
assert path != null && path.length() > 0;
for (Task task : taskExecutionPlan.getTasks()) {
if (task.getPath().equals(path)) {
@@ -133,14 +135,20 @@ public class DefaultTaskGraphExecuter implements TaskGraphExecuter {
}
public List<Task> getAllTasks() {
- assertPopulated();
+ ensurePopulated();
return taskExecutionPlan.getTasks();
}
- private void assertPopulated() {
- if (!populated) {
- throw new IllegalStateException(
- "Task information is not available, as this task execution graph has not been populated.");
+ private void ensurePopulated() {
+ switch (taskGraphState) {
+ case EMPTY:
+ throw new IllegalStateException(
+ "Task information is not available, as this task execution graph has not been populated.");
+ case DIRTY:
+ taskExecutionPlan.determineExecutionPlan();
+ taskGraphState = TaskGraphState.POPULATED;
+ return;
+ case POPULATED:
}
}
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/execution/taskgraph/DefaultTaskPlanExecutor.java b/subprojects/core/src/main/groovy/org/gradle/execution/taskgraph/DefaultTaskPlanExecutor.java
index b353a6d..ac30fd6 100644
--- a/subprojects/core/src/main/groovy/org/gradle/execution/taskgraph/DefaultTaskPlanExecutor.java
+++ b/subprojects/core/src/main/groovy/org/gradle/execution/taskgraph/DefaultTaskPlanExecutor.java
@@ -17,41 +17,22 @@
package org.gradle.execution.taskgraph;
import org.gradle.api.execution.TaskExecutionListener;
-import org.gradle.api.internal.TaskInternal;
-import org.gradle.api.specs.Spec;
-import org.gradle.api.specs.Specs;
+import org.gradle.api.internal.changedetection.state.TaskArtifactStateCacheAccess;
-class DefaultTaskPlanExecutor implements TaskPlanExecutor {
+class DefaultTaskPlanExecutor extends AbstractTaskPlanExecutor {
+ private final TaskArtifactStateCacheAccess stateCacheAccess;
- public void process(TaskExecutionPlan taskExecutionPlan, TaskExecutionListener taskListener) {
- Spec<TaskInfo> anyTask = Specs.satisfyAll();
- TaskInfo taskInfo = taskExecutionPlan.getTaskToExecute(anyTask);
- while (taskInfo != null) {
- processTask(taskInfo, taskExecutionPlan, taskListener);
- taskInfo = taskExecutionPlan.getTaskToExecute(anyTask);
- }
- taskExecutionPlan.awaitCompletion();
+ DefaultTaskPlanExecutor(TaskArtifactStateCacheAccess stateCacheAccess) {
+ this.stateCacheAccess = stateCacheAccess;
}
- protected void processTask(TaskInfo taskInfo, TaskExecutionPlan taskExecutionPlan, TaskExecutionListener taskListener) {
- try {
- executeTask(taskInfo, taskListener);
- } catch (Throwable e) {
- taskInfo.setExecutionFailure(e);
- } finally {
- taskExecutionPlan.taskComplete(taskInfo);
- }
- }
-
- // TODO:PARALLEL It would be good to move this logic into a TaskExecuter wrapper, but we'd need a way to give it a TaskExecutionListener that
- // is wired to the various add/remove listener methods on TaskExecutionGraph
- private void executeTask(TaskInfo taskInfo, TaskExecutionListener taskListener) {
- TaskInternal task = taskInfo.getTask();
- taskListener.beforeExecute(task);
- try {
- task.executeWithoutThrowingTaskFailure();
- } finally {
- taskListener.afterExecute(task, task.getState());
- }
+ public void process(final TaskExecutionPlan taskExecutionPlan, final TaskExecutionListener taskListener) {
+ //At the very beginning, we unlock the cache access. The synchronisation via 'useCache' is pushed down and ine grained.
+ stateCacheAccess.longRunningOperation("Execute tasks", new Runnable() {
+ public void run() {
+ taskWorker(taskExecutionPlan, taskListener).run();
+ taskExecutionPlan.awaitCompletion();
+ }
+ });
}
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/execution/taskgraph/ParallelTaskPlanExecutor.java b/subprojects/core/src/main/groovy/org/gradle/execution/taskgraph/ParallelTaskPlanExecutor.java
index 29af40c..7abedcc 100644
--- a/subprojects/core/src/main/groovy/org/gradle/execution/taskgraph/ParallelTaskPlanExecutor.java
+++ b/subprojects/core/src/main/groovy/org/gradle/execution/taskgraph/ParallelTaskPlanExecutor.java
@@ -19,58 +19,59 @@ package org.gradle.execution.taskgraph;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.execution.TaskExecutionListener;
-import org.gradle.api.internal.changedetection.TaskArtifactStateCacheAccess;
+import org.gradle.api.internal.changedetection.state.TaskArtifactStateCacheAccess;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
+import org.gradle.internal.concurrent.DefaultExecutorFactory;
+import org.gradle.internal.concurrent.ExecutorFactory;
+import org.gradle.internal.concurrent.StoppableExecutor;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
-import static org.gradle.util.Clock.prettyTime;
-
-class ParallelTaskPlanExecutor extends DefaultTaskPlanExecutor {
+class ParallelTaskPlanExecutor extends AbstractTaskPlanExecutor {
private static final Logger LOGGER = Logging.getLogger(ParallelTaskPlanExecutor.class);
-
- private final List<Thread> executorThreads = new ArrayList<Thread>();
- private final TaskArtifactStateCacheAccess stateCacheAccess;
private final int executorCount;
+ private final TaskArtifactStateCacheAccess cacheAccess;
public ParallelTaskPlanExecutor(TaskArtifactStateCacheAccess cacheAccess, int numberOfParallelExecutors) {
+ this.cacheAccess = cacheAccess;
if (numberOfParallelExecutors < 1) {
throw new IllegalArgumentException("Not a valid number of parallel executors: " + numberOfParallelExecutors);
}
- LOGGER.info("Using {} parallel executor threads", numberOfParallelExecutors);
-
- this.stateCacheAccess = cacheAccess;
this.executorCount = numberOfParallelExecutors;
}
public void process(final TaskExecutionPlan taskExecutionPlan, final TaskExecutionListener taskListener) {
- stateCacheAccess.longRunningOperation("Executing all tasks", new Runnable() {
+ // The main thread holds the lock for the task cache. Need to release the lock while executing the tasks.
+ // This locking needs to be pushed down closer to the things that need the lock and removed from here.
+ cacheAccess.longRunningOperation("Executing all tasks", new Runnable() {
public void run() {
- doProcess(taskExecutionPlan, taskListener);
- // TODO This needs to wait until all tasks have been executed, not just started....
- taskExecutionPlan.awaitCompletion();
+ DefaultExecutorFactory factory = new DefaultExecutorFactory();
+ try {
+ doProcess(taskExecutionPlan, taskListener, factory);
+ taskExecutionPlan.awaitCompletion();
+ } finally {
+ factory.stop();
+ }
}
});
}
- private void doProcess(TaskExecutionPlan taskExecutionPlan, TaskExecutionListener taskListener) {
+ private void doProcess(TaskExecutionPlan taskExecutionPlan, TaskExecutionListener taskListener, ExecutorFactory factory) {
List<Project> projects = getAllProjects(taskExecutionPlan);
int numExecutors = Math.min(executorCount, projects.size());
- numExecutors = Math.min(numExecutors, 4);
- for (int i = 0; i < numExecutors; i++) {
- TaskExecutorWorker worker = new TaskExecutorWorker(taskExecutionPlan, taskListener);
- executorThreads.add(new Thread(worker));
- }
+ LOGGER.info("Using {} parallel executor threads", numExecutors);
- for (Thread executorThread : executorThreads) {
+ for (int i = 0; i < numExecutors; i++) {
+ Runnable worker = taskWorker(taskExecutionPlan, taskListener);
+ StoppableExecutor executor = factory.create("Task worker " + (i+1));
// TODO A bunch more stuff to contextualise the thread
- executorThread.start();
+ executor.execute(worker);
}
}
@@ -81,41 +82,4 @@ class ParallelTaskPlanExecutor extends DefaultTaskPlanExecutor {
}
return new ArrayList<Project>(uniqueProjects);
}
-
- private class TaskExecutorWorker implements Runnable {
- private final TaskExecutionPlan taskExecutionPlan;
- private final TaskExecutionListener taskListener;
- private long busyMs;
- private long waitedForCacheMs;
-
- private TaskExecutorWorker(TaskExecutionPlan taskExecutionPlan, TaskExecutionListener taskListener) {
- this.taskExecutionPlan = taskExecutionPlan;
- this.taskListener = taskListener;
- }
-
- public void run() {
- long start = System.currentTimeMillis();
- TaskInfo task;
- while((task = taskExecutionPlan.getTaskToExecute()) != null) {
- executeTaskWithCacheLock(task);
- }
- long total = System.currentTimeMillis() - start;
- LOGGER.info("Parallel worker [{}] stopped, busy: {}, idle: {}, waited for cache: {}", Thread.currentThread(), prettyTime(busyMs), prettyTime(total - busyMs), prettyTime(waitedForCacheMs));
- }
-
- private void executeTaskWithCacheLock(final TaskInfo taskInfo) {
- final String taskPath = taskInfo.getTask().getPath();
- LOGGER.info(taskPath + " (" + Thread.currentThread() + " - start");
- final long start = System.currentTimeMillis();
- stateCacheAccess.useCache("Executing " + taskPath, new Runnable() {
- public void run() {
- waitedForCacheMs += System.currentTimeMillis() - start;
- processTask(taskInfo, taskExecutionPlan, taskListener);
- }
- });
- busyMs += System.currentTimeMillis() - start;
-
- LOGGER.info(taskPath + " (" + Thread.currentThread() + ") - complete");
- }
- }
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/execution/taskgraph/TaskDependencyGraph.java b/subprojects/core/src/main/groovy/org/gradle/execution/taskgraph/TaskDependencyGraph.java
new file mode 100644
index 0000000..2bf5e7c
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/execution/taskgraph/TaskDependencyGraph.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.execution.taskgraph;
+
+
+import org.gradle.api.Nullable;
+import org.gradle.api.Task;
+import org.gradle.api.internal.TaskInternal;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+public class TaskDependencyGraph {
+ private final Map<Task, TaskInfo> nodes = new HashMap<Task, TaskInfo>();
+
+ public Set<Task> getTasks() {
+ return nodes.keySet();
+ }
+
+ @Nullable
+ public TaskInfo getNode(Task task) {
+ return nodes.get(task);
+ }
+
+ public TaskInfo addNode(Task task) {
+ TaskInfo node = nodes.get(task);
+ if (node == null) {
+ node = new TaskInfo((TaskInternal) task);
+ nodes.put(task, node);
+ }
+ return node;
+ }
+
+ public void clear() {
+ nodes.clear();
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/execution/taskgraph/TaskExecutionPlan.java b/subprojects/core/src/main/groovy/org/gradle/execution/taskgraph/TaskExecutionPlan.java
index 7020ba2..3a2b9a4 100644
--- a/subprojects/core/src/main/groovy/org/gradle/execution/taskgraph/TaskExecutionPlan.java
+++ b/subprojects/core/src/main/groovy/org/gradle/execution/taskgraph/TaskExecutionPlan.java
@@ -17,7 +17,6 @@
package org.gradle.execution.taskgraph;
import org.gradle.api.Task;
-import org.gradle.api.specs.Spec;
import java.util.List;
@@ -26,15 +25,6 @@ import java.util.List;
*/
public interface TaskExecutionPlan {
/**
- * Provides a ready-to-execute task that matches the specified criteria. A task is ready-to-execute if all of it's dependencies have been completed successfully.
- * If the next matching task is not ready-to-execute, this method will block until it is ready.
- * If no tasks remain that match the criteria, null will be returned.
- * @param criteria Only tasks matching this Spec will be returned.
- * @return The next matching task, or null if no matching tasks remain.
- */
- TaskInfo getTaskToExecute(Spec<TaskInfo> criteria);
-
- /**
* Signals to the plan that execution of this task has completed. Execution is complete if the task succeeds, fails, or an exception is thrown during execution.
* @param task the completed task.
*/
@@ -50,6 +40,11 @@ public interface TaskExecutionPlan {
*/
List<Task> getTasks();
- //TODO SF this should replace completely getTaskToExecute(), inherit and expand existing unit test coverage
+ /**
+ * Provides a ready-to-execute task. A task is ready-to-execute if all of its dependencies have been completed successfully.
+ * This method blocks until the at least one task is ready-to-execute.
+ * If no tasks remain, null will be returned.
+ * @return The task, or null if no matching tasks remain.
+ */
TaskInfo getTaskToExecute();
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/execution/taskgraph/TaskInfo.java b/subprojects/core/src/main/groovy/org/gradle/execution/taskgraph/TaskInfo.java
index ea7b9fb..a362d70 100644
--- a/subprojects/core/src/main/groovy/org/gradle/execution/taskgraph/TaskInfo.java
+++ b/subprojects/core/src/main/groovy/org/gradle/execution/taskgraph/TaskInfo.java
@@ -16,45 +16,67 @@
package org.gradle.execution.taskgraph;
+import com.google.common.collect.Iterables;
import org.gradle.api.internal.TaskInternal;
-import java.util.Set;
+import java.util.TreeSet;
-class TaskInfo {
+class TaskInfo implements Comparable<TaskInfo> {
private enum TaskExecutionState {
- READY, EXECUTING, EXECUTED, SKIPPED
+ UNKNOWN, NOT_REQUIRED, SHOULD_RUN, MUST_RUN, MUST_NOT_RUN, EXECUTING, EXECUTED, SKIPPED
}
private final TaskInternal task;
- private final Set<TaskInfo> dependencies;
private TaskExecutionState state;
private Throwable executionFailure;
+ private boolean dependenciesProcessed;
+ private final TreeSet<TaskInfo> hardPredecessors = new TreeSet<TaskInfo>();
+ private final TreeSet<TaskInfo> hardSuccessors = new TreeSet<TaskInfo>();
+ private final TreeSet<TaskInfo> softSuccessors = new TreeSet<TaskInfo>();
+ private final TreeSet<TaskInfo> finalizers = new TreeSet<TaskInfo>();
- public TaskInfo(TaskInternal task, Set<TaskInfo> dependencies) {
+ public TaskInfo(TaskInternal task) {
this.task = task;
- this.dependencies = dependencies;
- this.state = TaskExecutionState.READY;
+ this.state = TaskExecutionState.UNKNOWN;
}
public TaskInternal getTask() {
return task;
}
- public Set<TaskInfo> getDependencies() {
- return dependencies;
+ public boolean isRequired() {
+ return state == TaskExecutionState.SHOULD_RUN;
+ }
+
+ public boolean getMustNotRun() {
+ return state == TaskExecutionState.MUST_NOT_RUN;
+ }
+
+ public boolean isIncludeInGraph() {
+ return state == TaskExecutionState.NOT_REQUIRED || state == TaskExecutionState.UNKNOWN;
}
public boolean isReady() {
- return state == TaskExecutionState.READY;
+ return state == TaskExecutionState.SHOULD_RUN || state == TaskExecutionState.MUST_RUN;
+ }
+
+ public boolean isInKnownState() {
+ return state != TaskExecutionState.UNKNOWN;
}
public boolean isComplete() {
- return state == TaskExecutionState.EXECUTED || state == TaskExecutionState.SKIPPED;
+ return state == TaskExecutionState.EXECUTED
+ || state == TaskExecutionState.SKIPPED
+ || state == TaskExecutionState.UNKNOWN
+ || state == TaskExecutionState.NOT_REQUIRED
+ || state == TaskExecutionState.MUST_NOT_RUN;
}
public boolean isSuccessful() {
- return state == TaskExecutionState.EXECUTED && !isFailed();
+ return (state == TaskExecutionState.EXECUTED && !isFailed())
+ || state == TaskExecutionState.NOT_REQUIRED
+ || state == TaskExecutionState.MUST_NOT_RUN;
}
public boolean isFailed() {
@@ -62,7 +84,7 @@ class TaskInfo {
}
public void startExecution() {
- assert state == TaskExecutionState.READY;
+ assert isReady();
state = TaskExecutionState.EXECUTING;
}
@@ -72,10 +94,27 @@ class TaskInfo {
}
public void skipExecution() {
- assert state == TaskExecutionState.READY;
+ assert state == TaskExecutionState.SHOULD_RUN;
state = TaskExecutionState.SKIPPED;
}
+ public void require() {
+ state = TaskExecutionState.SHOULD_RUN;
+ }
+
+ public void doNotRequire() {
+ state = TaskExecutionState.NOT_REQUIRED;
+ }
+
+ public void mustNotRun() {
+ state = TaskExecutionState.MUST_NOT_RUN;
+ }
+
+ public void enforceRun() {
+ assert state == TaskExecutionState.SHOULD_RUN || state == TaskExecutionState.MUST_NOT_RUN || state == TaskExecutionState.MUST_RUN;
+ state = TaskExecutionState.MUST_RUN;
+ }
+
public void setExecutionFailure(Throwable failure) {
assert state == TaskExecutionState.EXECUTING;
this.executionFailure = failure;
@@ -90,7 +129,7 @@ class TaskInfo {
}
public boolean allDependenciesComplete() {
- for (TaskInfo dependency : getDependencies()) {
+ for (TaskInfo dependency : Iterables.concat(softSuccessors, hardSuccessors)) {
if (!dependency.isComplete()) {
return false;
}
@@ -99,11 +138,52 @@ class TaskInfo {
}
public boolean allDependenciesSuccessful() {
- for (TaskInfo dependency : getDependencies()) {
+ for (TaskInfo dependency : hardSuccessors) {
if (!dependency.isSuccessful()) {
return false;
}
}
return true;
}
+
+ public TreeSet<TaskInfo> getHardPredecessors() {
+ return hardPredecessors;
+ }
+
+ public TreeSet<TaskInfo> getHardSuccessors() {
+ return hardSuccessors;
+ }
+
+ public TreeSet<TaskInfo> getSoftSuccessors() {
+ return softSuccessors;
+ }
+
+ public TreeSet<TaskInfo> getFinalizers() {
+ return finalizers;
+ }
+
+ public boolean getDependenciesProcessed() {
+ return dependenciesProcessed;
+ }
+
+ public void dependenciesProcessed() {
+ dependenciesProcessed = true;
+ }
+
+ public void addHardSuccessor(TaskInfo toNode) {
+ hardSuccessors.add(toNode);
+ toNode.hardPredecessors.add(this);
+ }
+
+ public void addSoftSuccessor(TaskInfo toNode) {
+ softSuccessors.add(toNode);
+ }
+
+ public void addFinalizer(TaskInfo finalizerNode) {
+ finalizers.add(finalizerNode);
+ }
+
+ public int compareTo(TaskInfo otherInfo) {
+ return task.compareTo(otherInfo.getTask());
+ }
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/execution/taskgraph/TaskPlanExecutorFactory.java b/subprojects/core/src/main/groovy/org/gradle/execution/taskgraph/TaskPlanExecutorFactory.java
index e988f2c..a112103 100644
--- a/subprojects/core/src/main/groovy/org/gradle/execution/taskgraph/TaskPlanExecutorFactory.java
+++ b/subprojects/core/src/main/groovy/org/gradle/execution/taskgraph/TaskPlanExecutorFactory.java
@@ -16,9 +16,8 @@
package org.gradle.execution.taskgraph;
-import org.gradle.api.internal.changedetection.TaskArtifactStateCacheAccess;
+import org.gradle.api.internal.changedetection.state.TaskArtifactStateCacheAccess;
import org.gradle.internal.Factory;
-import org.gradle.util.SingleMessageLogger;
public class TaskPlanExecutorFactory implements Factory<TaskPlanExecutor> {
@@ -33,10 +32,8 @@ public class TaskPlanExecutorFactory implements Factory<TaskPlanExecutor> {
public TaskPlanExecutor create() {
ExecutionOptions options = new ExecutionOptions(parallelThreads);
if (options.executeProjectsInParallel()) {
- SingleMessageLogger.informAboutIncubating("Parallel project execution");
return new ParallelTaskPlanExecutor(taskArtifactStateCacheAccess, options.numberOfParallelThreads());
}
- return new DefaultTaskPlanExecutor();
-
+ return new DefaultTaskPlanExecutor(taskArtifactStateCacheAccess);
}
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/execution/taskpath/ProjectFinderByTaskPath.java b/subprojects/core/src/main/groovy/org/gradle/execution/taskpath/ProjectFinderByTaskPath.java
index d6e43ff..50372ff 100644
--- a/subprojects/core/src/main/groovy/org/gradle/execution/taskpath/ProjectFinderByTaskPath.java
+++ b/subprojects/core/src/main/groovy/org/gradle/execution/taskpath/ProjectFinderByTaskPath.java
@@ -23,9 +23,6 @@ import org.gradle.util.NameMatcher;
import java.util.Map;
-/**
- * by Szczepan Faber, created at: 1/3/13
- */
public class ProjectFinderByTaskPath {
public ProjectInternal findProject(String projectPath, ProjectInternal startFrom) {
diff --git a/subprojects/core/src/main/groovy/org/gradle/execution/taskpath/ResolvedTaskPath.java b/subprojects/core/src/main/groovy/org/gradle/execution/taskpath/ResolvedTaskPath.java
index 031ddef..f074bec 100644
--- a/subprojects/core/src/main/groovy/org/gradle/execution/taskpath/ResolvedTaskPath.java
+++ b/subprojects/core/src/main/groovy/org/gradle/execution/taskpath/ResolvedTaskPath.java
@@ -18,9 +18,6 @@ package org.gradle.execution.taskpath;
import org.gradle.api.internal.project.ProjectInternal;
-/**
- * by Szczepan Faber, created at: 1/29/13
- */
public class ResolvedTaskPath {
private final String prefix;
private final String taskName;
diff --git a/subprojects/core/src/main/groovy/org/gradle/execution/taskpath/TaskPathResolver.java b/subprojects/core/src/main/groovy/org/gradle/execution/taskpath/TaskPathResolver.java
index a419d55..5d87ad5 100644
--- a/subprojects/core/src/main/groovy/org/gradle/execution/taskpath/TaskPathResolver.java
+++ b/subprojects/core/src/main/groovy/org/gradle/execution/taskpath/TaskPathResolver.java
@@ -19,9 +19,6 @@ package org.gradle.execution.taskpath;
import org.gradle.api.Project;
import org.gradle.api.internal.project.ProjectInternal;
-/**
- * by Szczepan Faber, created at: 1/29/13
- */
public class TaskPathResolver {
private final ProjectFinderByTaskPath projectFinder;
diff --git a/subprojects/core/src/main/groovy/org/gradle/groovy/scripts/BasicScript.java b/subprojects/core/src/main/groovy/org/gradle/groovy/scripts/BasicScript.java
index 4db2849..19d99ff 100755
--- a/subprojects/core/src/main/groovy/org/gradle/groovy/scripts/BasicScript.java
+++ b/subprojects/core/src/main/groovy/org/gradle/groovy/scripts/BasicScript.java
@@ -19,17 +19,13 @@ package org.gradle.groovy.scripts;
import groovy.lang.MetaClass;
import org.gradle.api.internal.DynamicObject;
import org.gradle.api.internal.DynamicObjectUtil;
-import org.gradle.internal.service.ServiceRegistry;
+import org.gradle.api.internal.ProcessOperations;
import org.gradle.api.internal.file.FileOperations;
+import org.gradle.internal.service.ServiceRegistry;
import org.gradle.logging.StandardOutputCapture;
-import org.gradle.api.internal.ProcessOperations;
import java.util.Map;
-/**
- * @author Hans Dockter
- *
- */
public abstract class BasicScript extends org.gradle.groovy.scripts.Script implements org.gradle.api.Script, FileOperations, ProcessOperations {
private StandardOutputCapture standardOutputCapture;
private Object target;
diff --git a/subprojects/core/src/main/groovy/org/gradle/groovy/scripts/DefaultScript.java b/subprojects/core/src/main/groovy/org/gradle/groovy/scripts/DefaultScript.java
index f911362..e56c636 100755
--- a/subprojects/core/src/main/groovy/org/gradle/groovy/scripts/DefaultScript.java
+++ b/subprojects/core/src/main/groovy/org/gradle/groovy/scripts/DefaultScript.java
@@ -17,6 +17,7 @@
package org.gradle.groovy.scripts;
import groovy.lang.Closure;
+import org.gradle.api.Action;
import org.gradle.api.PathValidation;
import org.gradle.api.Script;
import org.gradle.api.file.ConfigurableFileCollection;
@@ -26,6 +27,7 @@ import org.gradle.api.file.FileTree;
import org.gradle.api.initialization.dsl.ScriptHandler;
import org.gradle.api.internal.ProcessOperations;
import org.gradle.api.internal.file.*;
+import org.gradle.api.internal.file.copy.CopySpecInternal;
import org.gradle.api.internal.plugins.DefaultObjectConfigurationAction;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
@@ -34,6 +36,7 @@ import org.gradle.api.resources.ResourceHandler;
import org.gradle.api.tasks.WorkResult;
import org.gradle.configuration.ScriptPluginFactory;
import org.gradle.internal.nativeplatform.filesystem.FileSystems;
+import org.gradle.internal.reflect.Instantiator;
import org.gradle.internal.service.ServiceRegistry;
import org.gradle.process.ExecResult;
import org.gradle.util.ConfigureUtil;
@@ -54,14 +57,15 @@ public abstract class DefaultScript extends BasicScript {
super.init(target, services);
this.services = services;
loggingManager = services.get(LoggingManager.class);
+ Instantiator instantiator = services.get(Instantiator.class);
if (target instanceof FileOperations) {
fileOperations = (FileOperations) target;
} else if (getScriptSource().getResource().getFile() != null) {
fileOperations = new DefaultFileOperations(
- new BaseDirFileResolver(FileSystems.getDefault(), getScriptSource().getResource().getFile().getParentFile()), null, null
- );
+ new BaseDirFileResolver(FileSystems.getDefault(), getScriptSource().getResource().getFile().getParentFile()), null, null,
+ instantiator);
} else {
- fileOperations = new DefaultFileOperations(new IdentityFileResolver(), null, null);
+ fileOperations = new DefaultFileOperations(new IdentityFileResolver(), null, null, instantiator);
}
processOperations = (ProcessOperations) fileOperations;
@@ -153,10 +157,18 @@ public abstract class DefaultScript extends BasicScript {
return fileOperations.copy(closure);
}
+ public WorkResult sync(Action<? super CopySpec> action) {
+ return fileOperations.sync(action);
+ }
+
public CopySpec copySpec(Closure closure) {
return fileOperations.copySpec(closure);
}
+ public CopySpecInternal copySpec(Action<? super CopySpec> action) {
+ return fileOperations.copySpec(action);
+ }
+
public File mkdir(Object path) {
return fileOperations.mkdir(path);
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/groovy/scripts/DefaultScriptCompilerFactory.java b/subprojects/core/src/main/groovy/org/gradle/groovy/scripts/DefaultScriptCompilerFactory.java
index 62de9c6..fa34188 100644
--- a/subprojects/core/src/main/groovy/org/gradle/groovy/scripts/DefaultScriptCompilerFactory.java
+++ b/subprojects/core/src/main/groovy/org/gradle/groovy/scripts/DefaultScriptCompilerFactory.java
@@ -15,14 +15,11 @@
*/
package org.gradle.groovy.scripts;
-import org.gradle.internal.reflect.DirectInstantiator;
-import org.gradle.internal.reflect.Instantiator;
import org.gradle.groovy.scripts.internal.ScriptClassCompiler;
import org.gradle.groovy.scripts.internal.ScriptRunnerFactory;
+import org.gradle.internal.reflect.DirectInstantiator;
+import org.gradle.internal.reflect.Instantiator;
-/**
- * @author Hans Dockter
- */
public class DefaultScriptCompilerFactory implements ScriptCompilerFactory {
private final ScriptRunnerFactory scriptRunnerFactory;
private final ScriptClassCompiler scriptClassCompiler;
diff --git a/subprojects/core/src/main/groovy/org/gradle/groovy/scripts/ScriptCompilerFactory.java b/subprojects/core/src/main/groovy/org/gradle/groovy/scripts/ScriptCompilerFactory.java
index ea4fb9c..1c5e396 100644
--- a/subprojects/core/src/main/groovy/org/gradle/groovy/scripts/ScriptCompilerFactory.java
+++ b/subprojects/core/src/main/groovy/org/gradle/groovy/scripts/ScriptCompilerFactory.java
@@ -17,8 +17,6 @@ package org.gradle.groovy.scripts;
/**
* A factory for script compilers.
- *
- * @author Hans Dockter
*/
public interface ScriptCompilerFactory {
/**
diff --git a/subprojects/core/src/main/groovy/org/gradle/groovy/scripts/internal/AsmBackedEmptyScriptGenerator.java b/subprojects/core/src/main/groovy/org/gradle/groovy/scripts/internal/AsmBackedEmptyScriptGenerator.java
index b6c2fbb..afbaed7 100644
--- a/subprojects/core/src/main/groovy/org/gradle/groovy/scripts/internal/AsmBackedEmptyScriptGenerator.java
+++ b/subprojects/core/src/main/groovy/org/gradle/groovy/scripts/internal/AsmBackedEmptyScriptGenerator.java
@@ -16,7 +16,8 @@
package org.gradle.groovy.scripts.internal;
import groovy.lang.Script;
-import org.gradle.util.ReflectionUtil;
+import org.gradle.internal.reflect.JavaReflectionUtil;
+import org.gradle.util.JavaMethod;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
@@ -77,8 +78,9 @@ public class AsmBackedEmptyScriptGenerator implements EmptyScriptGenerator {
visitor.visitEnd();
byte[] bytecode = visitor.toByteArray();
- return (Class<T>) ReflectionUtil.invoke(type.getClassLoader(), "defineClass", new Object[]{
- typeName, bytecode, 0, bytecode.length
- });
+ JavaMethod<ClassLoader, Class> method = JavaReflectionUtil.method(ClassLoader.class, Class.class, "defineClass", String.class, byte[].class, int.class, int.class);
+ @SuppressWarnings("unchecked")
+ Class<T> clazz = method.invoke(type.getClassLoader(), typeName, bytecode, 0, bytecode.length);
+ return clazz;
}
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/groovy/scripts/internal/ClasspathScriptTransformer.java b/subprojects/core/src/main/groovy/org/gradle/groovy/scripts/internal/ClasspathScriptTransformer.java
index efe2952..f1cf200 100644
--- a/subprojects/core/src/main/groovy/org/gradle/groovy/scripts/internal/ClasspathScriptTransformer.java
+++ b/subprojects/core/src/main/groovy/org/gradle/groovy/scripts/internal/ClasspathScriptTransformer.java
@@ -41,7 +41,7 @@ import java.util.Map;
/**
* The classpath script transformer uses Groovy's AST support to implement a two-phase
* compilation of a script into a "class path script" and an "everything else script".
- * The classpath script can then be executed and it's results taken into account (in
+ * The classpath script can then be executed and its results taken into account (in
* particular, to update the classpath) before the remainder of the script is executed.
*/
public abstract class ClasspathScriptTransformer extends AbstractScriptTransformer {
@@ -174,4 +174,4 @@ public abstract class ClasspathScriptTransformer extends AbstractScriptTransform
}
};
}
-}
\ No newline at end of file
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/groovy/scripts/internal/DefaultScriptCompilationHandler.java b/subprojects/core/src/main/groovy/org/gradle/groovy/scripts/internal/DefaultScriptCompilationHandler.java
index 3182a27..3b143e6 100644
--- a/subprojects/core/src/main/groovy/org/gradle/groovy/scripts/internal/DefaultScriptCompilationHandler.java
+++ b/subprojects/core/src/main/groovy/org/gradle/groovy/scripts/internal/DefaultScriptCompilationHandler.java
@@ -44,9 +44,6 @@ import java.net.URLClassLoader;
import java.security.CodeSource;
import java.util.List;
-/**
- * @author Hans Dockter
- */
public class DefaultScriptCompilationHandler implements ScriptCompilationHandler {
private Logger logger = LoggerFactory.getLogger(DefaultScriptCompilationHandler.class);
private static final String EMPTY_SCRIPT_MARKER_FILE_NAME = "emptyScript.txt";
diff --git a/subprojects/core/src/main/groovy/org/gradle/groovy/scripts/internal/ScriptCompilationHandler.java b/subprojects/core/src/main/groovy/org/gradle/groovy/scripts/internal/ScriptCompilationHandler.java
index afd9584..3642cfc 100644
--- a/subprojects/core/src/main/groovy/org/gradle/groovy/scripts/internal/ScriptCompilationHandler.java
+++ b/subprojects/core/src/main/groovy/org/gradle/groovy/scripts/internal/ScriptCompilationHandler.java
@@ -21,9 +21,6 @@ import org.gradle.groovy.scripts.Transformer;
import java.io.File;
-/**
- * @author Hans Dockter
- */
public interface ScriptCompilationHandler {
void compileToDir(ScriptSource source, ClassLoader classLoader, File scriptCacheDir, Transformer transformer,
Class<? extends Script> scriptBaseClass);
diff --git a/subprojects/core/src/main/groovy/org/gradle/initialization/AbstractProjectSpec.java b/subprojects/core/src/main/groovy/org/gradle/initialization/AbstractProjectSpec.java
index ba20320..adf92f9 100644
--- a/subprojects/core/src/main/groovy/org/gradle/initialization/AbstractProjectSpec.java
+++ b/subprojects/core/src/main/groovy/org/gradle/initialization/AbstractProjectSpec.java
@@ -15,7 +15,7 @@
*/
package org.gradle.initialization;
-import org.gradle.api.internal.project.IProjectRegistry;
+import org.gradle.api.internal.project.ProjectRegistry;
import org.gradle.api.internal.project.ProjectIdentifier;
import org.gradle.api.InvalidUserDataException;
@@ -23,7 +23,7 @@ import java.util.List;
import java.util.ArrayList;
public abstract class AbstractProjectSpec implements ProjectSpec {
- public boolean containsProject(IProjectRegistry<?> registry) {
+ public boolean containsProject(ProjectRegistry<?> registry) {
checkPreconditions(registry);
for (ProjectIdentifier project : registry.getAllProjects()) {
if (select(project)) {
@@ -33,7 +33,7 @@ public abstract class AbstractProjectSpec implements ProjectSpec {
return false;
}
- public <T extends ProjectIdentifier> T selectProject(IProjectRegistry<? extends T> registry) {
+ public <T extends ProjectIdentifier> T selectProject(ProjectRegistry<? extends T> registry) {
checkPreconditions(registry);
List<T> matches = new ArrayList<T>();
for (T project : registry.getAllProjects()) {
@@ -50,7 +50,7 @@ public abstract class AbstractProjectSpec implements ProjectSpec {
return matches.get(0);
}
- protected void checkPreconditions(IProjectRegistry<?> registry) {
+ protected void checkPreconditions(ProjectRegistry<?> registry) {
}
protected abstract String formatMultipleMatchesMessage(Iterable<? extends ProjectIdentifier> matches);
diff --git a/subprojects/core/src/main/groovy/org/gradle/initialization/BaseSettings.java b/subprojects/core/src/main/groovy/org/gradle/initialization/BaseSettings.java
index 1aa27da..6b3e273 100644
--- a/subprojects/core/src/main/groovy/org/gradle/initialization/BaseSettings.java
+++ b/subprojects/core/src/main/groovy/org/gradle/initialization/BaseSettings.java
@@ -21,44 +21,54 @@ import org.gradle.api.initialization.ProjectDescriptor;
import org.gradle.api.initialization.Settings;
import org.gradle.api.internal.GradleInternal;
import org.gradle.api.internal.SettingsInternal;
-import org.gradle.api.internal.project.IProjectRegistry;
+import org.gradle.api.internal.file.FileResolver;
+import org.gradle.api.internal.project.AbstractPluginAware;
+import org.gradle.api.internal.project.ProjectRegistry;
+import org.gradle.internal.service.scopes.ServiceRegistryFactory;
+import org.gradle.api.plugins.PluginContainer;
+import org.gradle.configuration.ScriptPluginFactory;
import org.gradle.groovy.scripts.ScriptSource;
import java.io.File;
-import java.net.URLClassLoader;
-/**
- * @author Hans Dockter
- */
-public class BaseSettings implements SettingsInternal {
+public class BaseSettings extends AbstractPluginAware implements SettingsInternal {
public static final String DEFAULT_BUILD_SRC_DIR = "buildSrc";
private ScriptSource settingsScript;
private StartParameter startParameter;
- private URLClassLoader classloader;
+ private ClassLoader classloader;
private File settingsDir;
private DefaultProjectDescriptor rootProjectDescriptor;
private GradleInternal gradle;
- private IProjectDescriptorRegistry projectDescriptorRegistry;
- protected BaseSettings() {
- }
+ private ProjectDescriptorRegistry projectDescriptorRegistry;
+
+ private ServiceRegistryFactory services;
+
+ private PluginContainer plugins;
- public BaseSettings(GradleInternal gradle,
- IProjectDescriptorRegistry projectDescriptorRegistry,
- URLClassLoader classloader, File settingsDir, ScriptSource settingsScript,
+ private FileResolver fileResolver;
+
+ private ScriptPluginFactory scriptPluginFactory;
+
+ public BaseSettings(ServiceRegistryFactory serviceRegistryFactory, GradleInternal gradle,
+ ClassLoader classloader, File settingsDir, ScriptSource settingsScript,
StartParameter startParameter) {
this.gradle = gradle;
- this.projectDescriptorRegistry = projectDescriptorRegistry;
this.settingsDir = settingsDir;
this.settingsScript = settingsScript;
this.startParameter = startParameter;
this.classloader = classloader;
+ this.services = serviceRegistryFactory.createFor(this);
+ this.plugins = services.get(PluginContainer.class);
+ this.fileResolver = services.get(FileResolver.class);
+ this.scriptPluginFactory = services.get(ScriptPluginFactory.class);
+ this.projectDescriptorRegistry = services.get(ProjectDescriptorRegistry.class);
rootProjectDescriptor = createProjectDescriptor(null, settingsDir.getName(), settingsDir);
}
@@ -76,7 +86,7 @@ public class BaseSettings implements SettingsInternal {
}
public DefaultProjectDescriptor createProjectDescriptor(DefaultProjectDescriptor parent, String name, File dir) {
- return new DefaultProjectDescriptor(parent, name, dir, projectDescriptorRegistry);
+ return new DefaultProjectDescriptor(parent, name, dir, projectDescriptorRegistry, fileResolver);
}
public DefaultProjectDescriptor findProject(String path) {
@@ -134,7 +144,7 @@ public class BaseSettings implements SettingsInternal {
return projectPath;
}
- public URLClassLoader getClassLoader() {
+ public ClassLoader getClassLoader() {
return classloader;
}
@@ -174,15 +184,30 @@ public class BaseSettings implements SettingsInternal {
this.settingsScript = settingsScript;
}
- public IProjectDescriptorRegistry getProjectDescriptorRegistry() {
+ public ProjectDescriptorRegistry getProjectDescriptorRegistry() {
return projectDescriptorRegistry;
}
- public void setProjectDescriptorRegistry(IProjectDescriptorRegistry projectDescriptorRegistry) {
+ public void setProjectDescriptorRegistry(ProjectDescriptorRegistry projectDescriptorRegistry) {
this.projectDescriptorRegistry = projectDescriptorRegistry;
}
- public IProjectRegistry<DefaultProjectDescriptor> getProjectRegistry() {
+ public ProjectRegistry<DefaultProjectDescriptor> getProjectRegistry() {
return projectDescriptorRegistry;
}
+
+ public PluginContainer getPlugins() {
+ return plugins;
+ }
+
+
+ @Override
+ protected FileResolver getFileResolver() {
+ return fileResolver;
+ }
+
+ @Override
+ protected ScriptPluginFactory getScriptPluginFactory() {
+ return scriptPluginFactory;
+ }
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/initialization/BuildAction.java b/subprojects/core/src/main/groovy/org/gradle/initialization/BuildAction.java
new file mode 100644
index 0000000..258e0ee
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/initialization/BuildAction.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.initialization;
+
+/**
+ * An object that performs some action with a {@link BuildController} and produces a “result” object (e.g. the output).
+ * <p>
+ * Implementations of this are typically composed to bootstrap a build in a certain environment.
+ * <p>
+ */
+public interface BuildAction<T> {
+ /**
+ * Executes the action with the given controller.
+ * <p>
+ * The state of the build is not defined as part of this contract, it is highly context specific.
+ */
+ T run(BuildController buildController);
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/initialization/BuildController.java b/subprojects/core/src/main/groovy/org/gradle/initialization/BuildController.java
new file mode 100644
index 0000000..f74f6ea
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/initialization/BuildController.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.initialization;
+
+import org.gradle.GradleLauncher;
+import org.gradle.StartParameter;
+
+/**
+ * This is intended to eventually replace {@link GradleLauncher} internally. It's pretty rough at the moment.
+ */
+public interface BuildController {
+ /**
+ * Specifies the start parameter to use to run the build. Cannot be used after the launcher has been created.
+ */
+ void setStartParameter(StartParameter startParameter);
+
+ /**
+ * Returns the launcher to use to run the build.
+ */
+ GradleLauncher getLauncher();
+
+ /**
+ * Runs the build.
+ */
+ void run();
+
+ /**
+ * Configures the build but does not run any tasks.
+ */
+ void configure();
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/initialization/BuildFileProjectSpec.java b/subprojects/core/src/main/groovy/org/gradle/initialization/BuildFileProjectSpec.java
index e291545..3058929 100644
--- a/subprojects/core/src/main/groovy/org/gradle/initialization/BuildFileProjectSpec.java
+++ b/subprojects/core/src/main/groovy/org/gradle/initialization/BuildFileProjectSpec.java
@@ -18,7 +18,7 @@ package org.gradle.initialization;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.gradle.api.internal.project.ProjectIdentifier;
-import org.gradle.api.internal.project.IProjectRegistry;
+import org.gradle.api.internal.project.ProjectRegistry;
import org.gradle.api.InvalidUserDataException;
import java.io.File;
@@ -48,7 +48,7 @@ public class BuildFileProjectSpec extends AbstractProjectSpec implements Seriali
}
@Override
- protected void checkPreconditions(IProjectRegistry<?> registry) {
+ protected void checkPreconditions(ProjectRegistry<?> registry) {
if (!buildFile.exists()) {
throw new InvalidUserDataException(String.format("Build file '%s' does not exist.", buildFile));
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/initialization/BuildLayoutParameters.java b/subprojects/core/src/main/groovy/org/gradle/initialization/BuildLayoutParameters.java
index 9f32a3c..a8d0d81 100644
--- a/subprojects/core/src/main/groovy/org/gradle/initialization/BuildLayoutParameters.java
+++ b/subprojects/core/src/main/groovy/org/gradle/initialization/BuildLayoutParameters.java
@@ -16,17 +16,30 @@
package org.gradle.initialization;
+import org.gradle.StartParameter;
+import org.gradle.internal.SystemProperties;
+
import java.io.File;
-/**
- * by Szczepan Faber, created at: 2/18/13
- */
+import static org.gradle.util.GFileUtils.canonicalise;
+
public class BuildLayoutParameters {
- private Boolean searchUpwards;
- private File projectDir;
+ private boolean searchUpwards = true;
+ private File projectDir = canonicalise(SystemProperties.getCurrentDir());
private File gradleUserHomeDir;
+ public BuildLayoutParameters() {
+ String gradleUserHome = System.getProperty(StartParameter.GRADLE_USER_HOME_PROPERTY_KEY);
+ if (gradleUserHome == null) {
+ gradleUserHome = System.getenv("GRADLE_USER_HOME");
+ if (gradleUserHome == null) {
+ gradleUserHome = StartParameter.DEFAULT_GRADLE_USER_HOME.getAbsolutePath();
+ }
+ }
+ gradleUserHomeDir = canonicalise(new File(gradleUserHome));
+ }
+
public BuildLayoutParameters setSearchUpwards(boolean searchUpwards) {
this.searchUpwards = searchUpwards;
return this;
@@ -50,7 +63,7 @@ public class BuildLayoutParameters {
return gradleUserHomeDir;
}
- public Boolean getSearchUpwards() {
+ public boolean getSearchUpwards() {
return searchUpwards;
}
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/initialization/BuildSourceBuilder.java b/subprojects/core/src/main/groovy/org/gradle/initialization/BuildSourceBuilder.java
deleted file mode 100644
index d118ae6..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/initialization/BuildSourceBuilder.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.initialization;
-
-import org.gradle.BuildAdapter;
-import org.gradle.GradleLauncher;
-import org.gradle.StartParameter;
-import org.gradle.api.UncheckedIOException;
-import org.gradle.api.internal.GradleInternal;
-import org.gradle.api.internal.plugins.EmbeddableJavaProject;
-import org.gradle.api.invocation.Gradle;
-import org.gradle.cache.CacheBuilder;
-import org.gradle.cache.CacheRepository;
-import org.gradle.cache.PersistentCache;
-import org.gradle.cache.internal.FileLockManager;
-import org.gradle.internal.Factory;
-import org.gradle.internal.classpath.ClassPath;
-import org.gradle.internal.classpath.DefaultClassPath;
-import org.gradle.util.WrapUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.Collection;
-import java.util.Set;
-
-/**
- * @author Hans Dockter
- */
-public class BuildSourceBuilder {
- private static final Logger LOGGER = LoggerFactory.getLogger(BuildSourceBuilder.class);
-
- private final GradleLauncherFactory gradleLauncherFactory;
- private final ClassLoaderRegistry classLoaderRegistry;
- private final CacheRepository cacheRepository;
-
- private static final String DEFAULT_BUILD_SOURCE_SCRIPT_RESOURCE = "defaultBuildSourceScript.txt";
-
- public BuildSourceBuilder(GradleLauncherFactory gradleLauncherFactory, ClassLoaderRegistry classLoaderRegistry, CacheRepository cacheRepository) {
- this.gradleLauncherFactory = gradleLauncherFactory;
- this.classLoaderRegistry = classLoaderRegistry;
- this.cacheRepository = cacheRepository;
- }
-
- public URLClassLoader buildAndCreateClassLoader(StartParameter startParameter) {
- ClassPath classpath = createBuildSourceClasspath(startParameter);
- return new URLClassLoader(classpath.getAsURLArray(), classLoaderRegistry.getRootClassLoader());
- }
-
- private ClassPath createBuildSourceClasspath(StartParameter startParameter) {
- assert startParameter.getCurrentDir() != null && startParameter.getBuildFile() == null;
-
- LOGGER.debug("Starting to build the build sources.");
- if (!startParameter.getCurrentDir().isDirectory()) {
- LOGGER.debug("Gradle source dir does not exist. We leave.");
- return new DefaultClassPath();
- }
- LOGGER.info("================================================" + " Start building buildSrc");
-
- // If we were not the most recent version of Gradle to build the buildSrc dir, then do a clean build
- // Otherwise, just to a regular build
- final PersistentCache buildSrcCache = cacheRepository.
- cache("buildSrc").
- withLockMode(FileLockManager.LockMode.None).
- forObject(startParameter.getCurrentDir()).
- withVersionStrategy(CacheBuilder.VersionStrategy.SharedCacheInvalidateOnVersionChange).
- open();
-
- GradleLauncher gradleLauncher = buildGradleLauncher(startParameter);
- return buildSrcCache.useCache("rebuild buildSrc", new BuildSrcUpdateFactory(buildSrcCache, gradleLauncher));
- }
-
- private GradleLauncher buildGradleLauncher(StartParameter startParameter) {
- final StartParameter startParameterArg = startParameter.newInstance();
- startParameterArg.setProjectProperties(startParameter.getProjectProperties());
- startParameterArg.setSearchUpwards(false);
- startParameterArg.setProfile(startParameter.isProfile());
- return gradleLauncherFactory.newInstance(startParameterArg);
- }
-
- static URL getDefaultScript() {
- return BuildSourceBuilder.class.getResource(DEFAULT_BUILD_SOURCE_SCRIPT_RESOURCE);
- }
-
- private static class BuildSrcBuildListener extends BuildAdapter implements ModelConfigurationListener {
- private EmbeddableJavaProject projectInfo;
- private Set<File> classpath;
- private final boolean rebuild;
-
- public BuildSrcBuildListener(boolean rebuild) {
- this.rebuild = rebuild;
- }
-
- @Override
- public void projectsLoaded(Gradle gradle) {
- gradle.getRootProject().apply(WrapUtil.toMap("from", getDefaultScript()));
- }
-
- public Collection<File> getRuntimeClasspath() {
- return classpath;
- }
-
- public void onConfigure(GradleInternal gradle) {
- projectInfo = gradle.getRootProject().getConvention().getPlugin(EmbeddableJavaProject.class);
- gradle.getStartParameter().setTaskNames(rebuild ? projectInfo.getRebuildTasks() : projectInfo.getBuildTasks());
- classpath = projectInfo.getRuntimeClasspath().getFiles();
- }
- }
-
- private static class BuildSrcUpdateFactory implements Factory<DefaultClassPath> {
- private final PersistentCache cache;
- private final GradleLauncher gradleLauncher;
-
- public BuildSrcUpdateFactory(PersistentCache cache, GradleLauncher gradleLauncher) {
- this.cache = cache;
- this.gradleLauncher = gradleLauncher;
- }
-
- public DefaultClassPath create() {
- File markerFile = new File(cache.getBaseDir(), "built.bin");
- final boolean rebuild = !markerFile.exists();
-
- BuildSrcBuildListener listener = new BuildSrcBuildListener(rebuild);
- gradleLauncher.addListener(listener);
- gradleLauncher.run().rethrowFailure();
-
- Collection<File> classpath = listener.getRuntimeClasspath();
- LOGGER.debug("Gradle source classpath is: {}", classpath);
- LOGGER.info("================================================" + " Finished building buildSrc");
- try {
- markerFile.createNewFile();
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- return new DefaultClassPath(classpath);
- }
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/initialization/ClassLoaderRegistry.java b/subprojects/core/src/main/groovy/org/gradle/initialization/ClassLoaderRegistry.java
index bf1ca5a..e638ee6 100755
--- a/subprojects/core/src/main/groovy/org/gradle/initialization/ClassLoaderRegistry.java
+++ b/subprojects/core/src/main/groovy/org/gradle/initialization/ClassLoaderRegistry.java
@@ -15,13 +15,16 @@
*/
package org.gradle.initialization;
-import org.gradle.util.MultiParentClassLoader;
-
public interface ClassLoaderRegistry {
/**
- * Returns the root class loader shared by all builds.
+ * Returns the root class loader shared by all builds. This class loader exposes the Gradle API and built-in plugins.
+ */
+ ClassLoader getGradleApiClassLoader();
+
+ /**
+ * Returns the class loader for the Gradle runtime.
*/
- ClassLoader getRootClassLoader();
+ ClassLoader getRuntimeClassLoader();
/**
* Returns the class loader for the coreImpl project.
@@ -32,9 +35,4 @@ public interface ClassLoaderRegistry {
* Returns the class loader for the plugins.
*/
ClassLoader getPluginsClassLoader();
-
- /**
- * Creates the script class loader for a build.
- */
- MultiParentClassLoader createScriptClassLoader();
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/initialization/DefaultClassLoaderRegistry.java b/subprojects/core/src/main/groovy/org/gradle/initialization/DefaultClassLoaderRegistry.java
index eac333d..3f3ab98 100755
--- a/subprojects/core/src/main/groovy/org/gradle/initialization/DefaultClassLoaderRegistry.java
+++ b/subprojects/core/src/main/groovy/org/gradle/initialization/DefaultClassLoaderRegistry.java
@@ -17,10 +17,10 @@
package org.gradle.initialization;
import org.gradle.api.internal.ClassPathRegistry;
+import org.gradle.internal.classloader.*;
import org.gradle.internal.classpath.ClassPath;
import org.gradle.internal.classpath.DefaultClassPath;
import org.gradle.internal.jvm.Jvm;
-import org.gradle.util.*;
import java.io.File;
import java.net.URLClassLoader;
@@ -46,7 +46,7 @@ public class DefaultClassLoaderRegistry implements ClassLoaderRegistry {
// Add in libs for plugins
ClassPath pluginsClassPath = classPathRegistry.getClassPath("GRADLE_PLUGINS");
- MultiParentClassLoader pluginsImports = new MultiParentClassLoader(runtimeClassLoader, coreImplClassLoader);
+ ClassLoader pluginsImports = new CachingClassLoader(new MultiParentClassLoader(runtimeClassLoader, coreImplClassLoader));
pluginsClassLoader = new MutableURLClassLoader(pluginsImports, pluginsClassPath);
rootClassLoader = classLoaderFactory.createFilteringClassLoader(pluginsClassLoader);
@@ -63,7 +63,11 @@ public class DefaultClassLoaderRegistry implements ClassLoaderRegistry {
rootClassLoader.allowPackage("javax.inject");
}
- public ClassLoader getRootClassLoader() {
+ public ClassLoader getRuntimeClassLoader() {
+ return getClass().getClassLoader();
+ }
+
+ public ClassLoader getGradleApiClassLoader() {
return rootClassLoader;
}
@@ -74,8 +78,4 @@ public class DefaultClassLoaderRegistry implements ClassLoaderRegistry {
public ClassLoader getPluginsClassLoader() {
return pluginsClassLoader;
}
-
- public MultiParentClassLoader createScriptClassLoader() {
- return new MultiParentClassLoader(rootClassLoader);
- }
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/initialization/DefaultCommandLineConverter.java b/subprojects/core/src/main/groovy/org/gradle/initialization/DefaultCommandLineConverter.java
index 0be7a9a..5c5d88a 100644
--- a/subprojects/core/src/main/groovy/org/gradle/initialization/DefaultCommandLineConverter.java
+++ b/subprojects/core/src/main/groovy/org/gradle/initialization/DefaultCommandLineConverter.java
@@ -28,9 +28,8 @@ import org.gradle.logging.internal.LoggingCommandLineConverter;
import java.util.Map;
-/**
- * @author Hans Dockter
- */
+import static org.gradle.StartParameter.GRADLE_USER_HOME_PROPERTY_KEY;
+
public class DefaultCommandLineConverter extends AbstractCommandLineConverter<StartParameter> {
private static final String NO_PROJECT_DEPENDENCY_REBUILD = "a";
private static final String BUILD_FILE = "b";
@@ -103,17 +102,13 @@ public class DefaultCommandLineConverter extends AbstractCommandLineConverter<St
Map<String, String> projectProperties = projectPropertiesCommandLineConverter.convert(options);
startParameter.getProjectProperties().putAll(projectProperties);
- BuildLayoutParameters layout = new BuildLayoutParameters().setProjectDir(startParameter.getCurrentDir());
+ BuildLayoutParameters layout = new BuildLayoutParameters()
+ .setGradleUserHomeDir(startParameter.getGradleUserHomeDir())
+ .setProjectDir(startParameter.getCurrentDir());
layoutCommandLineConverter.convert(options, layout);
- if (layout.getGradleUserHomeDir() != null) {
- startParameter.setGradleUserHomeDir(layout.getGradleUserHomeDir());
- }
- if (layout.getProjectDir() != null) {
- startParameter.setProjectDir(layout.getProjectDir());
- }
- if (layout.getSearchUpwards() != null) {
- startParameter.setSearchUpwards(layout.getSearchUpwards());
- }
+ startParameter.setGradleUserHomeDir(layout.getGradleUserHomeDir());
+ startParameter.setProjectDir(layout.getProjectDir());
+ startParameter.setSearchUpwards(layout.getSearchUpwards());
if (options.hasOption(BUILD_FILE)) {
startParameter.setBuildFile(resolver.resolve(options.option(BUILD_FILE).getValue()));
@@ -208,9 +203,16 @@ public class DefaultCommandLineConverter extends AbstractCommandLineConverter<St
void convertCommandLineSystemProperties(Map<String, String> systemProperties, StartParameter startParameter, FileResolver resolver) {
startParameter.getSystemPropertiesArgs().putAll(systemProperties);
- String gradleUserHomeProp = "gradle.user.home";
- if (systemProperties.containsKey(gradleUserHomeProp)) {
- startParameter.setGradleUserHomeDir(resolver.resolve(systemProperties.get(gradleUserHomeProp)));
+ if (systemProperties.containsKey(GRADLE_USER_HOME_PROPERTY_KEY)) {
+ startParameter.setGradleUserHomeDir(resolver.resolve(systemProperties.get(GRADLE_USER_HOME_PROPERTY_KEY)));
}
}
+
+ public LayoutCommandLineConverter getLayoutConverter() {
+ return layoutCommandLineConverter;
+ }
+
+ public SystemPropertiesCommandLineConverter getSystemPropertiesConverter() {
+ return systemPropertiesCommandLineConverter;
+ }
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/initialization/DefaultGradleLauncher.java b/subprojects/core/src/main/groovy/org/gradle/initialization/DefaultGradleLauncher.java
index c853773..c12f534 100644
--- a/subprojects/core/src/main/groovy/org/gradle/initialization/DefaultGradleLauncher.java
+++ b/subprojects/core/src/main/groovy/org/gradle/initialization/DefaultGradleLauncher.java
@@ -46,7 +46,7 @@ public class DefaultGradleLauncher extends GradleLauncher {
/**
* Creates a new instance. Don't call this directly, use {@link #newInstance(org.gradle.StartParameter)} or {@link
- * #newInstance(String...)} instead. Note that this method is package-protected to discourage it's direct use.
+ * #newInstance(String...)} instead.
*/
public DefaultGradleLauncher(GradleInternal gradle, InitScriptHandler initScriptHandler, SettingsHandler settingsHandler,
BuildLoader buildLoader, BuildConfigurer buildConfigurer, BuildListener buildListener,
diff --git a/subprojects/core/src/main/groovy/org/gradle/initialization/DefaultGradleLauncherFactory.java b/subprojects/core/src/main/groovy/org/gradle/initialization/DefaultGradleLauncherFactory.java
index 088fb61..e12e63c 100644
--- a/subprojects/core/src/main/groovy/org/gradle/initialization/DefaultGradleLauncherFactory.java
+++ b/subprojects/core/src/main/groovy/org/gradle/initialization/DefaultGradleLauncherFactory.java
@@ -19,15 +19,16 @@ package org.gradle.initialization;
import org.gradle.*;
import org.gradle.api.internal.ExceptionAnalyser;
import org.gradle.api.internal.GradleInternal;
-import org.gradle.api.internal.project.GlobalServicesRegistry;
-import org.gradle.api.internal.project.TopLevelBuildServiceRegistry;
+import org.gradle.internal.service.scopes.BuildScopeServices;
import org.gradle.api.logging.Logging;
import org.gradle.api.logging.StandardOutputListener;
import org.gradle.cache.CacheRepository;
import org.gradle.cli.CommandLineConverter;
import org.gradle.configuration.BuildConfigurer;
import org.gradle.execution.BuildExecuter;
+import org.gradle.initialization.buildsrc.BuildSourceBuilder;
import org.gradle.initialization.layout.BuildLayoutFactory;
+import org.gradle.internal.featurelifecycle.ScriptUsageLocationReporter;
import org.gradle.internal.reflect.Instantiator;
import org.gradle.internal.service.ServiceRegistry;
import org.gradle.invocation.DefaultGradle;
@@ -37,26 +38,16 @@ import org.gradle.logging.ProgressLoggerFactory;
import org.gradle.logging.StyledTextOutputFactory;
import org.gradle.profile.ProfileEventAdapter;
import org.gradle.profile.ReportGeneratingProfileListener;
+import org.gradle.util.DeprecationLogger;
import java.util.Arrays;
-/**
- * @author Hans Dockter
- */
public class DefaultGradleLauncherFactory implements GradleLauncherFactory {
private final ServiceRegistry sharedServices;
private final NestedBuildTracker tracker;
private CommandLineConverter<StartParameter> commandLineConverter;
- public DefaultGradleLauncherFactory(ServiceRegistry loggingServices) {
- this(new GlobalServicesRegistry(loggingServices));
- }
-
- public DefaultGradleLauncherFactory() {
- this(new GlobalServicesRegistry());
- }
-
- private DefaultGradleLauncherFactory(GlobalServicesRegistry globalServices) {
+ public DefaultGradleLauncherFactory(ServiceRegistry globalServices) {
sharedServices = globalServices;
tracker = new NestedBuildTracker();
@@ -100,7 +91,7 @@ public class DefaultGradleLauncherFactory implements GradleLauncherFactory {
}
private DefaultGradleLauncher doNewInstance(StartParameter startParameter, BuildRequestMetaData requestMetaData) {
- final TopLevelBuildServiceRegistry serviceRegistry = new TopLevelBuildServiceRegistry(sharedServices, startParameter);
+ final BuildScopeServices serviceRegistry = new BuildScopeServices(sharedServices, startParameter);
serviceRegistry.add(BuildRequestMetaData.class, requestMetaData);
serviceRegistry.add(BuildClientMetaData.class, requestMetaData.getClient());
ListenerManager listenerManager = serviceRegistry.get(ListenerManager.class);
@@ -122,6 +113,9 @@ public class DefaultGradleLauncherFactory implements GradleLauncherFactory {
if (startParameter.isProfile()) {
listenerManager.addListener(new ReportGeneratingProfileListener());
}
+ ScriptUsageLocationReporter usageLocationReporter = new ScriptUsageLocationReporter();
+ listenerManager.addListener(usageLocationReporter);
+ DeprecationLogger.useLocationReporter(usageLocationReporter);
GradleInternal gradle = serviceRegistry.get(Instantiator.class).newInstance(DefaultGradle.class, tracker.getCurrentBuild(), startParameter, serviceRegistry);
return new DefaultGradleLauncher(
@@ -151,9 +145,9 @@ public class DefaultGradleLauncherFactory implements GradleLauncherFactory {
}
private static class BuildCleanupListener extends BuildAdapter {
- private final TopLevelBuildServiceRegistry services;
+ private final BuildScopeServices services;
- private BuildCleanupListener(TopLevelBuildServiceRegistry services) {
+ private BuildCleanupListener(BuildScopeServices services) {
this.services = services;
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/initialization/DefaultGradlePropertiesLoader.java b/subprojects/core/src/main/groovy/org/gradle/initialization/DefaultGradlePropertiesLoader.java
index bf360d8..62298a2 100644
--- a/subprojects/core/src/main/groovy/org/gradle/initialization/DefaultGradlePropertiesLoader.java
+++ b/subprojects/core/src/main/groovy/org/gradle/initialization/DefaultGradlePropertiesLoader.java
@@ -26,9 +26,6 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
-/**
- * @author Hans Dockter
- */
public class DefaultGradlePropertiesLoader implements IGradlePropertiesLoader {
private static Logger logger = LoggerFactory.getLogger(DefaultGradlePropertiesLoader.class);
diff --git a/subprojects/core/src/main/groovy/org/gradle/initialization/DefaultProjectDescriptor.java b/subprojects/core/src/main/groovy/org/gradle/initialization/DefaultProjectDescriptor.java
index 1a33d47..549f555 100644
--- a/subprojects/core/src/main/groovy/org/gradle/initialization/DefaultProjectDescriptor.java
+++ b/subprojects/core/src/main/groovy/org/gradle/initialization/DefaultProjectDescriptor.java
@@ -17,6 +17,7 @@ package org.gradle.initialization;
import org.gradle.api.Project;
import org.gradle.api.initialization.ProjectDescriptor;
+import org.gradle.api.internal.file.FileResolver;
import org.gradle.api.internal.project.ProjectIdentifier;
import org.gradle.util.GFileUtils;
import org.gradle.util.Path;
@@ -25,22 +26,21 @@ import java.io.File;
import java.util.LinkedHashSet;
import java.util.Set;
-/**
- * @author Hans Dockter
- */
public class DefaultProjectDescriptor implements ProjectDescriptor, ProjectIdentifier {
private String name;
+ private final FileResolver fileResolver;
private File dir;
private DefaultProjectDescriptor parent;
private Set<ProjectDescriptor> children = new LinkedHashSet<ProjectDescriptor>();
- private IProjectDescriptorRegistry projectDescriptorRegistry;
+ private ProjectDescriptorRegistry projectDescriptorRegistry;
private Path path;
private String buildFileName = Project.DEFAULT_BUILD_FILE;
public DefaultProjectDescriptor(DefaultProjectDescriptor parent, String name, File dir,
- IProjectDescriptorRegistry projectDescriptorRegistry) {
+ ProjectDescriptorRegistry projectDescriptorRegistry, FileResolver fileResolver) {
this.parent = parent;
this.name = name;
+ this.fileResolver = fileResolver;
this.dir = GFileUtils.canonicalise(dir);
this.projectDescriptorRegistry = projectDescriptorRegistry;
this.path = path(name);
@@ -80,7 +80,7 @@ public class DefaultProjectDescriptor implements ProjectDescriptor, ProjectIdent
}
public void setProjectDir(File dir) {
- this.dir = GFileUtils.canonicalise(dir);
+ this.dir = fileResolver.resolve(dir);
}
public DefaultProjectDescriptor getParent() {
@@ -115,11 +115,11 @@ public class DefaultProjectDescriptor implements ProjectDescriptor, ProjectIdent
return GFileUtils.canonicalise(new File(dir, buildFileName));
}
- public IProjectDescriptorRegistry getProjectDescriptorRegistry() {
+ public ProjectDescriptorRegistry getProjectDescriptorRegistry() {
return projectDescriptorRegistry;
}
- public void setProjectDescriptorRegistry(IProjectDescriptorRegistry projectDescriptorRegistry) {
+ public void setProjectDescriptorRegistry(ProjectDescriptorRegistry projectDescriptorRegistry) {
this.projectDescriptorRegistry = projectDescriptorRegistry;
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/initialization/DefaultProjectDescriptorRegistry.java b/subprojects/core/src/main/groovy/org/gradle/initialization/DefaultProjectDescriptorRegistry.java
index 148e100..cd3f64a 100644
--- a/subprojects/core/src/main/groovy/org/gradle/initialization/DefaultProjectDescriptorRegistry.java
+++ b/subprojects/core/src/main/groovy/org/gradle/initialization/DefaultProjectDescriptorRegistry.java
@@ -18,10 +18,7 @@ package org.gradle.initialization;
import org.gradle.api.internal.project.DefaultProjectRegistry;
import org.gradle.util.Path;
-/**
- * @author Hans Dockter
- */
-public class DefaultProjectDescriptorRegistry extends DefaultProjectRegistry<DefaultProjectDescriptor> implements IProjectDescriptorRegistry {
+public class DefaultProjectDescriptorRegistry extends DefaultProjectRegistry<DefaultProjectDescriptor> implements ProjectDescriptorRegistry {
public void changeDescriptorPath(Path oldPath, Path newPath) {
DefaultProjectDescriptor projectDescriptor = removeProject(oldPath.toString());
diff --git a/subprojects/core/src/main/groovy/org/gradle/initialization/DefaultProjectSpec.java b/subprojects/core/src/main/groovy/org/gradle/initialization/DefaultProjectSpec.java
index 1996eb0..56c77de 100644
--- a/subprojects/core/src/main/groovy/org/gradle/initialization/DefaultProjectSpec.java
+++ b/subprojects/core/src/main/groovy/org/gradle/initialization/DefaultProjectSpec.java
@@ -15,7 +15,7 @@
*/
package org.gradle.initialization;
-import org.gradle.api.internal.project.IProjectRegistry;
+import org.gradle.api.internal.project.ProjectRegistry;
import java.io.File;
@@ -25,7 +25,7 @@ public class DefaultProjectSpec extends ProjectDirectoryProjectSpec {
}
@Override
- protected void checkPreconditions(IProjectRegistry<?> registry) {
+ protected void checkPreconditions(ProjectRegistry<?> registry) {
// Ignore
}
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/initialization/DefaultSettings.groovy b/subprojects/core/src/main/groovy/org/gradle/initialization/DefaultSettings.groovy
index b5aedfe..64d2da4 100644
--- a/subprojects/core/src/main/groovy/org/gradle/initialization/DefaultSettings.groovy
+++ b/subprojects/core/src/main/groovy/org/gradle/initialization/DefaultSettings.groovy
@@ -18,19 +18,16 @@ package org.gradle.initialization
import org.gradle.StartParameter
import org.gradle.api.internal.GradleInternal
+import org.gradle.internal.service.scopes.ServiceRegistryFactory
import org.gradle.groovy.scripts.ScriptSource
-/**
- * @author Hans Dockter
- */
public class DefaultSettings extends BaseSettings {
- public DefaultSettings() {}
- DefaultSettings(GradleInternal gradle,
- IProjectDescriptorRegistry projectDescriptorRegistry,
- URLClassLoader classloader, File settingsDir,
+ DefaultSettings(ServiceRegistryFactory serviceRegistryFactory,
+ GradleInternal gradle,
+ ClassLoader classloader, File settingsDir,
ScriptSource settingsScript, StartParameter startParameter) {
- super(gradle, projectDescriptorRegistry, classloader, settingsDir, settingsScript, startParameter)
+ super(serviceRegistryFactory, gradle, classloader, settingsDir, settingsScript, startParameter)
}
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/initialization/DefaultSettingsFinder.java b/subprojects/core/src/main/groovy/org/gradle/initialization/DefaultSettingsFinder.java
index 6889452..c0c26c0 100644
--- a/subprojects/core/src/main/groovy/org/gradle/initialization/DefaultSettingsFinder.java
+++ b/subprojects/core/src/main/groovy/org/gradle/initialization/DefaultSettingsFinder.java
@@ -20,9 +20,6 @@ import org.gradle.initialization.layout.BuildLayout;
import org.gradle.initialization.layout.BuildLayoutConfiguration;
import org.gradle.initialization.layout.BuildLayoutFactory;
-/**
- * @author Hans Dockter
- */
public class DefaultSettingsFinder implements ISettingsFinder {
private final BuildLayoutFactory layoutFactory;
diff --git a/subprojects/core/src/main/groovy/org/gradle/initialization/DependencyResolutionLogger.java b/subprojects/core/src/main/groovy/org/gradle/initialization/DependencyResolutionLogger.java
index 7987192..a5e6801 100644
--- a/subprojects/core/src/main/groovy/org/gradle/initialization/DependencyResolutionLogger.java
+++ b/subprojects/core/src/main/groovy/org/gradle/initialization/DependencyResolutionLogger.java
@@ -22,7 +22,6 @@ import org.gradle.logging.ProgressLoggerFactory;
import java.util.LinkedList;
-// TODO:DAZ Think about a better way to do thread-safety here, maybe
public class DependencyResolutionLogger implements DependencyResolutionListener {
private final ThreadLocal<LinkedList<ProgressLogger>> progressLoggers = new ThreadLocal<LinkedList<ProgressLogger>>() {
protected LinkedList<ProgressLogger> initialValue() {
diff --git a/subprojects/core/src/main/groovy/org/gradle/initialization/GradleLauncherAction.java b/subprojects/core/src/main/groovy/org/gradle/initialization/GradleLauncherAction.java
deleted file mode 100644
index 2437d93..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/initialization/GradleLauncherAction.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.initialization;
-
-import org.gradle.BuildResult;
-import org.gradle.GradleLauncher;
-
-/**
- * An object that performs some action with a {@link GradleLauncher}, and optionally produces a “result” object (e.g. the output).
- * <p>
- * Implementations of this are typically composed to bootstrap a build in a certain environment.
- * <p>
- * @see org.gradle.launcher.cli.ExecuteBuildAction
- * @see org.gradle.tooling.internal.provider.BuildModelAction
- */
-public interface GradleLauncherAction<T> {
-
- /**
- * Something produced by the action, the meaning of which is entirely up to the implementation to define.
- */
- T getResult();
-
- /**
- * Executes the action with the given launcher.
- * <p>
- * The state of the launcher is not defined as part of this contract, it is highly context specific. For example,
- * it is not guaranteed that the start parameter for the launcher has been configured.
- */
- BuildResult run(GradleLauncher launcher);
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/initialization/GradleLauncherFactory.java b/subprojects/core/src/main/groovy/org/gradle/initialization/GradleLauncherFactory.java
index a271e0f..d749341 100644
--- a/subprojects/core/src/main/groovy/org/gradle/initialization/GradleLauncherFactory.java
+++ b/subprojects/core/src/main/groovy/org/gradle/initialization/GradleLauncherFactory.java
@@ -21,8 +21,6 @@ import org.gradle.StartParameter;
/**
* <p>A {@code GradleLauncherFactory} is responsible for creating a {@link org.gradle.GradleLauncher} instance for a build, from a {@link
* org.gradle.StartParameter}.</p>
- *
- * @author Hans Dockter
*/
public interface GradleLauncherFactory {
/**
diff --git a/subprojects/core/src/main/groovy/org/gradle/initialization/IGradlePropertiesLoader.java b/subprojects/core/src/main/groovy/org/gradle/initialization/IGradlePropertiesLoader.java
index 27db653..730e5c6 100644
--- a/subprojects/core/src/main/groovy/org/gradle/initialization/IGradlePropertiesLoader.java
+++ b/subprojects/core/src/main/groovy/org/gradle/initialization/IGradlePropertiesLoader.java
@@ -18,9 +18,6 @@ package org.gradle.initialization;
import java.io.File;
import java.util.Map;
-/**
- * @author Hans Dockter
- */
public interface IGradlePropertiesLoader {
public static final String SYSTEM_PROJECT_PROPERTIES_PREFIX = "org.gradle.project.";
diff --git a/subprojects/core/src/main/groovy/org/gradle/initialization/IProjectDescriptorRegistry.java b/subprojects/core/src/main/groovy/org/gradle/initialization/IProjectDescriptorRegistry.java
deleted file mode 100644
index 8dde639..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/initialization/IProjectDescriptorRegistry.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2007-2008 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.initialization;
-
-import org.gradle.api.internal.project.IProjectRegistry;
-import org.gradle.util.Path;
-
-/**
- * @author Hans Dockter
- */
-public interface IProjectDescriptorRegistry extends IProjectRegistry<DefaultProjectDescriptor> {
- void changeDescriptorPath(Path oldPath, Path newPath);
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/initialization/ISettingsFinder.java b/subprojects/core/src/main/groovy/org/gradle/initialization/ISettingsFinder.java
index 62074f6..ee1c1c0 100644
--- a/subprojects/core/src/main/groovy/org/gradle/initialization/ISettingsFinder.java
+++ b/subprojects/core/src/main/groovy/org/gradle/initialization/ISettingsFinder.java
@@ -17,9 +17,6 @@ package org.gradle.initialization;
import org.gradle.StartParameter;
-/**
- * @author Hans Dockter
- */
public interface ISettingsFinder {
SettingsLocation find(StartParameter startParameter);
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/initialization/InstantiatingBuildLoader.java b/subprojects/core/src/main/groovy/org/gradle/initialization/InstantiatingBuildLoader.java
index 3b13750..a2b5917 100644
--- a/subprojects/core/src/main/groovy/org/gradle/initialization/InstantiatingBuildLoader.java
+++ b/subprojects/core/src/main/groovy/org/gradle/initialization/InstantiatingBuildLoader.java
@@ -25,9 +25,6 @@ import org.gradle.api.internal.project.ProjectInternal;
import java.io.File;
-/**
- * @author Hans Dockter
- */
public class InstantiatingBuildLoader implements BuildLoader {
private final IProjectFactory projectFactory;
diff --git a/subprojects/core/src/main/groovy/org/gradle/initialization/LayoutCommandLineConverter.java b/subprojects/core/src/main/groovy/org/gradle/initialization/LayoutCommandLineConverter.java
index db5ba26..b3f263a 100644
--- a/subprojects/core/src/main/groovy/org/gradle/initialization/LayoutCommandLineConverter.java
+++ b/subprojects/core/src/main/groovy/org/gradle/initialization/LayoutCommandLineConverter.java
@@ -23,13 +23,8 @@ import org.gradle.cli.AbstractCommandLineConverter;
import org.gradle.cli.CommandLineArgumentException;
import org.gradle.cli.CommandLineParser;
import org.gradle.cli.ParsedCommandLine;
-import org.gradle.internal.SystemProperties;
import org.gradle.internal.nativeplatform.filesystem.FileSystems;
-import org.gradle.util.GFileUtils;
-/**
- * by Szczepan Faber, created at: 2/18/13
- */
public class LayoutCommandLineConverter extends AbstractCommandLineConverter<BuildLayoutParameters> {
public static final String GRADLE_USER_HOME = "g";
@@ -37,7 +32,7 @@ public class LayoutCommandLineConverter extends AbstractCommandLineConverter<Bui
private static final String PROJECT_DIR = "p";
protected BuildLayoutParameters newInstance() {
- return new BuildLayoutParameters().setProjectDir(GFileUtils.canonicalise(SystemProperties.getCurrentDir()));
+ return new BuildLayoutParameters();
}
public BuildLayoutParameters convert(ParsedCommandLine options, BuildLayoutParameters target) throws CommandLineArgumentException {
@@ -57,6 +52,6 @@ public class LayoutCommandLineConverter extends AbstractCommandLineConverter<Bui
public void configure(CommandLineParser parser) {
parser.option(NO_SEARCH_UPWARDS, "no-search-upward").hasDescription(String.format("Don't search in parent folders for a %s file.", Settings.DEFAULT_SETTINGS_FILE));
parser.option(PROJECT_DIR, "project-dir").hasArgument().hasDescription("Specifies the start directory for Gradle. Defaults to current directory.");
- parser.option(LayoutCommandLineConverter.GRADLE_USER_HOME, "gradle-user-home").hasArgument().hasDescription("Specifies the gradle user home directory.");
+ parser.option(GRADLE_USER_HOME, "gradle-user-home").hasArgument().hasDescription("Specifies the gradle user home directory.");
}
}
\ No newline at end of file
diff --git a/subprojects/core/src/main/groovy/org/gradle/initialization/ProjectAccessListener.java b/subprojects/core/src/main/groovy/org/gradle/initialization/ProjectAccessListener.java
index b4fa573..3a38789 100644
--- a/subprojects/core/src/main/groovy/org/gradle/initialization/ProjectAccessListener.java
+++ b/subprojects/core/src/main/groovy/org/gradle/initialization/ProjectAccessListener.java
@@ -20,8 +20,6 @@ import org.gradle.api.internal.project.ProjectInternal;
/**
* Internal interface, used by our configuration on demand mode.
- *
- * by Szczepan Faber, created at: 2/5/13
*/
public interface ProjectAccessListener {
void beforeRequestingTaskByPath(ProjectInternal targetProject);
diff --git a/subprojects/core/src/main/groovy/org/gradle/initialization/ProjectDescriptorRegistry.java b/subprojects/core/src/main/groovy/org/gradle/initialization/ProjectDescriptorRegistry.java
new file mode 100644
index 0000000..4df3a38
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/initialization/ProjectDescriptorRegistry.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2007-2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.initialization;
+
+import org.gradle.api.internal.project.ProjectRegistry;
+import org.gradle.util.Path;
+
+public interface ProjectDescriptorRegistry extends ProjectRegistry<DefaultProjectDescriptor> {
+ void changeDescriptorPath(Path oldPath, Path newPath);
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/initialization/ProjectDirectoryProjectSpec.java b/subprojects/core/src/main/groovy/org/gradle/initialization/ProjectDirectoryProjectSpec.java
index 320603a..72991d6 100644
--- a/subprojects/core/src/main/groovy/org/gradle/initialization/ProjectDirectoryProjectSpec.java
+++ b/subprojects/core/src/main/groovy/org/gradle/initialization/ProjectDirectoryProjectSpec.java
@@ -18,7 +18,7 @@ package org.gradle.initialization;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.gradle.api.internal.project.ProjectIdentifier;
-import org.gradle.api.internal.project.IProjectRegistry;
+import org.gradle.api.internal.project.ProjectRegistry;
import org.gradle.api.InvalidUserDataException;
import java.io.File;
@@ -48,7 +48,7 @@ public class ProjectDirectoryProjectSpec extends AbstractProjectSpec implements
}
@Override
- protected void checkPreconditions(IProjectRegistry<?> registry) {
+ protected void checkPreconditions(ProjectRegistry<?> registry) {
if (!dir.exists()) {
throw new InvalidUserDataException(String.format("Project directory '%s' does not exist.", dir));
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/initialization/ProjectPropertySettingBuildLoader.java b/subprojects/core/src/main/groovy/org/gradle/initialization/ProjectPropertySettingBuildLoader.java
index 6e6b30c..6e8fda7 100644
--- a/subprojects/core/src/main/groovy/org/gradle/initialization/ProjectPropertySettingBuildLoader.java
+++ b/subprojects/core/src/main/groovy/org/gradle/initialization/ProjectPropertySettingBuildLoader.java
@@ -30,9 +30,6 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
-/**
- * @author Hans Dockter
- */
public class ProjectPropertySettingBuildLoader implements BuildLoader {
private static final Logger LOGGER = LoggerFactory.getLogger(ProjectPropertySettingBuildLoader.class);
diff --git a/subprojects/core/src/main/groovy/org/gradle/initialization/ProjectSpec.java b/subprojects/core/src/main/groovy/org/gradle/initialization/ProjectSpec.java
index b8a73a6..2b2133e 100644
--- a/subprojects/core/src/main/groovy/org/gradle/initialization/ProjectSpec.java
+++ b/subprojects/core/src/main/groovy/org/gradle/initialization/ProjectSpec.java
@@ -16,21 +16,21 @@
package org.gradle.initialization;
import org.gradle.api.internal.project.ProjectIdentifier;
-import org.gradle.api.internal.project.IProjectRegistry;
+import org.gradle.api.internal.project.ProjectRegistry;
import org.gradle.api.InvalidUserDataException;
public interface ProjectSpec {
/**
* Determines whether the given registry contains at least 1 project which meets this spec.
*/
- boolean containsProject(IProjectRegistry<?> registry);
+ boolean containsProject(ProjectRegistry<?> registry);
/**
* Returns the single project in the given registry which meets this spec.
* @return the project. Never returns null.
* @throws InvalidUserDataException When project cannot be selected due to some user input mismatch.
*/
- <T extends ProjectIdentifier> T selectProject(IProjectRegistry<? extends T> registry) throws
+ <T extends ProjectIdentifier> T selectProject(ProjectRegistry<? extends T> registry) throws
InvalidUserDataException;
/**
diff --git a/subprojects/core/src/main/groovy/org/gradle/initialization/PropertiesLoadingSettingsProcessor.java b/subprojects/core/src/main/groovy/org/gradle/initialization/PropertiesLoadingSettingsProcessor.java
index 2b3cb50..a86add0 100644
--- a/subprojects/core/src/main/groovy/org/gradle/initialization/PropertiesLoadingSettingsProcessor.java
+++ b/subprojects/core/src/main/groovy/org/gradle/initialization/PropertiesLoadingSettingsProcessor.java
@@ -15,11 +15,9 @@
*/
package org.gradle.initialization;
+import org.gradle.StartParameter;
import org.gradle.api.internal.GradleInternal;
import org.gradle.api.internal.SettingsInternal;
-import org.gradle.StartParameter;
-
-import java.net.URLClassLoader;
public class PropertiesLoadingSettingsProcessor implements SettingsProcessor {
private final SettingsProcessor processor;
@@ -32,7 +30,7 @@ public class PropertiesLoadingSettingsProcessor implements SettingsProcessor {
public SettingsInternal process(GradleInternal gradle,
SettingsLocation settingsLocation,
- URLClassLoader buildSourceClassLoader,
+ ClassLoader buildSourceClassLoader,
StartParameter startParameter) {
propertiesLoader.loadProperties(settingsLocation.getSettingsDir());
return processor.process(gradle, settingsLocation, buildSourceClassLoader, startParameter);
diff --git a/subprojects/core/src/main/groovy/org/gradle/initialization/ScriptEvaluatingSettingsProcessor.java b/subprojects/core/src/main/groovy/org/gradle/initialization/ScriptEvaluatingSettingsProcessor.java
index 6656eb5..99e7c7f 100644
--- a/subprojects/core/src/main/groovy/org/gradle/initialization/ScriptEvaluatingSettingsProcessor.java
+++ b/subprojects/core/src/main/groovy/org/gradle/initialization/ScriptEvaluatingSettingsProcessor.java
@@ -25,14 +25,10 @@ import org.gradle.util.Clock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.net.URLClassLoader;
import java.util.Collections;
import java.util.Map;
-/**
- * @author Hans Dockter
- */
public class ScriptEvaluatingSettingsProcessor implements SettingsProcessor {
private static Logger logger = LoggerFactory.getLogger(ScriptEvaluatingSettingsProcessor.class);
@@ -50,20 +46,20 @@ public class ScriptEvaluatingSettingsProcessor implements SettingsProcessor {
public SettingsInternal process(GradleInternal gradle,
SettingsLocation settingsLocation,
- URLClassLoader buildSourceClassLoader,
+ ClassLoader buildSourceClassLoader,
StartParameter startParameter) {
Clock settingsProcessingClock = new Clock();
Map<String, String> properties = propertiesLoader.mergeProperties(Collections.<String, String>emptyMap());
SettingsInternal settings = settingsFactory.createSettings(gradle, settingsLocation.getSettingsDir(),
settingsLocation.getSettingsScriptSource(), properties, startParameter, buildSourceClassLoader);
- applySettingsScript(settingsLocation, buildSourceClassLoader, settings);
+ applySettingsScript(settingsLocation, settings);
logger.debug("Timing: Processing settings took: {}", settingsProcessingClock.getTime());
return settings;
}
- private void applySettingsScript(SettingsLocation settingsLocation, ClassLoader buildSourceClassLoader, SettingsInternal settings) {
+ private void applySettingsScript(SettingsLocation settingsLocation, SettingsInternal settings) {
ScriptPlugin configurer = configurerFactory.create(settingsLocation.getSettingsScriptSource());
- configurer.setClassLoader(buildSourceClassLoader);
+ configurer.setClassLoader(settings.getClassLoader());
configurer.setScriptBaseClass(SettingsScript.class);
configurer.apply(settings);
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/initialization/SettingsFactory.java b/subprojects/core/src/main/groovy/org/gradle/initialization/SettingsFactory.java
index ca633e8..16abfcc 100644
--- a/subprojects/core/src/main/groovy/org/gradle/initialization/SettingsFactory.java
+++ b/subprojects/core/src/main/groovy/org/gradle/initialization/SettingsFactory.java
@@ -18,31 +18,28 @@ package org.gradle.initialization;
import org.gradle.StartParameter;
import org.gradle.api.internal.*;
+import org.gradle.internal.service.scopes.ServiceRegistryFactory;
import org.gradle.groovy.scripts.ScriptSource;
import org.gradle.internal.reflect.Instantiator;
import java.io.File;
-import java.net.URLClassLoader;
import java.util.Map;
-/**
- * @author Hans Dockter
- */
public class SettingsFactory {
- private final IProjectDescriptorRegistry projectDescriptorRegistry;
private final Instantiator instantiator;
+ private final ServiceRegistryFactory serviceRegistryFactory;
- public SettingsFactory(IProjectDescriptorRegistry projectDescriptorRegistry, Instantiator instantiator) {
- this.projectDescriptorRegistry = projectDescriptorRegistry;
+ public SettingsFactory(Instantiator instantiator, ServiceRegistryFactory serviceRegistryFactory) {
this.instantiator = instantiator;
+ this.serviceRegistryFactory = serviceRegistryFactory;
}
public SettingsInternal createSettings(GradleInternal gradle, File settingsDir, ScriptSource settingsScript,
Map<String, String> gradleProperties, StartParameter startParameter,
- URLClassLoader classloader) {
+ ClassLoader classloader) {
- DefaultSettings settings = instantiator.newInstance(DefaultSettings.class,
- gradle, projectDescriptorRegistry, classloader, settingsDir, settingsScript, startParameter
+ DefaultSettings settings = instantiator.newInstance(DefaultSettings.class, serviceRegistryFactory,
+ gradle, classloader, settingsDir, settingsScript, startParameter
);
DynamicObject dynamicObject = ((DynamicObjectAware) settings).getAsDynamicObject();
diff --git a/subprojects/core/src/main/groovy/org/gradle/initialization/SettingsHandler.java b/subprojects/core/src/main/groovy/org/gradle/initialization/SettingsHandler.java
index fd88f4d..86fecda 100644
--- a/subprojects/core/src/main/groovy/org/gradle/initialization/SettingsHandler.java
+++ b/subprojects/core/src/main/groovy/org/gradle/initialization/SettingsHandler.java
@@ -20,9 +20,10 @@ import org.gradle.StartParameter;
import org.gradle.api.initialization.ProjectDescriptor;
import org.gradle.api.internal.GradleInternal;
import org.gradle.api.internal.SettingsInternal;
+import org.gradle.initialization.buildsrc.BuildSourceBuilder;
+import org.gradle.invocation.BuildClassLoaderRegistry;
import java.io.File;
-import java.net.URLClassLoader;
/**
* Handles locating and processing setting.gradle files. Also deals with the buildSrc module, since that modules is
@@ -69,7 +70,7 @@ public class SettingsHandler {
}
}
- gradle.getScriptClassLoader().addParent(settings.getClassLoader());
+ gradle.getServices().get(BuildClassLoaderRegistry.class).addRootClassLoader(settings.getClassLoader());
return settings;
}
@@ -87,7 +88,7 @@ public class SettingsHandler {
StartParameter buildSrcStartParameter = startParameter.newBuild();
buildSrcStartParameter.setCurrentDir(new File(settingsLocation.getSettingsDir(),
BaseSettings.DEFAULT_BUILD_SRC_DIR));
- URLClassLoader buildSourceClassLoader = buildSourceBuilder.buildAndCreateClassLoader(buildSrcStartParameter);
+ ClassLoader buildSourceClassLoader = buildSourceBuilder.buildAndCreateClassLoader(buildSrcStartParameter);
return loadSettings(gradle, settingsLocation, buildSourceClassLoader, startParameter);
}
@@ -97,7 +98,7 @@ public class SettingsHandler {
}
private SettingsInternal loadSettings(GradleInternal gradle, SettingsLocation settingsLocation,
- URLClassLoader buildSourceClassLoader, StartParameter startParameter) {
+ ClassLoader buildSourceClassLoader, StartParameter startParameter) {
return settingsProcessor.process(gradle, settingsLocation, buildSourceClassLoader, startParameter);
}
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/initialization/SettingsProcessor.java b/subprojects/core/src/main/groovy/org/gradle/initialization/SettingsProcessor.java
index 7ea4f02..1ca1e93 100644
--- a/subprojects/core/src/main/groovy/org/gradle/initialization/SettingsProcessor.java
+++ b/subprojects/core/src/main/groovy/org/gradle/initialization/SettingsProcessor.java
@@ -15,11 +15,9 @@
*/
package org.gradle.initialization;
+import org.gradle.StartParameter;
import org.gradle.api.internal.GradleInternal;
import org.gradle.api.internal.SettingsInternal;
-import org.gradle.StartParameter;
-
-import java.net.URLClassLoader;
/**
* Responsible for locating, constructing, and evaluating the {@link SettingsInternal} for a build.
@@ -27,6 +25,6 @@ import java.net.URLClassLoader;
public interface SettingsProcessor {
SettingsInternal process(GradleInternal gradle,
SettingsLocation settingsLocation,
- URLClassLoader buildSourceClassLoader,
+ ClassLoader buildSourceClassLoader,
StartParameter startParameter);
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/initialization/buildsrc/BuildSourceBuilder.java b/subprojects/core/src/main/groovy/org/gradle/initialization/buildsrc/BuildSourceBuilder.java
new file mode 100644
index 0000000..0ebff93
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/initialization/buildsrc/BuildSourceBuilder.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.initialization.buildsrc;
+
+import org.gradle.GradleLauncher;
+import org.gradle.StartParameter;
+import org.gradle.cache.CacheBuilder;
+import org.gradle.cache.CacheRepository;
+import org.gradle.cache.PersistentCache;
+import org.gradle.cache.internal.FileLockManager;
+import org.gradle.initialization.ClassLoaderRegistry;
+import org.gradle.initialization.GradleLauncherFactory;
+import org.gradle.internal.classpath.ClassPath;
+import org.gradle.internal.classpath.DefaultClassPath;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.URLClassLoader;
+
+public class BuildSourceBuilder {
+ private static final Logger LOGGER = LoggerFactory.getLogger(BuildSourceBuilder.class);
+
+ private final GradleLauncherFactory gradleLauncherFactory;
+ private final ClassLoaderRegistry classLoaderRegistry;
+ private final CacheRepository cacheRepository;
+
+ public BuildSourceBuilder(GradleLauncherFactory gradleLauncherFactory, ClassLoaderRegistry classLoaderRegistry, CacheRepository cacheRepository) {
+ this.gradleLauncherFactory = gradleLauncherFactory;
+ this.classLoaderRegistry = classLoaderRegistry;
+ this.cacheRepository = cacheRepository;
+ }
+
+ public ClassLoader buildAndCreateClassLoader(StartParameter startParameter) {
+ ClassPath classpath = createBuildSourceClasspath(startParameter);
+ return new URLClassLoader(classpath.getAsURLArray(), classLoaderRegistry.getGradleApiClassLoader());
+ }
+
+ ClassPath createBuildSourceClasspath(StartParameter startParameter) {
+ assert startParameter.getCurrentDir() != null && startParameter.getBuildFile() == null;
+
+ LOGGER.debug("Starting to build the build sources.");
+ if (!startParameter.getCurrentDir().isDirectory()) {
+ LOGGER.debug("Gradle source dir does not exist. We leave.");
+ return new DefaultClassPath();
+ }
+ LOGGER.info("================================================" + " Start building buildSrc");
+
+ // If we were not the most recent version of Gradle to build the buildSrc dir, then do a clean build
+ // Otherwise, just to a regular build
+ final PersistentCache buildSrcCache = createCache(startParameter);
+
+ GradleLauncher gradleLauncher = buildGradleLauncher(startParameter);
+ return buildSrcCache.useCache("rebuild buildSrc", new BuildSrcUpdateFactory(buildSrcCache, gradleLauncher, new BuildSrcBuildListenerFactory()));
+ }
+
+ PersistentCache createCache(StartParameter startParameter) {
+ return cacheRepository.
+ cache("buildSrc").
+ withLockMode(FileLockManager.LockMode.None).
+ forObject(startParameter.getCurrentDir()).
+ withVersionStrategy(CacheBuilder.VersionStrategy.SharedCacheInvalidateOnVersionChange).
+ open();
+ }
+
+ private GradleLauncher buildGradleLauncher(StartParameter startParameter) {
+ final StartParameter startParameterArg = startParameter.newInstance();
+ startParameterArg.setProjectProperties(startParameter.getProjectProperties());
+ startParameterArg.setSearchUpwards(false);
+ startParameterArg.setProfile(startParameter.isProfile());
+ return gradleLauncherFactory.newInstance(startParameterArg);
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/initialization/buildsrc/BuildSrcBuildListenerFactory.java b/subprojects/core/src/main/groovy/org/gradle/initialization/buildsrc/BuildSrcBuildListenerFactory.java
new file mode 100644
index 0000000..e52586d
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/initialization/buildsrc/BuildSrcBuildListenerFactory.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.initialization.buildsrc;
+
+import org.gradle.BuildAdapter;
+import org.gradle.api.internal.GradleInternal;
+import org.gradle.api.internal.plugins.EmbeddableJavaProject;
+import org.gradle.api.invocation.Gradle;
+import org.gradle.initialization.ModelConfigurationListener;
+import org.gradle.util.WrapUtil;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.Set;
+
+public class BuildSrcBuildListenerFactory {
+
+ private static final String DEFAULT_BUILD_SOURCE_SCRIPT_RESOURCE = "defaultBuildSourceScript.txt";
+
+ Listener create(boolean rebuild) {
+ return new Listener(rebuild);
+ }
+
+ public static class Listener extends BuildAdapter implements ModelConfigurationListener {
+ private Set<File> classpath;
+ private final boolean rebuild;
+
+ public Listener(boolean rebuild) {
+ this.rebuild = rebuild;
+ }
+
+ @Override
+ public void projectsLoaded(Gradle gradle) {
+ gradle.getRootProject().apply(WrapUtil.toMap("from", BuildSrcBuildListenerFactory.class.getResource(DEFAULT_BUILD_SOURCE_SCRIPT_RESOURCE)));
+ }
+
+ public Collection<File> getRuntimeClasspath() {
+ return classpath;
+ }
+
+ public void onConfigure(GradleInternal gradle) {
+ EmbeddableJavaProject projectInfo = gradle.getRootProject().getConvention().getPlugin(EmbeddableJavaProject.class);
+ gradle.getStartParameter().setTaskNames(rebuild ? projectInfo.getRebuildTasks() : projectInfo.getBuildTasks());
+ classpath = projectInfo.getRuntimeClasspath().getFiles();
+ }
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/initialization/buildsrc/BuildSrcUpdateFactory.java b/subprojects/core/src/main/groovy/org/gradle/initialization/buildsrc/BuildSrcUpdateFactory.java
new file mode 100644
index 0000000..31fe50b
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/initialization/buildsrc/BuildSrcUpdateFactory.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.initialization.buildsrc;
+
+import org.gradle.GradleLauncher;
+import org.gradle.api.UncheckedIOException;
+import org.gradle.api.logging.Logger;
+import org.gradle.api.logging.Logging;
+import org.gradle.cache.PersistentCache;
+import org.gradle.internal.Factory;
+import org.gradle.internal.classpath.DefaultClassPath;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+
+public class BuildSrcUpdateFactory implements Factory<DefaultClassPath> {
+ private final PersistentCache cache;
+ private final GradleLauncher gradleLauncher;
+ private BuildSrcBuildListenerFactory listenerFactory;
+ private static final Logger LOGGER = Logging.getLogger(BuildSrcUpdateFactory.class);
+
+ public BuildSrcUpdateFactory(PersistentCache cache, GradleLauncher gradleLauncher, BuildSrcBuildListenerFactory listenerFactory) {
+ this.cache = cache;
+ this.gradleLauncher = gradleLauncher;
+ this.listenerFactory = listenerFactory;
+ }
+
+ public DefaultClassPath create() {
+ File markerFile = new File(cache.getBaseDir(), "built.bin");
+ final boolean rebuild = !markerFile.exists();
+
+ BuildSrcBuildListenerFactory.Listener listener = listenerFactory.create(rebuild);
+ gradleLauncher.addListener(listener);
+ gradleLauncher.run().rethrowFailure();
+
+ Collection<File> classpath = listener.getRuntimeClasspath();
+ LOGGER.debug("Gradle source classpath is: {}", classpath);
+ LOGGER.info("================================================" + " Finished building buildSrc");
+ try {
+ markerFile.createNewFile();
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ return new DefaultClassPath(classpath);
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/internal/featurelifecycle/DeprecatedFeatureHandler.java b/subprojects/core/src/main/groovy/org/gradle/internal/featurelifecycle/DeprecatedFeatureHandler.java
new file mode 100644
index 0000000..16f3cad
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/internal/featurelifecycle/DeprecatedFeatureHandler.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.featurelifecycle;
+
+/**
+ * Notified when a deprecated feature is used.
+ *
+ * <p>Implementations need not be thread-safe.
+ */
+public interface DeprecatedFeatureHandler {
+ void deprecatedFeatureUsed(DeprecatedFeatureUsage usage);
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/internal/featurelifecycle/DeprecatedFeatureUsage.java b/subprojects/core/src/main/groovy/org/gradle/internal/featurelifecycle/DeprecatedFeatureUsage.java
new file mode 100644
index 0000000..5971aa2
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/internal/featurelifecycle/DeprecatedFeatureUsage.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.featurelifecycle;
+
+import org.codehaus.groovy.runtime.StackTraceUtils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * An immutable description of the usage of a deprecated feature.
+ */
+public class DeprecatedFeatureUsage {
+ private final String message;
+ private final Class<?> calledFrom;
+ private final List<StackTraceElement> stack;
+
+ public DeprecatedFeatureUsage(String message, Class<?> calledFrom) {
+ this.message = message;
+ this.calledFrom = calledFrom;
+ this.stack = Collections.emptyList();
+ }
+
+ private DeprecatedFeatureUsage(DeprecatedFeatureUsage usage, List<StackTraceElement> stack) {
+ this.message = usage.message;
+ this.calledFrom = usage.calledFrom;
+ this.stack = stack;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public List<StackTraceElement> getStack() {
+ return stack;
+ }
+
+ /**
+ * Creates a copy of this usage with the stack trace populated. Implementation is a bit limited in that it assumes that
+ * this method is called from the same thread that triggered the usage.
+ */
+ public DeprecatedFeatureUsage withStackTrace() {
+ if (!stack.isEmpty()) {
+ return this;
+ }
+
+ StackTraceElement[] originalStack = StackTraceUtils.sanitize(new Exception()).getStackTrace();
+ int caller = 0;
+ while (caller < originalStack.length && !originalStack[caller].getClassName().startsWith(calledFrom.getName())) {
+ caller++;
+ }
+ while (caller < originalStack.length && originalStack[caller].getClassName().startsWith(calledFrom.getName())) {
+ caller++;
+ }
+ caller++;
+ List<StackTraceElement> stack = new ArrayList<StackTraceElement>();
+ for (; caller < originalStack.length; caller++) {
+ stack.add(originalStack[caller]);
+ }
+ return new DeprecatedFeatureUsage(this, stack);
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/internal/featurelifecycle/LoggingDeprecatedFeatureHandler.java b/subprojects/core/src/main/groovy/org/gradle/internal/featurelifecycle/LoggingDeprecatedFeatureHandler.java
new file mode 100644
index 0000000..4b10d5d
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/internal/featurelifecycle/LoggingDeprecatedFeatureHandler.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.featurelifecycle;
+
+import org.gradle.api.logging.Logger;
+import org.gradle.api.logging.Logging;
+import org.gradle.internal.SystemProperties;
+import org.gradle.util.SingleMessageLogger;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class LoggingDeprecatedFeatureHandler implements DeprecatedFeatureHandler {
+ private static final Logger LOGGER = Logging.getLogger(LoggingDeprecatedFeatureHandler.class);
+ private final Set<String> messages = new HashSet<String>();
+ private UsageLocationReporter locationReporter;
+
+ public LoggingDeprecatedFeatureHandler() {
+ this(new UsageLocationReporter() {
+ public void reportLocation(DeprecatedFeatureUsage usage, StringBuilder target) {
+ }
+ });
+ }
+
+ public LoggingDeprecatedFeatureHandler(UsageLocationReporter locationReporter) {
+ this.locationReporter = locationReporter;
+ }
+
+ public void setLocationReporter(UsageLocationReporter locationReporter) {
+ this.locationReporter = locationReporter;
+ }
+
+ public void deprecatedFeatureUsed(DeprecatedFeatureUsage usage) {
+ if (messages.add(usage.getMessage())) {
+ usage = usage.withStackTrace();
+ StringBuilder message = new StringBuilder();
+ locationReporter.reportLocation(usage, message);
+ if (message.length() > 0) {
+ message.append(SystemProperties.getLineSeparator());
+ }
+ message.append(usage.getMessage());
+ logTraceIfNecessary(usage.getStack(), message);
+ LOGGER.warn(message.toString());
+ }
+ }
+
+ private void logTraceIfNecessary(List<StackTraceElement> stack, StringBuilder message) {
+ if (isTraceLoggingEnabled()) {
+ for (StackTraceElement frame : stack) {
+ message.append(SystemProperties.getLineSeparator());
+ message.append(" ");
+ message.append(frame.toString());
+ }
+ }
+ }
+
+ private static boolean isTraceLoggingEnabled() {
+ return Boolean.getBoolean(SingleMessageLogger.ORG_GRADLE_DEPRECATION_TRACE_PROPERTY_NAME);
+ }
+
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/internal/featurelifecycle/ScriptUsageLocationReporter.java b/subprojects/core/src/main/groovy/org/gradle/internal/featurelifecycle/ScriptUsageLocationReporter.java
new file mode 100644
index 0000000..8e1b375
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/internal/featurelifecycle/ScriptUsageLocationReporter.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.featurelifecycle;
+
+import net.jcip.annotations.ThreadSafe;
+import org.apache.commons.lang.StringUtils;
+import org.gradle.groovy.scripts.Script;
+import org.gradle.groovy.scripts.ScriptExecutionListener;
+import org.gradle.groovy.scripts.ScriptSource;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+ at ThreadSafe
+public class ScriptUsageLocationReporter implements ScriptExecutionListener, UsageLocationReporter {
+ private final Lock lock = new ReentrantLock();
+ private final Map<String, ScriptSource> scripts = new HashMap<String, ScriptSource>();
+
+ public void beforeScript(Script script) {
+ lock.lock();
+ try {
+ ScriptSource scriptSource = script.getScriptSource();
+ scripts.put(scriptSource.getFileName(), scriptSource);
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public void afterScript(Script script, Throwable result) {
+ }
+
+ public void reportLocation(DeprecatedFeatureUsage usage, StringBuilder target) {
+ lock.lock();
+ try {
+ doReportLocation(usage, target);
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ private void doReportLocation(DeprecatedFeatureUsage usage, StringBuilder target) {
+ List<StackTraceElement> stack = usage.getStack();
+ if (stack.isEmpty()) {
+ return;
+ }
+
+ StackTraceElement directCaller = stack.get(0);
+ if (scripts.containsKey(directCaller.getFileName())) {
+ reportStackTraceElement(directCaller, target);
+ return;
+ }
+
+ int caller = 1;
+ while (caller < stack.size() && stack.get(caller).getClassName().equals(directCaller.getClassName())) {
+ caller++;
+ }
+ if (caller == stack.size()) {
+ return;
+ }
+ StackTraceElement indirectCaller = stack.get(caller);
+ if (scripts.containsKey(indirectCaller.getFileName())) {
+ reportStackTraceElement(indirectCaller, target);
+ }
+ }
+
+ private void reportStackTraceElement(StackTraceElement stackTraceElement, StringBuilder target) {
+ ScriptSource scriptSource = scripts.get(stackTraceElement.getFileName());
+ target.append(StringUtils.capitalize(scriptSource.getDisplayName()));
+ if (stackTraceElement.getLineNumber() > 0) {
+ target.append(": line ");
+ target.append(stackTraceElement.getLineNumber());
+ }
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/internal/featurelifecycle/UsageLocationReporter.java b/subprojects/core/src/main/groovy/org/gradle/internal/featurelifecycle/UsageLocationReporter.java
new file mode 100644
index 0000000..2891692
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/internal/featurelifecycle/UsageLocationReporter.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.featurelifecycle;
+
+public interface UsageLocationReporter {
+ void reportLocation(DeprecatedFeatureUsage usage, StringBuilder target);
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/internal/graph/CachingDirectedGraphWalker.java b/subprojects/core/src/main/groovy/org/gradle/internal/graph/CachingDirectedGraphWalker.java
new file mode 100644
index 0000000..a2eeb73
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/internal/graph/CachingDirectedGraphWalker.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.graph;
+
+import org.gradle.util.GUtil;
+
+import java.util.*;
+
+/**
+ * A graph walker which collects the values reachable from a given set of start nodes. Handles cycles in the graph. Can
+ * be reused to perform multiple searches, and reuses the results of previous searches.
+ *
+ * Uses a variation of Tarjan's algorithm: http://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm
+ */
+public class CachingDirectedGraphWalker<N, T> {
+ private final DirectedGraphWithEdgeValues<N, T> graph;
+ private List<N> startNodes = new LinkedList<N>();
+ private Set<NodeDetails<N, T>> strongComponents = new LinkedHashSet<NodeDetails<N, T>>();
+ private final Map<N, Set<T>> cachedNodeValues = new HashMap<N, Set<T>>();
+
+ public CachingDirectedGraphWalker(DirectedGraph<N, T> graph) {
+ this.graph = new GraphWithEmpyEdges<N, T>(graph);
+ }
+
+ public CachingDirectedGraphWalker(DirectedGraphWithEdgeValues<N, T> graph) {
+ this.graph = graph;
+ }
+
+ /**
+ * Adds some start nodes.
+ */
+ public CachingDirectedGraphWalker<N, T> add(N... values) {
+ add(Arrays.asList(values));
+ return this;
+ }
+
+ /**
+ * Adds some start nodes.
+ */
+ public CachingDirectedGraphWalker add(Iterable<? extends N> values) {
+ GUtil.addToCollection(startNodes, values);
+ return this;
+ }
+
+ /**
+ * Calculates the set of values of nodes reachable from the start nodes.
+ */
+ public Set<T> findValues() {
+ try {
+ return doSearch();
+ } finally {
+ startNodes.clear();
+ }
+ }
+
+ /**
+ * Returns the set of cycles seen in the graph.
+ */
+ public List<Set<N>> findCycles() {
+ findValues();
+ List<Set<N>> result = new ArrayList<Set<N>>();
+ for (NodeDetails<N, T> nodeDetails : strongComponents) {
+ Set<N> componentMembers = new LinkedHashSet<N>();
+ for (NodeDetails<N, T> componentMember : nodeDetails.componentMembers) {
+ componentMembers.add(componentMember.node);
+ }
+ result.add(componentMembers);
+ }
+ return result;
+ }
+
+ private Set<T> doSearch() {
+ int componentCount = 0;
+ Map<N, NodeDetails<N, T>> seenNodes = new HashMap<N, NodeDetails<N, T>>();
+ Map<Integer, NodeDetails<N, T>> components = new HashMap<Integer, NodeDetails<N, T>>();
+ LinkedList<N> queue = new LinkedList<N>(startNodes);
+
+ while (!queue.isEmpty()) {
+ N node = queue.getFirst();
+ NodeDetails<N, T> details = seenNodes.get(node);
+ if (details == null) {
+ // Have not visited this node yet. Push its successors onto the queue in front of this node and visit
+ // them
+
+ details = new NodeDetails<N, T>(node, componentCount++);
+ seenNodes.put(node, details);
+ components.put(details.component, details);
+
+ Set<T> cacheValues = cachedNodeValues.get(node);
+ if (cacheValues != null) {
+ // Already visited this node
+ details.values = cacheValues;
+ details.finished = true;
+ queue.removeFirst();
+ continue;
+ }
+
+ graph.getNodeValues(node, details.values, details.successors);
+ for (N connectedNode : details.successors) {
+ NodeDetails<N, T> connectedNodeDetails = seenNodes.get(connectedNode);
+ if (connectedNodeDetails == null) {
+ // Have not visited the successor node, so add to the queue for visiting
+ queue.add(0, connectedNode);
+ } else if (!connectedNodeDetails.finished) {
+ // Currently visiting the successor node - we're in a cycle
+ details.stronglyConnected = true;
+ }
+ // Else, already visited
+ }
+ } else {
+ // Have visited all of this node's successors
+ queue.removeFirst();
+
+ if (cachedNodeValues.containsKey(node)) {
+ continue;
+ }
+
+ for (N connectedNode : details.successors) {
+ NodeDetails<N, T> connectedNodeDetails = seenNodes.get(connectedNode);
+ if (!connectedNodeDetails.finished) {
+ // part of a cycle
+ details.minSeen = Math.min(details.minSeen, connectedNodeDetails.minSeen);
+ details.stronglyConnected = true;
+ }
+ details.values.addAll(connectedNodeDetails.values);
+ graph.getEdgeValues(node, connectedNode, details.values);
+ }
+
+ if (details.minSeen != details.component) {
+ // Part of a strongly connected component (ie cycle) - move values to root of the component
+ // The root is the first node of the component we encountered
+ NodeDetails<N, T> rootDetails = components.get(details.minSeen);
+ rootDetails.values.addAll(details.values);
+ details.values.clear();
+ rootDetails.componentMembers.addAll(details.componentMembers);
+ } else {
+ // Not part of a strongly connected component or the root of a strongly connected component
+ for (NodeDetails<N, T> componentMember : details.componentMembers) {
+ cachedNodeValues.put(componentMember.node, details.values);
+ componentMember.finished = true;
+ components.remove(componentMember.component);
+ }
+ if (details.stronglyConnected) {
+ strongComponents.add(details);
+ }
+ }
+ }
+ }
+
+ Set<T> values = new LinkedHashSet<T>();
+ for (N startNode : startNodes) {
+ values.addAll(cachedNodeValues.get(startNode));
+ }
+ return values;
+ }
+
+ private static class NodeDetails<N, T> {
+ private final int component;
+ private final N node;
+ private Set<T> values = new LinkedHashSet<T>();
+ private List<N> successors = new ArrayList<N>();
+ private Set<NodeDetails<N, T>> componentMembers = new LinkedHashSet<NodeDetails<N, T>>();
+ private int minSeen;
+ private boolean stronglyConnected;
+ private boolean finished;
+
+ public NodeDetails(N node, int component) {
+ this.node = node;
+ this.component = component;
+ minSeen = component;
+ componentMembers.add(this);
+ }
+ }
+
+ private static class GraphWithEmpyEdges<N, T> implements DirectedGraphWithEdgeValues<N, T> {
+ private final DirectedGraph<N, T> graph;
+
+ public GraphWithEmpyEdges(DirectedGraph<N, T> graph) {
+ this.graph = graph;
+ }
+
+ public void getEdgeValues(N from, N to, Collection<T> values) {
+ }
+
+ public void getNodeValues(N node, Collection<? super T> values, Collection<? super N> connectedNodes) {
+ graph.getNodeValues(node, values, connectedNodes);
+ }
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/internal/graph/DirectedGraph.java b/subprojects/core/src/main/groovy/org/gradle/internal/graph/DirectedGraph.java
new file mode 100644
index 0000000..a1d8483
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/internal/graph/DirectedGraph.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.graph;
+
+import java.util.Collection;
+
+/**
+ * A directed graph with nodes of type N. Each node has a collection of values of type V.
+ */
+public interface DirectedGraph<N, V> {
+ void getNodeValues(N node, Collection<? super V> values, Collection<? super N> connectedNodes);
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/internal/graph/DirectedGraphRenderer.java b/subprojects/core/src/main/groovy/org/gradle/internal/graph/DirectedGraphRenderer.java
new file mode 100644
index 0000000..9376900
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/internal/graph/DirectedGraphRenderer.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.graph;
+
+import org.gradle.api.Action;
+import org.gradle.logging.StyledTextOutput;
+import org.gradle.logging.internal.StreamingStyledTextOutput;
+
+import java.util.*;
+
+import static org.gradle.logging.StyledTextOutput.Style.Info;
+
+public class DirectedGraphRenderer<N> {
+ private final GraphNodeRenderer<N> nodeRenderer;
+ private final DirectedGraph<N, ?> graph;
+ private boolean omittedDetails;
+
+ public DirectedGraphRenderer(GraphNodeRenderer<N> nodeRenderer, DirectedGraph<N, ?> graph) {
+ this.nodeRenderer = nodeRenderer;
+ this.graph = graph;
+ }
+
+ public void renderTo(N root, Appendable output) {
+ renderTo(root, new StreamingStyledTextOutput(output));
+ }
+
+ public void renderTo(N root, StyledTextOutput output) {
+ GraphRenderer renderer = new GraphRenderer(output);
+ Set<N> rendered = new HashSet<N>();
+ omittedDetails = false;
+ renderTo(root, renderer, rendered, false);
+ if (omittedDetails) {
+ output.println();
+ output.withStyle(Info).println("(*) - details omitted (listed previously)");
+ }
+ }
+
+ private void renderTo(final N node, GraphRenderer graphRenderer, Collection<N> rendered, boolean lastChild) {
+ final boolean alreadySeen = !rendered.add(node);
+
+ graphRenderer.visit(new Action<StyledTextOutput>() {
+ public void execute(StyledTextOutput output) {
+ nodeRenderer.renderTo(node, output);
+ if (alreadySeen) {
+ output.text(" (*)");
+ }
+ }
+ }, lastChild);
+
+ if (alreadySeen) {
+ omittedDetails = true;
+ return;
+ }
+
+ List<N> children = new ArrayList<N>();
+ graph.getNodeValues(node, new HashSet<Object>(), children);
+ if (children.isEmpty()) {
+ return;
+ }
+ graphRenderer.startChildren();
+ for (int i = 0; i < children.size(); i++) {
+ N child = children.get(i);
+ renderTo(child, graphRenderer, rendered, i == children.size() - 1);
+ }
+ graphRenderer.completeChildren();
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/internal/graph/DirectedGraphWithEdgeValues.java b/subprojects/core/src/main/groovy/org/gradle/internal/graph/DirectedGraphWithEdgeValues.java
new file mode 100644
index 0000000..5dcf7cb
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/internal/graph/DirectedGraphWithEdgeValues.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.graph;
+
+import java.util.Collection;
+
+/**
+ * A directed graph with nodes of type N. Each edge has a collection of values of type V
+ */
+public interface DirectedGraphWithEdgeValues<N, V> extends DirectedGraph<N, V> {
+ void getEdgeValues(N from, N to, Collection<V> values);
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/internal/graph/GraphAggregator.java b/subprojects/core/src/main/groovy/org/gradle/internal/graph/GraphAggregator.java
new file mode 100644
index 0000000..ae97929
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/internal/graph/GraphAggregator.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.graph;
+
+import java.util.*;
+
+/**
+ * Groups the nodes of a graph based on their reachability from a set of starting nodes.
+ */
+public class GraphAggregator<N> {
+ private final CachingDirectedGraphWalker<N, N> graphWalker;
+
+ public GraphAggregator(DirectedGraph<N, ?> graph) {
+ graphWalker = new CachingDirectedGraphWalker<N, N>(new ConnectedNodesAsValuesDirectedGraph<N>(graph));
+ }
+
+ public Result<N> group(Collection<? extends N> startNodes, Collection<? extends N> allNodes) {
+ Map<N, Set<N>> reachableByNode = new HashMap<N, Set<N>>();
+ Set<N> topLevelNodes = new LinkedHashSet<N>(allNodes);
+ for (N node : allNodes) {
+ Set<N> reachableNodes = graphWalker.add(node).findValues();
+ reachableByNode.put(node, reachableNodes);
+ topLevelNodes.removeAll(reachableNodes);
+ }
+ topLevelNodes.addAll(startNodes);
+ Map<N, Set<N>> nodes = new HashMap<N, Set<N>>();
+ for (N node : topLevelNodes) {
+ nodes.put(node, calculateReachableNodes(reachableByNode, node, topLevelNodes));
+ }
+ return new Result<N>(nodes, topLevelNodes);
+ }
+
+ private Set<N> calculateReachableNodes(Map<N, Set<N>> nodes, N node, Set<N> topLevelNodes) {
+ Set<N> reachableNodes = nodes.get(node);
+ reachableNodes.add(node);
+ Set<N> reachableStartNodes = new LinkedHashSet<N>(topLevelNodes);
+ reachableStartNodes.retainAll(reachableNodes);
+ reachableStartNodes.remove(node);
+ for (N startNode : reachableStartNodes) {
+ reachableNodes.removeAll(calculateReachableNodes(nodes, startNode, topLevelNodes));
+ }
+ return reachableNodes;
+ }
+
+ public static class Result<N> {
+ private final Map<N, Set<N>> nodes;
+ private final Set<N> topLevelNodes;
+
+ public Result(Map<N, Set<N>> nodes, Set<N> topLevelNodes) {
+ this.nodes = nodes;
+ this.topLevelNodes = topLevelNodes;
+ }
+
+ public Set<N> getNodes(N startNode) {
+ return nodes.get(startNode);
+ }
+
+ public Set<N> getTopLevelNodes() {
+ return topLevelNodes;
+ }
+ }
+
+ private static class ConnectedNodesAsValuesDirectedGraph<N> implements DirectedGraph<N, N> {
+ private final DirectedGraph<N, ?> graph;
+
+ private ConnectedNodesAsValuesDirectedGraph(DirectedGraph<N, ?> graph) {
+ this.graph = graph;
+ }
+
+ public void getNodeValues(N node, Collection<? super N> values, Collection<? super N> connectedNodes) {
+ Set<N> edges = new LinkedHashSet<N>();
+ graph.getNodeValues(node, new ArrayList(), edges);
+ values.addAll(edges);
+ connectedNodes.addAll(edges);
+ }
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/internal/graph/GraphNodeRenderer.java b/subprojects/core/src/main/groovy/org/gradle/internal/graph/GraphNodeRenderer.java
new file mode 100644
index 0000000..e595847
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/internal/graph/GraphNodeRenderer.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.graph;
+
+import org.gradle.logging.StyledTextOutput;
+
+public interface GraphNodeRenderer<N> {
+ void renderTo(N node, StyledTextOutput output);
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/internal/graph/GraphRenderer.java b/subprojects/core/src/main/groovy/org/gradle/internal/graph/GraphRenderer.java
new file mode 100644
index 0000000..09494dd
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/internal/graph/GraphRenderer.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.graph;
+
+import org.gradle.api.Action;
+import org.gradle.logging.StyledTextOutput;
+
+import static org.gradle.logging.StyledTextOutput.Style.Info;
+
+public class GraphRenderer {
+ private final StyledTextOutput output;
+ private StringBuilder prefix = new StringBuilder();
+ private boolean seenRootChildren;
+ private boolean lastChild = true;
+
+ public GraphRenderer(StyledTextOutput output) {
+ this.output = output;
+ }
+
+ /**
+ * Visits a node in the graph.
+ */
+ public void visit(Action<? super StyledTextOutput> node, boolean lastChild) {
+ if (seenRootChildren) {
+ output.withStyle(Info).text(prefix + (lastChild ? "\\--- " : "+--- "));
+ }
+ this.lastChild = lastChild;
+ node.execute(output);
+ output.println();
+ }
+
+ /**
+ * Starts visiting the children of the most recently visited node.
+ */
+ public void startChildren() {
+ if (seenRootChildren) {
+ prefix.append(lastChild ? " " : "| ");
+ }
+ seenRootChildren = true;
+ }
+
+ /**
+ * Completes visiting the children of the node which most recently started visiting children.
+ */
+ public void completeChildren() {
+ if (prefix.length() == 0) {
+ seenRootChildren = false;
+ } else {
+ prefix.setLength(prefix.length() - 5);
+ }
+ }
+
+ public StyledTextOutput getOutput() {
+ return output;
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/internal/service/scopes/BuildScopeServices.java b/subprojects/core/src/main/groovy/org/gradle/internal/service/scopes/BuildScopeServices.java
new file mode 100644
index 0000000..30fa8b2
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/internal/service/scopes/BuildScopeServices.java
@@ -0,0 +1,265 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.service.scopes;
+
+import org.gradle.StartParameter;
+import org.gradle.api.Project;
+import org.gradle.api.artifacts.Module;
+import org.gradle.api.internal.*;
+import org.gradle.api.internal.artifacts.DefaultModule;
+import org.gradle.api.internal.artifacts.DependencyManagementServices;
+import org.gradle.api.internal.artifacts.configurations.DependencyMetaDataProvider;
+import org.gradle.api.internal.classpath.ModuleRegistry;
+import org.gradle.api.internal.classpath.PluginModuleRegistry;
+import org.gradle.api.internal.file.FileResolver;
+import org.gradle.api.internal.initialization.DefaultScriptHandlerFactory;
+import org.gradle.api.internal.initialization.ScriptHandlerFactory;
+import org.gradle.api.internal.plugins.DefaultPluginRegistry;
+import org.gradle.api.internal.plugins.PluginRegistry;
+import org.gradle.api.internal.project.*;
+import org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory;
+import org.gradle.api.internal.project.taskfactory.DependencyAutoWireTaskFactory;
+import org.gradle.api.internal.project.taskfactory.ITaskFactory;
+import org.gradle.api.internal.project.taskfactory.TaskFactory;
+import org.gradle.cache.CacheRepository;
+import org.gradle.cache.CacheValidator;
+import org.gradle.cache.internal.CacheFactory;
+import org.gradle.cache.internal.DefaultCacheRepository;
+import org.gradle.configuration.*;
+import org.gradle.configuration.project.*;
+import org.gradle.groovy.scripts.DefaultScriptCompilerFactory;
+import org.gradle.groovy.scripts.ScriptCompilerFactory;
+import org.gradle.groovy.scripts.ScriptExecutionListener;
+import org.gradle.groovy.scripts.internal.*;
+import org.gradle.initialization.*;
+import org.gradle.internal.Factory;
+import org.gradle.internal.TimeProvider;
+import org.gradle.internal.TrueTimeProvider;
+import org.gradle.internal.classloader.ClassLoaderFactory;
+import org.gradle.internal.concurrent.ExecutorFactory;
+import org.gradle.internal.id.LongIdGenerator;
+import org.gradle.internal.reflect.Instantiator;
+import org.gradle.internal.service.DefaultServiceRegistry;
+import org.gradle.internal.service.ServiceLocator;
+import org.gradle.internal.service.ServiceRegistry;
+import org.gradle.invocation.BuildClassLoaderRegistry;
+import org.gradle.invocation.DefaultBuildClassLoaderRegistry;
+import org.gradle.listener.ListenerManager;
+import org.gradle.logging.LoggingManagerInternal;
+import org.gradle.messaging.actor.ActorFactory;
+import org.gradle.messaging.actor.internal.DefaultActorFactory;
+import org.gradle.messaging.remote.MessagingServer;
+import org.gradle.process.internal.DefaultWorkerProcessFactory;
+import org.gradle.process.internal.WorkerProcessBuilder;
+import org.gradle.process.internal.child.WorkerProcessClassPathProvider;
+import org.gradle.profile.ProfileEventAdapter;
+import org.gradle.profile.ProfileListener;
+
+/**
+ * Contains the singleton services for a single build invocation.
+ */
+public class BuildScopeServices extends DefaultServiceRegistry implements ServiceRegistryFactory {
+ private final StartParameter startParameter;
+
+ public BuildScopeServices(final ServiceRegistry parent, final StartParameter startParameter) {
+ super(parent);
+ this.startParameter = startParameter;
+ add(StartParameter.class, startParameter);
+ }
+
+ protected ImportsReader createImportsReader() {
+ return new ImportsReader();
+ }
+
+ protected TimeProvider createTimeProvider() {
+ return new TrueTimeProvider();
+ }
+
+ protected IProjectFactory createProjectFactory() {
+ return new ProjectFactory(get(Instantiator.class));
+ }
+
+ protected ListenerManager createListenerManager(ListenerManager listenerManager) {
+ return listenerManager.createChild();
+ }
+
+ protected ClassPathRegistry createClassPathRegistry() {
+ return new DefaultClassPathRegistry(
+ new DefaultClassPathProvider(get(ModuleRegistry.class)),
+ new DependencyClassPathProvider(get(ModuleRegistry.class), get(PluginModuleRegistry.class)),
+ new WorkerProcessClassPathProvider(get(CacheRepository.class), get(ModuleRegistry.class)));
+ }
+
+ protected IsolatedAntBuilder createIsolatedAntBuilder() {
+ return new DefaultIsolatedAntBuilder(get(ClassPathRegistry.class), get(ClassLoaderFactory.class));
+ }
+
+ protected ActorFactory createActorFactory() {
+ return new DefaultActorFactory(get(ExecutorFactory.class));
+ }
+
+ protected IGradlePropertiesLoader createGradlePropertiesLoader() {
+ return new DefaultGradlePropertiesLoader(startParameter);
+ }
+
+ protected BuildLoader createBuildLoader() {
+ return new ProjectPropertySettingBuildLoader(
+ get(IGradlePropertiesLoader.class),
+ new InstantiatingBuildLoader(get(IProjectFactory.class)));
+ }
+
+ protected CacheFactory createCacheFactory() {
+ return getFactory(CacheFactory.class).create();
+ }
+
+ protected CacheRepository createCacheRepository() {
+ CacheFactory factory = get(CacheFactory.class);
+ return new DefaultCacheRepository(startParameter.getGradleUserHomeDir(), startParameter.getProjectCacheDir(),
+ startParameter.getCacheUsage(), factory);
+ }
+
+ protected ProjectEvaluator createProjectEvaluator() {
+ ConfigureActionsProjectEvaluator withActionsEvaluator = new ConfigureActionsProjectEvaluator(
+ new PluginsProjectConfigureActions(get(ClassLoaderRegistry.class).getPluginsClassLoader()),
+ new BuildScriptProcessor(get(ScriptPluginFactory.class)),
+ new DelayedConfigurationActions(),
+ new ProjectDependencies2TaskResolver()
+ );
+ return new LifecycleProjectEvaluator(withActionsEvaluator);
+ }
+
+ protected ITaskFactory createITaskFactory() {
+ return new DependencyAutoWireTaskFactory(
+ new AnnotationProcessingTaskFactory(
+ new TaskFactory(
+ get(ClassGenerator.class))));
+ }
+
+ protected BuildClassLoaderRegistry createBuildClassLoaderRegistry() {
+ return new DefaultBuildClassLoaderRegistry(get(ClassLoaderRegistry.class));
+ }
+
+ protected ScriptCompilerFactory createScriptCompileFactory() {
+ ScriptExecutionListener scriptExecutionListener = get(ListenerManager.class).getBroadcaster(ScriptExecutionListener.class);
+ EmptyScriptGenerator emptyScriptGenerator = new AsmBackedEmptyScriptGenerator();
+ CacheValidator scriptCacheInvalidator = new CacheValidator() {
+ public boolean isValid() {
+ return !get(StartParameter.class).isRecompileScripts();
+ }
+ };
+ return new DefaultScriptCompilerFactory(
+ new CachingScriptClassCompiler(
+ new ShortCircuitEmptyScriptCompiler(
+ new FileCacheBackedScriptClassCompiler(
+ get(CacheRepository.class),
+ scriptCacheInvalidator,
+ new DefaultScriptCompilationHandler(
+ emptyScriptGenerator)),
+ emptyScriptGenerator)),
+ new DefaultScriptRunnerFactory(scriptExecutionListener));
+ }
+
+ protected ScriptPluginFactory createScriptObjectConfigurerFactory() {
+ return new DefaultScriptPluginFactory(
+ get(ScriptCompilerFactory.class),
+ get(ImportsReader.class),
+ get(ScriptHandlerFactory.class),
+ get(BuildClassLoaderRegistry.class).getScriptClassLoader(),
+ getFactory(LoggingManagerInternal.class),
+ get(Instantiator.class)
+ );
+ }
+
+ protected InitScriptHandler createInitScriptHandler() {
+ return new InitScriptHandler(
+ new DefaultInitScriptProcessor(get(ScriptPluginFactory.class))
+ );
+ }
+
+ protected SettingsProcessor createSettingsProcessor() {
+ return new PropertiesLoadingSettingsProcessor(
+ new ScriptEvaluatingSettingsProcessor(
+ get(ScriptPluginFactory.class),
+ new SettingsFactory(
+
+ get(Instantiator.class),
+ this
+ ),
+ get(IGradlePropertiesLoader.class)),
+ get(IGradlePropertiesLoader.class));
+ }
+
+ protected ExceptionAnalyser createExceptionAnalyser() {
+ return new MultipleBuildFailuresExceptionAnalyser(new DefaultExceptionAnalyser(get(ListenerManager.class)));
+ }
+
+ protected ScriptHandlerFactory createScriptHandlerFactory() {
+ return new DefaultScriptHandlerFactory(
+ get(DependencyManagementServices.class),
+ get(FileResolver.class),
+ new DependencyMetaDataProviderImpl());
+ }
+
+ protected Factory<WorkerProcessBuilder> createWorkerProcessFactory() {
+ ClassPathRegistry classPathRegistry = get(ClassPathRegistry.class);
+ return new DefaultWorkerProcessFactory(
+ startParameter.getLogLevel(),
+ get(MessagingServer.class),
+ classPathRegistry,
+ get(FileResolver.class),
+ new LongIdGenerator());
+ }
+
+ protected BuildConfigurer createBuildConfigurer() {
+ return new DefaultBuildConfigurer();
+ }
+
+ protected ProjectAccessListener createProjectAccessListener() {
+ return new DefaultProjectAccessListener();
+ }
+
+ protected ProfileEventAdapter createProfileEventAdapter() {
+ return new ProfileEventAdapter(get(BuildRequestMetaData.class), get(TimeProvider.class), get(ListenerManager.class).getBroadcaster(ProfileListener.class));
+ }
+
+ protected PluginRegistry createPluginRegistry() {
+ return new DefaultPluginRegistry(get(ClassLoaderRegistry.class).getPluginsClassLoader(), new DependencyInjectingInstantiator(this));
+ }
+
+ protected DependencyManagementServices createDependencyManagementServices() {
+ ClassLoader coreImplClassLoader = get(ClassLoaderRegistry.class).getCoreImplClassLoader();
+ ServiceLocator serviceLocator = new ServiceLocator(coreImplClassLoader);
+ return serviceLocator.getFactory(DependencyManagementServices.class).newInstance(this);
+ }
+
+ public ServiceRegistryFactory createFor(Object domainObject) {
+ if (domainObject instanceof GradleInternal) {
+ return new GradleScopeServices(this, (GradleInternal) domainObject);
+ }
+ if (domainObject instanceof SettingsInternal) {
+ return new SettingsScopeServices(this, (SettingsInternal) domainObject);
+ }
+ throw new IllegalArgumentException(String.format("Cannot create services for unknown domain object of type %s.",
+ domainObject.getClass().getSimpleName()));
+ }
+
+ private class DependencyMetaDataProviderImpl implements DependencyMetaDataProvider {
+ public Module getModule() {
+ return new DefaultModule("unspecified", "unspecified", Project.DEFAULT_VERSION, Project.DEFAULT_STATUS);
+ }
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/internal/service/scopes/GlobalScopeServices.java b/subprojects/core/src/main/groovy/org/gradle/internal/service/scopes/GlobalScopeServices.java
new file mode 100755
index 0000000..8d53ea7
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/internal/service/scopes/GlobalScopeServices.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.service.scopes;
+
+import org.gradle.StartParameter;
+import org.gradle.api.internal.*;
+import org.gradle.api.internal.classpath.DefaultModuleRegistry;
+import org.gradle.api.internal.classpath.DefaultPluginModuleRegistry;
+import org.gradle.api.internal.classpath.ModuleRegistry;
+import org.gradle.api.internal.classpath.PluginModuleRegistry;
+import org.gradle.api.internal.file.FileResolver;
+import org.gradle.api.internal.file.IdentityFileResolver;
+import org.gradle.cache.internal.*;
+import org.gradle.cache.internal.locklistener.DefaultFileLockContentionHandler;
+import org.gradle.cache.internal.locklistener.FileLockContentionHandler;
+import org.gradle.cli.CommandLineConverter;
+import org.gradle.initialization.*;
+import org.gradle.internal.Factory;
+import org.gradle.internal.concurrent.DefaultExecutorFactory;
+import org.gradle.internal.concurrent.ExecutorFactory;
+import org.gradle.internal.nativeplatform.ProcessEnvironment;
+import org.gradle.internal.nativeplatform.filesystem.FileSystem;
+import org.gradle.internal.nativeplatform.services.NativeServices;
+import org.gradle.internal.reflect.DirectInstantiator;
+import org.gradle.internal.reflect.Instantiator;
+import org.gradle.internal.service.DefaultServiceRegistry;
+import org.gradle.internal.service.ServiceLocator;
+import org.gradle.internal.service.ServiceRegistry;
+import org.gradle.listener.DefaultListenerManager;
+import org.gradle.listener.ListenerManager;
+import org.gradle.logging.LoggingServiceRegistry;
+import org.gradle.messaging.remote.MessagingServer;
+import org.gradle.messaging.remote.internal.MessagingServices;
+import org.gradle.messaging.remote.internal.inet.InetAddressFactory;
+import org.gradle.internal.classloader.ClassLoaderFactory;
+import org.gradle.internal.classloader.DefaultClassLoaderFactory;
+
+import java.util.List;
+
+/**
+ * Contains the services shared by all builds in a given process.
+ */
+public class GlobalScopeServices extends DefaultServiceRegistry {
+ public GlobalScopeServices() {
+ this(LoggingServiceRegistry.newProcessLogging());
+ }
+
+ public GlobalScopeServices(ServiceRegistry loggingServices) {
+ super(loggingServices);
+ add(NativeServices.getInstance());
+ List<PluginServiceRegistry> pluginServiceFactories = new ServiceLocator(get(ClassLoaderRegistry.class).getRuntimeClassLoader()).getAll(PluginServiceRegistry.class);
+ for (PluginServiceRegistry pluginServiceRegistry : pluginServiceFactories) {
+ add(pluginServiceRegistry.createGlobalServices(this));
+ }
+ }
+
+ protected GradleLauncherFactory createGradleLauncherFactory() {
+ return new DefaultGradleLauncherFactory(this);
+ }
+
+ protected CommandLineConverter<StartParameter> createCommandLine2StartParameterConverter() {
+ return new DefaultCommandLineConverter();
+ }
+
+ protected ClassPathRegistry createClassPathRegistry() {
+ return new DefaultClassPathRegistry(new DefaultClassPathProvider(get(ModuleRegistry.class)), new DynamicModulesClassPathProvider(get(ModuleRegistry.class), get(PluginModuleRegistry.class)));
+ }
+
+ protected DefaultModuleRegistry createModuleRegistry() {
+ return new DefaultModuleRegistry();
+ }
+
+ protected DocumentationRegistry createDocumentationRegistry() {
+ return new DocumentationRegistry();
+ }
+
+ protected PluginModuleRegistry createPluginModuleRegistry() {
+ return new DefaultPluginModuleRegistry(get(ModuleRegistry.class));
+ }
+
+ protected Factory<CacheFactory> createCacheFactory() {
+ return new DefaultCacheFactory(get(FileLockManager.class));
+ }
+
+ protected ClassLoaderRegistry createClassLoaderRegistry() {
+ return new DefaultClassLoaderRegistry(get(ClassPathRegistry.class), get(ClassLoaderFactory.class));
+ }
+
+ protected ListenerManager createListenerManager() {
+ return new DefaultListenerManager();
+ }
+
+ protected ClassLoaderFactory createClassLoaderFactory() {
+ return new DefaultClassLoaderFactory();
+ }
+
+ protected MessagingServices createMessagingServices() {
+ return new MessagingServices(get(ClassLoaderRegistry.class).getPluginsClassLoader());
+ }
+
+ protected MessagingServer createMessagingServer() {
+ return get(MessagingServices.class).get(MessagingServer.class);
+ }
+
+ protected ClassGenerator createClassGenerator() {
+ return new AsmBackedClassGenerator();
+ }
+
+ protected Instantiator createInstantiator() {
+ return new ClassGeneratorBackedInstantiator(get(ClassGenerator.class), new DirectInstantiator());
+ }
+
+ protected ExecutorFactory createExecutorFactory() {
+ return new DefaultExecutorFactory();
+ }
+
+ protected FileLockManager createFileLockManager() {
+ return new DefaultFileLockManager(
+ new DefaultProcessMetaDataProvider(
+ get(ProcessEnvironment.class)),
+ get(FileLockContentionHandler.class));
+ }
+
+ private DefaultFileLockContentionHandler createFileLockContentionHandler() {
+ return new DefaultFileLockContentionHandler(
+ get(ExecutorFactory.class),
+ get(MessagingServices.class).get(InetAddressFactory.class)
+ );
+ }
+
+ private FileResolver createFileResolver() {
+ return new IdentityFileResolver(get(FileSystem.class));
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/internal/service/scopes/GradleScopeServices.java b/subprojects/core/src/main/groovy/org/gradle/internal/service/scopes/GradleScopeServices.java
new file mode 100644
index 0000000..3b268aa
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/internal/service/scopes/GradleScopeServices.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.service.scopes;
+
+import org.gradle.StartParameter;
+import org.gradle.api.internal.DependencyInjectingInstantiator;
+import org.gradle.api.internal.GradleInternal;
+import org.gradle.api.internal.artifacts.dsl.dependencies.ProjectFinder;
+import org.gradle.api.internal.plugins.DefaultPluginContainer;
+import org.gradle.api.internal.plugins.PluginRegistry;
+import org.gradle.api.internal.project.DefaultProjectRegistry;
+import org.gradle.api.internal.project.ProjectInternal;
+import org.gradle.api.internal.project.ProjectRegistry;
+import org.gradle.api.plugins.PluginContainer;
+import org.gradle.execution.*;
+import org.gradle.execution.taskgraph.DefaultTaskGraphExecuter;
+import org.gradle.execution.taskgraph.TaskPlanExecutor;
+import org.gradle.internal.service.DefaultServiceRegistry;
+import org.gradle.internal.service.ServiceRegistry;
+import org.gradle.invocation.BuildClassLoaderRegistry;
+import org.gradle.listener.ListenerManager;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import static java.util.Arrays.asList;
+
+/**
+ * Contains the services for a given {@link GradleInternal} instance.
+ */
+public class GradleScopeServices extends DefaultServiceRegistry implements ServiceRegistryFactory {
+ private final GradleInternal gradle;
+
+ public GradleScopeServices(ServiceRegistry parent, final GradleInternal gradle) {
+ super(parent);
+ this.gradle = gradle;
+ add(new TaskExecutionServices(parent, gradle));
+ }
+
+ protected BuildExecuter createBuildExecuter() {
+ List<BuildConfigurationAction> configs = new LinkedList<BuildConfigurationAction>();
+ if (get(StartParameter.class).isConfigureOnDemand()) {
+ configs.add(new ProjectEvaluatingAction());
+ }
+ configs.add(new DefaultTasksBuildExecutionAction());
+ configs.add(new ExcludedTaskFilteringBuildConfigurationAction());
+ configs.add(new TaskNameResolvingBuildConfigurationAction());
+
+ return new DefaultBuildExecuter(
+ configs,
+ asList(new DryRunBuildExecutionAction(),
+ new SelectedTaskExecutionAction()));
+ }
+
+ protected ProjectFinder createProjectFinder() {
+ return new ProjectFinder() {
+ public ProjectInternal getProject(String path) {
+ return gradle.getRootProject().project(path);
+ }
+ };
+ }
+
+ protected ProjectRegistry createIProjectRegistry() {
+ return new DefaultProjectRegistry<ProjectInternal>();
+ }
+
+ protected TaskGraphExecuter createTaskGraphExecuter() {
+ return new DefaultTaskGraphExecuter(get(ListenerManager.class), get(TaskPlanExecutor.class));
+ }
+
+ public ServiceRegistryFactory createFor(Object domainObject) {
+ if (domainObject instanceof ProjectInternal) {
+ return new ProjectScopeServices(this, (ProjectInternal) domainObject);
+ }
+ throw new UnsupportedOperationException();
+ }
+
+ protected PluginRegistry createPluginRegistry(PluginRegistry parentRegistry) {
+ return parentRegistry.createChild(get(BuildClassLoaderRegistry.class).getScriptClassLoader(), new DependencyInjectingInstantiator(this));
+ }
+
+ protected PluginContainer createPluginContainer() {
+ return new DefaultPluginContainer(get(PluginRegistry.class), gradle);
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/internal/service/scopes/PluginServiceRegistry.java b/subprojects/core/src/main/groovy/org/gradle/internal/service/scopes/PluginServiceRegistry.java
new file mode 100644
index 0000000..4bd8bfe
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/internal/service/scopes/PluginServiceRegistry.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.service.scopes;
+
+import org.gradle.internal.service.ServiceRegistry;
+
+/**
+ * Can be implemented by plugins to provide services in the global scope.
+ *
+ * <p>Implementations are discovered using the JAR service locator mechanism (see {@link org.gradle.internal.service.ServiceLocator}).
+ */
+public interface PluginServiceRegistry {
+ ServiceRegistry createGlobalServices(ServiceRegistry parent);
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/internal/service/scopes/ProjectScopeServices.java b/subprojects/core/src/main/groovy/org/gradle/internal/service/scopes/ProjectScopeServices.java
new file mode 100644
index 0000000..db108af
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/internal/service/scopes/ProjectScopeServices.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.service.scopes;
+
+import org.gradle.api.AntBuilder;
+import org.gradle.api.artifacts.Module;
+import org.gradle.api.artifacts.dsl.ArtifactHandler;
+import org.gradle.api.artifacts.dsl.DependencyHandler;
+import org.gradle.api.artifacts.dsl.ComponentMetadataHandler;
+import org.gradle.api.artifacts.dsl.RepositoryHandler;
+import org.gradle.api.component.SoftwareComponentContainer;
+import org.gradle.api.internal.ClassGenerator;
+import org.gradle.api.internal.ClassGeneratorBackedInstantiator;
+import org.gradle.api.internal.DependencyInjectingInstantiator;
+import org.gradle.api.internal.TaskInternal;
+import org.gradle.api.internal.artifacts.ArtifactPublicationServices;
+import org.gradle.api.internal.artifacts.DependencyManagementServices;
+import org.gradle.api.internal.artifacts.DependencyResolutionServices;
+import org.gradle.api.internal.artifacts.ProjectBackedModule;
+import org.gradle.api.internal.artifacts.configurations.ConfigurationContainerInternal;
+import org.gradle.api.internal.artifacts.configurations.DependencyMetaDataProvider;
+import org.gradle.api.internal.artifacts.dsl.dependencies.ProjectFinder;
+import org.gradle.api.internal.component.DefaultSoftwareComponentContainer;
+import org.gradle.api.internal.file.*;
+import org.gradle.api.internal.initialization.DefaultScriptHandlerFactory;
+import org.gradle.api.internal.initialization.ScriptClassLoaderProvider;
+import org.gradle.api.internal.initialization.ScriptHandlerFactory;
+import org.gradle.api.internal.initialization.ScriptHandlerInternal;
+import org.gradle.api.internal.plugins.DefaultPluginContainer;
+import org.gradle.api.internal.plugins.PluginRegistry;
+import org.gradle.api.internal.project.DefaultAntBuilderFactory;
+import org.gradle.api.internal.project.ProjectInternal;
+import org.gradle.api.internal.project.ant.AntLoggingAdapter;
+import org.gradle.api.internal.project.taskfactory.ITaskFactory;
+import org.gradle.api.internal.tasks.DefaultTaskContainerFactory;
+import org.gradle.api.internal.tasks.TaskContainerInternal;
+import org.gradle.api.plugins.PluginContainer;
+import org.gradle.configuration.project.DefaultProjectConfigurationActionContainer;
+import org.gradle.configuration.project.ProjectConfigurationActionContainer;
+import org.gradle.initialization.ProjectAccessListener;
+import org.gradle.internal.Factory;
+import org.gradle.internal.nativeplatform.filesystem.FileSystem;
+import org.gradle.internal.reflect.Instantiator;
+import org.gradle.internal.service.DefaultServiceRegistry;
+import org.gradle.internal.service.ServiceRegistry;
+import org.gradle.invocation.BuildClassLoaderRegistry;
+import org.gradle.logging.LoggingManagerInternal;
+import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry;
+import org.gradle.tooling.provider.model.internal.DefaultToolingModelBuilderRegistry;
+
+import java.io.File;
+
+/**
+ * Contains the services for a given project.
+ */
+public class ProjectScopeServices extends DefaultServiceRegistry implements ServiceRegistryFactory {
+ private final ProjectInternal project;
+
+ public ProjectScopeServices(ServiceRegistry parent, final ProjectInternal project) {
+ super(parent);
+ this.project = project;
+ }
+
+ protected PluginRegistry createPluginRegistry(PluginRegistry parentRegistry) {
+ return parentRegistry.createChild(get(ScriptClassLoaderProvider.class).getClassLoader(), new DependencyInjectingInstantiator(this));
+ }
+
+ protected FileResolver createFileResolver() {
+ return new BaseDirFileResolver(get(FileSystem.class), project.getProjectDir());
+ }
+
+ protected LoggingManagerInternal createLoggingManager() {
+ return getFactory(LoggingManagerInternal.class).create();
+ }
+
+ protected ProjectConfigurationActionContainer createProjectConfigurationActionContainer() {
+ return new DefaultProjectConfigurationActionContainer();
+ }
+
+ protected DefaultFileOperations createFileOperations() {
+ return new DefaultFileOperations(get(FileResolver.class), project.getTasks(), get(TemporaryFileProvider.class), get(Instantiator.class));
+ }
+
+ protected TemporaryFileProvider createTemporaryFileProvider() {
+ return new DefaultTemporaryFileProvider(new Factory<File>() {
+ public File create() {
+ return new File(project.getBuildDir(), "tmp");
+ }
+ });
+ }
+
+ protected Factory<AntBuilder> createAntBuilderFactory() {
+ return new DefaultAntBuilderFactory(new AntLoggingAdapter(), project);
+ }
+
+ protected ToolingModelBuilderRegistry createToolingModelRegistry() {
+ return new DefaultToolingModelBuilderRegistry();
+ }
+
+ protected PluginContainer createPluginContainer() {
+ return new DefaultPluginContainer(get(PluginRegistry.class), project);
+ }
+
+ protected ITaskFactory createTaskFactory(ITaskFactory parentFactory) {
+ return parentFactory.createChild(project, new ClassGeneratorBackedInstantiator(get(ClassGenerator.class), new DependencyInjectingInstantiator(this)));
+ }
+
+ protected Factory<TaskContainerInternal> createTaskContainerInternal() {
+ return new DefaultTaskContainerFactory(get(Instantiator.class), get(ITaskFactory.class), project, get(ProjectAccessListener.class));
+ }
+
+ protected ArtifactPublicationServices createArtifactPublicationServices() {
+ return get(DependencyResolutionServices.class).createArtifactPublicationServices();
+ }
+
+ protected RepositoryHandler createRepositoryHandler() {
+ return get(DependencyResolutionServices.class).getResolveRepositoryHandler();
+ }
+
+ protected ConfigurationContainerInternal createConfigurationContainer() {
+ return get(DependencyResolutionServices.class).getConfigurationContainer();
+ }
+
+ protected SoftwareComponentContainer createSoftwareComponentContainer() {
+ Instantiator instantiator = get(Instantiator.class);
+ return instantiator.newInstance(DefaultSoftwareComponentContainer.class, instantiator);
+ }
+
+ protected DependencyResolutionServices createDependencyResolutionServices() {
+ return newDependencyResolutionServices();
+ }
+
+ private DependencyResolutionServices newDependencyResolutionServices() {
+ return get(DependencyManagementServices.class).create(get(FileResolver.class), get(DependencyMetaDataProvider.class), get(ProjectFinder.class), project);
+ }
+
+ protected ArtifactHandler createArtifactHandler() {
+ return get(DependencyResolutionServices.class).getArtifactHandler();
+ }
+
+ protected ProjectFinder createProjectFinder() {
+ return new ProjectFinder() {
+ public ProjectInternal getProject(String path) {
+ return project.project(path);
+ }
+ };
+ }
+
+ protected DependencyHandler createDependencyHandler() {
+ return get(DependencyResolutionServices.class).getDependencyHandler();
+ }
+
+ protected ComponentMetadataHandler createModuleHandler() {
+ return get(DependencyResolutionServices.class).getComponentMetadataHandler();
+ }
+
+ protected ScriptHandlerInternal createScriptHandler() {
+ ScriptHandlerFactory factory = new DefaultScriptHandlerFactory(
+ get(DependencyManagementServices.class),
+ get(FileResolver.class),
+ get(DependencyMetaDataProvider.class));
+ ClassLoader parentClassLoader;
+ if (project.getParent() != null) {
+ parentClassLoader = project.getParent().getBuildscript().getClassLoader();
+ } else {
+ parentClassLoader = get(BuildClassLoaderRegistry.class).getScriptClassLoader();
+ }
+ return factory.create(project.getBuildScriptSource(), parentClassLoader, project);
+ }
+
+ protected DependencyMetaDataProvider createDependencyMetaDataProvider() {
+ return new DependencyMetaDataProvider() {
+ public Module getModule() {
+ return new ProjectBackedModule(project);
+ }
+ };
+ }
+
+ public ServiceRegistryFactory createFor(Object domainObject) {
+ if (domainObject instanceof TaskInternal) {
+ return new TaskScopeServices(this, project, (TaskInternal)domainObject);
+ }
+ throw new UnsupportedOperationException();
+ }
+
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/internal/service/scopes/ServiceRegistryFactory.java b/subprojects/core/src/main/groovy/org/gradle/internal/service/scopes/ServiceRegistryFactory.java
new file mode 100644
index 0000000..2749b70
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/internal/service/scopes/ServiceRegistryFactory.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.service.scopes;
+
+import org.gradle.internal.service.ServiceRegistry;
+
+/**
+ * A hierarchical service registry.
+ */
+public interface ServiceRegistryFactory extends ServiceRegistry {
+ /**
+ * Creates the services for the given domain object.
+ *
+ * @param domainObject The domain object.
+ * @return The registry containing the services for the domain object.
+ */
+ ServiceRegistryFactory createFor(Object domainObject);
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/internal/service/scopes/SettingsScopeServices.java b/subprojects/core/src/main/groovy/org/gradle/internal/service/scopes/SettingsScopeServices.java
new file mode 100644
index 0000000..91306ea
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/internal/service/scopes/SettingsScopeServices.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.service.scopes;
+
+import org.gradle.api.internal.DependencyInjectingInstantiator;
+import org.gradle.api.internal.SettingsInternal;
+import org.gradle.api.internal.file.BaseDirFileResolver;
+import org.gradle.api.internal.file.FileResolver;
+import org.gradle.api.internal.plugins.DefaultPluginContainer;
+import org.gradle.api.internal.plugins.PluginRegistry;
+import org.gradle.api.plugins.PluginContainer;
+import org.gradle.initialization.DefaultProjectDescriptorRegistry;
+import org.gradle.initialization.ProjectDescriptorRegistry;
+import org.gradle.internal.nativeplatform.filesystem.FileSystem;
+import org.gradle.internal.service.DefaultServiceRegistry;
+import org.gradle.internal.service.ServiceRegistry;
+
+public class SettingsScopeServices extends DefaultServiceRegistry implements ServiceRegistryFactory {
+ private final SettingsInternal settings;
+
+ public SettingsScopeServices(ServiceRegistry parent, final SettingsInternal settings) {
+ super(parent);
+ this.settings = settings;
+ }
+
+ public ServiceRegistryFactory createFor(Object domainObject) {
+ throw new UnsupportedOperationException();
+ }
+
+ protected FileResolver createFileResolver() {
+ return new BaseDirFileResolver(get(FileSystem.class), settings.getSettingsDir());
+ }
+
+ protected PluginRegistry createPluginRegistry(PluginRegistry parentRegistry) {
+ return parentRegistry.createChild(settings.getClassLoader(), new DependencyInjectingInstantiator(this));
+ }
+
+ protected PluginContainer createPluginContainer() {
+ return new DefaultPluginContainer(get(PluginRegistry.class), settings);
+ }
+
+ protected ProjectDescriptorRegistry createProjectDescriptorRegistry() {
+ return new DefaultProjectDescriptorRegistry();
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/internal/service/scopes/TaskExecutionServices.java b/subprojects/core/src/main/groovy/org/gradle/internal/service/scopes/TaskExecutionServices.java
new file mode 100644
index 0000000..7cba668
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/internal/service/scopes/TaskExecutionServices.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.service.scopes;
+
+import org.gradle.StartParameter;
+import org.gradle.api.execution.TaskActionListener;
+import org.gradle.api.internal.changedetection.TaskArtifactStateRepository;
+import org.gradle.api.internal.changedetection.changes.DefaultTaskArtifactStateRepository;
+import org.gradle.api.internal.changedetection.changes.ShortCircuitTaskArtifactStateRepository;
+import org.gradle.api.internal.changedetection.state.*;
+import org.gradle.api.internal.tasks.TaskExecuter;
+import org.gradle.api.internal.tasks.execution.*;
+import org.gradle.api.invocation.Gradle;
+import org.gradle.cache.CacheRepository;
+import org.gradle.execution.taskgraph.TaskPlanExecutor;
+import org.gradle.execution.taskgraph.TaskPlanExecutorFactory;
+import org.gradle.internal.id.RandomLongIdGenerator;
+import org.gradle.internal.reflect.Instantiator;
+import org.gradle.internal.service.DefaultServiceRegistry;
+import org.gradle.internal.service.ServiceRegistry;
+import org.gradle.listener.ListenerManager;
+
+public class TaskExecutionServices extends DefaultServiceRegistry {
+ private final Gradle gradle;
+
+ public TaskExecutionServices(ServiceRegistry parent, Gradle gradle) {
+ super(parent);
+ this.gradle = gradle;
+ }
+
+ protected TaskExecuter createTaskExecuter() {
+ TaskArtifactStateCacheAccess cacheAccess = get(TaskArtifactStateCacheAccess.class);
+ TaskArtifactStateRepository repository = get(TaskArtifactStateRepository.class);
+ return new ExecuteAtMostOnceTaskExecuter(
+ new SkipOnlyIfTaskExecuter(
+ new SkipTaskWithNoActionsExecuter(
+ new SkipEmptySourceFilesTaskExecuter(
+ new ValidatingTaskExecuter(
+ new SkipUpToDateTaskExecuter(repository,
+ new PostExecutionAnalysisTaskExecuter(
+ new ExecuteActionsTaskExecuter(
+ get(ListenerManager.class).getBroadcaster(TaskActionListener.class)
+ ))))))));
+ }
+
+ protected TaskArtifactStateCacheAccess createCacheAccess() {
+ return new DefaultTaskArtifactStateCacheAccess(gradle, get(CacheRepository.class));
+ }
+
+ protected TaskArtifactStateRepository createTaskArtifactStateRepository() {
+ TaskArtifactStateCacheAccess cacheAccess = get(TaskArtifactStateCacheAccess.class);
+
+ FileSnapshotter fileSnapshotter = new DefaultFileSnapshotter(
+ new CachingHasher(
+ new DefaultHasher(),
+ cacheAccess), cacheAccess);
+
+ FileSnapshotter outputFilesSnapshotter = new OutputFilesSnapshotter(fileSnapshotter, new RandomLongIdGenerator(), cacheAccess);
+
+ TaskHistoryRepository taskHistoryRepository = new CacheBackedTaskHistoryRepository(cacheAccess, new CacheBackedFileSnapshotRepository(cacheAccess, new RandomLongIdGenerator()));
+
+ Instantiator instantiator = get(Instantiator.class);
+ return new ShortCircuitTaskArtifactStateRepository(
+ get(StartParameter.class),
+ instantiator,
+ new DefaultTaskArtifactStateRepository(
+ taskHistoryRepository,
+ instantiator,
+ outputFilesSnapshotter,
+ fileSnapshotter
+ )
+ );
+ }
+
+ protected TaskPlanExecutor createTaskExecutorFactory() {
+ StartParameter startParameter = gradle.getStartParameter();
+ TaskArtifactStateCacheAccess cacheAccess = get(TaskArtifactStateCacheAccess.class);
+ return new TaskPlanExecutorFactory(cacheAccess, startParameter.getParallelThreadCount()).create();
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/internal/service/scopes/TaskScopeServices.java b/subprojects/core/src/main/groovy/org/gradle/internal/service/scopes/TaskScopeServices.java
new file mode 100644
index 0000000..2c59b78
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/internal/service/scopes/TaskScopeServices.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.service.scopes;
+
+import org.gradle.api.internal.TaskInternal;
+import org.gradle.api.internal.TaskOutputsInternal;
+import org.gradle.api.internal.project.ProjectInternal;
+import org.gradle.api.internal.tasks.DefaultTaskInputs;
+import org.gradle.api.internal.tasks.DefaultTaskOutputs;
+import org.gradle.api.internal.tasks.TaskStatusNagger;
+import org.gradle.api.tasks.TaskInputs;
+import org.gradle.internal.service.DefaultServiceRegistry;
+import org.gradle.internal.service.ServiceRegistry;
+import org.gradle.logging.LoggingManagerInternal;
+
+/**
+ * Contains the services for a given task.
+ */
+public class TaskScopeServices extends DefaultServiceRegistry implements ServiceRegistryFactory {
+ private final ProjectInternal project;
+ private final TaskInternal taskInternal;
+
+ public TaskScopeServices(ServiceRegistry parent, final ProjectInternal project, TaskInternal taskInternal) {
+ super(parent);
+ this.project = project;
+ this.taskInternal = taskInternal;
+ }
+
+ protected TaskInputs createTaskInputs() {
+ return new DefaultTaskInputs(project.getFileResolver(), taskInternal, get(TaskStatusNagger.class));
+ }
+
+ protected TaskOutputsInternal createTaskOutputs() {
+ return new DefaultTaskOutputs(project.getFileResolver(), taskInternal, get(TaskStatusNagger.class));
+ }
+
+ protected TaskStatusNagger createTaskStatusNagger() {
+ return new TaskStatusNagger(taskInternal);
+ }
+
+ protected LoggingManagerInternal createLoggingManager() {
+ return getFactory(LoggingManagerInternal.class).create();
+ }
+
+ public ServiceRegistryFactory createFor(Object domainObject) {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/invocation/BuildClassLoaderRegistry.java b/subprojects/core/src/main/groovy/org/gradle/invocation/BuildClassLoaderRegistry.java
new file mode 100644
index 0000000..c9399bf
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/invocation/BuildClassLoaderRegistry.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.invocation;
+
+public interface BuildClassLoaderRegistry {
+ /**
+ * Registers a {@code ClassLoader} to make visible to all scripts.
+ */
+ void addRootClassLoader(ClassLoader classLoader);
+
+ /**
+ * Returns the root {@code ClassLoader} to use for all scripts, including init and settings scripts. This {@code ClassLoader} exposes the Gradle API
+ * plus any classes that are exposed using {@link #addRootClassLoader(ClassLoader)}.
+ *
+ * <p>This {@code ClassLoader} is also used to locate plugins by id.</p>
+ */
+ ClassLoader getScriptClassLoader();
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/invocation/DefaultBuildClassLoaderRegistry.java b/subprojects/core/src/main/groovy/org/gradle/invocation/DefaultBuildClassLoaderRegistry.java
new file mode 100644
index 0000000..9b47683
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/invocation/DefaultBuildClassLoaderRegistry.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.invocation;
+
+import org.gradle.initialization.ClassLoaderRegistry;
+import org.gradle.internal.classloader.CachingClassLoader;
+import org.gradle.internal.classloader.MultiParentClassLoader;
+
+public class DefaultBuildClassLoaderRegistry implements BuildClassLoaderRegistry {
+ private final MultiParentClassLoader rootClassLoader;
+ private final CachingClassLoader scriptClassLoader;
+
+ public DefaultBuildClassLoaderRegistry(ClassLoaderRegistry registry) {
+ rootClassLoader = new MultiParentClassLoader(registry.getGradleApiClassLoader());
+ scriptClassLoader = new CachingClassLoader(rootClassLoader);
+ }
+
+ public void addRootClassLoader(ClassLoader classLoader) {
+ rootClassLoader.addParent(classLoader);
+ }
+
+ public ClassLoader getScriptClassLoader() {
+ return scriptClassLoader;
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/invocation/DefaultGradle.java b/subprojects/core/src/main/groovy/org/gradle/invocation/DefaultGradle.java
index 9b21679..2bd4cee 100644
--- a/subprojects/core/src/main/groovy/org/gradle/invocation/DefaultGradle.java
+++ b/subprojects/core/src/main/groovy/org/gradle/invocation/DefaultGradle.java
@@ -25,28 +25,30 @@ import org.gradle.api.Project;
import org.gradle.api.ProjectEvaluationListener;
import org.gradle.api.internal.GradleDistributionLocator;
import org.gradle.api.internal.GradleInternal;
-import org.gradle.api.internal.project.IProjectRegistry;
+import org.gradle.api.internal.file.FileResolver;
+import org.gradle.api.internal.project.AbstractPluginAware;
import org.gradle.api.internal.project.ProjectInternal;
-import org.gradle.api.internal.project.ServiceRegistryFactory;
+import org.gradle.api.internal.project.ProjectRegistry;
+import org.gradle.internal.service.scopes.ServiceRegistryFactory;
import org.gradle.api.invocation.Gradle;
+import org.gradle.api.plugins.PluginContainer;
+import org.gradle.configuration.ScriptPluginFactory;
import org.gradle.execution.TaskGraphExecuter;
import org.gradle.listener.ActionBroadcast;
import org.gradle.listener.ClosureBackedMethodInvocationDispatch;
import org.gradle.listener.ListenerBroadcast;
import org.gradle.listener.ListenerManager;
import org.gradle.util.GradleVersion;
-import org.gradle.util.MultiParentClassLoader;
import java.io.File;
-public class DefaultGradle implements GradleInternal {
+public class DefaultGradle extends AbstractPluginAware implements GradleInternal {
private ProjectInternal rootProject;
private ProjectInternal defaultProject;
- private TaskGraphExecuter taskGraph;
+ private final TaskGraphExecuter taskGraph;
private final Gradle parent;
- private StartParameter startParameter;
- private MultiParentClassLoader scriptClassLoader;
- private IProjectRegistry<ProjectInternal> projectRegistry;
+ private final StartParameter startParameter;
+ private final ProjectRegistry<ProjectInternal> projectRegistry;
private final ListenerManager listenerManager;
private final ServiceRegistryFactory services;
private final GradleDistributionLocator distributionLocator;
@@ -54,18 +56,24 @@ public class DefaultGradle implements GradleInternal {
private final ListenerBroadcast<ProjectEvaluationListener> projectEvaluationListenerBroadcast;
private ActionBroadcast<Project> rootProjectActions = new ActionBroadcast<Project>();
+ private PluginContainer pluginContainer;
+ private FileResolver fileResolver;
+ private ScriptPluginFactory scriptPluginFactory;
+
public DefaultGradle(Gradle parent, StartParameter startParameter, ServiceRegistryFactory parentRegistry) {
this.parent = parent;
this.startParameter = startParameter;
this.services = parentRegistry.createFor(this);
this.listenerManager = services.get(ListenerManager.class);
- projectRegistry = services.get(IProjectRegistry.class);
+ projectRegistry = services.get(ProjectRegistry.class);
taskGraph = services.get(TaskGraphExecuter.class);
- scriptClassLoader = services.get(MultiParentClassLoader.class);
distributionLocator = services.get(GradleDistributionLocator.class);
+ pluginContainer = services.get(PluginContainer.class);
+ fileResolver = services.get(FileResolver.class);
+ scriptPluginFactory = services.get(ScriptPluginFactory.class);
buildListenerBroadcast = listenerManager.createAnonymousBroadcaster(BuildListener.class);
projectEvaluationListenerBroadcast = listenerManager.createAnonymousBroadcaster(ProjectEvaluationListener.class);
- buildListenerBroadcast.add(new BuildAdapter(){
+ buildListenerBroadcast.add(new BuildAdapter() {
@Override
public void projectsLoaded(Gradle gradle) {
rootProjectActions.execute(rootProject);
@@ -139,18 +147,10 @@ public class DefaultGradle implements GradleInternal {
return taskGraph;
}
- public void setTaskGraph(TaskGraphExecuter taskGraph) {
- this.taskGraph = taskGraph;
- }
-
- public IProjectRegistry<ProjectInternal> getProjectRegistry() {
+ public ProjectRegistry<ProjectInternal> getProjectRegistry() {
return projectRegistry;
}
- public MultiParentClassLoader getScriptClassLoader() {
- return scriptClassLoader;
- }
-
public ProjectEvaluationListener addProjectEvaluationListener(ProjectEvaluationListener listener) {
addListener(listener);
return listener;
@@ -219,4 +219,18 @@ public class DefaultGradle implements GradleInternal {
public ServiceRegistryFactory getServices() {
return services;
}
+
+ public PluginContainer getPlugins() {
+ return pluginContainer;
+ }
+
+ @Override
+ protected FileResolver getFileResolver() {
+ return fileResolver;
+ }
+
+ @Override
+ protected ScriptPluginFactory getScriptPluginFactory() {
+ return scriptPluginFactory;
+ }
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/logging/StandardOutputCapture.java b/subprojects/core/src/main/groovy/org/gradle/logging/StandardOutputCapture.java
index 8392d98..316b47a 100644
--- a/subprojects/core/src/main/groovy/org/gradle/logging/StandardOutputCapture.java
+++ b/subprojects/core/src/main/groovy/org/gradle/logging/StandardOutputCapture.java
@@ -15,9 +15,6 @@
*/
package org.gradle.logging;
-/**
- * @author Hans Dockter
- */
public interface StandardOutputCapture {
/**
* Starts redirection of System.out and System.err to the Gradle logging system.
diff --git a/subprojects/core/src/main/groovy/org/gradle/logging/internal/DefaultLoggingManager.java b/subprojects/core/src/main/groovy/org/gradle/logging/internal/DefaultLoggingManager.java
index 3745344..a729a18 100644
--- a/subprojects/core/src/main/groovy/org/gradle/logging/internal/DefaultLoggingManager.java
+++ b/subprojects/core/src/main/groovy/org/gradle/logging/internal/DefaultLoggingManager.java
@@ -25,9 +25,6 @@ import org.gradle.logging.LoggingManagerInternal;
import java.util.LinkedHashSet;
import java.util.Set;
-/**
- * @author Hans Dockter
- */
public class DefaultLoggingManager implements LoggingManagerInternal {
private boolean started;
private final StartableLoggingSystem loggingSystem;
diff --git a/subprojects/core/src/main/groovy/org/gradle/logging/internal/EmbeddedLoggingServices.java b/subprojects/core/src/main/groovy/org/gradle/logging/internal/EmbeddedLoggingServices.java
index e791f36..f98be66 100644
--- a/subprojects/core/src/main/groovy/org/gradle/logging/internal/EmbeddedLoggingServices.java
+++ b/subprojects/core/src/main/groovy/org/gradle/logging/internal/EmbeddedLoggingServices.java
@@ -19,9 +19,6 @@ package org.gradle.logging.internal;
import org.gradle.internal.Factory;
import org.gradle.logging.LoggingManagerInternal;
-/**
- * by Szczepan Faber, created at: 1/23/12
- */
public interface EmbeddedLoggingServices {
Factory<LoggingManagerInternal> getLoggingManagerFactory();
diff --git a/subprojects/core/src/main/groovy/org/gradle/logging/internal/LoggingCommandLineConverter.java b/subprojects/core/src/main/groovy/org/gradle/logging/internal/LoggingCommandLineConverter.java
index 3848666..9ba8e82 100644
--- a/subprojects/core/src/main/groovy/org/gradle/logging/internal/LoggingCommandLineConverter.java
+++ b/subprojects/core/src/main/groovy/org/gradle/logging/internal/LoggingCommandLineConverter.java
@@ -25,9 +25,9 @@ import org.gradle.cli.ParsedCommandLine;
import org.gradle.logging.LoggingConfiguration;
import org.gradle.logging.ShowStacktrace;
-import java.util.Collection;
-import java.util.Collections;
+import java.util.Arrays;
import java.util.HashSet;
+import java.util.Map;
import java.util.Set;
public class LoggingCommandLineConverter extends AbstractCommandLineConverter<LoggingConfiguration> {
@@ -49,7 +49,6 @@ public class LoggingCommandLineConverter extends AbstractCommandLineConverter<Lo
logLevelMap.put(QUIET, LogLevel.QUIET);
logLevelMap.put(INFO, LogLevel.INFO);
logLevelMap.put(DEBUG, LogLevel.DEBUG);
- logLevelMap.put("", LogLevel.LIFECYCLE);
showStacktraceMap.put(FULL_STACKTRACE, ShowStacktrace.ALWAYS_FULL);
showStacktraceMap.put(STACKTRACE, ShowStacktrace.ALWAYS);
}
@@ -60,45 +59,36 @@ public class LoggingCommandLineConverter extends AbstractCommandLineConverter<Lo
}
public LoggingConfiguration convert(ParsedCommandLine commandLine, LoggingConfiguration loggingConfiguration) throws CommandLineArgumentException {
- loggingConfiguration.setLogLevel(getLogLevel(commandLine));
- if (commandLine.hasOption(NO_COLOR)) {
- loggingConfiguration.setColorOutput(false);
+ for (Map.Entry<String, LogLevel> entry : logLevelMap.entrySet()) {
+ if (commandLine.hasOption(entry.getKey())) {
+ loggingConfiguration.setLogLevel(entry.getValue());
+ }
}
- loggingConfiguration.setShowStacktrace(getShowStacktrace(commandLine));
- return loggingConfiguration;
- }
- private ShowStacktrace getShowStacktrace(ParsedCommandLine options) {
- if (options.hasOption(FULL_STACKTRACE)) {
- return ShowStacktrace.ALWAYS_FULL;
+ for (Map.Entry<String, ShowStacktrace> entry : showStacktraceMap.entrySet()) {
+ if (commandLine.hasOption(entry.getKey())) {
+ loggingConfiguration.setShowStacktrace(entry.getValue());
+ }
}
- if (options.hasOption(STACKTRACE)) {
- return ShowStacktrace.ALWAYS;
- }
- return ShowStacktrace.INTERNAL_EXCEPTIONS;
- }
- private LogLevel getLogLevel(ParsedCommandLine options) {
- LogLevel logLevel = LogLevel.LIFECYCLE;
- if (options.hasOption(QUIET)) {
- logLevel = LogLevel.QUIET;
- }
- if (options.hasOption(INFO)) {
- logLevel = LogLevel.INFO;
- }
- if (options.hasOption(DEBUG)) {
- logLevel = LogLevel.DEBUG;
+ if (commandLine.hasOption(NO_COLOR)) {
+ loggingConfiguration.setColorOutput(false);
}
- return logLevel;
+
+ return loggingConfiguration;
}
public void configure(CommandLineParser parser) {
parser.option(DEBUG, DEBUG_LONG).hasDescription("Log in debug mode (includes normal stacktrace).");
parser.option(QUIET, QUIET_LONG).hasDescription("Log errors only.");
parser.option(INFO, INFO_LONG).hasDescription("Set log level to info.");
+ parser.allowOneOf(DEBUG, QUIET, INFO);
+
parser.option(NO_COLOR).hasDescription("Do not use color in the console output.");
+
parser.option(STACKTRACE, STACKTRACE_LONG).hasDescription("Print out the stacktrace for all exceptions.");
parser.option(FULL_STACKTRACE, FULL_STACKTRACE_LONG).hasDescription("Print out the full (very verbose) stacktrace for all exceptions.");
+ parser.allowOneOf(STACKTRACE, FULL_STACKTRACE_LONG);
}
/**
@@ -106,7 +96,6 @@ public class LoggingCommandLineConverter extends AbstractCommandLineConverter<Lo
*
* @param commandLineArgument a single command line argument (with no '-')
* @return the corresponding log level or null if it doesn't match any.
- * @author mhunsicker
*/
public LogLevel getLogLevel(String commandLineArgument) {
LogLevel logLevel = logLevelMap.get(commandLineArgument);
@@ -122,7 +111,6 @@ public class LoggingCommandLineConverter extends AbstractCommandLineConverter<Lo
*
* @param logLevel the log level.
* @return the command line argument or null if this level cannot be represented on the command line.
- * @author mhunsicker
*/
public String getLogLevelCommandLine(LogLevel logLevel) {
String commandLine = logLevelMap.inverse().get(logLevel);
@@ -137,19 +125,16 @@ public class LoggingCommandLineConverter extends AbstractCommandLineConverter<Lo
* This returns the log levels that are supported on the command line.
*
* @return a collection of available log levels
- * @author mhunsicker
*/
- public Collection<LogLevel> getLogLevels() {
- return Collections.unmodifiableCollection(logLevelMap.values());
+ public Set<LogLevel> getLogLevels() {
+ return new HashSet<LogLevel>(Arrays.asList(LogLevel.DEBUG, LogLevel.INFO, LogLevel.LIFECYCLE, LogLevel.QUIET));
}
/**
* @return the set of short option strings that are used to configure log levels.
*/
public Set<String> getLogLevelOptions() {
- Set<String> options = new HashSet<String>(logLevelMap.keySet());
- options.remove("");
- return options;
+ return logLevelMap.keySet();
}
/**
@@ -157,7 +142,6 @@ public class LoggingCommandLineConverter extends AbstractCommandLineConverter<Lo
*
* @param commandLineArgument a single command line argument (with no '-')
* @return the corresponding stack trace level or null if it doesn't match any.
- * @author mhunsicker
*/
public ShowStacktrace getShowStacktrace(String commandLineArgument) {
ShowStacktrace showStacktrace = showStacktraceMap.get(commandLineArgument);
@@ -173,7 +157,6 @@ public class LoggingCommandLineConverter extends AbstractCommandLineConverter<Lo
*
* @param showStacktrace the stack trace level.
* @return the command line argument or null if this level cannot be represented on the command line.
- * @author mhunsicker
*/
public String getShowStacktraceCommandLine(ShowStacktrace showStacktrace) {
String commandLine = showStacktraceMap.inverse().get(showStacktrace);
diff --git a/subprojects/core/src/main/groovy/org/gradle/logging/internal/LoggingConfigurer.java b/subprojects/core/src/main/groovy/org/gradle/logging/internal/LoggingConfigurer.java
index 6553da8..ceec51e 100644
--- a/subprojects/core/src/main/groovy/org/gradle/logging/internal/LoggingConfigurer.java
+++ b/subprojects/core/src/main/groovy/org/gradle/logging/internal/LoggingConfigurer.java
@@ -17,9 +17,6 @@ package org.gradle.logging.internal;
import org.gradle.api.logging.LogLevel;
-/**
- * @author Hans Dockter
- */
public interface LoggingConfigurer {
void configure(LogLevel logLevel);
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/logging/internal/NoOpLoggingSystem.java b/subprojects/core/src/main/groovy/org/gradle/logging/internal/NoOpLoggingSystem.java
index 373cb99..983548d 100644
--- a/subprojects/core/src/main/groovy/org/gradle/logging/internal/NoOpLoggingSystem.java
+++ b/subprojects/core/src/main/groovy/org/gradle/logging/internal/NoOpLoggingSystem.java
@@ -18,9 +18,6 @@ package org.gradle.logging.internal;
import org.gradle.api.logging.LogLevel;
-/**
- * by Szczepan Faber, created at: 11/21/11
- */
public class NoOpLoggingSystem implements StdOutLoggingSystem, StdErrLoggingSystem, LoggingSystem {
public Snapshot snapshot() {
return dummy();
diff --git a/subprojects/core/src/main/groovy/org/gradle/logging/internal/StdErrLoggingSystem.java b/subprojects/core/src/main/groovy/org/gradle/logging/internal/StdErrLoggingSystem.java
index ed19c67..b7ede43 100644
--- a/subprojects/core/src/main/groovy/org/gradle/logging/internal/StdErrLoggingSystem.java
+++ b/subprojects/core/src/main/groovy/org/gradle/logging/internal/StdErrLoggingSystem.java
@@ -16,8 +16,5 @@
package org.gradle.logging.internal;
-/**
- * by Szczepan Faber, created at: 11/21/11
- */
public interface StdErrLoggingSystem extends LoggingSystem {
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/logging/internal/StdOutLoggingSystem.java b/subprojects/core/src/main/groovy/org/gradle/logging/internal/StdOutLoggingSystem.java
index 7592ea3..f4eecf4 100644
--- a/subprojects/core/src/main/groovy/org/gradle/logging/internal/StdOutLoggingSystem.java
+++ b/subprojects/core/src/main/groovy/org/gradle/logging/internal/StdOutLoggingSystem.java
@@ -16,8 +16,5 @@
package org.gradle.logging.internal;
-/**
- * by Szczepan Faber, created at: 11/21/11
- */
public interface StdOutLoggingSystem extends LoggingSystem {
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/logging/internal/logback/LogbackLoggingConfigurer.java b/subprojects/core/src/main/groovy/org/gradle/logging/internal/logback/LogbackLoggingConfigurer.java
index cea30a6..4eba18f 100644
--- a/subprojects/core/src/main/groovy/org/gradle/logging/internal/logback/LogbackLoggingConfigurer.java
+++ b/subprojects/core/src/main/groovy/org/gradle/logging/internal/logback/LogbackLoggingConfigurer.java
@@ -28,7 +28,9 @@ import ch.qos.logback.core.ConsoleAppender;
import ch.qos.logback.core.spi.FilterReply;
import org.gradle.api.logging.LogLevel;
import org.gradle.internal.UncheckedException;
-import org.gradle.logging.internal.*;
+import org.gradle.logging.internal.LogEvent;
+import org.gradle.logging.internal.LoggingConfigurer;
+import org.gradle.logging.internal.OutputEventListener;
import org.slf4j.LoggerFactory;
import org.slf4j.Marker;
@@ -37,8 +39,6 @@ import java.io.PrintStream;
/**
* A {@link org.gradle.logging.internal.LoggingConfigurer} implementation which configures Logback
* to route logging events to a {@link org.gradle.logging.internal.OutputEventListener}.
- *
- * @author Hans Dockter
*/
public class LogbackLoggingConfigurer implements LoggingConfigurer {
private final OutputEventListener outputEventListener;
diff --git a/subprojects/core/src/main/groovy/org/gradle/model/ModelType.java b/subprojects/core/src/main/groovy/org/gradle/model/ModelType.java
new file mode 100644
index 0000000..80ecbfc
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/model/ModelType.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.model;
+
+import java.lang.annotation.*;
+
+/**
+ * Marks a type as representing some type of model object.
+ */
+ at Inherited
+ at Target(ElementType.TYPE)
+ at Retention(RetentionPolicy.RUNTIME)
+public @interface ModelType {
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/model/internal/PersistentModelObjectRegistry.java b/subprojects/core/src/main/groovy/org/gradle/model/internal/PersistentModelObjectRegistry.java
new file mode 100644
index 0000000..09e2070
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/model/internal/PersistentModelObjectRegistry.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.model.internal;
+
+import com.google.common.collect.MapMaker;
+import org.gradle.api.GradleException;
+import org.gradle.api.Nullable;
+import org.gradle.cache.internal.btree.BTreePersistentIndexedCache;
+import org.gradle.internal.CompositeStoppable;
+import org.gradle.internal.reflect.JavaReflectionUtil;
+import org.gradle.internal.reflect.PropertyAccessor;
+import org.gradle.messaging.serialize.DefaultSerializer;
+import org.gradle.model.ModelType;
+
+import java.io.File;
+import java.io.Serializable;
+import java.util.Map;
+import java.util.TreeMap;
+
+public class PersistentModelObjectRegistry {
+ private final BTreePersistentIndexedCache<Object, FlattenedObject> store;
+ private final Map<Object, Object> idToInstance;
+ private final Map<Object, Object> instanceToId;
+
+ public PersistentModelObjectRegistry(File outputFile) {
+ store = new BTreePersistentIndexedCache<Object, FlattenedObject>(outputFile, new DefaultSerializer<Object>(), new DefaultSerializer<FlattenedObject>());
+ idToInstance = new MapMaker().weakValues().makeMap();
+ instanceToId = new MapMaker().weakKeys().makeMap();
+ }
+
+ public void put(Object identifier, Object modelObject) {
+ if (modelObject.getClass().getAnnotation(ModelType.class) == null) {
+ throw new IllegalArgumentException(String.format("Cannot persist object of class %s, as this class is not marked @%s", modelObject.getClass().getSimpleName(), ModelType.class.getSimpleName()));
+ }
+
+ FlattenedObject flattened = new FlattenedObject();
+ Class<?> type = modelObject.getClass();
+ for (PropertyAccessor property : JavaReflectionUtil.readableProperties(type).values()) {
+ if (property.getName().equals("metaClass") || property.getName().equals("class")) {
+ continue;
+ }
+ Object value;
+ try {
+ value = property.getValue(modelObject);
+ } catch (Exception e) {
+ throw new GradleException(String.format("Could not get property %s for model %s (%s)", property.getName(), identifier, modelObject.getClass().getSimpleName()), e);
+ }
+ if (value != null && value.getClass().getAnnotation(ModelType.class) != null) {
+ Object valueId = instanceToId.get(value);
+ if (valueId == null) {
+ throw new IllegalStateException(String.format("Model %s (%s) references an unknown model object of type %s.", identifier, modelObject.getClass().getSimpleName(), value.getClass().getSimpleName()));
+ }
+ value = new Reference(value.getClass().getName(), valueId);
+ }
+ flattened.properties.put(property.getName(), value);
+ }
+
+ idToInstance.put(identifier, modelObject);
+ instanceToId.put(modelObject, identifier);
+ store.put(identifier, flattened);
+ }
+
+ @Nullable
+ public <T> T get(Object identifier, Class<T> type) {
+ Object modelObject = idToInstance.get(identifier);
+ if (modelObject != null) {
+ return type.cast(modelObject);
+ }
+
+ FlattenedObject flattened = store.get(identifier);
+ if (flattened == null) {
+ return null;
+ }
+ try {
+ modelObject = type.newInstance();
+ } catch (Exception e) {
+ throw new GradleException(String.format("Could not create an instance of %s.", type.getSimpleName()), e);
+ }
+ for (Map.Entry<String, Object> entry : flattened.properties.entrySet()) {
+ Object value = entry.getValue();
+ if (value instanceof Reference) {
+ Reference reference = (Reference) value;
+ Class<?> referenceType;
+ try {
+ referenceType = type.getClassLoader().loadClass(reference.type);
+ } catch (ClassNotFoundException e) {
+ throw new GradleException(String.format("Could not locate type %s referenced by model %s (%s)", reference.type, identifier, type.getSimpleName()));
+ }
+ value = get(reference.identifier, referenceType);
+ }
+ try {
+ JavaReflectionUtil.writeableProperty(modelObject.getClass(), entry.getKey()).setValue(modelObject, value);
+ } catch (Exception e) {
+ throw new GradleException(String.format("Could not set property %s for model %s (%s)", entry.getKey(), identifier, type.getSimpleName()), e);
+ }
+ }
+
+ idToInstance.put(identifier, modelObject);
+ instanceToId.put(modelObject, identifier);
+ return type.cast(modelObject);
+ }
+
+ public void close() {
+ CompositeStoppable.stoppable(store).stop();
+ }
+
+ private static class Reference implements Serializable {
+ final String type;
+ final Object identifier;
+
+ private Reference(String type, Object identifier) {
+ this.type = type;
+ this.identifier = identifier;
+ }
+ }
+
+ private static class FlattenedObject implements Serializable {
+ Map<String, Object> properties = new TreeMap<String, Object>();
+ }
+
+}
+
diff --git a/subprojects/core/src/main/groovy/org/gradle/process/BaseExecSpec.java b/subprojects/core/src/main/groovy/org/gradle/process/BaseExecSpec.java
index 734401a..85ecb0e 100644
--- a/subprojects/core/src/main/groovy/org/gradle/process/BaseExecSpec.java
+++ b/subprojects/core/src/main/groovy/org/gradle/process/BaseExecSpec.java
@@ -21,8 +21,6 @@ import java.util.List;
/**
* Specifies options for launching a child process.
- *
- * @author Hans Dockter
*/
public interface BaseExecSpec extends ProcessForkOptions {
/**
diff --git a/subprojects/core/src/main/groovy/org/gradle/process/ExecResult.java b/subprojects/core/src/main/groovy/org/gradle/process/ExecResult.java
index df3ef6a..0109805 100644
--- a/subprojects/core/src/main/groovy/org/gradle/process/ExecResult.java
+++ b/subprojects/core/src/main/groovy/org/gradle/process/ExecResult.java
@@ -20,8 +20,6 @@ import org.gradle.process.internal.ExecException;
/**
* Represents the result of running an external process.
- *
- * @author Hans Dockter
*/
public interface ExecResult {
/**
diff --git a/subprojects/core/src/main/groovy/org/gradle/process/ExecSpec.java b/subprojects/core/src/main/groovy/org/gradle/process/ExecSpec.java
index 83ca73a..7cb1a9e 100644
--- a/subprojects/core/src/main/groovy/org/gradle/process/ExecSpec.java
+++ b/subprojects/core/src/main/groovy/org/gradle/process/ExecSpec.java
@@ -19,8 +19,6 @@ import java.util.List;
/**
* Specified the options for executing some command.
- *
- * @author Hans Dockter
*/
public interface ExecSpec extends BaseExecSpec {
/**
diff --git a/subprojects/core/src/main/groovy/org/gradle/process/JavaExecSpec.java b/subprojects/core/src/main/groovy/org/gradle/process/JavaExecSpec.java
index 8c5222c..f92d5bd 100644
--- a/subprojects/core/src/main/groovy/org/gradle/process/JavaExecSpec.java
+++ b/subprojects/core/src/main/groovy/org/gradle/process/JavaExecSpec.java
@@ -21,8 +21,6 @@ import java.util.List;
/**
* Specifies the options for executing a Java application.
- *
- * @author Hans Dockter
*/
public interface JavaExecSpec extends JavaForkOptions, BaseExecSpec {
/**
diff --git a/subprojects/core/src/main/groovy/org/gradle/process/internal/AbstractExecHandleBuilder.java b/subprojects/core/src/main/groovy/org/gradle/process/internal/AbstractExecHandleBuilder.java
index 9672afa..f5064af 100644
--- a/subprojects/core/src/main/groovy/org/gradle/process/internal/AbstractExecHandleBuilder.java
+++ b/subprojects/core/src/main/groovy/org/gradle/process/internal/AbstractExecHandleBuilder.java
@@ -27,9 +27,6 @@ import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
-/**
- * @author Hans Dockter
- */
public abstract class AbstractExecHandleBuilder extends DefaultProcessForkOptions implements BaseExecSpec {
private OutputStream standardOutput;
private OutputStream errorOutput;
diff --git a/subprojects/core/src/main/groovy/org/gradle/process/internal/BadExitCodeException.java b/subprojects/core/src/main/groovy/org/gradle/process/internal/BadExitCodeException.java
index 2a2f17b..edbf5d1 100644
--- a/subprojects/core/src/main/groovy/org/gradle/process/internal/BadExitCodeException.java
+++ b/subprojects/core/src/main/groovy/org/gradle/process/internal/BadExitCodeException.java
@@ -15,9 +15,6 @@
*/
package org.gradle.process.internal;
-/**
- * @author Tom Eyckmans
- */
public class BadExitCodeException extends Exception {
public BadExitCodeException(String message) {
super(message);
diff --git a/subprojects/core/src/main/groovy/org/gradle/process/internal/DefaultExecAction.java b/subprojects/core/src/main/groovy/org/gradle/process/internal/DefaultExecAction.java
index 86ef6fc..7ea563c 100644
--- a/subprojects/core/src/main/groovy/org/gradle/process/internal/DefaultExecAction.java
+++ b/subprojects/core/src/main/groovy/org/gradle/process/internal/DefaultExecAction.java
@@ -20,9 +20,6 @@ import org.gradle.api.internal.file.FileResolver;
import org.gradle.api.internal.file.IdentityFileResolver;
import org.gradle.process.ExecResult;
-/**
- * @author Hans Dockter
- */
public class DefaultExecAction extends ExecHandleBuilder implements ExecAction {
public DefaultExecAction(FileResolver fileResolver) {
super(fileResolver);
diff --git a/subprojects/core/src/main/groovy/org/gradle/process/internal/DefaultExecHandle.java b/subprojects/core/src/main/groovy/org/gradle/process/internal/DefaultExecHandle.java
index 20a330f..33849a8 100755
--- a/subprojects/core/src/main/groovy/org/gradle/process/internal/DefaultExecHandle.java
+++ b/subprojects/core/src/main/groovy/org/gradle/process/internal/DefaultExecHandle.java
@@ -17,7 +17,6 @@
package org.gradle.process.internal;
import com.google.common.base.Joiner;
-
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
import org.gradle.internal.concurrent.DefaultExecutorFactory;
@@ -52,8 +51,6 @@ import java.util.concurrent.locks.ReentrantLock;
* <li>{@link #start()} allowed when state is INIT</li>
* <li>{@link #abort()} allowed when state is STARTED or DETACHED</li>
* </ul>
- *
- * @author Tom Eyckmans
*/
public class DefaultExecHandle implements ExecHandle, ProcessSettings {
private static final Logger LOGGER = Logging.getLogger(DefaultExecHandle.class);
@@ -200,7 +197,7 @@ public class DefaultExecHandle implements ExecHandle, ProcessSettings {
}
}
setState(newState);
- execResult = new ExecResultImpl(exitValue, wrappedException);
+ execResult = new ExecResultImpl(exitValue, wrappedException, displayName);
result = execResult;
} finally {
lock.unlock();
@@ -344,13 +341,15 @@ public class DefaultExecHandle implements ExecHandle, ProcessSettings {
return timeoutMillis;
}
- private class ExecResultImpl implements ExecResult {
+ private static class ExecResultImpl implements ExecResult {
private final int exitValue;
private final ExecException failure;
+ private final String displayName;
- public ExecResultImpl(int exitValue, ExecException failure) {
+ public ExecResultImpl(int exitValue, ExecException failure, String displayName) {
this.exitValue = exitValue;
this.failure = failure;
+ this.displayName = displayName;
}
public int getExitValue() {
diff --git a/subprojects/core/src/main/groovy/org/gradle/process/internal/DefaultJavaExecAction.java b/subprojects/core/src/main/groovy/org/gradle/process/internal/DefaultJavaExecAction.java
index 0dcae9a..1adcfd5 100644
--- a/subprojects/core/src/main/groovy/org/gradle/process/internal/DefaultJavaExecAction.java
+++ b/subprojects/core/src/main/groovy/org/gradle/process/internal/DefaultJavaExecAction.java
@@ -19,9 +19,6 @@ package org.gradle.process.internal;
import org.gradle.api.internal.file.FileResolver;
import org.gradle.process.ExecResult;
-/**
- * @author Hans Dockter
- */
public class DefaultJavaExecAction extends JavaExecHandleBuilder implements JavaExecAction {
public DefaultJavaExecAction(FileResolver fileResolver) {
super(fileResolver);
diff --git a/subprojects/core/src/main/groovy/org/gradle/process/internal/DefaultWorkerProcessFactory.java b/subprojects/core/src/main/groovy/org/gradle/process/internal/DefaultWorkerProcessFactory.java
index b4c7c3c..230bfba 100644
--- a/subprojects/core/src/main/groovy/org/gradle/process/internal/DefaultWorkerProcessFactory.java
+++ b/subprojects/core/src/main/groovy/org/gradle/process/internal/DefaultWorkerProcessFactory.java
@@ -27,7 +27,7 @@ import org.gradle.process.internal.child.ApplicationClassesInIsolatedClassLoader
import org.gradle.process.internal.child.ApplicationClassesInSystemClassLoaderWorkerFactory;
import org.gradle.process.internal.child.EncodedStream;
import org.gradle.process.internal.child.WorkerFactory;
-import org.gradle.util.ClasspathUtil;
+import org.gradle.internal.classloader.ClasspathUtil;
import org.gradle.util.GUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/subprojects/core/src/main/groovy/org/gradle/process/internal/ExecAction.java b/subprojects/core/src/main/groovy/org/gradle/process/internal/ExecAction.java
index ca68e64..854ce4f 100644
--- a/subprojects/core/src/main/groovy/org/gradle/process/internal/ExecAction.java
+++ b/subprojects/core/src/main/groovy/org/gradle/process/internal/ExecAction.java
@@ -15,12 +15,11 @@
*/
package org.gradle.process.internal;
+import org.gradle.api.NonExtensible;
import org.gradle.process.ExecResult;
import org.gradle.process.ExecSpec;
-/**
- * @author Hans Dockter
- */
+ at NonExtensible
public interface ExecAction extends ExecSpec {
ExecResult execute() throws ExecException;
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/process/internal/ExecException.java b/subprojects/core/src/main/groovy/org/gradle/process/internal/ExecException.java
index 6999d85..2e964de 100644
--- a/subprojects/core/src/main/groovy/org/gradle/process/internal/ExecException.java
+++ b/subprojects/core/src/main/groovy/org/gradle/process/internal/ExecException.java
@@ -18,9 +18,6 @@ package org.gradle.process.internal;
import org.gradle.api.GradleException;
-/**
- * @author Hans Dockter
- */
public class ExecException extends GradleException {
public ExecException(String message) {
super(message);
diff --git a/subprojects/core/src/main/groovy/org/gradle/process/internal/ExecHandle.java b/subprojects/core/src/main/groovy/org/gradle/process/internal/ExecHandle.java
index 9a999a1..5c58856 100644
--- a/subprojects/core/src/main/groovy/org/gradle/process/internal/ExecHandle.java
+++ b/subprojects/core/src/main/groovy/org/gradle/process/internal/ExecHandle.java
@@ -22,9 +22,6 @@ import java.io.File;
import java.util.List;
import java.util.Map;
-/**
- * @author Tom Eyckmans
- */
public interface ExecHandle {
File getDirectory();
diff --git a/subprojects/core/src/main/groovy/org/gradle/process/internal/ExecHandleBuilder.java b/subprojects/core/src/main/groovy/org/gradle/process/internal/ExecHandleBuilder.java
index 175d150..9ad91a5 100644
--- a/subprojects/core/src/main/groovy/org/gradle/process/internal/ExecHandleBuilder.java
+++ b/subprojects/core/src/main/groovy/org/gradle/process/internal/ExecHandleBuilder.java
@@ -29,9 +29,6 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-/**
- * @author Tom Eyckmans
- */
public class ExecHandleBuilder extends AbstractExecHandleBuilder implements ExecSpec {
private final List<Object> arguments = new ArrayList<Object>();
diff --git a/subprojects/core/src/main/groovy/org/gradle/process/internal/ExecHandleListener.java b/subprojects/core/src/main/groovy/org/gradle/process/internal/ExecHandleListener.java
index a3f8b58..6ef4a82 100644
--- a/subprojects/core/src/main/groovy/org/gradle/process/internal/ExecHandleListener.java
+++ b/subprojects/core/src/main/groovy/org/gradle/process/internal/ExecHandleListener.java
@@ -18,9 +18,6 @@ package org.gradle.process.internal;
import org.gradle.process.ExecResult;
-/**
- * @author Tom Eyckmans
- */
public interface ExecHandleListener {
void executionStarted(ExecHandle execHandle);
diff --git a/subprojects/core/src/main/groovy/org/gradle/process/internal/ExecHandleRunner.java b/subprojects/core/src/main/groovy/org/gradle/process/internal/ExecHandleRunner.java
index 7b86a21..b86fc58 100755
--- a/subprojects/core/src/main/groovy/org/gradle/process/internal/ExecHandleRunner.java
+++ b/subprojects/core/src/main/groovy/org/gradle/process/internal/ExecHandleRunner.java
@@ -23,9 +23,6 @@ import org.gradle.process.internal.streams.StreamsHandler;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
-/**
- * @author Tom Eyckmans
- */
public class ExecHandleRunner implements Runnable {
private static final Object START_LOCK = new Object();
private static final Logger LOGGER = Logging.getLogger(ExecHandleRunner.class);
diff --git a/subprojects/core/src/main/groovy/org/gradle/process/internal/ExecHandleShutdownHookAction.java b/subprojects/core/src/main/groovy/org/gradle/process/internal/ExecHandleShutdownHookAction.java
index f2cbddf..48a54c6 100644
--- a/subprojects/core/src/main/groovy/org/gradle/process/internal/ExecHandleShutdownHookAction.java
+++ b/subprojects/core/src/main/groovy/org/gradle/process/internal/ExecHandleShutdownHookAction.java
@@ -20,8 +20,6 @@ import org.slf4j.LoggerFactory;
/**
* Terminates the external running 'sub' process when the Gradle process is being cancelled.
- *
- * @author Tom Eyckmans
*/
public class ExecHandleShutdownHookAction implements Runnable {
diff --git a/subprojects/core/src/main/groovy/org/gradle/process/internal/ExecHandleState.java b/subprojects/core/src/main/groovy/org/gradle/process/internal/ExecHandleState.java
index 783c337..b3e227b 100644
--- a/subprojects/core/src/main/groovy/org/gradle/process/internal/ExecHandleState.java
+++ b/subprojects/core/src/main/groovy/org/gradle/process/internal/ExecHandleState.java
@@ -16,9 +16,6 @@
package org.gradle.process.internal;
-/**
- * @author Tom Eyckmans
- */
public enum ExecHandleState {
INIT,
STARTING,
diff --git a/subprojects/core/src/main/groovy/org/gradle/process/internal/JavaExecAction.java b/subprojects/core/src/main/groovy/org/gradle/process/internal/JavaExecAction.java
index 81f5b49..7d9e654 100644
--- a/subprojects/core/src/main/groovy/org/gradle/process/internal/JavaExecAction.java
+++ b/subprojects/core/src/main/groovy/org/gradle/process/internal/JavaExecAction.java
@@ -15,12 +15,11 @@
*/
package org.gradle.process.internal;
+import org.gradle.api.NonExtensible;
import org.gradle.process.ExecResult;
import org.gradle.process.JavaExecSpec;
-/**
- * @author Hans Dockter
- */
+ at NonExtensible
public interface JavaExecAction extends JavaExecSpec {
ExecResult execute();
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/process/internal/ProcessBuilderFactory.java b/subprojects/core/src/main/groovy/org/gradle/process/internal/ProcessBuilderFactory.java
index 59e4aa4..0957409 100644
--- a/subprojects/core/src/main/groovy/org/gradle/process/internal/ProcessBuilderFactory.java
+++ b/subprojects/core/src/main/groovy/org/gradle/process/internal/ProcessBuilderFactory.java
@@ -22,8 +22,6 @@ import java.util.Map;
/**
* Creates a {@link java.lang.ProcessBuilder} based on a {@link ExecHandle}.
- *
- * @author Tom Eyckmans
*/
public class ProcessBuilderFactory {
public ProcessBuilder createProcessBuilder(ProcessSettings processSettings) {
diff --git a/subprojects/core/src/main/groovy/org/gradle/process/internal/ProcessParentingInitializer.java b/subprojects/core/src/main/groovy/org/gradle/process/internal/ProcessParentingInitializer.java
index aba64ee..86cc12b 100644
--- a/subprojects/core/src/main/groovy/org/gradle/process/internal/ProcessParentingInitializer.java
+++ b/subprojects/core/src/main/groovy/org/gradle/process/internal/ProcessParentingInitializer.java
@@ -26,7 +26,6 @@ import org.gradle.internal.os.OperatingSystem;
/**
* Initializes for a well behaved parent process.
* <p>
- * by Szczepan Faber, created at: 3/2/12
*/
public class ProcessParentingInitializer {
diff --git a/subprojects/core/src/main/groovy/org/gradle/process/internal/ProcessSettings.java b/subprojects/core/src/main/groovy/org/gradle/process/internal/ProcessSettings.java
index f571230..b6dbe5a 100644
--- a/subprojects/core/src/main/groovy/org/gradle/process/internal/ProcessSettings.java
+++ b/subprojects/core/src/main/groovy/org/gradle/process/internal/ProcessSettings.java
@@ -20,9 +20,6 @@ import java.io.File;
import java.util.List;
import java.util.Map;
-/**
- * by Szczepan Faber, created at: 4/20/12
- */
public interface ProcessSettings {
File getDirectory();
diff --git a/subprojects/core/src/main/groovy/org/gradle/process/internal/child/EncodedStream.java b/subprojects/core/src/main/groovy/org/gradle/process/internal/child/EncodedStream.java
index b516b8c..e7a3159 100644
--- a/subprojects/core/src/main/groovy/org/gradle/process/internal/child/EncodedStream.java
+++ b/subprojects/core/src/main/groovy/org/gradle/process/internal/child/EncodedStream.java
@@ -23,8 +23,6 @@ import java.io.OutputStream;
/**
* Provides Input/OutputStream implementations that are able to encode/decode using a simple algorithm (byte<->2 digit hex string(2 bytes)).
* Useful when streams are interpreted a text streams as it happens on IBM java for standard input.
- * <p>
- * by Szczepan Faber, created at: 5/25/12
*/
public abstract class EncodedStream {
private final static char[] HEX_DIGIT = new char[] {
diff --git a/subprojects/core/src/main/groovy/org/gradle/process/internal/child/ImplementationClassLoaderWorker.java b/subprojects/core/src/main/groovy/org/gradle/process/internal/child/ImplementationClassLoaderWorker.java
index a482c8c..144fbe3 100644
--- a/subprojects/core/src/main/groovy/org/gradle/process/internal/child/ImplementationClassLoaderWorker.java
+++ b/subprojects/core/src/main/groovy/org/gradle/process/internal/child/ImplementationClassLoaderWorker.java
@@ -19,6 +19,10 @@ package org.gradle.process.internal.child;
import org.gradle.api.Action;
import org.gradle.api.logging.LogLevel;
import org.gradle.internal.UncheckedException;
+import org.gradle.internal.classloader.CachingClassLoader;
+import org.gradle.internal.classloader.FilteringClassLoader;
+import org.gradle.internal.classloader.MultiParentClassLoader;
+import org.gradle.internal.classloader.MutableURLClassLoader;
import org.gradle.internal.io.ClassLoaderObjectInputStream;
import org.gradle.logging.LoggingManagerInternal;
import org.gradle.logging.LoggingServiceRegistry;
@@ -86,6 +90,6 @@ public class ImplementationClassLoaderWorker implements Action<WorkerContext>, S
}
MutableURLClassLoader createImplementationClassLoader(ClassLoader system, ClassLoader application) {
- return new MutableURLClassLoader(new MultiParentClassLoader(application, system));
+ return new MutableURLClassLoader(new CachingClassLoader(new MultiParentClassLoader(application, system)));
}
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/process/internal/child/IsolatedApplicationClassLoaderWorker.java b/subprojects/core/src/main/groovy/org/gradle/process/internal/child/IsolatedApplicationClassLoaderWorker.java
index a069bb7..b8511c9 100644
--- a/subprojects/core/src/main/groovy/org/gradle/process/internal/child/IsolatedApplicationClassLoaderWorker.java
+++ b/subprojects/core/src/main/groovy/org/gradle/process/internal/child/IsolatedApplicationClassLoaderWorker.java
@@ -17,7 +17,7 @@
package org.gradle.process.internal.child;
import org.gradle.api.Action;
-import org.gradle.util.DefaultClassLoaderFactory;
+import org.gradle.internal.classloader.DefaultClassLoaderFactory;
import java.io.Serializable;
import java.net.URI;
diff --git a/subprojects/core/src/main/groovy/org/gradle/process/internal/child/SystemApplicationClassLoaderWorker.java b/subprojects/core/src/main/groovy/org/gradle/process/internal/child/SystemApplicationClassLoaderWorker.java
index ae6448f..dec4ff6 100644
--- a/subprojects/core/src/main/groovy/org/gradle/process/internal/child/SystemApplicationClassLoaderWorker.java
+++ b/subprojects/core/src/main/groovy/org/gradle/process/internal/child/SystemApplicationClassLoaderWorker.java
@@ -25,7 +25,6 @@ import java.util.concurrent.Callable;
/**
* <p>Stage 3 of the start-up for a worker process with the application classes loaded in the system ClassLoader. Takes
* care of adding the application classes to the system ClassLoader and then invoking the next stage of start-up.</p>
- * TODO:DAZ No longer adds application classes to system ClassLoader: is this required at all?
*
* <p> Instantiated in the worker bootstrap ClassLoader and invoked from {@link org.gradle.process.internal.launcher.BootstrapClassLoaderWorker}.
* See {@link ApplicationClassesInSystemClassLoaderWorkerFactory} for details.</p>
diff --git a/subprojects/core/src/main/groovy/org/gradle/process/internal/child/WorkerProcessClassPathProvider.java b/subprojects/core/src/main/groovy/org/gradle/process/internal/child/WorkerProcessClassPathProvider.java
index 4cfe4e9..56ed0a1 100644
--- a/subprojects/core/src/main/groovy/org/gradle/process/internal/child/WorkerProcessClassPathProvider.java
+++ b/subprojects/core/src/main/groovy/org/gradle/process/internal/child/WorkerProcessClassPathProvider.java
@@ -65,6 +65,7 @@ public class WorkerProcessClassPathProvider implements ClassPathProvider {
classpath = classpath.plus(moduleRegistry.getExternalModule("logback-classic").getClasspath());
classpath = classpath.plus(moduleRegistry.getExternalModule("logback-core").getClasspath());
classpath = classpath.plus(moduleRegistry.getExternalModule("jul-to-slf4j").getClasspath());
+ classpath = classpath.plus(moduleRegistry.getExternalModule("guava").getClasspath());
return classpath;
}
if (name.equals("WORKER_MAIN")) {
diff --git a/subprojects/core/src/main/groovy/org/gradle/process/internal/shutdown/ShutdownHookActionRegister.java b/subprojects/core/src/main/groovy/org/gradle/process/internal/shutdown/ShutdownHookActionRegister.java
index 24eca1f..bb18e2b 100644
--- a/subprojects/core/src/main/groovy/org/gradle/process/internal/shutdown/ShutdownHookActionRegister.java
+++ b/subprojects/core/src/main/groovy/org/gradle/process/internal/shutdown/ShutdownHookActionRegister.java
@@ -22,9 +22,6 @@ import java.io.IOException;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
-/**
- * @author Tom Eyckmans
- */
public class ShutdownHookActionRegister {
private static final ShutdownHookActionRegister INSTANCE = new ShutdownHookActionRegister();
private final List<Runnable> shutdownHookActions = new CopyOnWriteArrayList<Runnable>();
diff --git a/subprojects/core/src/main/groovy/org/gradle/process/internal/streams/ExecOutputHandleRunner.java b/subprojects/core/src/main/groovy/org/gradle/process/internal/streams/ExecOutputHandleRunner.java
index e1fb0ec..9f4e432 100644
--- a/subprojects/core/src/main/groovy/org/gradle/process/internal/streams/ExecOutputHandleRunner.java
+++ b/subprojects/core/src/main/groovy/org/gradle/process/internal/streams/ExecOutputHandleRunner.java
@@ -25,9 +25,6 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.util.concurrent.Executor;
-/**
- * @author Tom Eyckmans
- */
public class ExecOutputHandleRunner implements Runnable {
private final static Logger LOGGER = Logging.getLogger(ExecOutputHandleRunner.class);
diff --git a/subprojects/core/src/main/groovy/org/gradle/process/internal/streams/SafeStreams.java b/subprojects/core/src/main/groovy/org/gradle/process/internal/streams/SafeStreams.java
index d751b39..990e4f8 100644
--- a/subprojects/core/src/main/groovy/org/gradle/process/internal/streams/SafeStreams.java
+++ b/subprojects/core/src/main/groovy/org/gradle/process/internal/streams/SafeStreams.java
@@ -22,9 +22,6 @@ import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.OutputStream;
-/**
- * by Szczepan Faber, created at: 4/17/12
- */
public class SafeStreams {
public static OutputStream systemErr() {
diff --git a/subprojects/core/src/main/groovy/org/gradle/process/internal/streams/StreamsForwarder.java b/subprojects/core/src/main/groovy/org/gradle/process/internal/streams/StreamsForwarder.java
index 14fd1b2..35efc00 100644
--- a/subprojects/core/src/main/groovy/org/gradle/process/internal/streams/StreamsForwarder.java
+++ b/subprojects/core/src/main/groovy/org/gradle/process/internal/streams/StreamsForwarder.java
@@ -24,9 +24,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-/**
- * by Szczepan Faber, created at: 4/17/12
- */
public class StreamsForwarder implements StreamsHandler {
private final OutputStream standardOutput;
@@ -47,6 +44,11 @@ public class StreamsForwarder implements StreamsHandler {
}
public void connectStreams(Process process, String processName) {
+ /*
+ There's a potential problem here in that DisconnectableInputStream reads from input in the background.
+ This won't automatically stop when the process is over. Therefore, if input is not closed then this thread
+ will run forever. It would be better to ensure that this thread stops when the process does.
+ */
InputStream instr = new DisconnectableInputStream(input);
standardOutputRunner = new ExecOutputHandleRunner("read standard output of: " + processName,
diff --git a/subprojects/core/src/main/groovy/org/gradle/process/internal/streams/StreamsHandler.java b/subprojects/core/src/main/groovy/org/gradle/process/internal/streams/StreamsHandler.java
index f13d605..40e9c83 100644
--- a/subprojects/core/src/main/groovy/org/gradle/process/internal/streams/StreamsHandler.java
+++ b/subprojects/core/src/main/groovy/org/gradle/process/internal/streams/StreamsHandler.java
@@ -18,9 +18,6 @@ package org.gradle.process.internal.streams;
import org.gradle.internal.Stoppable;
-/**
- * by Szczepan Faber, created at: 4/27/12
- */
public interface StreamsHandler extends Stoppable {
void start();
diff --git a/subprojects/core/src/main/groovy/org/gradle/profile/BuildProfile.java b/subprojects/core/src/main/groovy/org/gradle/profile/BuildProfile.java
index d574371..7727436 100644
--- a/subprojects/core/src/main/groovy/org/gradle/profile/BuildProfile.java
+++ b/subprojects/core/src/main/groovy/org/gradle/profile/BuildProfile.java
@@ -15,10 +15,11 @@
*/
package org.gradle.profile;
-import org.gradle.api.Project;
-import org.gradle.api.artifacts.ResolvableDependencies;
-import org.gradle.api.invocation.Gradle;
+import org.gradle.StartParameter;
+import org.gradle.util.CollectionUtils;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
@@ -35,28 +36,26 @@ import java.util.Map;
* <li>setBuildStarted</li>
* <li>setSettingsEvaluated</li>
* <li>setProjectsLoaded</li>
- * <li>setProjectsEvaluated</li>
+ * <li>setProjectsConfigured</li>
* <li>setBuildFinished</li>
* </ul>
*/
public class BuildProfile {
- private final Gradle gradle;
- private final Map<Project, ProjectProfile> projects = new LinkedHashMap<Project, ProjectProfile>();
- private final Map<String, DependencyResolveProfile> dependencySets = new LinkedHashMap<String, DependencyResolveProfile>();
+
+ private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd - HH:mm:ss");
+
+ private final Map<String, ProjectProfile> projects = new LinkedHashMap<String, ProjectProfile>();
+ private final Map<String, ContinuousOperation> dependencySets = new LinkedHashMap<String, ContinuousOperation>();
private long profilingStarted;
private long buildStarted;
private long settingsEvaluated;
private long projectsLoaded;
- private long projectsEvaluated;
private long buildFinished;
+ private StartParameter startParameter;
private boolean successful;
- public BuildProfile(Gradle gradle) {
- this.gradle = gradle;
- }
-
- public Gradle getGradle() {
- return gradle;
+ public BuildProfile(StartParameter startParameter) {
+ this.startParameter = startParameter;
}
public long getBuildStarted() {
@@ -64,33 +63,43 @@ public class BuildProfile {
}
/**
- * Get a description of the tasks passed to gradle as targets from the command line
- * @return
+ * Get a description of this profiled build. It contains info about tasks passed to gradle as targets from the command line.
*/
- public String getTaskDescription() {
- StringBuilder result = new StringBuilder();
- for (String name : gradle.getStartParameter().getExcludedTaskNames()) {
- result.append("-x");
- result.append(name);
- result.append(" ");
+ public String getBuildDescription() {
+ StringBuilder sb = new StringBuilder();
+ for (String name : startParameter.getExcludedTaskNames()) {
+ sb.append("-x ");
+ sb.append(name);
+ sb.append(" ");
}
- for (String name : gradle.getStartParameter().getTaskNames()) {
- result.append(name);
- result.append(" ");
+ for (String name : startParameter.getTaskNames()) {
+ sb.append(name);
+ sb.append(" ");
}
- return result.toString();
+ String tasks = sb.toString();
+ if (tasks.length() == 0) {
+ tasks = "(no tasks specified)";
+ }
+ return String.format("Profiled build: %s", tasks);
+ }
+
+ public boolean isSuccessful() {
+ return successful;
+ }
+
+ public void setSuccessful(boolean successful) {
+ this.successful = successful;
}
/**
* Get the profiling container for the specified project
- * @param project to look up
- * @return
+ * @param projectPath to look up
*/
- public ProjectProfile getProjectProfile(Project project) {
- ProjectProfile result = projects.get(project);
+ public ProjectProfile getProjectProfile(String projectPath) {
+ ProjectProfile result = projects.get(projectPath);
if (result == null) {
- result = new ProjectProfile(project);
- projects.put(project, result);
+ result = new ProjectProfile(projectPath);
+ projects.put(projectPath, result);
}
return result;
}
@@ -100,28 +109,30 @@ public class BuildProfile {
* @return list
*/
public List<ProjectProfile> getProjects() {
- return new ArrayList<ProjectProfile>(projects.values());
+ return CollectionUtils.sort(projects.values(), Operation.slowestFirst());
}
public CompositeOperation<Operation> getProjectConfiguration() {
List<Operation> operations = new ArrayList<Operation>();
for (ProjectProfile projectProfile : projects.values()) {
- operations.add(projectProfile.getEvaluation());
+ operations.add(projectProfile.getConfigurationOperation());
}
+ operations = CollectionUtils.sort(operations, Operation.slowestFirst());
return new CompositeOperation<Operation>(operations);
}
- public DependencyResolveProfile getDependencySetProfile(ResolvableDependencies dependencySet) {
- DependencyResolveProfile profile = dependencySets.get(dependencySet.getPath());
+ public ContinuousOperation getDependencySetProfile(String dependencySetDescription) {
+ ContinuousOperation profile = dependencySets.get(dependencySetDescription);
if (profile == null) {
- profile = new DependencyResolveProfile(dependencySet);
- dependencySets.put(dependencySet.getPath(), profile);
+ profile = new ContinuousOperation(dependencySetDescription);
+ dependencySets.put(dependencySetDescription, profile);
}
return profile;
}
- public CompositeOperation<DependencyResolveProfile> getDependencySets() {
- return new CompositeOperation<DependencyResolveProfile>(dependencySets.values());
+ public CompositeOperation<ContinuousOperation> getDependencySets() {
+ final List<ContinuousOperation> profiles = CollectionUtils.sort(dependencySets.values(), Operation.slowestFirst());
+ return new CompositeOperation<ContinuousOperation>(profiles);
}
/**
@@ -160,15 +171,6 @@ public class BuildProfile {
}
/**
- * Should be set with a timestamp from a {@link org.gradle.BuildListener#projectsEvaluated}
- * callback.
- * @param projectsEvaluated
- */
- public void setProjectsEvaluated(long projectsEvaluated) {
- this.projectsEvaluated = projectsEvaluated;
- }
-
- /**
* Should be set with a timestamp from a {@link org.gradle.BuildListener#buildFinished}
* callback.
* @param buildFinished
@@ -211,38 +213,22 @@ public class BuildProfile {
}
/**
- * Get the elapsed time (in mSec) between the projectsEvaluated event and the projectsLoaded event.
- * @return
- */
- public long getElapsedProjectsEvaluated() {
- return projectsEvaluated - projectsLoaded;
- }
-
- /**
- * Get the elapsed time (in mSec) between the buildFinished event and the projectsEvaluated event.
- * @return
- */
- public long getElapsedAfterProjectsEvaluated() {
- return buildFinished - projectsEvaluated;
- }
-
- /**
* Get the total task execution time from all projects.
* @return
*/
public long getElapsedTotalExecutionTime() {
long result = 0;
for (ProjectProfile projectProfile : projects.values()) {
- result += projectProfile.getTasks().getElapsedTime();
+ result += projectProfile.getElapsedTime();
}
return result;
}
- public boolean isSuccessful() {
- return successful;
+ public String getBuildStartedDescription() {
+ return String.format("Started on: %s", DATE_FORMAT.format(buildStarted));
}
- public void setSuccessful(boolean successful) {
- this.successful = successful;
+ public StartParameter getStartParameter() {
+ return startParameter;
}
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/profile/CompositeOperation.java b/subprojects/core/src/main/groovy/org/gradle/profile/CompositeOperation.java
index 6965bd4..4fe6b75 100644
--- a/subprojects/core/src/main/groovy/org/gradle/profile/CompositeOperation.java
+++ b/subprojects/core/src/main/groovy/org/gradle/profile/CompositeOperation.java
@@ -47,4 +47,8 @@ public class CompositeOperation<T extends Operation> extends Operation implement
}
return sum;
}
+
+ public String getDescription() {
+ return "<composite operation>";
+ }
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/profile/ContinuousOperation.java b/subprojects/core/src/main/groovy/org/gradle/profile/ContinuousOperation.java
index c0b342c..2e647e1 100644
--- a/subprojects/core/src/main/groovy/org/gradle/profile/ContinuousOperation.java
+++ b/subprojects/core/src/main/groovy/org/gradle/profile/ContinuousOperation.java
@@ -21,13 +21,25 @@ package org.gradle.profile;
public class ContinuousOperation extends Operation {
private long start;
private long finish;
+ private String description;
- public void setStart(long start) {
+ public ContinuousOperation(String description) {
+ this.description = description;
+ }
+
+ @Override
+ public String toString() {
+ return description;
+ }
+
+ public ContinuousOperation setStart(long start) {
this.start = start;
+ return this;
}
- public void setFinish(long finish) {
+ public ContinuousOperation setFinish(long finish) {
this.finish = finish;
+ return this;
}
public long getStartTime() {
@@ -37,4 +49,8 @@ public class ContinuousOperation extends Operation {
public long getElapsedTime() {
return finish - start;
}
+
+ public String getDescription() {
+ return description;
+ }
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/profile/DependencyResolveProfile.java b/subprojects/core/src/main/groovy/org/gradle/profile/DependencyResolveProfile.java
deleted file mode 100644
index 8c703a5..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/profile/DependencyResolveProfile.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.profile;
-
-import org.gradle.api.artifacts.ResolvableDependencies;
-
-public class DependencyResolveProfile extends ContinuousOperation {
- private final ResolvableDependencies dependencySet;
-
- public DependencyResolveProfile(ResolvableDependencies dependencySet) {
- this.dependencySet = dependencySet;
- }
-
- public String getPath() {
- return dependencySet.getPath();
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/profile/EvalutationOperation.java b/subprojects/core/src/main/groovy/org/gradle/profile/EvalutationOperation.java
deleted file mode 100644
index b886e07..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/profile/EvalutationOperation.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2013 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.profile;
-
-import org.gradle.api.Project;
-
-public class EvalutationOperation extends ContinuousOperation {
- private final Project project;
-
- public EvalutationOperation(Project project) {
- this.project = project;
- }
-
- public String getPath(){
- return project.getPath();
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/profile/Operation.java b/subprojects/core/src/main/groovy/org/gradle/profile/Operation.java
index 591b71e..453b924 100644
--- a/subprojects/core/src/main/groovy/org/gradle/profile/Operation.java
+++ b/subprojects/core/src/main/groovy/org/gradle/profile/Operation.java
@@ -15,6 +15,8 @@
*/
package org.gradle.profile;
+import java.util.Comparator;
+
/**
* A general operation.
*/
@@ -23,4 +25,23 @@ public abstract class Operation {
* Returns the total elapsed execution time of this operation in millis.
*/
abstract long getElapsedTime();
+
+ abstract String getDescription();
+
+ /**
+ * @return comparator that compares operations, slowest first, then alphabetically
+ */
+ public static Comparator<? super Operation> slowestFirst() {
+ return new Comparator<Operation>() {
+ public int compare(Operation o1, Operation o2) {
+ long byElapsedTime = o2.getElapsedTime() - o1.getElapsedTime();
+ if (byElapsedTime > 0) {
+ return 1;
+ } else if (byElapsedTime < 0) {
+ return -1;
+ }
+ return o1.getDescription().compareTo(o2.getDescription());
+ }
+ };
+ }
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/profile/ProfileEventAdapter.java b/subprojects/core/src/main/groovy/org/gradle/profile/ProfileEventAdapter.java
index 81228bd..f28693c 100644
--- a/subprojects/core/src/main/groovy/org/gradle/profile/ProfileEventAdapter.java
+++ b/subprojects/core/src/main/groovy/org/gradle/profile/ProfileEventAdapter.java
@@ -47,8 +47,9 @@ public class ProfileEventAdapter implements BuildListener, ProjectEvaluationList
// BuildListener
public void buildStarted(Gradle gradle) {
- buildProfile = new BuildProfile(gradle);
- buildProfile.setBuildStarted(timeProvider.getCurrentTime());
+ long now = timeProvider.getCurrentTime();
+ buildProfile = new BuildProfile(gradle.getStartParameter());
+ buildProfile.setBuildStarted(now);
buildProfile.setProfilingStarted(buildMetaData.getBuildTimeClock().getStartTime());
}
@@ -60,9 +61,7 @@ public class ProfileEventAdapter implements BuildListener, ProjectEvaluationList
buildProfile.setProjectsLoaded(timeProvider.getCurrentTime());
}
- public void projectsEvaluated(Gradle gradle) {
- buildProfile.setProjectsEvaluated(timeProvider.getCurrentTime());
- }
+ public void projectsEvaluated(Gradle gradle) {}
public void buildFinished(BuildResult result) {
buildProfile.setBuildFinished(timeProvider.getCurrentTime());
@@ -76,39 +75,42 @@ public class ProfileEventAdapter implements BuildListener, ProjectEvaluationList
// ProjectEvaluationListener
public void beforeEvaluate(Project project) {
- buildProfile.getProjectProfile(project).getEvaluation().setStart(System.currentTimeMillis());
+ long now = timeProvider.getCurrentTime();
+ buildProfile.getProjectProfile(project.getPath()).getConfigurationOperation().setStart(now);
}
public void afterEvaluate(Project project, ProjectState state) {
- ProjectProfile projectProfile = buildProfile.getProjectProfile(project);
- projectProfile.getEvaluation().setFinish(timeProvider.getCurrentTime());
- projectProfile.setState(state);
+ long now = timeProvider.getCurrentTime();
+ ProjectProfile projectProfile = buildProfile.getProjectProfile(project.getPath());
+ projectProfile.getConfigurationOperation().setFinish(now);
}
// TaskExecutionListener
public void beforeExecute(Task task) {
+ long now = timeProvider.getCurrentTime();
Project project = task.getProject();
- ProjectProfile projectProfile = buildProfile.getProjectProfile(project);
- projectProfile.getTaskProfile(task).setStart(timeProvider.getCurrentTime());
+ ProjectProfile projectProfile = buildProfile.getProjectProfile(project.getPath());
+ projectProfile.getTaskProfile(task.getPath()).setStart(now);
}
public void afterExecute(Task task, TaskState state) {
+ long now = timeProvider.getCurrentTime();
Project project = task.getProject();
- ProjectProfile projectProfile = buildProfile.getProjectProfile(project);
- TaskExecution taskExecution = projectProfile.getTaskProfile(task);
- taskExecution.setFinish(timeProvider.getCurrentTime());
- taskExecution.setState(state);
+ ProjectProfile projectProfile = buildProfile.getProjectProfile(project.getPath());
+ TaskExecution taskExecution = projectProfile.getTaskProfile(task.getPath());
+ taskExecution.setFinish(now);
+ taskExecution.completed(state);
}
// DependencyResolutionListener
public void beforeResolve(ResolvableDependencies dependencies) {
- DependencyResolveProfile profile = buildProfile.getDependencySetProfile(dependencies);
- profile.setStart(timeProvider.getCurrentTime());
+ long now = timeProvider.getCurrentTime();
+ buildProfile.getDependencySetProfile(dependencies.getPath()).setStart(now);
}
public void afterResolve(ResolvableDependencies dependencies) {
- DependencyResolveProfile profile = buildProfile.getDependencySetProfile(dependencies);
- profile.setFinish(timeProvider.getCurrentTime());
+ long now = timeProvider.getCurrentTime();
+ buildProfile.getDependencySetProfile(dependencies.getPath()).setFinish(now);
}
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/profile/ProfileReportRenderer.java b/subprojects/core/src/main/groovy/org/gradle/profile/ProfileReportRenderer.java
index 9f5f6e4..3db502b 100644
--- a/subprojects/core/src/main/groovy/org/gradle/profile/ProfileReportRenderer.java
+++ b/subprojects/core/src/main/groovy/org/gradle/profile/ProfileReportRenderer.java
@@ -20,16 +20,10 @@ import org.gradle.reporting.DurationFormatter;
import org.gradle.reporting.HtmlReportRenderer;
import org.gradle.reporting.ReportRenderer;
import org.gradle.reporting.TabbedPageRenderer;
-import org.gradle.util.CollectionUtils;
import java.io.File;
import java.io.IOException;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.Comparator;
-import java.util.List;
-//TODO SF add coverage
public class ProfileReportRenderer {
public void writeTo(BuildProfile buildProfile, File file) {
HtmlReportRenderer renderer = new HtmlReportRenderer();
@@ -42,8 +36,6 @@ public class ProfileReportRenderer {
private static final DurationFormatter DURATION_FORMAT = new DurationFormatter();
private static class ProfilePageRenderer extends TabbedPageRenderer<BuildProfile> {
- static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd - HH:mm:ss");
-
@Override
protected String getTitle() {
return "Profile report";
@@ -55,8 +47,8 @@ public class ProfileReportRenderer {
@Override
public void render(BuildProfile model, SimpleHtmlWriter htmlWriter) throws IOException {
htmlWriter.startElement("div").attribute("id", "header")
- .startElement("p").characters(String.format("Profiled with tasks: %s", model.getTaskDescription())).endElement()
- .startElement("p").characters(String.format("Run on: %s", DATE_FORMAT.format(model.getBuildStarted()))).endElement()
+ .startElement("p").characters(model.getBuildDescription()).endElement()
+ .startElement("p").characters(model.getBuildStartedDescription()).endElement()
.endElement();
}
};
@@ -67,6 +59,8 @@ public class ProfileReportRenderer {
return new ReportRenderer<BuildProfile, SimpleHtmlWriter>() {
@Override
public void render(BuildProfile model, SimpleHtmlWriter htmlWriter) throws IOException {
+ CompositeOperation<Operation> profiledProjectConfiguration = model.getProjectConfiguration();
+
htmlWriter.startElement("div").attribute("id", "tabs")
.startElement("ul").attribute("class", "tabLinks")
.startElement("li").startElement("a").attribute("href", "#tab0").characters("Summary").endElement().endElement()
@@ -101,7 +95,7 @@ public class ProfileReportRenderer {
htmlWriter.endElement();
htmlWriter.startElement("tr");
htmlWriter.startElement("td").characters("Configuring Projects").endElement();
- htmlWriter.startElement("td").attribute("class", "numeric").characters(DURATION_FORMAT.format(model.getElapsedAfterProjectsEvaluated())).endElement();
+ htmlWriter.startElement("td").attribute("class", "numeric").characters(DURATION_FORMAT.format(profiledProjectConfiguration.getElapsedTime())).endElement();
htmlWriter.endElement();
htmlWriter.startElement("tr");
htmlWriter.startElement("td").characters("Task Execution").endElement();
@@ -120,18 +114,12 @@ public class ProfileReportRenderer {
htmlWriter.endElement();
htmlWriter.startElement("tr");
htmlWriter.startElement("td").characters("All projects").endElement();
- htmlWriter.startElement("td").attribute("class", "numeric").characters(DURATION_FORMAT.format(model.getProjectConfiguration().getElapsedTime())).endElement();
+ htmlWriter.startElement("td").attribute("class", "numeric").characters(DURATION_FORMAT.format(profiledProjectConfiguration.getElapsedTime())).endElement();
htmlWriter.endElement();
- final List<Operation> operations = CollectionUtils.sort(model.getProjectConfiguration().getOperations(), new Comparator<Operation>() {
- public int compare(Operation o1, Operation o2) {
- return Long.valueOf(o2.getElapsedTime()).compareTo(Long.valueOf(o1.getElapsedTime()));
- }
- });
- for (Operation operation : operations) {
- EvalutationOperation evalOperation = (EvalutationOperation)operation;
+ for (Operation operation : profiledProjectConfiguration) {
htmlWriter.startElement("tr");
- htmlWriter.startElement("td").characters(evalOperation.getPath()).endElement();
- htmlWriter.startElement("td").attribute("class", "numeric").characters(DURATION_FORMAT.format(evalOperation.getElapsedTime())).endElement();
+ htmlWriter.startElement("td").characters(operation.getDescription()).endElement();
+ htmlWriter.startElement("td").attribute("class", "numeric").characters(DURATION_FORMAT.format(operation.getElapsedTime())).endElement();
htmlWriter.endElement();
}
htmlWriter.endElement()
@@ -150,15 +138,10 @@ public class ProfileReportRenderer {
htmlWriter.startElement("td").attribute("class", "numeric").characters(DURATION_FORMAT.format(model.getDependencySets().getElapsedTime())).endElement();
htmlWriter.endElement();
- final List<DependencyResolveProfile> dependencyResolveProfiles = CollectionUtils.sort(model.getDependencySets().getOperations(), new Comparator<DependencyResolveProfile>() {
- public int compare(DependencyResolveProfile p1, DependencyResolveProfile p2) {
- return Long.valueOf(p2.getElapsedTime()).compareTo(Long.valueOf(p1.getElapsedTime()));
- }
- });
- for (DependencyResolveProfile profile : dependencyResolveProfiles) {
+ for (Operation operation : model.getDependencySets()) {
htmlWriter.startElement("tr");
- htmlWriter.startElement("td").characters(profile.getPath()).endElement();
- htmlWriter.startElement("td").attribute("class", "numeric").characters(DURATION_FORMAT.format(profile.getElapsedTime())).endElement();
+ htmlWriter.startElement("td").characters(operation.getDescription()).endElement();
+ htmlWriter.startElement("td").attribute("class", "numeric").characters(DURATION_FORMAT.format(operation.getElapsedTime())).endElement();
htmlWriter.endElement();
}
htmlWriter.endElement()
@@ -173,27 +156,17 @@ public class ProfileReportRenderer {
.startElement("th").characters("Result").endElement()
.endElement()
.endElement();
- final List<ProjectProfile> projects = CollectionUtils.sort(model.getProjects(), new Comparator<ProjectProfile>() {
- public int compare(ProjectProfile p1, ProjectProfile p2) {
- return Long.valueOf(p2.getTasks().getElapsedTime()).compareTo(p1.getTasks().getElapsedTime());
- }
- });
- for (ProjectProfile project : projects) {
+ for (ProjectProfile project : model.getProjects()) {
htmlWriter.startElement("tr")
.startElement("td").characters(project.getPath()).endElement()
- .startElement("td").attribute("class", "numeric").characters(DURATION_FORMAT.format(project.getTasks().getElapsedTime())).endElement()
+ .startElement("td").attribute("class", "numeric").characters(DURATION_FORMAT.format(project.getElapsedTime())).endElement()
.startElement("td").characters("(total)").endElement()
.endElement();
- final List<TaskExecution> taskExecutions = CollectionUtils.sort(project.getTasks().getOperations(), new Comparator<TaskExecution>() {
- public int compare(TaskExecution p1, TaskExecution p2) {
- return Long.valueOf(p2.getElapsedTime()).compareTo(Long.valueOf(p1.getElapsedTime()));
- }
- });
- for (TaskExecution taskExecution : taskExecutions) {
+ for (TaskExecution taskExecution : project.getTasks()) {
htmlWriter.startElement("tr")
.startElement("td").attribute("class", "indentPath").characters(taskExecution.getPath()).endElement()
.startElement("td").attribute("class", "numeric").characters(DURATION_FORMAT.format(taskExecution.getElapsedTime())).endElement()
- .startElement("td").characters(taskExecution.getState().getSkipped() ? taskExecution.getState().getSkipMessage() : (taskExecution.getState().getDidWork()) ? "" : "Did No Work").endElement()
+ .startElement("td").characters(taskExecution.getStatus()).endElement()
.endElement();
}
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/profile/ProjectProfile.java b/subprojects/core/src/main/groovy/org/gradle/profile/ProjectProfile.java
index e7abbe5..d0d2852 100644
--- a/subprojects/core/src/main/groovy/org/gradle/profile/ProjectProfile.java
+++ b/subprojects/core/src/main/groovy/org/gradle/profile/ProjectProfile.java
@@ -15,31 +15,29 @@
*/
package org.gradle.profile;
-import org.gradle.api.Project;
-import org.gradle.api.ProjectState;
-import org.gradle.api.Task;
+import org.gradle.util.CollectionUtils;
import java.util.HashMap;
+import java.util.List;
-public class ProjectProfile {
- private final Project project;
- private ProjectState state;
- private HashMap<Task, TaskExecution> tasks = new HashMap<Task, TaskExecution>();
- private final ContinuousOperation evaluation;
+public class ProjectProfile extends Operation {
+ private HashMap<String, TaskExecution> tasks = new HashMap<String, TaskExecution>();
+ private final ContinuousOperation configurationOperation;
+ private String projectPath;
- public ProjectProfile(Project project) {
- this.project = project;
- this.evaluation = new EvalutationOperation(project);
+ public ProjectProfile(String projectPath) {
+ this.projectPath = projectPath;
+ this.configurationOperation = new ContinuousOperation(projectPath);
}
/**
* Gets the task profiling container for the specified task.
*/
- public TaskExecution getTaskProfile(Task task) {
- TaskExecution result = tasks.get(task);
+ public TaskExecution getTaskProfile(String taskPath) {
+ TaskExecution result = tasks.get(taskPath);
if (result == null) {
- result = new TaskExecution(task);
- tasks.put(task, result);
+ result = new TaskExecution(taskPath);
+ tasks.put(taskPath, result);
}
return result;
}
@@ -48,31 +46,33 @@ public class ProjectProfile {
* Returns the task executions for this project.
*/
public CompositeOperation<TaskExecution> getTasks() {
- return new CompositeOperation<TaskExecution>(tasks.values());
+ List<TaskExecution> taskExecutions = CollectionUtils.sort(tasks.values(), Operation.slowestFirst());
+ return new CompositeOperation<TaskExecution>(taskExecutions);
}
/**
* Get the String project path.
*/
public String getPath() {
- return project.getPath();
+ return projectPath;
}
/**
- * Returns the evaluation time of this project.
+ * Returns the configuration time of this project.
*/
- public ContinuousOperation getEvaluation() {
- return evaluation;
+ public ContinuousOperation getConfigurationOperation() {
+ return configurationOperation;
}
- /**
- * Gets the state of the project after evaluation finishes.
- */
- public ProjectState getState() {
- return state;
+ public String toString() {
+ return projectPath;
+ }
+
+ public String getDescription() {
+ return projectPath;
}
- public void setState(ProjectState state) {
- this.state = state;
+ long getElapsedTime() {
+ return getTasks().getElapsedTime();
}
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/profile/TaskExecution.java b/subprojects/core/src/main/groovy/org/gradle/profile/TaskExecution.java
index e322a82..2596879 100644
--- a/subprojects/core/src/main/groovy/org/gradle/profile/TaskExecution.java
+++ b/subprojects/core/src/main/groovy/org/gradle/profile/TaskExecution.java
@@ -15,34 +15,41 @@
*/
package org.gradle.profile;
-import org.gradle.api.Task;
import org.gradle.api.tasks.TaskState;
/**
* Container for task profiling information.
- * This includes timestamps around task execution and the resulting TaskState.
+ * This includes timestamps around task execution and the resulting task status.
*/
public class TaskExecution extends ContinuousOperation {
- private final Task task;
+
+ final static String NO_WORK_MESSAGE = "Did No Work";
+
+ private final String path;
private TaskState state;
- public TaskExecution(Task task) {
- this.task = task;
+ public TaskExecution(String taskPath) {
+ super(taskPath);
+ this.path = taskPath;
}
/**
* Gets the string task path.
- * @return
*/
public String getPath() {
- return task.getPath();
+ return path;
+ }
+
+ public String getStatus() {
+ return state.getSkipped() ? state.getSkipMessage() : (state.getDidWork()) ? "" : NO_WORK_MESSAGE;
}
public TaskState getState() {
return state;
}
- public void setState(TaskState state) {
+ public TaskExecution completed(TaskState state) {
this.state = state;
+ return this;
}
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/reporting/ReportRenderer.java b/subprojects/core/src/main/groovy/org/gradle/reporting/ReportRenderer.java
index 328acff..d3142c8 100644
--- a/subprojects/core/src/main/groovy/org/gradle/reporting/ReportRenderer.java
+++ b/subprojects/core/src/main/groovy/org/gradle/reporting/ReportRenderer.java
@@ -20,7 +20,7 @@ import java.io.IOException;
public abstract class ReportRenderer<T, E> {
/**
- * Renders the report for the given model as children of the given DOM element.
+ * Renders the report for the given model to the given output.
*/
- public abstract void render(T model, E parent) throws IOException;
+ public abstract void render(T model, E output) throws IOException;
}
\ No newline at end of file
diff --git a/subprojects/core/src/main/groovy/org/gradle/testfixtures/internal/GlobalTestServices.java b/subprojects/core/src/main/groovy/org/gradle/testfixtures/internal/GlobalTestServices.java
deleted file mode 100644
index 168bc85..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/testfixtures/internal/GlobalTestServices.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.testfixtures.internal;
-
-import org.gradle.api.internal.project.GlobalServicesRegistry;
-import org.gradle.internal.Factory;
-import org.gradle.internal.TrueTimeProvider;
-import org.gradle.internal.service.DefaultServiceRegistry;
-import org.gradle.listener.DefaultListenerManager;
-import org.gradle.listener.ListenerManager;
-import org.gradle.logging.LoggingManagerInternal;
-import org.gradle.logging.ProgressLoggerFactory;
-import org.gradle.logging.StyledTextOutputFactory;
-import org.gradle.logging.internal.DefaultProgressLoggerFactory;
-import org.gradle.logging.internal.DefaultStyledTextOutputFactory;
-import org.gradle.logging.internal.OutputEventListener;
-import org.gradle.logging.internal.ProgressListener;
-
-public class GlobalTestServices extends GlobalServicesRegistry {
- public GlobalTestServices() {
- super(new TestLoggingServices());
- }
-
- private static class TestLoggingServices extends DefaultServiceRegistry {
- final ListenerManager listenerManager = new DefaultListenerManager();
-
- protected ProgressLoggerFactory createProgressLoggerFactory() {
- return new DefaultProgressLoggerFactory(listenerManager.getBroadcaster(ProgressListener.class), new TrueTimeProvider());
- }
-
- protected Factory<LoggingManagerInternal> createLoggingManagerFactory() {
- return new Factory<LoggingManagerInternal>() {
- public LoggingManagerInternal create() {
- return new NoOpLoggingManager();
- }
- };
- }
-
- protected StyledTextOutputFactory createStyledTextOutputFactory() {
- return new DefaultStyledTextOutputFactory(listenerManager.getBroadcaster(OutputEventListener.class), new TrueTimeProvider());
- }
-
- protected TestOutputEventListener createStubOutputEventListener() {
- return new TestOutputEventListener();
- }
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/testfixtures/internal/InMemoryCacheFactory.java b/subprojects/core/src/main/groovy/org/gradle/testfixtures/internal/InMemoryCacheFactory.java
index 3f802b2..b9f5d27 100644
--- a/subprojects/core/src/main/groovy/org/gradle/testfixtures/internal/InMemoryCacheFactory.java
+++ b/subprojects/core/src/main/groovy/org/gradle/testfixtures/internal/InMemoryCacheFactory.java
@@ -17,7 +17,6 @@ package org.gradle.testfixtures.internal;
import org.gradle.CacheUsage;
import org.gradle.api.Action;
-import org.gradle.api.internal.changedetection.InMemoryIndexedCache;
import org.gradle.cache.*;
import org.gradle.cache.internal.*;
import org.gradle.internal.Factory;
diff --git a/subprojects/core/src/main/groovy/org/gradle/testfixtures/internal/InMemoryIndexedCache.java b/subprojects/core/src/main/groovy/org/gradle/testfixtures/internal/InMemoryIndexedCache.java
new file mode 100644
index 0000000..cdea768
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/testfixtures/internal/InMemoryIndexedCache.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.testfixtures.internal;
+
+import org.gradle.cache.PersistentIndexedCache;
+import org.gradle.internal.UncheckedException;
+import org.gradle.messaging.serialize.InputStreamBackedDecoder;
+import org.gradle.messaging.serialize.OutputStreamBackedEncoder;
+import org.gradle.messaging.serialize.Serializer;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A simple in-memory cache, used by the testing fixtures.
+ */
+public class InMemoryIndexedCache<K, V> implements PersistentIndexedCache<K, V> {
+ private final Map<Object, byte[]> entries = new HashMap<Object, byte[]>();
+ private final Serializer<V> valueSerializer;
+
+ public InMemoryIndexedCache(Serializer<V> valueSerializer) {
+ this.valueSerializer = valueSerializer;
+ }
+
+ public V get(K key) {
+ byte[] serialised = entries.get(key);
+ if (serialised == null) {
+ return null;
+ }
+ try {
+ ByteArrayInputStream instr = new ByteArrayInputStream(serialised);
+ InputStreamBackedDecoder decoder = new InputStreamBackedDecoder(instr);
+ return valueSerializer.read(decoder);
+ } catch (Exception e) {
+ throw UncheckedException.throwAsUncheckedException(e);
+ }
+ }
+
+ public void put(K key, V value) {
+ ByteArrayOutputStream outstr = new ByteArrayOutputStream();
+ OutputStreamBackedEncoder encoder = new OutputStreamBackedEncoder(outstr);
+ try {
+ valueSerializer.write(encoder, value);
+ encoder.flush();
+ } catch (Exception e) {
+ throw UncheckedException.throwAsUncheckedException(e);
+ }
+
+ entries.put(key, outstr.toByteArray());
+ }
+
+ public void remove(K key) {
+ entries.remove(key);
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/testfixtures/internal/ProjectBuilderImpl.java b/subprojects/core/src/main/groovy/org/gradle/testfixtures/internal/ProjectBuilderImpl.java
index 51a8bb2..42cbe8a 100644
--- a/subprojects/core/src/main/groovy/org/gradle/testfixtures/internal/ProjectBuilderImpl.java
+++ b/subprojects/core/src/main/groovy/org/gradle/testfixtures/internal/ProjectBuilderImpl.java
@@ -20,25 +20,25 @@ import org.gradle.StartParameter;
import org.gradle.api.Project;
import org.gradle.api.internal.AsmBackedClassGenerator;
import org.gradle.api.internal.GradleInternal;
+import org.gradle.api.internal.file.BaseDirFileResolver;
import org.gradle.api.internal.file.TemporaryFileProvider;
import org.gradle.api.internal.file.TmpDirTemporaryFileProvider;
import org.gradle.api.internal.project.DefaultProject;
import org.gradle.api.internal.project.IProjectFactory;
import org.gradle.api.internal.project.ProjectInternal;
-import org.gradle.api.internal.project.ServiceRegistryFactory;
+import org.gradle.internal.nativeplatform.filesystem.FileSystems;
+import org.gradle.internal.service.scopes.ServiceRegistryFactory;
import org.gradle.groovy.scripts.StringScriptSource;
import org.gradle.initialization.DefaultProjectDescriptor;
import org.gradle.initialization.DefaultProjectDescriptorRegistry;
+import org.gradle.invocation.BuildClassLoaderRegistry;
import org.gradle.invocation.DefaultGradle;
import org.gradle.util.GFileUtils;
import java.io.File;
-/**
- * by Szczepan Faber, created at: 10/1/11
- */
public class ProjectBuilderImpl {
- private static final GlobalTestServices GLOBAL_SERVICES = new GlobalTestServices();
+ private static final TestGlobalScopeServices GLOBAL_SERVICES = new TestGlobalScopeServices();
private static final AsmBackedClassGenerator CLASS_GENERATOR = new AsmBackedClassGenerator();
public Project createChildProject(String name, Project parent, File projectDir) {
@@ -65,16 +65,17 @@ public class ProjectBuilderImpl {
StartParameter startParameter = new StartParameter();
startParameter.setGradleUserHomeDir(new File(projectDir, "userHome"));
- ServiceRegistryFactory topLevelRegistry = new TestTopLevelBuildServiceRegistry(GLOBAL_SERVICES, startParameter, homeDir);
+ ServiceRegistryFactory topLevelRegistry = new TestBuildScopeServices(GLOBAL_SERVICES, startParameter, homeDir);
GradleInternal gradle = new DefaultGradle(null, startParameter, topLevelRegistry);
- DefaultProjectDescriptor projectDescriptor = new DefaultProjectDescriptor(null, name, projectDir, new DefaultProjectDescriptorRegistry());
+ DefaultProjectDescriptor projectDescriptor = new DefaultProjectDescriptor(null, name, projectDir, new DefaultProjectDescriptorRegistry(),
+ new BaseDirFileResolver(FileSystems.getDefault(), projectDir));
ProjectInternal project = topLevelRegistry.get(IProjectFactory.class).createProject(projectDescriptor, null, gradle);
gradle.setRootProject(project);
gradle.setDefaultProject(project);
- gradle.getScriptClassLoader().addParent(getClass().getClassLoader());
+ gradle.getServices().get(BuildClassLoaderRegistry.class).addRootClassLoader(getClass().getClassLoader());
return project;
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/testfixtures/internal/TestBuildScopeServices.java b/subprojects/core/src/main/groovy/org/gradle/testfixtures/internal/TestBuildScopeServices.java
new file mode 100644
index 0000000..6fd3af3
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/testfixtures/internal/TestBuildScopeServices.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.testfixtures.internal;
+
+import org.gradle.StartParameter;
+import org.gradle.api.internal.GradleDistributionLocator;
+import org.gradle.internal.service.scopes.BuildScopeServices;
+import org.gradle.cache.internal.CacheFactory;
+import org.gradle.configuration.GradleLauncherMetaData;
+import org.gradle.initialization.BuildClientMetaData;
+import org.gradle.internal.service.ServiceRegistry;
+
+import java.io.File;
+
+public class TestBuildScopeServices extends BuildScopeServices {
+ private final File homeDir;
+
+ public TestBuildScopeServices(ServiceRegistry parent, StartParameter startParameter, File homeDir) {
+ super(parent, startParameter);
+ this.homeDir = homeDir;
+ }
+
+ protected BuildClientMetaData createClientMetaData() {
+ return new GradleLauncherMetaData();
+ }
+
+ @Override
+ protected CacheFactory createCacheFactory() {
+ return new InMemoryCacheFactory();
+ }
+
+ protected GradleDistributionLocator createGradleDistributionLocator() {
+ return new GradleDistributionLocator() {
+ public File getGradleHome() {
+ return homeDir;
+ }
+ };
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/testfixtures/internal/TestGlobalScopeServices.java b/subprojects/core/src/main/groovy/org/gradle/testfixtures/internal/TestGlobalScopeServices.java
new file mode 100644
index 0000000..72c3aea
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/testfixtures/internal/TestGlobalScopeServices.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.testfixtures.internal;
+
+import org.gradle.internal.service.scopes.GlobalScopeServices;
+import org.gradle.internal.Factory;
+import org.gradle.internal.TrueTimeProvider;
+import org.gradle.internal.service.DefaultServiceRegistry;
+import org.gradle.listener.DefaultListenerManager;
+import org.gradle.listener.ListenerManager;
+import org.gradle.logging.LoggingManagerInternal;
+import org.gradle.logging.ProgressLoggerFactory;
+import org.gradle.logging.StyledTextOutputFactory;
+import org.gradle.logging.internal.DefaultProgressLoggerFactory;
+import org.gradle.logging.internal.DefaultStyledTextOutputFactory;
+import org.gradle.logging.internal.OutputEventListener;
+import org.gradle.logging.internal.ProgressListener;
+
+public class TestGlobalScopeServices extends GlobalScopeServices {
+ public TestGlobalScopeServices() {
+ super(new TestLoggingServices());
+ }
+
+ private static class TestLoggingServices extends DefaultServiceRegistry {
+ final ListenerManager listenerManager = new DefaultListenerManager();
+
+ protected ProgressLoggerFactory createProgressLoggerFactory() {
+ return new DefaultProgressLoggerFactory(listenerManager.getBroadcaster(ProgressListener.class), new TrueTimeProvider());
+ }
+
+ protected Factory<LoggingManagerInternal> createLoggingManagerFactory() {
+ return new Factory<LoggingManagerInternal>() {
+ public LoggingManagerInternal create() {
+ return new NoOpLoggingManager();
+ }
+ };
+ }
+
+ protected StyledTextOutputFactory createStyledTextOutputFactory() {
+ return new DefaultStyledTextOutputFactory(listenerManager.getBroadcaster(OutputEventListener.class), new TrueTimeProvider());
+ }
+
+ protected TestOutputEventListener createStubOutputEventListener() {
+ return new TestOutputEventListener();
+ }
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/testfixtures/internal/TestTopLevelBuildServiceRegistry.java b/subprojects/core/src/main/groovy/org/gradle/testfixtures/internal/TestTopLevelBuildServiceRegistry.java
deleted file mode 100644
index 09bc272..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/testfixtures/internal/TestTopLevelBuildServiceRegistry.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.testfixtures.internal;
-
-import org.gradle.StartParameter;
-import org.gradle.api.internal.GradleDistributionLocator;
-import org.gradle.api.internal.project.TopLevelBuildServiceRegistry;
-import org.gradle.cache.internal.CacheFactory;
-import org.gradle.configuration.GradleLauncherMetaData;
-import org.gradle.initialization.BuildClientMetaData;
-import org.gradle.internal.service.ServiceRegistry;
-
-import java.io.File;
-
-public class TestTopLevelBuildServiceRegistry extends TopLevelBuildServiceRegistry {
- private final File homeDir;
-
- public TestTopLevelBuildServiceRegistry(ServiceRegistry parent, StartParameter startParameter, File homeDir) {
- super(parent, startParameter);
- this.homeDir = homeDir;
- }
-
- protected BuildClientMetaData createClientMetaData() {
- return new GradleLauncherMetaData();
- }
-
- @Override
- protected CacheFactory createCacheFactory() {
- return new InMemoryCacheFactory();
- }
-
- protected GradleDistributionLocator createGradleDistributionLocator() {
- return new GradleDistributionLocator() {
- public File getGradleHome() {
- return homeDir;
- }
- };
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/tooling/provider/model/ToolingModelBuilder.java b/subprojects/core/src/main/groovy/org/gradle/tooling/provider/model/ToolingModelBuilder.java
new file mode 100644
index 0000000..2b394b5
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/tooling/provider/model/ToolingModelBuilder.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.provider.model;
+
+import org.gradle.api.Incubating;
+import org.gradle.api.Project;
+
+/**
+ * Responsible for building tooling models.
+ */
+ at Incubating
+public interface ToolingModelBuilder {
+ boolean canBuild(String modelName);
+ Object buildAll(String modelName, Project project);
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/tooling/provider/model/ToolingModelBuilderRegistry.java b/subprojects/core/src/main/groovy/org/gradle/tooling/provider/model/ToolingModelBuilderRegistry.java
new file mode 100644
index 0000000..5757d23
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/tooling/provider/model/ToolingModelBuilderRegistry.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.provider.model;
+
+import org.gradle.api.Incubating;
+
+/**
+ * A registry of tooling model builders. Adding a builder to this registry makes a model (or models) available via the tooling API.
+ */
+ at Incubating
+public interface ToolingModelBuilderRegistry {
+ void register(ToolingModelBuilder builder);
+
+ ToolingModelBuilder getBuilder(String modelName) throws UnknownModelException;
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/tooling/provider/model/UnknownModelException.java b/subprojects/core/src/main/groovy/org/gradle/tooling/provider/model/UnknownModelException.java
new file mode 100644
index 0000000..f66d460
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/tooling/provider/model/UnknownModelException.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.provider.model;
+
+import org.gradle.api.GradleException;
+import org.gradle.api.Incubating;
+
+/**
+ * Thrown when an unknown tooling model is requested.
+ */
+ at Incubating
+public class UnknownModelException extends GradleException {
+ public UnknownModelException(String message) {
+ super(message);
+ }
+}
+
diff --git a/subprojects/core/src/main/groovy/org/gradle/tooling/provider/model/internal/DefaultToolingModelBuilderRegistry.java b/subprojects/core/src/main/groovy/org/gradle/tooling/provider/model/internal/DefaultToolingModelBuilderRegistry.java
new file mode 100644
index 0000000..2837773
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/tooling/provider/model/internal/DefaultToolingModelBuilderRegistry.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.provider.model.internal;
+
+import org.gradle.api.Project;
+import org.gradle.tooling.provider.model.ToolingModelBuilder;
+import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry;
+import org.gradle.tooling.provider.model.UnknownModelException;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class DefaultToolingModelBuilderRegistry implements ToolingModelBuilderRegistry {
+ private final List<ToolingModelBuilder> builders = new ArrayList<ToolingModelBuilder>();
+
+ public DefaultToolingModelBuilderRegistry() {
+ register(new VoidToolingModelBuilder());
+ }
+
+ public void register(ToolingModelBuilder builder) {
+ builders.add(builder);
+ }
+
+ public ToolingModelBuilder getBuilder(String modelName) throws UnsupportedOperationException {
+ ToolingModelBuilder match = null;
+ for (ToolingModelBuilder builder : builders) {
+ if (builder.canBuild(modelName)) {
+ if (match != null) {
+ throw new UnsupportedOperationException(String.format("Multiple builders are available to build a model of type '%s'.", modelName));
+ }
+ match = builder;
+ }
+ }
+ if (match != null) {
+ return match;
+ }
+
+ throw new UnknownModelException(String.format("No builders are available to build a model of type '%s'.", modelName));
+ }
+
+ private static class VoidToolingModelBuilder implements ToolingModelBuilder {
+ public boolean canBuild(String modelName) {
+ return modelName.equals(Void.class.getName());
+ }
+
+ public Object buildAll(String modelName, Project project) {
+ return null;
+ }
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/tooling/provider/model/internal/LegacyConsumerInterface.java b/subprojects/core/src/main/groovy/org/gradle/tooling/provider/model/internal/LegacyConsumerInterface.java
new file mode 100644
index 0000000..d58fc69
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/tooling/provider/model/internal/LegacyConsumerInterface.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.provider.model.internal;
+
+/**
+ * Indicates that a given marker interface should be mixed in to instances of the annotated type before they
+ * are passed to the tooling API client.
+ */
+public @interface LegacyConsumerInterface {
+ String value();
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/tooling/provider/model/package-info.java b/subprojects/core/src/main/groovy/org/gradle/tooling/provider/model/package-info.java
new file mode 100644
index 0000000..ae44366
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/tooling/provider/model/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+/**
+ * Interfaces and classes that allow tooling models to be made available to the tooling API client.
+ */
+package org.gradle.tooling.provider.model;
diff --git a/subprojects/core/src/main/groovy/org/gradle/util/AntUtil.java b/subprojects/core/src/main/groovy/org/gradle/util/AntUtil.java
index fc621f3..34fa854 100644
--- a/subprojects/core/src/main/groovy/org/gradle/util/AntUtil.java
+++ b/subprojects/core/src/main/groovy/org/gradle/util/AntUtil.java
@@ -15,12 +15,11 @@
*/
package org.gradle.util;
-import org.apache.tools.ant.*;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.ProjectHelper;
+import org.apache.tools.ant.Task;
import org.gradle.api.internal.project.ant.AntLoggingAdapter;
-/**
- * @author Hans Dockter
- */
public class AntUtil {
/**
* @return Factory method to create new Project instances
diff --git a/subprojects/core/src/main/groovy/org/gradle/util/AvailablePortFinder.java b/subprojects/core/src/main/groovy/org/gradle/util/AvailablePortFinder.java
index fd7efdd..677f86f 100644
--- a/subprojects/core/src/main/groovy/org/gradle/util/AvailablePortFinder.java
+++ b/subprojects/core/src/main/groovy/org/gradle/util/AvailablePortFinder.java
@@ -31,8 +31,6 @@ import java.util.concurrent.locks.ReentrantLock;
*
* <em>Note:</em> If possible, it's preferable to let the party creating the server socket select the port (e.g. with <tt>new ServerSocket(0)</tt>) and then query it for the port chosen. With this
* class, there is always a risk that someone else grabs the port between the time it is returned from <tt>getNextAvailable()</tt> and the time the socket is created.
- *
- * @author <a href="http://mina.apache.org">Apache MINA Project</a>
* @see <a href="http://www.iana.org/assignments/port-numbers">IANA.org</a>
*/
@ThreadSafe
diff --git a/subprojects/core/src/main/groovy/org/gradle/util/ClassLoaderBackedClasspathSource.java b/subprojects/core/src/main/groovy/org/gradle/util/ClassLoaderBackedClasspathSource.java
deleted file mode 100644
index a83a233..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/util/ClassLoaderBackedClasspathSource.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.util;
-
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.Arrays;
-import java.util.Collection;
-
-public class ClassLoaderBackedClasspathSource implements ClasspathSource {
- private final ClassLoader classLoader;
-
- public ClassLoaderBackedClasspathSource(ClassLoader classLoader) {
- this.classLoader = classLoader;
- }
-
- public void collectClasspath(Collection<? super URL> classpath) {
- ClassLoader stopAt = ClassLoader.getSystemClassLoader() == null ? null : ClassLoader.getSystemClassLoader().getParent();
- for (ClassLoader cl = classLoader; cl != null && cl != stopAt; cl = cl.getParent()) {
- if (cl instanceof ClasspathSource) {
- ClasspathSource classpathSource = (ClasspathSource) cl;
- classpathSource.collectClasspath(classpath);
- break;
- }
- if (cl instanceof URLClassLoader) {
- classpath.addAll(Arrays.asList(((URLClassLoader) cl).getURLs()));
- }
- }
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/util/ClassLoaderFactory.java b/subprojects/core/src/main/groovy/org/gradle/util/ClassLoaderFactory.java
deleted file mode 100644
index 084dc82..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/util/ClassLoaderFactory.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.util;
-
-import org.gradle.internal.classpath.ClassPath;
-
-import java.net.URI;
-
-public interface ClassLoaderFactory {
- /**
- * Creates a ClassLoader implementation which has only the classes from the specified URIs and the Java API visible.
- */
- ClassLoader createIsolatedClassLoader(ClassPath classPath);
-
- /**
- * Creates a ClassLoader implementation which has only the classes from the specified URIs and the Java API visible.
- */
- ClassLoader createIsolatedClassLoader(Iterable<URI> uris);
-
- /**
- * Creates a ClassLoader implementation which has, by default, only the classes from the Java API visible, but which can allow access
- * to selected classes from the given parent ClassLoader.
- *
- * @param parent the parent ClassLoader
- * @return The ClassLoader
- */
- FilteringClassLoader createFilteringClassLoader(ClassLoader parent);
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/util/ClasspathSource.java b/subprojects/core/src/main/groovy/org/gradle/util/ClasspathSource.java
deleted file mode 100644
index c47980f..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/util/ClasspathSource.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.util;
-
-import java.net.URL;
-import java.util.Collection;
-
-public interface ClasspathSource {
- void collectClasspath(Collection<? super URL> classpath);
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/util/ClasspathUtil.java b/subprojects/core/src/main/groovy/org/gradle/util/ClasspathUtil.java
deleted file mode 100644
index a80bec4..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/util/ClasspathUtil.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.util;
-
-import org.gradle.api.GradleException;
-import org.gradle.internal.UncheckedException;
-
-import java.io.File;
-import java.lang.reflect.Method;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author Hans Dockter
- */
-public class ClasspathUtil {
- public static void addUrl(URLClassLoader classLoader, Iterable<URL> classpathElements) {
- try {
- Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
- method.setAccessible(true);
- for (URL classpathElement : classpathElements) {
- method.invoke(classLoader, classpathElement);
- }
- } catch (Throwable t) {
- throw new RuntimeException("Error, could not add URL to classloader", t);
- }
- }
-
- public static List<URL> getClasspath(ClassLoader classLoader) {
- List<URL> implementationClassPath = new ArrayList<URL>();
- new ClassLoaderBackedClasspathSource(classLoader).collectClasspath(implementationClassPath);
- return implementationClassPath;
- }
-
- public static File getClasspathForClass(Class<?> targetClass) {
- URI location;
- try {
- location = targetClass.getProtectionDomain().getCodeSource().getLocation().toURI();
- } catch (URISyntaxException e) {
- throw UncheckedException.throwAsUncheckedException(e);
- }
- if (!location.getScheme().equals("file")) {
- throw new GradleException(String.format("Cannot determine classpath for %s from codebase '%s'.", targetClass.getName(), location));
- }
- return new File(location.getPath());
- }
-
- public static File getClasspathForResource(ClassLoader classLoader, String name) {
- if (classLoader == null) {
- return getClasspathForResource(ClassLoader.getSystemResource(name), name);
- } else {
- return getClasspathForResource(classLoader.getResource(name), name);
- }
- }
-
- public static File getClasspathForResource(URL resource, String name) {
- URI location;
- try {
- location = resource.toURI();
- String path = location.getPath();
- if (location.getScheme().equals("file")) {
- assert path.endsWith("/" + name);
- return new File(path.substring(0, path.length() - (name.length() + 1)));
- } else if (location.getScheme().equals("jar")) {
- String schemeSpecificPart = location.getRawSchemeSpecificPart();
- int pos = schemeSpecificPart.indexOf("!");
- if (pos > 0) {
- assert schemeSpecificPart.substring(pos + 1).equals("/" + name);
- URI jarFile = new URI(schemeSpecificPart.substring(0, pos));
- if (jarFile.getScheme().equals("file")) {
- return new File(jarFile.getPath());
- }
- }
- }
- } catch (URISyntaxException e) {
- throw UncheckedException.throwAsUncheckedException(e);
- }
- throw new GradleException(String.format("Cannot determine classpath for resource '%s' from location '%s'.", name, location));
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/util/Clock.java b/subprojects/core/src/main/groovy/org/gradle/util/Clock.java
index 317cff3..adf17dd 100644
--- a/subprojects/core/src/main/groovy/org/gradle/util/Clock.java
+++ b/subprojects/core/src/main/groovy/org/gradle/util/Clock.java
@@ -19,9 +19,6 @@ package org.gradle.util;
import org.gradle.internal.TimeProvider;
import org.gradle.internal.TrueTimeProvider;
-/**
- * @author Hans Dockter
- */
public class Clock {
private long start;
private TimeProvider timeProvider;
diff --git a/subprojects/core/src/main/groovy/org/gradle/util/ConfigureUtil.java b/subprojects/core/src/main/groovy/org/gradle/util/ConfigureUtil.java
index f70c538..482fd06 100644
--- a/subprojects/core/src/main/groovy/org/gradle/util/ConfigureUtil.java
+++ b/subprojects/core/src/main/groovy/org/gradle/util/ConfigureUtil.java
@@ -27,9 +27,6 @@ import java.util.Map;
import static org.gradle.util.CollectionUtils.toStringList;
-/**
- * @author Hans Dockter
- */
public class ConfigureUtil {
public static <T> T configureByMap(Map<?, ?> properties, T delegate) {
diff --git a/subprojects/core/src/main/groovy/org/gradle/util/DefaultClassLoaderFactory.java b/subprojects/core/src/main/groovy/org/gradle/util/DefaultClassLoaderFactory.java
deleted file mode 100644
index 684e616..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/util/DefaultClassLoaderFactory.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.util;
-
-import org.gradle.internal.UncheckedException;
-import org.gradle.internal.classpath.ClassPath;
-import org.gradle.internal.service.ServiceLocator;
-
-import javax.xml.datatype.DatatypeFactory;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.SAXParserFactory;
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.Collection;
-
-public class DefaultClassLoaderFactory implements ClassLoaderFactory {
- public ClassLoader createIsolatedClassLoader(Iterable<URI> uris) {
- return doCreateIsolatedClassLoader(GFileUtils.urisToUrls(uris));
- }
-
- public ClassLoader createIsolatedClassLoader(ClassPath classPath) {
- return doCreateIsolatedClassLoader(classPath.getAsURLs());
- }
-
- private ClassLoader doCreateIsolatedClassLoader(Collection<URL> classpath) {
- // This piece of ugliness copies the JAXP (ie XML API) provider, if any, from the system ClassLoader. Here's why:
- //
- // 1. When looking for a provider, JAXP looks for a service resource in the context ClassLoader, which is our isolated ClassLoader. If our classpath above does not contain a
- // provider, this returns null. If it does contain a provider, JAXP extracts the classname from the service resource.
- // 2. If not found, JAXP looks for a service resource in the system ClassLoader. This happens to include all the application classes specified on the classpath. If the application
- // classpath does not contain a provider, this returns null. If it does contain a provider, JAXP extracts the implementation classname from the service resource.
- // 3. If not found, JAXP uses a default classname
- // 4. JAXP attempts to load the provider using the context ClassLoader. which is our isolated ClassLoader. This is fine if the classname came from step 1 or 3. It blows up if the
- // classname came from step 2.
- //
- // So, as a workaround, locate and include the JAXP provider jar in the classpath for our isolated ClassLoader.
- //
- // Note that in practise, this is only triggered when running in our tests
-
- if (needJaxpImpl()) {
- try {
- classpath.add(ClasspathUtil.getClasspathForResource(ClassLoader.getSystemClassLoader(), "META-INF/services/javax.xml.parsers.SAXParserFactory").toURI().toURL());
- } catch (MalformedURLException e) {
- throw UncheckedException.throwAsUncheckedException(e);
- }
- }
-
- return new URLClassLoader(classpath.toArray(new URL[classpath.size()]), ClassLoader.getSystemClassLoader().getParent());
- }
-
- public FilteringClassLoader createFilteringClassLoader(ClassLoader parent) {
- // See the comment for {@link #createIsolatedClassLoader} above
- FilteringClassLoader classLoader = new FilteringClassLoader(parent);
- if (needJaxpImpl()) {
- ServiceLocator locator = new ServiceLocator(ClassLoader.getSystemClassLoader());
- makeServiceVisible(locator, classLoader, SAXParserFactory.class);
- makeServiceVisible(locator, classLoader, DocumentBuilderFactory.class);
- makeServiceVisible(locator, classLoader, DatatypeFactory.class);
- }
- return classLoader;
- }
-
- private void makeServiceVisible(ServiceLocator locator, FilteringClassLoader classLoader, Class<?> serviceType) {
- classLoader.allowClass(locator.getFactory(serviceType).getImplementationClass());
- classLoader.allowResource("META-INF/services/" + serviceType.getName());
- }
-
- private boolean needJaxpImpl() {
- return ClassLoader.getSystemResource("META-INF/services/javax.xml.parsers.SAXParserFactory") != null;
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/util/DeleteOnExit.java b/subprojects/core/src/main/groovy/org/gradle/util/DeleteOnExit.java
deleted file mode 100644
index a16ac23..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/util/DeleteOnExit.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.util;
-
-import org.apache.commons.io.FileUtils;
-
-import java.util.ArrayList;
-import java.io.File;
-
-/**
- * Provides a mechanism to delete files or whole directories on shutdown.
- * File.deleteOnExit won't work on subdirectories that are not empty.
- * There are some temporary files which are not currently well managed
- * but we want to make sure that they are eventually removed
- * @author Steve Appling
- */
-public class DeleteOnExit {
- private static final ArrayList<File> FILES = new ArrayList<File>();
-
- static {
- Runtime.getRuntime().addShutdownHook(new DeleteOnExitThread());
- }
-
- public static void addFile(File file) {
- synchronized (FILES) {
- FILES.add(file);
- }
- }
-
- private static class DeleteOnExitThread extends Thread {
- public void run() {
- synchronized (FILES) {
- for (File file : FILES) {
- FileUtils.deleteQuietly(file);
- }
- }
- }
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/util/FilteringClassLoader.java b/subprojects/core/src/main/groovy/org/gradle/util/FilteringClassLoader.java
deleted file mode 100644
index ab2b12a..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/util/FilteringClassLoader.java
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.util;
-
-import java.io.IOException;
-import java.net.URL;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.*;
-
-/**
- * A ClassLoader which hides all non-system classes, packages and resources. Allows certain non-system packages and classes to be declared as visible. By default, only the Java system classes,
- * packages and resources are visible.
- */
-public class FilteringClassLoader extends ClassLoader {
- private static final Set<ClassLoader> SYSTEM_CLASS_LOADERS = new HashSet<ClassLoader>();
- private static final ClassLoader EXT_CLASS_LOADER;
- private static final Set<String> SYSTEM_PACKAGES = new HashSet<String>();
- private final Set<String> packageNames = new HashSet<String>();
- private final Set<String> packagePrefixes = new HashSet<String>();
- private final Set<String> resourcePrefixes = new HashSet<String>();
- private final Set<String> resourceNames = new HashSet<String>();
- private final Set<String> classNames = new HashSet<String>();
- private final Set<String> disallowedClassNames = new HashSet<String>();
-
- static {
- EXT_CLASS_LOADER = ClassLoader.getSystemClassLoader().getParent();
- for (ClassLoader cl = EXT_CLASS_LOADER; cl != null; cl = cl.getParent()) {
- SYSTEM_CLASS_LOADERS.add(cl);
- }
- JavaMethod<ClassLoader, Package[]> method = JavaMethod.create(ClassLoader.class, Package[].class, "getPackages");
- Package[] systemPackages = method.invoke(EXT_CLASS_LOADER);
- for (Package p : systemPackages) {
- SYSTEM_PACKAGES.add(p.getName());
- }
- }
-
- public FilteringClassLoader(ClassLoader parent) {
- super(parent);
- }
-
- @Override
- protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
- Class<?> cl;
- try {
- cl = super.loadClass(name, false);
- } catch (NoClassDefFoundError e) {
- if (classAllowed(name)) {
- throw e;
- }
- // The class isn't visible
- throw new ClassNotFoundException(String.format("%s not found.", name));
- }
-
- if (!allowed(cl)) {
- throw new ClassNotFoundException(String.format("%s not found.", cl.getName()));
- }
- if (resolve) {
- resolveClass(cl);
- }
-
- return cl;
- }
-
- @Override
- protected Package getPackage(String name) {
- Package p = super.getPackage(name);
- if (p == null || !allowed(p)) {
- return null;
- }
- return p;
- }
-
- @Override
- protected Package[] getPackages() {
- List<Package> packages = new ArrayList<Package>();
- for (Package p : super.getPackages()) {
- if (allowed(p)) {
- packages.add(p);
- }
- }
- return packages.toArray(new Package[packages.size()]);
- }
-
- @Override
- public URL getResource(String name) {
- if (allowed(name)) {
- return super.getResource(name);
- }
- return EXT_CLASS_LOADER.getResource(name);
- }
-
- @Override
- public Enumeration<URL> getResources(String name) throws IOException {
- if (allowed(name)) {
- return super.getResources(name);
- }
- return EXT_CLASS_LOADER.getResources(name);
- }
-
- private boolean allowed(String resourceName) {
- if (resourceNames.contains(resourceName)) {
- return true;
- }
- for (String resourcePrefix : resourcePrefixes) {
- if (resourceName.startsWith(resourcePrefix)) {
- return true;
- }
- }
- return false;
- }
-
- private boolean allowed(Package pkg) {
- if (SYSTEM_PACKAGES.contains(pkg.getName())) {
- return true;
- }
- if (packageNames.contains(pkg.getName())) {
- return true;
- }
- for (String packagePrefix : packagePrefixes) {
- if (pkg.getName().startsWith(packagePrefix)) {
- return true;
- }
- }
- return false;
- }
-
- private boolean allowed(final Class<?> clazz) {
- boolean systemClass = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
- public Boolean run() {
- return clazz.getClassLoader() == null || SYSTEM_CLASS_LOADERS.contains(clazz.getClassLoader());
- }
- });
- return systemClass || classAllowed(clazz.getName());
- }
-
- private boolean classAllowed(String className) {
- if (disallowedClassNames.contains(className)) {
- return false;
- }
- if (classNames.contains(className)) {
- return true;
- }
- for (String packagePrefix : packagePrefixes) {
- if (className.startsWith(packagePrefix)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Marks a package and all its sub-packages as visible. Also makes resources in those packages visible.
- *
- * @param packageName the package name
- */
- public void allowPackage(String packageName) {
- packageNames.add(packageName);
- packagePrefixes.add(packageName + ".");
- resourcePrefixes.add(packageName.replace('.', '/') + '/');
- }
-
- /**
- * Marks a single class as visible.
- *
- * @param clazz the class
- */
- public void allowClass(Class<?> clazz) {
- classNames.add(clazz.getName());
- }
-
- /**
- * Marks a single class as not visible.
- *
- * @param className the class name
- */
- public void disallowClass(String className) {
- disallowedClassNames.add(className);
- }
-
- /**
- * Marks all resources with the given prefix as visible.
- *
- * @param resourcePrefix the resource prefix
- */
- public void allowResources(String resourcePrefix) {
- resourcePrefixes.add(resourcePrefix + "/");
- }
-
- /**
- * Marks a single resource as visible.
- *
- * @param resourceName the resource name
- */
- public void allowResource(String resourceName) {
- resourceNames.add(resourceName);
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/util/GFileUtils.java b/subprojects/core/src/main/groovy/org/gradle/util/GFileUtils.java
index a08f5d9..a202a58 100644
--- a/subprojects/core/src/main/groovy/org/gradle/util/GFileUtils.java
+++ b/subprojects/core/src/main/groovy/org/gradle/util/GFileUtils.java
@@ -23,16 +23,11 @@ import org.gradle.internal.UncheckedException;
import org.gradle.util.internal.LimitedDescription;
import java.io.*;
-import java.net.MalformedURLException;
-import java.net.URI;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.*;
import java.util.zip.Checksum;
-/**
- * @author Hans Dockter
- */
public class GFileUtils {
public static FileInputStream openInputStream(File file) {
@@ -114,18 +109,6 @@ public class GFileUtils {
return paths;
}
- public static List<URL> urisToUrls(Iterable<URI> uris) {
- List<URL> urls = new ArrayList<URL>();
- for (URI uri : uris) {
- try {
- urls.add(uri.toURL());
- } catch (MalformedURLException e) {
- throw new UncheckedIOException(e);
- }
- }
- return urls;
- }
-
public static void copyURLToFile(URL source, File destination) {
try {
FileUtils.copyURLToFile(source, destination);
diff --git a/subprojects/core/src/main/groovy/org/gradle/util/GStreamUtil.java b/subprojects/core/src/main/groovy/org/gradle/util/GStreamUtil.java
new file mode 100644
index 0000000..2e6d084
--- /dev/null
+++ b/subprojects/core/src/main/groovy/org/gradle/util/GStreamUtil.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.util;
+
+import java.io.DataInput;
+import java.io.IOException;
+
+public class GStreamUtil {
+
+ //skips 'n' bytes,
+ public static int skipBytes(int n, DataInput input) throws IOException {
+ int total = 0;
+ int cur;
+
+ while ((total<n) && ((cur = input.skipBytes(n - total)) > 0)) {
+ total += cur;
+ }
+ return total;
+ }
+}
diff --git a/subprojects/core/src/main/groovy/org/gradle/util/GUtil.java b/subprojects/core/src/main/groovy/org/gradle/util/GUtil.java
index e1be0fa..8f4adf5 100644
--- a/subprojects/core/src/main/groovy/org/gradle/util/GUtil.java
+++ b/subprojects/core/src/main/groovy/org/gradle/util/GUtil.java
@@ -29,9 +29,6 @@ import java.util.regex.Pattern;
import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
-/**
- * @author Hans Dockter
- */
public class GUtil {
private static final Pattern WORD_SEPARATOR = Pattern.compile("\\W+");
private static final Pattern UPPER_LOWER = Pattern.compile("(\\p{Upper}*)(\\p{Lower}*)");
diff --git a/subprojects/core/src/main/groovy/org/gradle/util/GradleVersion.java b/subprojects/core/src/main/groovy/org/gradle/util/GradleVersion.java
index 674eb14..c87eb2c 100644
--- a/subprojects/core/src/main/groovy/org/gradle/util/GradleVersion.java
+++ b/subprojects/core/src/main/groovy/org/gradle/util/GradleVersion.java
@@ -20,7 +20,6 @@ import groovy.lang.GroovySystem;
import org.apache.ivy.Ivy;
import org.apache.tools.ant.Main;
import org.gradle.api.GradleException;
-import org.gradle.api.Nullable;
import org.gradle.api.UncheckedIOException;
import org.gradle.internal.UncheckedException;
import org.gradle.internal.jvm.Jvm;
@@ -39,16 +38,16 @@ import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-/**
- * @author Hans Dockter
- * @author Russel Winder
- */
public class GradleVersion implements Comparable<GradleVersion> {
- public final static String URL = "http://www.gradle.org";
- private final static Pattern VERSION_PATTERN = Pattern.compile("(\\d+(\\.\\d+)+)(-(\\p{Alpha}+)-(\\d+[a-z]?))?(-(\\d{14}([-+]\\d{4})?))?");
+ public static final String URL = "http://www.gradle.org";
+ private static final Pattern VERSION_PATTERN = Pattern.compile("((\\d+)(\\.\\d+)+)(-(\\p{Alpha}+)-(\\d+[a-z]?))?(-(\\d{14}([-+]\\d{4})?))?");
+ private static final int STAGE_MILESTONE = 0;
private final String version;
+ private final int majorPart;
private final String buildTime;
+ private final String commitId;
+ private final String buildNumber;
private final Long snapshot;
private final String versionPart;
private final Stage stage;
@@ -69,9 +68,11 @@ public class GradleVersion implements Comparable<GradleVersion> {
String version = properties.get("versionNumber").toString();
String buildTimestamp = properties.get("buildTimestamp").toString();
+ String buildNumber = properties.get("buildNumber").toString();
+ String commitId = properties.get("commitId").toString();
Date buildTime = new SimpleDateFormat("yyyyMMddHHmmssZ").parse(buildTimestamp);
- CURRENT = new GradleVersion(version, buildTime);
+ CURRENT = new GradleVersion(version, buildTime, buildNumber, commitId);
} catch (Exception e) {
throw new GradleException(String.format("Could not load version details from resource '%s'.", resource), e);
} finally {
@@ -85,51 +86,58 @@ public class GradleVersion implements Comparable<GradleVersion> {
}
}
+
public static GradleVersion current() {
return CURRENT;
}
- public static GradleVersion version(String version) {
- return new GradleVersion(version, null);
+ /**
+ * Parses the given string into a GradleVersion.
+ *
+ * @throws IllegalArgumentException On unrecognized version string.
+ */
+ public static GradleVersion version(String version) throws IllegalArgumentException {
+ return new GradleVersion(version, null, null, null);
}
- private GradleVersion(String version, Date buildTime) {
+ private GradleVersion(String version, Date buildTime, String buildNumber, String commitId) {
this.version = version;
+ this.buildNumber = buildNumber;
+ this.commitId = commitId;
this.buildTime = buildTime == null ? null : formatBuildTime(buildTime);
Matcher matcher = VERSION_PATTERN.matcher(version);
if (!matcher.matches()) {
- // Unrecognized version
- versionPart = null;
- snapshot = null;
- stage = null;
- return;
+ throw new IllegalArgumentException(String.format("'%s' is not a valid Gradle version string (examples: '1.0', '1.0-rc-1')", version));
}
versionPart = matcher.group(1);
+ majorPart = Integer.parseInt(matcher.group(2), 10);
- if (matcher.group(3) != null) {
- int stageNumber = 0;
- if (matcher.group(4).equals("milestone")) {
- stageNumber = 1;
- } else if (matcher.group(4).equals("preview")) {
+ if (matcher.group(4) != null) {
+ int stageNumber;
+ if (matcher.group(5).equals("milestone")) {
+ stageNumber = STAGE_MILESTONE;
+ } else if (matcher.group(5).equals("preview")) {
stageNumber = 2;
- } else if (matcher.group(4).equals("rc")) {
+ } else if (matcher.group(5).equals("rc")) {
stageNumber = 3;
+ } else {
+ stageNumber = 1;
}
- String stageString = matcher.group(5);
+ String stageString = matcher.group(6);
stage = new Stage(stageNumber, stageString);
} else {
stage = null;
}
- if (matcher.group(7) != null) {
+ if (matcher.group(8) != null) {
try {
- if (matcher.group(8) != null) {
- snapshot = new SimpleDateFormat("yyyyMMddHHmmssZ").parse(matcher.group(7)).getTime();
+ if (matcher.group(9) != null) {
+ snapshot = new SimpleDateFormat("yyyyMMddHHmmssZ").parse(matcher.group(8)).getTime();
} else {
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
format.setTimeZone(TimeZone.getTimeZone("UTC"));
- snapshot = format.parse(matcher.group(7)).getTime();
+ snapshot = format.parse(matcher.group(8)).getTime();
}
} catch (ParseException e) {
throw UncheckedException.throwAsUncheckedException(e);
@@ -140,7 +148,7 @@ public class GradleVersion implements Comparable<GradleVersion> {
}
private String formatBuildTime(Date buildTime) {
- DateFormat format = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL);
+ DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
format.setTimeZone(TimeZone.getTimeZone("UTC"));
return format.format(buildTime);
}
@@ -159,37 +167,37 @@ public class GradleVersion implements Comparable<GradleVersion> {
}
public boolean isSnapshot() {
- return versionPart == null || snapshot != null;
+ return snapshot != null;
}
/**
- * The base version number of the overall version.
+ * The base version of this version. For pre-release versions, this is the target version.
*
* For example, the version base of '1.2-rc-1' is '1.2'.
*
- * @return The version base, or null if the version is unrecognised.
+ * @return The version base
*/
- @Nullable
- public String getVersionBase() {
- return versionPart;
+ public GradleVersion getBaseVersion() {
+ if (stage == null && snapshot == null) {
+ return this;
+ }
+ if (stage != null && stage.stage == STAGE_MILESTONE) {
+ return version(versionPart + "-milestone-" + stage.number);
+ }
+ return version(versionPart);
}
- public int getMajor() {
- if (isValid()) {
- return Integer.valueOf(versionPart.split("\\.", 2)[0], 10);
- } else {
- return -1;
+ public GradleVersion getNextMajor() {
+ if (stage != null && stage.stage == STAGE_MILESTONE) {
+ return version(majorPart + ".0");
}
+ return version((majorPart + 1) + ".0");
}
public int compareTo(GradleVersion gradleVersion) {
- assertCanQueryParts();
- gradleVersion.assertCanQueryParts();
-
String[] majorVersionParts = versionPart.split("\\.");
String[] otherMajorVersionParts = gradleVersion.versionPart.split("\\.");
-
for (int i = 0; i < majorVersionParts.length && i < otherMajorVersionParts.length; i++) {
int part = Integer.parseInt(majorVersionParts[i]);
int otherPart = Integer.parseInt(otherMajorVersionParts[i]);
@@ -234,12 +242,6 @@ public class GradleVersion implements Comparable<GradleVersion> {
return 0;
}
- private void assertCanQueryParts() {
- if (versionPart == null) {
- throw new IllegalArgumentException(String.format("Cannot compare unrecognized Gradle version '%s'.", version));
- }
- }
-
@Override
public boolean equals(Object o) {
if (o == this) {
@@ -261,17 +263,21 @@ public class GradleVersion implements Comparable<GradleVersion> {
final StringBuilder sb = new StringBuilder();
sb.append("\n------------------------------------------------------------\nGradle ");
sb.append(getVersion());
- sb.append("\n------------------------------------------------------------\n\nGradle build time: ");
+ sb.append("\n------------------------------------------------------------\n\nBuild time: ");
sb.append(getBuildTime());
- sb.append("\nGroovy: ");
+ sb.append("\nBuild number: ");
+ sb.append(buildNumber);
+ sb.append("\nRevision: ");
+ sb.append(commitId);
+ sb.append("\n\nGroovy: ");
sb.append(GroovySystem.getVersion());
- sb.append("\nAnt: ");
+ sb.append("\nAnt: ");
sb.append(Main.getAntVersion());
- sb.append("\nIvy: ");
+ sb.append("\nIvy: ");
sb.append(Ivy.getIvyVersion());
- sb.append("\nJVM: ");
+ sb.append("\nJVM: ");
sb.append(Jvm.current());
- sb.append("\nOS: ");
+ sb.append("\nOS: ");
sb.append(OperatingSystem.current());
sb.append("\n");
return sb.toString();
diff --git a/subprojects/core/src/main/groovy/org/gradle/util/JarUtil.java b/subprojects/core/src/main/groovy/org/gradle/util/JarUtil.java
index 998c81a..51f92a6 100644
--- a/subprojects/core/src/main/groovy/org/gradle/util/JarUtil.java
+++ b/subprojects/core/src/main/groovy/org/gradle/util/JarUtil.java
@@ -19,12 +19,9 @@ package org.gradle.util;
import org.apache.commons.io.IOUtils;
import java.io.*;
-import java.util.zip.ZipInputStream;
import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
-/**
- * @author Tom Eyckmans
- */
public class JarUtil {
public static boolean extractZipEntry(File jarFile, String entryName, File extractToFile) throws IOException {
boolean entryExtracted = false;
diff --git a/subprojects/core/src/main/groovy/org/gradle/util/JavaMethod.java b/subprojects/core/src/main/groovy/org/gradle/util/JavaMethod.java
deleted file mode 100644
index bbe0d9e..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/util/JavaMethod.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.util;
-
-import org.gradle.api.GradleException;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.Arrays;
-
-public class JavaMethod<T, R> {
- private final Method method;
- private final Class<R> returnType;
-
- private JavaMethod(Class<T> target, Class<R> returnType, String name, Class<?>... paramTypes) {
- this.returnType = returnType;
- method = findMethod(target, name, paramTypes);
- method.setAccessible(true);
- }
-
- private JavaMethod(Class<T> target, Class<R> returnType, Method method) {
- this.returnType = returnType;
- this.method = method;
- method.setAccessible(true);
- }
-
- private Method findMethod(Class target, String name, Class<?>[] paramTypes) {
- for (Method method : target.getDeclaredMethods()) {
- if (Modifier.isStatic(method.getModifiers())) {
- continue;
- }
- if (method.getName().equals(name) && Arrays.equals(method.getParameterTypes(), paramTypes)) {
- return method;
- }
- }
- throw new GradleException(String.format("Could not find method %s(%s) on %s", name, Arrays.toString(paramTypes),
- target));
- }
-
- public R invoke(T target, Object... args) {
- try {
- return returnType.cast(method.invoke(target, args));
- } catch (InvocationTargetException e) {
- Throwable cause = e.getCause();
- if (cause instanceof RuntimeException) {
- throw (RuntimeException) cause;
- }
- throw new GradleException(String.format("Could not call %s.%s() on %s", method.getDeclaringClass().getSimpleName(), method.getName(), target), cause);
- } catch (Exception e) {
- throw new GradleException(String.format("Could not call %s.%s() on %s", method.getDeclaringClass().getSimpleName(), method.getName(), target), e);
- }
- }
-
- public static <T, R> JavaMethod<T, R> create(Class<T> target, Class<R> returnType, String name, Class<?>... paramTypes) {
- return new JavaMethod<T, R>(target, returnType, name, paramTypes);
- }
-
- public static <T, R> JavaMethod<T, R> create(Class<T> target, Class<R> returnType, Method method) {
- return new JavaMethod<T, R>(target, returnType, method);
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/util/LineBufferingOutputStream.java b/subprojects/core/src/main/groovy/org/gradle/util/LineBufferingOutputStream.java
index 2811d0c..3d1a861 100644
--- a/subprojects/core/src/main/groovy/org/gradle/util/LineBufferingOutputStream.java
+++ b/subprojects/core/src/main/groovy/org/gradle/util/LineBufferingOutputStream.java
@@ -23,8 +23,6 @@ import java.io.OutputStream;
/**
* An OutputStream which separates bytes written into lines. Uses the platform default encoding. Is not thread safe.
- *
- * @author Hans Dockter
*/
public class LineBufferingOutputStream extends OutputStream {
private boolean hasBeenClosed;
diff --git a/subprojects/core/src/main/groovy/org/gradle/util/MultiParentClassLoader.java b/subprojects/core/src/main/groovy/org/gradle/util/MultiParentClassLoader.java
deleted file mode 100644
index d86da52..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/util/MultiParentClassLoader.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.util;
-
-import java.util.*;
-import java.net.URL;
-import java.io.IOException;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-/**
- * A {@code ClassLoader} which delegates to multiple parent ClassLoaders.
- */
-public class MultiParentClassLoader extends ClassLoader implements ClasspathSource {
- private final List<ClassLoader> parents;
- private final JavaMethod<ClassLoader, Package[]> getPackagesMethod;
- private final JavaMethod<ClassLoader, Package> getPackageMethod;
-
- public MultiParentClassLoader(ClassLoader... parents) {
- super(null);
- this.parents = new CopyOnWriteArrayList<ClassLoader>(Arrays.asList(parents));
- getPackagesMethod = JavaMethod.create(ClassLoader.class, Package[].class, "getPackages");
- getPackageMethod = JavaMethod.create(ClassLoader.class, Package.class, "getPackage", String.class);
- }
-
- public void addParent(ClassLoader parent) {
- parents.add(parent);
- }
-
- public void collectClasspath(Collection<? super URL> classpath) {
- for (ClassLoader parent : parents) {
- new ClassLoaderBackedClasspathSource(parent).collectClasspath(classpath);
- }
- }
-
- @Override
- protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
- for (ClassLoader parent : parents) {
- try {
- return parent.loadClass(name);
- } catch (ClassNotFoundException e) {
- // Expected
- }
- }
- throw new ClassNotFoundException(String.format("%s not found.", name));
- }
-
- @Override
- protected Package getPackage(String name) {
- for (ClassLoader parent : parents) {
- Package p = getPackageMethod.invoke(parent, name);
- if (p != null) {
- return p;
- }
- }
- return null;
- }
-
- @Override
- protected Package[] getPackages() {
- Set<Package> packages = new LinkedHashSet<Package>();
- for (ClassLoader parent : parents) {
- Package[] parentPackages = getPackagesMethod.invoke(parent);
- packages.addAll(Arrays.asList(parentPackages));
- }
- return packages.toArray(new Package[packages.size()]);
- }
-
- @Override
- public URL getResource(String name) {
- for (ClassLoader parent : parents) {
- URL resource = parent.getResource(name);
- if (resource != null) {
- return resource;
- }
- }
- return null;
- }
-
- @Override
- public Enumeration<URL> getResources(String name) throws IOException {
- Set<URL> resources = new LinkedHashSet<URL>();
- for (ClassLoader parent : parents) {
- Enumeration<URL> parentResources = parent.getResources(name);
- while (parentResources.hasMoreElements()) {
- resources.add(parentResources.nextElement());
- }
- }
- return Collections.enumeration(resources);
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/util/MutableURLClassLoader.java b/subprojects/core/src/main/groovy/org/gradle/util/MutableURLClassLoader.java
deleted file mode 100755
index c8a50ce..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/util/MutableURLClassLoader.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.util;
-
-import org.gradle.internal.classpath.ClassPath;
-
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.Collection;
-
-public class MutableURLClassLoader extends URLClassLoader {
- public MutableURLClassLoader(ClassLoader parent, URL... urls) {
- super(urls, parent);
- }
-
- public MutableURLClassLoader(ClassLoader parent, Collection<URL> urls) {
- super(urls.toArray(new URL[urls.size()]), parent);
- }
-
- public MutableURLClassLoader(ClassLoader parent, ClassPath classPath) {
- super(classPath.getAsURLArray(), parent);
- }
-
- @Override
- public void addURL(URL url) {
- super.addURL(url);
- }
-
- public void addURLs(Iterable<URL> urls) {
- for (URL url : urls) {
- addURL(url);
- }
- }
-}
diff --git a/subprojects/core/src/main/groovy/org/gradle/util/Path.java b/subprojects/core/src/main/groovy/org/gradle/util/Path.java
index f433fbf..6c70294 100644
--- a/subprojects/core/src/main/groovy/org/gradle/util/Path.java
+++ b/subprojects/core/src/main/groovy/org/gradle/util/Path.java
@@ -23,9 +23,6 @@ import org.gradle.api.Project;
import java.util.Arrays;
import java.util.Comparator;
-/**
- * @author Hans Dockter
- */
public class Path implements Comparable<Path> {
private static final Comparator<String> STRING_COMPARATOR = GUtil.caseInsensitive();
private final String prefix;
diff --git a/subprojects/core/src/main/groovy/org/gradle/util/ReflectionUtil.groovy b/subprojects/core/src/main/groovy/org/gradle/util/ReflectionUtil.groovy
deleted file mode 100644
index 80a1e05..0000000
--- a/subprojects/core/src/main/groovy/org/gradle/util/ReflectionUtil.groovy
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.util
-
-/**
- * @author Hans Dockter
- */
-class ReflectionUtil {
- static Object invoke(Object object, String method, Object... params) {
- object.invokeMethod(method, params)
- }
-
- static Object getProperty(Object object, String property) {
- object."$property"
- }
-
- static void setProperty(Object object, String property, Object value) {
- object."$property" = value
- }
-
- static boolean hasProperty(Object object, String property) {
- object.metaClass.hasProperty(object, property) != null
- }
-
- static boolean isClassAvailable(String className) {
- try {
- ReflectionUtil.classLoader.loadClass(className)
- return true
- } catch (ClassNotFoundException e) {
- return false
- }
- }
-}
\ No newline at end of file
diff --git a/subprojects/core/src/main/groovy/org/gradle/util/SingleMessageLogger.java b/subprojects/core/src/main/groovy/org/gradle/util/SingleMessageLogger.java
index 647345f..cca033d 100644
--- a/subprojects/core/src/main/groovy/org/gradle/util/SingleMessageLogger.java
+++ b/subprojects/core/src/main/groovy/org/gradle/util/SingleMessageLogger.java
@@ -16,12 +16,14 @@
package org.gradle.util;
+import net.jcip.annotations.ThreadSafe;
import org.apache.commons.lang.StringUtils;
-import org.codehaus.groovy.runtime.StackTraceUtils;
-import org.gradle.api.logging.LogLevel;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
import org.gradle.internal.Factory;
+import org.gradle.internal.featurelifecycle.DeprecatedFeatureUsage;
+import org.gradle.internal.featurelifecycle.LoggingDeprecatedFeatureHandler;
+import org.gradle.internal.featurelifecycle.UsageLocationReporter;
import java.util.Collections;
import java.util.HashSet;
@@ -29,15 +31,11 @@ import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
+ at ThreadSafe
public class SingleMessageLogger {
-
private static final Logger LOGGER = Logging.getLogger(DeprecationLogger.class);
- private static final Set<String> PLUGINS = Collections.synchronizedSet(new HashSet<String>());
- private static final Set<String> TASKS = Collections.synchronizedSet(new HashSet<String>());
- private static final Set<String> METHODS = Collections.synchronizedSet(new HashSet<String>());
private static final Set<String> DYNAMIC_PROPERTIES = Collections.synchronizedSet(new HashSet<String>());
- private static final Set<String> PROPERTIES = Collections.synchronizedSet(new HashSet<String>());
- private static final Set<String> NAMED_PARAMETERS = Collections.synchronizedSet(new HashSet<String>());
+ private static final Set<String> FEATURES = Collections.synchronizedSet(new HashSet<String>());
private static final ThreadLocal<Boolean> ENABLED = new ThreadLocal<Boolean>() {
@Override
@@ -46,128 +44,106 @@ public class SingleMessageLogger {
}
};
- private static final ThreadLocal<Boolean> LOG_TRACE = new ThreadLocal<Boolean>() {
- @Override
- protected Boolean initialValue() {
- return false;
- }
- };
-
public static final String ORG_GRADLE_DEPRECATION_TRACE_PROPERTY_NAME = "org.gradle.deprecation.trace";
+ public static final String INCUBATION_MESSAGE = "%s is an incubating feature.";
+ private static final Lock LOCK = new ReentrantLock();
+ private static LoggingDeprecatedFeatureHandler handler = new LoggingDeprecatedFeatureHandler();
private static String deprecationMessage;
- private static Lock deprecationMessageLock = new ReentrantLock();
- public static final String INCUBATION_MESSAGE = "%s is an incubating feature. Enjoy it and let us know how it works for you.";
private static String getDeprecationMessage() {
- if (deprecationMessage == null) {
- deprecationMessageLock.lock();
- try {
- if (deprecationMessage == null) {
- String messageBase = "has been deprecated and is scheduled to be removed in";
- String when;
-
- GradleVersion currentVersion = GradleVersion.current();
- int versionMajor = currentVersion.getMajor();
- if (versionMajor == -1) { // don't understand version number
- when = "the next major version of Gradle";
- } else {
- when = String.format("Gradle %d.0", versionMajor + 1);
- }
-
- deprecationMessage = String.format("%s %s", messageBase, when);
- }
- } finally {
- deprecationMessageLock.unlock();
+ LOCK.lock();
+ try {
+ if (deprecationMessage == null) {
+ String messageBase = "has been deprecated and is scheduled to be removed in";
+
+ GradleVersion currentVersion = GradleVersion.current();
+ String when = String.format("Gradle %s", currentVersion.getNextMajor().getVersion());
+
+ deprecationMessage = String.format("%s %s", messageBase, when);
}
+ return deprecationMessage;
+ } finally {
+ LOCK.unlock();
}
-
- return deprecationMessage;
}
public static void reset() {
- PLUGINS.clear();
- METHODS.clear();
- PROPERTIES.clear();
- NAMED_PARAMETERS.clear();
DYNAMIC_PROPERTIES.clear();
+ FEATURES.clear();
+ LOCK.lock();
+ try {
+ handler = new LoggingDeprecatedFeatureHandler();
+ } finally {
+ LOCK.unlock();
+ }
}
- public static void nagUserOfReplacedPlugin(String pluginName, String replacement) {
- if (isEnabled() && PLUGINS.add(pluginName)) {
- LOGGER.warn(String.format(
- "The %s plugin %S. Please use the %s plugin instead.",
- pluginName, getDeprecationMessage(), replacement));
- logTraceIfNecessary();
+ public static void useLocationReporter(UsageLocationReporter reporter) {
+ LOCK.lock();
+ try {
+ handler.setLocationReporter(reporter);
+ } finally {
+ LOCK.unlock();
}
}
+ public static void nagUserOfReplacedPlugin(String pluginName, String replacement) {
+ nagUserWith(String.format(
+ "The %s plugin %s. Please use the %s plugin instead.",
+ pluginName, getDeprecationMessage(), replacement));
+ }
+
public static void nagUserOfReplacedTaskType(String taskName, String replacement) {
- if (isEnabled() && TASKS.add(taskName)) {
- LOGGER.warn(String.format(
- "The %s task type %s. Please use the %s instead.",
- taskName, getDeprecationMessage(), replacement));
- logTraceIfNecessary();
- }
+ nagUserWith(String.format(
+ "The %s task type %s. Please use the %s instead.",
+ taskName, getDeprecationMessage(), replacement));
}
public static void nagUserOfReplacedMethod(String methodName, String replacement) {
- if (isEnabled() && METHODS.add(methodName)) {
- LOGGER.warn(String.format(
- "The %s method %s. Please use the %s method instead.",
- methodName, getDeprecationMessage(), replacement));
- logTraceIfNecessary();
- }
+ nagUserWith(String.format(
+ "The %s method %s. Please use the %s method instead.",
+ methodName, getDeprecationMessage(), replacement));
}
public static void nagUserOfReplacedProperty(String propertyName, String replacement) {
- if (isEnabled() && PROPERTIES.add(propertyName)) {
- LOGGER.warn(String.format(
- "The %s property %s. Please use the %s property instead.",
- propertyName, getDeprecationMessage(), replacement));
- logTraceIfNecessary();
- }
+ nagUserWith(String.format(
+ "The %s property %s. Please use the %s property instead.",
+ propertyName, getDeprecationMessage(), replacement));
}
public static void nagUserOfDiscontinuedMethod(String methodName) {
- if (isEnabled() && METHODS.add(methodName)) {
- LOGGER.warn(String.format("The %s method %s.",
- methodName, getDeprecationMessage()));
- logTraceIfNecessary();
- }
+ nagUserWith(String.format("The %s method %s.",
+ methodName, getDeprecationMessage()));
}
public static void nagUserOfDiscontinuedProperty(String propertyName, String advice) {
- if (isEnabled() && PROPERTIES.add(propertyName)) {
- LOGGER.warn(String.format("The %s property %s. %s",
- propertyName, getDeprecationMessage(), advice));
- logTraceIfNecessary();
- }
+ nagUserWith(String.format("The %s property %s. %s",
+ propertyName, getDeprecationMessage(), advice));
}
- public static void nagUserOfReplacedNamedParameter(String parameterName, String replacement) {
- if (isEnabled() && NAMED_PARAMETERS.add(parameterName)) {
- LOGGER.warn(String.format(
- "The %s named parameter %s. Please use the %s named parameter instead.",
- parameterName, getDeprecationMessage(), replacement));
- logTraceIfNecessary();
- }
+ public static void nagUserOfDiscontinuedConfiguration(String configurationName, String advice) {
+ nagUserWith(String.format("The %s configuration %s. %s",
+ configurationName, getDeprecationMessage(), advice));
}
- /**
- * Try to avoid using this nagging method. The other methods use a consistent wording for when things will be removed.
- */
- public static void nagUserWith(String message) {
- inform(LogLevel.WARN, message);
- logTraceIfNecessary();
+ public static void nagUserOfReplacedNamedParameter(String parameterName, String replacement) {
+ nagUserWith(String.format(
+ "The %s named parameter %s. Please use the %s named parameter instead.",
+ parameterName, getDeprecationMessage(), replacement));
}
/**
* Try to avoid using this nagging method. The other methods use a consistent wording for when things will be removed.
*/
- public static void inform(LogLevel level, String message) {
- if (isEnabled() && METHODS.add(message)) {
- LOGGER.log(level, message);
+ public static void nagUserWith(String message) {
+ if (isEnabled()) {
+ LOCK.lock();
+ try {
+ handler.deprecatedFeatureUsed(new DeprecatedFeatureUsage(message, SingleMessageLogger.class));
+ } finally {
+ LOCK.unlock();
+ }
}
}
@@ -204,29 +180,10 @@ public class SingleMessageLogger {
}
}
- private static boolean isTraceLoggingEnabled() {
- return Boolean.getBoolean(ORG_GRADLE_DEPRECATION_TRACE_PROPERTY_NAME) || LOG_TRACE.get();
- }
-
- private static void logTraceIfNecessary() {
- if (isTraceLoggingEnabled()) {
- StackTraceElement[] stack = StackTraceUtils.sanitize(new Exception()).getStackTrace();
- for (StackTraceElement frame : stack) {
- if (!frame.getClassName().startsWith(DeprecationLogger.class.getName())) {
- LOGGER.warn(" {}", frame.toString());
- }
- }
- }
- }
-
private static boolean isEnabled() {
return ENABLED.get();
}
- public static void setLogTrace(boolean flag) {
- LOG_TRACE.set(flag);
- }
-
public static void nagUserAboutDynamicProperty(String propertyName, Object target, Object value) {
if (!isEnabled()) {
return;
@@ -243,7 +200,9 @@ public class SingleMessageLogger {
}
}
- public static void informAboutIncubating(String incubatingFeature) {
- inform(LogLevel.LIFECYCLE, String.format(INCUBATION_MESSAGE, incubatingFeature));
+ public static void incubatingFeatureUsed(String incubatingFeature) {
+ if (FEATURES.add(incubatingFeature)) {
+ LOGGER.lifecycle(String.format(INCUBATION_MESSAGE, incubatingFeature));
+ }
}
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/util/TextUtil.java b/subprojects/core/src/main/groovy/org/gradle/util/TextUtil.java
index c7f6c9e..90e3186 100644
--- a/subprojects/core/src/main/groovy/org/gradle/util/TextUtil.java
+++ b/subprojects/core/src/main/groovy/org/gradle/util/TextUtil.java
@@ -61,6 +61,13 @@ public class TextUtil {
}
/**
+ * Converts all line separators in the specified string to a single new line character.
+ */
+ public static String normaliseLineSeparators(String str) {
+ return str == null ? null : convertLineSeparators(str, "\n");
+ }
+
+ /**
* Converts all native file separators in the specified string to '/'.
*/
public static String normaliseFileSeparators(String path) {
diff --git a/subprojects/core/src/main/groovy/org/gradle/util/VersionNumber.java b/subprojects/core/src/main/groovy/org/gradle/util/VersionNumber.java
index 3ad64b6..10255ff 100644
--- a/subprojects/core/src/main/groovy/org/gradle/util/VersionNumber.java
+++ b/subprojects/core/src/main/groovy/org/gradle/util/VersionNumber.java
@@ -26,8 +26,13 @@ import java.util.regex.Pattern;
/**
* Represents, parses, and compares version numbers following a major.minor.micro-qualifier format.
- * Note that this class considers "2.10.0" less than "2.10.0-something", presumably to make it easier to
- * test for "less than any 2.10 version" and "greater than any 2.10 version".
+ * The {@link #parse} method handles missing parts and allows "." to be used instead of "-".
+ *
+ * <p>Note that this class considers "1.2.3-something" less than "1.2.3". Qualifiers are compared
+ * lexicographically ("1.2.3-alpha" < "1.2.3-beta") and case-insensitive ("1.2.3-alpha" < "1.2.3.RELEASE").
+ *
+ * <p>To check if a version number is at least "1.2.3", disregarding a potential qualifier like "beta", use
+ * {@code version.getBaseVersion().compareTo(VersionNumber.parse("1.2.3")) >= 0}.
*/
public class VersionNumber implements Comparable<VersionNumber> {
public static final VersionNumber UNKNOWN = new VersionNumber(0, 0, 0, null);
@@ -63,11 +68,15 @@ public class VersionNumber implements Comparable<VersionNumber> {
return qualifier;
}
+ public VersionNumber getBaseVersion() {
+ return new VersionNumber(major, minor, micro, null);
+ }
+
public int compareTo(VersionNumber other) {
if (major != other.major) { return major - other.major; }
if (minor != other.minor) { return minor - other.minor; }
if (micro != other.micro) { return micro - other.micro; }
- return Ordering.natural().nullsFirst().compare(qualifier, other.qualifier);
+ return Ordering.natural().nullsLast().compare(toLowerCase(qualifier), toLowerCase(other.qualifier));
}
public boolean equals(Object other) {
@@ -100,5 +109,9 @@ public class VersionNumber implements Comparable<VersionNumber> {
return new VersionNumber(major, minor, micro, qualifier);
}
+
+ private String toLowerCase(@Nullable String string) {
+ return string == null ? null : string.toLowerCase();
+ }
}
diff --git a/subprojects/core/src/main/groovy/org/gradle/util/internal/LimitedDescription.java b/subprojects/core/src/main/groovy/org/gradle/util/internal/LimitedDescription.java
index 06a7a8a..e629ec0 100644
--- a/subprojects/core/src/main/groovy/org/gradle/util/internal/LimitedDescription.java
+++ b/subprojects/core/src/main/groovy/org/gradle/util/internal/LimitedDescription.java
@@ -23,8 +23,6 @@ import java.util.List;
/**
* Discards old entries when current count is over the limit.
- * <p>
- * by Szczepan Faber, created at: 2/28/12
*/
public class LimitedDescription {
diff --git a/subprojects/core/src/main/resources/org/gradle/configuration/default-imports.txt b/subprojects/core/src/main/resources/org/gradle/configuration/default-imports.txt
deleted file mode 100644
index 1d22590..0000000
--- a/subprojects/core/src/main/resources/org/gradle/configuration/default-imports.txt
+++ /dev/null
@@ -1,38 +0,0 @@
-import org.gradle.*
-import org.gradle.util.*
-import org.gradle.api.*
-import org.gradle.api.artifacts.*
-import org.gradle.api.artifacts.result.*
-import org.gradle.api.artifacts.dsl.*
-import org.gradle.api.artifacts.maven.*
-import org.gradle.api.artifacts.specs.*
-import org.gradle.api.publish.*
-import org.gradle.api.publish.ivy.*
-import org.gradle.api.publish.ivy.tasks.*
-import org.gradle.api.publish.maven.*
-import org.gradle.api.publish.maven.tasks.*
-import org.gradle.api.execution.*
-import org.gradle.api.file.*
-import org.gradle.api.resources.*
-import org.gradle.api.initialization.*
-import org.gradle.api.invocation.*
-import org.gradle.api.java.archives.*
-import org.gradle.api.logging.*
-import org.gradle.api.plugins.*
-import org.gradle.plugins.ide.eclipse.*
-import org.gradle.plugins.ide.idea.*
-import org.gradle.plugins.jetty.*
-import org.gradle.api.plugins.quality.*
-import org.gradle.api.plugins.announce.*
-import org.gradle.api.plugins.buildcomparison.gradle.*
-import org.gradle.api.specs.*
-import org.gradle.api.tasks.*
-import org.gradle.api.tasks.bundling.*
-import org.gradle.api.tasks.diagnostics.*
-import org.gradle.api.tasks.compile.*
-import org.gradle.api.tasks.javadoc.*
-import org.gradle.api.tasks.testing.*
-import org.gradle.api.tasks.util.*
-import org.gradle.api.tasks.wrapper.*
-import org.gradle.api.tasks.scala.*
-import org.gradle.process.*
diff --git a/subprojects/core/src/main/resources/org/gradle/initialization/buildsrc/defaultBuildSourceScript.txt b/subprojects/core/src/main/resources/org/gradle/initialization/buildsrc/defaultBuildSourceScript.txt
new file mode 100644
index 0000000..86b3740
--- /dev/null
+++ b/subprojects/core/src/main/resources/org/gradle/initialization/buildsrc/defaultBuildSourceScript.txt
@@ -0,0 +1,6 @@
+apply plugin: 'groovy'
+dependencies {
+ compile gradleApi()
+ compile localGroovy()
+}
+
diff --git a/subprojects/core/src/main/resources/org/gradle/initialization/defaultBuildSourceScript.txt b/subprojects/core/src/main/resources/org/gradle/initialization/defaultBuildSourceScript.txt
deleted file mode 100644
index a47ee21..0000000
--- a/subprojects/core/src/main/resources/org/gradle/initialization/defaultBuildSourceScript.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-apply plugin: 'groovy'
-dependencies {
- compile gradleApi()
- groovy localGroovy()
-}
diff --git a/subprojects/core/src/test/groovy/org/gradle/StartParameterTest.groovy b/subprojects/core/src/test/groovy/org/gradle/StartParameterTest.groovy
index fccd6e5..2b4ade3 100644
--- a/subprojects/core/src/test/groovy/org/gradle/StartParameterTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/StartParameterTest.groovy
@@ -25,9 +25,6 @@ import spock.lang.Specification
import static org.gradle.util.Matchers.isSerializable
import static org.junit.Assert.assertThat
-/**
- * @author Hans Dockter
- */
class StartParameterTest extends Specification {
@Rule private TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider()
@Rule private SetSystemProperties systemProperties = new SetSystemProperties()
@@ -286,19 +283,6 @@ class StartParameterTest extends Specification {
assertThat(newParameter, isSerializable())
}
- void "system properties are merged"() {
- def parameter = new StartParameter()
-
- System.properties.clear()
- System.properties.a = "sys a"
- System.properties.c = "sys c"
-
- parameter.systemPropertiesArgs= [a: 'a', b: 'b']
-
- expect:
- parameter.mergedSystemProperties.sort() == [a: 'a', b: 'b', c: 'sys c']
- }
-
void "gets all init scripts"() {
def gradleUserHomeDir = tmpDir.testDirectory.createDir("gradleUserHomeDie")
def gradleHomeDir = tmpDir.testDirectory.createDir("gradleHomeDir")
@@ -330,16 +314,4 @@ class StartParameterTest extends Specification {
then:
parameter.allInitScripts == [userMainInit, userInit1, userInit2, distroInit1, distroInit2]
}
-
- def "knows if parallel feature was configured"() {
- def parameter = new StartParameter()
- assert !parameter.parallelThreadCountConfigured
-
- when:
- parameter.setParallelThreadCount(15)
-
- then:
- parameter.parallelThreadCount == 15
- parameter.parallelThreadCountConfigured
- }
}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/AllGradleExceptionsTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/AllGradleExceptionsTest.groovy
index 4523490..47a1f9c 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/AllGradleExceptionsTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/AllGradleExceptionsTest.groovy
@@ -17,11 +17,9 @@
package org.gradle.api
import org.junit.Test
-import static org.junit.Assert.*;
-/**
- * @author Hans Dockter
- */
+import static org.junit.Assert.assertEquals;
+
class AllGradleExceptionsTest {
static final List EXCEPTION_CLASSES = [UnknownTaskException, UnknownProjectException, InvalidUserDataException, GradleException, CircularReferenceException]
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/file/ProjectCopySpecTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/file/ProjectCopySpecTest.groovy
new file mode 100644
index 0000000..ec124a5
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/api/file/ProjectCopySpecTest.groovy
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.file
+
+import org.gradle.api.Project
+import org.gradle.test.fixtures.file.TestFile
+import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
+import org.gradle.testfixtures.ProjectBuilder
+import org.junit.Rule
+import spock.lang.Specification
+
+class ProjectCopySpecTest extends Specification {
+
+ Project project
+
+ @Rule TestNameTestDirectoryProvider testDirectoryProvider = new TestNameTestDirectoryProvider()
+
+ def setup() {
+ project = ProjectBuilder.builder().withProjectDir(testDirectoryProvider.testDirectory).build()
+ }
+
+ TestFile getCopySource() {
+ testDirectoryProvider.testDirectory.createDir("source")
+ }
+
+ TestFile getCopyDest() {
+ testDirectoryProvider.testDirectory.createDir("dest")
+ }
+
+
+ def "copy spec is enhanced"() {
+ given:
+ def copySpecRootCalled = false
+ def copySpecEachFileCalled = false
+ def copySpecNestedEachFileCalled = false
+ def copyRootCalled = false
+ def copyEachFileCalled = false
+ def copyNestedEachFileCalled = false
+
+ copySource.createFile("file")
+ def copySpec = project.copySpec {
+ copySpecRootCalled = true
+ delegate.duplicatesStrategy "include"
+ from copySource
+
+ from copySource, {
+ delegate.duplicatesStrategy "include"
+ delegate.eachFile {
+ copySpecNestedEachFileCalled = true
+ delegate.duplicatesStrategy "include"
+ }
+ }
+
+ eachFile {
+ copySpecEachFileCalled = true
+ delegate.duplicatesStrategy "include"
+ }
+ }
+
+ expect:
+ project.copy {
+ copyRootCalled = true
+ into copyDest
+ with copySpec
+ from copySource
+ from copySource, {
+ delegate.duplicatesStrategy "include"
+ eachFile {
+ copyNestedEachFileCalled = true
+ delegate.duplicatesStrategy "include"
+ }
+ }
+ delegate.duplicatesStrategy "include"
+
+ eachFile {
+ delegate.duplicatesStrategy "include"
+ copyEachFileCalled = true
+ }
+ }
+
+ and:
+ copyRootCalled
+ copyEachFileCalled
+ copyNestedEachFileCalled
+ copySpecRootCalled
+ copySpecEachFileCalled
+ copySpecNestedEachFileCalled
+ }
+
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/AbstractNamedDomainObjectContainerTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/AbstractNamedDomainObjectContainerTest.groovy
index 75d6cf1..7d6d560 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/AbstractNamedDomainObjectContainerTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/AbstractNamedDomainObjectContainerTest.groovy
@@ -15,115 +15,147 @@
*/
package org.gradle.api.internal
-import org.junit.Ignore
-import org.junit.Test
-import static org.hamcrest.Matchers.*
-import static org.junit.Assert.assertThat
-import static org.junit.Assert.fail
+import org.gradle.api.Action
+import org.gradle.api.InvalidUserDataException
import org.gradle.internal.reflect.Instantiator
import org.gradle.internal.reflect.DirectInstantiator
-class AbstractNamedDomainObjectContainerTest {
- private final Instantiator instantiator = new ClassGeneratorBackedInstantiator(new AsmBackedClassGenerator(), new DirectInstantiator())
- private final AbstractNamedDomainObjectContainer container = instantiator.newInstance(TestContainer.class, instantiator)
+import spock.lang.Ignore
+import spock.lang.Specification
- @Test
- public void isDynamicObjectAware() {
- assertThat(container, instanceOf(DynamicObjectAware));
+class AbstractNamedDomainObjectContainerTest extends Specification {
+ Instantiator instantiator = new ClassGeneratorBackedInstantiator(new AsmBackedClassGenerator(), new DirectInstantiator())
+ AbstractNamedDomainObjectContainer container = instantiator.newInstance(TestContainer.class, instantiator)
+
+ def "is dynamic object aware"() {
+ expect:
+ container instanceof DynamicObjectAware
}
- @Test
- public void canAddObjectWithName() {
+ def "can create object by name"() {
+ when:
container.create('obj')
- assertThat(container.getByName('obj'), equalTo(['obj']))
+
+ then:
+ container.getByName('obj') == ['obj']
}
- @Test
- public void canAddAndConfigureAnObjectWithName() {
+ def "can create and configure object using closure"() {
+ when:
container.create('obj') {
add(1)
add('value')
}
- assertThat(container.getByName('obj'), equalTo(['obj', 1, 'value']))
+
+ then:
+ container.getByName('obj') == ['obj', 1, 'value']
+ }
+
+ def "can create and configure object using action"() {
+ def action = Mock(Action)
+
+ given:
+ action.execute(_) >> { TestObject obj ->
+ obj.add(1)
+ obj.add('value')
+ }
+
+ when:
+ container.create('obj', action)
+
+ then:
+ container.getByName('obj') == ['obj', 1, 'value']
}
- @Test
- public void canUseMaybeCreateToFindOrCreateObjectWithName() {
+ def "can use 'maybeCreate' to find or create object by name"() {
+ when:
def created = container.maybeCreate('obj')
- assertThat(container.getByName('obj'), equalTo(['obj']))
+ then:
+ container.getByName('obj') == ['obj']
+
+ when:
def fetched = container.maybeCreate('obj')
- assertThat(fetched, sameInstance(created))
+
+ then:
+ fetched.is(created)
}
- @Test
- public void failsToAddObjectWhenObjectWithSameNameAlreadyInContainer() {
+ def "creation fails if object with same name already exists"() {
container.create('obj')
- try {
- container.create('obj')
- fail()
- } catch (org.gradle.api.InvalidUserDataException e) {
- assertThat(e.message, equalTo('Cannot add a TestObject with name \'obj\' as a TestObject with that name already exists.'))
- }
+ when:
+ container.create('obj')
+
+ then:
+ InvalidUserDataException e = thrown()
+ e.message == 'Cannot add a TestObject with name \'obj\' as a TestObject with that name already exists.'
}
- @Test
- public void canConfigureExistingObject() {
+ def "can configure existing object"() {
container.create('list1')
+
+ when:
container.configure {
list1 { add(1) }
}
- assertThat(container.list1, equalTo(['list1', 1]))
+
+ then:
+ container.list1 == ['list1', 1]
}
- @Test
- public void propagatesNestedMissingMethodException() {
+ def "propagates nested MissingMethodException"() {
container.create('list1')
- try {
- container.configure {
- list1 { unknown { anotherUnknown(2) } }
- }
- } catch (groovy.lang.MissingMethodException e) {
- assertThat(e.method, equalTo('unknown'))
- assertThat(e.type, equalTo(TestObject))
+
+ when:
+ container.configure {
+ list1 { unknown { anotherUnknown(2) } }
}
+
+ then:
+ groovy.lang.MissingMethodException e = thrown()
+ e.method == 'unknown'
+ e.type == TestObject
}
- @Test
- public void propagatesMethodInvocationException() {
+ def "propagates method invocation exception"() {
RuntimeException failure = new RuntimeException()
- try {
- container.configure {
- list1 { throw failure }
- }
- } catch (RuntimeException e) {
- assertThat(e, sameInstance(failure))
+
+ when:
+ container.configure {
+ list1 { throw failure }
}
+
+ then:
+ RuntimeException e = thrown()
+ e.is(failure)
}
- @Test
- public void implicitlyAddsAnObjectWhenContainerIsBeingConfigured() {
+ def "implicitly creates an object when container is being configured"() {
+ when:
container.configure {
list1
list2 { add(1) }
}
- assertThat(container.list1, equalTo(['list1']))
- assertThat(container.list2, equalTo(['list2', 1]))
+
+ then:
+ container.list1 == ['list1']
+ container.list2 == ['list2', 1]
}
- @Test
- public void canReferToPropertiesAndMethodsOfOwner() {
+ def "can refer to properties and methods of owner"() {
new DynamicOwner().configure(container)
- assertThat(container.asMap.keySet(), equalTo(['list1', 'list2'] as Set))
- assertThat(container.list1, equalTo(['list1', 'dynamicProp', 'ownerProp', 'ownerMethod', 'dynamicMethod', 'dynamicMethod', 1, 'prop', 'testObjectDynamicMethod']))
- assertThat(container.list1.prop, equalTo('prop'))
- assertThat(container.list2, equalTo(['list2', container.list1]))
+
+ expect:
+ container.asMap.keySet() == ['list1', 'list2'] as Set
+ container.list1 == ['list1', 'dynamicProp', 'ownerProp', 'ownerMethod', 'dynamicMethod', 'dynamicMethod', 1, 'prop', 'testObjectDynamicMethod']
+ container.list1.prop == 'prop'
+ container.list2 == ['list2', container.list1]
}
- @Test @Ignore
- public void canUseAnItemCalledMainInAScript() {
- Script script = new GroovyShell().parse("""import org.gradle.util.ConfigureUtil
+ @Ignore
+ def "can use an item called 'main' in a script"() {
+ def script = new GroovyShell().parse("""import org.gradle.util.ConfigureUtil
c.configure {
run
main { add(1) }
@@ -131,10 +163,13 @@ class AbstractNamedDomainObjectContainerTest {
""")
script.getBinding().setProperty("c", container)
+
+ when:
script.run()
- assertThat(container.run, equalTo(['run']))
- assertThat(container.main, equalTo(['main', 1]))
+ then:
+ container.run == ['run']
+ container.main == ['main', 1]
}
}
@@ -195,8 +230,9 @@ class DynamicOwner {
}
class TestObject extends ArrayList<String> {
- def String prop
+ String prop
String name
+
def methodMissing(String name, Object params) {
if (name == 'testObjectDynamicMethod') {
add(name)
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/AbstractTaskSpec.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/AbstractTaskSpec.groovy
index d7607f0..c8d5ae1 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/AbstractTaskSpec.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/AbstractTaskSpec.groovy
@@ -25,7 +25,7 @@ import org.gradle.internal.reflect.DirectInstantiator
import org.gradle.internal.reflect.Instantiator
import org.gradle.internal.service.DefaultServiceRegistry
import org.gradle.util.GUtil
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import org.junit.Test
import spock.lang.Specification
@@ -42,7 +42,7 @@ class AbstractTaskSpec extends Specification {
}
public Task createTask(String name) {
- AbstractProject project = HelperUtil.createRootProject();
+ AbstractProject project = TestUtil.createRootProject();
DefaultServiceRegistry registry = new DefaultServiceRegistry();
registry.add(Instantiator.class, new DirectInstantiator());
Task task = rootFactory.createChild(project, instantiator).createTask(GUtil.map(Task.TASK_TYPE, TestTask.class, Task.TASK_NAME, name));
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/AsmBackedClassGeneratorGroovyTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/AsmBackedClassGeneratorGroovyTest.groovy
index 5523da1..69f3cef 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/AsmBackedClassGeneratorGroovyTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/AsmBackedClassGeneratorGroovyTest.groovy
@@ -16,11 +16,14 @@
package org.gradle.api.internal
+import org.gradle.api.Action
+import org.gradle.api.NonExtensible
+import org.gradle.api.internal.coerce.TypeCoercionException
+import org.gradle.api.plugins.ExtensionAware
import org.gradle.internal.reflect.DirectInstantiator
-import spock.lang.Specification
-import spock.lang.Issue
import org.gradle.util.ConfigureUtil
-import org.gradle.api.Action
+import spock.lang.Issue
+import spock.lang.Specification
class AsmBackedClassGeneratorGroovyTest extends Specification {
@@ -138,9 +141,164 @@ class AsmBackedClassGeneratorGroovyTest extends Specification {
tester.lastArgs.last().is(closure)
}
+ def "can coerce enum values"() {
+ given:
+ def i = create(EnumCoerceTestSubject)
+
+ when:
+ i.enumProperty = "abc"
+
+ then:
+ i.enumProperty == TestEnum.ABC
+
+ when:
+ i.someEnumMethod("DEF")
+
+ then:
+ i.enumProperty == TestEnum.DEF
+
+ when:
+ i.enumProperty "abc"
+
+ then:
+ i.enumProperty == TestEnum.ABC
+
+ when:
+ i.enumProperty "foo"
+
+ then:
+ thrown TypeCoercionException
+
+ when:
+ i.enumMethodWithStringOverload("foo")
+
+ then:
+ i.stringValue == "foo"
+
+ when:
+ i.enumMethodWithStringOverload(TestEnum.DEF)
+
+ then:
+ i.enumProperty == TestEnum.DEF
+ }
+
+ def "can call methods during construction"() {
+ /*
+ We route all methods through invokeMethod, which requires fields
+ added in the subclass. We have special handling for the case where
+ methods are called before this field has been initialised; this tests that.
+ */
+ when:
+ def i = create(CallsMethodDuringConstruction)
+
+ then:
+ i.setDuringConstructor == i.class
+ i.setAtFieldInit == i.class
+ }
+
+ def "can call private methods internally"() {
+ /*
+ We have to specially handle private methods in our dynamic protocol.
+ */
+ given:
+ def i = create(CallsPrivateMethods)
+
+ when:
+ i.flagCalled("a")
+
+ then:
+ i.calledWith == String
+
+ when:
+ i.flagCalled(1.2)
+
+ then:
+ i.calledWith == Number
+
+ when:
+ i.flagCalled([])
+
+ then:
+ i.calledWith == Object
+
+ when:
+ i.flagCalled(1)
+
+ then:
+ i.calledWith == Integer
+ }
+
+
+ def "can use non extensible objects"() {
+ def i = create(NonExtensibleObject)
+
+ when:
+ i.testEnum "ABC"
+
+ then:
+ i.testEnum == TestEnum.ABC
+
+ !(TestEnum instanceof ExtensionAware)
+ !(TestEnum instanceof IConventionAware)
+ !(TestEnum instanceof HasConvention)
+
+ when:
+ i.ext.foo = "bar"
+
+ then:
+ def e = thrown(MissingPropertyException)
+ e.property == "ext"
+ }
+
def conf(o, c) {
ConfigureUtil.configure(c, o)
}
+
+ @Issue("http://issues.gradle.org/browse/GRADLE-2863")
+ def "checked exceptions from private methods are thrown"() {
+ when:
+ create(CallsPrivateMethods).callsPrivateThatThrowsCheckedException("1")
+
+ then:
+ thrown IOException
+ }
+
+ @Issue("http://issues.gradle.org/browse/GRADLE-2863")
+ def "private methods are called with Groovy semantics"() {
+ when:
+ def foo = "bar"
+ def obj = create(CallsPrivateMethods)
+
+ then:
+ obj.callsPrivateStringMethodWithGString("$foo") == "BAR"
+ }
+}
+
+enum TestEnum {
+ ABC, DEF
+}
+
+class EnumCoerceTestSubject {
+ TestEnum enumProperty
+
+ String stringValue
+
+ void someEnumMethod(TestEnum testEnum) {
+ this.enumProperty = testEnum
+ }
+
+ void enumMethodWithStringOverload(TestEnum testEnum) {
+ enumProperty = testEnum
+ }
+
+ void enumMethodWithStringOverload(String stringValue) {
+ this.stringValue = stringValue
+ }
+}
+
+ at NonExtensible
+class NonExtensibleObject {
+ TestEnum testEnum
}
class DynamicThing {
@@ -209,7 +367,62 @@ class ActionsTester {
lastMethod = "hasClosure"
lastArgs = [s, closure]
}
+}
+
+class CallsMethodDuringConstruction {
+ Class setAtFieldInit = getClass()
+ Class setDuringConstructor
+ CallsMethodDuringConstruction() {
+ setDuringConstructor = getClass()
+ }
+}
-}
\ No newline at end of file
+class CallsPrivateMethods {
+
+ Class calledWith
+
+ void flagCalled(arg) {
+ doFlagCalled(arg)
+ }
+
+ private doFlagCalled(String s) {
+ calledWith = String
+ }
+
+ private doFlagCalled(Number s) {
+ calledWith = Number
+ }
+
+ private doFlagCalled(Integer s) {
+ calledWith = Integer
+ }
+
+ private doFlagCalled(Object s) {
+ calledWith = Object
+ }
+
+ // It's important here that we take an untyped arg, and call a method that types a typed arg
+ // See http://issues.gradle.org/browse/GRADLE-2863
+ def callsPrivateThatThrowsCheckedException(s) {
+ try {
+ throwsCheckedException(s)
+ } catch (Exception e) {
+ assert e instanceof IOException
+ throw e
+ }
+ }
+
+ private throwsCheckedException(String a) {
+ throw new IOException("!")
+ }
+
+ def callsPrivateStringMethodWithGString(GString gString) {
+ upperCaser(gString)
+ }
+
+ private upperCaser(String str) {
+ str.toUpperCase()
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/AsmBackedClassGeneratorTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/AsmBackedClassGeneratorTest.java
index 7e86531..0278604 100755
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/AsmBackedClassGeneratorTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/AsmBackedClassGeneratorTest.java
@@ -35,8 +35,8 @@ import java.lang.reflect.*;
import java.util.*;
import java.util.concurrent.Callable;
-import static org.gradle.util.HelperUtil.TEST_CLOSURE;
-import static org.gradle.util.HelperUtil.call;
+import static org.gradle.util.TestUtil.TEST_CLOSURE;
+import static org.gradle.util.TestUtil.call;
import static org.gradle.util.Matchers.isEmpty;
import static org.gradle.util.WrapUtil.toList;
import static org.hamcrest.Matchers.*;
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/CachingDirectedGraphWalkerTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/CachingDirectedGraphWalkerTest.groovy
deleted file mode 100644
index 26da809..0000000
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/CachingDirectedGraphWalkerTest.groovy
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal
-
-import spock.lang.Specification
-
-class CachingDirectedGraphWalkerTest extends Specification {
- private final DirectedGraphWithEdgeValues<Integer, String> graph = Mock()
- private final CachingDirectedGraphWalker walker = new CachingDirectedGraphWalker(graph)
-
- def collectsValuesForASingleNode() {
- when:
- walker.add(1)
- def values = walker.findValues()
-
- then:
- 1 * graph.getNodeValues(1, _, _) >> { args -> args[1] << '1' }
- 0 * _._
- values == ['1'] as Set
- }
-
- def collectsValuesForEachSuccessorNode() {
- when:
- walker.add(1)
- def values = walker.findValues()
-
- then:
- 1 * graph.getNodeValues(1, _, _) >> { args -> args[1] << '1'; args[2] << 2; args[2] << 3 }
- 1 * graph.getNodeValues(2, _, _) >> { args -> args[1] << '2'; args[2] << 3 }
- 1 * graph.getNodeValues(3, _, _) >> { args -> args[1] << '3' }
- 3 * graph.getEdgeValues(_, _, _)
- 0 * _._
- values == ['1', '2', '3'] as Set
- }
-
- def collectsValuesForEachEdgeTraversed() {
- when:
- walker.add(1)
- def values = walker.findValues()
-
- then:
- 1 * graph.getNodeValues(1, _, _) >> { args -> args[2] << 2; args[2] << 3 }
- 1 * graph.getEdgeValues(1, 2, _) >> { args -> args[2] << '1->2' }
- 1 * graph.getEdgeValues(1, 3, _) >> { args -> args[2] << '1->3' }
- 1 * graph.getNodeValues(2, _, _) >> { args -> args[2] << 3 }
- 1 * graph.getEdgeValues(2, 3, _) >> { args -> args[2] << '2->3' }
- 1 * graph.getNodeValues(3, _, _)
- 0 * _._
- values == ['1->2', '1->3', '2->3'] as Set
- }
-
- def collectsValuesForAllStartNodes() {
- when:
- walker.add(1, 2)
- def values = walker.findValues()
-
- then:
- 1 * graph.getNodeValues(1, _, _) >> { args -> args[1] << '1'; args[2] << 3 }
- 1 * graph.getNodeValues(2, _, _) >> { args -> args[1] << '2'; args[2] << 3 }
- 1 * graph.getNodeValues(3, _, _) >> { args -> args[1] << '3' }
- 2 * graph.getEdgeValues(_, _, _)
- 0 * _._
- values == ['1', '2', '3'] as Set
- }
-
- def collectsValuesWhenCycleIsPresentInGraph() {
- when:
- walker.add(1)
- def values = walker.findValues()
-
- then:
- 1 * graph.getNodeValues(1, _, _) >> { args -> args[1] << '1'; args[2] << 2 }
- 1 * graph.getEdgeValues(1, 2, _) >> { args -> args[2] << '1->2' }
- 1 * graph.getNodeValues(2, _, _) >> { args -> args[1] << '2'; args[2] << 3 }
- 1 * graph.getEdgeValues(2, 3, _) >> { args -> args[2] << '2->3' }
- 1 * graph.getNodeValues(3, _, _) >> { args -> args[1] << '3'; args[2] << 1 }
- 1 * graph.getEdgeValues(3, 1, _) >> { args -> args[2] << '3->1' }
- 0 * _._
- values == ['1', '1->2', '2', '2->3', '3', '3->1'] as Set
- }
-
- def collectsValuesWhenNodeConnectedToItself() {
- when:
- walker.add(1)
- def values = walker.findValues()
-
- then:
- 1 * graph.getNodeValues(1, _, _) >> { args -> args[1] << '1'; args[2] << 1 }
- 1 * graph.getEdgeValues(1, 1, _) >> { args -> args[2] << '1->1' }
- 0 * _._
- values == ['1', '1->1'] as Set
- }
-
- def collectsValuesWhenMultipleCyclesInGraph() {
- when:
- walker.add(1)
- def values = walker.findValues()
-
- then:
- 1 * graph.getNodeValues(1, _, _) >> { args -> args[1] << '1'; args[2] << 1; args[2] << 2 }
- 1 * graph.getNodeValues(2, _, _) >> { args -> args[1] << '2'; args[2] << 3; args[2] << 4 }
- 1 * graph.getNodeValues(3, _, _) >> { args -> args[1] << '3'; args[2] << 2 }
- 1 * graph.getNodeValues(4, _, _) >> { args -> args[1] << '4' }
- 5 * graph.getEdgeValues(_, _, _) >> { args -> args[2] << "${args[0]}->${args[1]}".toString() }
- 0 * _._
- values == ['1', '1->1', '1->2', '2', '2->3', '2->4', '3', '3->2', '4'] as Set
- }
-
- def canReuseWalkerForMultipleSearches() {
- when:
- walker.add(1)
- def values = walker.findValues()
-
- then:
- 1 * graph.getNodeValues(1, _, _) >> { args -> args[1] << '1'; args[2] << 2; args[2] << 3 }
- 1 * graph.getNodeValues(2, _, _) >> { args -> args[1] << '2'; args[2] << 3 }
- 1 * graph.getNodeValues(3, _, _) >> { args -> args[1] << '3' }
- 3 * graph.getEdgeValues(_, _, _)
- 0 * _._
- values == ['1', '2', '3'] as Set
-
- // Cached node (1) is reachable via 2 separate new paths (4->5->1 and 4->6->1)
- when:
- walker.add(4)
- values = walker.findValues()
-
- then:
- 1 * graph.getNodeValues(4, _, _) >> { args -> args[1] << '4'; args[2] << 5; args[2] << 6 }
- 1 * graph.getNodeValues(5, _, _) >> { args -> args[1] << '5'; args[2] << 1 }
- 1 * graph.getNodeValues(6, _, _) >> { args -> args[1] << '6'; args[2] << 1 }
- 4 * graph.getEdgeValues(_, _, _) >> { args -> args[2] << "${args[0]}->${args[1]}".toString() }
- 0 * _._
- values == ['4', '4->5', '4->6', '5', '5->1', '6', '6->1', '1', '2', '3'] as Set
-
- when:
- walker.add(2)
- values = walker.findValues()
-
- then:
- values == ['2', '3'] as Set
- }
-
- def canReuseWalkerWhenGraphContainsACycle() {
- when:
- walker.add(1)
- walker.findValues()
-
- then:
- 1 * graph.getNodeValues(1, _, _) >> { args -> args[1] << '1'; args[2] << 2 }
- 1 * graph.getNodeValues(2, _, _) >> { args -> args[1] << '2'; args[2] << 3 }
- 1 * graph.getNodeValues(3, _, _) >> { args -> args[1] << '3'; args[2] << 1; args[2] << 4 }
- 1 * graph.getNodeValues(4, _, _) >> { args -> args[1] << '4'; args[2] << 2}
- 5 * graph.getEdgeValues(_, _, _)
- 0 * _._
-
- when:
- walker.add(1)
- def values = walker.findValues()
-
- then:
- values == ['1', '2', '3', '4'] as Set
-
- when:
- walker.add(2)
- values = walker.findValues()
-
- then:
- values == ['1', '2', '3', '4'] as Set
-
- when:
- walker.add(3)
- values = walker.findValues()
-
- then:
- values == ['1', '2', '3', '4'] as Set
-
- when:
- walker.add(4)
- values = walker.findValues()
-
- then:
- values == ['1', '2', '3', '4'] as Set
- }
-}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/ChainingTransformerTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/ChainingTransformerTest.java
index a9c4c5a..1982ce8 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/ChainingTransformerTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/ChainingTransformerTest.java
@@ -15,6 +15,7 @@
*/
package org.gradle.api.internal;
+import org.gradle.util.TestUtil;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.jmock.integration.junit4.JMock;
import org.jmock.Expectations;
@@ -22,7 +23,6 @@ import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.gradle.util.HelperUtil;
import org.gradle.api.Transformer;
import groovy.lang.Closure;
@@ -59,7 +59,7 @@ public class ChainingTransformerTest {
@Test
public void canUseAClosureAsATransformer() {
- Closure closure = HelperUtil.toClosure("{ it + ' transformed' }");
+ Closure closure = TestUtil.toClosure("{ it + ' transformed' }");
transformer.add(closure);
@@ -68,7 +68,7 @@ public class ChainingTransformerTest {
@Test
public void usesOriginalObjectWhenClosureReturnsNull() {
- Closure closure = HelperUtil.toClosure("{ null }");
+ Closure closure = TestUtil.toClosure("{ null }");
transformer.add(closure);
@@ -77,7 +77,7 @@ public class ChainingTransformerTest {
@Test
public void usesOriginalObjectWhenClosureReturnsObjectOfUnexpectedType() {
- Closure closure = HelperUtil.toClosure("{ 9 }");
+ Closure closure = TestUtil.toClosure("{ 9 }");
transformer.add(closure);
@@ -86,7 +86,7 @@ public class ChainingTransformerTest {
@Test
public void originalObjectIsSetAsDelegateForClosure() {
- Closure closure = HelperUtil.toClosure("{ substring(1, 3) }");
+ Closure closure = TestUtil.toClosure("{ substring(1, 3) }");
transformer.add(closure);
@@ -95,7 +95,7 @@ public class ChainingTransformerTest {
@Test
public void closureCanTransformAStringIntoAGString() {
- Closure closure = HelperUtil.toClosure("{ \"[$it]\" }");
+ Closure closure = TestUtil.toClosure("{ \"[$it]\" }");
transformer.add(closure);
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/CompositeDomainObjectSetTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/CompositeDomainObjectSetTest.groovy
index 379a394..1a8a981 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/CompositeDomainObjectSetTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/CompositeDomainObjectSetTest.groovy
@@ -345,13 +345,12 @@ class CompositeDomainObjectSetTest extends Specification {
and:
component1 << "a" << "c"
- component2 << "a" << "d"
+ component2 << "a" << "d" << "a"
then:
- calledFor == ["c", "d"]
+ calledFor == ["a", "c", "d"]
}
- @IgnoreRest
def "all notifications are only fired once for each in composite"() {
given:
def component1 = collection("a")
@@ -400,4 +399,28 @@ class CompositeDomainObjectSetTest extends Specification {
thrown UnsupportedOperationException
}
+ def "behaves when the same collection added"() {
+ def same = collection("a", "b")
+ def composite = composite(same, same, same)
+
+ expect:
+ composite.toList() == ['a', 'b']
+
+ when:
+ same << 'c'
+
+ then:
+ composite.toList() == ['a', 'b', 'c']
+ }
+
+ def "removing collection removes all instances"() {
+ def instance = collection("a", "b")
+ def composite = composite(instance, instance)
+
+ when:
+ composite.removeCollection(instance)
+
+ then:
+ composite.toList() == []
+ }
}
\ No newline at end of file
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/ConventionAwareHelperTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/ConventionAwareHelperTest.java
index 4cd4991..3be760a 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/ConventionAwareHelperTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/ConventionAwareHelperTest.java
@@ -17,7 +17,7 @@
package org.gradle.api.internal;
import org.gradle.api.InvalidUserDataException;
-import org.gradle.util.HelperUtil;
+import org.gradle.util.TestUtil;
import org.gradle.util.TestTask;
import org.junit.Before;
import org.junit.Test;
@@ -33,28 +33,25 @@ import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.sameInstance;
import static org.junit.Assert.*;
-/**
- * @author Hans Dockter
- */
public class ConventionAwareHelperTest {
ConventionAwareHelper conventionAware;
TestTask testTask;
@Before public void setUp() {
- testTask = HelperUtil.createTask(TestTask.class);
+ testTask = TestUtil.createTask(TestTask.class);
conventionAware = new ConventionAwareHelper(testTask);
}
@Test
public void canMapPropertiesUsingClosure() {
- conventionAware.map("list1", HelperUtil.toClosure("{ ['a'] }"));
+ conventionAware.map("list1", TestUtil.toClosure("{ ['a'] }"));
assertThat(conventionAware.getConventionValue(null, "list1", false), equalTo((Object) toList("a")));
- conventionAware.map("list1", HelperUtil.toClosure("{ convention -> [convention] }"));
+ conventionAware.map("list1", TestUtil.toClosure("{ convention -> [convention] }"));
assertThat(conventionAware.getConventionValue(null, "list1", false), equalTo((Object) toList(conventionAware.getConvention())));
- conventionAware.map("list1", HelperUtil.toClosure("{ convention, object -> [convention, object] }"));
+ conventionAware.map("list1", TestUtil.toClosure("{ convention, object -> [convention, object] }"));
assertThat(conventionAware.getConventionValue(null, "list1", false), equalTo((Object) toList(conventionAware.getConvention(), testTask)));
}
@@ -72,7 +69,7 @@ public class ConventionAwareHelperTest {
@Test
public void canSetMappingUsingDynamicProperty() {
- HelperUtil.call("{ it.list1 = { ['a'] } }", conventionAware);
+ TestUtil.call("{ it.list1 = { ['a'] } }", conventionAware);
assertThat(conventionAware.getConventionValue(null, "list1", false), equalTo((Object) toList("a")));
}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultDomainObjectCollectionTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultDomainObjectCollectionTest.java
index 5408f9c..95101d1 100755
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultDomainObjectCollectionTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultDomainObjectCollectionTest.java
@@ -18,7 +18,7 @@ package org.gradle.api.internal;
import org.gradle.api.Action;
import org.gradle.api.DomainObjectCollection;
import org.gradle.api.specs.Spec;
-import org.gradle.util.HelperUtil;
+import org.gradle.util.TestUtil;
import org.gradle.util.TestClosure;
import org.hamcrest.Description;
import org.jmock.Expectations;
@@ -121,7 +121,7 @@ public class DefaultDomainObjectCollectionTest {
container.add("c");
assertThat(toList(container.matching(spec)), equalTo(toList((CharSequence) "a", "c")));
- assertThat(toList(container.matching(HelperUtil.toClosure(testClosure))), equalTo(toList((CharSequence) "a", "c")));
+ assertThat(toList(container.matching(TestUtil.toClosure(testClosure))), equalTo(toList((CharSequence) "a", "c")));
}
@Test
@@ -162,7 +162,7 @@ public class DefaultDomainObjectCollectionTest {
one(closure).call("a");
}});
- container.withType(String.class, HelperUtil.toClosure(closure));
+ container.withType(String.class, TestUtil.toClosure(closure));
container.add("a");
}
@@ -220,7 +220,7 @@ public class DefaultDomainObjectCollectionTest {
}
};
- container.matching(spec).whenObjectAdded(HelperUtil.toClosure(closure));
+ container.matching(spec).whenObjectAdded(TestUtil.toClosure(closure));
container.add("a");
container.add("b");
@@ -254,7 +254,7 @@ public class DefaultDomainObjectCollectionTest {
container.add("b");
container.add("c");
- Collection<CharSequence> collection = container.findAll(HelperUtil.toClosure("{ it != 'b' }"));
+ Collection<CharSequence> collection = container.findAll(TestUtil.toClosure("{ it != 'b' }"));
assertThat(collection, instanceOf(List.class));
assertThat(collection, equalTo((Collection) toList("a", "c")));
}
@@ -265,7 +265,7 @@ public class DefaultDomainObjectCollectionTest {
container.add("b");
container.add("c");
- Collection<CharSequence> collection = container.findAll(HelperUtil.toClosure("{ it != 'b' }"));
+ Collection<CharSequence> collection = container.findAll(TestUtil.toClosure("{ it != 'b' }"));
container.add("d");
assertThat(collection, equalTo((Collection) toList("a", "c")));
@@ -292,7 +292,7 @@ public class DefaultDomainObjectCollectionTest {
one(closure).call("a");
}});
- container.whenObjectAdded(HelperUtil.toClosure(closure));
+ container.whenObjectAdded(TestUtil.toClosure(closure));
container.add("a");
}
@@ -306,13 +306,13 @@ public class DefaultDomainObjectCollectionTest {
one(closure).call("a");
}});
- container.whenObjectRemoved(HelperUtil.toClosure(closure));
+ container.whenObjectRemoved(TestUtil.toClosure(closure));
container.remove("a");
}
@Test
public void callsClosureWithNewObjectAsDelegateWhenObjectAdded() {
- container.whenObjectAdded(HelperUtil.toClosure("{ assert delegate == 'a' }"));
+ container.whenObjectAdded(TestUtil.toClosure("{ assert delegate == 'a' }"));
container.add("a");
}
@@ -373,7 +373,7 @@ public class DefaultDomainObjectCollectionTest {
}});
container.add("a");
- container.all(HelperUtil.toClosure(closure));
+ container.all(TestUtil.toClosure(closure));
}
@Test
@@ -397,13 +397,13 @@ public class DefaultDomainObjectCollectionTest {
one(closure).call("a");
}});
- container.all(HelperUtil.toClosure(closure));
+ container.all(TestUtil.toClosure(closure));
container.add("a");
}
@Test
public void allCallsClosureWithObjectAsDelegate() {
- container.all(HelperUtil.toClosure(" { assert delegate == 'a' } "));
+ container.all(TestUtil.toClosure(" { assert delegate == 'a' } "));
container.add("a");
}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultNamedDomainObjectSetTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultNamedDomainObjectSetTest.java
index 514c216..3ea532d 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultNamedDomainObjectSetTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultNamedDomainObjectSetTest.java
@@ -22,7 +22,7 @@ import org.gradle.api.specs.Spec;
import org.gradle.api.specs.Specs;
import org.gradle.util.ConfigureUtil;
import org.gradle.util.GUtil;
-import org.gradle.util.HelperUtil;
+import org.gradle.util.TestUtil;
import org.gradle.util.TestClosure;
import org.jmock.Expectations;
import org.jmock.integration.junit4.JMock;
@@ -32,8 +32,8 @@ import org.junit.runner.RunWith;
import java.util.Iterator;
-import static org.gradle.util.HelperUtil.call;
-import static org.gradle.util.HelperUtil.toClosure;
+import static org.gradle.util.TestUtil.call;
+import static org.gradle.util.TestUtil.toClosure;
import static org.gradle.util.WrapUtil.toList;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
@@ -167,7 +167,7 @@ public class DefaultNamedDomainObjectSetTest {
container.add(bean3);
assertThat(toList(container.matching(spec)), equalTo(toList(bean2, bean3)));
- assertThat(toList(container.matching(HelperUtil.toClosure(testClosure))), equalTo(toList(bean2, bean3)));
+ assertThat(toList(container.matching(TestUtil.toClosure(testClosure))), equalTo(toList(bean2, bean3)));
assertThat(container.matching(spec).findByName("a"), nullValue());
assertThat(container.matching(spec).findByName("b"), sameInstance(bean2));
}
@@ -234,7 +234,7 @@ public class DefaultNamedDomainObjectSetTest {
one(closure).call(bean2);
}});
- container.withType(OtherBean.class, HelperUtil.toClosure(closure));
+ container.withType(OtherBean.class, TestUtil.toClosure(closure));
}
@Test
@@ -306,7 +306,7 @@ public class DefaultNamedDomainObjectSetTest {
}
};
- container.matching(spec).whenObjectAdded(HelperUtil.toClosure(closure));
+ container.matching(spec).whenObjectAdded(TestUtil.toClosure(closure));
container.add(bean);
container.add(new Bean());
@@ -461,7 +461,7 @@ public class DefaultNamedDomainObjectSetTest {
one(closure).call(bean);
}});
- container.whenObjectAdded(HelperUtil.toClosure(closure));
+ container.whenObjectAdded(TestUtil.toClosure(closure));
container.add(bean);
}
@@ -552,7 +552,7 @@ public class DefaultNamedDomainObjectSetTest {
}});
container.add(bean);
- container.all(HelperUtil.toClosure(closure));
+ container.all(TestUtil.toClosure(closure));
}
@Test
@@ -577,7 +577,7 @@ public class DefaultNamedDomainObjectSetTest {
one(closure).call(bean);
}});
- container.all(HelperUtil.toClosure(closure));
+ container.all(TestUtil.toClosure(closure));
container.add(bean);
}
@@ -704,7 +704,7 @@ public class DefaultNamedDomainObjectSetTest {
public void addRuleByClosure() {
String testPropertyKey = "org.gradle.test.addRuleByClosure";
String expectedTaskName = "someTaskName";
- Closure ruleClosure = HelperUtil.toClosure(String.format("{ taskName -> System.setProperty('%s', '%s') }",
+ Closure ruleClosure = TestUtil.toClosure(String.format("{ taskName -> System.setProperty('%s', '%s') }",
testPropertyKey, expectedTaskName));
container.addRule("description", ruleClosure);
container.getRules().get(0).apply(expectedTaskName);
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultPolymorphicDomainObjectContainerBaseTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultPolymorphicDomainObjectContainerBaseTest.groovy
new file mode 100644
index 0000000..88954e7
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultPolymorphicDomainObjectContainerBaseTest.groovy
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal
+
+import org.gradle.internal.reflect.Instantiator
+
+class DefaultPolymorphicDomainObjectContainerBaseTest extends AbstractNamedDomainObjectContainerTest {
+ def setup() {
+ container = instantiator.newInstance(PolymorphicTestContainer.class, instantiator)
+ }
+
+ static class PolymorphicTestContainer extends AbstractPolymorphicDomainObjectContainer<TestObject> {
+ PolymorphicTestContainer(Instantiator instantiator) {
+ super(TestObject, instantiator, new DynamicPropertyNamer())
+ }
+
+ @Override
+ protected TestObject doCreate(String name) {
+ def testObject = new TestObject()
+ testObject.name = name
+ testObject.add(name)
+ testObject
+ }
+
+ @Override
+ protected <U extends TestObject> U doCreate(String name, Class<U> type) {
+ throw new UnsupportedOperationException("doCreate")
+ }
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultPolymorphicDomainObjectContainerDslTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultPolymorphicDomainObjectContainerDslTest.groovy
index 5c3b2a5..f097a0d 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultPolymorphicDomainObjectContainerDslTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultPolymorphicDomainObjectContainerDslTest.groovy
@@ -18,7 +18,7 @@ package org.gradle.api.internal
import org.gradle.api.Named
import org.gradle.api.NamedDomainObjectFactory
import org.gradle.internal.reflect.Instantiator
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import spock.lang.Specification
@@ -28,7 +28,7 @@ class DefaultPolymorphicDomainObjectContainerDslTest extends Specification {
def agedFred = new DefaultAgeAwarePerson(name: "Fred", age: 42)
def agedBarney = new DefaultAgeAwarePerson(name: "Barney", age: 42)
- def project = HelperUtil.createRootProject()
+ def project = TestUtil.createRootProject()
def instantiator = project.services.get(Instantiator)
def container = instantiator.newInstance(DefaultPolymorphicDomainObjectContainer, Person, instantiator)
@@ -85,17 +85,13 @@ class DefaultPolymorphicDomainObjectContainerDslTest extends Specification {
container.asDynamicObject.getProperty("Barney") == barney
}
- def "configure elements with default type"() {
-
- }
-
def "create elements with specified type"() {
container.registerFactory(Person, { new DefaultPerson(name: it) } as NamedDomainObjectFactory)
container.registerFactory(AgeAwarePerson, { new DefaultAgeAwarePerson(name: it, age: 42) } as NamedDomainObjectFactory)
when:
project.container {
- Fred(Person) {}
+ Fred(Person)
Barney(AgeAwarePerson) {}
}
@@ -105,6 +101,84 @@ class DefaultPolymorphicDomainObjectContainerDslTest extends Specification {
container.findByName("Barney") == agedBarney
container.asDynamicObject.getProperty("Fred") == fred
container.asDynamicObject.getProperty("Barney") == agedBarney
+ }
+
+ def "configure elements with default type"() {
+ container.registerDefaultFactory({ new DefaultAgeAwarePerson(name: it, age: 42) } as NamedDomainObjectFactory)
+
+ when:
+ project.container {
+ Fred {
+ age = 11
+ }
+ Barney {
+ age = 22
+ }
+ }
+ then:
+ container.size() == 2
+ container.findByName("Fred").age == 11
+ container.findByName("Barney").age == 22
+ }
+
+ def "configure elements with specified type"() {
+ container.registerFactory(AgeAwarePerson, { new DefaultAgeAwarePerson(name: it, age: 42) } as NamedDomainObjectFactory)
+
+ when:
+ project.container {
+ Fred(AgeAwarePerson) {
+ age = 11
+ }
+ Barney(AgeAwarePerson) {
+ age = 22
+ }
+ }
+
+ then:
+ container.size() == 2
+ container.findByName("Fred").age == 11
+ container.findByName("Barney").age == 22
+ }
+
+ def "configure same element multiple times"() {
+ container.registerFactory(AgeAwarePerson, { new DefaultAgeAwarePerson(name: it, age: 42) } as NamedDomainObjectFactory)
+
+ when:
+ project.container {
+ Fred(AgeAwarePerson) {
+ age = 11
+ }
+ Barney(AgeAwarePerson) {
+ age = 22
+ }
+ Fred(AgeAwarePerson) {
+ age = 33
+ }
+ Barney(AgeAwarePerson) {
+ age = 44
+ }
+ }
+
+ then:
+ container.size() == 2
+ container.findByName("Fred").age == 33
+ container.findByName("Barney").age == 44
+ }
+
+ def "create elements without configuration"() {
+ container.registerDefaultFactory({ new DefaultAgeAwarePerson(name: it, age: 42) } as NamedDomainObjectFactory)
+ container.registerFactory(AgeAwarePerson, { new DefaultAgeAwarePerson(name: it, age: 43) } as NamedDomainObjectFactory)
+
+ when:
+ project.container {
+ Fred
+ Barney(AgeAwarePerson)
+ }
+
+ then:
+ container.size() == 2
+ container.findByName("Fred").age == 42
+ container.findByName("Barney").age == 43
}
}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultPolymorphicDomainObjectContainerTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultPolymorphicDomainObjectContainerTest.groovy
index 1f1ad01..d149ec2 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultPolymorphicDomainObjectContainerTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultPolymorphicDomainObjectContainerTest.groovy
@@ -63,6 +63,18 @@ class DefaultPolymorphicDomainObjectContainerTest extends Specification {
}
}
+ interface UnnamedPerson {} // doesn't implement Named
+
+ static class DefaultUnnamedPerson {}
+
+ interface CtorNamedPerson extends Person {}
+
+ static class DefaultCtorNamedPerson extends DefaultPerson implements CtorNamedPerson {
+ DefaultCtorNamedPerson(String name) {
+ this.name = name
+ }
+ }
+
def "add elements"() {
when:
container.add(fred)
@@ -95,10 +107,11 @@ class DefaultPolymorphicDomainObjectContainerTest extends Specification {
then:
InvalidUserDataException e = thrown()
- e.message == "This container does not support creating domain objects without specifying a type."
+ e.message == "Cannot create a Person named 'fred' because this container does not support creating " +
+ "elements by name alone. Please specify which subtype of Person to create. Known subtypes are: (None)"
}
- def "create elements with specified type"() {
+ def "create elements with specified type based on NamedDomainObjectFactory"() {
container.registerFactory(Person, { new DefaultPerson(name: it) } as NamedDomainObjectFactory)
container.registerFactory(AgeAwarePerson, { new DefaultAgeAwarePerson(name: it, age: 42) } as NamedDomainObjectFactory)
@@ -114,6 +127,45 @@ class DefaultPolymorphicDomainObjectContainerTest extends Specification {
container.asDynamicObject.getProperty("barney") == agedBarney
}
+ def "create elements with specified type based on closure-based factory"() {
+ container.registerFactory(Person, { new DefaultPerson(name: it) })
+ container.registerFactory(AgeAwarePerson, { new DefaultAgeAwarePerson(name: it, age: 42) })
+
+ when:
+ container.create("fred", Person)
+ container.create("barney", AgeAwarePerson)
+
+ then:
+ container.size() == 2
+ container.findByName("fred") == fred
+ container.findByName("barney") == agedBarney
+ container.asDynamicObject.getProperty("fred") == fred
+ container.asDynamicObject.getProperty("barney") == agedBarney
+ }
+
+ def "create elements with specified type based on type binding"() {
+ container = new DefaultPolymorphicDomainObjectContainer<?>(Object, new DirectInstantiator(),
+ { it instanceof Named ? it.name : "unknown" } as Named.Namer)
+
+ container.registerBinding(UnnamedPerson, DefaultUnnamedPerson)
+ container.registerBinding(CtorNamedPerson, DefaultCtorNamedPerson)
+
+ when:
+ container.create("fred", UnnamedPerson)
+ container.create("barney", CtorNamedPerson)
+
+ then:
+ container.size() == 2
+ !container.findByName("fred")
+ with(container.findByName("unknown")) {
+ it.getClass() == DefaultUnnamedPerson
+ }
+ with(container.findByName("barney")) {
+ it.getClass() == DefaultCtorNamedPerson
+ name == "barney"
+ }
+ }
+
def "throws meaningful exception if it doesn't support creating domain objects with the specified type"() {
container = new DefaultPolymorphicDomainObjectContainer<Person>(Person, new DirectInstantiator())
@@ -122,8 +174,7 @@ class DefaultPolymorphicDomainObjectContainerTest extends Specification {
then:
InvalidUserDataException e = thrown()
- e.message == "This container does not support creating domain objects of type " +
- "'org.gradle.api.internal.DefaultPolymorphicDomainObjectContainerTest\$Person'."
+ e.message == "Cannot create a Person because this type is not known to this container. Known types are: (None)"
}
def "throws meaningful exception if factory element type is not a subtype of container element type"() {
@@ -132,8 +183,8 @@ class DefaultPolymorphicDomainObjectContainerTest extends Specification {
then:
IllegalArgumentException e = thrown()
- e.message == "Factory element type 'java.lang.String' is not a subtype of container element type " +
- "'org.gradle.api.internal.DefaultPolymorphicDomainObjectContainerTest\$Person'"
+ e.message == "Cannot register a factory for type String because it is not a subtype of " +
+ "container element type Person."
}
def "fires events when elements are added"() {
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultTaskTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultTaskTest.groovy
index 11be2ae..808b7b6 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultTaskTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultTaskTest.groovy
@@ -39,9 +39,6 @@ import static org.gradle.util.Matchers.isEmpty
import static org.hamcrest.Matchers.*
import static org.junit.Assert.*
-/**
- * @author Hans Dockter
- */
class DefaultTaskTest extends AbstractTaskTest {
ClassLoader cl
DefaultTask defaultTask
@@ -69,7 +66,7 @@ class DefaultTaskTest extends AbstractTaskTest {
}
@Test public void testHasUsefulToString() {
- assertEquals('task \':taskname\'', task.toString())
+ assertEquals('task \':testTask\'', task.toString())
}
@Test public void testCanInjectValuesIntoTaskWhenUsingNoArgsConstructor() {
@@ -92,6 +89,36 @@ class DefaultTaskTest extends AbstractTaskTest {
}
@Test
+ public void testMustRunAfter() {
+ Task mustRunAfterTask = createTask(project, "mustRunAfter")
+ Task mustRunAfterTaskUsingPath = project.getTasks().add("path")
+ Task task = createTask(project, TEST_TASK_NAME)
+
+ task.mustRunAfter(mustRunAfterTask, "path")
+ assert task.mustRunAfter.getDependencies(task) == [mustRunAfterTask, mustRunAfterTaskUsingPath] as Set
+ }
+
+ @Test
+ public void testFinalizedBy() {
+ Task finalizer = createTask(project, "finalizer")
+ Task finalizerFromPath = project.getTasks().create("path")
+ Task finalized = createTask(project, TEST_TASK_NAME)
+
+ finalized.finalizedBy(finalizer, "path")
+ assert finalized.finalizedBy.getDependencies(finalized) == [finalizer, finalizerFromPath] as Set
+ }
+
+ @Test
+ public void testSetFinalizedBy() {
+ Task finalizer = createTask(project, "finalizer")
+ Task finalizerFromPath = project.getTasks().create("path")
+ Task finalized = createTask(project, TEST_TASK_NAME)
+
+ finalized.finalizedBy = [finalizer, "path"]
+ assert finalized.finalizedBy.getDependencies(finalized) == [finalizer, finalizerFromPath] as Set
+ }
+
+ @Test
public void testConfigure() {
Closure action1 = { Task t -> }
assertSame(task, task.configure {
@@ -239,7 +266,7 @@ class DefaultTaskTest extends AbstractTaskTest {
@Test
void canGetTemporaryDirectory() {
- File tmpDir = new File(project.buildDir, "tmp/taskname")
+ File tmpDir = new File(project.buildDir, "tmp/testTask")
assertFalse(tmpDir.exists())
assertThat(defaultTask.temporaryDir, equalTo(tmpDir))
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/DocumentationRegistryTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/DocumentationRegistryTest.groovy
index e5b6e70..bb69e62 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/DocumentationRegistryTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/DocumentationRegistryTest.groovy
@@ -23,53 +23,10 @@ import spock.lang.Specification
class DocumentationRegistryTest extends Specification {
@Rule TestNameTestDirectoryProvider tmpDir
- final GradleDistributionLocator locator = Mock()
final GradleVersion gradleVersion = GradleVersion.current()
- final DocumentationRegistry registry = new DocumentationRegistry(locator, gradleVersion)
-
-
- def "points users at the local user guide when target page is present in distribution"() {
- def distDir = tmpDir.createDir("home")
- distDir.createFile("docs/userguide/userguide.html")
- def daemonPage = distDir.createFile("docs/userguide/gradle_daemon.html")
-
- given:
- _ * locator.gradleHome >> distDir
-
- expect:
- registry.getDocumentationFor('gradle_daemon') == daemonPage.absolutePath
- }
-
- def "fails when local user guide is present in distribution but target page not found"() {
- def distDir = tmpDir.createDir("home")
- distDir.createFile("docs/userguide/userguide.html")
- def expectedPage = distDir.file("docs/userguide/gradle_daemon.html")
-
- given:
- _ * locator.gradleHome >> distDir
-
- when:
- registry.getDocumentationFor('gradle_daemon')
-
- then:
- IllegalArgumentException e = thrown()
- e.message == "User guide page '${expectedPage}' not found."
- }
-
- def "points users at the remote user guide when user guide not present in distribution"() {
- def distDir = tmpDir.createDir("home")
-
- given:
- _ * locator.gradleHome >> distDir
-
- expect:
- registry.getDocumentationFor('gradle_daemon') == "http://gradle.org/docs/${gradleVersion.version}/userguide/gradle_daemon.html"
- }
-
- def "points users at the remote user guide when no distribution"() {
- given:
- _ * locator.gradleHome >> null
+ final DocumentationRegistry registry = new DocumentationRegistry()
+ def "points users at the gradle docs web site"() {
expect:
registry.getDocumentationFor('gradle_daemon') == "http://gradle.org/docs/${gradleVersion.version}/userguide/gradle_daemon.html"
}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/ExtensibleDynamicObjectTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/ExtensibleDynamicObjectTest.java
index af3f768..85a7135 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/ExtensibleDynamicObjectTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/ExtensibleDynamicObjectTest.java
@@ -20,7 +20,7 @@ import groovy.lang.MissingMethodException;
import org.gradle.api.internal.project.AbstractProject;
import org.gradle.api.plugins.Convention;
import org.gradle.testfixtures.ProjectBuilder;
-import org.gradle.util.HelperUtil;
+import org.gradle.util.TestUtil;
import org.junit.Test;
import java.util.Map;
@@ -413,7 +413,7 @@ public class ExtensibleDynamicObjectTest {
@Test
public void canInvokeMethodDefinedByScriptObject() {
Bean bean = new Bean();
- Script script = HelperUtil.createScript("def scriptMethod(a, b) { \"script:$a.$b\" } ");
+ Script script = TestUtil.createScript("def scriptMethod(a, b) { \"script:$a.$b\" } ");
bean.extensibleDynamicObject.addObject(new BeanDynamicObject(script), ExtensibleDynamicObject.Location.BeforeConvention);
assertTrue(bean.hasMethod("scriptMethod", "a", "b"));
@@ -484,7 +484,7 @@ public class ExtensibleDynamicObjectTest {
@Test
public void canInvokeClosurePropertyAsAMethod() {
Bean bean = new Bean();
- bean.setProperty("someMethod", HelperUtil.toClosure("{ param -> param.toLowerCase() }"));
+ bean.setProperty("someMethod", TestUtil.toClosure("{ param -> param.toLowerCase() }"));
assertThat(bean.invokeMethod("someMethod", "Param"), equalTo((Object) "param"));
}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/GraphAggregatorTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/GraphAggregatorTest.groovy
deleted file mode 100644
index b956b28..0000000
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/GraphAggregatorTest.groovy
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal
-
-import spock.lang.Specification
-
-class GraphAggregatorTest extends Specification {
- private final DirectedGraph<String, String> graph = Mock()
- private final GraphAggregator aggregator = new GraphAggregator(graph)
-
- def groupsNodeWithTheEntryNodeItIsReachableFrom() {
- when:
- def result = aggregator.group(['a'], ['a', 'b'])
-
- then:
- 1 * graph.getNodeValues('a', !null, !null) >> { args -> args[2].add('b') }
- result.getNodes('a') == ['a', 'b'] as Set
- }
-
- def groupsNodeWithTheClosesEntryNodeItIsReachableFrom() {
- when:
- def result = aggregator.group(['a', 'b'], ['a', 'b', 'c'])
-
- then:
- 1 * graph.getNodeValues('a', !null, !null) >> { args -> args[2].add('b') }
- 1 * graph.getNodeValues('b', !null, !null) >> { args -> args[2].add('c') }
- result.getNodes('a') == ['a'] as Set
- result.getNodes('b') == ['b', 'c'] as Set
- }
-
- def groupsNodeWithMultipleEntryNodesWhenTheNodeHasMultipleClosesNodes() {
- when:
- def result = aggregator.group(['a', 'b'], ['a', 'b', 'c'])
-
- then:
- 1 * graph.getNodeValues('a', !null, !null) >> { args -> args[2].add('c') }
- 1 * graph.getNodeValues('b', !null, !null) >> { args -> args[2].add('c') }
- result.getNodes('a') == ['a', 'c'] as Set
- result.getNodes('b') == ['b', 'c'] as Set
- }
-
- def groupsNodesWhichAreNotReachableFromStartNodes() {
- when:
- def result = aggregator.group(['a', 'b'], ['a', 'b', 'c', 'd'])
-
- then:
- 1 * graph.getNodeValues('a', !null, !null) >> { args -> args[2].add('b') }
- 1 * graph.getNodeValues('c', !null, !null) >> { args -> args[2].add('d') }
- result.topLevelNodes == ['a', 'b', 'c'] as Set
- result.getNodes('c') == ['c', 'd'] as Set
- }
-}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/DefaultExcludeRuleContainerTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/DefaultExcludeRuleContainerTest.java
index 48d2981..1ea7fd2 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/DefaultExcludeRuleContainerTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/DefaultExcludeRuleContainerTest.java
@@ -25,9 +25,6 @@ import java.util.*;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertThat;
-/**
- * @author Hans Dockter
- */
public class DefaultExcludeRuleContainerTest {
@Test
public void testInit() {
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/ProjectBackedModuleTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/ProjectBackedModuleTest.groovy
index 89a8e3e..dcca9cb 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/ProjectBackedModuleTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/ProjectBackedModuleTest.groovy
@@ -16,14 +16,14 @@
package org.gradle.api.internal.artifacts
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import spock.lang.Specification
class ProjectBackedModuleTest extends Specification {
def "module exposes project properties"() {
given:
- def project = HelperUtil.createRootProject()
+ def project = TestUtil.createRootProject()
def module = new ProjectBackedModule(project)
expect:
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/dependencies/AbstractModuleDependencySpec.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/dependencies/AbstractModuleDependencySpec.groovy
index 653f467..e5a1bca 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/dependencies/AbstractModuleDependencySpec.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/dependencies/AbstractModuleDependencySpec.groovy
@@ -19,7 +19,7 @@ import org.gradle.api.artifacts.Dependency
import org.gradle.api.artifacts.DependencyArtifact
import org.gradle.api.artifacts.ModuleDependency
import org.gradle.api.internal.artifacts.DefaultExcludeRule
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import org.gradle.util.WrapUtil
import spock.lang.Specification
@@ -83,7 +83,7 @@ class AbstractModuleDependencySpec extends Specification {
}
private DependencyArtifact createAnonymousArtifact() {
- return new DefaultDependencyArtifact(HelperUtil.createUniqueId(), "type", "org", "classifier", "url")
+ return new DefaultDependencyArtifact(TestUtil.createUniqueId(), "type", "org", "classifier", "url")
}
public static void assertDeepCopy(ModuleDependency dependency, ModuleDependency copiedDependency) {
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/dependencies/AbstractModuleDependencyTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/dependencies/AbstractModuleDependencyTest.java
index 58d2472..118ea7b 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/dependencies/AbstractModuleDependencyTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/dependencies/AbstractModuleDependencyTest.java
@@ -20,7 +20,7 @@ import org.gradle.api.artifacts.DependencyArtifact;
import org.gradle.api.artifacts.ExcludeRule;
import org.gradle.api.artifacts.ModuleDependency;
import org.gradle.api.internal.artifacts.DefaultExcludeRule;
-import org.gradle.util.HelperUtil;
+import org.gradle.util.TestUtil;
import org.gradle.util.JUnit4GroovyMockery;
import org.gradle.util.WrapUtil;
import org.jmock.integration.junit4.JMock;
@@ -35,9 +35,6 @@ import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
-/**
- * @author Hans Dockter
- */
@RunWith(JMock.class)
abstract public class AbstractModuleDependencyTest {
//TODO SF rework the remaining coverage of this hierarchy in the spirit of AbstractModuleDependencySpec and DefaultProjectDependencyTest
@@ -85,7 +82,7 @@ abstract public class AbstractModuleDependencyTest {
}
private DependencyArtifact createAnonymousArtifact() {
- return new DefaultDependencyArtifact(HelperUtil.createUniqueId(), "type", "org", "classifier", "url");
+ return new DefaultDependencyArtifact(TestUtil.createUniqueId(), "type", "org", "classifier", "url");
}
@Test
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/dependencies/DefaultClientModuleTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/dependencies/DefaultClientModuleTest.java
index 6a3e98a..e99073c 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/dependencies/DefaultClientModuleTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/dependencies/DefaultClientModuleTest.java
@@ -23,9 +23,6 @@ import org.junit.Test;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertThat;
-/**
- * @author Hans Dockter
- */
public class DefaultClientModuleTest extends AbstractModuleDependencyTest {
private static final String TEST_GROUP = "org.gradle";
private static final String TEST_NAME = "gradle-core";
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/dependencies/DefaultDependencyArtifactTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/dependencies/DefaultDependencyArtifactTest.java
index e27779a..1194e84 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/dependencies/DefaultDependencyArtifactTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/dependencies/DefaultDependencyArtifactTest.java
@@ -16,12 +16,10 @@
package org.gradle.api.internal.artifacts.dependencies;
import org.gradle.api.artifacts.DependencyArtifact;
-import static org.junit.Assert.assertEquals;
import org.junit.Test;
-/**
- * @author Hans Dockter
- */
+import static org.junit.Assert.assertEquals;
+
public class DefaultDependencyArtifactTest {
@Test
public void testInit() {
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/dependencies/DefaultExternalModuleDependencyTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/dependencies/DefaultExternalModuleDependencyTest.java
index d1b657c..1019446 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/dependencies/DefaultExternalModuleDependencyTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/dependencies/DefaultExternalModuleDependencyTest.java
@@ -27,9 +27,6 @@ import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
-/**
- * @author Hans Dockter
- */
@RunWith(JMock.class)
public class DefaultExternalModuleDependencyTest extends AbstractModuleDependencyTest {
private static final String TEST_GROUP = "org.gradle";
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/dependencies/DefaultProjectDependencyTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/dependencies/DefaultProjectDependencyTest.groovy
index 31bedb9..bc1b489 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/dependencies/DefaultProjectDependencyTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/dependencies/DefaultProjectDependencyTest.groovy
@@ -1,5 +1,5 @@
/*
- * Copyright 2009 the original author or authors.
+ * Copyright 2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,7 +22,7 @@ import org.gradle.api.internal.artifacts.DependencyResolveContext
import org.gradle.api.internal.project.ProjectInternal
import org.gradle.api.internal.tasks.TaskDependencyResolveContext
import org.gradle.initialization.ProjectAccessListener
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import spock.lang.Specification
import static org.gradle.api.internal.artifacts.dependencies.AbstractModuleDependencySpec.assertDeepCopy
@@ -31,7 +31,7 @@ import static org.junit.Assert.assertThat
class DefaultProjectDependencyTest extends Specification {
- ProjectInternal project = HelperUtil.createRootProject()
+ ProjectInternal project = TestUtil.createRootProject()
ProjectAccessListener listener = Mock()
private projectDependency = new DefaultProjectDependency(project, null, false)
@@ -62,8 +62,8 @@ class DefaultProjectDependencyTest extends Specification {
void "transitive resolution resolves all dependencies"() {
def context = Mock(DependencyResolveContext)
- def superConf = project.configurations.add("superConf")
- def conf = project.configurations.add("conf")
+ def superConf = project.configurations.create("superConf")
+ def conf = project.configurations.create("conf")
conf.extendsFrom(superConf)
def dep1 = Mock(ProjectDependency)
@@ -110,7 +110,7 @@ class DefaultProjectDependencyTest extends Specification {
void "is Buildable"() {
def context = Mock(TaskDependencyResolveContext)
- def conf = project.configurations.add('conf')
+ def conf = project.configurations.create('conf')
def listener = Mock(ProjectAccessListener)
projectDependency = new DefaultProjectDependency(project, 'conf', listener, true)
@@ -126,7 +126,7 @@ class DefaultProjectDependencyTest extends Specification {
void "does not build project dependencies if configured so"() {
def context = Mock(TaskDependencyResolveContext)
- project.configurations.add('conf')
+ project.configurations.create('conf')
projectDependency = new DefaultProjectDependency(project, 'conf', listener, false)
when:
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/dsl/dependencies/DefaultDependencyHandlerTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/dsl/dependencies/DefaultDependencyHandlerTest.groovy
index c58f082..534f9d4 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/dsl/dependencies/DefaultDependencyHandlerTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/dsl/dependencies/DefaultDependencyHandlerTest.groovy
@@ -15,12 +15,10 @@
*/
package org.gradle.api.internal.artifacts.dsl.dependencies
-import spock.lang.Specification
import org.gradle.api.artifacts.*
+import org.gradle.api.artifacts.dsl.ComponentMetadataHandler
+import spock.lang.Specification
-/**
- * @author Hans Dockter
- */
class DefaultDependencyHandlerTest extends Specification {
private static final String TEST_CONF_NAME = "someConf"
private ConfigurationContainer configurationContainer = Mock()
@@ -29,7 +27,7 @@ class DefaultDependencyHandlerTest extends Specification {
private ProjectFinder projectFinder = Mock()
private DependencySet dependencySet = Mock()
- private DefaultDependencyHandler dependencyHandler = new DefaultDependencyHandler(configurationContainer, dependencyFactory, projectFinder)
+ private DefaultDependencyHandler dependencyHandler = new DefaultDependencyHandler(configurationContainer, dependencyFactory, projectFinder, Stub(ComponentMetadataHandler))
void setup() {
_ * configurationContainer.findByName(TEST_CONF_NAME) >> configuration
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/dsl/dependencies/ModuleFactoryDelegateTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/dsl/dependencies/ModuleFactoryDelegateTest.java
index 27fe2f6..e6b4772 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/dsl/dependencies/ModuleFactoryDelegateTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/dsl/dependencies/ModuleFactoryDelegateTest.java
@@ -20,7 +20,7 @@ import org.gradle.api.artifacts.ClientModule;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.artifacts.ModuleDependency;
import org.gradle.api.internal.artifacts.dependencies.DefaultClientModule;
-import org.gradle.util.HelperUtil;
+import org.gradle.util.TestUtil;
import org.gradle.util.WrapUtil;
import org.hamcrest.Matchers;
import org.jmock.Expectations;
@@ -29,9 +29,6 @@ import org.junit.Test;
import static org.junit.Assert.assertThat;
-/**
- * @author Hans Dockter
- */
public class ModuleFactoryDelegateTest {
private JUnit4Mockery context = new JUnit4Mockery();
@@ -52,7 +49,7 @@ public class ModuleFactoryDelegateTest {
@Test
public void dependencyWithClosure() {
final String dependencyNotation = "someNotation";
- final Closure configureClosure = HelperUtil.toClosure("{}");
+ final Closure configureClosure = TestUtil.toClosure("{}");
final ModuleDependency dependencyDummy = context.mock(ModuleDependency.class);
letFactoryStubReturnDependency(dependencyNotation, dependencyDummy);
moduleFactoryDelegate.dependency(dependencyNotation, configureClosure);
@@ -81,7 +78,7 @@ public class ModuleFactoryDelegateTest {
@Test
public void module() {
final String clientModuleNotation = "someNotation";
- final Closure configureClosure = HelperUtil.toClosure("{}");
+ final Closure configureClosure = TestUtil.toClosure("{}");
final ClientModule clientModuleDummy = context.mock(ClientModule.class);
context.checking(new Expectations() {{
allowing(dependencyFactoryStub).createModule(clientModuleNotation, configureClosure);
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/publish/AbstractPublishArtifactTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/publish/AbstractPublishArtifactTest.java
index b29f542..2a91119 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/publish/AbstractPublishArtifactTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/publish/AbstractPublishArtifactTest.java
@@ -21,14 +21,12 @@ import org.gradle.api.artifacts.PublishArtifact;
import org.gradle.util.JUnit4GroovyMockery;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.jmock.lib.legacy.ClassImposteriser;
-import static org.junit.Assert.assertEquals;
import java.io.File;
import java.util.Date;
-/**
- * @author Hans Dockter
- */
+import static org.junit.Assert.assertEquals;
+
public abstract class AbstractPublishArtifactTest {
private static final File TEST_FILE = new File("artifactFile");
private static final String TEST_NAME = "myfile-1";
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/publish/ArchivePublishArtifactTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/publish/ArchivePublishArtifactTest.groovy
index 4713781..b873b6d 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/publish/ArchivePublishArtifactTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/publish/ArchivePublishArtifactTest.groovy
@@ -26,9 +26,6 @@ import static org.hamcrest.Matchers.equalTo
import static org.hamcrest.Matchers.sameInstance
import static org.junit.Assert.assertThat
-/**
- * @author Hans Dockter
- */
public class ArchivePublishArtifactTest extends AbstractPublishArtifactTest {
private AbstractArchiveTask archiveTask = context.mock(AbstractArchiveTask.class)
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/publish/DefaultPublishArtifactTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/publish/DefaultPublishArtifactTest.java
index e1a857f..681f65a 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/publish/DefaultPublishArtifactTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/publish/DefaultPublishArtifactTest.java
@@ -28,9 +28,6 @@ import static org.gradle.util.WrapUtil.toSet;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
-/**
- * @author Hans Dockter
- */
@RunWith(JMock.class)
public class DefaultPublishArtifactTest extends AbstractPublishArtifactTest {
protected PublishArtifact createPublishArtifact(String classifier) {
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/repositories/ArtifactRepositoryChangingNameAfterContainerInclusionDeprecationTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/repositories/ArtifactRepositoryChangingNameAfterContainerInclusionDeprecationTest.groovy
index 428c62e..1e09674 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/repositories/ArtifactRepositoryChangingNameAfterContainerInclusionDeprecationTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/repositories/ArtifactRepositoryChangingNameAfterContainerInclusionDeprecationTest.groovy
@@ -21,26 +21,23 @@ import org.gradle.api.artifacts.repositories.ArtifactRepository
import org.gradle.logging.ConfigureLogging
import org.gradle.logging.TestAppender
import org.gradle.util.DeprecationLogger
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
+import org.junit.Rule
import spock.lang.Specification
import spock.lang.Unroll
class ArtifactRepositoryChangingNameAfterContainerInclusionDeprecationTest extends Specification {
TestAppender appender = new TestAppender()
- ConfigureLogging logging
+ @Rule ConfigureLogging logging = new ConfigureLogging(appender)
Project project
def setup() {
- project = HelperUtil.createRootProject()
+ project = TestUtil.createRootProject()
DeprecationLogger.reset()
- appender = new TestAppender()
- logging = new ConfigureLogging(appender)
- logging.attachAppender()
}
def cleanup() {
- logging.detachAppender()
DeprecationLogger.reset()
}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/version/LatestVersionSemanticComparatorSpec.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/version/LatestVersionSemanticComparatorSpec.groovy
deleted file mode 100644
index b363c9d..0000000
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/version/LatestVersionSemanticComparatorSpec.groovy
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.artifacts.version
-
-import spock.lang.Specification
-
-/**
- * by Szczepan Faber, created at: 10/9/12
- */
-class LatestVersionSemanticComparatorSpec extends Specification {
-
- private comparator = new LatestVersionSemanticComparator()
-
- def "compares versions"() {
- expect:
- comparator.compare(a, b) < 0
- comparator.compare(b, a) > 0
- comparator.compare(a, a) == 0
- comparator.compare(b, b) == 0
-
- where:
- a | b
- '1.0' | '2.0'
- '1.2' | '1.10'
- '1.0' | '1.0.1'
- '1.0-rc-1' | '1.0-rc-2'
- '1.0-alpha' | '1.0'
- '1.0-alpha' | '1.0-beta'
- '1.0-1' | '1.0-2'
- '1.0.a' | '1.0.b'
- '1.0.alpha' | '1.0.b'
- }
-
- def "equal"() {
- expect:
- comparator.compare(a, b) == 0
- comparator.compare(b, a) == 0
-
- //some of the comparison are not working hence commented out.
- //consider updating the implementation when we port the ivy comparison mechanism.
- where:
- a | b
- '1.0' | '1.0'
- '5.0' | '5.0'
-// '1.0.0' | '1.0'
-// '1.0.0' | '1'
-// '1.0-alpha' | '1.0-ALPHA'
-// '1.0.alpha' | '1.0-alpha'
- }
-
- def "not equal"() {
- expect:
- comparator.compare(a, b) != 0
- comparator.compare(b, a) != 0
-
- where:
- a | b
- '1.0' | ''
- '1.0' | null
- '1.0' | 'hey joe'
- }
-}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/CacheBackedFileSnapshotRepositoryTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/CacheBackedFileSnapshotRepositoryTest.groovy
deleted file mode 100644
index 94a6498..0000000
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/CacheBackedFileSnapshotRepositoryTest.groovy
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.changedetection
-
-import org.gradle.cache.PersistentIndexedCache
-import spock.lang.Specification
-
-class CacheBackedFileSnapshotRepositoryTest extends Specification {
- final TaskArtifactStateCacheAccess cacheAccess = Mock()
- final PersistentIndexedCache<Object, Object> indexedCache = Mock()
- FileSnapshotRepository repository
-
- def setup() {
- 1 * cacheAccess.createCache("fileSnapshots", Object, Object) >> indexedCache
- repository = new CacheBackedFileSnapshotRepository(cacheAccess)
- }
-
- def "assigns an id when a snapshot is added"() {
- FileCollectionSnapshot snapshot = Mock()
-
- when:
- def id = repository.add(snapshot)
-
- then:
- id == 4
- 1 * indexedCache.get("nextId") >> (4 as Long)
- 1 * indexedCache.put("nextId", 5)
- 1 * indexedCache.put(4, snapshot)
- 0 * _._
- }
-
- def "can fetch a snapshot by id"() {
- FileCollectionSnapshot snapshot = Mock()
-
- when:
- def result = repository.get(4)
-
- then:
- result == snapshot
- 1 * indexedCache.get(4) >> snapshot
- 0 * _._
- }
-
- def "can delete a snapshot by id"() {
- when:
- repository.remove(4)
-
- then:
- 1 * indexedCache.remove(4)
- 0 * _._
- }
-}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/CachingHasherTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/CachingHasherTest.java
deleted file mode 100644
index 4082439..0000000
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/CachingHasherTest.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.changedetection;
-
-import org.gradle.cache.PersistentIndexedCache;
-import org.gradle.messaging.serialize.Serializer;
-import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider;
-import org.jmock.Expectations;
-import org.jmock.integration.junit4.JMock;
-import org.jmock.integration.junit4.JUnit4Mockery;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.io.File;
-
-import static org.gradle.util.Matchers.reflectionEquals;
-import static org.hamcrest.Matchers.*;
-import static org.junit.Assert.assertThat;
-
- at RunWith(JMock.class)
-public class CachingHasherTest {
- @Rule
- TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider();
- private final JUnit4Mockery context = new JUnit4Mockery();
- private final Hasher delegate = context.mock(Hasher.class);
- private final PersistentIndexedCache<File, CachingHasher.FileInfo> cache = context.mock(
- PersistentIndexedCache.class);
- private final TaskArtifactStateCacheAccess cacheAccess = context.mock(TaskArtifactStateCacheAccess.class);
- private final byte[] hash = "hash".getBytes();
- private final File file = tmpDir.createFile("testfile").write("content");
- private CachingHasher hasher;
-
- @Before
- public void setup() {
- context.checking(new Expectations(){{
- one(cacheAccess).createCache(with(equalTo("fileHashes")), with(equalTo(File.class)), with(notNullValue(Class.class)), with(notNullValue(Serializer.class)));
- will(returnValue(cache));
- }});
- hasher = new CachingHasher(delegate, cacheAccess);
- }
-
- @Test
- public void hashesFileWhenHashNotCached() {
- context.checking(new Expectations() {{
- one(cache).get(file);
- will(returnValue(null));
- one(delegate).hash(file);
- will(returnValue(hash));
- one(cache).put(with(equalTo(file)), with(reflectionEquals(new CachingHasher.FileInfo(hash, file.length(),
- file.lastModified()))));
- }});
-
- assertThat(hasher.hash(file), sameInstance(hash));
- }
-
- @Test
- public void hashesFileWhenLengthHasChanged() {
- context.checking(new Expectations() {{
- one(cache).get(file);
- will(returnValue(new CachingHasher.FileInfo(hash, 1078, file.lastModified())));
- one(delegate).hash(file);
- will(returnValue(hash));
- one(cache).put(with(equalTo(file)), with(reflectionEquals(new CachingHasher.FileInfo(hash, file.length(),
- file.lastModified()))));
- }});
-
- assertThat(hasher.hash(file), sameInstance(hash));
- }
-
- @Test
- public void hashesFileWhenTimestampHasChanged() {
- context.checking(new Expectations() {{
- one(cache).get(file);
- will(returnValue(new CachingHasher.FileInfo(hash, file.length(), 12)));
- one(delegate).hash(file);
- will(returnValue(hash));
- one(cache).put(with(equalTo(file)), with(reflectionEquals(new CachingHasher.FileInfo(hash, file.length(),
- file.lastModified()))));
- }});
-
- assertThat(hasher.hash(file), sameInstance(hash));
- }
-
- @Test
- public void doesNotHashFileWhenTimestampAndLengthHaveNotChanged() {
- context.checking(new Expectations() {{
- one(cache).get(file);
- will(returnValue(new CachingHasher.FileInfo(hash, file.length(), file.lastModified())));
- }});
-
- assertThat(hasher.hash(file), sameInstance(hash));
- }
-}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/CompositeUpToDateRuleTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/CompositeUpToDateRuleTest.groovy
deleted file mode 100644
index ef36edf..0000000
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/CompositeUpToDateRuleTest.groovy
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.changedetection
-
-import spock.lang.Specification
-import org.gradle.api.internal.TaskInternal
-
-class CompositeUpToDateRuleTest extends Specification {
- final UpToDateRule rule1 = Mock()
- final UpToDateRule rule2 = Mock()
- final UpToDateRule.TaskUpToDateState state1 = Mock()
- final UpToDateRule.TaskUpToDateState state2 = Mock()
- final TaskInternal task = Mock()
- final TaskExecution previous = Mock()
- final TaskExecution current = Mock()
- final CompositeUpToDateRule rule = new CompositeUpToDateRule(rule1, rule2)
-
- def delegatesToEachRuleInOrder() {
- when:
- def state = rule.create(task, previous, current)
-
- then:
- 1 * rule1.create(task, previous, current) >> state1
- 1 * rule2.create(task, previous, current) >> state2
-
- when:
- state.checkUpToDate([])
-
- then:
- 1 * state1.checkUpToDate([])
- 1 * state2.checkUpToDate([])
-
- when:
- state.snapshotAfterTask()
-
- then:
- 1 * state1.snapshotAfterTask()
- 1 * state2.snapshotAfterTask()
- }
-
- def checkUpToDateStopsAtFirstRuleWhichMarksTaskOutOfDate() {
- when:
- def state = rule.create(task, previous, current)
-
- then:
- 1 * rule1.create(task, previous, current) >> state1
- 1 * rule2.create(task, previous, current) >> state2
-
- when:
- state.checkUpToDate([])
-
- then:
- 1 * state1.checkUpToDate([]) >> { args -> args[0] << 'out-of-date' }
- 0 * state2.checkUpToDate(_)
- }
-}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/DefaultFileSnapshotterTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/DefaultFileSnapshotterTest.groovy
deleted file mode 100755
index 961a356..0000000
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/DefaultFileSnapshotterTest.groovy
+++ /dev/null
@@ -1,330 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.changedetection
-
-import org.gradle.api.file.FileCollection
-import org.gradle.api.file.FileTree
-import org.gradle.test.fixtures.file.TestFile
-import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
-import org.gradle.util.ChangeListener
-import org.gradle.util.JUnit4GroovyMockery
-import org.jmock.integration.junit4.JMock
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-
-import static org.hamcrest.Matchers.equalTo
-import static org.hamcrest.Matchers.notNullValue
-import static org.junit.Assert.assertThat
-
- at RunWith(JMock.class)
-public class DefaultFileSnapshotterTest {
- private final JUnit4GroovyMockery context = new JUnit4GroovyMockery()
- private final Hasher hasher = new DefaultHasher()
- private int counter
- private ChangeListener listener = context.mock(ChangeListener.class)
- private final DefaultFileSnapshotter snapshotter = new DefaultFileSnapshotter(hasher)
- @Rule
- public final TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider()
-
- @Test
- public void getFilesReturnsOnlyTheFilesWhichExisted() {
- TestFile file = tmpDir.createFile('file1')
- TestFile dir = tmpDir.createDir('file2')
- TestFile noExist = tmpDir.file('file3')
-
- FileCollectionSnapshot snapshot = snapshotter.snapshot(files(file, dir, noExist))
-
- assertThat(snapshot.files.files as List, equalTo([file]))
- }
-
- @Test
- public void notifiesListenerWhenFileAdded() {
- TestFile file1 = tmpDir.createFile('file1')
- TestFile file2 = tmpDir.createFile('file2')
-
- FileCollectionSnapshot snapshot = snapshotter.snapshot(files(file1))
-
- context.checking {
- one(listener).added(file2)
- }
- snapshotter.snapshot(files(file1, file2)).changesSince(snapshot, listener)
- }
-
- @Test
- public void notifiesListenerWhenFileRemoved() {
- TestFile file1 = tmpDir.createFile('file1')
- TestFile file2 = tmpDir.createFile('file2')
-
- FileCollectionSnapshot snapshot = snapshotter.snapshot(files(file1, file2))
-
- context.checking {
- one(listener).removed(file2)
- }
- snapshotter.snapshot(files(file1)).changesSince(snapshot, listener)
- }
-
- @Test
- public void fileHasNotChangedWhenTypeAndHashHaveNotChanged() {
- TestFile file = tmpDir.createFile('file')
-
- FileCollectionSnapshot snapshot = snapshotter.snapshot(files(file))
- assertThat(snapshot, notNullValue())
-
- snapshotter.snapshot(files(file)).changesSince(snapshot, listener)
- }
-
- @Test
- public void fileHasChangedWhenTypeHasChanged() {
- TestFile file = tmpDir.createFile('file')
-
- FileCollectionSnapshot snapshot = snapshotter.snapshot(files(file))
-
- file.delete()
- file.createDir()
-
- context.checking {
- one(listener).changed(file)
- }
- snapshotter.snapshot(files(file)).changesSince(snapshot, listener)
- }
-
- @Test
- public void fileHasChangedWhenHashHasChanged() {
- TestFile file = tmpDir.createFile('file')
-
- FileCollectionSnapshot snapshot = snapshotter.snapshot(files(file))
-
- file.write('new content')
-
- context.checking {
- one(listener).changed(file)
- }
- snapshotter.snapshot(files(file)).changesSince(snapshot, listener)
- }
-
- @Test
- public void directoryHasNotChangedWhenTypeHasNotChanged() {
- TestFile dir = tmpDir.createDir('dir')
-
- FileCollectionSnapshot snapshot = snapshotter.snapshot(files(dir))
-
- snapshotter.snapshot(files(dir)).changesSince(snapshot, listener)
- }
-
- @Test
- public void directoryHasChangedWhenTypeHasChanged() {
- TestFile dir = tmpDir.createDir('dir')
-
- FileCollectionSnapshot snapshot = snapshotter.snapshot(files(dir))
-
- dir.deleteDir()
- dir.createFile()
-
- context.checking {
- one(listener).changed(dir)
- }
- snapshotter.snapshot(files(dir)).changesSince(snapshot, listener)
- }
-
- @Test
- public void nonExistentFileUnchangedWhenTypeHasNotChanged() {
- TestFile file = tmpDir.file('unknown')
-
- FileCollectionSnapshot snapshot = snapshotter.snapshot(files(file))
-
- snapshotter.snapshot(files(file)).changesSince(snapshot, listener)
- }
-
- @Test
- public void nonExistentFileIsChangedWhenTypeHasChanged() {
- TestFile file = tmpDir.file('unknown')
-
- FileCollectionSnapshot snapshot = snapshotter.snapshot(files(file))
-
- file.createFile()
-
- context.checking {
- one(listener).changed(file)
- }
- snapshotter.snapshot(files(file)).changesSince(snapshot, listener)
- }
-
- @Test
- public void ignoresDuplicatesInFileCollection() {
- TestFile file1 = tmpDir.createFile('file')
- TestFile file2 = tmpDir.createFile('file')
-
- FileCollectionSnapshot snapshot = snapshotter.snapshot(files(file1, file2))
-
- snapshotter.snapshot(files(file1)).changesSince(snapshot, listener)
- }
-
- @Test
- public void canCreateEmptySnapshot() {
- TestFile file = tmpDir.createFile('file')
- FileCollectionSnapshot snapshot = snapshotter.emptySnapshot()
-
- FileCollectionSnapshot newSnapshot = snapshotter.snapshot(files(file))
-
- context.checking {
- one(listener).added(file)
- }
-
- newSnapshot.changesSince(snapshot, listener)
- }
-
- @Test
- public void diffAddsAddedFilesToSnapshot() {
- TestFile file = tmpDir.createFile('file')
- ChangeListener<FileCollectionSnapshot.Merge> mergeListener = context.mock(ChangeListener.class)
-
- FileCollectionSnapshot original = snapshotter.emptySnapshot()
- FileCollectionSnapshot modified = snapshotter.snapshot(files(file))
-
- context.checking {
- one(mergeListener).added(withParam(notNullValue()))
- }
-
- FileCollectionSnapshot target = modified.changesSince(original).applyTo(snapshotter.emptySnapshot(), mergeListener)
-
- context.checking {
- one(listener).added(file)
- }
- target.changesSince(original, listener)
- }
-
- @Test
- public void canIgnoreAddedFileInDiff() {
- TestFile file = tmpDir.createFile('file')
- ChangeListener<FileCollectionSnapshot.Merge> mergeListener = context.mock(ChangeListener.class)
-
- FileCollectionSnapshot original = snapshotter.emptySnapshot()
- FileCollectionSnapshot modified = snapshotter.snapshot(files(file))
-
- context.checking {
- one(mergeListener).added(withParam(notNullValue()))
- will {merge -> merge.ignore()}
- }
-
- FileCollectionSnapshot target = modified.changesSince(original).applyTo(snapshotter.emptySnapshot(), mergeListener)
-
- target.changesSince(original, listener)
- }
-
- @Test
- public void diffAddsChangedFilesToSnapshot() {
- TestFile file = tmpDir.createFile('file')
- ChangeListener<FileCollectionSnapshot.Merge> mergeListener = context.mock(ChangeListener.class)
-
- FileCollectionSnapshot original = snapshotter.snapshot(files(file))
- file.write('new content')
- FileCollectionSnapshot modified = snapshotter.snapshot(files(file))
-
- context.checking {
- one(mergeListener).changed(withParam(notNullValue()))
- }
-
- FileCollectionSnapshot target = modified.changesSince(original).applyTo(snapshotter.emptySnapshot(), mergeListener)
-
- context.checking {
- one(listener).changed(file)
- }
- target.changesSince(original, listener)
- }
-
- @Test
- public void canIgnoreChangedFileInDiff() {
- TestFile file = tmpDir.createFile('file')
- ChangeListener<FileCollectionSnapshot.Merge> mergeListener = context.mock(ChangeListener.class)
-
- FileCollectionSnapshot original = snapshotter.snapshot(files(file))
- FileCollectionSnapshot target = snapshotter.snapshot(files(file))
- file.write('new content')
- FileCollectionSnapshot modified = snapshotter.snapshot(files(file))
-
- context.checking {
- one(mergeListener).changed(withParam(notNullValue()))
- will {merge -> merge.ignore()}
- }
-
- target = modified.changesSince(original).applyTo(target, mergeListener)
-
- target.changesSince(original, listener)
- }
-
- @Test
- public void diffRemovesDeletedFilesFromSnapshot() {
- TestFile file = tmpDir.createFile('file')
- ChangeListener<FileCollectionSnapshot.Merge> mergeListener = context.mock(ChangeListener.class)
-
- FileCollectionSnapshot original = snapshotter.snapshot(files(file))
- FileCollectionSnapshot modified = snapshotter.emptySnapshot()
-
- context.checking {
- one(mergeListener).removed(withParam(notNullValue()))
- }
-
- FileCollectionSnapshot target = modified.changesSince(original).applyTo(snapshotter.snapshot(files(file)), mergeListener)
-
- context.checking {
- one(listener).removed(file)
- }
- target.changesSince(original, listener)
- }
-
- @Test
- public void canIgnoreRemovedFileInDiff() {
- TestFile file = tmpDir.createFile('file')
- ChangeListener<FileCollectionSnapshot.Merge> mergeListener = context.mock(ChangeListener.class)
-
- FileCollectionSnapshot original = snapshotter.snapshot(files(file))
- FileCollectionSnapshot modified = snapshotter.emptySnapshot()
-
- context.checking {
- one(mergeListener).removed(withParam(notNullValue()))
- will{merge -> merge.ignore()}
- }
-
- FileCollectionSnapshot target = modified.changesSince(original).applyTo(snapshotter.snapshot(files(file)), mergeListener)
-
- target.changesSince(original, listener)
- }
-
- @Test
- public void diffIgnoresUnchangedFilesInSnapshot() {
- TestFile file = tmpDir.createFile('file')
- ChangeListener<FileCollectionSnapshot.Merge> mergeListener = context.mock(ChangeListener.class)
-
- FileCollectionSnapshot original = snapshotter.snapshot(files(file))
- FileCollectionSnapshot modified = snapshotter.snapshot(files(file))
- FileCollectionSnapshot target = modified.changesSince(original).applyTo(snapshotter.emptySnapshot(), mergeListener)
-
- target.changesSince(snapshotter.emptySnapshot(), listener)
- }
-
- private FileCollection files(File... files) {
- FileTree collection = context.mock(FileTree.class)
- context.checking {
- allowing(collection).getAsFileTree()
- will(returnValue(collection))
- allowing(collection).iterator()
- will(returnIterator(files as List))
- }
- return collection
- }
-
-}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/DefaultTaskArtifactStateCacheAccessTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/DefaultTaskArtifactStateCacheAccessTest.groovy
deleted file mode 100644
index afbbad1..0000000
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/DefaultTaskArtifactStateCacheAccessTest.groovy
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.changedetection
-
-import org.gradle.cache.CacheRepository
-import spock.lang.Specification
-import org.gradle.api.internal.GradleInternal
-import org.gradle.cache.DirectoryCacheBuilder
-import org.gradle.cache.PersistentCache
-import org.gradle.cache.PersistentIndexedCache
-
-class DefaultTaskArtifactStateCacheAccessTest extends Specification {
- final GradleInternal gradle = Mock()
- final CacheRepository cacheRepository = Mock()
- final DefaultTaskArtifactStateCacheAccess cacheAccess = new DefaultTaskArtifactStateCacheAccess(gradle, cacheRepository)
-
- def "opens backing cache on first use"() {
- DirectoryCacheBuilder cacheBuilder = Mock()
- PersistentCache backingCache = Mock()
- PersistentIndexedCache<String, Integer> backingIndexedCache = Mock()
-
- when:
- def indexedCache = cacheAccess.createCache("some-cache", String, Integer)
-
- then:
- 0 * _._
-
- when:
- indexedCache.get("key")
-
- then:
- 1 * cacheRepository.cache("taskArtifacts") >> cacheBuilder
- 1 * cacheBuilder.open() >> backingCache
- _ * cacheBuilder._ >> cacheBuilder
- _ * backingCache.baseDir >> new File("baseDir")
- 1 * backingCache.createCache(new File("baseDir/some-cache.bin"), String, Integer) >> backingIndexedCache
- 1 * backingIndexedCache.get("key")
- 0 * _._
- }
-}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/DefaultTaskArtifactStateRepositoryTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/DefaultTaskArtifactStateRepositoryTest.java
deleted file mode 100644
index c25ebbc..0000000
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/DefaultTaskArtifactStateRepositoryTest.java
+++ /dev/null
@@ -1,606 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.changedetection;
-
-import org.gradle.CacheUsage;
-import org.gradle.api.DefaultTask;
-import org.gradle.api.internal.TaskInternal;
-import org.gradle.api.internal.project.ProjectInternal;
-import org.gradle.api.invocation.Gradle;
-import org.gradle.cache.CacheRepository;
-import org.gradle.cache.internal.DefaultCacheRepository;
-import org.gradle.internal.id.RandomLongIdGenerator;
-import org.gradle.test.fixtures.file.TestFile;
-import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider;
-import org.gradle.testfixtures.internal.InMemoryCacheFactory;
-import org.gradle.util.HelperUtil;
-import org.hamcrest.Matcher;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-
-import java.io.File;
-import java.util.*;
-
-import static org.gradle.util.Matchers.isEmpty;
-import static org.gradle.util.WrapUtil.*;
-import static org.hamcrest.Matchers.*;
-import static org.junit.Assert.*;
-
-public class DefaultTaskArtifactStateRepositoryTest {
- @Rule
- public TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider();
- private final ProjectInternal project = HelperUtil.createRootProject();
- private final Gradle gradle = project.getGradle();
- private final TestFile outputFile = tmpDir.file("output-file");
- private final TestFile outputDir = tmpDir.file("output-dir");
- private final TestFile outputDirFile = outputDir.file("some-file");
- private final TestFile outputDirFile2 = outputDir.file("some-file-2");
- private final TestFile emptyOutputDir = tmpDir.file("empty-output-dir");
- private final TestFile missingOutputFile = tmpDir.file("missing-output-file");
- private final TestFile inputFile = tmpDir.createFile("input-file");
- private final TestFile inputDir = tmpDir.createDir("input-dir");
- private final TestFile inputDirFile = inputDir.file("input-file2").createFile();
- private final TestFile missingInputFile = tmpDir.file("missing-input-file");
- private final Set<TestFile> inputFiles = toSet(inputFile, inputDir, missingInputFile);
- private final Set<TestFile> outputFiles = toSet(outputFile, outputDir, emptyOutputDir, missingOutputFile);
- private final Set<TestFile> createFiles = toSet(outputFile, outputDirFile, outputDirFile2);
- private DefaultTaskArtifactStateRepository repository;
-
- @Before
- public void setup() {
- CacheRepository cacheRepository = new DefaultCacheRepository(tmpDir.createDir("user-home"), null, CacheUsage.ON, new InMemoryCacheFactory());
- TaskArtifactStateCacheAccess cacheAccess = new DefaultTaskArtifactStateCacheAccess(gradle, cacheRepository);
- FileSnapshotter inputFilesSnapshotter = new DefaultFileSnapshotter(new DefaultHasher());
- FileSnapshotter outputFilesSnapshotter = new OutputFilesSnapshotter(inputFilesSnapshotter, new RandomLongIdGenerator(), cacheAccess);
- TaskHistoryRepository taskHistoryRepository = new CacheBackedTaskHistoryRepository(cacheAccess, new CacheBackedFileSnapshotRepository(cacheAccess));
- repository = new DefaultTaskArtifactStateRepository(taskHistoryRepository, inputFilesSnapshotter, outputFilesSnapshotter);
- }
-
- @Test
- public void artifactsAreNotUpToDateWhenCacheIsEmpty() {
- TaskArtifactState state = repository.getStateFor(task());
- assertNotNull(state);
- assertFalse(state.isUpToDate());
- }
-
- @Test
- public void artifactsAreNotUpToDateWhenAnyOutputFileNoLongerExists() {
- execute();
-
- outputFile.delete();
-
- TaskArtifactState state = repository.getStateFor(task());
- assertFalse(state.isUpToDate());
- }
-
- @Test
- public void artifactsAreNotUpToDateWhenAnyFileInOutputDirNoLongerExists() {
- execute();
-
- outputDirFile.delete();
-
- TaskArtifactState state = repository.getStateFor(task());
- assertFalse(state.isUpToDate());
- }
-
- @Test
- public void artifactsAreNotUpToDateWhenAnyOutputFileHasChangedType() {
- execute();
-
- outputFile.delete();
- outputFile.createDir();
-
- TaskArtifactState state = repository.getStateFor(task());
- assertFalse(state.isUpToDate());
- }
-
- @Test
- public void artifactsAreNotUpToDateWhenAnyFileInOutputDirHasChangedType() {
- execute();
-
- outputDirFile.delete();
- outputDirFile.createDir();
-
- TaskArtifactState state = repository.getStateFor(task());
- assertFalse(state.isUpToDate());
- }
-
- @Test
- public void artifactsAreNotUpToDateWhenAnyOutputFileHasChangedHash() {
- execute();
-
- outputFile.write("new content");
-
- TaskArtifactState state = repository.getStateFor(task());
- assertFalse(state.isUpToDate());
- }
-
- @Test
- public void artifactsAreNotUpToDateWhenAnyFileInOutputDirHasChangedHash() {
- execute();
-
- outputDirFile.write("new content");
-
- TaskArtifactState state = repository.getStateFor(task());
- assertFalse(state.isUpToDate());
- }
-
- @Test
- public void artifactsAreNotUpToDateWhenAnyOutputFilesAddedToSet() {
- execute();
-
- TaskInternal task = builder().withOutputFiles(outputFile, outputDir, tmpDir.createFile("output-file-2"), emptyOutputDir, missingOutputFile).task();
-
- TaskArtifactState state = repository.getStateFor(task);
- assertFalse(state.isUpToDate());
- }
-
- @Test
- public void artifactsAreNotUpToDateWhenAnyOutputFilesRemovedFromSet() {
- execute();
-
- TaskInternal task = builder().withOutputFiles(outputFile, emptyOutputDir, missingOutputFile).task();
-
- TaskArtifactState state = repository.getStateFor(task);
- assertFalse(state.isUpToDate());
- }
-
- @Test
- public void artifactsAreNotUpToDateWhenTaskWithDifferentTypeGeneratedAnyOutputFiles() {
- TaskInternal task1 = builder().withOutputFiles(outputFile).task();
- TaskInternal task2 = builder().withType(TaskSubType.class).withOutputFiles(outputFile).task();
-
- execute(task1, task2);
-
- TaskArtifactState state = repository.getStateFor(task1);
- assertFalse(state.isUpToDate());
- }
-
- @Test
- public void artifactsAreNotUpToDateWhenAnyInputFilesAddedToSet() {
- execute();
-
- TaskInternal task = builder().withInputFiles(inputFile, inputDir, tmpDir.createFile("other-input"), missingInputFile).task();
- TaskArtifactState state = repository.getStateFor(task);
- assertFalse(state.isUpToDate());
- }
-
- @Test
- public void artifactsAreNotUpToDateWhenAnyInputFilesRemovedFromSet() {
- execute();
-
- TaskInternal task = builder().withInputFiles(inputFile).task();
- TaskArtifactState state = repository.getStateFor(task);
- assertFalse(state.isUpToDate());
- }
-
- @Test
- public void artifactsAreNotUpToDateWhenAnyInputFileHasChangedHash() {
- execute();
-
- inputFile.write("some new content");
-
- TaskArtifactState state = repository.getStateFor(task());
- assertFalse(state.isUpToDate());
- }
-
- @Test
- public void artifactsAreNotUpToDateWhenAnyInputFileHasChangedType() {
- execute();
-
- inputFile.delete();
- inputFile.createDir();
-
- TaskArtifactState state = repository.getStateFor(task());
- assertFalse(state.isUpToDate());
- }
-
- @Test
- public void artifactsAreNotUpToDateWhenAnyInputFileNoLongerExists() {
- execute();
-
- inputFile.delete();
-
- TaskArtifactState state = repository.getStateFor(task());
- assertFalse(state.isUpToDate());
- }
-
- @Test
- public void artifactsAreNotUpToDateWhenAnyFileCreatedInInputDir() {
- execute();
-
- inputDir.file("other-file").createFile();
-
- TaskArtifactState state = repository.getStateFor(task());
- assertFalse(state.isUpToDate());
- }
-
- @Test
- public void artifactsAreNotUpToDateWhenAnyFileDeletedFromInputDir() {
- execute();
-
- inputDirFile.delete();
-
- TaskArtifactState state = repository.getStateFor(task());
- assertFalse(state.isUpToDate());
- }
-
- @Test
- public void artifactsAreNotUpToDateWhenAnyFileInInputDirChangesHash() {
- execute();
-
- inputDirFile.writelns("new content");
-
- TaskArtifactState state = repository.getStateFor(task());
- assertFalse(state.isUpToDate());
- }
-
- @Test
- public void artifactsAreNotUpToDateWhenAnyFileInInputDirChangesType() {
- execute();
-
- inputDirFile.delete();
- inputDirFile.mkdir();
-
- TaskArtifactState state = repository.getStateFor(task());
- assertFalse(state.isUpToDate());
- }
-
- @Test
- public void artifactsAreNotUpToDateWhenAnyInputPropertyValueChanged() {
- execute();
-
- TaskArtifactState state = repository.getStateFor(builder().withProperty("prop", "new value").task());
- assertFalse(state.isUpToDate());
- }
-
- @Test
- public void inputPropertyValueCanBeNull() {
- TaskInternal task = builder().withProperty("prop", null).task();
- execute(task);
-
- TaskArtifactState state = repository.getStateFor(task);
- assertTrue(state.isUpToDate());
- }
-
- @Test
- public void artifactsAreNotUpToDateWhenAnyInputPropertyAdded() {
- execute();
-
- TaskArtifactState state = repository.getStateFor(builder().withProperty("prop2", "value").task());
- assertFalse(state.isUpToDate());
- }
-
- @Test
- public void artifactsAreNotUpToDateWhenAnyInputPropertyRemoved() {
- execute(builder().withProperty("prop2", "value").task());
-
- TaskArtifactState state = repository.getStateFor(task());
- assertFalse(state.isUpToDate());
- }
-
- @Test
- public void artifactsAreNotUpToDateWhenStateHasNotBeenUpdated() {
- repository.getStateFor(task());
-
- TaskArtifactState state = repository.getStateFor(task());
- assertFalse(state.isUpToDate());
- }
-
- @Test
- public void artifactsAreNotUpToDateWhenOutputDirWhichUsedToExistHasBeenDeleted() {
- // Output dir already exists before first execution of task
- outputDirFile.createFile();
-
- TaskInternal task1 = builder().withOutputFiles(outputDir).createsFiles(outputDirFile).task();
- TaskInternal task2 = builder().withPath("other").withOutputFiles(outputDir).createsFiles(outputDirFile2).task();
-
- TaskArtifactState state = repository.getStateFor(task1);
- assertFalse(state.isUpToDate());
- state.afterTask();
-
- outputDir.deleteDir();
-
- // Another task creates dir
- state = repository.getStateFor(task2);
- assertFalse(state.isUpToDate());
- task2.execute();
- state.afterTask();
-
- // Task should be out-of-date
- state = repository.getStateFor(task1);
- assertFalse(state.isUpToDate());
- }
-
- @Test
- public void artifactsAreUpToDateWhenNothingHasChangedSinceOutputFilesWereGenerated() {
- execute();
-
- TaskArtifactState state = repository.getStateFor(task());
- assertTrue(state.isUpToDate());
-
- state = repository.getStateFor(task());
- assertTrue(state.isUpToDate());
- }
-
- @Test
- public void artifactsAreUpToDateWhenOutputFileWhichDidNotExistNowExists() {
- execute();
-
- missingOutputFile.touch();
-
- TaskArtifactState state = repository.getStateFor(task());
- assertTrue(state.isUpToDate());
- }
-
- @Test
- public void artifactsAreUpToDateWhenOutputDirWhichWasEmptyIsNoLongerEmpty() {
- execute();
-
- emptyOutputDir.file("some-file").touch();
-
- TaskArtifactState state = repository.getStateFor(task());
- assertTrue(state.isUpToDate());
- }
-
- @Test
- public void hasEmptyTaskHistoryWhenTaskHasNeverBeenExecuted() {
- TaskArtifactState state = repository.getStateFor(task());
- assertThat(state.getExecutionHistory().getOutputFiles().getFiles(), isEmpty());
- }
-
- @Test
- public void hasTaskHistoryFromPreviousExecution() {
- execute();
-
- TaskArtifactState state = repository.getStateFor(task());
- assertThat(state.getExecutionHistory().getOutputFiles().getFiles(), equalTo(toLinkedSet((File) outputFile, outputDirFile, outputDirFile2)));
- }
-
- @Test
- public void multipleTasksCanProduceFilesIntoTheSameOutputDirectory() {
- TaskInternal task1 = task();
- TaskInternal task2 = builder().withPath("other").withOutputFiles(outputDir).createsFiles(outputDir.file("output2")).task();
- execute(task1, task2);
-
- TaskArtifactState state = repository.getStateFor(task1);
- assertTrue(state.isUpToDate());
-
- state = repository.getStateFor(task2);
- assertTrue(state.isUpToDate());
- }
-
- @Test
- public void multipleTasksCanProduceTheSameFileWithTheSameContents() {
- TaskInternal task1 = builder().withOutputFiles(outputFile).task();
- TaskInternal task2 = builder().withPath("other").withOutputFiles(outputFile).task();
- execute(task1, task2);
-
- TaskArtifactState state = repository.getStateFor(task1);
- assertTrue(state.isUpToDate());
-
- state = repository.getStateFor(task2);
- assertTrue(state.isUpToDate());
- }
-
- @Test
- public void multipleTasksCanProduceTheSameEmptyDir() {
- TaskInternal task1 = task();
- TaskInternal task2 = builder().withPath("other").withOutputFiles(outputDir).task();
- execute(task1, task2);
-
- TaskArtifactState state = repository.getStateFor(task1);
- assertTrue(state.isUpToDate());
-
- state = repository.getStateFor(task2);
- assertTrue(state.isUpToDate());
- }
-
- @Test
- public void doesNotConsiderExistingFilesInOutputDirectoryAsProducedByTask() {
- TestFile otherFile = outputDir.file("other").createFile();
-
- execute();
-
- otherFile.delete();
-
- TaskArtifactState state = repository.getStateFor(task());
- assertTrue(state.isUpToDate());
- assertThat(state.getExecutionHistory().getOutputFiles().getFiles(), (Matcher) not(hasItem(otherFile)));
- }
-
- @Test
- public void considersExistingFileInOutputDirectoryWhichIsUpdatedByTheTaskAsProducedByTask() {
- TestFile otherFile = outputDir.file("other").createFile();
-
- TaskInternal task = task();
- TaskArtifactState state = repository.getStateFor(task);
- assertFalse(state.isUpToDate());
-
- task.execute();
- otherFile.write("new content");
-
- state.afterTask();
-
- otherFile.delete();
-
- state = repository.getStateFor(task());
- assertFalse(state.isUpToDate());
- assertThat(state.getExecutionHistory().getOutputFiles().getFiles(), hasItem((File) otherFile));
- }
-
- @Test
- public void fileIsNoLongerConsideredProducedByTaskOnceItIsDeleted() {
- execute();
-
- outputDirFile.delete();
-
- TaskArtifactState state = repository.getStateFor(task());
- assertFalse(state.isUpToDate());
- state.afterTask();
-
- outputDirFile.write("ignore me");
-
- state = repository.getStateFor(task());
- assertTrue(state.isUpToDate());
- assertThat(state.getExecutionHistory().getOutputFiles().getFiles(), not(hasItem((File) outputDirFile)));
- state.afterTask();
- }
-
- @Test
- public void artifactsAreUpToDateWhenTaskDoesNotAcceptAnyInputs() {
- TaskInternal task = builder().doesNotAcceptInput().task();
- execute(task);
-
- TaskArtifactState state = repository.getStateFor(task);
- assertTrue(state.isUpToDate());
-
- outputDirFile.delete();
-
- state = repository.getStateFor(task);
- assertFalse(state.isUpToDate());
- }
-
- @Test
- public void artifactsAreUpToDateWhenTaskHasNoInputFiles() {
- TaskInternal task = builder().withInputFiles().task();
- execute(task);
-
- TaskArtifactState state = repository.getStateFor(task);
- assertTrue(state.isUpToDate());
- }
-
- @Test
- public void artifactsAreUpToDateWhenTaskHasNoOutputs() {
- TaskInternal task = builder().withOutputFiles().task();
- execute(task);
-
- TaskArtifactState state = repository.getStateFor(task);
- assertTrue(state.isUpToDate());
- }
-
- @Test
- public void taskCanProduceIntoDifferentSetsOfOutputFiles() {
- TestFile outputDir2 = tmpDir.createDir("output-dir-2");
- TestFile outputDirFile2 = outputDir2.file("output-file-2");
- TaskInternal instance1 = builder().withOutputFiles(outputDir).createsFiles(outputDirFile).task();
- TaskInternal instance2 = builder().withOutputFiles(outputDir2).createsFiles(outputDirFile2).task();
-
- execute(instance1, instance2);
-
- TaskArtifactState state = repository.getStateFor(instance1);
- assertTrue(state.isUpToDate());
- assertThat(state.getExecutionHistory().getOutputFiles().getFiles(), equalTo(toLinkedSet((File) outputDirFile)));
-
- state = repository.getStateFor(instance2);
- assertTrue(state.isUpToDate());
- assertThat(state.getExecutionHistory().getOutputFiles().getFiles(), equalTo(toLinkedSet((File) outputDirFile2)));
- }
-
- private void execute() {
- execute(task());
- }
-
- private void execute(TaskInternal... tasks) {
- for (TaskInternal task : tasks) {
- TaskArtifactState state = repository.getStateFor(task);
- state.isUpToDate();
- task.execute();
- state.afterTask();
- }
- }
-
- private TaskInternal task() {
- return builder().task();
- }
-
- private TaskBuilder builder() {
- return new TaskBuilder();
- }
-
- private class TaskBuilder {
- private String path = "task";
- private Collection<? extends File> inputs = inputFiles;
- private Collection<? extends File> outputs = outputFiles;
- private Collection<? extends TestFile> create = createFiles;
- private Class<? extends TaskInternal> type = TaskInternal.class;
- private Map<String, Object> inputProperties = new HashMap<String, Object>(toMap("prop", "value"));
-
- TaskBuilder withInputFiles(File... inputFiles) {
- inputs = Arrays.asList(inputFiles);
- return this;
- }
-
- TaskBuilder withOutputFiles(File... outputFiles) {
- outputs = Arrays.asList(outputFiles);
- return this;
- }
-
- TaskBuilder createsFiles(TestFile... outputFiles) {
- create = Arrays.asList(outputFiles);
- return this;
- }
-
- TaskBuilder withPath(String path) {
- this.path = path;
- return this;
- }
-
- TaskBuilder withType(Class<? extends TaskInternal> type) {
- this.type = type;
- return this;
- }
-
- TaskBuilder doesNotAcceptInput() {
- inputs = null;
- inputProperties = null;
- return this;
- }
-
- public TaskBuilder withProperty(String name, Object value) {
- inputProperties.put(name, value);
- return this;
- }
-
- TaskInternal task() {
- final TaskInternal task = HelperUtil.createTask(type, project, path);
- if (inputs != null) {
- task.getInputs().files(inputs);
- }
- if (inputProperties != null) {
- task.getInputs().properties(inputProperties);
- }
- if (outputs != null) {
- task.getOutputs().files(outputs);
- }
- task.doLast(new org.gradle.api.Action<Object>() {
- public void execute(Object o) {
- for (TestFile file : create) {
- file.createFile();
- }
- }
- });
-
- return task;
- }
- }
-
- public static class TaskSubType extends DefaultTask {
- }
-
-}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/FileCacheBroadcastTaskArtifactStateRepositoryTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/FileCacheBroadcastTaskArtifactStateRepositoryTest.groovy
deleted file mode 100644
index b7f1794..0000000
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/FileCacheBroadcastTaskArtifactStateRepositoryTest.groovy
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.changedetection
-
-import org.gradle.api.file.FileCollection
-import org.gradle.api.internal.TaskInternal
-import org.gradle.api.internal.TaskOutputsInternal
-import org.gradle.api.tasks.TaskInputs
-import spock.lang.Specification
-
-class FileCacheBroadcastTaskArtifactStateRepositoryTest extends Specification {
- final TaskArtifactStateRepository target = Mock()
- final TaskArtifactState targetState = Mock()
- final TaskInternal task = Mock()
- final TaskInputs taskInputs = Mock()
- final TaskOutputsInternal taskOutputs = Mock()
- final FileCollection outputs = Mock()
- final FileCollection inputs = Mock()
- final FileCacheListener listener = Mock()
- final FileCacheBroadcastTaskArtifactStateRepository repository = new FileCacheBroadcastTaskArtifactStateRepository(target, listener)
-
- def setup() {
- _ * task.inputs >> taskInputs
- _ * taskInputs.files >> inputs
- _ * task.outputs >> taskOutputs
- _ * taskOutputs.files >> outputs
- }
-
- def marksTaskInputsAndOutputsAsCacheableWhenCheckingUpToDate() {
- when:
- def state = repository.getStateFor(task)
- state.isUpToDate()
-
- then:
- 1 * listener.cacheable(inputs)
- 1 * listener.cacheable(outputs)
- 1 * target.getStateFor(task) >> targetState
- 1 * targetState.isUpToDate()
- 0 * listener._
- }
-
- def invalidatesTaskOutputsWhenTaskIsToBeExecuted() {
- given:
- taskOutputs.hasOutput >> true
-
- when:
- def state = repository.getStateFor(task)
- state.beforeTask()
-
- then:
- 1 * listener.invalidate(outputs)
- 1 * target.getStateFor(task) >> targetState
- 1 * targetState.beforeTask()
- 0 * listener._
- }
-
- def invalidatesEverythingWhenTaskWhichDoesNotDeclareAnyOutputsIsToBeExecuted() {
- given:
- taskOutputs.hasOutput >> false
-
- when:
- def state = repository.getStateFor(task)
- state.beforeTask()
-
- then:
- 1 * listener.invalidateAll()
- 1 * target.getStateFor(task) >> targetState
- 1 * targetState.beforeTask()
- 0 * listener._
- }
-
- def marksTaskOutputsAsCacheableAfterTaskHasExecuted() {
- when:
- def state = repository.getStateFor(task)
- state.afterTask()
-
- then:
- 1 * listener.cacheable(outputs)
- 1 * target.getStateFor(task) >> targetState
- 1 * targetState.afterTask()
- 0 * listener._
- }
-
- def delegatesToBackingStateForOtherMethods() {
- when:
- def state = repository.getStateFor(task)
- state.finished()
-
- then:
- 1 * target.getStateFor(task) >> targetState
- 1 * targetState.finished()
- 0 * listener._
- }
-}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/ShortCircuitTaskArtifactStateRepositoryTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/ShortCircuitTaskArtifactStateRepositoryTest.java
deleted file mode 100755
index ecec7f5..0000000
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/ShortCircuitTaskArtifactStateRepositoryTest.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.changedetection;
-
-import org.gradle.StartParameter;
-import org.gradle.api.Task;
-import org.gradle.api.internal.TaskExecutionHistory;
-import org.gradle.api.internal.TaskInternal;
-import org.gradle.api.internal.TaskOutputsInternal;
-import org.gradle.api.specs.Spec;
-import org.jmock.Expectations;
-import org.jmock.integration.junit4.JMock;
-import org.jmock.integration.junit4.JUnit4Mockery;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static org.hamcrest.Matchers.sameInstance;
-import static org.junit.Assert.*;
-
- at RunWith(JMock.class)
-public class ShortCircuitTaskArtifactStateRepositoryTest {
- private final JUnit4Mockery context = new JUnit4Mockery();
- private final StartParameter startParameter = new StartParameter();
- private final TaskArtifactStateRepository delegate = context.mock(TaskArtifactStateRepository.class);
- private final TaskArtifactState taskArtifactState = context.mock(TaskArtifactState.class);
- private final TaskOutputsInternal taskOutputsInternal = context.mock(TaskOutputsInternal.class);
- private final Spec<Task> upToDateSpec = context.mock(Spec.class);
- private final ShortCircuitTaskArtifactStateRepository repository = new ShortCircuitTaskArtifactStateRepository(startParameter, delegate);
-
- @Test
- public void doesNotCreateStateObjectWhenTaskHasNotDeclaredAnyOutputs() {
- TaskInternal task = taskWithNoOutputs();
- TaskArtifactState state = repository.getStateFor(task);
- assertNotNull(state);
-
- assertFalse(state.isUpToDate());
- state.beforeTask();
- state.afterTask();
- state.finished();
- }
-
- @Test
- public void delegatesToBackingRepositoryToCreateStateObjectForTaskThatHasDeclaredSomeOutputs() {
- TaskInternal task = taskWithOutputs();
- expectTaskStateCreated(task);
-
- TaskArtifactState state = repository.getStateFor(task);
- assertNotNull(state);
-
- final TaskExecutionHistory executionHistory = context.mock(TaskExecutionHistory.class);
-
- context.checking(new Expectations() {{
- one(taskArtifactState).getExecutionHistory();
- will(returnValue(executionHistory));
- one(taskArtifactState).beforeTask();
- one(taskArtifactState).afterTask();
- one(taskArtifactState).finished();
- }});
-
- assertThat(state.getExecutionHistory(), sameInstance(executionHistory));
- state.beforeTask();
- state.afterTask();
- state.finished();
- }
-
- @Test
- public void taskArtifactsAreOutOfDateWhenStartParameterOverrideNoOptIsSet() {
- TaskInternal task = taskWithOutputs();
- expectTaskStateCreated(task);
-
- TaskArtifactState state = repository.getStateFor(task);
-
- startParameter.setRerunTasks(true);
- assertFalse(state.isUpToDate());
- }
-
- @Test
- public void taskArtifactsAreOutOfDateWhenStartParameterOverrideRerunTasksIsSet() {
- TaskInternal task = taskWithOutputs();
- expectTaskStateCreated(task);
-
- TaskArtifactState state = repository.getStateFor(task);
-
- startParameter.setRerunTasks(true);
- assertFalse(state.isUpToDate());
- }
-
- @Test
- public void taskArtifactsAreOutOfDateWhenUpToDateSpecIsFalse() {
- final TaskInternal task = taskWithOutputs();
- expectTaskStateCreated(task);
-
- TaskArtifactState state = repository.getStateFor(task);
-
- context.checking(new Expectations() {{
- one(upToDateSpec).isSatisfiedBy(task);
- will(returnValue(false));
- }});
-
- assertFalse(state.isUpToDate());
- }
-
- @Test
- public void determinesWhetherTaskArtifactsAreUpToDateUsingBackingRepository() {
- final TaskInternal task = taskWithOutputs();
- expectTaskStateCreated(task);
-
- TaskArtifactState state = repository.getStateFor(task);
-
- context.checking(new Expectations() {{
- one(upToDateSpec).isSatisfiedBy(task);
- will(returnValue(true));
- one(taskArtifactState).isUpToDate();
- will(returnValue(true));
- }});
-
- assertTrue(state.isUpToDate());
- }
-
- private void expectTaskStateCreated(final TaskInternal task) {
- context.checking(new Expectations() {{
- one(delegate).getStateFor(task);
- will(returnValue(taskArtifactState));
- }});
- }
-
- private TaskInternal taskWithOutputs() {
- final TaskInternal task = context.mock(TaskInternal.class);
- context.checking(new Expectations() {{
- allowing(task).getOutputs();
- will(returnValue(taskOutputsInternal));
- allowing(taskOutputsInternal).getHasOutput();
- will(returnValue(true));
- allowing(taskOutputsInternal).getUpToDateSpec();
- will(returnValue(upToDateSpec));
- }});
-
- return task;
- }
-
- private TaskInternal taskWithNoOutputs() {
- final TaskInternal task = context.mock(TaskInternal.class);
- context.checking(new Expectations() {{
- allowing(task).getOutputs();
- will(returnValue(taskOutputsInternal));
- allowing(taskOutputsInternal).getHasOutput();
- will(returnValue(false));
- }});
-
- return task;
- }
-}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/changes/DefaultTaskArtifactStateRepositoryTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/changes/DefaultTaskArtifactStateRepositoryTest.groovy
new file mode 100644
index 0000000..4b20daa
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/changes/DefaultTaskArtifactStateRepositoryTest.groovy
@@ -0,0 +1,683 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.changes
+import org.gradle.CacheUsage
+import org.gradle.api.Action
+import org.gradle.api.DefaultTask
+import org.gradle.api.internal.TaskInternal
+import org.gradle.api.internal.changedetection.TaskArtifactState
+import org.gradle.api.internal.changedetection.state.*
+import org.gradle.api.tasks.incremental.InputFileDetails
+import org.gradle.cache.CacheRepository
+import org.gradle.cache.internal.DefaultCacheRepository
+import org.gradle.internal.id.RandomLongIdGenerator
+import org.gradle.internal.reflect.DirectInstantiator
+import org.gradle.test.fixtures.file.TestFile
+import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
+import org.gradle.testfixtures.internal.InMemoryCacheFactory
+import org.gradle.util.TestUtil
+import org.junit.Rule
+import spock.lang.Specification
+
+import static org.gradle.util.WrapUtil.toMap
+import static org.gradle.util.WrapUtil.toSet
+
+public class DefaultTaskArtifactStateRepositoryTest extends Specification {
+
+ @Rule
+ public TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider()
+ final project = TestUtil.createRootProject()
+ final gradle = project.getGradle()
+ final outputFile = tmpDir.file("output-file")
+ final outputDir = tmpDir.file("output-dir")
+ final outputDirFile = outputDir.file("some-file")
+ final outputDirFile2 = outputDir.file("some-file-2")
+ final emptyOutputDir = tmpDir.file("empty-output-dir")
+ final missingOutputFile = tmpDir.file("missing-output-file")
+ final inputFile = tmpDir.createFile("input-file")
+ final inputDir = tmpDir.createDir("input-dir")
+ final inputDirFile = inputDir.file("input-file2").createFile()
+ final missingInputFile = tmpDir.file("missing-input-file")
+ final inputFiles = toSet(inputFile, inputDir, missingInputFile)
+ final outputFiles = toSet(outputFile, outputDir, emptyOutputDir, missingOutputFile)
+ final createFiles = toSet(outputFile, outputDirFile, outputDirFile2)
+ TaskInternal task = builder.task()
+ DefaultTaskArtifactStateRepository repository
+
+
+ def setup() {
+ CacheRepository cacheRepository = new DefaultCacheRepository(tmpDir.createDir("user-home"), null, CacheUsage.ON, new InMemoryCacheFactory())
+ TaskArtifactStateCacheAccess cacheAccess = new DefaultTaskArtifactStateCacheAccess(gradle, cacheRepository)
+ FileSnapshotter inputFilesSnapshotter = new DefaultFileSnapshotter(new DefaultHasher(), cacheAccess)
+ FileSnapshotter outputFilesSnapshotter = new OutputFilesSnapshotter(inputFilesSnapshotter, new RandomLongIdGenerator(), cacheAccess)
+ TaskHistoryRepository taskHistoryRepository = new CacheBackedTaskHistoryRepository(cacheAccess, new CacheBackedFileSnapshotRepository(cacheAccess, new RandomLongIdGenerator()))
+ repository = new DefaultTaskArtifactStateRepository(taskHistoryRepository, new DirectInstantiator(), outputFilesSnapshotter, inputFilesSnapshotter)
+ }
+
+ def artifactsAreNotUpToDateWhenCacheIsEmpty() {
+ expect:
+ outOfDate(task)
+ }
+
+ def artifactsAreNotUpToDateWhenAnyOutputFileNoLongerExists() {
+ given:
+ execute(task)
+
+ when:
+ outputFile.delete()
+
+ then:
+ outOfDate task
+ }
+
+ def artifactsAreNotUpToDateWhenAnyFileInOutputDirNoLongerExists() {
+ given:
+ execute(task)
+
+ when:
+ outputDirFile.delete()
+
+ then:
+ outOfDate task
+ }
+
+ def artifactsAreNotUpToDateWhenAnyOutputFileHasChangedType() {
+ given:
+ execute(task)
+
+ when:
+ outputFile.delete()
+ outputFile.createDir()
+
+ then:
+ outOfDate task
+ }
+
+ def artifactsAreNotUpToDateWhenAnyFileInOutputDirHasChangedType() {
+ given:
+ execute(task)
+
+ when:
+ outputDirFile.delete()
+ outputDirFile.createDir()
+
+ then:
+ outOfDate task
+ }
+
+ def artifactsAreNotUpToDateWhenAnyOutputFileHasChangedHash() {
+ given:
+ execute(task)
+
+ when:
+ outputFile.write("new content")
+
+ then:
+ outOfDate task
+ }
+
+ def artifactsAreNotUpToDateWhenAnyFileInOutputDirHasChangedHash() {
+ given:
+ execute(task)
+
+ when:
+ outputDirFile.write("new content")
+
+ then:
+ outOfDate task
+ }
+
+ def artifactsAreNotUpToDateWhenAnyOutputFilesAddedToSet() {
+ when:
+ execute(task)
+ TaskInternal outputFilesAddedTask = builder.withOutputFiles(outputFile, outputDir, tmpDir.createFile("output-file-2"), emptyOutputDir, missingOutputFile).task()
+
+ then:
+ outOfDate outputFilesAddedTask
+ }
+
+ def artifactsAreNotUpToDateWhenAnyOutputFilesRemovedFromSet() {
+ when:
+ execute(task)
+ TaskInternal outputFilesRemovedTask = builder.withOutputFiles(outputFile, emptyOutputDir, missingOutputFile).task()
+
+ then:
+ outOfDate outputFilesRemovedTask
+ }
+
+ def artifactsAreNotUpToDateWhenTaskWithDifferentTypeGeneratedAnyOutputFiles() {
+ when:
+ TaskInternal task1 = builder.withOutputFiles(outputFile).task()
+ TaskInternal task2 = builder.withType(TaskSubType.class).withOutputFiles(outputFile).task()
+ execute(task1, task2)
+
+ then:
+ outOfDate task
+ }
+
+ def artifactsAreNotUpToDateWhenAnyInputFilesAddedToSet() {
+ final addedFile = tmpDir.createFile("other-input")
+
+ when:
+ execute(task)
+ TaskInternal inputFilesAdded = builder.withInputFiles(inputFile, inputDir, addedFile, missingInputFile).task()
+
+ then:
+ inputsOutOfDate(inputFilesAdded).withAddedFile(addedFile)
+ }
+
+ def artifactsAreNotUpToDateWhenAnyInputFilesRemovedFromSet() {
+ when:
+ execute(task)
+ TaskInternal inputFilesRemoved = builder.withInputFiles(inputFile).task()
+
+ then:
+ inputsOutOfDate(inputFilesRemoved).withRemovedFile(inputDirFile)
+ }
+
+ def artifactsAreNotUpToDateWhenAnyInputFileHasChangedHash() {
+ given:
+ execute(task)
+
+ when:
+ inputFile.write("some new content")
+
+ then:
+ inputsOutOfDate(task).withModifiedFile(inputFile)
+ }
+
+ def artifactsAreNotUpToDateWhenAnyInputFileHasChangedType() {
+ given:
+ execute(task)
+
+ when:
+ inputFile.delete()
+ inputFile.createDir()
+
+ then:
+ inputsOutOfDate(task).withRemovedFile(inputFile)
+ }
+
+ def artifactsAreNotUpToDateWhenAnyInputFileNoLongerExists() {
+ given:
+ execute(task)
+
+ when:
+ inputFile.delete()
+
+ then:
+ inputsOutOfDate(task).withRemovedFile(inputFile)
+ }
+
+ def artifactsAreNotUpToDateWhenAnyFileCreatedInInputDir() {
+ given:
+ execute(task)
+
+ when:
+ def file = inputDir.file("other-file").createFile()
+
+ then:
+ inputsOutOfDate(task).withAddedFile(file)
+ }
+
+ def artifactsAreNotUpToDateWhenAnyFileDeletedFromInputDir() {
+ given:
+ execute(task)
+
+ when:
+ inputDirFile.delete()
+
+ then:
+ inputsOutOfDate(task).withRemovedFile(inputDirFile)
+ }
+
+ def artifactsAreNotUpToDateWhenAnyFileInInputDirChangesHash() {
+ given:
+ execute(task)
+
+ when:
+ inputDirFile.writelns("new content")
+
+ then:
+ inputsOutOfDate(task).withModifiedFile(inputDirFile)
+ }
+
+ def artifactsAreNotUpToDateWhenAnyFileInInputDirChangesType() {
+ given:
+ execute(task)
+
+ when:
+ inputDirFile.delete()
+ inputDirFile.mkdir()
+
+ then:
+ inputsOutOfDate(task).withRemovedFile(inputDirFile)
+ }
+
+ def artifactsAreNotUpToDateWhenAnyInputPropertyValueChanged() {
+ when:
+ execute(builder.withProperty("prop", "original value").task())
+ final inputPropertiesTask = builder.withProperty("prop", "new value").task()
+
+ then:
+ outOfDate inputPropertiesTask
+ }
+
+ def inputPropertyValueCanBeNull() {
+ when:
+ TaskInternal task = builder.withProperty("prop", null).task()
+ execute(task)
+
+ then:
+ upToDate(task)
+ }
+
+ def artifactsAreNotUpToDateWhenAnyInputPropertyAdded() {
+ when:
+ execute(task)
+ final addedPropertyTask = builder.withProperty("prop2", "value").task()
+
+ then:
+ outOfDate addedPropertyTask
+ }
+
+ def artifactsAreNotUpToDateWhenAnyInputPropertyRemoved() {
+ given:
+ execute(builder.withProperty("prop2", "value").task())
+
+ expect:
+ outOfDate task
+ }
+
+ def artifactsAreNotUpToDateWhenStateHasNotBeenUpdated() {
+ when:
+ repository.getStateFor(task)
+
+ then:
+ outOfDate task
+ }
+
+ def artifactsAreNotUpToDateWhenOutputDirWhichUsedToExistHasBeenDeleted() {
+ given:
+ // Output dir already exists before first execution of task
+ outputDirFile.createFile()
+
+ TaskInternal task1 = builder.withOutputFiles(outputDir).createsFiles(outputDirFile).task()
+ TaskInternal task2 = builder.withPath("other").withOutputFiles(outputDir).createsFiles(outputDirFile2).task()
+
+ when:
+ TaskArtifactState state = repository.getStateFor(task1)
+ state.afterTask()
+
+ then:
+ !state.upToDate
+
+ when:
+ outputDir.deleteDir()
+
+ and:
+ // Another task creates dir
+ state = repository.getStateFor(task2)
+
+ then:
+ !state.isUpToDate([])
+
+ when:
+ task2.execute()
+ state.afterTask()
+
+ then:
+ // Task should be out-of-date
+ outOfDate task1
+ }
+
+ def artifactsAreUpToDateWhenNothingHasChangedSinceOutputFilesWereGenerated() {
+ given:
+ execute(task)
+
+ expect:
+ repository.getStateFor(task).isUpToDate([])
+ repository.getStateFor(task).isUpToDate([])
+ }
+
+ def artifactsAreUpToDateWhenOutputFileWhichDidNotExistNowExists() {
+ given:
+ execute(task)
+
+ when:
+ missingOutputFile.touch()
+
+ then:
+ upToDate task
+ }
+
+ def artifactsAreUpToDateWhenOutputDirWhichWasEmptyIsNoLongerEmpty() {
+ given:
+ execute(task)
+
+ when:
+ emptyOutputDir.file("some-file").touch()
+
+ then:
+ upToDate task
+ }
+
+ def hasEmptyTaskHistoryWhenTaskHasNeverBeenExecuted() {
+ when:
+ TaskArtifactState state = repository.getStateFor(task)
+
+ then:
+ state.getExecutionHistory().getOutputFiles().getFiles().isEmpty()
+ }
+
+ def hasTaskHistoryFromPreviousExecution() {
+ given:
+ execute(task)
+
+ when:
+ TaskArtifactState state = repository.getStateFor(task)
+
+ then:
+ state.getExecutionHistory().getOutputFiles().getFiles() == [outputFile, outputDirFile, outputDirFile2] as Set
+ }
+
+ def multipleTasksCanProduceFilesIntoTheSameOutputDirectory() {
+ when:
+ TaskInternal task1 = task
+ TaskInternal task2 = builder.withPath("other").withOutputFiles(outputDir).createsFiles(outputDir.file("output2")).task()
+ execute(task1, task2)
+
+ then:
+ upToDate task1
+ upToDate task2
+ }
+
+ def multipleTasksCanProduceTheSameFileWithTheSameContents() {
+ when:
+ TaskInternal task1 = builder.withOutputFiles(outputFile).task()
+ TaskInternal task2 = builder.withPath("other").withOutputFiles(outputFile).task()
+ execute(task1, task2)
+
+ then:
+ upToDate task1
+ upToDate task2
+ }
+
+ def multipleTasksCanProduceTheSameEmptyDir() {
+ when:
+ TaskInternal task1 = task
+ TaskInternal task2 = builder.withPath("other").withOutputFiles(outputDir).task()
+ execute(task1, task2)
+
+ then:
+ upToDate task1
+ upToDate task2
+ }
+
+ def doesNotConsiderExistingFilesInOutputDirectoryAsProducedByTask() {
+ when:
+ TestFile otherFile = outputDir.file("other").createFile()
+ execute(task)
+ otherFile.delete()
+
+ then:
+ TaskArtifactState state = repository.getStateFor(task)
+ state.isUpToDate([])
+ !state.getExecutionHistory().getOutputFiles().getFiles().contains(otherFile)
+ }
+
+ def considersExistingFileInOutputDirectoryWhichIsUpdatedByTheTaskAsProducedByTask() {
+ when:
+ TestFile otherFile = outputDir.file("other").createFile()
+ TaskArtifactState state = repository.getStateFor(task)
+
+ then:
+ !state.isUpToDate([])
+
+ when:
+ task.execute()
+ otherFile.write("new content")
+ state.afterTask()
+ otherFile.delete()
+
+ then:
+ def stateAfter = repository.getStateFor(task)
+ !stateAfter.upToDate
+ stateAfter.executionHistory.outputFiles.files.contains(otherFile)
+ }
+
+ def fileIsNoLongerConsideredProducedByTaskOnceItIsDeleted() {
+ given:
+ execute(task)
+
+ outputDirFile.delete()
+ TaskArtifactState state = repository.getStateFor(task)
+ state.afterTask()
+
+ when:
+ outputDirFile.write("ignore me")
+
+ then:
+ def stateAfter = repository.getStateFor(task)
+ stateAfter.isUpToDate([])
+ !stateAfter.executionHistory.outputFiles.files.contains(outputDirFile)
+ }
+
+ def artifactsAreUpToDateWhenTaskDoesNotAcceptAnyInputs() {
+ when:
+ TaskInternal noInputsTask = builder.doesNotAcceptInput().task()
+ execute(noInputsTask)
+
+ then:
+ upToDate noInputsTask
+
+ when:
+ outputDirFile.delete()
+
+ then:
+ outOfDate noInputsTask
+ }
+
+ def artifactsAreUpToDateWhenTaskHasNoInputFiles() {
+ when:
+ TaskInternal noInputFilesTask = builder.withInputFiles().task()
+ execute(noInputFilesTask)
+
+ then:
+ upToDate noInputFilesTask
+ }
+
+ def artifactsAreUpToDateWhenTaskHasNoOutputFiles() {
+ when:
+ TaskInternal noOutputsTask = builder.withOutputFiles().task()
+ execute(noOutputsTask)
+
+ then:
+ upToDate noOutputsTask
+ }
+
+ def taskCanProduceIntoDifferentSetsOfOutputFiles() {
+ when:
+ TestFile outputDir2 = tmpDir.createDir("output-dir-2")
+ TestFile outputDirFile2 = outputDir2.file("output-file-2")
+ TaskInternal task1 = builder.withOutputFiles(outputDir).createsFiles(outputDirFile).task()
+ TaskInternal task2 = builder.withOutputFiles(outputDir2).createsFiles(outputDirFile2).task()
+
+ execute(task1, task2)
+
+ then:
+ def state1 = repository.getStateFor(task1)
+ state1.isUpToDate([])
+ state1.executionHistory.outputFiles.files == [outputDirFile] as Set
+
+ and:
+ def state2 = repository.getStateFor(task2)
+ state2.isUpToDate([])
+ state2.executionHistory.outputFiles.files == [outputDirFile2] as Set
+ }
+
+ private void outOfDate(TaskInternal task) {
+ final state = repository.getStateFor(task)
+ assert !state.upToDate
+ assert !state.inputChanges.incremental
+ }
+
+ def inputsOutOfDate(TaskInternal task) {
+ final state = repository.getStateFor(task)
+ assert !state.upToDate
+
+ final inputChanges = state.inputChanges
+ assert inputChanges.incremental
+
+ final changedFiles = new ChangedFiles()
+ inputChanges.outOfDate(new Action<InputFileDetails>() {
+ void execute(InputFileDetails t) {
+ if (t.added) {
+ println "Added: " + t.file
+ changedFiles.added << t.file
+ } else if (t.modified) {
+ println "Modified: " + t.file
+ changedFiles.modified << t.file
+ } else {
+ assert false : "Not a valid change"
+ }
+ }
+ })
+ inputChanges.removed(new Action<InputFileDetails>() {
+ void execute(InputFileDetails t) {
+ println "Removed: " + t.file
+ assert t.removed
+ changedFiles.removed << t.file
+ }
+ })
+
+ return changedFiles
+ }
+
+ private void upToDate(TaskInternal task) {
+ final state = repository.getStateFor(task)
+ assert state.isUpToDate([])
+ }
+
+ private void execute(TaskInternal... tasks) {
+ for (TaskInternal task : tasks) {
+ TaskArtifactState state = repository.getStateFor(task)
+ state.isUpToDate([])
+ task.execute()
+ state.afterTask()
+ }
+ }
+
+ private static class ChangedFiles {
+ def added = []
+ def modified = []
+ def removed = []
+
+ void withAddedFile(File file) {
+ assert added == [file]
+ assert modified == []
+ assert removed == []
+ }
+
+ void withModifiedFile(File file) {
+ assert added == []
+ assert modified == [file]
+ assert removed == []
+ }
+
+ void withRemovedFile(File file) {
+ assert added == []
+ assert modified == []
+ assert removed == [file]
+ }
+ }
+
+ private TaskBuilder getBuilder() {
+ return new TaskBuilder()
+ }
+
+ private class TaskBuilder {
+ private String path = "task"
+ private Collection<? extends File> inputs = inputFiles
+ private Collection<? extends File> outputs = outputFiles
+ private Collection<? extends TestFile> create = createFiles
+ private Class<? extends TaskInternal> type = TaskInternal.class
+ private Map<String, Object> inputProperties = new HashMap<String, Object>(toMap("prop", "value"))
+
+ TaskBuilder withInputFiles(File... inputFiles) {
+ inputs = Arrays.asList(inputFiles)
+ return this
+ }
+
+ TaskBuilder withOutputFiles(File... outputFiles) {
+ outputs = Arrays.asList(outputFiles)
+ return this
+ }
+
+ TaskBuilder createsFiles(TestFile... outputFiles) {
+ create = Arrays.asList(outputFiles)
+ return this
+ }
+
+ TaskBuilder withPath(String path) {
+ this.path = path
+ return this
+ }
+
+ TaskBuilder withType(Class<? extends TaskInternal> type) {
+ this.type = type
+ return this
+ }
+
+ TaskBuilder doesNotAcceptInput() {
+ inputs = null
+ inputProperties = null
+ return this
+ }
+
+ public TaskBuilder withProperty(String name, Object value) {
+ inputProperties.put(name, value)
+ return this
+ }
+
+ TaskInternal task() {
+ final TaskInternal task = TestUtil.createTask(type, project, path)
+ if (inputs != null) {
+ task.getInputs().files(inputs)
+ }
+ if (inputProperties != null) {
+ task.getInputs().properties(inputProperties)
+ }
+ if (outputs != null) {
+ task.getOutputs().files(outputs)
+ }
+ task.doLast(new org.gradle.api.Action<Object>() {
+ public void execute(Object o) {
+ for (TestFile file : create) {
+ file.createFile()
+ }
+ }
+ })
+
+ return task
+ }
+ }
+
+ public static class TaskSubType extends DefaultTask {
+ }
+
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/changes/ShortCircuitTaskArtifactStateRepositoryTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/changes/ShortCircuitTaskArtifactStateRepositoryTest.groovy
new file mode 100755
index 0000000..86723cb
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/changes/ShortCircuitTaskArtifactStateRepositoryTest.groovy
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.changes
+
+import org.gradle.StartParameter
+import org.gradle.api.internal.TaskInternal
+import org.gradle.api.internal.TaskOutputsInternal
+import org.gradle.api.internal.changedetection.TaskArtifactState
+import org.gradle.api.internal.changedetection.TaskArtifactStateRepository
+import org.gradle.api.specs.Spec
+import org.gradle.internal.reflect.DirectInstantiator
+import spock.lang.Specification
+
+public class ShortCircuitTaskArtifactStateRepositoryTest extends Specification {
+ StartParameter startParameter = new StartParameter()
+ TaskArtifactStateRepository delegate = Mock(TaskArtifactStateRepository)
+ ShortCircuitTaskArtifactStateRepository repository = new ShortCircuitTaskArtifactStateRepository(startParameter, new DirectInstantiator(), delegate)
+ TaskArtifactState taskArtifactState = Mock(TaskArtifactState)
+ TaskInternal task = Mock(TaskInternal)
+ TaskOutputsInternal outputs = Mock(TaskOutputsInternal)
+ Spec upToDateSpec = Mock(Spec)
+
+ def doesNotLoadHistoryWhenTaskHasNoDeclaredOutputs() {
+ def messages = []
+
+ when:
+ TaskArtifactState state = repository.getStateFor(task);
+
+ then:
+ 1 * task.getOutputs() >> outputs
+ 1 * outputs.getHasOutput() >> false
+ 0 * _
+
+ and:
+ state instanceof NoHistoryArtifactState
+ !state.isUpToDate(messages)
+ !messages.empty
+ }
+
+ def delegatesDirectToBackingRepositoryWithoutRerunTasks() {
+ when:
+ TaskArtifactState state = repository.getStateFor(task);
+
+ then:
+ 2 * task.getOutputs() >> outputs
+ 1 * outputs.getHasOutput() >> true
+ 1 * outputs.getUpToDateSpec() >> upToDateSpec
+ 1 * upToDateSpec.isSatisfiedBy(task) >> true
+
+ and:
+ 1 * delegate.getStateFor(task) >> taskArtifactState
+ state == taskArtifactState
+ }
+
+ def taskArtifactsAreAlwaysOutOfDateWithRerunTasks() {
+ def messages = []
+
+ when:
+ startParameter.setRerunTasks(true);
+ def state = repository.getStateFor(task)
+
+ then:
+ 1 * task.getOutputs() >> outputs
+ 1 * outputs.getHasOutput() >> true
+ 1 * delegate.getStateFor(task) >> taskArtifactState
+ 0 * taskArtifactState._
+
+ and:
+ !state.isUpToDate(messages)
+ !messages.empty
+
+ and:
+ !state.inputChanges.incremental
+ }
+
+ def taskArtifactsAreAlwaysOutOfDateWhenUpToDateSpecReturnsFalse() {
+ def messages = []
+
+ when:
+ def state = repository.getStateFor(task)
+
+ then:
+ 2 * task.getOutputs() >> outputs
+ 1 * outputs.getHasOutput() >> true
+ 1 * outputs.getUpToDateSpec() >> upToDateSpec
+ 1 * upToDateSpec.isSatisfiedBy(task) >> false
+
+ and:
+ 1 * delegate.getStateFor(task) >> taskArtifactState
+ 0 * taskArtifactState._
+
+ and:
+ !state.isUpToDate(messages)
+ !messages.empty
+
+ and:
+ !state.inputChanges.incremental
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/rules/CachingTaskStateChangesTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/rules/CachingTaskStateChangesTest.groovy
new file mode 100644
index 0000000..3acfff7
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/rules/CachingTaskStateChangesTest.groovy
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.rules;
+
+import spock.lang.Specification;
+
+public class CachingTaskStateChangesTest extends Specification {
+ def delegate = Mock(TaskStateChanges)
+ def change1 = Mock(TaskStateChange)
+ def change2 = Mock(TaskStateChange)
+ def change3 = Mock(TaskStateChange)
+
+ def cachingChanges = new CachingTaskStateChanges(2, delegate)
+
+ def "delegates to underlying instance"() {
+ when:
+ def reported = cachingChanges.iterator().collect()
+
+ then:
+ delegate.iterator() >> [change1, change2, change3].iterator()
+
+ and:
+ reported == [change1, change2, change3]
+
+ when:
+ cachingChanges.snapshotAfterTask()
+
+ then:
+ delegate.snapshotAfterTask()
+ }
+
+ def "caches all reported changes under cache size"() {
+ when:
+ cachingChanges.iterator().collect()
+
+ then:
+ 1 * delegate.iterator() >> [change1, change2].iterator()
+ 0 * _
+
+ when:
+ cachingChanges.iterator().collect()
+ def reported = cachingChanges.iterator().collect()
+
+ then:
+ 0 * _
+
+ and:
+ reported == [change1, change2]
+ }
+
+ def "does not cache once reported changes exceed cache size"() {
+ when:
+ cachingChanges.iterator().collect()
+
+ then:
+ 1 * delegate.iterator() >> [change1, change2, change3].iterator()
+ 0 * _
+
+ when:
+ cachingChanges.iterator().collect()
+ def reported = cachingChanges.iterator().collect()
+
+ then:
+ 2 * delegate.iterator() >> [change1, change2, change3].iterator() >> [change3, change2, change1].iterator()
+ 0 * _
+
+ and:
+ reported == [change3, change2, change1]
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/rules/InputFilesStateChangeRuleTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/rules/InputFilesStateChangeRuleTest.groovy
new file mode 100644
index 0000000..6bad53c
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/rules/InputFilesStateChangeRuleTest.groovy
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.rules
+import org.gradle.api.internal.TaskInternal
+import org.gradle.api.internal.changedetection.state.FileCollectionSnapshot
+import org.gradle.api.internal.changedetection.state.FileSnapshotter
+import org.gradle.api.internal.changedetection.state.TaskExecution
+import org.gradle.api.internal.file.collections.SimpleFileCollection
+import org.gradle.api.tasks.TaskInputs
+import org.gradle.util.ChangeListener
+import spock.lang.Specification
+
+public class InputFilesStateChangeRuleTest extends Specification {
+ def inputSnapshot = Mock(FileCollectionSnapshot)
+ def previousInputSnapshot = Mock(FileCollectionSnapshot)
+ FileCollectionSnapshot.ChangeIterator<String> changeIterator = Mock()
+
+ TaskStateChanges createStateChanges() {
+ def taskInputs = Stub(TaskInputs) {
+ getFiles() >> new SimpleFileCollection()
+ }
+ def task = Stub(TaskInternal) {
+ getInputs() >> taskInputs
+ }
+ def snapshotter = Stub(FileSnapshotter) {
+ snapshot(_) >> inputSnapshot
+ }
+
+ def previousExecution = Stub(TaskExecution) {
+ getInputFilesSnapshot() >> previousInputSnapshot
+ }
+ return InputFilesStateChangeRule.create(task, previousExecution, Mock(TaskExecution), snapshotter)
+ }
+
+ def "emits change for no previous input snapshot"() {
+ when:
+ previousInputSnapshot = null
+ def messages = createStateChanges().iterator().collect {it.message}
+
+ then:
+ messages == ["Input file history is not available."]
+ }
+
+ def "emits change for file changes since previous input snapshot"() {
+ when:
+ def messages = createStateChanges().iterator().collect {it.message}
+
+ then:
+ 1 * inputSnapshot.iterateChangesSince(previousInputSnapshot) >> changeIterator
+ 4 * changeIterator.next(_ as ChangeListener) >> { ChangeListener listener ->
+ listener.added("one")
+ true
+ } >> { ChangeListener listener ->
+ listener.removed("two")
+ true
+ } >> { ChangeListener listener ->
+ listener.changed("three")
+ true
+ } >> false
+
+ and:
+ messages == ["Input file one has been added.", "Input file two has been removed.", "Input file three has changed."]
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/rules/OutputFilesStateChangeRuleTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/rules/OutputFilesStateChangeRuleTest.groovy
new file mode 100644
index 0000000..cbcfe75
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/rules/OutputFilesStateChangeRuleTest.groovy
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.rules
+
+import org.gradle.api.internal.TaskInternal
+import org.gradle.api.internal.TaskOutputsInternal
+import org.gradle.api.internal.changedetection.state.FileCollectionSnapshot
+import org.gradle.api.internal.changedetection.state.FileSnapshotter
+import org.gradle.api.internal.changedetection.state.TaskExecution
+import org.gradle.api.internal.file.collections.SimpleFileCollection
+import org.gradle.util.ChangeListener
+import spock.lang.Specification;
+
+public class OutputFilesStateChangeRuleTest extends Specification {
+ def outputSnapshot = Mock(FileCollectionSnapshot)
+ def previousOutputSnapshot = Mock(FileCollectionSnapshot)
+
+ TaskStateChanges createStateChanges() {
+ def taskOutputs = Stub(TaskOutputsInternal) {
+ getFiles() >> new SimpleFileCollection()
+ }
+ def task = Stub(TaskInternal) {
+ getOutputs() >> taskOutputs
+ }
+ def snapshotter = Stub(FileSnapshotter) {
+ snapshot(_) >> outputSnapshot
+ }
+
+ def previousExecution = Stub(TaskExecution) {
+ getOutputFilesSnapshot() >> previousOutputSnapshot
+ }
+ return OutputFilesStateChangeRule.create(task, previousExecution, Mock(TaskExecution), snapshotter)
+ }
+
+ def "emits change for no previous output snapshot"() {
+ when:
+ previousOutputSnapshot = null
+ def it = createStateChanges().iterator()
+
+ then:
+ it.hasNext()
+ it.next().message == "Output file history is not available."
+ !it.hasNext()
+ }
+
+ def "emits change for file changes since previous output snapshot"() {
+ FileCollectionSnapshot.ChangeIterator<String> changeIterator = Mock()
+ when:
+ def it = createStateChanges().iterator()
+ def messages = it.collect {it.message}
+
+ then:
+ 1 * outputSnapshot.iterateChangesSince(previousOutputSnapshot) >> changeIterator
+ 4 * changeIterator.next(_ as ChangeListener<String>) >> { ChangeListener listener ->
+ listener.added("one")
+ true
+ } >> { ChangeListener listener ->
+ listener.removed("two")
+ true
+ } >> { ChangeListener listener ->
+ listener.changed("three")
+ true
+ } >> false
+
+ and:
+ messages == ["Output file one has been added.", "Output file two has been removed.", "Output file three has changed."]
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/rules/SimpleTaskStateChangesTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/rules/SimpleTaskStateChangesTest.groovy
new file mode 100644
index 0000000..5c89d6f
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/rules/SimpleTaskStateChangesTest.groovy
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.rules
+
+import spock.lang.Specification;
+
+public class SimpleTaskStateChangesTest extends Specification {
+ def simpleTaskStateChanges = new TestSimpleTaskStateChanges()
+ def change1 = Mock(TaskStateChange)
+ def change2 = Mock(TaskStateChange)
+
+ def "fires all changes"() {
+ when:
+ final iterator = simpleTaskStateChanges.iterator()
+
+ then:
+ iterator.hasNext()
+ iterator.next() == change1
+ iterator.hasNext()
+ iterator.next() == change2
+ }
+
+ def "caches all changes"() {
+ when:
+ simpleTaskStateChanges.iterator().next()
+ simpleTaskStateChanges.iterator().next()
+
+ then:
+ simpleTaskStateChanges.addAllCount == 1
+ }
+
+ private class TestSimpleTaskStateChanges extends SimpleTaskStateChanges {
+ int addAllCount;
+ @Override
+ protected void addAllChanges(List<TaskStateChange> changes) {
+ changes.addAll([change1, change2])
+ addAllCount++
+ }
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/rules/SummaryTaskStateChangesTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/rules/SummaryTaskStateChangesTest.groovy
new file mode 100644
index 0000000..1fb1171
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/rules/SummaryTaskStateChangesTest.groovy
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.rules
+
+import spock.lang.Specification
+
+class SummaryTaskStateChangesTest extends Specification {
+
+ def state1 = Mock(TaskStateChanges)
+ def state2 = Mock(TaskStateChanges)
+ def state = new SummaryTaskStateChanges(2, state1, state2)
+ def change = Mock(TaskStateChange)
+
+ def looksForChangesInAllDelegateChangeSets() {
+ when:
+ def hasNext = state.iterator().hasNext()
+
+ then:
+ 1 * state1.iterator() >> [].iterator()
+ 1 * state2.iterator() >> [].iterator()
+ 0 * _
+
+ and:
+ !hasNext
+ }
+
+ def delegatesSnapshotToAllDelegateChangeSets() {
+ when:
+ state.snapshotAfterTask()
+
+ then:
+ 1 * state1.snapshotAfterTask()
+ 1 * state2.snapshotAfterTask()
+ 0 * _
+ }
+
+ def onlyReturnsChangesFromASingleDelegate() {
+ def change1 = Mock(TaskStateChange)
+
+ when:
+ def it = state.iterator()
+ it.hasNext()
+
+ then:
+ 1 * state1.iterator() >> [change1].iterator()
+ 0 * _
+
+ and:
+ it.hasNext()
+ it.next() == change1
+ !it.hasNext()
+ }
+
+ def willNotEmitMoreChangesThanSpecified() {
+ def change1 = Mock(TaskStateChange)
+ def change2 = Mock(TaskStateChange)
+ def change3 = Mock(TaskStateChange)
+
+ when:
+ def it = state.iterator()
+ it.hasNext()
+
+ then:
+ 1 * state1.iterator() >> [].iterator()
+ 1 * state2.iterator() >> [change1, change2, change3].iterator()
+
+ and:
+ it.hasNext()
+ it.next() == change1
+ it.hasNext()
+ it.next() == change2
+ !it.hasNext()
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/state/CacheBackedFileSnapshotRepositoryTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/state/CacheBackedFileSnapshotRepositoryTest.groovy
new file mode 100644
index 0000000..0627bb8
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/state/CacheBackedFileSnapshotRepositoryTest.groovy
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.state
+
+import org.gradle.cache.PersistentIndexedCache
+import org.gradle.internal.id.IdGenerator
+import spock.lang.Specification
+
+class CacheBackedFileSnapshotRepositoryTest extends Specification {
+ final TaskArtifactStateCacheAccess cacheAccess = Mock()
+ final PersistentIndexedCache<Object, Object> indexedCache = Mock()
+ final IdGenerator<Long> idGenerator = Mock()
+ FileSnapshotRepository repository
+
+ def setup() {
+ 1 * cacheAccess.createCache("fileSnapshots", _, _, _) >> indexedCache
+ repository = new CacheBackedFileSnapshotRepository(cacheAccess, idGenerator)
+ }
+
+ def "assigns an id when a snapshot is added"() {
+ FileCollectionSnapshot snapshot = Mock()
+
+ when:
+ def id = repository.add(snapshot)
+
+ then:
+ id == 15
+ 1 * idGenerator.generateId() >> 15L
+ 1 * indexedCache.put(15, snapshot)
+ 0 * _._
+ }
+
+ def "can fetch a snapshot by id"() {
+ FileCollectionSnapshot snapshot = Mock()
+
+ when:
+ def result = repository.get(4)
+
+ then:
+ result == snapshot
+ 1 * indexedCache.get(4) >> snapshot
+ 0 * _._
+ }
+
+ def "can delete a snapshot by id"() {
+ when:
+ repository.remove(4)
+
+ then:
+ 1 * indexedCache.remove(4)
+ 0 * _._
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/state/CachingHasherTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/state/CachingHasherTest.java
new file mode 100644
index 0000000..b44c277
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/state/CachingHasherTest.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.state;
+
+import org.gradle.cache.PersistentIndexedCache;
+import org.gradle.messaging.serialize.Serializer;
+import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider;
+import org.jmock.Expectations;
+import org.jmock.integration.junit4.JMock;
+import org.jmock.integration.junit4.JUnit4Mockery;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+
+import static org.gradle.util.Matchers.reflectionEquals;
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.assertThat;
+
+ at RunWith(JMock.class)
+public class CachingHasherTest {
+ @Rule
+ TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider();
+ private final JUnit4Mockery context = new JUnit4Mockery();
+ private final Hasher delegate = context.mock(Hasher.class);
+ private final PersistentIndexedCache<File, CachingHasher.FileInfo> cache = context.mock(
+ PersistentIndexedCache.class);
+ private final TaskArtifactStateCacheAccess cacheAccess = context.mock(TaskArtifactStateCacheAccess.class);
+ private final byte[] hash = "hash".getBytes();
+ private final File file = tmpDir.createFile("testfile").write("content");
+ private CachingHasher hasher;
+
+ @Before
+ public void setup() {
+ context.checking(new Expectations(){{
+ one(cacheAccess).createCache(with(equalTo("fileHashes")), with(equalTo(File.class)), with(notNullValue(Class.class)), with(notNullValue(Serializer.class)));
+ will(returnValue(cache));
+ }});
+ hasher = new CachingHasher(delegate, cacheAccess);
+ }
+
+ @Test
+ public void hashesFileWhenHashNotCached() {
+ context.checking(new Expectations() {{
+ one(cache).get(file);
+ will(returnValue(null));
+ one(delegate).hash(file);
+ will(returnValue(hash));
+ one(cache).put(with(equalTo(file)), with(reflectionEquals(new CachingHasher.FileInfo(hash, file.length(),
+ file.lastModified()))));
+ }});
+
+ assertThat(hasher.hash(file), sameInstance(hash));
+ }
+
+ @Test
+ public void hashesFileWhenLengthHasChanged() {
+ context.checking(new Expectations() {{
+ one(cache).get(file);
+ will(returnValue(new CachingHasher.FileInfo(hash, 1078, file.lastModified())));
+ one(delegate).hash(file);
+ will(returnValue(hash));
+ one(cache).put(with(equalTo(file)), with(reflectionEquals(new CachingHasher.FileInfo(hash, file.length(),
+ file.lastModified()))));
+ }});
+
+ assertThat(hasher.hash(file), sameInstance(hash));
+ }
+
+ @Test
+ public void hashesFileWhenTimestampHasChanged() {
+ context.checking(new Expectations() {{
+ one(cache).get(file);
+ will(returnValue(new CachingHasher.FileInfo(hash, file.length(), 12)));
+ one(delegate).hash(file);
+ will(returnValue(hash));
+ one(cache).put(with(equalTo(file)), with(reflectionEquals(new CachingHasher.FileInfo(hash, file.length(),
+ file.lastModified()))));
+ }});
+
+ assertThat(hasher.hash(file), sameInstance(hash));
+ }
+
+ @Test
+ public void doesNotHashFileWhenTimestampAndLengthHaveNotChanged() {
+ context.checking(new Expectations() {{
+ one(cache).get(file);
+ will(returnValue(new CachingHasher.FileInfo(hash, file.length(), file.lastModified())));
+ }});
+
+ assertThat(hasher.hash(file), sameInstance(hash));
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/state/DefaultFileSnapshotterSerializerTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/state/DefaultFileSnapshotterSerializerTest.groovy
new file mode 100644
index 0000000..c7779e5
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/state/DefaultFileSnapshotterSerializerTest.groovy
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.state
+
+import org.gradle.messaging.serialize.SerializerSpec
+
+class DefaultFileSnapshotterSerializerTest extends SerializerSpec {
+
+ def serializer = new DefaultFileSnapshotterSerializer()
+
+ def "reads and writes the snapshot"() {
+ when:
+ DefaultFileSnapshotter.FileCollectionSnapshotImpl out = serialize(new DefaultFileSnapshotter.FileCollectionSnapshotImpl([
+ "1": new DefaultFileSnapshotter.DirSnapshot(),
+ "2": new DefaultFileSnapshotter.MissingFileSnapshot(),
+ "3": new DefaultFileSnapshotter.FileHashSnapshot("foo".bytes)]), serializer)
+
+ then:
+ out.snapshots.size() == 3
+ out.snapshots['1'] instanceof DefaultFileSnapshotter.DirSnapshot
+ out.snapshots['2'] instanceof DefaultFileSnapshotter.MissingFileSnapshot
+ ((DefaultFileSnapshotter.FileHashSnapshot) out.snapshots['3']).hash == "foo".bytes
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/state/DefaultFileSnapshotterTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/state/DefaultFileSnapshotterTest.groovy
new file mode 100755
index 0000000..170868d
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/state/DefaultFileSnapshotterTest.groovy
@@ -0,0 +1,346 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.state
+
+import org.gradle.api.file.FileCollection
+import org.gradle.api.file.FileTree
+import org.gradle.test.fixtures.file.TestFile
+import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
+import org.gradle.util.ChangeListener
+import org.junit.Rule
+import spock.lang.Specification
+
+public class DefaultFileSnapshotterTest extends Specification {
+ def hasher = new DefaultHasher()
+ def cacheAccess = Stub(TaskArtifactStateCacheAccess)
+ def snapshotter = new DefaultFileSnapshotter(hasher, cacheAccess)
+
+ def listener = Mock(ChangeListener)
+ @Rule
+ public final TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider()
+
+ def setup() {
+ cacheAccess.useCache(_, _) >> { args ->
+ args[1].run()
+ }
+ }
+
+ def getFilesReturnsOnlyTheFilesWhichExisted() {
+ given:
+ TestFile file = tmpDir.createFile('file1')
+ TestFile dir = tmpDir.createDir('file2')
+ TestFile noExist = tmpDir.file('file3')
+
+ when:
+ def snapshot = snapshotter.snapshot(files(file, dir, noExist))
+
+ then:
+ snapshot.files.files as List == [file]
+ }
+
+ def notifiesListenerWhenFileAdded() {
+ given:
+ TestFile file1 = tmpDir.createFile('file1')
+ TestFile file2 = tmpDir.createFile('file2')
+
+ when:
+ def snapshot = snapshotter.snapshot(files(file1))
+ snapshotter.snapshot(files(file1, file2)).iterateChangesSince(snapshot).next(listener)
+
+ then:
+ 1 * listener.added(file2.path)
+ 0 * _
+ }
+
+ def notifiesListenerWhenFileRemoved() {
+ given:
+ TestFile file1 = tmpDir.createFile('file1')
+ TestFile file2 = tmpDir.createFile('file2')
+
+ when:
+ FileCollectionSnapshot snapshot = snapshotter.snapshot(files(file1, file2))
+ snapshotter.snapshot(files(file1)).iterateChangesSince(snapshot).next(listener)
+
+ then:
+ 1 * listener.removed(file2.path)
+ 0 * _
+ }
+
+ def fileHasNotChangedWhenTypeAndHashHaveNotChanged() {
+ given:
+ TestFile file = tmpDir.createFile('file')
+
+ when:
+ FileCollectionSnapshot snapshot = snapshotter.snapshot(files(file))
+ snapshotter.snapshot(files(file)).iterateChangesSince(snapshot).next(listener)
+
+ then:
+ _ * listener.stopped >> false
+ _ * listener.resumeAfter >> null
+ 0 * listener._
+ }
+
+ def fileHasChangedWhenTypeHasChanged() {
+ given:
+ TestFile file = tmpDir.createFile('file')
+
+ when:
+ FileCollectionSnapshot snapshot = snapshotter.snapshot(files(file))
+ file.delete()
+ file.createDir()
+ snapshotter.snapshot(files(file)).iterateChangesSince(snapshot).next(listener)
+
+ then:
+ 1 * listener.changed(file.path)
+
+ and:
+ _ * listener.stopped >> false
+ _ * listener.resumeAfter >> null
+ 0 * _
+ }
+
+ def fileHasChangedWhenHashHasChanged() {
+ TestFile file = tmpDir.createFile('file')
+
+ when:
+ FileCollectionSnapshot snapshot = snapshotter.snapshot(files(file))
+ file.write('new content')
+ snapshotter.snapshot(files(file)).iterateChangesSince(snapshot).next(listener)
+
+ then:
+ 1 * listener.changed(file.path)
+
+ and:
+ _ * listener.stopped >> false
+ _ * listener.resumeAfter >> null
+ 0 * _
+ }
+
+ def directoryHasNotChangedWhenTypeHasNotChanged() {
+ TestFile dir = tmpDir.createDir('dir')
+
+ when:
+ FileCollectionSnapshot snapshot = snapshotter.snapshot(files(dir))
+
+ snapshotter.snapshot(files(dir)).iterateChangesSince(snapshot).next(listener)
+
+ then:
+ _ * listener.stopped >> false
+ _ * listener.resumeAfter >> null
+ 0 * _
+ }
+
+ def directoryHasChangedWhenTypeHasChanged() {
+ TestFile dir = tmpDir.createDir('dir')
+
+ when:
+ FileCollectionSnapshot snapshot = snapshotter.snapshot(files(dir))
+ dir.deleteDir()
+ dir.createFile()
+ snapshotter.snapshot(files(dir)).iterateChangesSince(snapshot).next(listener)
+
+ then:
+ 1 * listener.changed(dir.path)
+ }
+
+ def nonExistentFileUnchangedWhenTypeHasNotChanged() {
+ TestFile file = tmpDir.file('unknown')
+
+ when:
+ FileCollectionSnapshot snapshot = snapshotter.snapshot(files(file))
+ snapshotter.snapshot(files(file)).iterateChangesSince(snapshot).next(listener)
+
+ then:
+ _ * listener.stopped >> false
+ _ * listener.resumeAfter >> null
+ 0 * _
+ }
+
+ def nonExistentFileIsChangedWhenTypeHasChanged() {
+ TestFile file = tmpDir.file('unknown')
+
+ when:
+ FileCollectionSnapshot snapshot = snapshotter.snapshot(files(file))
+ file.createFile()
+ snapshotter.snapshot(files(file)).iterateChangesSince(snapshot).next(listener)
+
+ then:
+ 1 * listener.changed(file.path)
+ }
+
+ def ignoresDuplicatesInFileCollection() {
+ TestFile file1 = tmpDir.createFile('file')
+ TestFile file2 = tmpDir.createFile('file')
+
+ when:
+ FileCollectionSnapshot snapshot = snapshotter.snapshot(files(file1, file2))
+ snapshotter.snapshot(files(file1)).iterateChangesSince(snapshot).next(listener)
+
+ then:
+ _ * listener.stopped >> false
+ _ * listener.resumeAfter >> null
+ 0 * _
+ }
+
+ def canCreateEmptySnapshot() {
+ TestFile file = tmpDir.createFile('file')
+
+ when:
+ FileCollectionSnapshot snapshot = snapshotter.emptySnapshot()
+ FileCollectionSnapshot newSnapshot = snapshotter.snapshot(files(file))
+ newSnapshot.iterateChangesSince(snapshot).next(listener)
+
+ then:
+ 1 * listener.added(file.path)
+ }
+
+ def diffAddsAddedFilesToSnapshot() {
+ TestFile file = tmpDir.createFile('file')
+
+ given:
+ ChangeListener<FileCollectionSnapshot.Merge> mergeListener = Mock(ChangeListener.class)
+
+ FileCollectionSnapshot original = snapshotter.emptySnapshot()
+ FileCollectionSnapshot modified = snapshotter.snapshot(files(file))
+
+ when:
+ FileCollectionSnapshot target = modified.changesSince(original).applyTo(snapshotter.emptySnapshot(), mergeListener)
+
+ then:
+ 1 * mergeListener.added(_)
+
+ when:
+ target.iterateChangesSince(original).next(listener)
+
+ then:
+ 1 * listener.added(file.path)
+ }
+
+ def canIgnoreAddedFileInDiff() {
+ TestFile file = tmpDir.createFile('file')
+
+ ChangeListener<FileCollectionSnapshot.Merge> mergeListener = Mock(ChangeListener.class)
+ FileCollectionSnapshot original = snapshotter.emptySnapshot()
+ FileCollectionSnapshot modified = snapshotter.snapshot(files(file))
+
+ when:
+ FileCollectionSnapshot target = modified.changesSince(original).applyTo(snapshotter.emptySnapshot(), mergeListener)
+ target.iterateChangesSince(original).next(listener)
+
+ then:
+ mergeListener.added(!null) >> { FileCollectionSnapshot.Merge merge -> merge.ignore() }
+ }
+
+ def diffAddsChangedFilesToSnapshot() {
+ TestFile file = tmpDir.createFile('file')
+
+ ChangeListener<FileCollectionSnapshot.Merge> mergeListener = Mock(ChangeListener.class)
+
+ FileCollectionSnapshot original = snapshotter.snapshot(files(file))
+ file.write('new content')
+ FileCollectionSnapshot modified = snapshotter.snapshot(files(file))
+
+ when:
+ FileCollectionSnapshot target = modified.changesSince(original).applyTo(snapshotter.emptySnapshot(), mergeListener)
+
+ then:
+ 1 * mergeListener.changed(!null)
+
+ when:
+ target.iterateChangesSince(original).next(listener)
+
+ then:
+ 1 * listener.changed(file.path)
+ }
+
+ def canIgnoreChangedFileInDiff() {
+ TestFile file = tmpDir.createFile('file')
+ ChangeListener<FileCollectionSnapshot.Merge> mergeListener = Mock(ChangeListener.class)
+
+ when:
+ FileCollectionSnapshot original = snapshotter.snapshot(files(file))
+ FileCollectionSnapshot target = snapshotter.snapshot(files(file))
+ file.write('new content')
+ FileCollectionSnapshot modified = snapshotter.snapshot(files(file))
+
+ and:
+ target = modified.changesSince(original).applyTo(target, mergeListener)
+ target.iterateChangesSince(original).next(listener)
+
+ then:
+ 1 * mergeListener.changed(!null) >> { FileCollectionSnapshot.Merge merge -> merge.ignore() }
+ }
+
+ def diffRemovesDeletedFilesFromSnapshot() {
+ TestFile file = tmpDir.createFile('file')
+ ChangeListener<FileCollectionSnapshot.Merge> mergeListener = Mock(ChangeListener.class)
+
+ when:
+ FileCollectionSnapshot original = snapshotter.snapshot(files(file))
+ FileCollectionSnapshot modified = snapshotter.emptySnapshot()
+
+ FileCollectionSnapshot target = modified.changesSince(original).applyTo(snapshotter.snapshot(files(file)), mergeListener)
+
+ then:
+ 1 * mergeListener.removed(!null)
+
+ when:
+ target.iterateChangesSince(original).next(listener)
+
+ then:
+ 1 * listener.removed(file.path)
+ }
+
+ def canIgnoreRemovedFileInDiff() {
+ TestFile file = tmpDir.createFile('file')
+ ChangeListener<FileCollectionSnapshot.Merge> mergeListener = Mock(ChangeListener.class)
+
+ when:
+ FileCollectionSnapshot original = snapshotter.snapshot(files(file))
+ FileCollectionSnapshot modified = snapshotter.emptySnapshot()
+ FileCollectionSnapshot target = modified.changesSince(original).applyTo(snapshotter.snapshot(files(file)), mergeListener)
+
+ target.iterateChangesSince(original).next(listener)
+
+ then:
+ mergeListener.removed(!null) >> { FileCollectionSnapshot.Merge merge -> merge.ignore() }
+ }
+
+ def diffIgnoresUnchangedFilesInSnapshot() {
+ TestFile file = tmpDir.createFile('file')
+ ChangeListener<FileCollectionSnapshot.Merge> mergeListener = Mock(ChangeListener.class)
+
+ when:
+ FileCollectionSnapshot original = snapshotter.snapshot(files(file))
+ FileCollectionSnapshot modified = snapshotter.snapshot(files(file))
+ FileCollectionSnapshot target = modified.changesSince(original).applyTo(snapshotter.emptySnapshot(), mergeListener)
+
+ target.iterateChangesSince(snapshotter.emptySnapshot()).next(listener)
+
+ then:
+ _ * listener.stopped >> false
+ _ * listener.resumeAfter >> null
+ 0 * _
+ }
+
+ private FileCollection files(File... files) {
+ FileTree collection = Mock(FileTree.class)
+ _ * collection.asFileTree >> collection
+ _ * collection.getFiles() >> files
+ return collection
+ }
+
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/state/DefaultTaskArtifactStateCacheAccessTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/state/DefaultTaskArtifactStateCacheAccessTest.groovy
new file mode 100644
index 0000000..390150c
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/state/DefaultTaskArtifactStateCacheAccessTest.groovy
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.state
+
+import org.gradle.api.internal.GradleInternal
+import org.gradle.cache.CacheRepository
+import org.gradle.cache.DirectoryCacheBuilder
+import org.gradle.cache.PersistentCache
+import org.gradle.cache.PersistentIndexedCache
+import org.gradle.messaging.serialize.DefaultSerializer
+import spock.lang.Specification
+
+class DefaultTaskArtifactStateCacheAccessTest extends Specification {
+ final GradleInternal gradle = Mock()
+ final CacheRepository cacheRepository = Mock()
+ final DefaultTaskArtifactStateCacheAccess cacheAccess = new DefaultTaskArtifactStateCacheAccess(gradle, cacheRepository)
+
+ def "opens backing cache on first use"() {
+ DirectoryCacheBuilder cacheBuilder = Mock()
+ PersistentCache backingCache = Mock()
+ PersistentIndexedCache<String, Integer> backingIndexedCache = Mock()
+
+ def serializer = new DefaultSerializer<Integer>()
+ when:
+ def indexedCache = cacheAccess.createCache("some-cache", String, Integer, serializer)
+
+ then:
+ 0 * _._
+
+ when:
+ indexedCache.get("key")
+
+ then:
+ 1 * cacheRepository.cache("taskArtifacts") >> cacheBuilder
+ 1 * cacheBuilder.open() >> backingCache
+ _ * cacheBuilder._ >> cacheBuilder
+ _ * backingCache.baseDir >> new File("baseDir")
+ 1 * backingCache.createCache(new File("baseDir/some-cache.bin"), String, serializer) >> backingIndexedCache
+ 1 * backingIndexedCache.get("key")
+ 0 * _._
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/state/FileSnapshotSerializerTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/state/FileSnapshotSerializerTest.groovy
new file mode 100644
index 0000000..7f264d0
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/state/FileSnapshotSerializerTest.groovy
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.state
+
+import org.gradle.messaging.serialize.SerializerSpec
+
+class FileSnapshotSerializerTest extends SerializerSpec {
+
+ def snapshot = new DefaultFileSnapshotter.FileCollectionSnapshotImpl(["hey": new DefaultFileSnapshotter.DirSnapshot()])
+ def outputSnapshot = new OutputFilesSnapshotter.OutputFilesSnapshot(["foo": 1L, "bar": 2L], snapshot)
+
+ def "handles default snapshots"() {
+ when:
+ DefaultFileSnapshotter.FileCollectionSnapshotImpl out = serialize(snapshot, new FileSnapshotSerializer())
+
+ then:
+ out.snapshots.size() == 1
+ out.snapshots['hey'] instanceof DefaultFileSnapshotter.DirSnapshot
+ }
+
+ def "handles output snapshots"() {
+ when:
+ OutputFilesSnapshotter.OutputFilesSnapshot out = serialize(outputSnapshot, new FileSnapshotSerializer())
+
+ then:
+ out.rootFileIds == ["foo": 1L, "bar": 2L]
+ DefaultFileSnapshotter.FileCollectionSnapshotImpl filesSnapshot = out.filesSnapshot
+ filesSnapshot.snapshots.size() == 1
+ filesSnapshot.snapshots['hey'] instanceof DefaultFileSnapshotter.DirSnapshot
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/state/OutputFilesSnapshotSerializerTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/state/OutputFilesSnapshotSerializerTest.groovy
new file mode 100644
index 0000000..7c4e2db
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/changedetection/state/OutputFilesSnapshotSerializerTest.groovy
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.changedetection.state
+
+import org.gradle.messaging.serialize.SerializerSpec
+
+class OutputFilesSnapshotSerializerTest extends SerializerSpec {
+
+ def serializer = new OutputFilesSnapshotSerializer()
+
+ def "reads and writes the snapshot"() {
+ def snapshot = new DefaultFileSnapshotter.FileCollectionSnapshotImpl(["1": new DefaultFileSnapshotter.DirSnapshot()])
+ def outputSnapshot = new OutputFilesSnapshotter.OutputFilesSnapshot(["x": 14L], snapshot)
+
+ when:
+ OutputFilesSnapshotter.OutputFilesSnapshot out = serialize(outputSnapshot, serializer)
+
+ then:
+ ((DefaultFileSnapshotter.FileCollectionSnapshotImpl)out.filesSnapshot).snapshots.size() == 1
+ out.rootFileIds == ['x': 14L]
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/coerce/TypeCoercingMethodArgumentsTransformerTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/coerce/TypeCoercingMethodArgumentsTransformerTest.groovy
new file mode 100644
index 0000000..50e39f6
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/coerce/TypeCoercingMethodArgumentsTransformerTest.groovy
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.coerce
+
+import spock.lang.Specification
+import spock.lang.Unroll
+
+ at SuppressWarnings("GroovyUnusedDeclaration")
+class TypeCoercingMethodArgumentsTransformerTest extends Specification {
+
+ def transformer = new TypeCoercingMethodArgumentsTransformer()
+
+ static enum TestEnum {
+ ABC, DEF
+ }
+
+ static class EnumTester {
+ TestEnum enumProperty
+
+ void oneArgEnumMethod(TestEnum testEnum) {}
+
+ void twoArgEnumMethod(TestEnum testEnum, String other) {}
+
+ void oneArgNonEnumMethod(String other) {}
+ }
+
+ @Unroll
+ def "can enum transform correctly - #desc"() {
+ def i = new EnumTester()
+
+ expect:
+ transformer.transform(i, name, args.toArray()).toList() == transformed
+
+ where:
+ name | args | transformed | desc
+ "setEnumProperty" | ["abc"] | [TestEnum.ABC] | "for property"
+ "oneArgEnumMethod" | ["dEf"] | [TestEnum.DEF] | "one arg method"
+ "twoArgEnumMethod" | ["abc"] | ["abc"] | "two arg method"
+ "oneArgNonEnumMethod" | ["abc"] | ["abc"] | "one arg method non enum method"
+ }
+
+ def "exception thrown when coercing invalid string to enum"() {
+ def i = new EnumTester()
+
+ when:
+ transformer.transform(i, "oneArgEnumMethod", "invalid")
+
+ then:
+ def e = thrown TypeCoercionException
+ e.message.contains TestEnum.values().toString() // error message shows valid values
+ }
+
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/AbstractFileCollectionTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/AbstractFileCollectionTest.java
index 564d959..b0ca056 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/AbstractFileCollectionTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/AbstractFileCollectionTest.java
@@ -25,7 +25,7 @@ import org.gradle.api.tasks.TaskDependency;
import org.gradle.test.fixtures.file.TestFile;
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider;
import org.gradle.util.GUtil;
-import org.gradle.util.HelperUtil;
+import org.gradle.util.TestUtil;
import org.gradle.util.JUnit4GroovyMockery;
import org.jmock.Expectations;
import org.jmock.integration.junit4.JMock;
@@ -275,7 +275,7 @@ public class AbstractFileCollectionTest {
File file2 = new File("f2");
TestFileCollection collection = new TestFileCollection(file1, file2);
- FileCollection filtered = collection.filter(HelperUtil.toClosure("{f -> f.name == 'f1'}"));
+ FileCollection filtered = collection.filter(TestUtil.toClosure("{f -> f.name == 'f1'}"));
assertThat(filtered.getFiles(), equalTo(toSet(file1)));
}
@@ -286,7 +286,7 @@ public class AbstractFileCollectionTest {
File file3 = new File("dir/f1");
TestFileCollection collection = new TestFileCollection(file1, file2);
- FileCollection filtered = collection.filter(HelperUtil.toClosure("{f -> f.name == 'f1'}"));
+ FileCollection filtered = collection.filter(TestUtil.toClosure("{f -> f.name == 'f1'}"));
assertThat(filtered.getFiles(), equalTo(toSet(file1)));
collection.files.add(file3);
@@ -304,14 +304,14 @@ public class AbstractFileCollectionTest {
collection.files.add(new File("f1"));
assertHasSameDependencies(collection.getAsFileTree());
- assertHasSameDependencies(collection.getAsFileTree().matching(HelperUtil.TEST_CLOSURE));
+ assertHasSameDependencies(collection.getAsFileTree().matching(TestUtil.TEST_CLOSURE));
}
@Test
public void filteredCollectionHasSameDependenciesAsThis() {
TestFileCollectionWithDependency collection = new TestFileCollectionWithDependency();
- assertHasSameDependencies(collection.filter(HelperUtil.toClosure("{true}")));
+ assertHasSameDependencies(collection.filter(TestUtil.toClosure("{true}")));
}
private void assertHasSameDependencies(FileCollection tree) {
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/BaseDirFileResolverTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/BaseDirFileResolverTest.groovy
index 10115b1..aa838ce 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/BaseDirFileResolverTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/BaseDirFileResolverTest.groovy
@@ -33,9 +33,6 @@ import java.util.concurrent.Callable
import static org.hamcrest.Matchers.*
import static org.junit.Assert.*
-/**
- * @author Hans Dockter
- */
class BaseDirFileResolverTest {
static final String TEST_PATH = 'testpath'
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/CompositeFileCollectionTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/CompositeFileCollectionTest.java
index e0382ca..1ce86c3 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/CompositeFileCollectionTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/CompositeFileCollectionTest.java
@@ -21,7 +21,7 @@ import org.gradle.api.file.FileTree;
import org.gradle.api.internal.file.collections.*;
import org.gradle.api.specs.Spec;
import org.gradle.api.tasks.TaskDependency;
-import org.gradle.util.HelperUtil;
+import org.gradle.util.TestUtil;
import org.gradle.util.JUnit4GroovyMockery;
import org.jmock.Expectations;
import org.jmock.integration.junit4.JMock;
@@ -266,12 +266,12 @@ public class CompositeFileCollectionTest {
@Test
public void fileTreeDependsOnUnionOfAllDependencies() {
assertDependsOnUnionOfSourceCollections(collection.getAsFileTree());
- assertDependsOnUnionOfSourceCollections(collection.getAsFileTree().matching(HelperUtil.TEST_CLOSURE));
+ assertDependsOnUnionOfSourceCollections(collection.getAsFileTree().matching(TestUtil.TEST_CLOSURE));
}
@Test
public void filteredCollectionDependsOnUnionOfAllDependencies() {
- assertDependsOnUnionOfSourceCollections(collection.filter(HelperUtil.TEST_CLOSURE));
+ assertDependsOnUnionOfSourceCollections(collection.filter(TestUtil.TEST_CLOSURE));
}
private void assertDependsOnUnionOfSourceCollections(FileCollection collection) {
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/CompositeFileTreeTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/CompositeFileTreeTest.java
index 5bf5d8c..057e82b 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/CompositeFileTreeTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/CompositeFileTreeTest.java
@@ -20,7 +20,7 @@ import org.gradle.api.file.FileTree;
import org.gradle.api.file.FileVisitor;
import org.gradle.api.internal.file.collections.FileCollectionResolveContext;
import org.gradle.api.tasks.util.PatternSet;
-import org.gradle.util.HelperUtil;
+import org.gradle.util.TestUtil;
import static org.gradle.util.WrapUtil.*;
import static org.hamcrest.Matchers.*;
@@ -52,7 +52,7 @@ public class CompositeFileTreeTest {
@Test
public void matchingWithClosureReturnsUnionOfFilteredSets() {
- final Closure closure = HelperUtil.TEST_CLOSURE;
+ final Closure closure = TestUtil.TEST_CLOSURE;
final FileTree filtered1 = context.mock(FileTree.class);
final FileTree filtered2 = context.mock(FileTree.class);
@@ -114,7 +114,7 @@ public class CompositeFileTreeTest {
@Test
public void visitsEachTreeWithClosure() {
- final Closure visitor = HelperUtil.TEST_CLOSURE;
+ final Closure visitor = TestUtil.TEST_CLOSURE;
context.checking(new Expectations() {{
one(source1).visit(visitor);
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/DefaultCompositeFileTreeTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/DefaultCompositeFileTreeTest.groovy
new file mode 100644
index 0000000..bb8175c
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/DefaultCompositeFileTreeTest.groovy
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.file
+
+import org.gradle.internal.nativeplatform.filesystem.FileSystems
+import org.gradle.test.fixtures.file.WorkspaceTest
+
+class DefaultCompositeFileTreeTest extends WorkspaceTest {
+
+ def "can be empty"() {
+ when:
+ def ft = new DefaultCompositeFileTree(Collections.emptyList())
+
+ then:
+ ft.files.isEmpty()
+ }
+
+ def "contains all files"() {
+ given:
+ def a1 = file("a/1.txt") << "a/1"
+ def b1 = file("b/1.txt") << "b/1"
+ def fileResolver = new BaseDirFileResolver(FileSystems.getDefault(), testDirectory)
+
+ when:
+ def a = fileResolver.resolveFilesAsTree("a")
+ def b = fileResolver.resolveFilesAsTree("b")
+ def composite = new DefaultCompositeFileTree(Arrays.asList(a, b))
+
+ then:
+ composite.files == [a1, b1].toSet()
+ }
+
+ def "can visit all files"() {
+ given:
+ def a1 = file("a/1.txt") << "a/1"
+ def b1 = file("b/1.txt") << "b/1"
+ def fileResolver = new BaseDirFileResolver(FileSystems.getDefault(), testDirectory)
+
+ when:
+ def a = fileResolver.resolveFilesAsTree("a")
+ def b = fileResolver.resolveFilesAsTree("b")
+ def composite = new DefaultCompositeFileTree(Arrays.asList(a, b))
+
+ and:
+ def visited = []
+ composite.visit {
+ visited << it.file
+ }
+
+ then:
+ visited.toSet() == [a1, b1].toSet()
+ }
+
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/DefaultFileOperationsTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/DefaultFileOperationsTest.groovy
index 43c5019..2acba65 100755
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/DefaultFileOperationsTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/DefaultFileOperationsTest.groovy
@@ -26,15 +26,16 @@ import org.gradle.api.internal.file.archive.TarFileTree
import org.gradle.api.internal.file.archive.ZipFileTree
import org.gradle.api.internal.file.collections.DefaultConfigurableFileCollection
import org.gradle.api.internal.file.collections.FileTreeAdapter
-import org.gradle.api.internal.file.copy.CopyActionImpl
-import org.gradle.api.internal.file.copy.CopySpecImpl
+import org.gradle.api.internal.file.copy.DefaultCopySpec
import org.gradle.api.internal.tasks.TaskResolver
import org.gradle.internal.os.OperatingSystem
+import org.gradle.internal.reflect.DirectInstantiator
+import org.gradle.internal.reflect.Instantiator
import org.gradle.process.ExecResult
import org.gradle.process.internal.ExecException
import org.gradle.test.fixtures.file.TestFile
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
-import org.gradle.util.ClasspathUtil
+import org.gradle.internal.classloader.ClasspathUtil
import org.junit.Rule
import org.junit.Test
import spock.lang.Specification
@@ -43,7 +44,8 @@ public class DefaultFileOperationsTest extends Specification {
private final FileResolver resolver = Mock()
private final TaskResolver taskResolver = Mock()
private final TemporaryFileProvider temporaryFileProvider = Mock()
- private DefaultFileOperations fileOperations = new DefaultFileOperations(resolver, taskResolver, temporaryFileProvider)
+ private final Instantiator instantiator = new DirectInstantiator()
+ private DefaultFileOperations fileOperations = new DefaultFileOperations(resolver, taskResolver, temporaryFileProvider, instantiator)
@Rule
public final TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider()
@@ -171,7 +173,6 @@ public class DefaultFileOperationsTest extends Specification {
def result = fileOperations.copy { from 'file'; into 'dir' }
then:
- result instanceof CopyActionImpl
!result.didWork
}
@@ -216,7 +217,7 @@ public class DefaultFileOperationsTest extends Specification {
def spec = fileOperations.copySpec { include 'pattern'}
then:
- spec instanceof CopySpecImpl
+ spec instanceof DefaultCopySpec
spec.includes == ['pattern'] as Set
}
@@ -240,7 +241,7 @@ public class DefaultFileOperationsTest extends Specification {
def javaexec() {
File testFile = tmpDir.file("someFile")
- fileOperations = new DefaultFileOperations(resolver(), taskResolver, temporaryFileProvider)
+ fileOperations = new DefaultFileOperations(resolver(), taskResolver, temporaryFileProvider, instantiator)
List files = ClasspathUtil.getClasspath(getClass().classLoader)
when:
@@ -256,7 +257,7 @@ public class DefaultFileOperationsTest extends Specification {
}
def javaexecWithNonZeroExitValueShouldThrowException() {
- fileOperations = new DefaultFileOperations(resolver(), taskResolver, temporaryFileProvider)
+ fileOperations = new DefaultFileOperations(resolver(), taskResolver, temporaryFileProvider, instantiator)
when:
fileOperations.javaexec {
@@ -268,7 +269,7 @@ public class DefaultFileOperationsTest extends Specification {
}
def javaexecWithNonZeroExitValueAndIgnoreExitValueShouldNotThrowException() {
- fileOperations = new DefaultFileOperations(resolver(), taskResolver, temporaryFileProvider)
+ fileOperations = new DefaultFileOperations(resolver(), taskResolver, temporaryFileProvider, instantiator)
when:
ExecResult result = fileOperations.javaexec {
@@ -285,7 +286,7 @@ public class DefaultFileOperationsTest extends Specification {
return
}
- fileOperations = new DefaultFileOperations(resolver(), taskResolver, temporaryFileProvider)
+ fileOperations = new DefaultFileOperations(resolver(), taskResolver, temporaryFileProvider, instantiator)
File testFile = tmpDir.file("someFile")
when:
@@ -304,7 +305,7 @@ public class DefaultFileOperationsTest extends Specification {
if (OperatingSystem.current().isWindows()) {
return
}
- fileOperations = new DefaultFileOperations(resolver(), taskResolver, temporaryFileProvider)
+ fileOperations = new DefaultFileOperations(resolver(), taskResolver, temporaryFileProvider, instantiator)
when:
fileOperations.exec {
@@ -321,7 +322,7 @@ public class DefaultFileOperationsTest extends Specification {
if (OperatingSystem.current().isWindows()) {
return
}
- fileOperations = new DefaultFileOperations(resolver(), taskResolver, temporaryFileProvider)
+ fileOperations = new DefaultFileOperations(resolver(), taskResolver, temporaryFileProvider, instantiator)
when:
ExecResult result = fileOperations.exec {
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/DelegatingFileCollectionTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/DelegatingFileCollectionTest.groovy
new file mode 100644
index 0000000..073e9fe
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/DelegatingFileCollectionTest.groovy
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.file
+
+import org.gradle.api.file.FileCollection
+import org.gradle.api.internal.file.collections.DelegatingFileCollection
+import org.gradle.api.internal.file.collections.MinimalFileSet
+import org.gradle.api.specs.Spec
+import org.gradle.api.specs.Specs
+
+import spock.lang.Specification
+
+class DelegatingFileCollectionTest extends Specification {
+ FileCollection delegatedTo = Mock()
+ DelegatingFileCollection fileCollection = new DelegatingFileCollection() {
+ @Override
+ FileCollection getDelegate() {
+ delegatedTo
+ }
+ }
+
+ File aFile = new File("foo")
+ FileCollection aCollection = Stub()
+ Object anObject = new Object()
+
+ def "delegates all method calls"() {
+ when:
+ fileCollection.with {
+ getSingleFile()
+ getFiles()
+ contains(aFile)
+ getAsPath()
+ plus(aCollection)
+ minus(aCollection)
+ filter({ true })
+ filter(Specs.satisfyAll())
+ delegate.asType(List) // avoid collision with DGM method
+ add(aCollection)
+ isEmpty()
+ stopExecutionIfEmpty()
+ getAsFileTree()
+ addToAntBuilder(anObject, "nodeName", FileCollection.AntType.MatchingTask)
+ addToAntBuilder(anObject, "nodeName")
+ getBuildDependencies()
+ delegate.iterator() // avoid collision with DGM method
+ }
+
+ then:
+ with(delegatedTo) {
+ 1 * getSingleFile()
+ 1 * getFiles()
+ 1 * contains({ it.is(aFile) })
+ 1 * getAsPath()
+ 1 * plus({ it.is(aCollection) })
+ 1 * minus({ it.is(aCollection) })
+ 1 * filter(_ as Closure)
+ 1 * filter(_ as Spec)
+ 1 * asType(List)
+ 1 * add({ it.is(aCollection) })
+ 1 * isEmpty()
+ 1 * stopExecutionIfEmpty()
+ 1 * getAsFileTree()
+ 1 * addToAntBuilder(anObject, "nodeName", FileCollection.AntType.MatchingTask)
+ 1 * addToAntBuilder(anObject, "nodeName")
+ 1 * getBuildDependencies()
+ 1 * iterator()
+ 0 * _
+ }
+ }
+
+ interface MyFileCollection extends FileCollection, MinimalFileSet {}
+
+ def "delegates getDisplayName() to toString() if delegate is not a MinimalFileSet"() {
+ when:
+ fileCollection.getDisplayName()
+
+ then:
+ 1 * delegatedTo.toString()
+
+ }
+
+ def "delegates getDisplayName() to getDisplayName() if delegate is a MinimalFileSet"() {
+ delegatedTo = Mock(MyFileCollection)
+
+ when:
+ fileCollection.getDisplayName()
+
+ then:
+ 1 * delegatedTo.getDisplayName()
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/LazilyInitializedFileCollectionTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/LazilyInitializedFileCollectionTest.groovy
new file mode 100644
index 0000000..c5734a2
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/LazilyInitializedFileCollectionTest.groovy
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.file
+
+import org.gradle.api.file.FileCollection
+import org.gradle.api.internal.file.collections.LazilyInitializedFileCollection
+import org.gradle.api.internal.file.collections.SimpleFileCollection
+
+import spock.lang.Specification
+
+class LazilyInitializedFileCollectionTest extends Specification {
+ def createCount = 0
+ def fileCollection = new LazilyInitializedFileCollection() {
+ @Override
+ FileCollection createDelegate() {
+ createCount++
+ new SimpleFileCollection([new File("foo")])
+ }
+ }
+
+ def "creates delegate on first access"() {
+ expect:
+ createCount == 0
+
+ when:
+ def files = fileCollection.files
+
+ then:
+ createCount == 1
+ files == [new File("foo")] as Set
+
+ when:
+ fileCollection.files
+
+ then:
+ createCount == 1
+ files == [new File("foo")] as Set
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/MaybeCompressedFileResourceTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/MaybeCompressedFileResourceTest.groovy
index c07f889..d3a886b 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/MaybeCompressedFileResourceTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/MaybeCompressedFileResourceTest.groovy
@@ -21,9 +21,6 @@ import org.gradle.api.internal.file.archive.compression.Bzip2Archiver
import org.gradle.api.internal.file.archive.compression.GzipArchiver
import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 11/24/11
- */
public class MaybeCompressedFileResourceTest extends Specification {
def "understands file extensions"() {
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/archive/TarCopyActionTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/archive/TarCopyActionTest.java
new file mode 100644
index 0000000..bdcead0
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/archive/TarCopyActionTest.java
@@ -0,0 +1,244 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.file.archive;
+
+import org.apache.commons.io.IOUtils;
+import org.gradle.api.GradleException;
+import org.gradle.api.file.RelativePath;
+import org.gradle.api.internal.file.CopyActionProcessingStreamAction;
+import org.gradle.api.internal.file.FileResource;
+import org.gradle.api.internal.file.archive.compression.ArchiveOutputStreamFactory;
+import org.gradle.api.internal.file.archive.compression.Bzip2Archiver;
+import org.gradle.api.internal.file.archive.compression.GzipArchiver;
+import org.gradle.api.internal.file.archive.compression.SimpleCompressor;
+import org.gradle.api.internal.file.copy.CopyActionProcessingStream;
+import org.gradle.api.internal.file.copy.FileCopyDetailsInternal;
+import org.gradle.test.fixtures.file.TestFile;
+import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider;
+import org.hamcrest.Description;
+import org.jmock.Expectations;
+import org.jmock.api.Invocation;
+import org.jmock.integration.junit4.JMock;
+import org.jmock.integration.junit4.JUnit4Mockery;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.OutputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.gradle.api.file.FileVisitorUtil.assertVisitsPermissions;
+import static org.gradle.api.internal.file.copy.CopyActionExecuterUtil.visit;
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+ at RunWith(JMock.class)
+public class TarCopyActionTest {
+ @Rule
+ public final TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider();
+ private final JUnit4Mockery context = new JUnit4Mockery();
+ private TarCopyAction action;
+
+
+ @Test
+ public void createsTarFile() {
+ final TestFile tarFile = initializeTarFile(tmpDir.getTestDirectory().file("test.tar"),
+ new SimpleCompressor());
+ tarAndUntarAndCheckFileContents(tarFile);
+ }
+
+ private void tarAndUntarAndCheckFileContents(TestFile tarFile) {
+ tar(file("dir/file1"), file("file2"));
+
+ TestFile expandDir = tmpDir.getTestDirectory().file("expanded");
+ tarFile.untarTo(expandDir);
+ expandDir.file("dir/file1").assertContents(equalTo("contents of dir/file1"));
+ expandDir.file("file2").assertContents(equalTo("contents of file2"));
+ }
+
+ @Test
+ public void createsGzipCompressedTarFile() {
+ final TestFile tarFile = initializeTarFile(tmpDir.getTestDirectory().file("test.tgz"),
+ GzipArchiver.getCompressor());
+ tarAndUntarAndCheckFileContents(tarFile);
+ }
+
+ @Test
+ public void createsBzip2CompressedTarFile() {
+ final TestFile tarFile = initializeTarFile(tmpDir.getTestDirectory().file("test.tbz2"),
+ Bzip2Archiver.getCompressor());
+ tarAndUntarAndCheckFileContents(tarFile);
+ }
+
+ @Test
+ public void tarFileContainsExpectedPermissions() {
+ final TestFile tarFile = initializeTarFile(tmpDir.getTestDirectory().file("test.tar"),
+ new SimpleCompressor());
+
+ tar(dir("dir"), file("file"));
+
+ Map<String, Integer> expected = new HashMap<String, Integer>();
+ expected.put("dir", 2);
+ expected.put("file", 1);
+
+ assertVisitsPermissions(new TarFileTree(new FileResource(tarFile), null),
+ expected);
+ }
+
+ @Test
+ public void wrapsFailureToOpenOutputFile() {
+ final TestFile tarFile = initializeTarFile(tmpDir.createDir("test.tar"),
+ new SimpleCompressor());
+
+ try {
+ action.execute(new CopyActionProcessingStream() {
+ public void process(CopyActionProcessingStreamAction action) {
+ // nothing
+ }
+ });
+ fail();
+ } catch (GradleException e) {
+ assertThat(e.getMessage(), equalTo(String.format("Could not create TAR '%s'.", tarFile)));
+ }
+ }
+
+ @Test
+ public void wrapsFailureToAddElement() {
+ final TestFile tarFile = initializeTarFile(tmpDir.getTestDirectory().file("test.tar"),
+ new SimpleCompressor());
+
+ Throwable failure = new RuntimeException("broken");
+ try {
+ visit(action, brokenFile("dir/file1", failure));
+ fail();
+ } catch (GradleException e) {
+ assertThat(e.getMessage(), equalTo(String.format("Could not add [dir/file1] to TAR '%s'.", tarFile)));
+ assertThat(e.getCause(), sameInstance(failure));
+ }
+ }
+
+ private TestFile initializeTarFile(final TestFile tarFile, final ArchiveOutputStreamFactory compressor) {
+ action = new TarCopyAction(tarFile, compressor);
+ return tarFile;
+ }
+
+ private void tar(final FileCopyDetailsInternal... files) {
+ action.execute(new CopyActionProcessingStream() {
+ public void process(CopyActionProcessingStreamAction action) {
+ for (FileCopyDetailsInternal f : files) {
+ if (f.isDirectory()) {
+ action.processFile(f);
+ } else {
+ action.processFile(f);
+ }
+ }
+ }
+ });
+ }
+
+ private FileCopyDetailsInternal file(final String path) {
+ final FileCopyDetailsInternal details = context.mock(FileCopyDetailsInternal.class, path);
+ final String content = String.format("contents of %s", path);
+
+ context.checking(new Expectations() {{
+ allowing(details).getRelativePath();
+ will(returnValue(RelativePath.parse(true, path)));
+
+ allowing(details).getLastModified();
+ will(returnValue(1000L));
+
+ allowing(details).getSize();
+ will(returnValue((long) content.getBytes().length));
+
+ allowing(details).isDirectory();
+ will(returnValue(false));
+
+ allowing(details).getMode();
+ will(returnValue(1));
+
+ allowing(details).copyTo(with(notNullValue(OutputStream.class)));
+ will(new org.jmock.api.Action() {
+ public void describeTo(Description description) {
+ description.appendText("write content");
+ }
+
+ public Object invoke(Invocation invocation) throws Throwable {
+ IOUtils.write(content, (OutputStream) invocation.getParameter(0));
+ return null;
+ }
+ });
+ }});
+
+ return details;
+ }
+
+ private FileCopyDetailsInternal dir(final String path) {
+ final FileCopyDetailsInternal details = context.mock(FileCopyDetailsInternal.class, path);
+
+ context.checking(new Expectations() {{
+ allowing(details).getRelativePath();
+ will(returnValue(RelativePath.parse(false, path)));
+
+ allowing(details).getLastModified();
+ will(returnValue(1000L));
+
+ allowing(details).isDirectory();
+ will(returnValue(true));
+
+ allowing(details).getMode();
+ will(returnValue(2));
+ }});
+
+ return details;
+ }
+
+ private FileCopyDetailsInternal brokenFile(final String path, final Throwable failure) {
+ final FileCopyDetailsInternal details = context.mock(FileCopyDetailsInternal.class, String.format("[%s]", path));
+
+ context.checking(new Expectations() {{
+ allowing(details).getRelativePath();
+ will(returnValue(RelativePath.parse(true, path)));
+
+ allowing(details).getLastModified();
+ will(returnValue(1000L));
+
+ allowing(details).getSize();
+ will(returnValue(1000L));
+
+ allowing(details).isDirectory();
+ will(returnValue(false));
+
+ allowing(details).getMode();
+ will(returnValue(1));
+
+ allowing(details).copyTo(with(notNullValue(OutputStream.class)));
+ will(new org.jmock.api.Action() {
+ public void describeTo(Description description) {
+ description.appendText("write content");
+ }
+
+ public Object invoke(Invocation invocation) throws Throwable {
+ failure.fillInStackTrace();
+ throw failure;
+ }
+ });
+ }});
+
+ return details;
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/archive/TarCopySpecVisitorTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/archive/TarCopySpecVisitorTest.java
deleted file mode 100644
index 6f4d75f..0000000
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/archive/TarCopySpecVisitorTest.java
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.file.archive;
-
-import org.apache.commons.io.IOUtils;
-import org.gradle.api.GradleException;
-import org.gradle.api.file.FileVisitDetails;
-import org.gradle.api.file.RelativePath;
-import org.gradle.api.internal.file.FileResource;
-import org.gradle.api.internal.file.archive.compression.ArchiveOutputStreamFactory;
-import org.gradle.api.internal.file.archive.compression.Bzip2Archiver;
-import org.gradle.api.internal.file.archive.compression.GzipArchiver;
-import org.gradle.api.internal.file.archive.compression.SimpleCompressor;
-import org.gradle.api.internal.file.copy.ArchiveCopyAction;
-import org.gradle.api.internal.file.copy.ReadableCopySpec;
-import org.gradle.test.fixtures.file.TestFile;
-import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider;
-import org.hamcrest.Description;
-import org.jmock.Expectations;
-import org.jmock.api.Action;
-import org.jmock.api.Invocation;
-import org.jmock.integration.junit4.JMock;
-import org.jmock.integration.junit4.JUnit4Mockery;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.io.OutputStream;
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.gradle.api.file.FileVisitorUtil.assertVisitsPermissions;
-import static org.hamcrest.Matchers.*;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
-
- at RunWith(JMock.class)
-public class TarCopySpecVisitorTest {
- @Rule
- public final TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider();
- private final JUnit4Mockery context = new JUnit4Mockery();
- private final ArchiveCopyAction copyAction = context.mock(ArchiveCopyAction.class);
- private final ReadableCopySpec copySpec = context.mock(ReadableCopySpec.class);
- private final TarCopySpecVisitor visitor = new TarCopySpecVisitor();
-
- @Test
- public void createsTarFile() {
- final TestFile tarFile = initializeTarFile(tmpDir.getTestDirectory().file("test.tar"),
- new SimpleCompressor());
- tarAndUntarAndCheckFileContents(tarFile);
- }
-
- private void tarAndUntarAndCheckFileContents(TestFile tarFile) {
- tar(file("dir/file1"), file("file2"));
-
- TestFile expandDir = tmpDir.getTestDirectory().file("expanded");
- tarFile.untarTo(expandDir);
- expandDir.file("dir/file1").assertContents(equalTo("contents of dir/file1"));
- expandDir.file("file2").assertContents(equalTo("contents of file2"));
- }
-
- @Test
- public void createsGzipCompressedTarFile() {
- final TestFile tarFile = initializeTarFile(tmpDir.getTestDirectory().file("test.tgz"),
- GzipArchiver.getCompressor());
- tarAndUntarAndCheckFileContents(tarFile);
- }
-
- @Test
- public void createsBzip2CompressedTarFile() {
- final TestFile tarFile = initializeTarFile(tmpDir.getTestDirectory().file("test.tbz2"),
- Bzip2Archiver.getCompressor());
- tarAndUntarAndCheckFileContents(tarFile);
- }
-
- @Test
- public void tarFileContainsExpectedPermissions() {
- final TestFile tarFile = initializeTarFile(tmpDir.getTestDirectory().file("test.tar"),
- new SimpleCompressor());
-
- tar(dir("dir"), file("file"));
-
- Map<String, Integer> expected = new HashMap<String, Integer>();
- expected.put("dir", 2);
- expected.put("file", 1);
-
- assertVisitsPermissions(new TarFileTree(new FileResource(tarFile), null),
- expected);
- }
-
- @Test
- public void wrapsFailureToOpenOutputFile() {
- final TestFile tarFile = initializeTarFile(tmpDir.createDir("test.tar"),
- new SimpleCompressor());
-
- try {
- visitor.startVisit(copyAction);
- fail();
- } catch (GradleException e) {
- assertThat(e.getMessage(), equalTo(String.format("Could not create TAR '%s'.", tarFile)));
- }
- }
-
- @Test
- public void wrapsFailureToAddElement() {
- final TestFile tarFile = initializeTarFile(tmpDir.getTestDirectory().file("test.tar"),
- new SimpleCompressor());
-
- visitor.startVisit(copyAction);
- visitor.visitSpec(copySpec);
-
- Throwable failure = new RuntimeException("broken");
- try {
- visitor.visitFile(brokenFile("dir/file1", failure));
- fail();
- } catch (GradleException e) {
- assertThat(e.getMessage(), equalTo(String.format("Could not add [dir/file1] to TAR '%s'.", tarFile)));
- assertThat(e.getCause(), sameInstance(failure));
- }
- }
-
- private TestFile initializeTarFile(final TestFile tarFile, final ArchiveOutputStreamFactory compressor) {
- context.checking(new Expectations() {{
- allowing(copyAction).getArchivePath();
- will(returnValue(tarFile));
- allowing(copyAction).getCompressor();
- will(returnValue(compressor));
- }});
- return tarFile;
- }
-
- private void tar(FileVisitDetails... files) {
- visitor.startVisit(copyAction);
- visitor.visitSpec(copySpec);
-
- for (FileVisitDetails f : files) {
- if (f.isDirectory()) {
- visitor.visitDir(f);
- } else {
- visitor.visitFile(f);
- }
- }
-
- visitor.endVisit();
- }
-
- private FileVisitDetails file(final String path) {
- final FileVisitDetails details = context.mock(FileVisitDetails.class, path);
- final String content = String.format("contents of %s", path);
-
- context.checking(new Expectations() {{
- allowing(details).getRelativePath();
- will(returnValue(RelativePath.parse(true, path)));
-
- allowing(details).getLastModified();
- will(returnValue(1000L));
-
- allowing(details).getSize();
- will(returnValue((long)content.getBytes().length));
-
- allowing(details).isDirectory();
- will(returnValue(false));
-
- allowing(details).getMode();
- will(returnValue(1));
-
- allowing(details).copyTo(with(notNullValue(OutputStream.class)));
- will(new Action() {
- public void describeTo(Description description) {
- description.appendText("write content");
- }
-
- public Object invoke(Invocation invocation) throws Throwable {
- IOUtils.write(content, (OutputStream) invocation.getParameter(0));
- return null;
- }
- });
- }});
-
- return details;
- }
-
- private FileVisitDetails dir(final String path) {
- final FileVisitDetails details = context.mock(FileVisitDetails.class, path);
-
- context.checking(new Expectations() {{
- allowing(details).getRelativePath();
- will(returnValue(RelativePath.parse(false, path)));
-
- allowing(details).getLastModified();
- will(returnValue(1000L));
-
- allowing(details).isDirectory();
- will(returnValue(true));
-
- allowing(details).getMode();
- will(returnValue(2));
- }});
-
- return details;
- }
-
- private FileVisitDetails brokenFile(final String path, final Throwable failure) {
- final FileVisitDetails details = context.mock(FileVisitDetails.class, String.format("[%s]", path));
-
- context.checking(new Expectations() {{
- allowing(details).getRelativePath();
- will(returnValue(RelativePath.parse(true, path)));
-
- allowing(details).getLastModified();
- will(returnValue(1000L));
-
- allowing(details).getSize();
- will(returnValue(1000L));
-
- allowing(details).isDirectory();
- will(returnValue(false));
-
- allowing(details).getMode();
- will(returnValue(1));
-
- allowing(details).copyTo(with(notNullValue(OutputStream.class)));
- will(new Action() {
- public void describeTo(Description description) {
- description.appendText("write content");
- }
-
- public Object invoke(Invocation invocation) throws Throwable {
- failure.fillInStackTrace();
- throw failure;
- }
- });
- }});
-
- return details;
- }
-}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/archive/ZipCopyActionTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/archive/ZipCopyActionTest.java
new file mode 100644
index 0000000..cbfaefa
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/archive/ZipCopyActionTest.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.file.archive;
+
+import org.apache.commons.io.IOUtils;
+import org.gradle.api.GradleException;
+import org.gradle.api.file.RelativePath;
+import org.gradle.api.internal.file.CopyActionProcessingStreamAction;
+import org.gradle.api.internal.file.copy.CopyActionProcessingStream;
+import org.gradle.api.internal.file.copy.FileCopyDetailsInternal;
+import org.gradle.api.internal.file.copy.ZipStoredCompressor;
+import org.gradle.test.fixtures.file.TestFile;
+import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider;
+import org.hamcrest.Description;
+import org.jmock.Expectations;
+import org.jmock.api.Invocation;
+import org.jmock.integration.junit4.JMock;
+import org.jmock.integration.junit4.JUnit4Mockery;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.OutputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.gradle.api.file.FileVisitorUtil.assertVisitsPermissions;
+import static org.gradle.api.internal.file.copy.CopyActionExecuterUtil.visit;
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+ at RunWith(JMock.class)
+public class ZipCopyActionTest {
+ @Rule
+ public final TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider();
+ private final JUnit4Mockery context = new JUnit4Mockery();
+ private ZipCopyAction visitor;
+ private TestFile zipFile;
+
+ @Before
+ public void setup() {
+ zipFile = tmpDir.getTestDirectory().file("test.zip");
+ visitor = new ZipCopyAction(zipFile, ZipStoredCompressor.INSTANCE);
+ }
+
+ @Test
+ public void createsZipFile() {
+ zip(dir("dir"), file("dir/file1"), file("file2"));
+
+ TestFile expandDir = tmpDir.getTestDirectory().file("expanded");
+ zipFile.unzipTo(expandDir);
+ expandDir.file("dir/file1").assertContents(equalTo("contents of dir/file1"));
+ expandDir.file("file2").assertContents(equalTo("contents of file2"));
+ }
+
+ @Test
+ public void createsDeflatedZipFile() {
+ zip(dir("dir"), file("dir/file1"), file("file2"));
+
+ TestFile expandDir = tmpDir.getTestDirectory().file("expanded");
+ zipFile.unzipTo(expandDir);
+ expandDir.file("dir/file1").assertContents(equalTo("contents of dir/file1"));
+ expandDir.file("file2").assertContents(equalTo("contents of file2"));
+ }
+
+ @Test
+ public void zipFileContainsExpectedPermissions() {
+ zip(dir("dir"), file("file"));
+
+ Map<String, Integer> expected = new HashMap<String, Integer>();
+ expected.put("dir", 2);
+ expected.put("file", 1);
+
+ assertVisitsPermissions(new ZipFileTree(zipFile, null), expected);
+ }
+
+ @Test
+ public void wrapsFailureToOpenOutputFile() {
+ final TestFile invalidZipFile = tmpDir.createDir("test.zip");
+ visitor = new ZipCopyAction(invalidZipFile, ZipStoredCompressor.INSTANCE);
+
+ try {
+ visitor.execute(new CopyActionProcessingStream() {
+ public void process(CopyActionProcessingStreamAction action) {
+ // nothing
+ }
+ });
+ fail();
+ } catch (GradleException e) {
+ assertThat(e.getMessage(), equalTo(String.format("Could not create ZIP '%s'.", zipFile)));
+ }
+ }
+
+ @Test
+ public void wrapsFailureToAddElement() {
+
+ Throwable failure = new RuntimeException("broken");
+ try {
+ visit(visitor, brokenFile("dir/file1", failure));
+ fail();
+ } catch (GradleException e) {
+ assertThat(e.getMessage(), equalTo(String.format("Could not add [dir/file1] to ZIP '%s'.", zipFile)));
+ assertThat(e.getCause(), sameInstance(failure));
+ }
+ }
+
+ private void zip(final FileCopyDetailsInternal... files) {
+ visitor.execute(new CopyActionProcessingStream() {
+ public void process(CopyActionProcessingStreamAction action) {
+ for (FileCopyDetailsInternal f : files) {
+ action.processFile(f);
+ }
+ }
+ });
+ }
+
+ private FileCopyDetailsInternal file(final String path) {
+ final FileCopyDetailsInternal details = context.mock(FileCopyDetailsInternal.class, path);
+
+ context.checking(new Expectations() {{
+ allowing(details).getRelativePath();
+ will(returnValue(RelativePath.parse(true, path)));
+
+ allowing(details).getLastModified();
+ will(returnValue(1000L));
+
+ allowing(details).isDirectory();
+ will(returnValue(false));
+
+ allowing(details).getMode();
+ will(returnValue(1));
+
+ allowing(details).copyTo(with(notNullValue(OutputStream.class)));
+ will(new org.jmock.api.Action() {
+ public void describeTo(Description description) {
+ description.appendText("write content");
+ }
+
+ public Object invoke(Invocation invocation) throws Throwable {
+ IOUtils.write(String.format("contents of %s", path), (OutputStream) invocation.getParameter(0));
+ return null;
+ }
+ });
+ }});
+
+ return details;
+ }
+
+ private FileCopyDetailsInternal dir(final String path) {
+ final FileCopyDetailsInternal details = context.mock(FileCopyDetailsInternal.class, path);
+
+ context.checking(new Expectations() {{
+ allowing(details).getRelativePath();
+ will(returnValue(RelativePath.parse(false, path)));
+
+ allowing(details).getLastModified();
+ will(returnValue(1000L));
+
+ allowing(details).isDirectory();
+ will(returnValue(true));
+
+ allowing(details).getMode();
+ will(returnValue(2));
+ }});
+
+ return details;
+ }
+
+ private FileCopyDetailsInternal brokenFile(final String path, final Throwable failure) {
+ final FileCopyDetailsInternal details = context.mock(FileCopyDetailsInternal.class, String.format("[%s]", path));
+
+ context.checking(new Expectations() {{
+ allowing(details).getRelativePath();
+ will(returnValue(RelativePath.parse(true, path)));
+
+ allowing(details).getLastModified();
+ will(returnValue(1000L));
+
+ allowing(details).isDirectory();
+ will(returnValue(false));
+
+ allowing(details).getMode();
+ will(returnValue(1));
+
+ allowing(details).copyTo(with(notNullValue(OutputStream.class)));
+ will(new org.jmock.api.Action() {
+ public void describeTo(Description description) {
+ description.appendText("write content");
+ }
+
+ public Object invoke(Invocation invocation) throws Throwable {
+ failure.fillInStackTrace();
+ throw failure;
+ }
+ });
+ }});
+
+ return details;
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/archive/ZipCopySpecVisitorTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/archive/ZipCopySpecVisitorTest.java
deleted file mode 100644
index bbc30b5..0000000
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/archive/ZipCopySpecVisitorTest.java
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.file.archive;
-
-import org.apache.commons.io.IOUtils;
-import org.gradle.api.GradleException;
-import org.gradle.api.file.FileVisitDetails;
-import org.gradle.api.file.RelativePath;
-import org.gradle.api.internal.file.archive.compression.ArchiveOutputStreamFactory;
-import org.gradle.api.internal.file.copy.ArchiveCopyAction;
-import org.gradle.api.internal.file.copy.ZipDeflatedCompressor;
-import org.gradle.api.internal.file.copy.ReadableCopySpec;
-import org.gradle.api.internal.file.copy.ZipStoredCompressor;
-import org.gradle.test.fixtures.file.TestFile;
-import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider;
-import org.hamcrest.Description;
-import org.jmock.Expectations;
-import org.jmock.api.Action;
-import org.jmock.api.Invocation;
-import org.jmock.integration.junit4.JMock;
-import org.jmock.integration.junit4.JUnit4Mockery;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.io.OutputStream;
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.gradle.api.file.FileVisitorUtil.assertVisitsPermissions;
-import static org.hamcrest.Matchers.*;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
-
- at RunWith(JMock.class)
-public class ZipCopySpecVisitorTest {
- @Rule
- public final TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider();
- private final JUnit4Mockery context = new JUnit4Mockery();
- private final ArchiveCopyAction copyAction = context.mock(ZipCopyAction.class);
- private final ReadableCopySpec copySpec = context.mock(ReadableCopySpec.class);
- private final ZipCopySpecVisitor visitor = new ZipCopySpecVisitor();
- private TestFile zipFile;
-
- @Before
- public void setup() {
- zipFile = tmpDir.getTestDirectory().file("test.zip");
- context.checking(new Expectations() {{
- allowing(copyAction).getArchivePath();
- will(returnValue(zipFile));
- }});
- context.checking(new Expectations() {{
- allowing(copyAction).getCompressor();
- will(returnValue(ZipStoredCompressor.INSTANCE));
- }});
- }
-
- private TestFile initializeZipFile(final TestFile testFile, final ArchiveOutputStreamFactory compressor) {
- context.checking(new Expectations() {{
- allowing(copyAction).getArchivePath();
- will(returnValue(zipFile));
- allowing(copyAction).getCompressor();
- will(returnValue(compressor));
- }});
- return testFile;
- }
-
- @Test
- public void createsZipFile() {
- initializeZipFile(zipFile, ZipStoredCompressor.INSTANCE);
- zip(dir("dir"), file("dir/file1"), file("file2"));
-
- TestFile expandDir = tmpDir.getTestDirectory().file("expanded");
- zipFile.unzipTo(expandDir);
- expandDir.file("dir/file1").assertContents(equalTo("contents of dir/file1"));
- expandDir.file("file2").assertContents(equalTo("contents of file2"));
- }
-
- @Test
- public void createsDeflatedZipFile() {
- initializeZipFile(zipFile, ZipDeflatedCompressor.INSTANCE);
- zip(dir("dir"), file("dir/file1"), file("file2"));
-
- TestFile expandDir = tmpDir.getTestDirectory().file("expanded");
- zipFile.unzipTo(expandDir);
- expandDir.file("dir/file1").assertContents(equalTo("contents of dir/file1"));
- expandDir.file("file2").assertContents(equalTo("contents of file2"));
- }
-
- @Test
- public void zipFileContainsExpectedPermissions() {
- zip(dir("dir"), file("file"));
-
- Map<String, Integer> expected = new HashMap<String, Integer>();
- expected.put("dir", 2);
- expected.put("file", 1);
-
- assertVisitsPermissions(new ZipFileTree(zipFile, null), expected);
- }
-
- @Test
- public void wrapsFailureToOpenOutputFile() {
- final TestFile invalidZipFile = tmpDir.createDir("test.zip");
-
- context.checking(new Expectations() {{
- allowing(copyAction).getArchivePath();
- will(returnValue(invalidZipFile));
- }});
-
- try {
- visitor.startVisit(copyAction);
- fail();
- } catch (GradleException e) {
- assertThat(e.getMessage(), equalTo(String.format("Could not create ZIP '%s'.", zipFile)));
- }
- }
-
- @Test
- public void wrapsFailureToAddElement() {
- visitor.startVisit(copyAction);
- visitor.visitSpec(copySpec);
-
- Throwable failure = new RuntimeException("broken");
- try {
- visitor.visitFile(brokenFile("dir/file1", failure));
- fail();
- } catch (GradleException e) {
- assertThat(e.getMessage(), equalTo(String.format("Could not add [dir/file1] to ZIP '%s'.", zipFile)));
- assertThat(e.getCause(), sameInstance(failure));
- }
- }
-
- private void zip(FileVisitDetails... files) {
- visitor.startVisit(copyAction);
- visitor.visitSpec(copySpec);
-
- for (FileVisitDetails f : files) {
- if (f.isDirectory()) {
- visitor.visitDir(f);
- } else {
- visitor.visitFile(f);
- }
- }
-
- visitor.endVisit();
- }
-
- private FileVisitDetails file(final String path) {
- final FileVisitDetails details = context.mock(FileVisitDetails.class, path);
-
- context.checking(new Expectations() {{
- allowing(details).getRelativePath();
- will(returnValue(RelativePath.parse(true, path)));
-
- allowing(details).getLastModified();
- will(returnValue(1000L));
-
- allowing(details).isDirectory();
- will(returnValue(false));
-
- allowing(details).getMode();
- will(returnValue(1));
-
- allowing(details).copyTo(with(notNullValue(OutputStream.class)));
- will(new Action() {
- public void describeTo(Description description) {
- description.appendText("write content");
- }
-
- public Object invoke(Invocation invocation) throws Throwable {
- IOUtils.write(String.format("contents of %s", path), (OutputStream) invocation.getParameter(0));
- return null;
- }
- });
- }});
-
- return details;
- }
-
- private FileVisitDetails dir(final String path) {
- final FileVisitDetails details = context.mock(FileVisitDetails.class, path);
-
- context.checking(new Expectations() {{
- allowing(details).getRelativePath();
- will(returnValue(RelativePath.parse(false, path)));
-
- allowing(details).getLastModified();
- will(returnValue(1000L));
-
- allowing(details).isDirectory();
- will(returnValue(true));
-
- allowing(details).getMode();
- will(returnValue(2));
- }});
-
- return details;
- }
-
- private FileVisitDetails brokenFile(final String path, final Throwable failure) {
- final FileVisitDetails details = context.mock(FileVisitDetails.class, String.format("[%s]", path));
-
- context.checking(new Expectations() {{
- allowing(details).getRelativePath();
- will(returnValue(RelativePath.parse(true, path)));
-
- allowing(details).getLastModified();
- will(returnValue(1000L));
-
- allowing(details).isDirectory();
- will(returnValue(false));
-
- allowing(details).getMode();
- will(returnValue(1));
-
- allowing(details).copyTo(with(notNullValue(OutputStream.class)));
- will(new Action() {
- public void describeTo(Description description) {
- description.appendText("write content");
- }
-
- public Object invoke(Invocation invocation) throws Throwable {
- failure.fillInStackTrace();
- throw failure;
- }
- });
- }});
-
- return details;
- }
-}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/archive/compression/ArchiversTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/archive/compression/ArchiversTest.groovy
index 7dd9b99..935df22 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/archive/compression/ArchiversTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/archive/compression/ArchiversTest.groovy
@@ -20,9 +20,6 @@ package org.gradle.api.internal.file.archive.compression;
import org.gradle.api.internal.file.FileResource
import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 12/13/11
- */
public class ArchiversTest extends Specification {
def "archivers have unqique URIs"() {
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/collections/DefaultConfigurableFileCollectionTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/collections/DefaultConfigurableFileCollectionTest.java
index ecaa42b..ad4e016 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/collections/DefaultConfigurableFileCollectionTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/collections/DefaultConfigurableFileCollectionTest.java
@@ -22,7 +22,7 @@ import org.gradle.api.internal.file.FileResolver;
import org.gradle.api.internal.tasks.TaskResolver;
import org.gradle.api.tasks.TaskDependency;
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider;
-import org.gradle.util.HelperUtil;
+import org.gradle.util.TestUtil;
import org.gradle.util.JUnit4GroovyMockery;
import org.jmock.Expectations;
import org.jmock.integration.junit4.JMock;
@@ -118,7 +118,7 @@ public class DefaultConfigurableFileCollectionTest {
}});
List<Character> files = toList('a');
- Closure closure = HelperUtil.returns(files);
+ Closure closure = TestUtil.returns(files);
collection.from(closure);
assertThat(collection.getFiles(), equalTo(toLinkedSet(file1)));
@@ -130,7 +130,7 @@ public class DefaultConfigurableFileCollectionTest {
@Test
public void canUseAClosureToSpecifyASingleFile() {
- Closure closure = HelperUtil.returns('a');
+ Closure closure = TestUtil.returns('a');
final File file = new File("1");
collection.from(closure);
@@ -145,7 +145,7 @@ public class DefaultConfigurableFileCollectionTest {
@Test
public void closureCanReturnNull() {
- Closure closure = HelperUtil.returns(null);
+ Closure closure = TestUtil.returns(null);
collection.from(closure);
@@ -202,7 +202,7 @@ public class DefaultConfigurableFileCollectionTest {
will(returnValue(file2));
}});
- collection.from(HelperUtil.toClosure("{[{['src1', { ['src2'] as String[] }]}]}"));
+ collection.from(TestUtil.toClosure("{[{['src1', { ['src2'] as String[] }]}]}"));
assertThat(collection.getFiles(), equalTo(toLinkedSet(file1, file2)));
}
@@ -362,7 +362,7 @@ public class DefaultConfigurableFileCollectionTest {
assertThat(collection.getBuildDependencies().getDependencies(null), equalTo((Set) toSet(task)));
assertThat(collection.getAsFileTree().getBuildDependencies().getDependencies(null), equalTo((Set) toSet(task)));
- assertThat(collection.getAsFileTree().matching(HelperUtil.TEST_CLOSURE).getBuildDependencies().getDependencies(null), equalTo((Set) toSet(task)));
+ assertThat(collection.getAsFileTree().matching(TestUtil.TEST_CLOSURE).getBuildDependencies().getDependencies(null), equalTo((Set) toSet(task)));
}
}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/collections/DefaultConfigurableFileTreeTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/collections/DefaultConfigurableFileTreeTest.groovy
index 0dcb1ea..8bdd6b5 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/collections/DefaultConfigurableFileTreeTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/collections/DefaultConfigurableFileTreeTest.groovy
@@ -26,6 +26,7 @@ import org.gradle.api.tasks.TaskDependency
import org.gradle.api.tasks.util.AbstractTestForPatternSet
import org.gradle.api.tasks.util.PatternFilterable
import org.gradle.api.tasks.util.PatternSet
+import org.gradle.internal.reflect.Instantiator
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
import org.gradle.util.JUnit4GroovyMockery
import org.gradle.util.WrapUtil
@@ -41,12 +42,10 @@ import static org.gradle.util.Matchers.isEmpty
import static org.hamcrest.Matchers.*
import static org.junit.Assert.*
-/**
- * @author Hans Dockter
- */
class DefaultConfigurableFileTreeTest extends AbstractTestForPatternSet {
JUnit4Mockery context = new JUnit4GroovyMockery();
TaskResolver taskResolverStub = context.mock(TaskResolver.class);
+ Instantiator instantiator = context.mock(Instantiator)
DefaultConfigurableFileTree fileSet
FileResolver fileResolverStub = [resolve: {it as File}] as FileResolver
@Rule public TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider();
@@ -62,27 +61,27 @@ class DefaultConfigurableFileTreeTest extends AbstractTestForPatternSet {
@Before public void setUp() {
super.setUp()
- fileSet = patternSetType.newInstance(testDir, fileResolverStub, taskResolverStub)
+ fileSet = patternSetType.newInstance(testDir, fileResolverStub, taskResolverStub, instantiator)
}
@Test public void testFileSetConstructionWithBaseDir() {
- fileSet = new DefaultConfigurableFileTree(testDir, fileResolverStub, taskResolverStub)
+ fileSet = new DefaultConfigurableFileTree(testDir, fileResolverStub, taskResolverStub, instantiator)
assertEquals(testDir, fileSet.dir)
}
@Test public void testFileSetConstructionFromMap() {
- fileSet = new DefaultConfigurableFileTree(fileResolverStub, taskResolverStub, dir: testDir, includes: ['include'])
+ fileSet = new DefaultConfigurableFileTree(fileResolverStub, taskResolverStub, dir: testDir, includes: ['include'], instantiator)
assertEquals(testDir, fileSet.dir)
assertEquals(['include'] as Set, fileSet.includes)
}
@Test(expected = InvalidUserDataException) public void testFileSetConstructionWithNoBaseDirSpecified() {
- DefaultConfigurableFileTree fileSet = new DefaultConfigurableFileTree([:], fileResolverStub, taskResolverStub)
+ DefaultConfigurableFileTree fileSet = new DefaultConfigurableFileTree([:], fileResolverStub, taskResolverStub, instantiator)
fileSet.contains(new File('unknown'))
}
@Test public void testFileSetConstructionWithBaseDirAsString() {
- DefaultConfigurableFileTree fileSet = new DefaultConfigurableFileTree(fileResolverStub, taskResolverStub, dir: 'dirname')
+ DefaultConfigurableFileTree fileSet = new DefaultConfigurableFileTree(fileResolverStub, taskResolverStub, dir: 'dirname', instantiator)
assertEquals(new File('dirname'), fileSet.dir);
}
@@ -299,7 +298,7 @@ class DefaultConfigurableFileTreeTest extends AbstractTestForPatternSet {
@Test
public void canGetAndSetTaskDependencies() {
FileResolver fileResolverStub = context.mock(FileResolver.class);
- fileSet = patternSetType.newInstance(testDir, fileResolverStub, taskResolverStub)
+ fileSet = patternSetType.newInstance(testDir, fileResolverStub, taskResolverStub, instantiator)
assertThat(fileSet.getBuiltBy(), isEmpty());
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/collections/DirectoryFileTreeTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/collections/DirectoryFileTreeTest.java
index 9cb0f03..11a4694 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/collections/DirectoryFileTreeTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/collections/DirectoryFileTreeTest.java
@@ -16,8 +16,8 @@
package org.gradle.api.internal.file.collections;
import org.gradle.api.file.FileVisitDetails;
+import org.gradle.api.file.FileVisitor;
import org.gradle.api.file.RelativePath;
-import org.gradle.api.internal.file.copy.CopySpecVisitor;
import org.gradle.api.specs.Spec;
import org.gradle.api.tasks.util.PatternSet;
import org.gradle.test.fixtures.file.TestFile;
@@ -51,11 +51,11 @@ public class DirectoryFileTreeTest {
@Rule
public final TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider();
private JUnit4Mockery context = new JUnit4GroovyMockery();
- private CopySpecVisitor visitor;
+ private FileVisitor visitor;
@Before
public void setUp() {
- visitor = context.mock(CopySpecVisitor.class);
+ visitor = context.mock(FileVisitor.class);
}
@Test
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/collections/MapFileTreeTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/collections/MapFileTreeTest.java
index 9eb4a54..ebe56be 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/collections/MapFileTreeTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/collections/MapFileTreeTest.java
@@ -18,7 +18,7 @@ package org.gradle.api.internal.file.collections;
import groovy.lang.Closure;
import org.gradle.test.fixtures.file.TestFile;
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider;
-import org.gradle.util.HelperUtil;
+import org.gradle.util.TestUtil;
import org.junit.Rule;
import org.junit.Test;
@@ -45,7 +45,7 @@ public class MapFileTreeTest {
@Test
public void canAddAnElementUsingAClosureToGeneratedContent() {
- Closure closure = HelperUtil.toClosure("{it.write('content'.getBytes())}");
+ Closure closure = TestUtil.toClosure("{it.write('content'.getBytes())}");
tree.add("path/file.txt", closure);
assertVisits(tree, toList("path/file.txt"), toList("path"));
@@ -57,7 +57,7 @@ public class MapFileTreeTest {
@Test
public void canAddMultipleElementsInDifferentDirs() {
- Closure closure = HelperUtil.toClosure("{it.write('content'.getBytes())}");
+ Closure closure = TestUtil.toClosure("{it.write('content'.getBytes())}");
tree.add("path/file.txt", closure);
tree.add("file.txt", closure);
tree.add("path/subdir/file.txt", closure);
@@ -68,7 +68,7 @@ public class MapFileTreeTest {
@Test
public void canStopVisitingElements() {
- Closure closure = HelperUtil.toClosure("{it.write('content'.getBytes())}");
+ Closure closure = TestUtil.toClosure("{it.write('content'.getBytes())}");
tree.add("path/file.txt", closure);
tree.add("file.txt", closure);
assertCanStopVisiting(tree);
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/CopyActionExecuterTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/CopyActionExecuterTest.groovy
new file mode 100644
index 0000000..23bc6dc
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/CopyActionExecuterTest.groovy
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.file.copy
+
+import org.gradle.api.Action
+import org.gradle.api.file.FileCopyDetails
+import org.gradle.api.internal.file.BaseDirFileResolver
+import org.gradle.api.internal.file.CopyActionProcessingStreamAction
+import org.gradle.api.internal.tasks.SimpleWorkResult
+import org.gradle.api.tasks.WorkResult
+import org.gradle.internal.nativeplatform.filesystem.FileSystems
+import org.gradle.internal.reflect.DirectInstantiator
+import org.gradle.test.fixtures.file.WorkspaceTest
+
+class CopyActionExecuterTest extends WorkspaceTest {
+
+ def "correctly executes copy actions, normalising and handling excludes"() {
+ given:
+ file("a").with {
+ createFile("a")
+ }
+ file("b").with {
+ createFile("b")
+ createDir("b1").createFile("b1")
+ }
+
+ def resolver = new BaseDirFileResolver(FileSystems.getDefault(), testDirectory)
+ def copySpec = new DestinationRootCopySpec(resolver, new DefaultCopySpec(resolver, new DirectInstantiator()))
+ copySpec.with {
+ into "out"
+ from "a", {
+ from "b/b1", {
+ it.eachFile {
+ FileCopyDetails fcd -> fcd.exclude()
+ }
+ }
+ }
+ }
+
+ def action = Mock(CopyActionProcessingStreamAction)
+ def workResult = true
+ def copyAction = new CopyAction() {
+ WorkResult execute(CopyActionProcessingStream stream) {
+ stream.process(action)
+ new SimpleWorkResult(workResult)
+ }
+ }
+ def executer = new CopyActionExecuter(new DirectInstantiator(), FileSystems.getDefault())
+
+ when:
+ executer.execute(copySpec, copyAction)
+
+ then:
+ 1 * action.processFile({ it.relativePath.pathString == "a" })
+ 0 * action.processFile(_)
+ }
+
+ Closure path(path) {
+ return { println it.relativePath.pathString; it.relativePath.pathString == path }
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/CopyActionImplTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/CopyActionImplTest.groovy
deleted file mode 100644
index d2024f5..0000000
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/CopyActionImplTest.groovy
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.file.copy
-
-import org.gradle.api.file.FileTree
-import org.gradle.api.internal.file.FileResolver
-import spock.lang.Specification
-
-public class CopyActionImplTest extends Specification {
- FileCopySpecVisitor visitor = Mock()
- FileResolver resolver = Mock()
- FileTree sourceFileTree = Mock()
- CopyActionImpl copyAction = new CopyActionImpl(resolver, visitor)
-
- def delegatesToMainSpecRootSpec() {
- when:
- copyAction.include 'a'
-
- then:
- copyAction.includes == ['a'] as Set
- copyAction.mainSpec.includes == ['a'] as Set
- copyAction.rootSpec.includes == [] as Set
- copyAction.rootSpec.childSpecs.contains(copyAction.mainSpec)
- }
-
- def didWorkDelegatesToVisitor() {
- when:
- def didWork = copyAction.didWork
-
- then:
- 1 * visitor.didWork >> true
- didWork
- }
-
- def visitsAndCopiesEachSpec() {
- FileTree source = Mock()
- _ * source.matching(_) >> source
-
- copyAction.from('source1')
- def child = copyAction.from('source2') { }
-
- when:
- copyAction.execute()
-
- then:
- 1 * visitor.startVisit(copyAction)
- 1 * visitor.visitSpec(copyAction.rootSpec)
- 1 * resolver.resolveFilesAsTree([[] as Set] as Object[]) >> source
- 1 * visitor.visitSpec(copyAction.mainSpec)
- 1 * resolver.resolveFilesAsTree([['source1'] as Set] as Object[]) >> source
- 1 * visitor.visitSpec(child)
- 1 * resolver.resolveFilesAsTree([['source2'] as Set] as Object[]) >> source
- 1 * visitor.endVisit()
- 0 * resolver._
- 0 * visitor._
- }
-
- def allSourceIncludesSourceFromAllSpecs() {
- FileTree mainSource = Mock()
- _ * mainSource.matching(_) >> mainSource
- FileTree rootSource = Mock()
- _ * rootSource.matching(_) >> rootSource
- FileTree childSource = Mock()
- _ * childSource.matching(_) >> childSource
- FileTree allSource = Mock()
-
- copyAction.from('source1')
- copyAction.from('source2') { }
-
- when:
- def source = copyAction.allSource
-
- then:
- source == allSource
- 1 * resolver.resolveFilesAsTree([[] as Set] as Object[]) >> rootSource
- 1 * resolver.resolveFilesAsTree([['source1'] as Set] as Object[]) >> mainSource
- 1 * resolver.resolveFilesAsTree([['source2'] as Set] as Object[]) >> childSource
- 1 * resolver.resolveFilesAsTree([[rootSource, mainSource, childSource]] as Object[]) >> allSource
- 0 * resolver._
- 0 * visitor._
- }
-}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/CopySpecImplTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/CopySpecImplTest.groovy
deleted file mode 100644
index 089d334..0000000
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/CopySpecImplTest.groovy
+++ /dev/null
@@ -1,350 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.file.copy
-
-import org.apache.tools.ant.filters.HeadFilter
-import org.apache.tools.ant.filters.StripJavaComments
-import org.gradle.api.Action
-import org.gradle.api.file.FileTree
-import org.gradle.api.file.RelativePath
-import org.gradle.api.internal.file.FileResolver
-import org.gradle.api.specs.Spec
-import org.gradle.api.tasks.util.PatternSet
-import org.gradle.test.fixtures.file.TestFile
-import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
-import org.gradle.util.JUnit4GroovyMockery
-import org.jmock.integration.junit4.JMock
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-
-import static org.hamcrest.Matchers.*
-import static org.junit.Assert.*
-
- at RunWith(JMock)
-public class CopySpecImplTest {
-
- @Rule public TestNameTestDirectoryProvider testDir = new TestNameTestDirectoryProvider();
- private TestFile baseFile = testDir.testDirectory
- private final JUnit4GroovyMockery context = new JUnit4GroovyMockery();
- private final FileResolver fileResolver = context.mock(FileResolver);
- private final CopySpecImpl spec = new CopySpecImpl(fileResolver)
-
- private List<String> getTestSourceFileNames() {
- ['first', 'second']
- }
-
- private List<File> getAbsoluteTestSources() {
- testSourceFileNames.collect { new File(baseFile, it) }
- }
-
- @Test public void testAbsoluteFromList() {
- List<File> sources = getAbsoluteTestSources();
- spec.from(sources);
- assertEquals([sources], spec.sourcePaths as List);
- }
-
- @Test public void testFromArray() {
- List<File> sources = getAbsoluteTestSources();
- spec.from(sources as File[]);
- assertEquals(sources, spec.sourcePaths as List);
- }
-
- @Test public void testSourceWithClosure() {
- CopySpecImpl child = spec.from('source') {
- }
-
- assertThat(child, not(sameInstance(spec)))
- assertEquals(['source'], child.sourcePaths as List);
- }
-
- @Test public void testMultipleSourcesWithClosure() {
- CopySpecImpl child = spec.from(['source1', 'source2']) {
- }
-
- assertThat(child, not(sameInstance(spec)))
- assertEquals(['source1', 'source2'], child.sourcePaths.flatten() as List);
- }
-
- @Test public void testDefaultDestinationPathForRootSpec() {
- assertThat(spec.destPath, equalTo(new RelativePath(false)))
- }
-
- @Test public void testInto() {
- spec.into 'spec'
- assertThat(spec.destPath, equalTo(new RelativePath(false, 'spec')))
- spec.into '/'
- assertThat(spec.destPath, equalTo(new RelativePath(false)))
- }
-
- @Test public void testIntoWithAClosure() {
- spec.into { 'spec' }
- assertThat(spec.destPath, equalTo(new RelativePath(false, 'spec')))
- spec.into { return { 'spec' } }
- assertThat(spec.destPath, equalTo(new RelativePath(false, 'spec')))
- }
-
- @Test public void testWithSpec() {
- CopySpecImpl other1 = new CopySpecImpl(fileResolver)
- CopySpecImpl other2 = new CopySpecImpl(fileResolver)
-
- spec.with other1, other2
- assertTrue(spec.sourcePaths.empty)
- assertThat(spec.childSpecs.size(), equalTo(2))
- }
-
- @Test public void testWithSpecSource() {
- CopyActionImpl source = new CopyActionImpl(fileResolver, null)
-
- spec.with source
- assertTrue(spec.sourcePaths.empty)
- assertThat(spec.childSpecs.size(), equalTo(1))
- }
-
- @Test public void testWithSpecInheritsDestinationPathFromParent() {
- CopySpecImpl other = new CopySpecImpl(fileResolver)
- other.into 'other'
-
- spec.into 'spec'
- spec.with other
-
- ReadableCopySpec child = spec.childSpecs[0]
- assertThat(child.destPath, equalTo(new RelativePath(false, 'spec', 'other')))
- }
-
- @Test public void testDestinationWithClosure() {
- CopySpecImpl child = spec.into('target') {
- }
-
- assertThat(child, not(sameInstance(spec)))
- assertThat(child.destPath, equalTo(new RelativePath(false, 'target')))
- }
-
- @Test public void testGetAllSpecsReturnsBreadthwiseTraverseOfSpecs() {
- CopySpecImpl child = spec.into('somedir') { }
- CopySpecImpl grandchild = child.into('somedir') { }
- CopySpecImpl child2 = spec.into('somedir') { }
-
- assertThat(spec.allSpecs, equalTo([spec, child, grandchild, child2]))
- }
-
- @Test public void testRootSpecHasRootPathAsDestination() {
- assertThat(spec.destPath, equalTo(new RelativePath(false)))
- }
-
- @Test public void testChildSpecResolvesIntoArgRelativeToParentDestinationDir() {
- CopySpecImpl child = spec.from('somedir') { into 'child' }
- assertThat(child.destPath, equalTo(new RelativePath(false, 'child')))
-
- CopySpecImpl grandchild = child.from('somedir') { into 'grandchild'}
- assertThat(grandchild.destPath, equalTo(new RelativePath(false, 'child', 'grandchild')))
-
- grandchild.into '/grandchild'
- assertThat(grandchild.destPath, equalTo(new RelativePath(false, 'grandchild')))
- }
-
- @Test public void testChildSpecUsesParentDestinationPathAsDefault() {
- CopySpecImpl child = spec.from('somedir') { }
- assertThat(child.destPath, equalTo(spec.destPath))
-
- child.into 'child'
-
- CopySpecImpl grandchild = child.from('somedir') { }
- assertThat(grandchild.destPath, equalTo(child.destPath))
- }
-
- @Test public void testSourceIsFilteredTreeOfSources() {
- spec.from 'a'
- spec.from 'b'
-
- def filteredTree = context.mock(FileTree, 'filtered')
-
- context.checking {
- one(fileResolver).resolveFilesAsTree(['a', 'b'] as Set)
- def tree = context.mock(FileTree, 'source')
- will(returnValue(tree))
- one(tree).matching(withParam(equalTo(spec.patternSet)))
- will(returnValue(filteredTree))
- }
-
- assertThat(spec.source, sameInstance(filteredTree))
- }
-
- @Test public void testChildUsesPatternsFromParent() {
- CopySpecImpl child = spec.from('dir') {}
- Spec specInclude = [:] as Spec
- Spec specExclude = [:] as Spec
- Spec childInclude = [:] as Spec
- Spec childExclude = [:] as Spec
-
- spec.include('parent-include')
- spec.exclude('parent-exclude')
- spec.include(specInclude)
- spec.exclude(specExclude)
- child.include('child-include')
- child.exclude('child-exclude')
- child.include(childInclude)
- child.exclude(childExclude)
-
- PatternSet patterns = child.patternSet
- assertThat(patterns.includes, equalTo(['parent-include', 'child-include'] as Set))
- assertThat(patterns.excludes, equalTo(['parent-exclude', 'child-exclude'] as Set))
- assertThat(patterns.includeSpecs, equalTo([specInclude, childInclude] as Set))
- assertThat(patterns.excludeSpecs, equalTo([specExclude, childExclude] as Set))
- }
-
- @Test public void testChildUsesParentPatternsAsDefault() {
- CopySpecImpl child = spec.from('dir') {}
- Spec specInclude = [:] as Spec
- Spec specExclude = [:] as Spec
-
- spec.include('parent-include')
- spec.exclude('parent-exclude')
- spec.include(specInclude)
- spec.exclude(specExclude)
-
- PatternSet patterns = child.patternSet
- assertThat(patterns.includes, equalTo(['parent-include'] as Set))
- assertThat(patterns.excludes, equalTo(['parent-exclude'] as Set))
- assertThat(patterns.includeSpecs, equalTo([specInclude] as Set))
- assertThat(patterns.excludeSpecs, equalTo([specExclude] as Set))
- }
-
- @Test public void testChildUsesCaseSensitiveFlagFromParentAsDefault() {
- CopySpecImpl child = spec.from('dir') {}
- assertTrue(child.caseSensitive)
- assertTrue(child.patternSet.caseSensitive)
-
- spec.caseSensitive = false
- assertFalse(child.caseSensitive)
- assertFalse(child.patternSet.caseSensitive)
-
- child.caseSensitive = true
- assertTrue(child.caseSensitive)
- assertTrue(child.patternSet.caseSensitive)
- }
-
- @Test public void testChildUsesIncludeEmptyDirsFlagFromParentAsDefault() {
- def child = spec.from('dir') {}
- assert child.includeEmptyDirs
-
- spec.includeEmptyDirs = false
- assert !child.includeEmptyDirs
-
- child.includeEmptyDirs = true
- assert child.includeEmptyDirs
- }
-
- @Test public void testNoArgFilter() {
- spec.filter(StripJavaComments)
- assertThat(spec.allCopyActions.size(), equalTo(1))
- }
-
- @Test public void testArgFilter() {
- spec.filter(HeadFilter, lines: 15, skip: 2)
- assertThat(spec.allCopyActions.size(), equalTo(1))
- }
-
- @Test public void testExpand() {
- spec.expand(version: '1.2', skip: 2)
- assertThat(spec.allCopyActions.size(), equalTo(1))
- }
-
- @Test public void testTwoFilters() {
- spec.filter(StripJavaComments)
- spec.filter(HeadFilter, lines: 15, skip: 2)
-
- assertThat(spec.allCopyActions.size(), equalTo(2))
- }
-
- @Test public void testAddsStringNameTransformerToActions() {
- spec.rename("regexp", "replacement")
-
- assertThat(spec.allCopyActions.size(), equalTo(1))
- assertThat(spec.allCopyActions[0], instanceOf(RenamingCopyAction))
- assertThat(spec.allCopyActions[0].transformer, instanceOf(RegExpNameMapper))
- }
-
- @Test public void testAddsPatternNameTransformerToActions() {
- spec.rename(/regexp/, "replacement")
-
- assertThat(spec.allCopyActions.size(), equalTo(1))
- assertThat(spec.allCopyActions[0], instanceOf(RenamingCopyAction))
- assertThat(spec.allCopyActions[0].transformer, instanceOf(RegExpNameMapper))
- }
-
- @Test public void testAddsClosureToActions() {
- spec.rename {}
-
- assertThat(spec.allCopyActions.size(), equalTo(1))
- assertThat(spec.allCopyActions[0], instanceOf(RenamingCopyAction))
- }
-
- @Test public void testAddAction() {
- def action = context.mock(Action)
- spec.eachFile(action)
-
- assertThat(spec.allCopyActions, equalTo([action]))
- }
-
- @Test public void testAddActionAsClosure() {
- def action = {}
- spec.eachFile(action)
-
- assertThat(spec.allCopyActions.size(), equalTo(1))
- }
-
- @Test public void testSpecInheritsActionsFromParent() {
- Action parentAction = context.mock(Action, 'parent')
- Action childAction = context.mock(Action, 'child')
-
- spec.eachFile parentAction
- CopySpecImpl childSpec = spec.from('src') {
- eachFile childAction
- }
-
- assertThat(childSpec.allCopyActions, equalTo([parentAction, childAction]))
- }
-
- @Test public void testHasNoPermissionsByDefault() {
- assert spec.fileMode == null
- assert spec.dirMode == null
- }
-
- @Test public void testInheritsPermissionsFromParent() {
- spec.fileMode = 0x1
- spec.dirMode = 0x2
-
- CopySpecImpl child = spec.from('src') { }
- org.junit.Assert.assertEquals(0x1, child.fileMode)
- org.junit.Assert.assertEquals(0x2, child.dirMode)
- }
-
- @Test public void testHasNoSourceByDefault() {
- assertFalse(spec.hasSource())
- }
-
- @Test public void testHasSourceWhenSpecHasSource() {
- spec.from 'source'
- assertTrue(spec.hasSource())
- }
-
- @Test public void testHasSourceWhenChildSpecHasSource() {
- spec.from('source') {}
- assertTrue(spec.hasSource())
- }
-}
-
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/CopySpecMatchingTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/CopySpecMatchingTest.groovy
new file mode 100644
index 0000000..03b9f1d
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/CopySpecMatchingTest.groovy
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.file.copy
+
+import org.gradle.api.Action
+import org.gradle.api.file.FileCopyDetails
+import org.gradle.api.file.FileTree
+import org.gradle.api.file.RelativePath
+import org.gradle.api.internal.Actions
+import org.gradle.api.internal.file.TestFiles
+import org.gradle.internal.reflect.DirectInstantiator
+import spock.lang.Specification
+
+class CopySpecMatchingTest extends Specification {
+
+ DefaultCopySpec copySpec = new DefaultCopySpec(TestFiles.resolver(), new DirectInstantiator(), null)
+
+ FileTree fileTree = Mock()
+
+ def canMatchFiles() {
+ given:
+
+ FileCopyDetails details1 = Mock()
+ FileCopyDetails details2 = Mock()
+
+ details1.relativePath >> RelativePath.parse(true, 'path/abc.txt')
+ details2.relativePath >> RelativePath.parse(true, 'path/bcd.txt')
+
+ Action matchingAction = Mock()
+
+ when:
+ copySpec.filesMatching("**/a*", matchingAction)
+ copySpec.allCopyActions.each { copyAction ->
+ copyAction.execute(details1)
+ copyAction.execute(details2)
+ }
+
+ then:
+ 1 * matchingAction.execute(details1)
+ }
+
+
+ def canNotMatchFiles() {
+ given:
+
+ FileCopyDetails details1 = Mock()
+ FileCopyDetails details2 = Mock()
+
+ details1.relativePath >> RelativePath.parse(true, 'path/abc.txt')
+ details2.relativePath >> RelativePath.parse(true, 'path/bcd.txt')
+
+ Action matchingAction = Mock()
+
+ when:
+ copySpec.filesNotMatching("**/a*", matchingAction)
+ copySpec.allCopyActions.each { copyAction ->
+ copyAction.execute(details1)
+ copyAction.execute(details2)
+ }
+
+ then:
+ 1 * matchingAction.execute(details2)
+ }
+
+ def matchingSpecInherited() {
+ given:
+ DefaultCopySpec childSpec = copySpec.addChild()
+ when:
+ copySpec.filesMatching("**/*.java", Actions.doNothing())
+ then:
+ 1 == childSpec.allCopyActions.size()
+ childSpec.allCopyActions[0] instanceof MatchingCopyAction
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/DefaultCopySpecTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/DefaultCopySpecTest.groovy
new file mode 100644
index 0000000..1060738
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/DefaultCopySpecTest.groovy
@@ -0,0 +1,394 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.file.copy
+
+import org.apache.tools.ant.filters.HeadFilter
+import org.apache.tools.ant.filters.StripJavaComments
+import org.gradle.api.Action
+import org.gradle.api.file.DuplicatesStrategy
+import org.gradle.api.file.FileTree
+import org.gradle.api.file.RelativePath
+import org.gradle.api.internal.Actions
+import org.gradle.api.internal.file.FileResolver
+import org.gradle.api.specs.Spec
+import org.gradle.api.tasks.util.PatternSet
+import org.gradle.internal.reflect.DirectInstantiator
+import org.gradle.internal.reflect.Instantiator
+import org.gradle.test.fixtures.file.TestFile
+import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
+import org.gradle.util.JUnit4GroovyMockery
+import org.jmock.integration.junit4.JMock
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+import static org.hamcrest.Matchers.*
+import static org.junit.Assert.*
+
+ at RunWith(JMock)
+public class DefaultCopySpecTest {
+
+ @Rule public TestNameTestDirectoryProvider testDir = new TestNameTestDirectoryProvider();
+ private TestFile baseFile = testDir.testDirectory
+ private final JUnit4GroovyMockery context = new JUnit4GroovyMockery();
+ private final FileResolver fileResolver = context.mock(FileResolver);
+ private final Instantiator instantiator = new DirectInstantiator()
+ private final DefaultCopySpec spec = new DefaultCopySpec(fileResolver, instantiator)
+
+ private List<String> getTestSourceFileNames() {
+ ['first', 'second']
+ }
+
+ private List<File> getAbsoluteTestSources() {
+ testSourceFileNames.collect { new File(baseFile, it) }
+ }
+
+ @Test public void testAbsoluteFromList() {
+ List<File> sources = getAbsoluteTestSources();
+ spec.from(sources);
+ assertEquals([sources], spec.sourcePaths as List);
+ }
+
+ @Test public void testFromArray() {
+ List<File> sources = getAbsoluteTestSources();
+ spec.from(sources as File[]);
+ assertEquals(sources, spec.sourcePaths as List);
+ }
+
+ @Test public void testSourceWithClosure() {
+ DefaultCopySpec child = spec.from('source') {
+ }
+
+ assertThat(child, not(sameInstance(spec)))
+ assertEquals(['source'], child.sourcePaths as List);
+ }
+
+ @Test public void testMultipleSourcesWithClosure() {
+ DefaultCopySpec child = spec.from(['source1', 'source2']) {
+ }
+
+ assertThat(child, not(sameInstance(spec)))
+ assertEquals(['source1', 'source2'], child.sourcePaths.flatten() as List);
+ }
+
+ @Test public void testDefaultDestinationPathForRootSpec() {
+ assertThat(spec.destPath, equalTo(new RelativePath(false)))
+ }
+
+ @Test public void testInto() {
+ spec.into 'spec'
+ assertThat(spec.destPath, equalTo(new RelativePath(false, 'spec')))
+ spec.into '/'
+ assertThat(spec.destPath, equalTo(new RelativePath(false)))
+ }
+
+ @Test public void testIntoWithAClosure() {
+ spec.into { 'spec' }
+ assertThat(spec.destPath, equalTo(new RelativePath(false, 'spec')))
+ spec.into { return { 'spec' } }
+ assertThat(spec.destPath, equalTo(new RelativePath(false, 'spec')))
+ }
+
+ @Test public void testWithSpec() {
+ DefaultCopySpec other1 = new DefaultCopySpec(fileResolver, instantiator)
+ DefaultCopySpec other2 = new DefaultCopySpec(fileResolver, instantiator)
+
+ spec.with other1, other2
+ assertTrue(spec.sourcePaths.empty)
+ assertThat(spec.childSpecs.size(), equalTo(2))
+ }
+
+ @Test public void testWithSpecInheritsDestinationPathFromParent() {
+ DefaultCopySpec other = new DefaultCopySpec(fileResolver, instantiator)
+ other.into 'other'
+
+ spec.into 'spec'
+ spec.with other
+
+ CopySpecInternal child = spec.childSpecs[0]
+ assertThat(child.destPath, equalTo(new RelativePath(false, 'spec', 'other')))
+ }
+
+ @Test public void testDestinationWithClosure() {
+ DefaultCopySpec child = spec.into('target') {
+ }
+
+ assertThat(child, not(sameInstance(spec)))
+ assertThat(child.destPath, equalTo(new RelativePath(false, 'target')))
+ }
+
+ @Test public void testRootSpecHasRootPathAsDestination() {
+ assertThat(spec.destPath, equalTo(new RelativePath(false)))
+ }
+
+ @Test public void testChildSpecResolvesIntoArgRelativeToParentDestinationDir() {
+ DefaultCopySpec child = spec.from('somedir') { into 'child' }
+ assertThat(child.destPath, equalTo(new RelativePath(false, 'child')))
+
+ DefaultCopySpec grandchild = child.from('somedir') { into 'grandchild'}
+ assertThat(grandchild.destPath, equalTo(new RelativePath(false, 'child', 'grandchild')))
+
+ grandchild.into '/grandchild'
+ assertThat(grandchild.destPath, equalTo(new RelativePath(false, 'grandchild')))
+ }
+
+ @Test public void testChildSpecUsesParentDestinationPathAsDefault() {
+ DefaultCopySpec child = spec.from('somedir') { }
+ assertThat(child.destPath, equalTo(spec.destPath))
+
+ child.into 'child'
+
+ DefaultCopySpec grandchild = child.from('somedir') { }
+ assertThat(grandchild.destPath, equalTo(child.destPath))
+ }
+
+ @Test public void testSourceIsFilteredTreeOfSources() {
+ spec.from 'a'
+ spec.from 'b'
+
+ def filteredTree = context.mock(FileTree, 'filtered')
+
+ context.checking {
+ one(fileResolver).resolveFilesAsTree(['a', 'b'] as Set)
+ def tree = context.mock(FileTree, 'source')
+ will(returnValue(tree))
+ one(tree).matching(withParam(equalTo(spec.patternSet)))
+ will(returnValue(filteredTree))
+ }
+
+ assertThat(spec.source, sameInstance(filteredTree))
+ }
+
+ @Test public void testChildUsesPatternsFromParent() {
+ DefaultCopySpec child = spec.from('dir') {}
+ Spec specInclude = [:] as Spec
+ Spec specExclude = [:] as Spec
+ Spec childInclude = [:] as Spec
+ Spec childExclude = [:] as Spec
+
+ spec.include('parent-include')
+ spec.exclude('parent-exclude')
+ spec.include(specInclude)
+ spec.exclude(specExclude)
+ child.include('child-include')
+ child.exclude('child-exclude')
+ child.include(childInclude)
+ child.exclude(childExclude)
+
+ PatternSet patterns = child.patternSet
+ assertThat(patterns.includes, equalTo(['parent-include', 'child-include'] as Set))
+ assertThat(patterns.excludes, equalTo(['parent-exclude', 'child-exclude'] as Set))
+ assertThat(patterns.includeSpecs, equalTo([specInclude, childInclude] as Set))
+ assertThat(patterns.excludeSpecs, equalTo([specExclude, childExclude] as Set))
+ }
+
+ @Test public void testChildUsesParentPatternsAsDefault() {
+ DefaultCopySpec child = spec.from('dir') {}
+ Spec specInclude = [:] as Spec
+ Spec specExclude = [:] as Spec
+
+ spec.include('parent-include')
+ spec.exclude('parent-exclude')
+ spec.include(specInclude)
+ spec.exclude(specExclude)
+
+ PatternSet patterns = child.patternSet
+ assertThat(patterns.includes, equalTo(['parent-include'] as Set))
+ assertThat(patterns.excludes, equalTo(['parent-exclude'] as Set))
+ assertThat(patterns.includeSpecs, equalTo([specInclude] as Set))
+ assertThat(patterns.excludeSpecs, equalTo([specExclude] as Set))
+ }
+
+ @Test public void caseSensitiveFlagDefaultsToTrue() {
+ assert spec.caseSensitive
+ assert spec.patternSet.caseSensitive
+ }
+
+ @Test public void childUsesCaseSensitiveFlagFromParentAsDefault() {
+ def child = spec.from('dir') {}
+
+ assert child.caseSensitive
+ assert child.patternSet.caseSensitive
+
+ spec.caseSensitive = false
+ assert !child.caseSensitive
+ assert !child.patternSet.caseSensitive
+
+ child.caseSensitive = true
+ assert child.caseSensitive
+ assert child.patternSet.caseSensitive
+ }
+
+ @Test public void includeEmptyDirsFlagDefaultsToTrue() {
+ assert spec.includeEmptyDirs
+ }
+
+ @Test public void childUsesIncludeEmptyDirsFlagFromParentAsDefault() {
+ def child = spec.from('dir') {}
+
+ assert child.includeEmptyDirs
+
+ spec.includeEmptyDirs = false
+ assert !child.includeEmptyDirs
+
+ child.includeEmptyDirs = true
+ assert child.includeEmptyDirs
+ }
+
+ @Test public void testNoArgFilter() {
+ spec.filter(StripJavaComments)
+ assertThat(spec.allCopyActions.size(), equalTo(1))
+ }
+
+ @Test public void testArgFilter() {
+ spec.filter(HeadFilter, lines: 15, skip: 2)
+ assertThat(spec.allCopyActions.size(), equalTo(1))
+ }
+
+ @Test public void testExpand() {
+ spec.expand(version: '1.2', skip: 2)
+ assertThat(spec.allCopyActions.size(), equalTo(1))
+ }
+
+ @Test public void testTwoFilters() {
+ spec.filter(StripJavaComments)
+ spec.filter(HeadFilter, lines: 15, skip: 2)
+
+ assertThat(spec.allCopyActions.size(), equalTo(2))
+ }
+
+ @Test public void testAddsStringNameTransformerToActions() {
+ spec.rename("regexp", "replacement")
+
+ assertThat(spec.allCopyActions.size(), equalTo(1))
+ assertThat(spec.allCopyActions[0], instanceOf(RenamingCopyAction))
+ assertThat(spec.allCopyActions[0].transformer, instanceOf(RegExpNameMapper))
+ }
+
+ @Test public void testAddsPatternNameTransformerToActions() {
+ spec.rename(/regexp/, "replacement")
+
+ assertThat(spec.allCopyActions.size(), equalTo(1))
+ assertThat(spec.allCopyActions[0], instanceOf(RenamingCopyAction))
+ assertThat(spec.allCopyActions[0].transformer, instanceOf(RegExpNameMapper))
+ }
+
+ @Test public void testAddsClosureToActions() {
+ spec.rename {}
+
+ assertThat(spec.allCopyActions.size(), equalTo(1))
+ assertThat(spec.allCopyActions[0], instanceOf(RenamingCopyAction))
+ }
+
+ @Test public void testAddAction() {
+ def action = context.mock(Action)
+ spec.eachFile(action)
+
+ assertThat(spec.allCopyActions, equalTo([action]))
+ }
+
+ @Test public void testAddActionAsClosure() {
+ def action = {}
+ spec.eachFile(action)
+
+ assertThat(spec.allCopyActions.size(), equalTo(1))
+ }
+
+ @Test public void testSpecInheritsActionsFromParent() {
+ Action parentAction = context.mock(Action, 'parent')
+ Action childAction = context.mock(Action, 'child')
+
+ spec.eachFile parentAction
+ DefaultCopySpec childSpec = spec.from('src') {
+ eachFile childAction
+ }
+
+ assertThat(childSpec.allCopyActions, equalTo([parentAction, childAction]))
+ }
+
+ @Test public void testHasNoPermissionsByDefault() {
+ assert spec.fileMode == null
+ assert spec.dirMode == null
+ }
+
+ @Test public void testInheritsPermissionsFromParent() {
+ spec.fileMode = 0x1
+ spec.dirMode = 0x2
+
+ DefaultCopySpec child = spec.from('src') { }
+ org.junit.Assert.assertEquals(0x1, child.fileMode)
+ org.junit.Assert.assertEquals(0x2, child.dirMode)
+ }
+
+ @Test public void testHasNoSourceByDefault() {
+ assertFalse(spec.hasSource())
+ }
+
+ @Test public void testHasSourceWhenSpecHasSource() {
+ spec.from 'source'
+ assertTrue(spec.hasSource())
+ }
+
+ @Test public void testHasSourceWhenChildSpecHasSource() {
+ spec.from('source') {}
+ assertTrue(spec.hasSource())
+ }
+
+ @Test public void duplicatesStrategyDefaultsToInclude() {
+ assert spec.duplicatesStrategy == DuplicatesStrategy.INCLUDE
+ }
+
+ @Test public void childInheritsDuplicatesStrategyFromParent() {
+ def child = spec.from('dir') {}
+
+ assert child.duplicatesStrategy == DuplicatesStrategy.INCLUDE
+
+ spec.duplicatesStrategy = 'EXCLUDE'
+ assert child.duplicatesStrategy == DuplicatesStrategy.EXCLUDE
+
+ child.duplicatesStrategy = 'INCLUDE'
+ assert child.duplicatesStrategy == DuplicatesStrategy.INCLUDE
+ }
+
+ @Test public void testMatchingCreatesAppropriateAction() {
+ spec.filesMatching "root/**/a*", Actions.doNothing()
+ assertEquals(1, spec.allCopyActions.size())
+ assertThat(spec.allCopyActions[0], instanceOf(MatchingCopyAction))
+
+ Spec<RelativePath> matchSpec = spec.allCopyActions[0].matchSpec
+ assertTrue(matchSpec.isSatisfiedBy(RelativePath.parse(true, '/root/folder/abc')))
+ assertTrue(matchSpec.isSatisfiedBy(RelativePath.parse(true, '/root/abc')))
+ assertFalse(matchSpec.isSatisfiedBy(RelativePath.parse(true, '/notRoot/abc')))
+ assertFalse(matchSpec.isSatisfiedBy(RelativePath.parse(true, '/root/bbc')))
+ assertFalse(matchSpec.isSatisfiedBy(RelativePath.parse(true, '/notRoot/bbc')))
+ }
+
+ @Test public void testNotMatchingCreatesAppropriateAction() {
+ // no path component starting with an a
+ spec.filesNotMatching("**/a*/**", Actions.doNothing())
+ assertEquals(1, spec.allCopyActions.size())
+ assertThat(spec.allCopyActions[0], instanceOf(MatchingCopyAction))
+
+ Spec<RelativePath> matchSpec = spec.allCopyActions[0].matchSpec
+ assertTrue(matchSpec.isSatisfiedBy(RelativePath.parse(true, 'root/folder1/folder2')))
+ assertTrue(matchSpec.isSatisfiedBy(RelativePath.parse(true, 'modules/project1')))
+ assertFalse(matchSpec.isSatisfiedBy(RelativePath.parse(true, 'archives/folder/file')))
+ assertFalse(matchSpec.isSatisfiedBy(RelativePath.parse(true, 'root/archives/file')))
+ assertFalse(matchSpec.isSatisfiedBy(RelativePath.parse(true, 'root/folder/abc')))
+ }
+
+}
+
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/DeleteActionImplTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/DeleteActionImplTest.groovy
index b5f5439..bb13cca 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/DeleteActionImplTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/DeleteActionImplTest.groovy
@@ -21,9 +21,6 @@ import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
import org.junit.Rule
import spock.lang.Specification
-/**
- * @author Hans Dockter
- */
class DeleteActionImplTest extends Specification {
@Rule
TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider()
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/DuplicateHandlingCopyActionDecoratorTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/DuplicateHandlingCopyActionDecoratorTest.groovy
new file mode 100644
index 0000000..7fbb8c7
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/DuplicateHandlingCopyActionDecoratorTest.groovy
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.file.copy
+
+import org.gradle.api.Action
+import org.gradle.api.file.*
+import org.gradle.api.internal.ClosureBackedAction
+import org.gradle.api.internal.ThreadGlobalInstantiator
+import org.gradle.api.internal.file.CopyActionProcessingStreamAction
+import org.gradle.api.internal.tasks.SimpleWorkResult
+import org.gradle.api.tasks.WorkResult
+import org.gradle.internal.nativeplatform.filesystem.FileSystem
+import org.gradle.internal.reflect.Instantiator
+import org.gradle.logging.ConfigureLogging
+import org.gradle.logging.TestAppender
+import org.junit.Rule
+import spock.lang.Shared
+import spock.lang.Specification
+
+class DuplicateHandlingCopyActionDecoratorTest extends Specification {
+
+ private static interface MyCopySpec extends CopySpec, CopySpecInternal {}
+
+ def fileSystem = Mock(FileSystem)
+ def delegateAction = Mock(CopyActionProcessingStreamAction)
+ def delegate = new CopyAction() {
+ WorkResult execute(CopyActionProcessingStream stream) {
+ stream.process(delegateAction)
+ return new SimpleWorkResult(true)
+ }
+ }
+
+ def appender = new TestAppender()
+ @Rule ConfigureLogging logging = new ConfigureLogging(appender)
+
+ @Shared Instantiator instantiator = ThreadGlobalInstantiator.getOrCreate()
+ def driver = new CopyActionExecuter(instantiator, fileSystem)
+ def copySpec = Mock(MyCopySpec) {
+ getChildren() >> []
+ }
+
+ def duplicatesIncludedByDefault() {
+ given:
+ files 'path/file1.txt', 'path/file2.txt', 'path/file1.txt'
+ actions {}
+
+ when:
+ visit()
+
+ then:
+ 2 * delegateAction.processFile({ it.relativePath.pathString == '/root/path/file1.txt' })
+ 1 * delegateAction.processFile({ it.relativePath.pathString == '/root/path/file2.txt' })
+ }
+
+ def duplicatesExcludedByPerFileConfiguration() {
+ given:
+ files 'path/file1.txt', 'path/file2.txt', 'path/file1.txt'
+ actions { it.duplicatesStrategy = 'exclude' }
+
+ when:
+ visit()
+
+ then:
+ 1 * delegateAction.processFile({ FileCopyDetails it ->
+ it.relativePath.pathString == '/root/path/file1.txt'
+ })
+ 1 * delegateAction.processFile({ it.relativePath.pathString == '/root/path/file2.txt' })
+ }
+
+
+ def duplicatesExcludedEvenWhenRenamed() {
+ given:
+ files 'module1/path/file1.txt', 'module1/path/file2.txt', 'module2/path/file1.txt'
+
+ actions({ it.name = it.name.replaceAll('module[0-9]+/', '') }, { it.duplicatesStrategy = 'exclude' })
+
+ when:
+ visit()
+
+ then:
+ 1 * delegateAction.processFile({ it.relativePath.pathString == '/root/path/file1.txt' })
+ 1 * delegateAction.processFile({ it.relativePath.pathString == '/root/path/file2.txt' })
+ }
+
+ def duplicatesExcludedByDefaultConfiguration() {
+ given:
+ files 'path/file1.txt', 'path/file2.txt', 'path/file1.txt'
+ actions {}
+ copySpec.duplicatesStrategy >> DuplicatesStrategy.EXCLUDE
+
+ when:
+ visit()
+
+ then:
+ 1 * delegateAction.processFile({ it.relativePath.pathString == '/root/path/file1.txt' })
+ 1 * delegateAction.processFile({ it.relativePath.pathString == '/root/path/file2.txt' })
+ }
+
+ def duplicatesFailByDefaultConfiguration() {
+ given:
+ files 'path/file1.txt', 'path/file2.txt', 'path/file1.txt'
+ actions {}
+ copySpec.duplicatesStrategy >> DuplicatesStrategy.FAIL
+
+ when:
+ visit()
+
+ then:
+ 1 * delegateAction.processFile({ it.relativePath.pathString == '/root/path/file1.txt' })
+ 1 * delegateAction.processFile({ it.relativePath.pathString == '/root/path/file2.txt' })
+ thrown(DuplicateFileCopyingException)
+ }
+
+ def duplicatesWarnByDefaultConfiguration() {
+ given:
+ files 'path/file1.txt', 'path/file2.txt', 'path/file1.txt'
+ actions {}
+ copySpec.duplicatesStrategy >> DuplicatesStrategy.WARN
+
+ when:
+ visit()
+
+ then:
+ 2 * delegateAction.processFile({ it.relativePath.pathString == '/root/path/file1.txt' })
+ 1 * delegateAction.processFile({ it.relativePath.pathString == '/root/path/file2.txt' })
+ appender.toString().contains('WARN Encountered duplicate path "/root/path/file1.txt"')
+ }
+
+
+ def duplicatesWarnByPerFileConfiguration() {
+ given:
+ files 'path/file1.txt', 'path/file2.txt', 'path/file1.txt'
+ actions { it.duplicatesStrategy = 'warn' }
+
+ when:
+ visit()
+
+ then:
+ 2 * delegateAction.processFile({ it.relativePath.pathString == '/root/path/file1.txt' })
+ 1 * delegateAction.processFile({ it.relativePath.pathString == '/root/path/file2.txt' })
+ appender.toString().contains('WARN Encountered duplicate path "/root/path/file1.txt"')
+ }
+
+ def duplicatesFailByPerFileConfiguration() {
+ given:
+ files 'path/file1.txt', 'path/file2.txt', 'path/file1.txt'
+ actions { it.duplicatesStrategy = 'fail' }
+
+ when:
+ visit()
+
+ then:
+ 1 * delegateAction.processFile({ it.relativePath.pathString == '/root/path/file1.txt' })
+ 1 * delegateAction.processFile({ it.relativePath.pathString == '/root/path/file2.txt' })
+ thrown(DuplicateFileCopyingException)
+ }
+
+
+ void files(String... fileNames) {
+ copySpec.destPath >> new RelativePath(false, '/root')
+ def fileTree = Mock(FileTree)
+ copySpec.getSource() >> fileTree
+ fileTree.visit(_ as FileVisitor) >> { FileVisitor visitor ->
+ fileNames.each { filename ->
+ def fvd = Mock(FileVisitDetails) {
+ getRelativePath() >> new RelativePath(true, filename)
+ }
+ visitor.visitFile(fvd)
+ }
+ fileTree
+ }
+ copySpec.walk(_) >> { Action it -> it.execute(copySpec) }
+ }
+
+ void actions(Closure... actions) {
+ copySpec.allCopyActions >> actions.collect { new ClosureBackedAction<>(it) }
+ }
+
+ void visit() {
+ driver.execute(copySpec, delegate)
+ }
+
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/FileCopyActionImplTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/FileCopyActionImplTest.java
deleted file mode 100644
index afca533..0000000
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/FileCopyActionImplTest.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.file.copy;
-
-import org.gradle.api.internal.file.FileResolver;
-import org.jmock.Expectations;
-import org.jmock.integration.junit4.JMock;
-import org.jmock.integration.junit4.JUnit4Mockery;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.io.File;
-
-import static org.hamcrest.Matchers.equalTo;
-import static org.hamcrest.Matchers.nullValue;
-import static org.junit.Assert.assertThat;
-
- at RunWith(JMock.class)
-public class FileCopyActionImplTest {
- private final JUnit4Mockery context = new JUnit4Mockery();
- private final FileResolver fileResolver = context.mock(FileResolver.class);
- private final FileCopyActionImpl spec = new FileCopyActionImpl(fileResolver, context.mock(CopySpecVisitor.class));
-
- @Test public void testRootSpecResolvesItsIntoArgAsDestinationDir() {
- final File file = new File("base dir");
-
- spec.into("somedir");
-
- context.checking(new Expectations() {{
- allowing(fileResolver).resolve("somedir");
- will(returnValue(file));
- }});
-
- assertThat(spec.getDestinationDir(), equalTo(file));
- }
-
- @Test public void testRootSpecHasNoDefaultDestinationDir() {
- assertThat(spec.getDestinationDir(), nullValue());
- }
-
-}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/FileCopyActionTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/FileCopyActionTest.java
new file mode 100644
index 0000000..85981fe
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/FileCopyActionTest.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.file.copy;
+
+import org.gradle.api.file.RelativePath;
+import org.gradle.api.internal.file.BaseDirFileResolver;
+import org.gradle.internal.nativeplatform.filesystem.FileSystems;
+import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider;
+import org.jmock.Expectations;
+import org.jmock.integration.junit4.JMock;
+import org.jmock.integration.junit4.JUnit4Mockery;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+import java.io.IOException;
+
+import static org.gradle.api.internal.file.copy.CopyActionExecuterUtil.visit;
+
+ at RunWith(JMock.class)
+public class FileCopyActionTest {
+ private File destDir;
+ private final JUnit4Mockery context = new JUnit4Mockery();
+
+ @Rule
+ public TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider();
+
+ @Before
+ public void setUp() throws IOException {
+ destDir = tmpDir.getTestDirectory().file("dest");
+ }
+
+ @Test
+ public void plainCopy() {
+ FileCopyAction visitor = new FileCopyAction(new BaseDirFileResolver(FileSystems.getDefault(), destDir));
+ visit(visitor,
+ file(new RelativePath(true, "rootfile.txt"), new File(destDir, "rootfile.txt")),
+ file(new RelativePath(true, "subdir", "anotherfile.txt"), new File(destDir, "subdir/anotherfile.txt"))
+ );
+ }
+
+ private FileCopyDetailsInternal file(final RelativePath relativePath, final File targetFile) {
+ final FileCopyDetailsInternal details = context.mock(FileCopyDetailsInternal.class, relativePath.getPathString());
+ context.checking(new Expectations() {{
+ allowing(details).getRelativePath();
+ will(returnValue(relativePath));
+ one(details).copyTo(targetFile);
+ }});
+ return details;
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/FileCopySpecVisitorTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/FileCopySpecVisitorTest.java
deleted file mode 100644
index 06345eb..0000000
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/FileCopySpecVisitorTest.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.file.copy;
-
-import org.gradle.api.InvalidUserDataException;
-import org.gradle.api.file.FileVisitDetails;
-import org.gradle.api.file.RelativePath;
-import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider;
-import org.jmock.Expectations;
-import org.jmock.integration.junit4.JMock;
-import org.jmock.integration.junit4.JUnit4Mockery;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.io.File;
-import java.io.IOException;
-
-import static org.hamcrest.Matchers.equalTo;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
-
- at RunWith(JMock.class)
-public class FileCopySpecVisitorTest {
- private File destDir;
- private final JUnit4Mockery context = new JUnit4Mockery();
- private final FileCopySpecVisitor visitor = new FileCopySpecVisitor();
- @Rule
- public TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider();
-
- @Before
- public void setUp() throws IOException {
- destDir = tmpDir.getTestDirectory().file("dest");
- }
-
- @Test
- public void plainCopy() {
- visitor.startVisit(action(destDir));
-
- visitor.visitDir(file(new RelativePath(false), destDir));
-
- visitor.visitFile(file(new RelativePath(true, "rootfile.txt"), new File(destDir, "rootfile.txt")));
-
- visitor.visitDir(file(new RelativePath(false, "subdir"), new File(destDir, "subdir")));
-
- visitor.visitFile(file(new RelativePath(true, "subdir", "anotherfile.txt"), new File(destDir, "subdir/anotherfile.txt")));
- }
-
- @Test
- public void testThrowsExceptionWhenNoDestinationSet() {
- try {
- visitor.startVisit(action(null));
- fail();
- } catch (InvalidUserDataException e) {
- assertThat(e.getMessage(), equalTo("No copy destination directory has been specified, use 'into' to specify a target directory."));
- }
- }
-
- private FileCopyAction action(final File destDir) {
- final FileCopyAction action = context.mock(FileCopyAction.class);
- context.checking(new Expectations(){{
- allowing(action).getDestinationDir();
- will(returnValue(destDir));
- }});
- return action;
- }
-
- private FileVisitDetails file(final RelativePath relativePath, final File targetFile) {
- final FileVisitDetails details = context.mock(FileVisitDetails.class, relativePath.getPathString());
- context.checking(new Expectations(){{
- allowing(details).getRelativePath();
- will(returnValue(relativePath));
- one(details).copyTo(targetFile);
- }});
- return details;
- }
-}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/FilterChainTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/FilterChainTest.java
index 019ec32..8dc07b3 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/FilterChainTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/FilterChainTest.java
@@ -16,7 +16,7 @@
package org.gradle.api.internal.file.copy;
import org.apache.commons.io.IOUtils;
-import org.gradle.util.HelperUtil;
+import org.gradle.util.TestUtil;
import org.gradle.util.WrapUtil;
import org.junit.Test;
@@ -59,7 +59,7 @@ public class FilterChainTest {
@Test
public void canAddLineFilterReaderToEndOfChain() {
- filterChain.add(HelperUtil.TEST_CLOSURE);
+ filterChain.add(TestUtil.TEST_CLOSURE);
Reader transformedReader = filterChain.transform(originalReader);
assertThat(transformedReader, instanceOf(LineFilter.class));
}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/MappingCopySpecVisitorTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/MappingCopySpecVisitorTest.java
deleted file mode 100644
index 6ddd161..0000000
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/MappingCopySpecVisitorTest.java
+++ /dev/null
@@ -1,400 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.file.copy;
-
-import org.gradle.api.Action;
-import org.gradle.api.file.FileCopyDetails;
-import org.gradle.api.file.FileVisitDetails;
-import org.gradle.api.file.RelativePath;
-import org.gradle.internal.nativeplatform.filesystem.FileSystem;
-import org.gradle.test.fixtures.file.TestFile;
-import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider;
-import org.gradle.util.HelperUtil;
-import org.hamcrest.Description;
-import org.jmock.Expectations;
-import org.jmock.Sequence;
-import org.jmock.api.Invocation;
-import org.jmock.integration.junit4.JMock;
-import org.jmock.integration.junit4.JUnit4Mockery;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.IOException;
-
-import static org.gradle.util.Matchers.*;
-import static org.gradle.util.WrapUtil.toList;
-import static org.hamcrest.Matchers.*;
-import static org.junit.Assert.*;
-
- at RunWith(JMock.class)
-public class MappingCopySpecVisitorTest {
- private final JUnit4Mockery context = new JUnit4Mockery();
-
- @Rule
- public final TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider();
- private final CopySpecVisitor delegate = context.mock(CopySpecVisitor.class);
- private final ReadableCopySpec spec = context.mock(ReadableCopySpec.class);
- private final FileVisitDetails details = context.mock(FileVisitDetails.class);
- private final FileSystem fileSystem = context.mock(FileSystem.class);
- private final MappingCopySpecVisitor visitor = new MappingCopySpecVisitor(delegate, fileSystem);
-
- @Test
- public void delegatesStartAndEndVisitMethods() {
- final CopyAction action = context.mock(CopyAction.class);
-
- context.checking(new Expectations() {{
- one(delegate).startVisit(action);
- one(delegate).endVisit();
- }});
-
- visitor.startVisit(action);
- visitor.endVisit();
- }
-
- @Test
- public void delegatesDidWork() {
- context.checking(new Expectations() {{
- allowing(delegate).getDidWork();
- will(onConsecutiveCalls(returnValue(true), returnValue(false)));
- }});
-
- assertTrue(visitor.getDidWork());
- assertFalse(visitor.getDidWork());
- }
-
- @Test
- public void visitFileInvokesEachCopyAction() {
- @SuppressWarnings("unchecked")
- final Action<FileCopyDetails> action1 = context.mock(Action.class, "action1");
- @SuppressWarnings("unchecked")
- final Action<FileCopyDetails> action2 = context.mock(Action.class, "action2");
- final Collector<FileCopyDetails> collectDetails1 = collector();
- final Collector<Object> collectDetails2 = collector();
- final Collector<Object> collectDetails3 = collector();
-
- context.checking(new Expectations() {{
- Sequence seq = context.sequence("seq");
- one(delegate).visitSpec(spec);
- inSequence(seq);
-
- allowing(spec).getAllCopyActions();
- will(returnValue(toList(action1, action2)));
-
- one(action1).execute(with(notNullValue(FileCopyDetails.class)));
- inSequence(seq);
- will(collectTo(collectDetails1));
-
- one(action2).execute(with(notNullValue(FileCopyDetails.class)));
- inSequence(seq);
- will(collectTo(collectDetails2));
-
- one(delegate).visitFile(with(not(sameInstance(details))));
- inSequence(seq);
- will(collectTo(collectDetails3));
- }});
-
- visitor.visitSpec(spec);
- visitor.visitFile(details);
-
- assertThat(collectDetails1.get(), sameInstance(collectDetails2.get()));
- assertThat(collectDetails1.get(), sameInstance(collectDetails3.get()));
- }
-
- @Test
- public void initialRelativePathForFileIsSpecPathPlusFilePath() {
- FileCopyDetails copyDetails = expectActionExecutedWhenFileVisited();
-
- context.checking(new Expectations() {{
- allowing(spec).getDestPath();
- will(returnValue(new RelativePath(false, "spec")));
- allowing(details).getRelativePath();
- will(returnValue(new RelativePath(true, "file")));
- }});
-
- assertThat(copyDetails.getRelativePath(), equalTo(new RelativePath(true, "spec", "file")));
- }
-
- @Test
- public void relativePathForDirIsSpecPathPlusFilePath() {
- FileVisitDetails visitDetails = expectSpecAndDirVisited();
-
- context.checking(new Expectations() {{
- allowing(spec).getDestPath();
- will(returnValue(new RelativePath(false, "spec")));
- allowing(details).getRelativePath();
- will(returnValue(new RelativePath(false, "dir")));
- }});
-
- assertThat(visitDetails.getRelativePath(), equalTo(new RelativePath(false, "spec", "dir")));
- }
-
- @Test
- public void copyActionCanChangeFileDestinationPath() {
- FileCopyDetails copyDetails = expectActionExecutedWhenFileVisited();
-
- RelativePath newPath = new RelativePath(true, "new");
- copyDetails.setRelativePath(newPath);
- assertThat(copyDetails.getRelativePath(), equalTo(newPath));
-
- copyDetails.setPath("/a/b");
- assertThat(copyDetails.getRelativePath(), equalTo(new RelativePath(true, "a", "b")));
-
- copyDetails.setName("new name");
- assertThat(copyDetails.getRelativePath(), equalTo(new RelativePath(true, "a", "new name")));
- }
-
- @Test
- public void copyActionCanExcludeFile() {
- @SuppressWarnings("unchecked")
- final Action<FileCopyDetails> action1 = context.mock(Action.class, "action1");
- @SuppressWarnings("unchecked")
- final Action<FileCopyDetails> action2 = context.mock(Action.class, "action2");
-
- context.checking(new Expectations() {{
- Sequence seq = context.sequence("seq");
- one(delegate).visitSpec(spec);
- inSequence(seq);
-
- allowing(spec).getAllCopyActions();
- will(returnValue(toList(action1, action2)));
-
- one(action1).execute(with(notNullValue(FileCopyDetails.class)));
- inSequence(seq);
- will(excludeFile());
- }});
-
- visitor.visitSpec(spec);
- visitor.visitFile(details);
- }
-
- @Test
- public void copyActionCanFilterContentWhenFileIsCopiedToStream() {
- final FileCopyDetails mappedDetails = expectActionExecutedWhenFileVisited();
-
- context.checking(new Expectations() {{
- one(details).open();
- will(returnValue(new ByteArrayInputStream("content".getBytes())));
- }});
-
- mappedDetails.filter(HelperUtil.toClosure("{ 'PREFIX: ' + it } "));
-
- ByteArrayOutputStream outstr = new ByteArrayOutputStream();
- mappedDetails.copyTo(outstr);
- assertThat(new String(outstr.toByteArray()), equalTo("PREFIX: content"));
- }
-
- @Test
- public void copyActionCanFilterContentWhenFileIsCopiedToFile() {
- final FileCopyDetails mappedDetails = expectActionExecutedWhenFileVisited();
-
- // shortcut the permission logic by explicitly setting permissions
- mappedDetails.setMode(0644);
-
- context.checking(new Expectations() {{
-
- one(details).open();
- will(returnValue(new ByteArrayInputStream("content".getBytes())));
- one(details).isDirectory();
- will(returnValue(false));
- one(details).getLastModified();
- will(returnValue(90L));
- }});
-
- mappedDetails.filter(HelperUtil.toClosure("{ 'PREFIX: ' + it } "));
-
- TestFile destDir = tmpDir.getTestDirectory().file("test.txt");
- mappedDetails.copyTo(destDir);
- destDir.assertContents(equalTo("PREFIX: content"));
- }
-
- @Test
- public void explicitFileModeDefinitionIsAppliedToTarget() throws IOException {
- final FileCopyDetails mappedDetails = expectActionExecutedWhenFileVisited();
- final TestFile destFile = tmpDir.getTestDirectory().file("test.txt").createFile();
-
- // set file permissions explicitly
- mappedDetails.setMode(0645);
- context.checking(new Expectations() {{
- one(details).copyTo(destFile);
- will(returnValue(true));
- one(fileSystem).chmod(destFile, 0645);
- }});
- mappedDetails.copyTo(destFile);
- }
-
- @Test
- public void getSizeReturnsSizeOfFilteredContent() {
- final FileCopyDetails mappedDetails = expectActionExecutedWhenFileVisited();
-
- context.checking(new Expectations() {{
- one(details).open();
- will(returnValue(new ByteArrayInputStream("content".getBytes())));
- }});
-
- mappedDetails.filter(HelperUtil.toClosure("{ 'PREFIX: ' + it } "));
-
- assertThat(mappedDetails.getSize(), equalTo(15L));
- }
-
- @Test
- public void wrappedFileElementDelegatesToSourceForRemainingMethods() {
- final FileVisitDetails mappedDetails = expectSpecAndFileVisited();
- final File file = new File("file");
-
- context.checking(new Expectations() {{
- one(details).getFile();
- will(returnValue(file));
- }});
-
- assertThat(mappedDetails.getFile(), sameInstance(file));
- }
-
- @Test
- public void permissionsArePreservedByDefault() {
- FileCopyDetails copyDetails = expectActionExecutedWhenFileVisited();
-
- context.checking(new Expectations() {{
- one(details).isDirectory();
- will(returnValue(true));
-
- one(spec).getDirMode();
- will(returnValue(null));
-
- one(details).getMode();
- will(returnValue(123));
- }});
-
- assertThat(copyDetails.getMode(), equalTo(123));
- }
-
- @Test
- public void filePermissionsCanBeOverriddenBySpec() {
- FileCopyDetails copyDetails = expectActionExecutedWhenFileVisited();
-
- context.checking(new Expectations() {{
- one(details).isDirectory();
- will(returnValue(false));
-
- one(spec).getFileMode();
- will(returnValue(234));
- }});
-
- assertThat(copyDetails.getMode(), equalTo(234));
- }
-
-
- @Test
- public void directoryPermissionsCanBeOverriddenBySpec() {
- FileCopyDetails copyDetails = expectActionExecutedWhenFileVisited();
-
- context.checking(new Expectations() {{
- one(details).isDirectory();
- will(returnValue(true));
-
- one(spec).getDirMode();
- will(returnValue(345));
- }});
-
- assertThat(copyDetails.getMode(), equalTo(345));
- }
-
- @Test
- public void permissionsCanBeOverriddenByCopyAction() {
- FileCopyDetails copyDetails = expectActionExecutedWhenFileVisited();
-
- copyDetails.setMode(456);
- assertThat(copyDetails.getMode(), equalTo(456));
- }
-
- private FileVisitDetails expectSpecAndFileVisited() {
- final Collector<FileVisitDetails> collector = collector();
-
- context.checking(new Expectations() {{
- one(delegate).visitSpec(spec);
-
- one(spec).getAllCopyActions();
- will(returnValue(toList()));
-
- one(delegate).visitFile(with(not(sameInstance(details))));
- will(collectTo(collector));
- }});
-
- visitor.visitSpec(spec);
- visitor.visitFile(details);
- return collector.get();
- }
-
- private FileCopyDetails expectActionExecutedWhenFileVisited() {
- final Collector<FileCopyDetails> collectDetails = collector();
- @SuppressWarnings("unchecked")
- final Action<FileCopyDetails> action = context.mock(Action.class, "action1");
-
- context.checking(new Expectations() {{
- Sequence seq = context.sequence("seq");
- one(delegate).visitSpec(spec);
- inSequence(seq);
-
- allowing(spec).getAllCopyActions();
- will(returnValue(toList(action)));
-
- one(action).execute(with(notNullValue(FileCopyDetails.class)));
- inSequence(seq);
- will(collectTo(collectDetails));
-
- one(delegate).visitFile(with(not(sameInstance(details))));
- inSequence(seq);
- }});
-
- visitor.visitSpec(spec);
- visitor.visitFile(details);
-
- return collectDetails.get();
- }
-
- private FileVisitDetails expectSpecAndDirVisited() {
- final Collector<FileVisitDetails> collector = collector();
-
- context.checking(new Expectations() {{
- one(delegate).visitSpec(spec);
- one(delegate).visitDir(with(not(sameInstance(details))));
-
- will(collectTo(collector));
- }});
-
- visitor.visitSpec(spec);
- visitor.visitDir(details);
-
- return collector.get();
- }
-
- private org.jmock.api.Action excludeFile() {
- return new org.jmock.api.Action() {
- public void describeTo(Description description) {
- description.appendText("exclude file");
- }
-
- public Object invoke(Invocation invocation) throws Throwable {
- FileCopyDetails details = (FileCopyDetails) invocation.getParameter(0);
- details.exclude();
- return null;
- }
- };
- }
-}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/NormalizingCopyActionDecoratorTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/NormalizingCopyActionDecoratorTest.java
new file mode 100644
index 0000000..9830cf4
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/NormalizingCopyActionDecoratorTest.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.file.copy;
+
+import org.gradle.api.file.FileCopyDetails;
+import org.gradle.api.file.RelativePath;
+import org.gradle.api.internal.file.CopyActionProcessingStreamAction;
+import org.gradle.api.internal.tasks.SimpleWorkResult;
+import org.gradle.api.tasks.WorkResult;
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.jmock.Expectations;
+import org.jmock.integration.junit4.JMock;
+import org.jmock.integration.junit4.JUnit4Mockery;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.gradle.api.internal.file.copy.CopyActionExecuterUtil.visit;
+
+ at RunWith(JMock.class)
+public class NormalizingCopyActionDecoratorTest {
+ private final JUnit4Mockery context = new JUnit4Mockery();
+ private final CopyActionProcessingStreamAction delegateAction = context.mock(CopyActionProcessingStreamAction.class);
+ private final CopyAction delegate = new CopyAction() {
+ public WorkResult execute(CopyActionProcessingStream stream) {
+ stream.process(delegateAction);
+ return new SimpleWorkResult(true);
+ }
+ };
+ private final NormalizingCopyActionDecorator decorator = new NormalizingCopyActionDecorator(delegate);
+
+ @Test
+ public void doesNotVisitADirectoryWhichHasBeenVisitedBefore() {
+ final FileCopyDetailsInternal details = file("dir", true, true);
+ final FileCopyDetailsInternal file = file("dir/file", false, true);
+
+ context.checking(new Expectations() {{
+ one(delegateAction).processFile(details);
+ one(delegateAction).processFile(file);
+ }});
+
+ visit(decorator, details, file, details);
+ }
+
+ @Test
+ public void visitsDirectoryAncestorsWhichHaveNotBeenVisited() {
+ final FileCopyDetailsInternal dir1 = file("a/b/c", true, true);
+ final FileCopyDetailsInternal file1 = file("a/b/c/file", false, true);
+
+ decorator.execute(new CopyActionProcessingStream() {
+ public void process(CopyActionProcessingStreamAction action) {
+ context.checking(new Expectations() {{
+ one(delegateAction).processFile(with(hasPath("a")));
+ one(delegateAction).processFile(with(hasPath("a/b")));
+ one(delegateAction).processFile(dir1);
+ one(delegateAction).processFile(file1);
+ }});
+
+ action.processFile(dir1);
+ action.processFile(file1);
+
+ final FileCopyDetailsInternal dir2 = file("a/b/d/e", true, true);
+ final FileCopyDetailsInternal file2 = file("a/b/d/e/file", false, true);
+
+ context.checking(new Expectations() {{
+ one(delegateAction).processFile(with(hasPath("a/b/d")));
+ one(delegateAction).processFile(dir2);
+ one(delegateAction).processFile(file2);
+ }});
+
+ action.processFile(dir2);
+ action.processFile(file2);
+ }
+ });
+ }
+
+ @Test
+ public void visitsFileAncestorsWhichHaveNotBeenVisited() {
+ final FileCopyDetailsInternal details = file("a/b/c", false, true);
+
+ context.checking(new Expectations() {{
+ one(delegateAction).processFile(with(hasPath("a")));
+ one(delegateAction).processFile(with(hasPath("a/b")));
+ one(delegateAction).processFile(details);
+ }});
+
+ visit(decorator, details);
+ }
+
+ @Test
+ public void visitsAnEmptyDirectoryIfCorrespondingOptionIsOn() {
+ final FileCopyDetailsInternal dir = file("dir", true, true);
+
+ context.checking(new Expectations() {{
+ one(delegateAction).processFile(dir);
+ }});
+
+ visit(decorator, dir);
+ }
+
+ @Test
+ public void doesNotVisitAnEmptyDirectoryIfCorrespondingOptionIsOff() {
+ final FileCopyDetailsInternal dir = file("dir", true, false);
+
+ context.checking(new Expectations() {{
+ exactly(0).of(delegateAction).processFile(dir);
+ }});
+
+ visit(decorator, dir);
+ }
+
+ private FileCopyDetailsInternal file(final String path, final boolean isDir, final boolean includeEmptyDirs) {
+ final FileCopyDetailsInternal details = context.mock(FileCopyDetailsInternal.class, path);
+ context.checking(new Expectations() {{
+ allowing(details).getRelativePath();
+ will(returnValue(RelativePath.parse(false, path)));
+ allowing(details).isDirectory();
+ will(returnValue(isDir));
+ allowing(details).isIncludeEmptyDirs();
+ will(returnValue(includeEmptyDirs));
+ }});
+ return details;
+ }
+
+ private Matcher<FileCopyDetailsInternal> hasPath(final String path) {
+ return new BaseMatcher<FileCopyDetailsInternal>() {
+ public void describeTo(Description description) {
+ description.appendText("has path ").appendValue(path);
+ }
+
+ public boolean matches(Object o) {
+ FileCopyDetails details = (FileCopyDetails) o;
+ return details.getRelativePath().getPathString().equals(path);
+ }
+ };
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/NormalizingCopySpecVisitorTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/NormalizingCopySpecVisitorTest.java
deleted file mode 100644
index 53e3889..0000000
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/NormalizingCopySpecVisitorTest.java
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.file.copy;
-
-import org.gradle.api.file.FileVisitDetails;
-import org.gradle.api.file.RelativePath;
-import org.hamcrest.BaseMatcher;
-import org.hamcrest.Description;
-import org.hamcrest.Matcher;
-import org.jmock.Expectations;
-import org.jmock.integration.junit4.JUnit4Mockery;
-import org.jmock.integration.junit4.JMock;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
- at RunWith(JMock.class)
-public class NormalizingCopySpecVisitorTest {
- private final JUnit4Mockery context = new JUnit4Mockery();
- private final CopySpecVisitor delegate = context.mock(CopySpecVisitor.class);
- private final NormalizingCopySpecVisitor visitor = new NormalizingCopySpecVisitor(delegate);
- private final ReadableCopySpec spec = context.mock(ReadableCopySpec.class);
-
- private void allowGetIncludeEmptyDirs() {
- context.checking(new Expectations() {{
- allowing(spec).getIncludeEmptyDirs();
- will(returnValue(true));
- }});
- }
-
- @Test
- public void doesNotVisitADirectoryWhichHasBeenVisitedBefore() {
- final FileVisitDetails details = file("dir");
- final FileVisitDetails file = file("dir/file");
-
- allowGetIncludeEmptyDirs();
-
- context.checking(new Expectations() {{
- one(delegate).visitSpec(spec);
- one(delegate).visitDir(details);
- one(delegate).visitFile(file);
- }});
-
- visitor.visitSpec(spec);
- visitor.visitDir(details);
- visitor.visitFile(file);
- visitor.visitDir(details);
- }
-
- @Test
- public void doesNotVisitADirectoryUntilAChildFileIsVisited() {
- final FileVisitDetails dir = file("dir");
- final FileVisitDetails file = file("dir/file");
-
- allowGetIncludeEmptyDirs();
-
- context.checking(new Expectations() {{
- one(delegate).visitSpec(spec);
- }});
-
- visitor.visitSpec(spec);
- visitor.visitDir(dir);
-
- context.checking(new Expectations() {{
- one(delegate).visitDir(dir);
- one(delegate).visitFile(file);
- }});
-
- visitor.visitFile(file);
- }
-
- @Test
- public void doesNotVisitADirectoryUntilAChildDirIsVisited() {
- final FileVisitDetails dir = file("dir");
- final FileVisitDetails subdir = file("dir/sub");
- final FileVisitDetails file = file("dir/sub/file");
-
- allowGetIncludeEmptyDirs();
-
- context.checking(new Expectations() {{
- one(delegate).visitSpec(spec);
- }});
-
- visitor.visitSpec(spec);
- visitor.visitDir(dir);
- visitor.visitDir(subdir);
-
- context.checking(new Expectations() {{
- one(delegate).visitDir(dir);
- one(delegate).visitDir(subdir);
- one(delegate).visitFile(file);
- }});
-
- visitor.visitFile(file);
- }
-
- @Test
- public void visitsDirectoryAncestorsWhichHaveNotBeenVisited() {
- final FileVisitDetails dir1 = file("a/b/c");
- final FileVisitDetails file1 = file("a/b/c/file");
-
- allowGetIncludeEmptyDirs();
-
- context.checking(new Expectations() {{
- one(delegate).visitSpec(spec);
- one(delegate).visitDir(with(hasPath("a")));
- one(delegate).visitDir(with(hasPath("a/b")));
- one(delegate).visitDir(dir1);
- one(delegate).visitFile(file1);
- }});
-
- visitor.visitSpec(spec);
- visitor.visitDir(dir1);
- visitor.visitFile(file1);
-
- final FileVisitDetails dir2 = file("a/b/d/e");
- final FileVisitDetails file2 = file("a/b/d/e/file");
-
- context.checking(new Expectations() {{
- one(delegate).visitSpec(spec);
- one(delegate).visitDir(with(hasPath("a/b/d")));
- one(delegate).visitDir(dir2);
- one(delegate).visitFile(file2);
- }});
-
- visitor.visitSpec(spec);
- visitor.visitDir(dir2);
- visitor.visitFile(file2);
- }
-
- @Test
- public void visitsFileAncestorsWhichHaveNotBeenVisited() {
- final FileVisitDetails details = file("a/b/c");
-
- allowGetIncludeEmptyDirs();
-
- context.checking(new Expectations() {{
- one(delegate).visitSpec(spec);
- one(delegate).visitDir(with(hasPath("a")));
- one(delegate).visitDir(with(hasPath("a/b")));
- one(delegate).visitFile(details);
- }});
-
- visitor.visitSpec(spec);
- visitor.visitFile(details);
- }
-
- @Test
- public void visitSpecDelegatesToVisitor() {
- allowGetIncludeEmptyDirs();
-
- context.checking(new Expectations() {{
- one(delegate).visitSpec(spec);
- }});
-
- visitor.visitSpec(spec);
- }
-
- @Test
- public void visitsAnEmptyDirectoryIfCorrespondingOptionIsOn() {
- final FileVisitDetails dir = file("dir");
-
- context.checking(new Expectations() {{
- one(spec).getIncludeEmptyDirs();
- will(returnValue(true));
- one(delegate).visitSpec(spec);
- one(delegate).visitDir(dir);
- one(delegate).endVisit();
- }});
-
- visitor.visitSpec(spec);
- visitor.visitDir(dir);
- visitor.endVisit();
- }
-
- @Test
- public void doesNotVisitAnEmptyDirectoryIfCorrespondingOptionIsOff() {
- FileVisitDetails dir = file("dir");
-
- context.checking(new Expectations() {{
- one(spec).getIncludeEmptyDirs();
- will(returnValue(false));
- one(delegate).visitSpec(spec);
- one(delegate).endVisit();
- }});
-
- visitor.visitSpec(spec);
- visitor.visitDir(dir);
- visitor.endVisit();
- }
-
- private FileVisitDetails file(final String path) {
- final FileVisitDetails details = context.mock(FileVisitDetails.class, path);
- context.checking(new Expectations() {{
- allowing(details).getRelativePath();
- will(returnValue(RelativePath.parse(false, path)));
- }});
- return details;
- }
-
- private Matcher<FileVisitDetails> hasPath(final String path) {
- return new BaseMatcher<FileVisitDetails>() {
- public void describeTo(Description description) {
- description.appendText("has path ").appendValue(path);
- }
-
- public boolean matches(Object o) {
- FileVisitDetails details = (FileVisitDetails) o;
- return details.getRelativePath().getPathString().equals(path);
- }
- };
- }
-}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/SyncCopyActionDecoratorTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/SyncCopyActionDecoratorTest.groovy
new file mode 100644
index 0000000..604afe8
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/SyncCopyActionDecoratorTest.groovy
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.file.copy
+
+import org.gradle.api.Action
+import org.gradle.api.internal.file.BaseDirFileResolver
+import org.gradle.internal.nativeplatform.filesystem.FileSystems
+import org.gradle.internal.reflect.DirectInstantiator
+import org.gradle.test.fixtures.file.WorkspaceTest
+
+class SyncCopyActionDecoratorTest extends WorkspaceTest {
+
+ FileCopier copier
+
+ def setup() {
+ copier = new FileCopier(new DirectInstantiator(), new BaseDirFileResolver(FileSystems.getDefault(), testDirectory))
+ }
+
+ void deletesExtraFilesFromDestinationDirectoryAtTheEndOfVisit() {
+ given:
+ file("src").with {
+ createFile("subdir/included.txt")
+ createFile("included.txt")
+ }
+
+ file("dest").with {
+ createFile("subdir/included.txt")
+ createFile("subdir/extra.txt")
+ createFile("included.txt")
+ createFile("extra.txt")
+ createDir("extra")
+ }
+
+ when:
+ def result = copier.sync({
+ it.from "src"
+ it.into "dest"
+ } as Action)
+
+ then:
+ result.didWork
+ file("dest").assertHasDescendants("subdir/included.txt", "included.txt");
+ }
+
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/SyncCopySpecVisitorTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/SyncCopySpecVisitorTest.java
deleted file mode 100644
index 68e806b..0000000
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/copy/SyncCopySpecVisitorTest.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.file.copy;
-
-import org.gradle.api.file.FileVisitDetails;
-import org.gradle.api.file.FileVisitor;
-import org.gradle.api.file.RelativePath;
-import org.gradle.api.internal.file.collections.DirectoryFileTree;
-import org.gradle.test.fixtures.file.TestFile;
-import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider;
-import org.jmock.Expectations;
-import org.jmock.integration.junit4.JMock;
-import org.jmock.integration.junit4.JUnit4Mockery;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.io.File;
-import java.lang.reflect.Field;
-import java.util.HashSet;
-import java.util.Set;
-
-import static org.hamcrest.Matchers.notNullValue;
-import static org.junit.Assert.assertTrue;
-
- at RunWith(JMock.class)
-public class SyncCopySpecVisitorTest {
- @Rule
- public final TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider();
- private final JUnit4Mockery context = new JUnit4Mockery();
- private final CopySpecVisitor delegate = context.mock(CopySpecVisitor.class);
- private final SyncCopySpecVisitor visitor = new SyncCopySpecVisitor(delegate);
-
- @Before
- public void setUp() {
- context.checking(new Expectations(){{
- allowing(delegate).startVisit(with(notNullValue(CopyAction.class)));
- allowing(delegate).visitFile(with(notNullValue(FileVisitDetails.class)));
- allowing(delegate).visitDir(with(notNullValue(FileVisitDetails.class)));
- allowing(delegate).endVisit();
- }});
- }
-
- @Test
- public void deletesExtraFilesFromDestinationDirectoryAtTheEndOfVisit() {
- TestFile destDir = tmpDir.createDir("dest");
- destDir.createFile("subdir/included.txt");
- destDir.createFile("subdir/extra.txt");
- destDir.createFile("included.txt");
- destDir.createFile("extra.txt");
-
- visitor.startVisit(action(destDir));
- visitor.visitDir(dir("subdir"));
- visitor.visitFile(file("subdir/included.txt"));
- visitor.visitFile(file("included.txt"));
- visitor.endVisit();
-
- destDir.assertHasDescendants("subdir/included.txt", "included.txt");
- }
-
- @Test
- public void deletesExtraDirectoriesFromDestinationDirectoryAtTheEndOfVisit() throws Exception {
- TestFile destDir = tmpDir.createDir("dest");
- destDir.createFile("included.txt");
- destDir.createFile("extra/extra.txt");
-
- visitor.startVisit(action(destDir));
- visitor.visitFile(file("included.txt"));
-
- // TODO - delete these
- Field field = SyncCopySpecVisitor.class.getDeclaredField("visited");
- field.setAccessible(true);
- Set visited = (Set) field.get(visitor);
- assert visited.contains(new RelativePath(true, "included.txt"));
- assert !visited.contains(new RelativePath(true, "extra", "extra.txt"));
- final Set<RelativePath> actual = new HashSet<RelativePath>();
- new DirectoryFileTree(destDir).postfix().visit(new FileVisitor() {
- public void visitDir(FileVisitDetails dirDetails) {
- }
-
- public void visitFile(FileVisitDetails fileDetails) {
- actual.add(fileDetails.getRelativePath());
- }
- });
- assert actual.contains(new RelativePath(true, "included.txt"));
- assert actual.contains(new RelativePath(true, "extra", "extra.txt"));
-
- visitor.endVisit();
-
- destDir.assertHasDescendants("included.txt");
- }
-
- @Test
- public void doesNotDeleteDestDirectoryWhenNothingCopied() {
- TestFile destDir = tmpDir.createDir("dest");
- destDir.createFile("extra.txt");
- destDir.createFile("extra/extra.txt");
-
- visitor.startVisit(action(destDir));
- visitor.endVisit();
-
- destDir.assertHasDescendants();
- }
-
- @Test
- public void didWorkWhenDelegateDidWork() {
- context.checking(new Expectations() {{
- allowing(delegate).getDidWork();
- will(returnValue(true));
- }});
-
- assertTrue(visitor.getDidWork());
- }
-
- @Test
- public void didWorkWhenFilesDeleted() {
- TestFile destDir = tmpDir.createDir("dest");
- destDir.createFile("extra.txt");
-
- visitor.startVisit(action(destDir));
- visitor.endVisit();
-
- assertTrue(visitor.getDidWork());
- }
-
- private FileCopyAction action(final File destDir) {
- final FileCopyAction action = context.mock(FileCopyAction.class);
-
- context.checking(new Expectations() {{
- allowing(action).getDestinationDir();
- will(returnValue(destDir));
- }});
-
- return action;
- }
-
- private FileVisitDetails file(final String path) {
- return file(RelativePath.parse(true, path));
- }
-
- private FileVisitDetails dir(final String path) {
- return file(RelativePath.parse(false, path));
- }
-
- private FileVisitDetails file(final RelativePath relativePath) {
- final FileVisitDetails details = context.mock(FileVisitDetails.class, relativePath.toString());
-
- context.checking(new Expectations(){{
- allowing(details).getRelativePath();
- will(returnValue(relativePath));
- }});
-
- return details;
- }
-}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/pattern/RegExpPatternStepTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/pattern/RegExpPatternStepTest.java
index fffdd9f..d4df917 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/pattern/RegExpPatternStepTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/pattern/RegExpPatternStepTest.java
@@ -16,11 +16,9 @@
package org.gradle.api.internal.file.pattern;
import org.junit.Test;
+
import static org.junit.Assert.*;
-/**
- * @author Steve Appling
- */
public class RegExpPatternStepTest {
private void testPatternEscape(String expected, String pattern) {
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/initialization/DefaultScriptHandlerFactoryTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/initialization/DefaultScriptHandlerFactoryTest.groovy
index 36e91a4..c87aaec 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/initialization/DefaultScriptHandlerFactoryTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/initialization/DefaultScriptHandlerFactoryTest.groovy
@@ -24,7 +24,7 @@ import org.gradle.api.internal.file.FileResolver
import org.gradle.groovy.scripts.ScriptSource
import spock.lang.Specification
-import org.gradle.util.MutableURLClassLoader
+import org.gradle.internal.classloader.MutableURLClassLoader
class DefaultScriptHandlerFactoryTest extends Specification {
private final DependencyMetaDataProvider metaDataProvider = Mock()
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/initialization/DefaultScriptHandlerTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/initialization/DefaultScriptHandlerTest.groovy
index e295350..5f79e1e 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/initialization/DefaultScriptHandlerTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/initialization/DefaultScriptHandlerTest.groovy
@@ -19,87 +19,76 @@ import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.ConfigurationContainer
import org.gradle.api.artifacts.dsl.DependencyHandler
import org.gradle.api.artifacts.dsl.RepositoryHandler
-import org.gradle.util.JUnit4GroovyMockery
-import org.gradle.util.WrapUtil
-import org.jmock.integration.junit4.JMock
-import org.junit.Test
-import org.junit.runner.RunWith
-
-import static org.hamcrest.Matchers.*
-import static org.junit.Assert.*
import org.gradle.groovy.scripts.ScriptSource
-import org.gradle.util.MutableURLClassLoader
+import org.gradle.util.WrapUtil
+import org.gradle.internal.classloader.MutableURLClassLoader
import org.gradle.util.ConfigureUtil
- at RunWith(JMock)
-public class DefaultScriptHandlerTest {
- private final JUnit4GroovyMockery context = new JUnit4GroovyMockery()
- private final RepositoryHandler repositoryHandler = context.mock(RepositoryHandler.class)
- private final DependencyHandler dependencyHandler = context.mock(DependencyHandler.class)
- private final ConfigurationContainer configurationContainer = context.mock(ConfigurationContainer.class)
- private final Configuration configuration = context.mock(Configuration.class)
- private final ScriptSource scriptSource = context.mock(ScriptSource.class)
- private final MutableURLClassLoader classLoader = context.mock(MutableURLClassLoader.class)
-
- @Test void addsClasspathConfiguration() {
- context.checking {
- one(configurationContainer).add('classpath')
- }
+import spock.lang.Specification
+class DefaultScriptHandlerTest extends Specification {
+ RepositoryHandler repositoryHandler = Mock()
+ DependencyHandler dependencyHandler = Mock()
+ ConfigurationContainer configurationContainer = Mock()
+ Configuration configuration = Mock()
+ ScriptSource scriptSource = Mock()
+ MutableURLClassLoader classLoader = Mock()
+
+ def "adds classpath configuration"() {
+ when:
new DefaultScriptHandler(scriptSource, repositoryHandler, dependencyHandler, configurationContainer, classLoader)
+
+ then:
+ 1 * configurationContainer.create('classpath')
}
- @Test void createsAClassLoaderAndAddsContentsOfClassPathConfiguration() {
- DefaultScriptHandler handler = handler()
+ def "creates a class loader and adds contents of classpath configuration"() {
+ def handler = handler()
+ def classLoader = handler.classLoader
- ClassLoader classLoader = handler.classLoader
- assertThat(classLoader, sameInstance(this.classLoader))
+ expect:
+ classLoader.is this.classLoader
- File file1 = new File('a')
- File file2 = new File('b')
- context.checking {
- one(configuration).getFiles()
- will(returnValue(WrapUtil.toSet(file1, file2)))
- one(classLoader).addURL(file1.toURI().toURL())
- one(classLoader).addURL(file2.toURI().toURL())
- }
+ def file1 = new File('a')
+ def file2 = new File('b')
+ when:
handler.updateClassPath()
- }
- @Test void canConfigureRepositories() {
- DefaultScriptHandler handler = handler()
+ then:
+ 1 * configuration.getFiles() >> WrapUtil.toSet(file1, file2)
+ 1 * classLoader.addURL(file1.toURI().toURL())
+ 1 * classLoader.addURL(file2.toURI().toURL())
+ }
+ def "can configure repositories"() {
+ def handler = handler()
def configure = {
mavenCentral()
}
- context.checking {
- one(repositoryHandler).configure(configure)
- will { ConfigureUtil.configure(configure, repositoryHandler, false) }
- one(repositoryHandler).mavenCentral()
- }
-
+ when:
handler.repositories(configure)
- }
- @Test void canConfigureDependencies() {
- DefaultScriptHandler handler = handler()
+ then:
+ 1 * repositoryHandler.configure(configure) >> { ConfigureUtil.configure(configure, repositoryHandler, false) }
+ 1 * repositoryHandler.mavenCentral()
+ }
- context.checking {
- one(dependencyHandler).add('config', 'dep')
- }
+ def "can configure dependencies"() {
+ def handler = handler()
+ when:
handler.dependencies {
add('config', 'dep')
}
+
+ then:
+ 1 * dependencyHandler.add('config', 'dep')
}
private DefaultScriptHandler handler() {
- context.checking {
- one(configurationContainer).add('classpath')
- will(returnValue(configuration))
- }
+ 1 * configurationContainer.create('classpath') >> configuration
return new DefaultScriptHandler(scriptSource, repositoryHandler, dependencyHandler, configurationContainer, classLoader)
}
}
\ No newline at end of file
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/notations/parsers/ClosureToSpecNotationParserTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/notations/parsers/ClosureToSpecNotationParserTest.groovy
index fbd7659..cf86bae 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/notations/parsers/ClosureToSpecNotationParserTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/notations/parsers/ClosureToSpecNotationParserTest.groovy
@@ -19,9 +19,6 @@ package org.gradle.api.internal.notations.parsers
import org.gradle.api.internal.notations.api.UnsupportedNotationException
import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 10/12/12
- */
class ClosureToSpecNotationParserTest extends Specification {
private ClosureToSpecNotationParser parser = new ClosureToSpecNotationParser()
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/notations/parsers/TimeUnitsParserTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/notations/parsers/TimeUnitsParserTest.groovy
index 8f70474..a016f9e 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/notations/parsers/TimeUnitsParserTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/notations/parsers/TimeUnitsParserTest.groovy
@@ -22,9 +22,6 @@ import spock.lang.Specification
import static java.util.concurrent.TimeUnit.MILLISECONDS
import static java.util.concurrent.TimeUnit.NANOSECONDS
-/**
- * by Szczepan Faber, created at: 2/12/13
- */
class TimeUnitsParserTest extends Specification {
def parser = new TimeUnitsParser()
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/notations/parsers/TypedNotationParserTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/notations/parsers/TypedNotationParserTest.groovy
index 85881bd..e1a896f 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/notations/parsers/TypedNotationParserTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/notations/parsers/TypedNotationParserTest.groovy
@@ -20,9 +20,6 @@ package org.gradle.api.internal.notations.parsers;
import org.gradle.api.internal.notations.api.UnsupportedNotationException
import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 11/10/11
- */
public class TypedNotationParserTest extends Specification {
def parser = new DummyParser();
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/plugins/DefaultConventionTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/plugins/DefaultConventionTest.groovy
index 99c255a..87d0f77 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/plugins/DefaultConventionTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/plugins/DefaultConventionTest.groovy
@@ -16,19 +16,17 @@
package org.gradle.api.internal.plugins
-import org.gradle.internal.reflect.Instantiator
import org.gradle.api.internal.ThreadGlobalInstantiator
import org.gradle.api.plugins.Convention
import org.gradle.api.plugins.TestPluginConvention1
import org.gradle.api.plugins.TestPluginConvention2
+import org.gradle.internal.reflect.Instantiator
import org.junit.Before
import org.junit.Test
+
import static org.hamcrest.Matchers.equalTo
import static org.junit.Assert.*
-/**
- * @author Hans Dockter
- */
class DefaultConventionTest {
Convention convention
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/plugins/DefaultPluginContainerTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/plugins/DefaultPluginContainerTest.java
new file mode 100644
index 0000000..5f2e756
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/plugins/DefaultPluginContainerTest.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.plugins;
+
+import org.gradle.api.Plugin;
+import org.gradle.api.internal.project.DefaultProject;
+import org.gradle.api.internal.project.TestPlugin1;
+import org.gradle.api.internal.project.TestPlugin2;
+import org.gradle.api.plugins.UnknownPluginException;
+import org.gradle.util.TestUtil;
+import org.jmock.Expectations;
+import org.jmock.integration.junit4.JUnit4Mockery;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.assertThat;
+
+public class DefaultPluginContainerTest {
+ protected String pluginId = "somePluginId";
+ protected JUnit4Mockery context = new JUnit4Mockery();
+ private final DefaultProject project = TestUtil.createRootProject();
+
+ private PluginRegistry pluginRegistryStub = context.mock(PluginRegistry.class);
+ private DefaultPluginContainer container = new DefaultPluginContainer(pluginRegistryStub, project);
+
+ private TestPlugin1 pluginWithIdMock = new TestPlugin1();
+ private TestPlugin2 pluginWithoutIdMock = new TestPlugin2();
+
+ @Before
+ public void setUp() {
+ context.checking(new Expectations() {{
+ allowing(pluginRegistryStub).getTypeForId(pluginId); will(returnValue(TestPlugin1.class));
+ allowing(pluginRegistryStub).loadPlugin(TestPlugin1.class); will(returnValue(pluginWithIdMock));
+ allowing(pluginRegistryStub).loadPlugin(TestPlugin2.class); will(returnValue(pluginWithoutIdMock));
+ }});
+ }
+
+ @Test
+ public void usePluginById() {
+ Plugin addedPlugin = container.apply(pluginId);
+ assertThat(pluginWithIdMock, sameInstance(addedPlugin));
+ assertThat(container.apply(pluginId), sameInstance(addedPlugin));
+
+ assertThat(container.findPlugin(addedPlugin.getClass()), sameInstance(addedPlugin));
+ assertThat(container.findPlugin(pluginId), sameInstance(addedPlugin));
+ }
+
+ @Test
+ public void usePluginWithIdByType() {
+ Class<? extends Plugin> type = pluginWithIdMock.getClass();
+
+ Plugin addedPlugin = container.apply(type);
+ assertThat(pluginWithIdMock, sameInstance(addedPlugin));
+ assertThat(container.apply(type), sameInstance(addedPlugin));
+ assertThat(container.apply(pluginId), sameInstance(addedPlugin));
+
+ assertThat(container.findPlugin(type), sameInstance(addedPlugin));
+ assertThat(container.findPlugin(pluginId), sameInstance(addedPlugin));
+ }
+
+ @Test
+ public void usePluginWithoutId() {
+ Class<? extends Plugin> type = pluginWithoutIdMock.getClass();
+ Plugin addedPlugin = container.apply(type);
+ assertThat(pluginWithoutIdMock, sameInstance(addedPlugin));
+ assertThat(container.apply(type), sameInstance(addedPlugin));
+
+ assertThat(container.findPlugin(type), sameInstance(addedPlugin));
+ }
+
+ @Test
+ public void hasAndFindForPluginWithId() {
+ container.apply(pluginId);
+ assertThat(container.hasPlugin(pluginId), equalTo(true));
+ assertThat(container.hasPlugin(pluginWithIdMock.getClass()), equalTo(true));
+ assertThat(container.findPlugin(pluginId), sameInstance((Plugin) pluginWithIdMock));
+ assertThat(container.findPlugin(pluginWithIdMock.getClass()), sameInstance((Plugin) pluginWithIdMock));
+ }
+
+ @Test
+ public void hasAndFindForUnknownPluginId() {
+ context.checking(new Expectations() {{
+ allowing(pluginRegistryStub).getTypeForId("unknown"); will(throwException(new UnknownPluginException("unknown")));
+ }});
+
+ assertThat(container.hasPlugin("unknown"), equalTo(false));
+ assertThat(container.findPlugin("unknown"), nullValue());
+ }
+
+ @Test
+ public void hasAndFindForPluginWithoutId() {
+ Plugin plugin = pluginWithoutIdMock;
+ Class<? extends Plugin> pluginType = plugin.getClass();
+ container.apply(pluginType);
+ assertThat(container.hasPlugin(pluginType), equalTo(true));
+ assertThat(container.findPlugin(pluginType), sameInstance(plugin));
+ }
+
+ @Test
+ public void hasAndFindPluginByTypeWithUnknownPlugin() {
+ assertThat(container.hasPlugin(TestPlugin2.class), equalTo(false));
+ assertThat(container.findPlugin(TestPlugin2.class), nullValue());
+ }
+
+ @Test(expected = UnknownPluginException.class)
+ public void getNonUsedPluginById() {
+ container.getPlugin(pluginId);
+ }
+
+ @Test(expected = UnknownPluginException.class)
+ public void getNonUsedPluginByType() {
+ container.getPlugin(TestPlugin1.class);
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/plugins/DefaultProjectsPluginContainerTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/plugins/DefaultProjectsPluginContainerTest.java
deleted file mode 100644
index 5c27473..0000000
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/plugins/DefaultProjectsPluginContainerTest.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.plugins;
-
-import org.gradle.api.Plugin;
-import org.gradle.api.internal.project.DefaultProject;
-import org.gradle.api.internal.project.TestPlugin1;
-import org.gradle.api.internal.project.TestPlugin2;
-import org.gradle.api.plugins.UnknownPluginException;
-import org.gradle.util.HelperUtil;
-import org.jmock.Expectations;
-import org.jmock.integration.junit4.JUnit4Mockery;
-import org.junit.Before;
-import org.junit.Test;
-
-import static org.hamcrest.Matchers.*;
-import static org.junit.Assert.assertThat;
-
-/**
- * @author Hans Dockter
- */
-public class DefaultProjectsPluginContainerTest {
- protected String pluginId = "somePluginId";
- protected JUnit4Mockery context = new JUnit4Mockery();
- private final DefaultProject project = HelperUtil.createRootProject();
-
- private PluginRegistry pluginRegistryStub = context.mock(PluginRegistry.class);
- private DefaultProjectsPluginContainer container = new DefaultProjectsPluginContainer(pluginRegistryStub, project);
-
- private TestPlugin1 pluginWithIdMock = new TestPlugin1();
- private TestPlugin2 pluginWithoutIdMock = new TestPlugin2();
-
- @Before
- public void setUp() {
- context.checking(new Expectations() {{
- allowing(pluginRegistryStub).getTypeForId(pluginId); will(returnValue(TestPlugin1.class));
- allowing(pluginRegistryStub).loadPlugin(TestPlugin1.class); will(returnValue(pluginWithIdMock));
- allowing(pluginRegistryStub).loadPlugin(TestPlugin2.class); will(returnValue(pluginWithoutIdMock));
- }});
- }
-
- @Test
- public void usePluginById() {
- Plugin addedPlugin = container.apply(pluginId);
- assertThat(pluginWithIdMock, sameInstance(addedPlugin));
- assertThat(container.apply(pluginId), sameInstance(addedPlugin));
-
- assertThat(container.findPlugin(addedPlugin.getClass()), sameInstance(addedPlugin));
- assertThat(container.findPlugin(pluginId), sameInstance(addedPlugin));
- }
-
- @Test
- public void usePluginWithIdByType() {
- Class<? extends Plugin> type = pluginWithIdMock.getClass();
-
- Plugin addedPlugin = container.apply(type);
- assertThat(pluginWithIdMock, sameInstance(addedPlugin));
- assertThat(container.apply(type), sameInstance(addedPlugin));
- assertThat(container.apply(pluginId), sameInstance(addedPlugin));
-
- assertThat(container.findPlugin(type), sameInstance(addedPlugin));
- assertThat(container.findPlugin(pluginId), sameInstance(addedPlugin));
- }
-
- @Test
- public void usePluginWithoutId() {
- Class<? extends Plugin> type = pluginWithoutIdMock.getClass();
- Plugin addedPlugin = container.apply(type);
- assertThat(pluginWithoutIdMock, sameInstance(addedPlugin));
- assertThat(container.apply(type), sameInstance(addedPlugin));
-
- assertThat(container.findPlugin(type), sameInstance(addedPlugin));
- }
-
- @Test
- public void hasAndFindForPluginWithId() {
- container.apply(pluginId);
- assertThat(container.hasPlugin(pluginId), equalTo(true));
- assertThat(container.hasPlugin(pluginWithIdMock.getClass()), equalTo(true));
- assertThat(container.findPlugin(pluginId), sameInstance((Plugin) pluginWithIdMock));
- assertThat(container.findPlugin(pluginWithIdMock.getClass()), sameInstance((Plugin) pluginWithIdMock));
- }
-
- @Test
- public void hasAndFindForUnknownPluginId() {
- context.checking(new Expectations() {{
- allowing(pluginRegistryStub).getTypeForId("unknown"); will(throwException(new UnknownPluginException("unknown")));
- }});
-
- assertThat(container.hasPlugin("unknown"), equalTo(false));
- assertThat(container.findPlugin("unknown"), nullValue());
- }
-
- @Test
- public void hasAndFindForPluginWithoutId() {
- Plugin plugin = pluginWithoutIdMock;
- Class<? extends Plugin> pluginType = plugin.getClass();
- container.apply(pluginType);
- assertThat(container.hasPlugin(pluginType), equalTo(true));
- assertThat(container.findPlugin(pluginType), sameInstance(plugin));
- }
-
- @Test
- public void hasAndFindPluginByTypeWithUnknownPlugin() {
- assertThat(container.hasPlugin(TestPlugin2.class), equalTo(false));
- assertThat(container.findPlugin(TestPlugin2.class), nullValue());
- }
-
- @Test(expected = UnknownPluginException.class)
- public void getNonUsedPluginById() {
- container.getPlugin(pluginId);
- }
-
- @Test(expected = UnknownPluginException.class)
- public void getNonUsedPluginByType() {
- container.getPlugin(TestPlugin1.class);
- }
-}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/plugins/ExtensionContainerTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/plugins/ExtensionContainerTest.groovy
index 2c78e79..8a4a1b0 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/plugins/ExtensionContainerTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/plugins/ExtensionContainerTest.groovy
@@ -23,9 +23,6 @@ import org.gradle.api.plugins.ExtensionAware
import org.gradle.api.plugins.ExtraPropertiesExtension
import spock.lang.Specification
-/**
- * @author: Szczepan Faber, created at: 6/24/11
- */
public class ExtensionContainerTest extends Specification {
def container = new DefaultConvention(ThreadGlobalInstantiator.getOrCreate())
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/plugins/ExtensionsStorageTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/plugins/ExtensionsStorageTest.groovy
index 9e7049f..9056abc 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/plugins/ExtensionsStorageTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/plugins/ExtensionsStorageTest.groovy
@@ -17,6 +17,7 @@
package org.gradle.api.internal.plugins
import org.gradle.api.Action
+import org.gradle.api.InvalidUserDataException
import org.gradle.api.UnknownDomainObjectException
import org.gradle.api.plugins.DeferredConfigurable
import spock.lang.Specification
@@ -132,6 +133,81 @@ class ExtensionsStorageTest extends Specification {
1 * delegate.call(2)
}
+ def "propagates configure exception on each attempt to access deferred configurable exception"() {
+
+ TestDeferredExtension extension = new TestDeferredExtension()
+ def delegate = Mock(TestExtension)
+ extension.delegate = delegate
+
+ given:
+ storage.add("ext", extension)
+ storage.configureExtension("ext", {
+ throw new RuntimeException("bad")
+ })
+
+ when:
+ storage.getByName("ext")
+
+ then:
+ def first = thrown RuntimeException
+ first.message == "bad"
+
+ when:
+ storage.getByName("ext")
+
+ then:
+ def second = thrown RuntimeException
+ second == first
+ }
+
+ def "rethrows unknown domain object exception thrown by deferred configurable extension config"() {
+
+ TestDeferredExtension extension = new TestDeferredExtension()
+ def delegate = Mock(TestExtension)
+ extension.delegate = delegate
+
+ when:
+ storage.add("ext", extension)
+ storage.configureExtension("ext", {
+ throw new UnknownDomainObjectException("ORIGINAL")
+ })
+
+ then:
+ 0 * _
+
+ when:
+ storage.findByType(TestDeferredExtension)
+
+ then:
+ def t = thrown UnknownDomainObjectException
+ t.message == "ORIGINAL"
+ }
+
+ def "cannot configure deferred configurable extension after access"() {
+
+ TestDeferredExtension extension = new TestDeferredExtension()
+ def delegate = Mock(TestExtension)
+ extension.delegate = delegate
+
+ given:
+ storage.add("ext", extension)
+ storage.configureExtension("ext", {
+ it.call(1)
+ })
+
+ and:
+ storage.getByName("ext")
+
+ when:
+ storage.configureExtension("ext", {
+ it.call(2)
+ })
+
+ then:
+ def t = thrown InvalidUserDataException
+ t.message == "Cannot configure the 'ext' extension after it has been accessed."
+ }
+
public static interface TestExtension {
void call(def value);
}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/project/DefaultAntBuilderFactoryTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/project/DefaultAntBuilderFactoryTest.groovy
index 87a851b..b6e240a 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/project/DefaultAntBuilderFactoryTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/project/DefaultAntBuilderFactoryTest.groovy
@@ -17,7 +17,7 @@ package org.gradle.api.internal.project
import org.apache.tools.ant.BuildListener
import org.gradle.api.Project
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import org.gradle.util.JUnit4GroovyMockery
import org.jmock.integration.junit4.JMock
import org.junit.Before
@@ -30,7 +30,7 @@ import static org.junit.Assert.*
public class DefaultAntBuilderFactoryTest {
private final JUnit4GroovyMockery context = new JUnit4GroovyMockery()
private final BuildListener listener = context.mock(BuildListener)
- private final Project project = HelperUtil.createRootProject()
+ private final Project project = TestUtil.createRootProject()
private final DefaultAntBuilderFactory factory = new DefaultAntBuilderFactory(listener, project)
@Before
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/project/DefaultAntBuilderTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/project/DefaultAntBuilderTest.groovy
index f3c5ad4..37025bc 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/project/DefaultAntBuilderTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/project/DefaultAntBuilderTest.groovy
@@ -18,7 +18,7 @@ package org.gradle.api.internal.project
import groovy.xml.MarkupBuilder
import org.junit.Test
import org.gradle.api.Project
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import static org.junit.Assert.*
import static org.hamcrest.Matchers.*
import static org.gradle.util.Matchers.*
@@ -28,7 +28,7 @@ import org.apache.tools.ant.Target
import org.apache.tools.ant.Task
class DefaultAntBuilderTest {
- private final Project project = HelperUtil.createRootProject()
+ private final Project project = TestUtil.createRootProject()
private final def ant = new DefaultAntBuilder(project)
@Test
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/project/DefaultIsolatedAntBuilderTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/project/DefaultIsolatedAntBuilderTest.groovy
index ebf5826..c4082c8 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/project/DefaultIsolatedAntBuilderTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/project/DefaultIsolatedAntBuilderTest.groovy
@@ -28,7 +28,7 @@ import org.gradle.api.internal.classpath.ModuleRegistry
import org.gradle.api.internal.project.ant.BasicAntBuilder
import org.gradle.logging.ConfigureLogging
import org.gradle.logging.TestAppender
-import org.gradle.util.DefaultClassLoaderFactory
+import org.gradle.internal.classloader.DefaultClassLoaderFactory
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@@ -36,7 +36,7 @@ import static org.hamcrest.Matchers.*
import static org.junit.Assert.assertThat
import static org.junit.Assert.fail
import org.apache.tools.ant.Task
-import org.gradle.util.ClasspathUtil
+import org.gradle.internal.classloader.ClasspathUtil
class DefaultIsolatedAntBuilderTest {
private final ModuleRegistry moduleRegistry = new DefaultModuleRegistry()
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/project/DefaultProjectRegistryTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/project/DefaultProjectRegistryTest.java
index 7b9c0d1..24bb1c7 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/project/DefaultProjectRegistryTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/project/DefaultProjectRegistryTest.java
@@ -18,7 +18,7 @@ package org.gradle.api.internal.project;
import org.gradle.api.InvalidUserDataException;
import org.gradle.api.Project;
import org.gradle.api.specs.Spec;
-import org.gradle.util.HelperUtil;
+import org.gradle.util.TestUtil;
import org.junit.Before;
import org.junit.Test;
@@ -26,18 +26,11 @@ import java.util.SortedSet;
import java.util.TreeSet;
import static junit.framework.Assert.assertSame;
-import static org.gradle.util.WrapUtil.*;
+import static org.gradle.util.WrapUtil.toSet;
+import static org.gradle.util.WrapUtil.toSortedSet;
import static org.hamcrest.Matchers.*;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
import static org.junit.Assert.*;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-/**
- * @author Hans Dockter
- */
public class DefaultProjectRegistryTest {
public static final String CHILD_NAME = "child";
public static final String CHILD_CHILD_NAME = "childchild";
@@ -50,9 +43,9 @@ public class DefaultProjectRegistryTest {
@Before
public void setUp() {
projectRegistry = new DefaultProjectRegistry<ProjectInternal>();
- rootMock = HelperUtil.createRootProject();
- childMock = HelperUtil.createChildProject(rootMock, CHILD_NAME);
- childChildMock = HelperUtil.createChildProject(childMock, CHILD_CHILD_NAME);
+ rootMock = TestUtil.createRootProject();
+ childMock = TestUtil.createChildProject(rootMock, CHILD_NAME);
+ childChildMock = TestUtil.createChildProject(childMock, CHILD_CHILD_NAME);
projectRegistry.addProject(rootMock);
projectRegistry.addProject(childMock);
projectRegistry.addProject(childChildMock);
@@ -77,7 +70,7 @@ public class DefaultProjectRegistryTest {
@Test
public void cannotLocateProjectsWithAmbiguousProjectDir() {
- DefaultProject duplicateProjectDirProject = HelperUtil.createChildProject(childMock, "childchild2", childMock.getProjectDir());
+ DefaultProject duplicateProjectDirProject = TestUtil.createChildProject(childMock, "childchild2", childMock.getProjectDir());
projectRegistry.addProject(duplicateProjectDirProject);
try {
@@ -91,7 +84,7 @@ public class DefaultProjectRegistryTest {
@Test
public void accessMethodsForNonExistingsPaths() {
projectRegistry = new DefaultProjectRegistry<ProjectInternal>();
- Project otherRoot = HelperUtil.createRootProject();
+ Project otherRoot = TestUtil.createRootProject();
assertNull(projectRegistry.getProject(otherRoot.getPath()));
assertEquals(new TreeSet<ProjectInternal>(), projectRegistry.getAllProjects(otherRoot.getPath()));
assertEquals(new TreeSet<ProjectInternal>(), projectRegistry.getSubProjects(otherRoot.getPath()));
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/project/DefaultProjectTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/project/DefaultProjectTest.groovy
index 32c4cee..9bab2e2 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/project/DefaultProjectTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/project/DefaultProjectTest.groovy
@@ -17,15 +17,17 @@
package org.gradle.api.internal.project
import org.apache.tools.ant.types.FileSet
+import org.gradle.api.*
import org.gradle.api.artifacts.Module
import org.gradle.api.artifacts.dsl.ArtifactHandler
import org.gradle.api.artifacts.dsl.DependencyHandler
+import org.gradle.api.artifacts.dsl.ComponentMetadataHandler
import org.gradle.api.artifacts.dsl.RepositoryHandler
import org.gradle.api.component.SoftwareComponentContainer
import org.gradle.api.initialization.dsl.ScriptHandler
+import org.gradle.api.internal.*
import org.gradle.api.internal.artifacts.configurations.ConfigurationContainerInternal
import org.gradle.api.internal.artifacts.configurations.DependencyMetaDataProvider
-import org.gradle.api.internal.artifacts.dsl.dependencies.DependencyFactory
import org.gradle.api.internal.file.FileOperations
import org.gradle.api.internal.file.FileResolver
import org.gradle.api.internal.initialization.ScriptClassLoaderProvider
@@ -33,52 +35,44 @@ import org.gradle.api.internal.tasks.TaskContainerInternal
import org.gradle.api.invocation.Gradle
import org.gradle.api.plugins.PluginContainer
import org.gradle.api.tasks.Directory
-import org.gradle.configuration.ProjectEvaluator
import org.gradle.configuration.ScriptPluginFactory
+import org.gradle.configuration.project.ProjectConfigurationActionContainer
+import org.gradle.configuration.project.ProjectEvaluator
import org.gradle.groovy.scripts.EmptyScript
import org.gradle.groovy.scripts.ScriptSource
import org.gradle.internal.Factory
import org.gradle.internal.reflect.Instantiator
import org.gradle.internal.service.ServiceRegistry
+import org.gradle.internal.service.scopes.ServiceRegistryFactory
import org.gradle.logging.LoggingManagerInternal
import org.gradle.logging.StandardOutputCapture
-import org.gradle.util.HelperUtil
import org.gradle.util.JUnit4GroovyMockery
import org.gradle.util.TestClosure
+import org.gradle.util.TestUtil
import org.jmock.integration.junit4.JMock
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-import java.awt.Point
+import java.awt.*
import java.text.FieldPosition
-import org.gradle.api.*
-import org.gradle.api.internal.*
-
import static org.hamcrest.Matchers.*
import static org.junit.Assert.*
-/**
- * @author Hans Dockter
- */
@RunWith (JMock.class)
class DefaultProjectTest {
JUnit4GroovyMockery context = new JUnit4GroovyMockery()
- static final String TEST_PROJECT_NAME = 'testproject'
-
static final String TEST_BUILD_FILE_NAME = 'build.gradle'
- static final String TEST_TASK_NAME = 'testtask'
-
Task testTask;
DefaultProject project, child1, child2, childchild
ProjectEvaluator projectEvaluator = context.mock(ProjectEvaluator.class)
- IProjectRegistry projectRegistry
+ ProjectRegistry projectRegistry
File rootDir
@@ -94,8 +88,8 @@ class DefaultProjectTest {
ConfigurationContainerInternal configurationContainerMock = context.mock(ConfigurationContainerInternal.class)
RepositoryHandler repositoryHandlerMock = context.mock(RepositoryHandler.class)
- DependencyFactory dependencyFactoryMock = context.mock(DependencyFactory.class)
DependencyHandler dependencyHandlerMock = context.mock(DependencyHandler)
+ ComponentMetadataHandler moduleHandlerMock = context.mock(ComponentMetadataHandler)
PluginContainer pluginContainerMock = context.mock(PluginContainer)
ScriptHandler scriptHandlerMock = context.mock(ScriptHandler)
DependencyMetaDataProvider dependencyMetaDataProviderMock = context.mock(DependencyMetaDataProvider)
@@ -105,6 +99,7 @@ class DefaultProjectTest {
LoggingManagerInternal loggingManagerMock = context.mock(LoggingManagerInternal.class)
Instantiator instantiatorMock = context.mock(Instantiator)
SoftwareComponentContainer softwareComponentsMock = context.mock(SoftwareComponentContainer.class)
+ ProjectConfigurationActionContainer configureActions = context.mock(ProjectConfigurationActionContainer.class)
@Before
void setUp() {
@@ -120,7 +115,7 @@ class DefaultProjectTest {
testScript = new EmptyScript()
- testTask = HelperUtil.createTask(DefaultTask)
+ testTask = TestUtil.createTask(DefaultTask)
projectRegistry = new DefaultProjectRegistry()
@@ -135,6 +130,7 @@ class DefaultProjectTest {
allowing(serviceRegistryMock).get(ConfigurationContainerInternal); will(returnValue(configurationContainerMock))
allowing(serviceRegistryMock).get(ArtifactHandler); will(returnValue(context.mock(ArtifactHandler)))
allowing(serviceRegistryMock).get(DependencyHandler); will(returnValue(dependencyHandlerMock))
+ allowing(serviceRegistryMock).get(ComponentMetadataHandler); will(returnValue(moduleHandlerMock))
allowing(serviceRegistryMock).get(SoftwareComponentContainer); will(returnValue(softwareComponentsMock))
allowing(serviceRegistryMock).get(ProjectEvaluator); will(returnValue(projectEvaluator))
allowing(serviceRegistryMock).getFactory(AntBuilder); will(returnValue(antBuilderFactoryMock))
@@ -143,13 +139,14 @@ class DefaultProjectTest {
allowing(serviceRegistryMock).get(ScriptClassLoaderProvider); will(returnValue(context.mock(ScriptClassLoaderProvider)))
allowing(serviceRegistryMock).get(LoggingManagerInternal); will(returnValue(loggingManagerMock))
allowing(serviceRegistryMock).get(StandardOutputCapture); will(returnValue(context.mock(StandardOutputCapture)))
- allowing(serviceRegistryMock).get(IProjectRegistry); will(returnValue(projectRegistry))
+ allowing(serviceRegistryMock).get(ProjectRegistry); will(returnValue(projectRegistry))
allowing(serviceRegistryMock).get(DependencyMetaDataProvider); will(returnValue(dependencyMetaDataProviderMock))
allowing(serviceRegistryMock).get(FileResolver); will(returnValue([toString: { -> "file resolver" }] as FileResolver))
allowing(serviceRegistryMock).get(Instantiator); will(returnValue(instantiatorMock))
allowing(serviceRegistryMock).get(FileOperations); will(returnValue(fileOperationsMock))
allowing(serviceRegistryMock).get(ProcessOperations); will(returnValue(processOperationsMock))
allowing(serviceRegistryMock).get(ScriptPluginFactory); will(returnValue([toString: { -> "script plugin factory" }] as ScriptPluginFactory))
+ allowing(serviceRegistryMock).get(ProjectConfigurationActionContainer); will(returnValue(configureActions))
Object listener = context.mock(ProjectEvaluationListener)
ignoring(listener)
allowing(build).getProjectEvaluationBroadcaster();
@@ -255,7 +252,7 @@ class DefaultProjectTest {
one(listener).call(project)
}
- project.beforeEvaluate(HelperUtil.toClosure(listener))
+ project.beforeEvaluate(TestUtil.toClosure(listener))
project.projectEvaluationBroadcaster.beforeEvaluate(project)
}
@@ -265,7 +262,7 @@ class DefaultProjectTest {
one(listener).call(project)
}
- project.afterEvaluate(HelperUtil.toClosure(listener))
+ project.afterEvaluate(TestUtil.toClosure(listener))
project.projectEvaluationBroadcaster.afterEvaluate(project, null)
}
@@ -551,9 +548,9 @@ class DefaultProjectTest {
}
@Test void testGetAllTasksRecursive() {
- Task projectTask = HelperUtil.createTask(DefaultTask.class)
- Task child1Task = HelperUtil.createTask(DefaultTask.class)
- Task child2Task = HelperUtil.createTask(DefaultTask.class)
+ Task projectTask = TestUtil.createTask(DefaultTask.class)
+ Task child1Task = TestUtil.createTask(DefaultTask.class)
+ Task child2Task = TestUtil.createTask(DefaultTask.class)
Map expectedMap = new TreeMap()
expectedMap[project] = [projectTask] as TreeSet
@@ -576,7 +573,7 @@ class DefaultProjectTest {
}
@Test void testGetAllTasksNonRecursive() {
- Task projectTask = HelperUtil.createTask(DefaultTask.class)
+ Task projectTask = TestUtil.createTask(DefaultTask.class)
Map expectedMap = new TreeMap()
expectedMap[project] = [projectTask] as TreeSet
@@ -590,8 +587,8 @@ class DefaultProjectTest {
}
@Test void testGetTasksByNameRecursive() {
- Task projectTask = HelperUtil.createTask(DefaultTask.class)
- Task child1Task = HelperUtil.createTask(DefaultTask.class)
+ Task projectTask = TestUtil.createTask(DefaultTask.class)
+ Task child1Task = TestUtil.createTask(DefaultTask.class)
context.checking {
one(taskContainerMock).findByName('task'); will(returnValue(projectTask))
@@ -604,7 +601,7 @@ class DefaultProjectTest {
}
@Test void testGetTasksByNameNonRecursive() {
- Task projectTask = HelperUtil.createTask(DefaultTask.class)
+ Task projectTask = TestUtil.createTask(DefaultTask.class)
context.checking {
one(taskContainerMock).findByName('task'); will(returnValue(projectTask))
@@ -661,7 +658,7 @@ def scriptMethod(Closure closure) {
"$returnValue"
}
"""
- HelperUtil.createScript(code)
+ TestUtil.createScript(code)
}
@Test void testSetPropertyAndPropertyMissingWithProjectProperty() {
@@ -789,44 +786,44 @@ def scriptMethod(Closure closure) {
}
@Test public void testDir() {
- Task dirTask1 = HelperUtil.createTask(Directory.class)
- Task dirTask12 = HelperUtil.createTask(Directory.class)
- Task dirTask123 = HelperUtil.createTask(Directory.class)
+ Task dirTask1 = TestUtil.createTask(Directory.class)
+ Task dirTask12 = TestUtil.createTask(Directory.class)
+ Task dirTask123 = TestUtil.createTask(Directory.class)
context.checking {
one(taskContainerMock).findByName('dir1'); will(returnValue(null))
- one(taskContainerMock).add('dir1', Directory); will(returnValue(dirTask1))
+ one(taskContainerMock).create('dir1', Directory); will(returnValue(dirTask1))
one(taskContainerMock).findByName('dir1/dir2'); will(returnValue(null))
- one(taskContainerMock).add('dir1/dir2', Directory); will(returnValue(dirTask12))
+ one(taskContainerMock).create('dir1/dir2', Directory); will(returnValue(dirTask12))
one(taskContainerMock).findByName('dir1/dir2/dir3'); will(returnValue(null))
- one(taskContainerMock).add('dir1/dir2/dir3', Directory); will(returnValue(dirTask123))
+ one(taskContainerMock).create('dir1/dir2/dir3', Directory); will(returnValue(dirTask123))
}
assertSame(dirTask123, project.dir('dir1/dir2/dir3'));
}
@Test public void testDirWithExistingParentDirTask() {
- Task dirTask1 = HelperUtil.createTask(Directory.class)
+ Task dirTask1 = TestUtil.createTask(Directory.class)
context.checking {
one(taskContainerMock).findByName('dir1'); will(returnValue(null))
- one(taskContainerMock).add('dir1', Directory); will(returnValue(dirTask1))
+ one(taskContainerMock).create('dir1', Directory); will(returnValue(dirTask1))
}
project.dir('dir1')
- Task dirTask14 = HelperUtil.createTask(Directory.class)
+ Task dirTask14 = TestUtil.createTask(Directory.class)
context.checking {
one(taskContainerMock).findByName('dir1'); will(returnValue(dirTask1))
one(taskContainerMock).findByName('dir1/dir4'); will(returnValue(null))
- one(taskContainerMock).add('dir1/dir4', Directory); will(returnValue(dirTask14))
+ one(taskContainerMock).create('dir1/dir4', Directory); will(returnValue(dirTask14))
}
assertSame(dirTask14, project.dir('dir1/dir4'))
}
@Test public void testDirWithConflictingNonDirTask() {
- Task dirTask14 = HelperUtil.createTask(DefaultTask.class)
+ Task dirTask14 = TestUtil.createTask(DefaultTask.class)
- Task dirTask1 = HelperUtil.createTask(Directory.class)
+ Task dirTask1 = TestUtil.createTask(Directory.class)
context.checking {
one(taskContainerMock).findByName('dir1'); will(returnValue(null))
- one(taskContainerMock).add('dir1', Directory); will(returnValue(dirTask1))
+ one(taskContainerMock).create('dir1', Directory); will(returnValue(dirTask1))
one(taskContainerMock).findByName('dir1/dir4'); will(returnValue(dirTask14))
}
@@ -894,7 +891,7 @@ def scriptMethod(Closure closure) {
private void checkConfigureProject(String configureMethod, Set projectsToCheck) {
String propValue = 'someValue'
if (configureMethod == 'configure') {
- project."$configureMethod" projectsToCheck as List,
+ project."$configureMethod" projectsToCheck as java.util.List,
{
testSubProp = propValue
}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/project/GlobalServicesRegistryTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/project/GlobalServicesRegistryTest.java
deleted file mode 100755
index 664b628..0000000
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/project/GlobalServicesRegistryTest.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.project;
-
-import org.gradle.api.internal.*;
-import org.gradle.api.internal.classpath.DefaultModuleRegistry;
-import org.gradle.api.internal.classpath.DefaultPluginModuleRegistry;
-import org.gradle.api.internal.classpath.ModuleRegistry;
-import org.gradle.api.internal.classpath.PluginModuleRegistry;
-import org.gradle.cache.internal.CacheFactory;
-import org.gradle.cache.internal.DefaultCacheFactory;
-import org.gradle.cache.internal.DefaultFileLockManager;
-import org.gradle.cache.internal.FileLockManager;
-import org.gradle.initialization.ClassLoaderRegistry;
-import org.gradle.cli.CommandLineConverter;
-import org.gradle.initialization.DefaultClassLoaderRegistry;
-import org.gradle.initialization.DefaultCommandLineConverter;
-import org.gradle.internal.nativeplatform.*;
-import org.gradle.internal.nativeplatform.filesystem.FileSystem;
-import org.gradle.listener.DefaultListenerManager;
-import org.gradle.listener.ListenerManager;
-import org.gradle.logging.LoggingManagerInternal;
-import org.gradle.logging.ProgressLoggerFactory;
-import org.gradle.logging.internal.DefaultLoggingManagerFactory;
-import org.gradle.logging.internal.DefaultProgressLoggerFactory;
-import org.gradle.messaging.remote.MessagingServer;
-import org.gradle.util.ClassLoaderFactory;
-import org.gradle.util.DefaultClassLoaderFactory;
-import org.junit.Test;
-
-import static org.hamcrest.Matchers.instanceOf;
-import static org.hamcrest.Matchers.notNullValue;
-import static org.junit.Assert.assertThat;
-
-public class GlobalServicesRegistryTest {
- private final GlobalServicesRegistry registry = new GlobalServicesRegistry();
-
- @Test
- public void providesCommandLineArgsConverter() {
- assertThat(registry.get(CommandLineConverter.class), instanceOf(
- DefaultCommandLineConverter.class));
- }
-
- @Test
- public void providesACacheFactoryFactory() {
- assertThat(registry.getFactory(CacheFactory.class), instanceOf(DefaultCacheFactory.class));
- }
-
- @Test
- public void providesAModuleRegistry() {
- assertThat(registry.get(ModuleRegistry.class), instanceOf(DefaultModuleRegistry.class));
- }
-
- @Test
- public void providesAPluginModuleRegistry() {
- assertThat(registry.get(PluginModuleRegistry.class), instanceOf(DefaultPluginModuleRegistry.class));
- }
-
- @Test
- public void providesAClassPathRegistry() {
- assertThat(registry.get(ClassPathRegistry.class), instanceOf(DefaultClassPathRegistry.class));
- }
-
- @Test
- public void providesAClassLoaderRegistry() {
- assertThat(registry.get(ClassLoaderRegistry.class), instanceOf(DefaultClassLoaderRegistry.class));
- }
-
- @Test
- public void providesALoggingManagerFactory() {
- assertThat(registry.getFactory(LoggingManagerInternal.class), instanceOf(DefaultLoggingManagerFactory.class));
- }
-
- @Test
- public void providesAListenerManager() {
- assertThat(registry.get(ListenerManager.class), instanceOf(DefaultListenerManager.class));
- }
-
- @Test
- public void providesAProgressLoggerFactory() {
- assertThat(registry.get(ProgressLoggerFactory.class), instanceOf(DefaultProgressLoggerFactory.class));
- }
-
- @Test
- public void providesAGradleDistributionLocator() {
- assertThat(registry.get(GradleDistributionLocator.class), instanceOf(DefaultModuleRegistry.class));
- }
-
- @Test
- public void providesAClassLoaderFactory() {
- assertThat(registry.get(ClassLoaderFactory.class), instanceOf(DefaultClassLoaderFactory.class));
- }
-
- @Test
- public void providesAMessagingServer() {
- assertThat(registry.get(MessagingServer.class), instanceOf(MessagingServer.class));
- }
-
- @Test
- public void providesAClassGenerator() {
- assertThat(registry.get(ClassGenerator.class), instanceOf(AsmBackedClassGenerator.class));
- }
-
- @Test
- public void providesAnInstantiator() {
- assertThat(registry.get(org.gradle.internal.reflect.Instantiator.class), instanceOf(ClassGeneratorBackedInstantiator.class));
- }
-
- @Test
- public void providesAFileLockManager() {
- assertThat(registry.get(FileLockManager.class), instanceOf(DefaultFileLockManager.class));
- }
-
- @Test
- public void providesAProcessEnvironment() {
- assertThat(registry.get(ProcessEnvironment.class), notNullValue());
- }
-
- @Test
- public void providesAFileSystem() {
- assertThat(registry.get(FileSystem.class), notNullValue());
- }
-
- @Test
- public void providesADocumentationRegistry() throws Exception {
- assertThat(registry.get(DocumentationRegistry.class), instanceOf(DocumentationRegistry.class));
- }
-}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/project/GradleInternalServiceRegistryTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/project/GradleInternalServiceRegistryTest.groovy
deleted file mode 100644
index 9902974..0000000
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/project/GradleInternalServiceRegistryTest.groovy
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.project;
-
-
-import org.gradle.StartParameter
-import org.gradle.api.internal.DocumentationRegistry
-import org.gradle.api.internal.GradleInternal
-import org.gradle.api.internal.plugins.DefaultPluginRegistry
-import org.gradle.api.internal.plugins.PluginRegistry
-import org.gradle.cache.CacheRepository
-import org.gradle.execution.BuildExecuter
-import org.gradle.execution.DefaultBuildExecuter
-import org.gradle.execution.TaskGraphExecuter
-import org.gradle.execution.taskgraph.DefaultTaskGraphExecuter
-import org.gradle.internal.service.ServiceRegistry
-import org.gradle.listener.ListenerManager
-import org.gradle.util.MultiParentClassLoader
-import spock.lang.Specification
-
-import static org.hamcrest.Matchers.sameInstance
-
-public class GradleInternalServiceRegistryTest extends Specification {
- private GradleInternal gradle = Mock()
- private ServiceRegistry parent = Mock()
- private ListenerManager listenerManager = Mock()
- private CacheRepository cacheRepository = Mock()
- private GradleInternalServiceRegistry registry = new GradleInternalServiceRegistry(parent, gradle)
- private StartParameter startParameter = new StartParameter()
-
- public void setup() {
- parent.get(StartParameter) >> Mock(StartParameter)
- parent.get(ListenerManager) >> listenerManager
- parent.get(CacheRepository) >> cacheRepository
- parent.get(DocumentationRegistry) >> Mock(DocumentationRegistry)
- gradle.getStartParameter() >> startParameter
- gradle.getScriptClassLoader() >> new MultiParentClassLoader()
- }
-
- def "can create services for a project instance"() {
- ProjectInternal project = Mock()
-
- when:
- ServiceRegistryFactory serviceRegistry = registry.createFor(project)
-
- then:
- serviceRegistry instanceof ProjectInternalServiceRegistry
- }
-
- def "provides a project registry"() {
- when:
- def projectRegistry = registry.get(IProjectRegistry)
- def secondRegistry = registry.get(IProjectRegistry)
-
- then:
- projectRegistry instanceof DefaultProjectRegistry
- projectRegistry sameInstance(secondRegistry)
- }
-
- def "provides a plugin registry"() {
- when:
- def pluginRegistry = registry.get(PluginRegistry)
- def secondRegistry = registry.get(PluginRegistry)
-
- then:
- pluginRegistry instanceof DefaultPluginRegistry
- secondRegistry sameInstance(pluginRegistry)
- }
-
- def "provides a build executer"() {
- when:
- def buildExecuter = registry.get(BuildExecuter)
- def secondExecuter = registry.get(BuildExecuter)
-
- then:
- buildExecuter instanceof DefaultBuildExecuter
- buildExecuter sameInstance(secondExecuter)
- }
-
- def "provides a task graph executer"() {
- when:
- def graphExecuter = registry.get(TaskGraphExecuter)
- def secondExecuter = registry.get(TaskGraphExecuter)
-
- then:
- graphExecuter instanceof DefaultTaskGraphExecuter
- graphExecuter sameInstance(secondExecuter)
- }
-}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/project/NewDefaultProjectTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/project/NewDefaultProjectTest.groovy
index 7584cac..3c9a0bb 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/project/NewDefaultProjectTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/project/NewDefaultProjectTest.groovy
@@ -19,15 +19,12 @@ package org.gradle.api.internal.project
import org.gradle.api.artifacts.dsl.ArtifactHandler
import org.gradle.api.artifacts.dsl.DependencyHandler
import org.gradle.api.internal.artifacts.configurations.ConfigurationContainerInternal
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import spock.lang.Specification
-/**
- * @author Szczepan Faber
- */
class NewDefaultProjectTest extends Specification {
- def project = HelperUtil.createRootProject()
+ def project = TestUtil.createRootProject()
void "delegates to artifacts handler"() {
def handler = Mock(ArtifactHandler)
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/project/ProjectFactoryTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/project/ProjectFactoryTest.java
index 077e2b9..798f3a5 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/project/ProjectFactoryTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/project/ProjectFactoryTest.java
@@ -24,11 +24,12 @@ import org.gradle.api.internal.GradleInternal;
import org.gradle.groovy.scripts.StringScriptSource;
import org.gradle.groovy.scripts.UriScriptSource;
import org.gradle.internal.Factory;
+import org.gradle.internal.service.scopes.ServiceRegistryFactory;
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider;
-import org.gradle.testfixtures.internal.GlobalTestServices;
-import org.gradle.testfixtures.internal.TestTopLevelBuildServiceRegistry;
+import org.gradle.testfixtures.internal.TestBuildScopeServices;
+import org.gradle.testfixtures.internal.TestGlobalScopeServices;
import org.gradle.util.JUnit4GroovyMockery;
-import org.gradle.util.MultiParentClassLoader;
+import org.gradle.internal.classloader.MultiParentClassLoader;
import org.jmock.Expectations;
import org.jmock.integration.junit4.JMock;
import org.jmock.integration.junit4.JUnit4Mockery;
@@ -43,9 +44,6 @@ import java.io.IOException;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
-/**
- * @author Hans Dockter
- */
@RunWith(JMock.class)
public class ProjectFactoryTest {
private final JUnit4Mockery context = new JUnit4GroovyMockery();
@@ -57,7 +55,7 @@ public class ProjectFactoryTest {
private Factory<RepositoryHandler> repositoryHandlerFactory = context.mock(Factory.class);
private RepositoryHandler repositoryHandler = context.mock(RepositoryHandler.class);
private StartParameter startParameterStub = new StartParameter();
- private ServiceRegistryFactory serviceRegistryFactory = new TestTopLevelBuildServiceRegistry(new GlobalTestServices(), startParameterStub, rootDir);
+ private ServiceRegistryFactory serviceRegistryFactory = new TestBuildScopeServices(new TestGlobalScopeServices(), startParameterStub, rootDir);
private org.gradle.internal.reflect.Instantiator instantiatorMock = serviceRegistryFactory.get(org.gradle.internal.reflect.Instantiator.class);
private GradleInternal gradle = context.mock(GradleInternal.class);
@@ -77,9 +75,7 @@ public class ProjectFactoryTest {
allowing(gradle).getStartParameter();
will(returnValue(startParameterStub));
allowing(gradle).getProjectRegistry();
- will(returnValue(gradleServices.get(IProjectRegistry.class)));
- allowing(gradle).getScriptClassLoader();
- will(returnValue(buildScriptClassLoader));
+ will(returnValue(gradleServices.get(ProjectRegistry.class)));
allowing(gradle).getGradleUserHomeDir();
will(returnValue(new File("gradleUserHomeDir")));
ignoring(gradle).getProjectEvaluationBroadcaster();
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/project/ProjectInternalServiceRegistryTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/project/ProjectInternalServiceRegistryTest.java
deleted file mode 100644
index 2894370..0000000
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/project/ProjectInternalServiceRegistryTest.java
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.project;
-
-import org.gradle.api.AntBuilder;
-import org.gradle.api.artifacts.dsl.ArtifactHandler;
-import org.gradle.api.artifacts.dsl.DependencyHandler;
-import org.gradle.api.artifacts.dsl.RepositoryHandler;
-import org.gradle.api.initialization.dsl.ScriptHandler;
-import org.gradle.api.internal.*;
-import org.gradle.api.internal.artifacts.ArtifactPublicationServices;
-import org.gradle.api.internal.artifacts.DependencyManagementServices;
-import org.gradle.api.internal.artifacts.DependencyResolutionServices;
-import org.gradle.api.internal.artifacts.configurations.ConfigurationContainerInternal;
-import org.gradle.api.internal.artifacts.configurations.DependencyMetaDataProvider;
-import org.gradle.api.internal.artifacts.dsl.dependencies.DependencyFactory;
-import org.gradle.api.internal.artifacts.dsl.dependencies.ProjectFinder;
-import org.gradle.api.internal.file.*;
-import org.gradle.api.internal.initialization.DefaultScriptHandler;
-import org.gradle.api.internal.initialization.ScriptClassLoaderProvider;
-import org.gradle.api.internal.plugins.DefaultProjectsPluginContainer;
-import org.gradle.api.internal.plugins.PluginRegistry;
-import org.gradle.api.internal.project.taskfactory.ITaskFactory;
-import org.gradle.api.internal.tasks.DefaultTaskContainerFactory;
-import org.gradle.api.internal.tasks.TaskContainerInternal;
-import org.gradle.api.logging.LoggingManager;
-import org.gradle.api.plugins.PluginContainer;
-import org.gradle.initialization.ProjectAccessListener;
-import org.gradle.internal.Factory;
-import org.gradle.internal.nativeplatform.filesystem.FileSystem;
-import org.gradle.internal.reflect.DirectInstantiator;
-import org.gradle.internal.reflect.Instantiator;
-import org.gradle.internal.service.ServiceRegistry;
-import org.gradle.logging.LoggingManagerInternal;
-import org.gradle.util.JUnit4GroovyMockery;
-import org.hamcrest.Matcher;
-import org.hamcrest.Matchers;
-import org.jmock.Expectations;
-import org.jmock.integration.junit4.JMock;
-import org.jmock.integration.junit4.JUnit4Mockery;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.io.File;
-
-import static org.hamcrest.Matchers.*;
-import static org.junit.Assert.assertThat;
-
- at RunWith(JMock.class)
-public class ProjectInternalServiceRegistryTest {
- private final JUnit4Mockery context = new JUnit4GroovyMockery();
- private final ProjectInternal project = context.mock(ProjectInternal.class);
- private final ConfigurationContainerInternal configurationContainer = context.mock(ConfigurationContainerInternal.class);
- private final GradleInternal gradle = context.mock(GradleInternal.class);
- private final DependencyManagementServices dependencyManagementServices = context.mock(DependencyManagementServices.class);
- private final ITaskFactory taskFactory = context.mock(ITaskFactory.class);
- private final DependencyFactory dependencyFactory = context.mock(DependencyFactory.class);
- private final ServiceRegistry parent = context.mock(ServiceRegistry.class);
- private final ProjectInternalServiceRegistry registry = new ProjectInternalServiceRegistry(parent, project);
- private final PluginRegistry pluginRegistry = context.mock(PluginRegistry.class);
- private final DependencyResolutionServices dependencyResolutionServices = context.mock(DependencyResolutionServices.class);
- private final RepositoryHandler repositoryHandler = context.mock(RepositoryHandler.class);
- private final ArtifactPublicationServices publicationServices = context.mock(ArtifactPublicationServices.class);
- private final DependencyHandler dependencyHandler = context.mock(DependencyHandler.class);
- private final ArtifactHandler artifactHandler = context.mock(ArtifactHandler.class);
- private final DirectInstantiator instantiator = new DirectInstantiator();
-
- @Before
- public void setUp() {
- context.checking(new Expectations() {{
- allowing(project).getGradle();
- will(returnValue(gradle));
- allowing(project).getProjectDir();
- will(returnValue(new File("project-dir").getAbsoluteFile()));
- allowing(project).getBuildScriptSource();
- allowing(parent).get(ITaskFactory.class);
- will(returnValue(taskFactory));
- allowing(parent).get(DependencyFactory.class);
- will(returnValue(dependencyFactory));
- allowing(parent).get(PluginRegistry.class);
- will(returnValue(pluginRegistry));
- allowing(parent).get(DependencyManagementServices.class);
- will(returnValue(dependencyManagementServices));
- allowing(parent).get(org.gradle.internal.reflect.Instantiator.class);
- will(returnValue(instantiator));
- allowing(parent).get(FileSystem.class);
- will(returnValue(context.mock(FileSystem.class)));
- allowing(parent).get(ClassGenerator.class);
- will(returnValue(context.mock(ClassGenerator.class)));
- allowing(parent).get(ProjectAccessListener.class);
- will(returnValue(context.mock(ProjectAccessListener.class)));
- }});
- }
-
- @Test
- public void createsARegistryForATask() {
- ServiceRegistryFactory taskRegistry = registry.createFor(context.mock(TaskInternal.class));
- assertThat(taskRegistry, instanceOf(TaskInternalServiceRegistry.class));
- }
-
- @Test
- public void providesATaskContainerFactory() {
- final ITaskFactory childFactory = context.mock(ITaskFactory.class);
-
- context.checking(new Expectations() {{
- Matcher matcher = instanceOf(ClassGeneratorBackedInstantiator.class);
- one(taskFactory).createChild(with(sameInstance(project)), with((Matcher<Instantiator>)matcher));
- will(returnValue(childFactory));
- }});
-
- assertThat(registry.getFactory(TaskContainerInternal.class), instanceOf(DefaultTaskContainerFactory.class));
- }
-
- @Test
- public void providesAPluginContainer() {
- expectScriptClassLoaderProviderCreated();
- context.checking(new Expectations() {{
- Matcher matcher = Matchers.instanceOf(DependencyInjectingInstantiator.class);
- one(pluginRegistry).createChild(with(notNullValue(ClassLoader.class)), with((Matcher<Instantiator>)matcher));
- }});
-
- assertThat(registry.get(PluginContainer.class), instanceOf(DefaultProjectsPluginContainer.class));
- assertThat(registry.get(PluginContainer.class), sameInstance(registry.get(PluginContainer.class)));
- }
-
- @Test
- public void providesAnArtifactPublicationServicesFactory() {
- expectDependencyResolutionServicesCreated();
-
- assertThat(registry.get(ArtifactPublicationServices.class), sameInstance(publicationServices));
- }
-
- @Test
- public void providesARepositoryHandler() {
- expectDependencyResolutionServicesCreated();
-
- assertThat(registry.get(RepositoryHandler.class), sameInstance(repositoryHandler));
- assertThat(registry.get(RepositoryHandler.class), sameInstance(registry.get(RepositoryHandler.class)));
- }
-
- @Test
- public void providesAConfigurationContainer() {
- expectDependencyResolutionServicesCreated();
-
- assertThat(registry.get(ConfigurationContainerInternal.class), sameInstance(configurationContainer));
- assertThat(registry.get(ConfigurationContainerInternal.class), sameInstance(registry.get(ConfigurationContainerInternal.class)));
- }
-
- @Test
- public void providesAnArtifactHandler() {
- expectDependencyResolutionServicesCreated();
-
- assertThat(registry.get(ArtifactHandler.class), sameInstance(artifactHandler));
- assertThat(registry.get(ArtifactHandler.class), sameInstance(registry.get(ArtifactHandler.class)));
- }
-
- @Test
- public void providesADependencyHandler() {
- expectDependencyResolutionServicesCreated();
-
- assertThat(registry.get(DependencyHandler.class), sameInstance(dependencyHandler));
- assertThat(registry.get(DependencyHandler.class), sameInstance(registry.get(DependencyHandler.class)));
- }
-
- @Test
- public void providesAnAntBuilderFactory() {
- assertThat(registry.getFactory(AntBuilder.class), instanceOf(DefaultAntBuilderFactory.class));
- assertThat(registry.getFactory(AntBuilder.class), sameInstance((Object) registry.getFactory(AntBuilder.class)));
- }
-
- @Test
- public void providesAScriptHandlerAndScriptClassLoaderProvider() {
- expectScriptClassLoaderProviderCreated();
-
- assertThat(registry.get(ScriptHandler.class), instanceOf(DefaultScriptHandler.class));
- assertThat(registry.get(ScriptHandler.class), sameInstance(registry.get(ScriptHandler.class)));
- assertThat(registry.get(ScriptClassLoaderProvider.class), sameInstance((Object) registry.get(
- ScriptHandler.class)));
- }
-
- @Test
- public void providesAFileResolver() {
- assertThat(registry.get(FileResolver.class), instanceOf(BaseDirFileResolver.class));
- assertThat(registry.get(FileResolver.class), sameInstance(registry.get(FileResolver.class)));
- }
-
- @Test
- public void providesAFileOperationsInstance() {
- context.checking(new Expectations(){{
- one(project).getTasks();
- }});
-
- assertThat(registry.get(FileOperations.class), instanceOf(DefaultFileOperations.class));
- assertThat(registry.get(FileOperations.class), sameInstance(registry.get(FileOperations.class)));
- }
-
- @Test
- public void providesATemporaryFileProvider() {
- assertThat(registry.get(TemporaryFileProvider.class), instanceOf(DefaultTemporaryFileProvider.class));
- assertThat(registry.get(TemporaryFileProvider.class), sameInstance(registry.get(TemporaryFileProvider.class)));
- }
-
- @Test
- public void providesALoggingManager() {
- final Factory<LoggingManagerInternal> loggingManagerFactory = context.mock(Factory.class);
- final LoggingManager loggingManager = context.mock(LoggingManagerInternal.class);
-
- context.checking(new Expectations(){{
- allowing(parent).getFactory(LoggingManagerInternal.class);
- will(returnValue(loggingManagerFactory));
- one(loggingManagerFactory).create();
- will(returnValue(loggingManager));
- }});
-
- assertThat(registry.get(LoggingManager.class), sameInstance(loggingManager));
- assertThat(registry.get(LoggingManager.class), sameInstance(registry.get(LoggingManager.class)));
- }
-
- private void expectScriptClassLoaderProviderCreated() {
- context.checking(new Expectations() {{
- one(dependencyManagementServices).create(with(notNullValue(FileResolver.class)),
- with(notNullValue(DependencyMetaDataProvider.class)),
- with(notNullValue(ProjectFinder.class)),
- with(notNullValue(DomainObjectContext.class)));
- will(returnValue(dependencyResolutionServices));
-
- ignoring(dependencyResolutionServices);
-
- allowing(project).getParent();
- will(returnValue(null));
-
- allowing(gradle).getScriptClassLoader();
- will(returnValue(null));
- }});
- }
-
- private void expectDependencyResolutionServicesCreated() {
- context.checking(new Expectations(){{
- one(dependencyManagementServices).create(with(notNullValue(FileResolver.class)),
- with(notNullValue(DependencyMetaDataProvider.class)),
- with(notNullValue(ProjectFinder.class)),
- with(notNullValue(DomainObjectContext.class)));
- will(returnValue(dependencyResolutionServices));
-
- allowing(dependencyResolutionServices).getResolveRepositoryHandler();
- will(returnValue(repositoryHandler));
-
- allowing(dependencyResolutionServices).createArtifactPublicationServices();
- will(returnValue(publicationServices));
-
- allowing(dependencyResolutionServices).getConfigurationContainer();
- will(returnValue(configurationContainer));
-
- allowing(dependencyResolutionServices).getDependencyHandler();
- will(returnValue(dependencyHandler));
-
- allowing(dependencyResolutionServices).getArtifactHandler();
- will(returnValue(artifactHandler));
- }});
- }
-}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/project/TaskExecutionServicesTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/project/TaskExecutionServicesTest.groovy
deleted file mode 100644
index a73b72b..0000000
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/project/TaskExecutionServicesTest.groovy
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.project
-
-import spock.lang.Specification
-import org.gradle.api.internal.tasks.TaskExecuter
-import org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter
-import org.gradle.listener.ListenerManager
-import org.gradle.cache.CacheRepository
-import org.gradle.StartParameter
-import org.gradle.api.invocation.Gradle
-import org.gradle.cache.DirectoryCacheBuilder
-import org.gradle.cache.PersistentCache
-import org.gradle.internal.service.ServiceRegistry
-
-class TaskExecutionServicesTest extends Specification {
- final ServiceRegistry parent = Mock()
- final Gradle gradle = Mock()
- final TaskExecutionServices services = new TaskExecutionServices(parent, gradle)
-
- def "makes a TaskExecutor available"() {
- given:
- ListenerManager listenerManager = Mock()
- StartParameter startParameter = Mock()
- CacheRepository cacheRepository = Mock()
- DirectoryCacheBuilder cacheBuilder = Mock()
- PersistentCache cache = Mock()
- _ * parent.get(ListenerManager) >> listenerManager
- _ * parent.get(StartParameter) >> startParameter
- _ * parent.get(CacheRepository) >> cacheRepository
- _ * cacheRepository.cache(!null) >> cacheBuilder
- _ * cacheBuilder.forObject(gradle) >> cacheBuilder
- _ * cacheBuilder.withDisplayName(!null) >> cacheBuilder
- _ * cacheBuilder.withLockMode(!null) >> cacheBuilder
- _ * cacheBuilder.open() >> cache
-
- expect:
- services.get(TaskExecuter) instanceof ExecuteAtMostOnceTaskExecuter
- services.get(TaskExecuter).is(services.get(TaskExecuter))
- }
-}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/project/TaskInternalServiceRegistryTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/project/TaskInternalServiceRegistryTest.java
deleted file mode 100644
index 1844816..0000000
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/project/TaskInternalServiceRegistryTest.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.project;
-
-import org.gradle.api.internal.TaskInternal;
-import org.gradle.api.internal.TaskOutputsInternal;
-import org.gradle.api.internal.file.FileResolver;
-import org.gradle.api.internal.tasks.DefaultTaskInputs;
-import org.gradle.api.internal.tasks.DefaultTaskOutputs;
-import org.gradle.api.internal.tasks.TaskStatusNagger;
-import org.gradle.api.logging.LoggingManager;
-import org.gradle.api.tasks.TaskInputs;
-import org.gradle.internal.Factory;
-import org.gradle.internal.service.ServiceRegistry;
-import org.gradle.logging.LoggingManagerInternal;
-import org.jmock.Expectations;
-import org.jmock.integration.junit4.JMock;
-import org.jmock.integration.junit4.JUnit4Mockery;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static junit.framework.Assert.assertSame;
-import static org.hamcrest.Matchers.instanceOf;
-import static org.hamcrest.Matchers.sameInstance;
-import static org.junit.Assert.assertThat;
-
- at RunWith(JMock.class)
-public class TaskInternalServiceRegistryTest {
- private final JUnit4Mockery context = new JUnit4Mockery();
- private final ServiceRegistry parent = context.mock(ServiceRegistry.class);
- private final ProjectInternal project = context.mock(ProjectInternal.class);
- private final TaskInternal task = context.mock(TaskInternal.class);
- private final TaskInternalServiceRegistry registry = new TaskInternalServiceRegistry(parent, project, task);
-
- @Before
- public void setUp() {
- context.checking(new Expectations() {{
- allowing(project).getFileResolver();
- will(returnValue(context.mock(FileResolver.class)));
- }});
- }
-
- @Test
- public void createsATaskInputsInstance() {
- TaskInputs inputs = registry.get(TaskInputs.class);
- assertThat(inputs, instanceOf(DefaultTaskInputs.class));
- }
-
- @Test
- public void createsATaskOutputsInternalInstance() {
- TaskOutputsInternal outputs = registry.get(TaskOutputsInternal.class);
- assertThat(outputs, instanceOf(DefaultTaskOutputs.class));
- }
-
- @Test
- public void createsATaskStatusNaggerInstance() {
- TaskStatusNagger nagger = registry.get(TaskStatusNagger.class);
- assertSame(nagger, registry.get(TaskStatusNagger.class));
- }
-
- @Test
- public void createsALoggingManagerAndStdOutputCapture() {
- final Factory<LoggingManagerInternal> loggingManagerFactory = context.mock(Factory.class);
- final LoggingManager loggingManager = context.mock(LoggingManagerInternal.class);
-
- context.checking(new Expectations() {{
- allowing(parent).getFactory(LoggingManagerInternal.class);
- will(returnValue(loggingManagerFactory));
- one(loggingManagerFactory).create();
- will(returnValue(loggingManager));
- }});
-
- assertThat(registry.get(LoggingManager.class), sameInstance(loggingManager));
- }
-}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/project/TestPlugin1.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/project/TestPlugin1.groovy
index 3dc70b5..6dc5e3d 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/project/TestPlugin1.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/project/TestPlugin1.groovy
@@ -19,9 +19,6 @@ package org.gradle.api.internal.project
import org.gradle.api.Plugin
import org.gradle.api.Project
-/**
-* @author Hans Dockter
-*/
class TestPlugin1 implements Plugin<Project> {
int applyCounter = 0
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/project/TestPlugin2.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/project/TestPlugin2.groovy
index b68f716..87bde21 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/project/TestPlugin2.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/project/TestPlugin2.groovy
@@ -19,9 +19,6 @@ package org.gradle.api.internal.project
import org.gradle.api.Plugin
import org.gradle.api.Project
-/**
-* @author Hans Dockter
-*/
class TestPlugin2 implements Plugin<Project> {
void apply(Project project) {
}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/project/TopLevelBuildServiceRegistryTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/project/TopLevelBuildServiceRegistryTest.groovy
deleted file mode 100644
index 6cc5a13..0000000
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/project/TopLevelBuildServiceRegistryTest.groovy
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.project
-
-import org.gradle.StartParameter
-import org.gradle.api.internal.*
-import org.gradle.api.internal.classpath.DefaultModuleRegistry
-import org.gradle.api.internal.classpath.ModuleRegistry
-import org.gradle.api.internal.classpath.PluginModuleRegistry
-import org.gradle.cache.CacheRepository
-import org.gradle.cache.internal.CacheFactory
-import org.gradle.cache.internal.DefaultCacheRepository
-import org.gradle.configuration.BuildConfigurer
-import org.gradle.configuration.DefaultBuildConfigurer
-import org.gradle.configuration.DefaultScriptPluginFactory
-import org.gradle.configuration.ScriptPluginFactory
-import org.gradle.groovy.scripts.DefaultScriptCompilerFactory
-import org.gradle.groovy.scripts.ScriptCompilerFactory
-import org.gradle.initialization.*
-import org.gradle.internal.Factory
-import org.gradle.internal.concurrent.DefaultExecutorFactory
-import org.gradle.internal.concurrent.ExecutorFactory
-import org.gradle.internal.reflect.Instantiator
-import org.gradle.internal.service.ServiceRegistry
-import org.gradle.listener.DefaultListenerManager
-import org.gradle.listener.ListenerManager
-import org.gradle.logging.LoggingManagerInternal
-import org.gradle.messaging.remote.MessagingServer
-import org.gradle.process.internal.DefaultWorkerProcessFactory
-import org.gradle.process.internal.WorkerProcessBuilder
-import org.gradle.profile.ProfileEventAdapter
-import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
-import org.gradle.util.ClassLoaderFactory
-import org.gradle.util.MultiParentClassLoader
-import org.junit.Rule
-import spock.lang.Specification
-import spock.lang.Timeout
-
-import static org.hamcrest.Matchers.instanceOf
-import static org.hamcrest.Matchers.sameInstance
-import static org.junit.Assert.assertThat
-
-public class TopLevelBuildServiceRegistryTest extends Specification {
- @Rule
- TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider()
- StartParameter startParameter = new StartParameter()
- ServiceRegistry parent = Mock()
- Factory<CacheFactory> cacheFactoryFactory = Mock()
- ClosableCacheFactory cacheFactory = Mock()
- ClassLoaderRegistry classLoaderRegistry = Mock()
-
- TopLevelBuildServiceRegistry registry = new TopLevelBuildServiceRegistry(parent, startParameter)
-
- def setup() {
- startParameter.gradleUserHomeDir = tmpDir.testDirectory
- parent.getFactory(CacheFactory) >> cacheFactoryFactory
- cacheFactoryFactory.create() >> cacheFactory
- parent.get(ClassLoaderRegistry) >> classLoaderRegistry
- parent.getFactory(LoggingManagerInternal) >> Mock(Factory)
- parent.get(ModuleRegistry) >> new DefaultModuleRegistry()
- parent.get(PluginModuleRegistry) >> Mock(PluginModuleRegistry)
- parent.get(Instantiator) >> ThreadGlobalInstantiator.getOrCreate()
- }
-
- def delegatesToParentForUnknownService() {
- setup:
- parent.get(String) >> "value"
-
- expect:
- registry.get(String) == "value"
- }
-
- def throwsExceptionForUnknownDomainObject() {
- when:
- registry.createFor("string")
- then:
- def e = thrown(IllegalArgumentException)
- e.message == "Cannot create services for unknown domain object of type String."
- }
-
- def canCreateServicesForAGradleInstance() {
- setup:
- GradleInternal gradle = Mock()
- ServiceRegistryFactory registry = this.registry.createFor(gradle)
- expect:
- registry instanceof GradleInternalServiceRegistry
- }
-
- def providesAListenerManager() {
- setup:
- ListenerManager listenerManager = expectListenerManagerCreated()
- expect:
- assertThat(registry.get(ListenerManager), sameInstance(listenerManager))
- }
-
- @Timeout(5)
- def providesAScriptCompilerFactory() {
- setup:
- expectListenerManagerCreated()
-
- expect:
- registry.get(ScriptCompilerFactory) instanceof DefaultScriptCompilerFactory
- registry.get(ScriptCompilerFactory) == registry.get(ScriptCompilerFactory)
- }
-
- def providesACacheRepositoryAndCleansUpOnClose() {
- setup:
- 1 * cacheFactory.close()
-
- expect:
- registry.get(CacheRepository) instanceof DefaultCacheRepository
- registry.get(CacheRepository) == registry.get(CacheRepository)
- registry.close()
- }
-
- def providesAnInitScriptHandler() {
- setup:
- allowGetCoreImplClassLoader()
- expectScriptClassLoaderCreated()
- expectListenerManagerCreated()
- allowGetGradleDistributionLocator()
-
- expect:
- registry.get(InitScriptHandler) instanceof InitScriptHandler
- registry.get(InitScriptHandler) == registry.get(InitScriptHandler)
- }
-
- def providesAScriptObjectConfigurerFactory() {
- setup:
- allowGetCoreImplClassLoader()
- expectListenerManagerCreated()
- expectScriptClassLoaderCreated()
- expect:
- assertThat(registry.get(ScriptPluginFactory), instanceOf(DefaultScriptPluginFactory))
- assertThat(registry.get(ScriptPluginFactory), sameInstance(registry.get(ScriptPluginFactory)))
- }
-
- def providesASettingsProcessor() {
- setup:
- allowGetCoreImplClassLoader()
- expectListenerManagerCreated()
- expectScriptClassLoaderCreated()
- expect:
- assertThat(registry.get(SettingsProcessor), instanceOf(PropertiesLoadingSettingsProcessor))
- assertThat(registry.get(SettingsProcessor), sameInstance(registry.get(SettingsProcessor)))
- }
-
- def providesAnExceptionAnalyser() {
- setup:
- expectListenerManagerCreated()
- expect:
- assertThat(registry.get(ExceptionAnalyser), instanceOf(MultipleBuildFailuresExceptionAnalyser))
- assertThat(registry.get(ExceptionAnalyser).delegate, instanceOf(DefaultExceptionAnalyser))
- assertThat(registry.get(ExceptionAnalyser), sameInstance(registry.get(ExceptionAnalyser)))
- }
-
- def providesAWorkerProcessFactory() {
- setup:
- expectParentServiceLocated(MessagingServer)
- allowGetCoreImplClassLoader()
-
- expect:
- assertThat(registry.getFactory(WorkerProcessBuilder), instanceOf(DefaultWorkerProcessFactory))
- }
-
- def providesAnIsolatedAntBuilder() {
- setup:
- expectParentServiceLocated(ClassLoaderFactory)
- allowGetCoreImplClassLoader()
- expect:
-
- assertThat(registry.get(IsolatedAntBuilder), instanceOf(DefaultIsolatedAntBuilder))
- assertThat(registry.get(IsolatedAntBuilder), sameInstance(registry.get(IsolatedAntBuilder)))
- }
-
- def providesAProjectFactory() {
- setup:
- expectParentServiceLocated(Instantiator)
- expectParentServiceLocated(ClassGenerator)
- expect:
- assertThat(registry.get(IProjectFactory), instanceOf(ProjectFactory))
- assertThat(registry.get(IProjectFactory), sameInstance(registry.get(IProjectFactory)))
- }
-
- def providesAnExecutorFactory() {
- expect:
- assertThat(registry.get(ExecutorFactory), instanceOf(DefaultExecutorFactory))
- assertThat(registry.get(ExecutorFactory), sameInstance(registry.get(ExecutorFactory)))
- }
-
- def providesABuildConfigurer() {
- expect:
- assertThat(registry.get(BuildConfigurer), instanceOf(DefaultBuildConfigurer))
- assertThat(registry.get(BuildConfigurer), sameInstance(registry.get(BuildConfigurer)))
- }
-
- def providesAPropertiesLoader() {
- expect:
- assertThat(registry.get(IGradlePropertiesLoader), instanceOf(DefaultGradlePropertiesLoader))
- assertThat(registry.get(IGradlePropertiesLoader), sameInstance(registry.get(IGradlePropertiesLoader)))
- }
-
- def providesABuildLoader() {
- setup:
- expectParentServiceLocated(Instantiator)
- expect:
- assertThat(registry.get(BuildLoader), instanceOf(ProjectPropertySettingBuildLoader))
- assertThat(registry.get(BuildLoader), sameInstance(registry.get(BuildLoader)))
- }
-
- def providesAProfileEventAdapter() {
- setup:
- expectParentServiceLocated(BuildRequestMetaData)
- expectListenerManagerCreated()
-
- expect:
- assertThat(registry.get(ProfileEventAdapter), instanceOf(ProfileEventAdapter))
- assertThat(registry.get(ProfileEventAdapter), sameInstance(registry.get(ProfileEventAdapter)))
- }
-
- private <T> T expectParentServiceLocated(Class<T> type) {
- T t = Mock(type)
- parent.get(type) >> t
- t
- }
-
- private ListenerManager expectListenerManagerCreated() {
- final ListenerManager listenerManager = new DefaultListenerManager()
- final ListenerManager listenerManagerParent = Mock()
- parent.get(ListenerManager) >> listenerManagerParent
- 1 * listenerManagerParent.createChild() >> listenerManager
- listenerManager
- }
-
- private void allowGetCoreImplClassLoader() {
- classLoaderRegistry.getCoreImplClassLoader() >> new ClassLoader() {}
- }
-
- private void expectScriptClassLoaderCreated() {
- 1 * classLoaderRegistry.createScriptClassLoader() >> new MultiParentClassLoader()
- }
-
- private void allowGetGradleDistributionLocator() {
- parent.get(GradleDistributionLocator) >> Mock(GradleDistributionLocator)
- }
-
- public interface ClosableCacheFactory extends CacheFactory {
- void close()
- }
-}
\ No newline at end of file
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/project/taskfactory/AnnotationProcessingTaskFactoryTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/project/taskfactory/AnnotationProcessingTaskFactoryTest.java
index 032e97d..d8b9442 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/project/taskfactory/AnnotationProcessingTaskFactoryTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/project/taskfactory/AnnotationProcessingTaskFactoryTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2010 the original author or authors.
+ * Copyright 2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@
package org.gradle.api.internal.project.taskfactory;
+import org.gradle.api.Action;
import org.gradle.api.DefaultTask;
import org.gradle.api.GradleException;
import org.gradle.api.Task;
@@ -24,11 +25,11 @@ import org.gradle.api.internal.AbstractTask;
import org.gradle.api.internal.TaskInternal;
import org.gradle.api.internal.project.DefaultProject;
import org.gradle.api.tasks.*;
+import org.gradle.api.tasks.incremental.IncrementalTaskInputs;
import org.gradle.test.fixtures.file.TestFile;
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider;
import org.gradle.util.GFileUtils;
-import org.gradle.util.HelperUtil;
-import org.gradle.util.ReflectionUtil;
+import org.gradle.util.TestUtil;
import org.jmock.Expectations;
import org.jmock.integration.junit4.JMock;
import org.jmock.integration.junit4.JUnit4Mockery;
@@ -36,11 +37,13 @@ import org.jmock.lib.legacy.ClassImposteriser;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import spock.lang.Issue;
import java.io.File;
import java.util.*;
import java.util.concurrent.Callable;
+import static org.gradle.internal.reflect.JavaReflectionUtil.readField;
import static org.gradle.util.Matchers.isEmpty;
import static org.gradle.util.WrapUtil.toList;
import static org.gradle.util.WrapUtil.toSet;
@@ -77,7 +80,7 @@ public class AnnotationProcessingTaskFactoryTest {
}
private <T extends Task> T expectTaskCreated(final Class<T> type, final Object... params) {
- DefaultProject project = HelperUtil.createRootProject();
+ DefaultProject project = TestUtil.createRootProject();
T task = AbstractTask.injectIntoNewInstance(project, "task", new Callable<T>() {
public T call() throws Exception {
if (params.length > 0) {
@@ -139,11 +142,29 @@ public class AnnotationProcessingTaskFactoryTest {
}
@Test
+ public void createsContextualActionFoIncrementalTaskAction() {
+ final Action<IncrementalTaskInputs> action = context.mock(Action.class);
+ TaskWithIncrementalAction task = expectTaskCreated(TaskWithIncrementalAction.class, action);
+
+ context.checking(new Expectations() {{
+ one(action).execute(with(notNullValue(IncrementalTaskInputs.class)));
+ }});
+
+ task.execute();
+ }
+
+ @Test
+ public void failsWhenMultipleActionsAreIncremental() {
+ assertTaskCreationFails(TaskWithMultipleIncrementalActions.class,
+ "Cannot have multiple @TaskAction methods accepting an IncrementalTaskInputs parameter.");
+ }
+
+ @Test
public void cachesClassMetaInfo() {
TaskWithInputFile task = expectTaskCreated(TaskWithInputFile.class, existingFile);
TaskWithInputFile task2 = expectTaskCreated(TaskWithInputFile.class, missingFile);
- assertThat(ReflectionUtil.getProperty(task.getActions().get(0), "action"), sameInstance(ReflectionUtil.getProperty(task2.getActions().get(0), "action")));
+ assertThat(readField(task.getActions().get(0), Action.class, "action"), sameInstance(readField(task2.getActions().get(0), Action.class, "action")));
}
@Test
@@ -154,8 +175,14 @@ public class AnnotationProcessingTaskFactoryTest {
@Test
public void failsWhenMethodWithParametersHasTaskActionAnnotation() {
- assertTaskCreationFails(TaskWithParamMethod.class,
- "Cannot use @TaskAction annotation on method TaskWithParamMethod.doStuff() as this method takes parameters.");
+ assertTaskCreationFails(TaskWithMultiParamAction.class,
+ "Cannot use @TaskAction annotation on method TaskWithMultiParamAction.doStuff() as this method takes multiple parameters.");
+ }
+
+ @Test
+ public void failsWhenMethodWithInvalidParameterHasTaskActionAnnotation() {
+ assertTaskCreationFails(TaskWithSingleParamAction.class,
+ "Cannot use @TaskAction annotation on method TaskWithSingleParamAction.doStuff() because int is not a valid parameter to an action method.");
}
private void assertTaskCreationFails(Class<? extends Task> type, String message) {
@@ -565,6 +592,13 @@ public class AnnotationProcessingTaskFactoryTest {
}
@Test
+ @Issue("http://issues.gradle.org/browse/GRADLE-2815")
+ public void registersSpecifiedBooleanInputValue() {
+ TaskWithBooleanInput task = expectTaskCreated(TaskWithBooleanInput.class, true);
+ assertThat(task.getInputs().getProperties().get("inputValue"), equalTo((Object) true));
+ }
+
+ @Test
public void validationActionSucceedsWhenPropertyMarkedWithOptionalAnnotationNotSpecified() {
TaskWithOptionalInputFile task = expectTaskCreated(TaskWithOptionalInputFile.class);
task.execute();
@@ -732,9 +766,39 @@ public class AnnotationProcessingTaskFactoryTest {
}
}
- public static class TaskWithParamMethod extends DefaultTask {
+ public static class TaskWithIncrementalAction extends DefaultTask {
+ private final Action<IncrementalTaskInputs> action;
+
+ public TaskWithIncrementalAction(Action<IncrementalTaskInputs> action) {
+ this.action = action;
+ }
+
+ @TaskAction
+ public void doStuff(IncrementalTaskInputs changes) {
+ action.execute(changes);
+ }
+ }
+
+ public static class TaskWithMultipleIncrementalActions extends DefaultTask {
+
+ @TaskAction
+ public void doStuff(IncrementalTaskInputs changes) {
+ }
+
+ @TaskAction
+ public void doStuff2(IncrementalTaskInputs changes) {
+ }
+ }
+
+ public static class TaskWithSingleParamAction extends DefaultTask {
@TaskAction
- public void doStuff(int value) {
+ public void doStuff(int value1) {
+ }
+ }
+
+ public static class TaskWithMultiParamAction extends DefaultTask {
+ @TaskAction
+ public void doStuff(int value1, int value2) {
}
}
@@ -777,6 +841,19 @@ public class AnnotationProcessingTaskFactoryTest {
}
}
+ public static class TaskWithBooleanInput extends DefaultTask {
+ boolean inputValue;
+
+ public TaskWithBooleanInput(boolean inputValue) {
+ this.inputValue = inputValue;
+ }
+
+ @Input
+ public boolean isInputValue() {
+ return inputValue;
+ }
+ }
+
public static class BrokenTaskWithInputDir extends TaskWithInputDir {
public BrokenTaskWithInputDir(File inputDir) {
super(inputDir);
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/project/taskfactory/TaskFactoryTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/project/taskfactory/TaskFactoryTest.groovy
index eb83288..f5517b7 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/project/taskfactory/TaskFactoryTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/project/taskfactory/TaskFactoryTest.groovy
@@ -25,13 +25,13 @@ import org.gradle.api.internal.project.ProjectInternal
import org.gradle.api.tasks.TaskInstantiationException
import org.gradle.internal.reflect.Instantiator
import org.gradle.internal.reflect.ObjectInstantiationException
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import spock.lang.Specification
class TaskFactoryTest extends Specification {
final ClassGenerator generator = Mock()
final Instantiator instantiator = Mock()
- final ProjectInternal project = HelperUtil.createRootProject()
+ final ProjectInternal project = TestUtil.createRootProject()
final ITaskFactory taskFactory = new TaskFactory(generator).createChild(project, instantiator)
def setup() {
@@ -94,6 +94,23 @@ class TaskFactoryTest extends Specification {
task.dependsOn == ["/path1"] as Set
}
+ public void taskCreationFailsWithUnknownArguments() {
+ when:
+ taskFactory.createTask([name: 'task', dependson: 'anotherTask'])
+
+ then:
+ InvalidUserDataException exception = thrown()
+ exception.message == "Could not create task 'task': Unknown argument(s) in task definition: [dependson]"
+
+ when:
+ taskFactory.createTask([name: 'task', Type: NotATask])
+
+ then:
+ exception = thrown()
+ exception.message == "Could not create task 'task': Unknown argument(s) in task definition: [Type]"
+
+ }
+
public void testCreateTaskWithAction() {
Action<Task> action = Mock()
@@ -118,7 +135,7 @@ class TaskFactoryTest extends Specification {
public void testCreateTaskForTypeWhichDoesNotImplementTask() {
when:
- taskFactory.createTask([name: 'task', type: NotATask])
+ taskFactory.createTask([name: 'task', type: NotATask])
then:
InvalidUserDataException e = thrown()
@@ -129,7 +146,7 @@ class TaskFactoryTest extends Specification {
def failure = new RuntimeException()
when:
- taskFactory.createTask([name: 'task', type: TestDefaultTask])
+ taskFactory.createTask([name: 'task', type: TestDefaultTask])
then:
TaskInstantiationException e = thrown()
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/resource/UriResourceTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/resource/UriResourceTest.groovy
index dc2fb84..beb8119 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/resource/UriResourceTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/resource/UriResourceTest.groovy
@@ -19,7 +19,8 @@ package org.gradle.api.internal.resource
import org.gradle.test.fixtures.file.TestFile
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
-import org.gradle.testing.internal.util.Network
+import org.gradle.util.TestPrecondition
+import org.junit.Assume
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@@ -150,7 +151,7 @@ class UriResourceTest {
@Test
public void hasNoContentWhenUsingHttpUriAndFileDoesNotExist() {
- if (Network.offline) { return } // when this test moves to spock, ignore this test instead of just passing.
+ Assume.assumeTrue(TestPrecondition.ONLINE.fulfilled) // when this test moves to spock, ignore this test instead of just passing.
UriResource resource = new UriResource('<display-name>', new URI("http://www.gradle.org/unknown.txt"));
assertFalse(resource.exists)
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/resources/URIBuilderTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/resources/URIBuilderTest.groovy
index cb11589..1cdb045 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/resources/URIBuilderTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/resources/URIBuilderTest.groovy
@@ -19,9 +19,6 @@ package org.gradle.api.internal.resources;
import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 12/13/11
- */
public class URIBuilderTest extends Specification {
def "builds URIs"() {
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/DefaultTaskContainerTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/DefaultTaskContainerTest.groovy
index d1ca77b..9a6689a 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/DefaultTaskContainerTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/DefaultTaskContainerTest.groovy
@@ -14,13 +14,9 @@
* limitations under the License.
*/
-package org.gradle.api.internal.tasks;
+package org.gradle.api.internal.tasks
-
-import org.gradle.api.InvalidUserDataException
-import org.gradle.api.Rule
-import org.gradle.api.Task
-import org.gradle.api.UnknownTaskException
+import org.gradle.api.*
import org.gradle.api.internal.TaskInternal
import org.gradle.api.internal.project.ProjectInternal
import org.gradle.api.internal.project.taskfactory.ITaskFactory
@@ -28,7 +24,6 @@ import org.gradle.api.tasks.TaskDependency
import org.gradle.initialization.ProjectAccessListener
import org.gradle.internal.reflect.Instantiator
import org.gradle.util.GUtil
-import org.gradle.util.HelperUtil
import spock.lang.Specification
import static java.util.Collections.singletonMap
@@ -76,7 +71,7 @@ public class DefaultTaskContainerTest extends Specification {
void "adds by name and closure"() {
given:
- final Closure action = HelperUtil.toClosure("{ description = 'description' }")
+ final Closure action = {}
def options = singletonMap(Task.TASK_NAME, "task")
def task = task("task")
@@ -90,6 +85,38 @@ public class DefaultTaskContainerTest extends Specification {
1 * task.configure(action) >> task
}
+ void "creates by name and closure"() {
+ given:
+ final Closure action = {}
+ def options = singletonMap(Task.TASK_NAME, "task")
+ def task = task("task")
+
+ taskFactory.createTask(options) >> task
+
+ when:
+ def added = container.create("task", action)
+
+ then:
+ added == task
+ 1 * task.configure(action) >> task
+ }
+
+ void "creates by name and action"() {
+ given:
+ def action = Mock(Action)
+ def options = singletonMap(Task.TASK_NAME, "task")
+ def task = task("task")
+
+ taskFactory.createTask(options) >> task
+
+ when:
+ def added = container.create("task", action)
+
+ then:
+ added == task
+ 1 * action.execute(task)
+ }
+
void "replaces task by name"() {
given:
def options = singletonMap(Task.TASK_NAME, "task")
@@ -272,13 +299,43 @@ public class DefaultTaskContainerTest extends Specification {
aTaskDependency.getDependencies(task) >> { container.add("b"); Collections.singleton(b) }
task.dependsOn("b")
+ addPlaceholderTask("c")
+
assert container.size() == 1
when:
container.actualize()
then:
- container.size() == 2
+ container.size() == 3
+ }
+
+ void "can add task via placeholder action"() {
+ when:
+ addPlaceholderTask("task")
+ then:
+ container.getByName("task") != null
+ }
+
+ void "task priotized over placeholders"() {
+ given:
+ Task task = addTask("task")
+ Runnable placeholderAction = addPlaceholderTask("task")
+
+ when:
+ container.getByName("task") == task
+
+ then:
+ 0 * placeholderAction.run()
+ }
+
+ void "getNames contains task and placeholder action names"() {
+ when:
+ addTask("task1")
+ Runnable placeholderAction = addPlaceholderTask("task2")
+ 0 * placeholderAction.run()
+ then:
+ container.names == ['task1', 'task2'] as SortedSet
}
private ProjectInternal expectTaskLookupInOtherProject(final String projectPath, final String taskName, def task) {
@@ -299,11 +356,18 @@ public class DefaultTaskContainerTest extends Specification {
}
}
+ private Runnable addPlaceholderTask(String placeholderName) {
+ Runnable runnable = Mock(Runnable)
+ runnable.run() >> { addTask(placeholderName) }
+ container.addPlaceholderAction(placeholderName, runnable)
+ runnable
+ }
+
private Task addTask(String name) {
def task = task(name)
def options = singletonMap(Task.TASK_NAME, name)
taskFactory.createTask(options) >> task
- container.add(name)
+ container.create(name)
return task;
}
}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.java
index f7bf87e..725b307 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2010 the original author or authors.
+ * Copyright 2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,11 +15,12 @@
*/
package org.gradle.api.internal.tasks.execution;
-import org.gradle.api.Action;
import org.gradle.api.Task;
import org.gradle.api.execution.TaskActionListener;
import org.gradle.api.internal.TaskInternal;
import org.gradle.api.internal.project.ProjectInternal;
+import org.gradle.api.internal.tasks.ContextAwareTaskAction;
+import org.gradle.api.internal.tasks.TaskExecutionContext;
import org.gradle.api.internal.tasks.TaskStateInternal;
import org.gradle.api.tasks.StopActionException;
import org.gradle.api.tasks.StopExecutionException;
@@ -47,11 +48,10 @@ import static org.junit.Assert.assertThat;
public class ExecuteActionsTaskExecuterTest {
private final JUnit4Mockery context = new JUnit4GroovyMockery();
private final TaskInternal task = context.mock(TaskInternal.class, "<task>");
- @SuppressWarnings("unchecked")
- private final Action<Task> action1 = context.mock(Action.class, "action1");
- @SuppressWarnings("unchecked")
- private final Action<Task> action2 = context.mock(Action.class, "action2");
+ private final ContextAwareTaskAction action1 = context.mock(ContextAwareTaskAction.class, "action1");
+ private final ContextAwareTaskAction action2 = context.mock(ContextAwareTaskAction.class, "action2");
private final TaskStateInternal state = context.mock(TaskStateInternal.class);
+ private final TaskExecutionContext executionContext = context.mock(TaskExecutionContext.class);
private final ScriptSource scriptSource = context.mock(ScriptSource.class);
private final StandardOutputCapture standardOutputCapture = context.mock(StandardOutputCapture.class);
private final Sequence sequence = context.sequence("seq");
@@ -79,7 +79,7 @@ public class ExecuteActionsTaskExecuterTest {
@Test
public void doesNothingWhenTaskHasNoActions() {
context.checking(new Expectations() {{
- allowing(task).getActions();
+ allowing(task).getTaskActions();
will(returnValue(emptyList()));
one(listener).beforeActions(task);
@@ -98,13 +98,13 @@ public class ExecuteActionsTaskExecuterTest {
inSequence(sequence);
}});
- executer.execute(task, state);
+ executer.execute(task, state, executionContext);
}
@Test
public void executesEachActionInOrder() {
context.checking(new Expectations() {{
- allowing(task).getActions();
+ allowing(task).getTaskActions();
will(returnValue(toList(action1, action2)));
one(listener).beforeActions(task);
@@ -119,9 +119,15 @@ public class ExecuteActionsTaskExecuterTest {
one(standardOutputCapture).start();
inSequence(sequence);
+ one(action1).contextualise(executionContext);
+ inSequence(sequence);
+
one(action1).execute(task);
inSequence(sequence);
+ one(action1).contextualise(null);
+ inSequence(sequence);
+
one(standardOutputCapture).stop();
inSequence(sequence);
@@ -131,9 +137,15 @@ public class ExecuteActionsTaskExecuterTest {
one(standardOutputCapture).start();
inSequence(sequence);
+ one(action2).contextualise(executionContext);
+ inSequence(sequence);
+
one(action2).execute(task);
inSequence(sequence);
+ one(action2).contextualise(null);
+ inSequence(sequence);
+
one(standardOutputCapture).stop();
inSequence(sequence);
@@ -147,7 +159,7 @@ public class ExecuteActionsTaskExecuterTest {
inSequence(sequence);
}});
- executer.execute(task, state);
+ executer.execute(task, state, executionContext);
}
@Test
@@ -157,6 +169,9 @@ public class ExecuteActionsTaskExecuterTest {
allowing(task).getActions();
will(returnValue(toList(action1)));
+ allowing(task).getTaskActions();
+ will(returnValue(toList(action1)));
+
one(listener).beforeActions(task);
inSequence(sequence);
@@ -169,6 +184,9 @@ public class ExecuteActionsTaskExecuterTest {
one(standardOutputCapture).start();
inSequence(sequence);
+ one(action1).contextualise(executionContext);
+ inSequence(sequence);
+
one(action1).execute(task);
will(new CustomAction("Add action to actions list") {
public Object invoke(Invocation invocation) throws Throwable {
@@ -179,6 +197,9 @@ public class ExecuteActionsTaskExecuterTest {
inSequence(sequence);
+ one(action1).contextualise(null);
+ inSequence(sequence);
+
one(standardOutputCapture).stop();
one(state).executed(null);
inSequence(sequence);
@@ -190,7 +211,7 @@ public class ExecuteActionsTaskExecuterTest {
inSequence(sequence);
}
});
- executer.execute(task, state);
+ executer.execute(task, state, executionContext);
}
@@ -199,7 +220,7 @@ public class ExecuteActionsTaskExecuterTest {
final Throwable failure = new RuntimeException("failure");
final Collector<Throwable> wrappedFailure = collector();
context.checking(new Expectations() {{
- allowing(task).getActions();
+ allowing(task).getTaskActions();
will(returnValue(toList(action1, action2)));
one(listener).beforeActions(task);
@@ -214,10 +235,16 @@ public class ExecuteActionsTaskExecuterTest {
one(standardOutputCapture).start();
inSequence(sequence);
+ one(action1).contextualise(executionContext);
+ inSequence(sequence);
+
one(action1).execute(task);
will(throwException(failure));
inSequence(sequence);
+ one(action1).contextualise(null);
+ inSequence(sequence);
+
one(standardOutputCapture).stop();
inSequence(sequence);
@@ -232,7 +259,7 @@ public class ExecuteActionsTaskExecuterTest {
inSequence(sequence);
}});
- executer.execute(task, state);
+ executer.execute(task, state, executionContext);
assertThat(wrappedFailure.get(), instanceOf(TaskExecutionException.class));
TaskExecutionException exception = (TaskExecutionException) wrappedFailure.get();
@@ -244,7 +271,7 @@ public class ExecuteActionsTaskExecuterTest {
@Test
public void stopsAtFirstActionWhichThrowsStopExecutionException() {
context.checking(new Expectations() {{
- allowing(task).getActions();
+ allowing(task).getTaskActions();
will(returnValue(toList(action1, action2)));
one(listener).beforeActions(task);
@@ -259,10 +286,16 @@ public class ExecuteActionsTaskExecuterTest {
one(standardOutputCapture).start();
inSequence(sequence);
+ one(action1).contextualise(executionContext);
+ inSequence(sequence);
+
one(action1).execute(task);
will(throwException(new StopExecutionException("stop")));
inSequence(sequence);
+ one(action1).contextualise(null);
+ inSequence(sequence);
+
one(standardOutputCapture).stop();
inSequence(sequence);
@@ -276,13 +309,13 @@ public class ExecuteActionsTaskExecuterTest {
inSequence(sequence);
}});
- executer.execute(task, state);
+ executer.execute(task, state, executionContext);
}
@Test
public void skipsActionWhichThrowsStopActionException() {
context.checking(new Expectations() {{
- allowing(task).getActions();
+ allowing(task).getTaskActions();
will(returnValue(toList(action1, action2)));
one(listener).beforeActions(task);
@@ -297,10 +330,16 @@ public class ExecuteActionsTaskExecuterTest {
one(standardOutputCapture).start();
inSequence(sequence);
+ one(action1).contextualise(executionContext);
+ inSequence(sequence);
+
one(action1).execute(task);
will(throwException(new StopActionException("stop")));
inSequence(sequence);
+ one(action1).contextualise(null);
+ inSequence(sequence);
+
one(standardOutputCapture).stop();
inSequence(sequence);
@@ -310,9 +349,15 @@ public class ExecuteActionsTaskExecuterTest {
one(standardOutputCapture).start();
inSequence(sequence);
+ one(action2).contextualise(executionContext);
+ inSequence(sequence);
+
one(action2).execute(task);
inSequence(sequence);
+ one(action2).contextualise(null);
+ inSequence(sequence);
+
one(standardOutputCapture).stop();
inSequence(sequence);
@@ -326,6 +371,6 @@ public class ExecuteActionsTaskExecuterTest {
inSequence(sequence);
}});
- executer.execute(task, state);
+ executer.execute(task, state, executionContext);
}
}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteAtMostOnceTaskExecuterTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteAtMostOnceTaskExecuterTest.groovy
index ecb7cb2..d751c10 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteAtMostOnceTaskExecuterTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteAtMostOnceTaskExecuterTest.groovy
@@ -16,14 +16,17 @@
package org.gradle.api.internal.tasks.execution
import org.gradle.api.internal.TaskInternal
+import org.gradle.api.internal.tasks.TaskExecuter
+import org.gradle.api.internal.tasks.TaskExecutionContext
+import org.gradle.api.internal.tasks.TaskStateInternal
import org.gradle.util.JUnit4GroovyMockery
import org.jmock.integration.junit4.JMock
import org.junit.Test
import org.junit.runner.RunWith
-import org.gradle.api.internal.tasks.TaskExecuter
-import org.gradle.api.internal.tasks.TaskStateInternal
-import static org.junit.Assert.*
-import static org.hamcrest.Matchers.*
+
+import static org.hamcrest.Matchers.sameInstance
+import static org.junit.Assert.assertThat
+import static org.junit.Assert.fail
@RunWith(JMock.class)
class ExecuteAtMostOnceTaskExecuterTest {
@@ -31,6 +34,7 @@ class ExecuteAtMostOnceTaskExecuterTest {
private final TaskExecuter target = context.mock(TaskExecuter.class)
private final TaskInternal task = context.mock(TaskInternal.class)
private final TaskStateInternal state = context.mock(TaskStateInternal.class)
+ private final TaskExecutionContext executionContext = context.mock(TaskExecutionContext)
private final ExecuteAtMostOnceTaskExecuter executer = new ExecuteAtMostOnceTaskExecuter(target)
@Test
@@ -40,7 +44,7 @@ class ExecuteAtMostOnceTaskExecuterTest {
will(returnValue(true))
}
- executer.execute(task, state)
+ executer.execute(task, state, executionContext)
}
@Test
@@ -48,11 +52,11 @@ class ExecuteAtMostOnceTaskExecuterTest {
context.checking {
allowing(state).getExecuted()
will(returnValue(false))
- one(target).execute(task, state)
+ one(target).execute(task, state, executionContext)
one(state).executed()
}
- executer.execute(task, state)
+ executer.execute(task, state, executionContext)
}
@Test
@@ -62,13 +66,13 @@ class ExecuteAtMostOnceTaskExecuterTest {
context.checking {
allowing(state).getExecuted()
will(returnValue(false))
- one(target).execute(task, state)
+ one(target).execute(task, state, executionContext)
will(throwException(failure))
one(state).executed()
}
try {
- executer.execute(task, state)
+ executer.execute(task, state, executionContext)
fail()
} catch (RuntimeException e) {
assertThat(e, sameInstance(failure))
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/PostExecutionAnalysisTaskExecuterTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/PostExecutionAnalysisTaskExecuterTest.groovy
index 9054502..aa17273 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/PostExecutionAnalysisTaskExecuterTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/PostExecutionAnalysisTaskExecuterTest.groovy
@@ -14,52 +14,38 @@
* limitations under the License.
*/
-
-
-
package org.gradle.api.internal.tasks.execution
-
-import org.gradle.api.Action
import org.gradle.api.internal.TaskInternal
import org.gradle.api.internal.tasks.TaskExecuter
+import org.gradle.api.internal.tasks.TaskExecutionContext
import org.gradle.api.internal.tasks.TaskStateInternal
-import org.gradle.util.JUnit4GroovyMockery
-import org.jmock.integration.junit4.JMock
-import org.junit.Test
-import org.junit.runner.RunWith
-
- at RunWith(JMock.class)
-class PostExecutionAnalysisTaskExecuterTest {
- private final JUnit4GroovyMockery context = new JUnit4GroovyMockery()
- private final TaskExecuter target = context.mock(TaskExecuter.class)
- private final TaskInternal task = context.mock(TaskInternal.class)
- private final TaskStateInternal state = context.mock(TaskStateInternal.class)
- private final PostExecutionAnalysisTaskExecuter executer = new PostExecutionAnalysisTaskExecuter(target)
-
- @Test
- public void marksTaskUpToDateWhenItHasActionsAndItDidNotDoWork() {
- context.checking {
- one(target).execute(task, state)
- allowing(task).getActions();
- will(returnValue([{} as Action]))
- allowing(state).getDidWork()
- will(returnValue(false))
- one(state).upToDate()
- }
-
- executer.execute(task, state)
+import spock.lang.Specification
+
+class PostExecutionAnalysisTaskExecuterTest extends Specification {
+ def target = Mock(TaskExecuter)
+ def task = Mock(TaskInternal)
+ def state = Mock(TaskStateInternal)
+ def context = Mock(TaskExecutionContext)
+ final PostExecutionAnalysisTaskExecuter executer = new PostExecutionAnalysisTaskExecuter(target)
+
+ def marksTaskUpToDateWhenItHasActionsAndItDidNotDoWork() {
+ when:
+ executer.execute(task, state, context)
+
+ then:
+ 1 * target.execute(task, state, context)
+ 1 * state.didWork >> false
+ 1 * state.upToDate()
+ 0 * _
}
- @Test
- public void doesNotMarkTaskUpToDateWhenItHasActionsAndDidWork() {
- context.checking {
- one(target).execute(task, state)
- allowing(task).getActions();
- will(returnValue([{} as Action]))
- allowing(state).getDidWork()
- will(returnValue(true))
- }
+ def doesNotMarkTaskUpToDateWhenItHasActionsAndDidWork() {
+ when:
+ executer.execute(task, state, context)
- executer.execute(task, state)
+ then:
+ 1 * target.execute(task, state, context)
+ 1 * state.didWork >> true
+ 0 * _
}
}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/SkipEmptySourceFilesTaskExecuterTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/SkipEmptySourceFilesTaskExecuterTest.groovy
index c6746c0..8a638b8 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/SkipEmptySourceFilesTaskExecuterTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/SkipEmptySourceFilesTaskExecuterTest.groovy
@@ -18,6 +18,7 @@ package org.gradle.api.internal.tasks.execution
import org.gradle.api.file.FileCollection
import org.gradle.api.internal.TaskInternal
import org.gradle.api.internal.tasks.TaskExecuter
+import org.gradle.api.internal.tasks.TaskExecutionContext
import org.gradle.api.internal.tasks.TaskStateInternal
import org.gradle.api.tasks.TaskInputs
import spock.lang.Specification
@@ -26,6 +27,7 @@ class SkipEmptySourceFilesTaskExecuterTest extends Specification {
final TaskExecuter target = Mock()
final TaskInternal task = Mock()
final TaskStateInternal state = Mock()
+ final TaskExecutionContext executionContext = Mock()
final TaskInputs taskInputs = Mock()
final FileCollection sourceFiles = Mock()
final SkipEmptySourceFilesTaskExecuter executer = new SkipEmptySourceFilesTaskExecuter(target)
@@ -41,7 +43,7 @@ class SkipEmptySourceFilesTaskExecuterTest extends Specification {
sourceFiles.empty >> true
when:
- executer.execute(task, state)
+ executer.execute(task, state, executionContext)
then:
1 * state.upToDate()
@@ -55,10 +57,10 @@ class SkipEmptySourceFilesTaskExecuterTest extends Specification {
sourceFiles.empty >> false
when:
- executer.execute(task, state)
+ executer.execute(task, state, executionContext)
then:
- 1 * target.execute(task, state)
+ 1 * target.execute(task, state, executionContext)
0 * target._
0 * state._
}
@@ -68,10 +70,10 @@ class SkipEmptySourceFilesTaskExecuterTest extends Specification {
taskInputs.hasSourceFiles >> false
when:
- executer.execute(task, state)
+ executer.execute(task, state, executionContext)
then:
- 1 * target.execute(task, state)
+ 1 * target.execute(task, state, executionContext)
0 * target._
0 * state._
}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/SkipOnlyIfTaskExecuterTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/SkipOnlyIfTaskExecuterTest.java
index 80ab5cf..21453f0 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/SkipOnlyIfTaskExecuterTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/SkipOnlyIfTaskExecuterTest.java
@@ -21,6 +21,7 @@ import org.gradle.api.Task;
import org.gradle.api.internal.TaskInternal;
import org.gradle.api.internal.project.ProjectInternal;
import org.gradle.api.internal.tasks.TaskExecuter;
+import org.gradle.api.internal.tasks.TaskExecutionContext;
import org.gradle.api.internal.tasks.TaskStateInternal;
import org.gradle.api.specs.Spec;
import org.gradle.groovy.scripts.ScriptSource;
@@ -42,6 +43,8 @@ public class SkipOnlyIfTaskExecuterTest {
private final TaskInternal task = context.mock(TaskInternal.class, "<task>");
private final Spec<Task> spec = context.mock(Spec.class);
private final TaskStateInternal state = context.mock(TaskStateInternal.class);
+ private final TaskExecutionContext executionContext = context.mock(TaskExecutionContext.class);
+
private final ScriptSource scriptSource = context.mock(ScriptSource.class);
private final TaskExecuter delegate = context.mock(TaskExecuter.class);
private final SkipOnlyIfTaskExecuter executer = new SkipOnlyIfTaskExecuter(delegate);
@@ -73,10 +76,10 @@ public class SkipOnlyIfTaskExecuterTest {
allowing(spec).isSatisfiedBy(task);
will(returnValue(true));
- one(delegate).execute(task, state);
+ one(delegate).execute(task, state, executionContext);
}});
- executer.execute(task, state);
+ executer.execute(task, state, executionContext);
}
@Test
@@ -89,7 +92,7 @@ public class SkipOnlyIfTaskExecuterTest {
one(state).skipped("SKIPPED");
}});
- executer.execute(task, state);
+ executer.execute(task, state, executionContext);
}
@Test
@@ -105,7 +108,7 @@ public class SkipOnlyIfTaskExecuterTest {
will(collectTo(wrappedFailure));
}});
- executer.execute(task, state);
+ executer.execute(task, state, executionContext);
GradleException exception = (GradleException) wrappedFailure.get();
assertThat(exception.getMessage(), equalTo("Could not evaluate onlyIf predicate for <task>."));
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/SkipTaskWithNoActionsExecuterTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/SkipTaskWithNoActionsExecuterTest.groovy
index 429f7ea..e3dd720 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/SkipTaskWithNoActionsExecuterTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/SkipTaskWithNoActionsExecuterTest.groovy
@@ -16,15 +16,17 @@
package org.gradle.api.internal.tasks.execution
import org.gradle.api.internal.TaskInternal
+import org.gradle.api.internal.tasks.TaskExecuter
+import org.gradle.api.internal.tasks.TaskExecutionContext
+import org.gradle.api.internal.tasks.TaskStateInternal
import org.gradle.api.tasks.TaskAction
import org.gradle.api.tasks.TaskDependency
import spock.lang.Specification
-import org.gradle.api.internal.tasks.TaskStateInternal
-import org.gradle.api.internal.tasks.TaskExecuter
class SkipTaskWithNoActionsExecuterTest extends Specification {
final TaskInternal task = Mock()
final TaskStateInternal state = Mock()
+ final TaskExecutionContext executionContext = Mock()
final TaskExecuter target = Mock()
final TaskInternal dependency = Mock()
final TaskStateInternal dependencyState = Mock()
@@ -43,7 +45,7 @@ class SkipTaskWithNoActionsExecuterTest extends Specification {
dependencyState.skipped >> true
when:
- executor.execute(task, state)
+ executor.execute(task, state, executionContext)
then:
1 * state.upToDate()
@@ -57,7 +59,7 @@ class SkipTaskWithNoActionsExecuterTest extends Specification {
dependencyState.skipped >> false
when:
- executor.execute(task, state)
+ executor.execute(task, state, executionContext)
then:
0 * target._
@@ -69,10 +71,10 @@ class SkipTaskWithNoActionsExecuterTest extends Specification {
task.actions >> [{} as TaskAction]
when:
- executor.execute(task, state)
+ executor.execute(task, state, executionContext)
then:
- 1 * target.execute(task, state)
+ 1 * target.execute(task, state, executionContext)
0 * target._
0 * state._
}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/SkipUpToDateTaskExecuterTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/SkipUpToDateTaskExecuterTest.groovy
new file mode 100644
index 0000000..1d474dd
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/SkipUpToDateTaskExecuterTest.groovy
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.tasks.execution
+
+import org.gradle.api.Action
+import org.gradle.api.Task
+import org.gradle.api.internal.TaskExecutionHistory
+import org.gradle.api.internal.TaskInternal
+import org.gradle.api.internal.TaskOutputsInternal
+import org.gradle.api.internal.changedetection.TaskArtifactState
+import org.gradle.api.internal.changedetection.TaskArtifactStateRepository
+import org.gradle.api.internal.tasks.TaskExecuter
+import org.gradle.api.internal.tasks.TaskExecutionContext
+import org.gradle.api.internal.tasks.TaskStateInternal
+import spock.lang.Specification
+
+public class SkipUpToDateTaskExecuterTest extends Specification {
+ def delegate = Mock(TaskExecuter)
+ def outputs = Mock(TaskOutputsInternal)
+ def task = Mock(TaskInternal)
+ def taskState = Mock(TaskStateInternal)
+ def taskContext = Mock(TaskExecutionContext)
+ def repository = Mock(TaskArtifactStateRepository)
+ def taskArtifactState = Mock(TaskArtifactState)
+ def executionHistory = Mock(TaskExecutionHistory)
+ Action<Task> action = Mock(Action)
+
+ def executer = new SkipUpToDateTaskExecuter(repository, delegate)
+
+ def skipsTaskWhenOutputsAreUpToDate() {
+ when:
+ executer.execute(task, taskState, taskContext);
+
+ then:
+ 1 * repository.getStateFor(task) >> taskArtifactState
+ 1 * taskArtifactState.isUpToDate([]) >> true
+ 1 * taskState.upToDate()
+ 1 * taskArtifactState.finished()
+ 0 * _
+ }
+
+ def executesTaskWhenOutputsAreNotUpToDate() {
+ when:
+ executer.execute(task, taskState, taskContext);
+
+ then:
+ 1 * repository.getStateFor(task) >> taskArtifactState
+ 1 * taskArtifactState.isUpToDate([]) >> false
+
+ then:
+ 1 * taskArtifactState.beforeTask()
+ 1 * taskArtifactState.getExecutionHistory() >> executionHistory
+ 1 * task.outputs >> outputs
+ 1 * outputs.setHistory(executionHistory)
+ 1 * taskContext.setTaskArtifactState(taskArtifactState)
+
+ then:
+ 1 * delegate.execute(task, taskState, taskContext)
+ _ * taskState.getFailure() >> null
+
+ then:
+ 1 * taskArtifactState.afterTask()
+ 1 * task.outputs >> outputs
+ 1 * outputs.setHistory(null)
+ 1 * taskContext.setTaskArtifactState(null)
+ 1 * taskArtifactState.finished()
+ 0 * _
+ }
+
+ def doesNotUpdateStateWhenTaskFails() {
+ when:
+ executer.execute(task, taskState, taskContext)
+
+ then:
+ 1 * repository.getStateFor(task) >> taskArtifactState
+ 1 * taskArtifactState.isUpToDate([]) >> false
+
+ then:
+ 1 * taskArtifactState.beforeTask()
+ 1 * taskArtifactState.getExecutionHistory() >> executionHistory
+ 1 * task.outputs >> outputs
+ 1 * outputs.setHistory(executionHistory)
+ 1 * taskContext.setTaskArtifactState(taskArtifactState)
+
+ then:
+ 1 * delegate.execute(task, taskState, taskContext)
+ 1 * taskState.getFailure() >> new RuntimeException()
+
+ then:
+ 1 * task.outputs >> outputs
+ 1 * outputs.setHistory(null)
+ 1 * taskContext.setTaskArtifactState(null)
+ 1 * taskArtifactState.finished()
+ 0 * _
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/SkipUpToDateTaskExecuterTest.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/SkipUpToDateTaskExecuterTest.java
deleted file mode 100644
index 61a5847..0000000
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/SkipUpToDateTaskExecuterTest.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.tasks.execution;
-
-import org.gradle.api.internal.TaskExecutionHistory;
-import org.gradle.api.internal.TaskInternal;
-import org.gradle.api.internal.TaskOutputsInternal;
-import org.gradle.api.internal.changedetection.TaskArtifactState;
-import org.gradle.api.internal.changedetection.TaskArtifactStateRepository;
-import org.gradle.api.internal.tasks.TaskExecuter;
-import org.gradle.api.internal.tasks.TaskStateInternal;
-import org.gradle.util.JUnit4GroovyMockery;
-import org.jmock.Expectations;
-import org.jmock.Sequence;
-import org.jmock.integration.junit4.JMock;
-import org.jmock.integration.junit4.JUnit4Mockery;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
- at RunWith(JMock.class)
-public class SkipUpToDateTaskExecuterTest {
- private final JUnit4Mockery context = new JUnit4GroovyMockery();
- private final TaskExecuter delegate = context.mock(TaskExecuter.class);
- private final TaskOutputsInternal outputs = context.mock(TaskOutputsInternal.class);
- private final TaskInternal task = context.mock(TaskInternal.class);
- private final TaskStateInternal taskState = context.mock(TaskStateInternal.class);
- private final TaskArtifactStateRepository repository = context.mock(TaskArtifactStateRepository.class);
- private final TaskArtifactState taskArtifactState = context.mock(TaskArtifactState.class);
- private final TaskExecutionHistory executionHistory = context.mock(TaskExecutionHistory.class);
- private final SkipUpToDateTaskExecuter executer = new SkipUpToDateTaskExecuter(delegate, repository);
-
- @Before
- public void setup() {
-
- context.checking(new Expectations(){{
- allowing(task).getOutputs();
- will(returnValue(outputs));
- }});
- }
- @Test
- public void skipsTaskWhenOutputsAreUpToDate() {
- context.checking(new Expectations() {{
- one(repository).getStateFor(task);
- will(returnValue(taskArtifactState));
-
- one(taskArtifactState).isUpToDate();
- will(returnValue(true));
-
- one(taskState).upToDate();
-
- one(taskArtifactState).finished();
- }});
-
- executer.execute(task, taskState);
- }
-
- @Test
- public void executesTaskWhenOutputsAreNotUpToDate() {
- context.checking(new Expectations() {{
- Sequence sequence = context.sequence("seq");
-
- one(repository).getStateFor(task);
- will(returnValue(taskArtifactState));
- inSequence(sequence);
-
- one(taskArtifactState).isUpToDate();
- will(returnValue(false));
- inSequence(sequence);
-
- one(taskArtifactState).beforeTask();
- inSequence(sequence);
-
- one(taskArtifactState).getExecutionHistory();
- will(returnValue(executionHistory));
-
- one(outputs).setHistory(executionHistory);
- inSequence(sequence);
-
- one(delegate).execute(task, taskState);
- inSequence(sequence);
-
- allowing(taskState).getFailure();
- will(returnValue(null));
-
- one(taskArtifactState).afterTask();
- inSequence(sequence);
-
- one(outputs).setHistory(null);
- inSequence(sequence);
-
- one(taskArtifactState).finished();
- inSequence(sequence);
- }});
-
- executer.execute(task, taskState);
- }
-
- @Test
- public void doesNotUpdateStateWhenTaskFails() {
- context.checking(new Expectations() {{
- one(repository).getStateFor(task);
- will(returnValue(taskArtifactState));
-
- one(taskArtifactState).isUpToDate();
- will(returnValue(false));
-
- one(taskArtifactState).beforeTask();
-
- one(taskArtifactState).getExecutionHistory();
- will(returnValue(executionHistory));
-
- one(outputs).setHistory(executionHistory);
-
- one(delegate).execute(task, taskState);
-
- allowing(taskState).getFailure();
- will(returnValue(new RuntimeException()));
-
- one(outputs).setHistory(null);
-
- one(taskArtifactState).finished();
- }});
-
- executer.execute(task, taskState);
- }
-}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ValidatingTaskExecuterTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ValidatingTaskExecuterTest.groovy
index 74e5113..07c4a05 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ValidatingTaskExecuterTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ValidatingTaskExecuterTest.groovy
@@ -15,34 +15,36 @@
*/
package org.gradle.api.internal.tasks.execution
-import spock.lang.Specification
-import org.gradle.api.internal.tasks.TaskStateInternal
+import org.gradle.api.InvalidUserDataException
import org.gradle.api.internal.TaskInternal
import org.gradle.api.internal.tasks.TaskExecuter
-import org.gradle.api.InvalidUserDataException
+import org.gradle.api.internal.tasks.TaskExecutionContext
+import org.gradle.api.internal.tasks.TaskStateInternal
import org.gradle.api.tasks.TaskValidationException
+import spock.lang.Specification
class ValidatingTaskExecuterTest extends Specification {
final TaskExecuter target = Mock()
final TaskInternal task = Mock()
final TaskStateInternal state = Mock()
+ final TaskExecutionContext executionContext = Mock()
final TaskValidator validator = Mock()
final ValidatingTaskExecuter executer = new ValidatingTaskExecuter(target)
def executesTaskWhenThereAreNoViolations() {
when:
- executer.execute(task, state)
+ executer.execute(task, state, executionContext)
then:
_ * task.validators >> [validator]
1 * validator.validate(task, !null)
- 1 * target.execute(task, state)
+ 1 * target.execute(task, state, executionContext)
0 * _._
}
def failsTaskWhenThereIsAViolation() {
when:
- executer.execute(task, state)
+ executer.execute(task, state, executionContext)
then:
_ * task.validators >> [validator]
@@ -59,7 +61,7 @@ class ValidatingTaskExecuterTest extends Specification {
def failsTaskWhenThereAreMultipleViolations() {
when:
- executer.execute(task, state)
+ executer.execute(task, state, executionContext)
then:
_ * task.validators >> [validator]
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/util/DefaultJavaForkOptionsTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/util/DefaultJavaForkOptionsTest.groovy
index abce164..9141221 100755
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/util/DefaultJavaForkOptionsTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/util/DefaultJavaForkOptionsTest.groovy
@@ -17,10 +17,11 @@
package org.gradle.api.internal.tasks.util
+import org.gradle.api.internal.file.TestFiles
+
import java.nio.charset.Charset
import org.gradle.api.file.FileCollection
import org.gradle.api.internal.file.FileResolver
-import org.gradle.api.internal.file.IdentityFileResolver
import org.gradle.process.JavaForkOptions
import org.gradle.process.internal.DefaultJavaForkOptions
import org.gradle.util.JUnit4GroovyMockery
@@ -235,7 +236,7 @@ public class DefaultJavaForkOptionsTest {
@Test
public void canAddToBootstrapClasspath() {
def files = ['file1.jar', 'file2.jar'].collect { new File(it).canonicalFile }
- options = new DefaultJavaForkOptions(new IdentityFileResolver());
+ options = new DefaultJavaForkOptions(TestFiles.resolver());
options.bootstrapClasspath(files[0])
options.bootstrapClasspath(files[1])
@@ -245,7 +246,7 @@ public class DefaultJavaForkOptionsTest {
@Test
public void allJvmArgsIncludeBootstrapClasspath() {
def files = ['file1.jar', 'file2.jar'].collect { new File(it).canonicalFile }
- options = new DefaultJavaForkOptions(new IdentityFileResolver());
+ options = new DefaultJavaForkOptions(TestFiles.resolver());
options.bootstrapClasspath(files)
context.checking {
@@ -259,7 +260,7 @@ public class DefaultJavaForkOptionsTest {
@Test
public void canSetBootstrapClasspathViaAllJvmArgs() {
def files = ['file1.jar', 'file2.jar'].collect { new File(it).canonicalFile }
- options = new DefaultJavaForkOptions(new IdentityFileResolver());
+ options = new DefaultJavaForkOptions(TestFiles.resolver());
options.bootstrapClasspath(files[0])
options.allJvmArgs = ['-Xbootclasspath:' + files[1]]
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/xml/SimpleXmlWriterSpec.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/xml/SimpleXmlWriterSpec.groovy
index 38a67b4..6e22d70 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/xml/SimpleXmlWriterSpec.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/xml/SimpleXmlWriterSpec.groovy
@@ -16,14 +16,11 @@
package org.gradle.api.internal.xml
+import org.gradle.util.TextUtil
import spock.lang.Specification
import javax.xml.parsers.DocumentBuilderFactory
-import org.gradle.util.TextUtil
-/**
- * by Szczepan Faber, created at: 12/3/12
- */
class SimpleXmlWriterSpec extends Specification {
private sw = new ByteArrayOutputStream()
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/plugins/TestPluginConvention1.groovy b/subprojects/core/src/test/groovy/org/gradle/api/plugins/TestPluginConvention1.groovy
index c38c20f..0af5662 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/plugins/TestPluginConvention1.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/plugins/TestPluginConvention1.groovy
@@ -16,9 +16,6 @@
package org.gradle.api.plugins
-/**
- * @author Hans Dockter
- */
class TestPluginConvention1 {
String a = 'a1'
String b = 'b'
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/plugins/TestPluginConvention2.groovy b/subprojects/core/src/test/groovy/org/gradle/api/plugins/TestPluginConvention2.groovy
index a7e1b4d..0aab5b1 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/plugins/TestPluginConvention2.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/plugins/TestPluginConvention2.groovy
@@ -16,9 +16,6 @@
package org.gradle.api.plugins
-/**
- * @author Hans Dockter
- */
class TestPluginConvention2 {
String a = 'a2'
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/tasks/AbstractCopyTaskTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/tasks/AbstractCopyTaskTest.groovy
new file mode 100644
index 0000000..ad7f4a8
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/api/tasks/AbstractCopyTaskTest.groovy
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.tasks
+
+import org.gradle.api.file.FileCollection
+import org.gradle.api.file.FileTree
+import org.gradle.api.internal.file.copy.CopyAction
+import org.gradle.test.fixtures.file.WorkspaceTest
+import org.gradle.util.TestUtil
+import org.junit.Test
+
+class AbstractCopyTaskTest extends WorkspaceTest {
+
+ TestCopyTask task
+
+ def setup() {
+ task = TestUtil.createTask(TestCopyTask)
+ }
+
+ void usesDefaultSourceWhenNoSourceHasBeenSpecified() {
+ given:
+ def defaultSource = Mock(FileTree)
+
+ when:
+ task.defaultSource = defaultSource
+
+ then:
+ task.source.is(defaultSource)
+ }
+
+ public void doesNotUseDefaultSourceWhenSourceHasBeenSpecifiedOnSpec() {
+ when:
+ FileTree source = Mock(FileTree)
+ task.defaultSource = source
+ task.from "foo"
+
+ then:
+ !task.source.is(source)
+ }
+
+ @Test
+ public void copySpecMethodsDelegateToMainSpecOfCopyAction() {
+ given:
+ file("include") << "bar"
+
+ expect:
+ task.rootSpec.source.isEmpty()
+
+ when:
+ task.from testDirectory.absolutePath
+ task.include "include"
+
+ then:
+ task.mainSpec.getIncludes() == ["include"].toSet()
+ task.mainSpec.source.files == task.project.fileTree(testDirectory).files
+ }
+
+ static class TestCopyTask extends AbstractCopyTask {
+ CopyAction copyAction
+ FileCollection defaultSource
+
+ protected CopyAction createCopyAction() {
+ copyAction
+ }
+
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/tasks/AbstractCopyTaskTest.java b/subprojects/core/src/test/groovy/org/gradle/api/tasks/AbstractCopyTaskTest.java
deleted file mode 100644
index 61a7581..0000000
--- a/subprojects/core/src/test/groovy/org/gradle/api/tasks/AbstractCopyTaskTest.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.tasks;
-
-import org.gradle.api.file.FileCollection;
-import org.gradle.api.file.FileTree;
-import org.gradle.api.internal.AbstractTask;
-import org.gradle.api.internal.file.copy.CopyActionImpl;
-import org.gradle.util.JUnit4GroovyMockery;
-import org.jmock.Expectations;
-import org.jmock.integration.junit4.JMock;
-import org.jmock.integration.junit4.JUnit4Mockery;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static org.hamcrest.Matchers.sameInstance;
-import static org.junit.Assert.assertThat;
-
- at RunWith(JMock.class)
-public class AbstractCopyTaskTest extends AbstractTaskTest {
- private final JUnit4Mockery context = new JUnit4GroovyMockery();
- private TestCopyTask task;
-
- @Before
- public void setUp() {
- task = createTask(TestCopyTask.class);
- task.action = context.mock(CopyActionImpl.class);
- task.defaultSource = context.mock(FileCollection.class);
- }
-
- @Override
- public AbstractTask getTask() {
- return task;
- }
-
- @Test
- public void usesDefaultSourceWhenNoSourceHasBeenSpecified() {
- context.checking(new Expectations() {{
- one(task.action).hasSource();
- will(returnValue(false));
-
- }});
- assertThat(task.getSource(), sameInstance(task.defaultSource));
- }
-
- @Test
- public void doesNotUseDefaultSourceWhenSourceHasBeenSpecifiedOnSpec() {
- final FileTree source = context.mock(FileTree.class, "source");
- context.checking(new Expectations() {{
- one(task.action).hasSource();
- will(returnValue(true));
- one(task.action).getAllSource();
- will(returnValue(source));
- }});
- assertThat(task.getSource(), sameInstance((FileCollection) source));
- }
-
-
- @Test
- public void copySpecMethodsDelegateToMainSpecOfCopyAction() {
- context.checking(new Expectations() {{
- one(task.action).include("include");
- one(task.action).from("source");
- }});
-
- assertThat(task.include("include"), sameInstance((AbstractCopyTask) task));
- assertThat(task.from("source"), sameInstance((AbstractCopyTask) task));
- }
-
- public static class TestCopyTask extends AbstractCopyTask {
- CopyActionImpl action;
- FileCollection defaultSource;
-
- @Override
- protected CopyActionImpl getCopyAction() {
- return action;
- }
-
- @Override
- @SuppressWarnings("deprecation")
- public FileCollection getDefaultSource() {
- return defaultSource;
- }
- }
-}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/tasks/CopyTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/tasks/CopyTest.groovy
index 9ac42c6..6c0f48c 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/tasks/CopyTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/tasks/CopyTest.groovy
@@ -1,5 +1,5 @@
/*
- * Copyright 2009 the original author or authors.
+ * Copyright 2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,69 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.gradle.api.tasks
-
-import org.gradle.api.internal.AbstractTask
-
-import org.gradle.util.JUnit4GroovyMockery
-import org.jmock.lib.legacy.ClassImposteriser
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.gradle.api.internal.file.copy.FileCopyActionImpl
-
- at RunWith (org.jmock.integration.junit4.JMock)
-public class CopyTest extends AbstractTaskTest {
- Copy copyTask;
- FileCopyActionImpl action;
- JUnit4GroovyMockery context = new JUnit4GroovyMockery();
-
- @Before
- public void setUp() {
- context.setImposteriser(ClassImposteriser.INSTANCE)
- action = context.mock(FileCopyActionImpl.class)
- copyTask = createTask(Copy.class)
- copyTask.copyAction = action
- }
-
- public AbstractTask getTask() {
- return copyTask;
- }
-
- @Test public void executesActionOnExecute() {
- context.checking {
- one(action).hasSource(); will(returnValue(true))
- one(action).getDestinationDir(); will(returnValue(new File('dest')))
- one(action).execute()
- one(action).getDidWork()
- }
-
- copyTask.copy()
- }
-
- @Test public void usesConventionValuesForDestDirWhenNotSpecified() {
- copyTask.conventionMapping.destinationDir = { new File('convention') }
-
- context.checking {
- exactly(2).of(action).getDestinationDir()
- will(returnValue(null))
- one(action).into(new File('convention'))
- one(action).hasSource(); will(returnValue(true))
- }
-
- copyTask.configureRootSpec()
- }
+package org.gradle.api.tasks
- @Test public void doesNotUseConventionValueForDestDirWhenSpecified() {
- copyTask.conventionMapping.destinationDir = { new File('convention') }
+class CopyTest extends AbstractCopyTaskContractTest {
- context.checking {
- one(action).getDestinationDir()
- will(returnValue(new File('dest')))
- one(action).hasSource(); will(returnValue(true))
- }
+ private Copy task = project.tasks.create(TEST_TASK_NAME, Copy)
- copyTask.configureRootSpec()
+ AbstractCopyTask getTask() {
+ return task
}
}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/tasks/DeleteTest.java b/subprojects/core/src/test/groovy/org/gradle/api/tasks/DeleteTest.java
index 45cc0d1..b8c8558 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/tasks/DeleteTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/api/tasks/DeleteTest.java
@@ -35,9 +35,6 @@ import java.io.IOException;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.*;
-/**
- * @author Hans Dockter
- */
@RunWith(org.jmock.integration.junit4.JMock.class)
public class DeleteTest extends AbstractConventionTaskTest {
private Mockery context = new JUnit4GroovyMockery();
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/tasks/DirectoryTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/tasks/DirectoryTest.groovy
index 9633666..f8e3842 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/tasks/DirectoryTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/tasks/DirectoryTest.groovy
@@ -16,18 +16,16 @@
package org.gradle.api.tasks
+import org.gradle.api.GradleException
import org.gradle.api.InvalidUserDataException
import org.gradle.api.UncheckedIOException
import org.gradle.api.internal.AbstractTask
import org.junit.Before
import org.junit.Test
+
+import static org.hamcrest.Matchers.instanceOf
import static org.junit.Assert.*
-import static org.hamcrest.Matchers.*
-import org.gradle.api.GradleException
-/**
- * @author Hans Dockter
- */
class DirectoryTest extends AbstractTaskTest {
static final String TASK_DIR_NAME = 'parent/child'
Directory directoryForAbstractTest
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/tasks/GradleBuildTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/tasks/GradleBuildTest.groovy
index 2e3f6e6..676313a 100755
--- a/subprojects/core/src/test/groovy/org/gradle/api/tasks/GradleBuildTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/tasks/GradleBuildTest.groovy
@@ -18,54 +18,39 @@ package org.gradle.api.tasks
import org.gradle.BuildResult
import org.gradle.GradleLauncher
import org.gradle.initialization.GradleLauncherFactory
-import org.gradle.api.internal.AbstractTask
-import org.junit.After
-import org.junit.Before
-import org.junit.Test
-import static org.hamcrest.Matchers.*
-import static org.junit.Assert.*
+import org.gradle.util.TestUtil
+import spock.lang.Specification
-public class GradleBuildTest extends AbstractTaskTest {
- GradleLauncherFactory launcherFactoryMock = context.mock(GradleLauncherFactory.class)
- GradleBuild task
+public class GradleBuildTest extends Specification {
+ GradleLauncherFactory launcherFactory = Mock()
+ GradleBuild task = TestUtil.createTask(GradleBuild, [gradleLauncherFactory: launcherFactory])
- AbstractTask getTask() {
- return task
- }
-
- @Before
- void setUp() {
- task = createTask(GradleBuild.class)
- GradleLauncher.injectCustomFactory(launcherFactoryMock)
- }
+ void usesCopyOfCurrentBuildsStartParams() {
+ def expectedStartParameter = task.project.gradle.startParameter.newBuild()
+ expectedStartParameter.currentDir = task.project.projectDir
- @After
- void tearDown() {
- GradleLauncher.injectCustomFactory(null)
- }
+ expect:
+ task.startParameter == expectedStartParameter
- @Test
- void usesCopyOfCurrentBuildsStartParams() {
- def expectedStartParameter = project.gradle.startParameter.newBuild()
- expectedStartParameter.currentDir = project.projectDir
- assertThat(task.startParameter, equalTo(expectedStartParameter))
+ when:
task.tasks = ['a', 'b']
- assertThat(task.tasks, equalTo(['a', 'b']))
- assertThat(task.startParameter.taskNames, equalTo(['a', 'b']))
+
+ then:
+ task.tasks == ['a', 'b']
+ task.startParameter.taskNames == ['a', 'b']
}
- @Test
void executesBuild() {
- GradleLauncher launcherMock = context.mock(GradleLauncher.class)
- BuildResult resultMock = context.mock(BuildResult.class)
+ GradleLauncher launcher = Mock()
+ BuildResult resultMock = Mock()
- context.checking {
- one(launcherFactoryMock).newInstance(task.startParameter)
- will(returnValue(launcherMock))
- one(launcherMock).run()
- will(returnValue(resultMock))
- one(resultMock).rethrowFailure()
- }
+ when:
task.build()
+
+ then:
+ 1 * launcherFactory.newInstance(task.startParameter) >> launcher
+ 1 * launcher.run() >> resultMock
+ 1 * resultMock.rethrowFailure()
+ 0 * _._
}
}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/tasks/SyncTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/tasks/SyncTest.groovy
new file mode 100644
index 0000000..818c133
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/api/tasks/SyncTest.groovy
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.tasks
+
+class SyncTest extends AbstractCopyTaskContractTest {
+
+ private Sync task = project.tasks.create(TEST_TASK_NAME, Sync)
+
+ @Override
+ AbstractCopyTask getTask() {
+ task
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/tasks/UploadTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/tasks/UploadTest.groovy
index 8b70973..af4e4cd 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/tasks/UploadTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/tasks/UploadTest.groovy
@@ -16,14 +16,14 @@
package org.gradle.api.tasks
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import spock.lang.Specification
class UploadTest extends Specification {
def "can create task"() {
when:
- HelperUtil.createTask(Upload)
+ TestUtil.createTask(Upload)
then:
noExceptionThrown()
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/tasks/ant/AntTargetTest.java b/subprojects/core/src/test/groovy/org/gradle/api/tasks/ant/AntTargetTest.java
index 124125a..685ccfa 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/tasks/ant/AntTargetTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/api/tasks/ant/AntTargetTest.java
@@ -21,7 +21,7 @@ import org.apache.tools.ant.Target;
import org.gradle.api.Task;
import org.gradle.api.internal.project.DefaultProject;
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider;
-import org.gradle.util.HelperUtil;
+import org.gradle.util.TestUtil;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -36,8 +36,8 @@ import static org.junit.Assert.assertTrue;
public class AntTargetTest {
private final Target antTarget = new Target();
- private final DefaultProject project = HelperUtil.createRootProject();
- private final AntTarget task = HelperUtil.createTask(AntTarget.class, project);
+ private final DefaultProject project = TestUtil.createRootProject();
+ private final AntTarget task = TestUtil.createTask(AntTarget.class, project);
@Rule
public TestNameTestDirectoryProvider testDir = new TestNameTestDirectoryProvider();
private final File baseDir = testDir.getTestDirectory();
@@ -62,8 +62,8 @@ public class AntTargetTest {
@Test
public void dependsOnTargetDependencies() {
- Task a = project.getTasks().add("a");
- Task b = project.getTasks().add("b");
+ Task a = project.getTasks().create("a");
+ Task b = project.getTasks().create("b");
antTarget.setDepends("a, b");
task.setTarget(antTarget);
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/tasks/bundling/TarTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/tasks/bundling/TarTest.groovy
index c65aef8..4934138 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/tasks/bundling/TarTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/tasks/bundling/TarTest.groovy
@@ -16,14 +16,12 @@
package org.gradle.api.tasks.bundling
-import static org.junit.Assert.*
-import static org.hamcrest.Matchers.*
import org.junit.Before
-import org.junit.Test;
+import org.junit.Test
+
+import static org.hamcrest.Matchers.equalTo
+import static org.junit.Assert.assertThat;
-/**
- * @author Hans Dockter
- */
class TarTest extends AbstractArchiveTaskTest {
Tar tar
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/tasks/bundling/ZipTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/tasks/bundling/ZipTest.groovy
index 9ea31f0..e48bfaf 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/tasks/bundling/ZipTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/tasks/bundling/ZipTest.groovy
@@ -18,11 +18,9 @@ package org.gradle.api.tasks.bundling
import org.junit.Before
import org.junit.Test
-import static org.junit.Assert.*
-/**
- * @author Hans Dockter
- */
+import static org.junit.Assert.assertEquals
+
class ZipTest extends AbstractArchiveTaskTest {
Zip zip
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/tasks/util/AbstractTestForPatternSet.groovy b/subprojects/core/src/test/groovy/org/gradle/api/tasks/util/AbstractTestForPatternSet.groovy
index e2480a6..6165667 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/tasks/util/AbstractTestForPatternSet.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/tasks/util/AbstractTestForPatternSet.groovy
@@ -16,15 +16,15 @@
package org.gradle.api.tasks.util
-import static org.junit.Assert.*
-import static org.hamcrest.Matchers.*
-import static org.gradle.util.Matchers.*
import org.junit.Before
import org.junit.Test
-/**
- * @author Hans Dockter
- */
+import static org.gradle.util.Matchers.isEmpty
+import static org.hamcrest.Matchers.equalTo
+import static org.hamcrest.Matchers.sameInstance
+import static org.junit.Assert.assertEquals
+import static org.junit.Assert.assertThat
+
abstract class AbstractTestForPatternSet {
static final String TEST_PATTERN_1 = 'pattern1'
static final String TEST_PATTERN_2 = 'pattern2'
diff --git a/subprojects/core/src/test/groovy/org/gradle/cache/internal/DefaultCacheAccessTest.groovy b/subprojects/core/src/test/groovy/org/gradle/cache/internal/DefaultCacheAccessTest.groovy
index fa4ffc9..b2b4210 100644
--- a/subprojects/core/src/test/groovy/org/gradle/cache/internal/DefaultCacheAccessTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/cache/internal/DefaultCacheAccessTest.groovy
@@ -16,6 +16,7 @@
package org.gradle.cache.internal
import org.gradle.cache.internal.btree.BTreePersistentIndexedCache
+import org.gradle.cache.internal.cacheops.CacheAccessOperationsStack
import org.gradle.internal.Factory
import org.gradle.messaging.serialize.Serializer
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
@@ -28,415 +29,321 @@ class DefaultCacheAccessTest extends Specification {
@Rule final TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider()
final FileLockManager lockManager = Mock()
final File lockFile = tmpDir.file('lock.bin')
- final File targetFile = tmpDir.file('cache.bin')
final FileLock lock = Mock()
+ final CacheAccessOperationsStack operations = Mock()
final BTreePersistentIndexedCache<String, Integer> backingCache = Mock()
- final DefaultCacheAccess manager = new DefaultCacheAccess("<display-name>", lockFile, lockManager) {
- @Override
- def <K, V> BTreePersistentIndexedCache<K, V> doCreateCache(File cacheFile, Serializer<K> keySerializer, Serializer<V> valueSerializer) {
- return backingCache
+ DefaultCacheAccess access = newAccess(operations)
+
+ private DefaultCacheAccess newAccess(CacheAccessOperationsStack operations) {
+ new DefaultCacheAccess("<display-name>", lockFile, lockManager, operations) {
+ @Override
+ def <K, V> BTreePersistentIndexedCache<K, V> doCreateCache(File cacheFile, Serializer<K> keySerializer, Serializer<V> valueSerializer) {
+ return backingCache
+ }
}
}
def "acquires lock on open and releases on close when initial lock mode is not none"() {
when:
- manager.open(Shared)
+ access.open(Shared)
then:
1 * lockManager.lock(lockFile, Shared, "<display-name>") >> lock
+ 1 * lockManager.allowContention(lock, _ as Runnable)
+ 1 * operations.pushCacheAction("Access <display-name>")
0 * _._
+ and:
+ access.owner
+
when:
- manager.close()
+ access.close()
then:
1 * lock.close()
+ 1 * operations.close()
0 * _._
+
+ and:
+ !access.owner
}
- def "does not acquires lock on open when initial lock mode is none"() {
+ def "lock cannot be acquired more than once when initial lock mode is not none"() {
+ lockManager.lock(lockFile, Shared, "<display-name>") >> lock
+
when:
- manager.open(None)
+ access.open(Shared)
+ access.open(Shared)
then:
- 0 * _._
+ thrown(IllegalStateException)
+ }
+ def "does not acquire lock on open when initial lock mode is none"() {
when:
- manager.close()
+ access.open(None)
then:
0 * _._
- }
-
- def "acquires lock at the start of the cache action and releases lock at the end of the cache action when initial lock mode is none"() {
- Factory<String> action = Mock()
-
- given:
- manager.open(None)
when:
- manager.useCache("some operation", action)
+ access.close()
then:
- 1 * lockManager.lock(lockFile, Exclusive, "<display-name>", "some operation") >> lock
-
- and:
- 1 * action.create()
+ 1 * operations.close()
+ 0 * _._
and:
- 1 * lock.close()
- 0 * _._
+ !access.owner
}
- def "does not acquire lock at start of cache action when initial lock mode is exclusive"() {
+ def "using cache pushes an operation and acquires ownership"() {
Factory<String> action = Mock()
- given:
- 1 * lockManager.lock(lockFile, Exclusive, "<display-name>") >> lock
- manager.open(Exclusive)
- def cache = manager.newCache(targetFile, String, Integer)
-
when:
- manager.useCache("some operation", action)
+ access.useCache("some operation", action)
+
+ then:
+ 1 * operations.pushCacheAction("some operation")
+
+ then:
+ 1 * operations.description >> "some operation"
+ 1 * lockManager.lock(lockFile, Exclusive, "<display-name>", "some operation") >> lock
+ 1 * lockManager.allowContention(lock, _ as Runnable)
then:
1 * action.create() >> {
- canAccess cache
+ assert access.owner
}
- _ * lock.readFile(_)
- _ * lock.writeFile(_)
- and:
+ then:
+ 1 * lock.getMode() >> Exclusive
+ 1 * operations.inCacheAction >> false
+ 1 * operations.popCacheAction("some operation")
0 * _._
+
+ and:
+ !access.owner
}
- def "can create cache instance outside of cache action"() {
- given:
- manager.open(None)
+ def "nested use cache operation does not release the ownership"() {
+ Factory<String> action = Mock()
when:
- def cache = manager.newCache(tmpDir.file('cache.bin'), String.class, Integer.class)
+ access.useCache("some operation", action)
then:
- cache instanceof MultiProcessSafePersistentIndexedCache
- 0 * _._
- }
+ 1 * lockManager.lock(lockFile, Exclusive, "<display-name>", _) >> lock
+ 1 * action.create()
+ 1 * operations.inCacheAction >> true
- def "can create cache instance inside of cache action"() {
- def cache
+ then:
+ access.owner
+ }
- given:
- manager.open(None)
+ def "use cache operation reuses existing file lock"() {
+ Factory<String> action = Mock()
when:
- manager.useCache("init", {
- cache = manager.newCache(tmpDir.file('cache.bin'), String.class, Integer.class)
- } as Factory)
+ access.open(Exclusive)
then:
- cache instanceof MultiProcessSafePersistentIndexedCache
+ 1 * lockManager.lock(lockFile, Exclusive, "<display-name>") >> lock
- and:
- 1 * lockManager.lock(lockFile, Exclusive, _, _) >> lock
- }
+ when:
+ access.useCache("some operation", action)
- def "can use cache instance during cache action"() {
- Factory<String> action = Mock()
+ then:
+ 0 * lockManager._
+ 1 * action.create()
+ }
- given:
- manager.open(None)
- def cache = manager.newCache(targetFile, String, Integer)
+ def "use cache operation does not allow shared locks"() {
+ access.open(Shared)
when:
- manager.useCache("some operation", action)
+ access.useCache("some operation", Mock(Factory))
then:
- 1 * action.create() >> {
- canAccess cache
- }
- 1 * lockManager.lock(lockFile, Exclusive, "<display-name>", "some operation") >> lock
- _ * lock.readFile(_)
-
- and:
- _ * lock.writeFile(_)
- 1 * lock.close()
- 0 * _._
+ thrown(UnsupportedOperationException)
}
- def "releases lock before long running operation and reacquires after"() {
- Factory<String> action = Mock()
- Factory<String> longRunningAction = Mock()
-
- given:
- manager.open(None)
- def cache = manager.newCache(targetFile, String, Integer)
-
+ def "long running operation fails early when there is no lock"() {
when:
- manager.useCache("some operation", action)
+ access.longRunningOperation("some operation", Mock(Factory))
then:
- 1 * action.create() >> {
- canAccess cache
- manager.longRunningOperation("nested", longRunningAction)
- canAccess cache
- }
- 1 * longRunningAction.create()
- 2 * lockManager.lock(lockFile, Exclusive, "<display-name>", "some operation") >> lock
- _ * lock.readFile(_)
- _ * lock.writeFile(_)
- 2 * lock.close()
- 0 * _._
+ IllegalStateException e = thrown()
+ e.message == 'Cannot start long running operation, as the <display-name> has not been locked.'
}
- def "releases lock before nested long running operation and reacquires after"() {
+ def "long running operation pushes an operation and releases ownership"() {
+ lock.mode >> Exclusive
Factory<String> action = Mock()
- Factory<String> lockInsideLongRunningOperation = Mock()
- Factory<String> nestedLongRunningAction = Mock()
- Factory<String> deeplyNestedAction = Mock()
- FileLock anotherLock = Mock()
+ when:
+ access.open(Exclusive)
- given:
- manager.open(None)
- def cache = manager.newCache(targetFile, String, Integer)
+ then:
+ 1 * lockManager.lock(lockFile, Exclusive, "<display-name>") >> lock
+ assert access.owner
when:
- manager.useCache("some operation", action)
+ access.longRunningOperation("some operation", action)
+
+ then:
+ 1 * operations.maybeReentrantLongRunningOperation("some operation") >> false
+
+ then:
+ 0 * lock.close()
+ 1 * operations.pushLongRunningOperation("some operation")
then:
1 * action.create() >> {
- canAccess cache
- manager.longRunningOperation("nested", lockInsideLongRunningOperation)
- canAccess cache
- }
- 1 * lockInsideLongRunningOperation.create() >> {
- cannotAccess cache
- manager.useCache("nested operation", nestedLongRunningAction)
- cannotAccess cache
- }
- 1 * nestedLongRunningAction.create() >> {
- canAccess cache
- manager.longRunningOperation("nested-2", deeplyNestedAction)
- canAccess cache
- }
- 1 * deeplyNestedAction.create() >> {
- cannotAccess cache
+ assert !access.owner
}
- 2 * lockManager.lock(lockFile, Exclusive, "<display-name>", "some operation") >> lock
- _ * lock.readFile(_)
- _ * lock.writeFile(_)
- 2 * lock.close()
+ then:
+ 0 * lockManager._
+ 1 * operations.popLongRunningOperation("some operation")
- 2 * lockManager.lock(lockFile, Exclusive, "<display-name>", "nested operation") >> anotherLock
- _ * anotherLock.readFile(_)
- _ * anotherLock.writeFile(_)
- 2 * anotherLock.close()
- 0 * _._
+ then:
+ access.owner
}
- def "cannot run long running operation from outside cache action"() {
- given:
- manager.open(None)
+ def "long running operation closes the lock if contended"() {
+ Factory<String> action = Mock()
when:
- manager.longRunningOperation("operation", Mock(Factory))
+ access.open(Exclusive)
then:
- IllegalStateException e = thrown()
- e.message == 'Cannot start long running operation, as the <display-name> has not been locked.'
- }
+ 1 * lockManager.lock(lockFile, Exclusive, "<display-name>") >> lock
- def "cannot use cache from within long running operation"() {
- Factory<String> action = Mock()
- Factory<String> longRunningAction = Mock()
+ when:
+ access.whenContended().run()
+ access.longRunningOperation("some operation", action)
- given:
- manager.open(None)
- def cache = manager.newCache(targetFile, String, Integer)
+ then:
+ 1 * lock.close()
- when:
- manager.useCache("some operation", action)
+ then:
+ 1 * action.create()
then:
- _ * lockManager.lock(lockFile, Exclusive, "<display-name>", "some operation") >> lock
- 1 * action.create() >> {
- manager.longRunningOperation("nested", longRunningAction)
- }
- 1 * longRunningAction.create() >> {
- cannotAccess cache
- }
+ 1 * lockManager.lock(lockFile, Exclusive, "<display-name>", _)
}
- def "can execute cache action from within long running operation"() {
+ def "long running operation closes the lock if the lock is shared"() {
Factory<String> action = Mock()
- Factory<String> longRunningAction = Mock()
- Factory<String> nestedAction = Mock()
-
- given:
- manager.open(None)
- def cache = manager.newCache(targetFile, String, Integer)
when:
- manager.useCache("some operation", action)
+ access.open(Shared)
then:
- 1 * lockManager.lock(lockFile, Exclusive, "<display-name>", "some operation") >> lock
+ 1 * lockManager.lock(lockFile, Shared, "<display-name>") >> lock
- and:
- 1 * action.create() >> {
- canAccess cache
- manager.longRunningOperation("nested", longRunningAction)
- canAccess cache
- }
+ when:
+ access.longRunningOperation("some operation", action)
- and:
+ then:
+ 1 * lock.mode >> Shared
1 * lock.close()
- and:
- 1 * longRunningAction.create() >> {
- cannotAccess cache
- manager.useCache("nested 2", nestedAction)
- cannotAccess cache
- }
-
- and:
- 1 * lockManager.lock(lockFile, Exclusive, "<display-name>", "nested 2") >> lock
-
- and:
- 1 * nestedAction.create() >> {
- canAccess cache
- }
+ then:
+ 1 * action.create()
- and:
- 1 * lockManager.lock(lockFile, Exclusive, "<display-name>", "some operation") >> lock
- _ * lock.readFile(_)
- _ * lock.writeFile(_)
- 2 * lock.close()
- 0 * _._
+ then:
+ 1 * lockManager.lock(lockFile, Exclusive, "<display-name>", _)
}
- def "can execute long running operation from within long running operation"() {
+ def "reentrant long running operation does not involve locking"() {
Factory<String> action = Mock()
- Factory<String> longRunningAction = Mock()
- Factory<String> nestedAction = Mock()
-
- given:
- manager.open(None)
- def cache = manager.newCache(targetFile, String, Integer)
when:
- manager.useCache("some operation", action)
+ access.longRunningOperation("some operation", action)
then:
- 1 * action.create() >> {
- canAccess cache
- manager.longRunningOperation("nested", longRunningAction)
- canAccess cache
- }
- 1 * longRunningAction.create() >> {
- cannotAccess cache
- manager.longRunningOperation("nested 2", nestedAction)
- cannotAccess cache
- }
- 1 * nestedAction.create() >> {
- cannotAccess cache
- }
- 2 * lockManager.lock(lockFile, Exclusive, "<display-name>", "some operation") >> lock
- _ * lock.readFile(_)
- _ * lock.writeFile(_)
- 2 * lock.close()
- 0 * _._
+ 1 * operations.maybeReentrantLongRunningOperation("some operation") >> true
+
+ then:
+ 1 * action.create()
+
+ then:
+ 1 * operations.popLongRunningOperation("some operation")
+ 0 * lock._
+ 0 * lockManager._
}
- def "can execute cache action from within cache action"() {
- Factory<String> action = Mock()
- Factory<String> nestedAction = Mock()
+ def "can create new cache"() {
+ when:
+ def cache = access.newCache(tmpDir.file('cache.bin'), String.class, Integer.class)
- given:
- manager.open(None)
- def cache = manager.newCache(targetFile, String, Integer)
+ then:
+ cache instanceof MultiProcessSafePersistentIndexedCache
+ 0 * _._
+ }
+ def "contended action does nothing when no lock"() {
when:
- manager.useCache("some operation", action)
+ access.whenContended().run()
then:
- 1 * action.create() >> {
- canAccess cache
- manager.useCache("nested", nestedAction)
- canAccess cache
- }
- 1 * nestedAction.create() >> {
- canAccess cache
- }
- 1 * lockManager.lock(lockFile, Exclusive, "<display-name>", "some operation") >> lock
- _ * lock.readFile(_)
- _ * lock.writeFile(_)
- 1 * lock.close()
0 * _._
}
- def "closes caches at the end of the cache action when initial lock mode is none"() {
+ def "contended action safely closes the lock when cache is not busy"() {
Factory<String> action = Mock()
- given:
- manager.open(None)
- def cache = manager.newCache(targetFile, String, Integer)
-
when:
- manager.useCache("some operation", action)
+ access.open(Exclusive)
+ access.longRunningOperation("some operation", action)
then:
- 1 * action.create() >> {
- canAccess cache
+ 1 * lockManager.lock(lockFile, Exclusive, "<display-name>") >> lock
+ action.create() >> {
+ access.whenContended().run()
}
- 1 * lockManager.lock(lockFile, Exclusive, "<display-name>", "some operation") >> lock
- _ * lock.readFile(_)
and:
- _ * lock.writeFile(_) >> {Runnable runnable -> runnable.run()}
- 1 * backingCache.close()
+ 1 * operations.pushCacheAction('Other process requested access to <display-name>')
1 * lock.close()
- 0 * _._
+ 1 * operations.popCacheAction('Other process requested access to <display-name>')
}
- def "closes caches on close when initial lock mode is not none"() {
- given:
- 1 * lockManager.lock(lockFile, Exclusive, "<display-name>") >> lock
- _ * lock.readFile(_) >> {Factory factory -> factory.create()}
- _ * lock.writeFile(_) >> {Runnable runnable -> runnable.run()}
-
- and:
- manager.open(Exclusive)
- def cache = manager.newCache(targetFile, String, Integer)
- cache.get("key")
+ def "file access requires acquired lock"() {
+ def runnable = Mock(Runnable)
when:
- manager.close()
+ access.open(None)
+ access.fileAccess.updateFile(runnable)
then:
- _ * lock.readFile(_) >> {Factory factory -> factory.create()}
- _ * lock.writeFile(_) >> {Runnable runnable -> runnable.run()}
- 1 * backingCache.close()
- 1 * lock.close()
- 0 * _._
+ thrown(IllegalStateException)
}
- def canAccess(def cache) {
- try {
- cache.get("key")
- } catch (IllegalStateException e) {
- assert false: "Should be able to access cache here"
- }
- }
+ def "file access is available when lock is acquired"() {
+ def runnable = Mock(Runnable)
- def cannotAccess(def cache) {
- try {
- cache.get("key")
- assert false: "Should not be able to access cache here"
- } catch (IllegalStateException e) {
- assert e.message == 'The <display-name> has not been locked.'
- }
+ when:
+ access.open(Exclusive)
+ access.fileAccess.updateFile(runnable)
+
+ then:
+ 1 * lockManager.lock(lockFile, Exclusive, "<display-name>") >> lock
+ 1 * lock.updateFile(runnable)
}
-}
+ def "file access can be accessed when there is no owner"() {
+ def runnable = Mock(Runnable)
+
+ when:
+ access.open(None)
+ access.useCache("use cache", {} as Runnable) //acquires file lock but releases the thread lock
+ access.fileAccess.updateFile(runnable)
+
+ then:
+ 1 * lockManager.lock(lockFile, Exclusive, "<display-name>", _) >> lock
+ 1 * lock.updateFile(runnable)
+ }
+}
\ No newline at end of file
diff --git a/subprojects/core/src/test/groovy/org/gradle/cache/internal/DefaultCacheFactoryTest.groovy b/subprojects/core/src/test/groovy/org/gradle/cache/internal/DefaultCacheFactoryTest.groovy
index 3de6d72..29a8572 100755
--- a/subprojects/core/src/test/groovy/org/gradle/cache/internal/DefaultCacheFactoryTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/cache/internal/DefaultCacheFactoryTest.groovy
@@ -18,6 +18,7 @@ package org.gradle.cache.internal
import org.gradle.CacheUsage
import org.gradle.api.Action
import org.gradle.cache.CacheValidator
+import org.gradle.cache.internal.locklistener.NoOpFileLockContentionHandler
import org.gradle.messaging.serialize.DefaultSerializer
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
import org.junit.Rule
@@ -29,7 +30,7 @@ class DefaultCacheFactoryTest extends Specification {
final Action<?> opened = Mock()
final Action<?> closed = Mock()
final ProcessMetaDataProvider metaDataProvider = Mock()
- private final DefaultCacheFactory factoryFactory = new DefaultCacheFactory(new DefaultFileLockManager(metaDataProvider)) {
+ private final DefaultCacheFactory factoryFactory = new DefaultCacheFactory(new DefaultFileLockManager(metaDataProvider, new NoOpFileLockContentionHandler())) {
@Override
void onOpen(Object cache) {
opened.execute(cache)
diff --git a/subprojects/core/src/test/groovy/org/gradle/cache/internal/DefaultFileLockManagerTest.groovy b/subprojects/core/src/test/groovy/org/gradle/cache/internal/DefaultFileLockManagerTest.groovy
index f43bc06..d841feb 100644
--- a/subprojects/core/src/test/groovy/org/gradle/cache/internal/DefaultFileLockManagerTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/cache/internal/DefaultFileLockManagerTest.groovy
@@ -18,7 +18,9 @@ package org.gradle.cache.internal
import org.apache.commons.lang.RandomStringUtils
import org.gradle.cache.internal.FileLockManager.LockMode
+import org.gradle.cache.internal.locklistener.NoOpFileLockContentionHandler
import org.gradle.internal.Factory
+import org.gradle.internal.id.IdGenerator
import org.gradle.test.fixtures.file.TestFile
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
import org.gradle.util.Requires
@@ -30,13 +32,12 @@ import spock.lang.Unroll
import static org.gradle.cache.internal.FileLockManager.LockMode.Exclusive
import static org.gradle.cache.internal.FileLockManager.LockMode.Shared
-/**
- * @author: Szczepan Faber, created at: 8/30/11
- */
class DefaultFileLockManagerTest extends Specification {
@Rule TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider()
def metaDataProvider = Mock(ProcessMetaDataProvider)
- FileLockManager manager = new DefaultFileLockManager(metaDataProvider)
+ def generator = Stub(IdGenerator)
+
+ FileLockManager manager = new DefaultFileLockManager(metaDataProvider, 5000, new NoOpFileLockContentionHandler(), generator)
TestFile testFile
TestFile testFileLock
@@ -51,6 +52,7 @@ class DefaultFileLockManagerTest extends Specification {
metaDataProvider.processIdentifier >> '123'
metaDataProvider.processDisplayName >> 'process'
+ generator.generateId() >> 678L
}
@Unroll
@@ -396,7 +398,7 @@ class DefaultFileLockManagerTest extends Specification {
def customMetaDataProvider = Mock(ProcessMetaDataProvider)
def processIdentifier = RandomStringUtils.randomAlphanumeric(1000)
1 * customMetaDataProvider.processIdentifier >> processIdentifier
- def customManager = new DefaultFileLockManager(customMetaDataProvider)
+ def customManager = new DefaultFileLockManager(customMetaDataProvider, 5000, new NoOpFileLockContentionHandler(), generator)
def operationalDisplayName = RandomStringUtils.randomAlphanumeric(1000)
when:
@@ -453,7 +455,9 @@ class DefaultFileLockManagerTest extends Specification {
lockFile.withDataInputStream { str ->
assert str.readByte() == 1
assert !str.readBoolean()
- assert str.readByte() == 2
+ assert str.readByte() == 3
+ assert str.readInt() == -1
+ assert str.readLong() == 678L
assert str.readUTF() == processIdentifier
assert str.readUTF() == operationalName
assert str.read() < 0
diff --git a/subprojects/core/src/test/groovy/org/gradle/cache/internal/DefaultPersistentDirectoryCacheTest.java b/subprojects/core/src/test/groovy/org/gradle/cache/internal/DefaultPersistentDirectoryCacheTest.java
index fff1a16..268abc5 100644
--- a/subprojects/core/src/test/groovy/org/gradle/cache/internal/DefaultPersistentDirectoryCacheTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/cache/internal/DefaultPersistentDirectoryCacheTest.java
@@ -20,6 +20,7 @@ import org.gradle.api.Action;
import org.gradle.cache.CacheOpenException;
import org.gradle.cache.CacheValidator;
import org.gradle.cache.PersistentCache;
+import org.gradle.cache.internal.locklistener.NoOpFileLockContentionHandler;
import org.gradle.test.fixtures.file.TestFile;
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider;
import org.gradle.util.GUtil;
@@ -47,7 +48,7 @@ public class DefaultPersistentDirectoryCacheTest {
public final TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider();
private final JUnit4Mockery context = new JUnit4GroovyMockery();
private final ProcessMetaDataProvider metaDataProvider = context.mock(ProcessMetaDataProvider.class);
- private final FileLockManager lockManager = new DefaultFileLockManager(metaDataProvider);
+ private final FileLockManager lockManager = new DefaultFileLockManager(metaDataProvider, new NoOpFileLockContentionHandler());
private final Action<PersistentCache> action = context.mock(Action.class);
private final CacheValidator validator = context.mock(CacheValidator.class);
private final Map<String, String> properties = GUtil.map("prop", "value", "prop2", "other-value");
diff --git a/subprojects/core/src/test/groovy/org/gradle/cache/internal/FileLockCommunicatorTest.groovy b/subprojects/core/src/test/groovy/org/gradle/cache/internal/FileLockCommunicatorTest.groovy
new file mode 100644
index 0000000..4cc108c
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/cache/internal/FileLockCommunicatorTest.groovy
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.cache.internal
+
+import org.gradle.messaging.remote.internal.inet.InetAddressFactory
+import org.gradle.util.ConcurrentSpecification
+
+import static org.gradle.test.fixtures.ConcurrentTestUtil.poll
+
+class FileLockCommunicatorTest extends ConcurrentSpecification {
+
+ def communicator = new FileLockCommunicator(new InetAddressFactory())
+ Long receivedId
+
+ def cleanup() {
+ communicator.stop()
+ }
+
+ def "knows port"() {
+ expect:
+ communicator.getPort() != -1
+ }
+
+ def "knows port after stopping"() {
+ when:
+ communicator.stop()
+
+ then:
+ communicator.getPort() == -1
+ }
+
+ def "can receive lock id"() {
+ start {
+ receivedId = communicator.receive()
+ }
+
+ poll {
+ assert communicator.getPort() != -1 && receivedId == null
+ }
+
+ when:
+ communicator.pingOwner(communicator.getPort(), 155, "lock")
+
+ then:
+ poll {
+ assert receivedId == 155
+ }
+ }
+
+ def "may not receive after the stop"() {
+ communicator.stop()
+ when:
+ communicator.receive()
+ then:
+ thrown(GracefullyStoppedException)
+ }
+
+ def "pinging on a port that nobody listens is safe"() {
+ when:
+ communicator.pingOwner(6666, 166, "lock")
+
+ then:
+ noExceptionThrown()
+ }
+
+ def "can be stopped"() {
+ expect:
+ communicator.stop()
+ }
+
+ def "can be stopped during receive"() {
+ start {
+ try {
+ communicator.receive()
+ } catch (GracefullyStoppedException e) {}
+ }
+
+ when:
+ communicator.stop()
+
+ then:
+ finished()
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/cache/internal/cacheops/CacheAccessOperationsStackTest.groovy b/subprojects/core/src/test/groovy/org/gradle/cache/internal/cacheops/CacheAccessOperationsStackTest.groovy
new file mode 100644
index 0000000..eea7bc3
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/cache/internal/cacheops/CacheAccessOperationsStackTest.groovy
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.cache.internal.cacheops
+
+import org.gradle.util.ConcurrentSpecification
+
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.TimeUnit
+
+class CacheAccessOperationsStackTest extends ConcurrentSpecification {
+
+ def stack = new CacheAccessOperationsStack()
+
+ def "maintains operations per thread"() {
+ expect:
+ start {
+ assert !stack.isInCacheAction()
+ stack.pushCacheAction("foo1")
+ stack.pushCacheAction("foo2")
+ assert stack.description == "foo2"
+ }
+ start {
+ assert !stack.isInCacheAction()
+ stack.pushCacheAction("bar1")
+ stack.pushCacheAction("bar2")
+ assert stack.description == "bar2"
+ }
+ }
+
+ def "cannot access operations from a different thread"() {
+ expect:
+ start {
+ stack.pushCacheAction("foo")
+ }
+ finished()
+
+ when:
+ start {
+ stack.popCacheAction("foo")
+ }
+ finished()
+
+ then:
+ thrown(IllegalStateException)
+ }
+
+ def "manages reentrant long running operations"() {
+ expect:
+ start {
+ assert !stack.maybeReentrantLongRunningOperation("long")
+ }
+ finished()
+ start {
+ assert !stack.maybeReentrantLongRunningOperation("long")
+ stack.pushLongRunningOperation("long")
+ }
+ finished()
+ start {
+ assert stack.maybeReentrantLongRunningOperation("long2")
+ assert stack.description == "long2"
+ }
+ }
+
+ def "when all long running operations complete the next operation is no longer reentrant"() {
+ when:
+ stack.pushLongRunningOperation("foo")
+ stack.pushLongRunningOperation("foo2")
+
+ then:
+ stack.maybeReentrantLongRunningOperation("foo3")
+
+ when:
+ stack.popLongRunningOperation("foo3")
+ stack.popLongRunningOperation("foo2")
+ stack.popLongRunningOperation("foo")
+
+ then:
+ !stack.maybeReentrantLongRunningOperation("hey")
+ }
+
+ def "if any thread is in cache the next long running operation is not reentrant"() {
+ when:
+ stack.pushLongRunningOperation("long")
+ start { stack.pushCacheAction("cache") }
+ finished()
+
+ then:
+ !stack.maybeReentrantLongRunningOperation("long2")
+ }
+
+ def "long running operation is reentrant if previous long running operation belongs to a different thread"() {
+ when:
+ start {
+ stack.pushLongRunningOperation("a")
+ }
+ finished()
+ then:
+ stack.maybeReentrantLongRunningOperation("b")
+ }
+
+ def "long running operations in separate threads can interleave"() {
+ when:
+ //Here's the scenario:
+ //Thread 1: pushes a
+ //Thread 2: pushes b
+ //Thread 1: pops a
+ //Thread 2: pops b
+
+ def latch1 = new CountDownLatch(1)
+ def latch2 = new CountDownLatch(1)
+ start {
+ stack.pushLongRunningOperation("a")
+ latch1.await(1, TimeUnit.SECONDS)
+ stack.popLongRunningOperation("a")
+ latch2.countDown()
+ }
+ start {
+ stack.pushLongRunningOperation("b")
+ latch1.countDown()
+ latch2.await(1, TimeUnit.SECONDS)
+ stack.popLongRunningOperation("b")
+ }
+ finished()
+
+ then:
+ noExceptionThrown()
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/cache/internal/cacheops/CacheOperationStackTest.groovy b/subprojects/core/src/test/groovy/org/gradle/cache/internal/cacheops/CacheOperationStackTest.groovy
new file mode 100644
index 0000000..7011814
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/cache/internal/cacheops/CacheOperationStackTest.groovy
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.cache.internal.cacheops
+
+import spock.lang.Specification
+
+class CacheOperationStackTest extends Specification {
+
+ def stack = new CacheOperationStack()
+
+ def "provides no description initially"() {
+ when:
+ stack.description
+ then:
+ thrown(IllegalStateException)
+ }
+
+ def "manages long running operations"() {
+ when:
+ stack.pushLongRunningOperation("long")
+ then:
+ stack.description == "long"
+
+ when:
+ stack.pushLongRunningOperation("long2")
+ then:
+ stack.description == "long2"
+
+ when:
+ stack.popLongRunningOperation("long2")
+ then:
+ stack.description == "long"
+
+ when:
+ stack.popLongRunningOperation("long")
+ and:
+ stack.description
+ then:
+ thrown(IllegalStateException)
+ }
+
+ def "manages cache actions"() {
+ when:
+ stack.pushCacheAction("foo")
+ then:
+ stack.description == "foo"
+
+ when:
+ stack.pushCacheAction("foo2")
+ then:
+ stack.description == "foo2"
+
+ when:
+ stack.popCacheAction("foo2")
+ then:
+ stack.description == "foo"
+
+ when:
+ stack.popCacheAction("foo")
+ and:
+ stack.description
+ then:
+ thrown(IllegalStateException)
+ }
+
+ def "prevents popping latest operation if the name does not match"() {
+ stack.pushCacheAction("foo")
+
+ when:
+ stack.popCacheAction("foo2")
+ then:
+ thrown(IllegalStateException)
+ }
+
+ def "prevents popping latest operation if the kind does not match"() {
+ stack.pushCacheAction("foo")
+
+ when:
+ stack.popLongRunningOperation("foo")
+ then:
+ thrown(IllegalStateException)
+ }
+
+ def "knows the kind of current cache operation"() {
+ assert !stack.isInCacheAction()
+
+ when:
+ stack.pushLongRunningOperation("long")
+ then:
+ !stack.inCacheAction
+ stack.inLongRunningOperation
+
+ when:
+ stack.pushCacheAction("cache")
+ then:
+ stack.inCacheAction
+ !stack.inLongRunningOperation
+
+ when:
+ stack.pushCacheAction("cache2")
+ then:
+ stack.inCacheAction
+ !stack.inLongRunningOperation
+
+ when:
+ stack.popCacheAction("cache2")
+ stack.popCacheAction("cache")
+ then:
+ !stack.inCacheAction
+ stack.inLongRunningOperation
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/cache/internal/locklistener/DefaultFileLockContentionHandlerTest.groovy b/subprojects/core/src/test/groovy/org/gradle/cache/internal/locklistener/DefaultFileLockContentionHandlerTest.groovy
new file mode 100644
index 0000000..3440b77
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/cache/internal/locklistener/DefaultFileLockContentionHandlerTest.groovy
@@ -0,0 +1,185 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.cache.internal.locklistener
+
+import org.gradle.internal.concurrent.ExecutorFactory
+import org.gradle.internal.concurrent.StoppableExecutor
+import org.gradle.messaging.remote.internal.inet.InetAddressFactory
+import org.gradle.util.ConcurrentSpecification
+
+import java.util.concurrent.atomic.AtomicBoolean
+
+import static org.gradle.test.fixtures.ConcurrentTestUtil.poll
+
+class DefaultFileLockContentionHandlerTest extends ConcurrentSpecification {
+ def addressFactory = new InetAddressFactory()
+ def handler = new DefaultFileLockContentionHandler(executorFactory, addressFactory)
+ def client = new DefaultFileLockContentionHandler(executorFactory, addressFactory)
+
+ def cleanup() {
+ handler?.stop()
+ client?.stop()
+ }
+
+ def "manages contention for multiple locks"() {
+ def action1 = new AtomicBoolean()
+ def action2 = new AtomicBoolean()
+
+ when:
+ int port = handler.reservePort()
+ handler.start(10, { action1.set(true) })
+ handler.start(11, { action2.set(true) })
+
+ client.pingOwner(port, 10, "lock 1")
+ client.pingOwner(port, 11, "lock 2")
+
+ then:
+ poll {
+ assert action1.get() && action2.get()
+ }
+ }
+
+ def "there is only one executor thread"() {
+ def factory = Mock(ExecutorFactory)
+ handler = new DefaultFileLockContentionHandler(factory, addressFactory)
+
+ when:
+ handler.reservePort()
+ handler.start(10, {} as Runnable)
+ handler.start(11, {} as Runnable)
+
+ then:
+ 1 * factory.create(_ as String) >> Mock(StoppableExecutor)
+ 0 * factory._
+ }
+
+ def "cannot start contention handling when the handler was stopped"() {
+ handler.stop()
+
+ when:
+ handler.start(10, {} as Runnable)
+
+ then:
+ thrown(IllegalStateException)
+ }
+
+ def "cannot start contention handling when the handler was not initialized"() {
+ when:
+ handler.start(10, {} as Runnable)
+
+ then:
+ thrown(IllegalStateException)
+ }
+
+ def "handler can be closed and contended action does not run"() {
+ when:
+ int port = handler.reservePort();
+ handler.start(10, { throw new RuntimeException("Boo!") } as Runnable)
+ handler.stop()
+
+ client.pingOwner(port, 10, "lock 1")
+
+ then:
+ noExceptionThrown()
+ }
+
+ def "can receive request for lock that is already closed"() {
+ when:
+ int port = handler.reservePort()
+ handler.start(10, { assert false } as Runnable)
+ sleep(300) //so that it starts receiving
+
+ //close the lock
+ handler.stop(10)
+
+ //receive request for lock that is already closed
+ client.pingOwner(port, 10, "lock 1")
+
+ then:
+ canHandleMoreRequests()
+ }
+
+ private void canHandleMoreRequests() {
+ def executed = new AtomicBoolean()
+ int port = handler.reservePort();
+ handler.start(15, { executed.set(true) } as Runnable)
+ client.pingOwner(port, 15, "lock")
+ poll { assert executed.get() }
+ }
+
+ def "reserving port is safely reentrant"() {
+ when:
+ int port = handler.reservePort()
+
+ then:
+ handler.reservePort() == port
+ }
+
+ def "cannot reserve port when the handler was stopped"() {
+ handler.stop()
+
+ when:
+ handler.reservePort()
+
+ then:
+ thrown(IllegalStateException)
+ }
+
+ def "reserving port does not start the thread"() {
+ def factory = Mock(ExecutorFactory)
+ handler = new DefaultFileLockContentionHandler(factory, addressFactory)
+
+ when:
+ handler.reservePort()
+
+ then:
+ 0 * factory._
+ }
+
+ def "stopping the handler stops the executor"() {
+ def factory = Mock(ExecutorFactory)
+ def executor = Mock(StoppableExecutor)
+ handler = new DefaultFileLockContentionHandler(factory, addressFactory)
+
+ when:
+ handler.reservePort()
+ handler.start(10, {} as Runnable)
+ handler.stop()
+
+ then:
+ 1 * factory.create(_ as String) >> executor
+ 1 * executor.stop()
+ }
+
+ def "stopping is safe even if the handler was not initialized"() {
+ when:
+ handler.stop()
+
+ then:
+ noExceptionThrown()
+ }
+
+ def "stopping is safe even if the executor was not initialized"() {
+ handler.reservePort()
+
+ when:
+ handler.stop()
+
+ then:
+ noExceptionThrown()
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/configuration/BuildScriptProcessorTest.java b/subprojects/core/src/test/groovy/org/gradle/configuration/BuildScriptProcessorTest.java
deleted file mode 100644
index 60ae726..0000000
--- a/subprojects/core/src/test/groovy/org/gradle/configuration/BuildScriptProcessorTest.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.configuration;
-
-import org.gradle.api.internal.project.ProjectInternal;
-import org.gradle.api.internal.project.ProjectStateInternal;
-import org.gradle.groovy.scripts.ScriptSource;
-import org.gradle.util.JUnit4GroovyMockery;
-import org.jmock.Expectations;
-import org.jmock.integration.junit4.JMock;
-import org.jmock.integration.junit4.JUnit4Mockery;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
- at RunWith(JMock.class)
-public class BuildScriptProcessorTest {
- private final JUnit4Mockery context = new JUnit4GroovyMockery();
- private final ProjectInternal project = context.mock(ProjectInternal.class);
- private final ScriptSource scriptSource = context.mock(ScriptSource.class);
- private final ScriptPluginFactory configurerFactory = context.mock(ScriptPluginFactory.class);
- private final ScriptPlugin scriptPlugin = context.mock(ScriptPlugin.class);
- private final ProjectStateInternal state = context.mock(ProjectStateInternal.class);
- private final BuildScriptProcessor evaluator = new BuildScriptProcessor(configurerFactory);
-
- @Before
- public void setUp() {
- context.checking(new Expectations() {{
- allowing(project).getBuildScriptSource();
- will(returnValue(scriptSource));
- ignoring(scriptSource);
- }});
- }
-
- @Test
- public void configuresProjectUsingBuildScript() {
- context.checking(new Expectations() {{
- one(configurerFactory).create(scriptSource);
- will(returnValue(scriptPlugin));
-
- one(scriptPlugin).apply(project);
- }});
-
- evaluator.evaluate(project, state);
- }
-}
\ No newline at end of file
diff --git a/subprojects/core/src/test/groovy/org/gradle/configuration/DefaultBuildConfigurerTest.groovy b/subprojects/core/src/test/groovy/org/gradle/configuration/DefaultBuildConfigurerTest.groovy
index 347c903..7a7b531 100644
--- a/subprojects/core/src/test/groovy/org/gradle/configuration/DefaultBuildConfigurerTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/configuration/DefaultBuildConfigurerTest.groovy
@@ -32,16 +32,19 @@ class DefaultBuildConfigurerTest extends Specification {
}
def "configures build for standard mode"() {
+ def child1 = Mock(ProjectInternal)
+ def child2 = Mock(ProjectInternal)
+
+ given:
+ _ * rootProject.allprojects >> [rootProject, child1, child2]
+
when:
configurer.configure(gradle)
then:
- 1 * gradle.addProjectEvaluationListener(_ as ImplicitTasksConfigurer);
- 1 * gradle.addProjectEvaluationListener(_ as ProjectDependencies2TaskResolver);
- 1 * rootProject.allprojects(!null) >> { args ->
- assert args[0] instanceof DefaultBuildConfigurer.ConfigureProject
- }
- 0 * rootProject._
+ 1 * rootProject.evaluate()
+ 1 * child1.evaluate()
+ 1 * child2.evaluate()
}
def "configures build for on demand mode"() {
@@ -49,12 +52,8 @@ class DefaultBuildConfigurerTest extends Specification {
configurer.configure(gradle)
then:
- 1 * startParameter.isConfigureOnDemand() >> true
+ startParameter.isConfigureOnDemand() >> true
1 * rootProject.evaluate()
0 * rootProject._
-
- and:
- 1 * gradle.addProjectEvaluationListener(_ as ImplicitTasksConfigurer);
- 1 * gradle.addProjectEvaluationListener(_ as ProjectDependencies2TaskResolver);
}
}
diff --git a/subprojects/core/src/test/groovy/org/gradle/configuration/DefaultScriptPluginFactoryTest.java b/subprojects/core/src/test/groovy/org/gradle/configuration/DefaultScriptPluginFactoryTest.java
index 556878e..bf55c84 100755
--- a/subprojects/core/src/test/groovy/org/gradle/configuration/DefaultScriptPluginFactoryTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/configuration/DefaultScriptPluginFactoryTest.java
@@ -15,12 +15,13 @@
*/
package org.gradle.configuration;
-import org.gradle.internal.Factory;
-import org.gradle.internal.service.ServiceRegistry;
-import org.gradle.groovy.scripts.internal.ClasspathScriptTransformer;
import org.gradle.api.internal.initialization.ScriptHandlerFactory;
import org.gradle.api.internal.initialization.ScriptHandlerInternal;
import org.gradle.groovy.scripts.*;
+import org.gradle.groovy.scripts.internal.ClasspathScriptTransformer;
+import org.gradle.internal.Factory;
+import org.gradle.internal.reflect.Instantiator;
+import org.gradle.internal.service.ServiceRegistry;
import org.gradle.logging.LoggingManagerInternal;
import org.jmock.Expectations;
import org.jmock.Sequence;
@@ -33,7 +34,8 @@ import org.junit.runner.RunWith;
import java.net.URL;
import java.net.URLClassLoader;
-import static org.hamcrest.Matchers.*;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.hamcrest.Matchers.sameInstance;
@RunWith(JMock.class)
public class DefaultScriptPluginFactoryTest {
@@ -46,6 +48,7 @@ public class DefaultScriptPluginFactoryTest {
private final ScriptSource scriptSourceMock = context.mock(ScriptSource.class);
private final ScriptRunner scriptRunnerMock = context.mock(ScriptRunner.class, "scriptRunner");
private final BasicScript scriptMock = context.mock(BasicScript.class);
+ private final Instantiator instantiatorMock = context.mock(Instantiator.class);
private final URLClassLoader parentClassLoader = new URLClassLoader(new URL[0]);
private final URLClassLoader scriptClassLoader = new URLClassLoader(new URL[0]);
private final ScriptHandlerFactory scriptHandlerFactoryMock = context.mock(ScriptHandlerFactory.class);
@@ -53,7 +56,7 @@ public class DefaultScriptPluginFactoryTest {
private final ScriptRunner classPathScriptRunnerMock = context.mock(ScriptRunner.class, "classpathScriptRunner");
private final BasicScript classPathScriptMock = context.mock(BasicScript.class, "classpathScript");
private final Factory<LoggingManagerInternal> loggingManagerFactoryMock = context.mock(Factory.class);
- private final DefaultScriptPluginFactory factory = new DefaultScriptPluginFactory(scriptCompilerFactoryMock, importsReaderMock, scriptHandlerFactoryMock, parentClassLoader, loggingManagerFactoryMock);
+ private final DefaultScriptPluginFactory factory = new DefaultScriptPluginFactory(scriptCompilerFactoryMock, importsReaderMock, scriptHandlerFactoryMock, parentClassLoader, loggingManagerFactoryMock, instantiatorMock);
@Test
public void configuresATargetObjectUsingScript() {
diff --git a/subprojects/core/src/test/groovy/org/gradle/configuration/ImplicitTasksConfigurerTest.groovy b/subprojects/core/src/test/groovy/org/gradle/configuration/ImplicitTasksConfigurerTest.groovy
deleted file mode 100644
index ecbeebe..0000000
--- a/subprojects/core/src/test/groovy/org/gradle/configuration/ImplicitTasksConfigurerTest.groovy
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.configuration
-
-import org.gradle.api.internal.project.ProjectInternal
-import org.gradle.util.HelperUtil
-import spock.lang.Specification
-
-class ImplicitTasksConfigurerTest extends Specification {
- private final ImplicitTasksConfigurer configurer = new ImplicitTasksConfigurer()
- private final ProjectInternal project = HelperUtil.createRootProject()
-
- def "applies help tasks after evaluate"() {
- when:
- configurer.afterEvaluate(project, null)
-
- then:
- project.plugins.hasPlugin('help-tasks')
- }
-}
diff --git a/subprojects/core/src/test/groovy/org/gradle/configuration/ImportsReaderTest.groovy b/subprojects/core/src/test/groovy/org/gradle/configuration/ImportsReaderTest.groovy
index 7ca7732..e75959a 100644
--- a/subprojects/core/src/test/groovy/org/gradle/configuration/ImportsReaderTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/configuration/ImportsReaderTest.groovy
@@ -19,27 +19,26 @@ package org.gradle.configuration
import org.gradle.groovy.scripts.ScriptSource
import org.gradle.util.Resources
import org.junit.Rule
-import org.junit.Test
-import static org.hamcrest.Matchers.*
-import static org.junit.Assert.*
+import spock.lang.Specification
-/**
- * @author Hans Dockter
- */
-class ImportsReaderTest {
+class ImportsReaderTest extends Specification {
@Rule public Resources resources = new Resources()
- ImportsReader testObj = new ImportsReader()
+ ImportsReader reader = new ImportsReader()
- @Test public void testReadImportsFromResource() {
- String result = testObj.getImports()
- assertEquals(resources.getResource('default-imports.txt').text, result)
+ public void testReadImportsFromResource() {
+ expect:
+ reader.imports.contains('import org.gradle.api.*')
}
- @Test public void testCreatesScriptSource() {
- ScriptSource source = [:] as ScriptSource
- ScriptSource importsSource = testObj.withImports(source)
- assertThat(importsSource, instanceOf(ImportsScriptSource.class))
- assertThat(importsSource.source, sameInstance(source))
- assertThat(importsSource.importsReader, sameInstance(testObj))
+ public void testCreatesScriptSource() {
+ def source = [:] as ScriptSource
+
+ when:
+ def importsSource = reader.withImports(source)
+
+ then:
+ importsSource instanceof ImportsScriptSource
+ importsSource.source == source
+ importsSource.importsReader == reader
}
}
diff --git a/subprojects/core/src/test/groovy/org/gradle/configuration/LifecycleProjectEvaluatorTest.groovy b/subprojects/core/src/test/groovy/org/gradle/configuration/LifecycleProjectEvaluatorTest.groovy
deleted file mode 100644
index fbc6c84..0000000
--- a/subprojects/core/src/test/groovy/org/gradle/configuration/LifecycleProjectEvaluatorTest.groovy
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.configuration
-
-import org.gradle.api.ProjectEvaluationListener
-import org.gradle.api.internal.project.ProjectInternal
-import org.gradle.api.internal.project.ProjectStateInternal
-import spock.lang.Specification
-
-public class LifecycleProjectEvaluatorTest extends Specification {
- private project = Mock(ProjectInternal)
- private listener = Mock(ProjectEvaluationListener)
- private delegate = Mock(ProjectEvaluator)
- private state = Mock(ProjectStateInternal)
- private evaluator = new LifecycleProjectEvaluator(delegate)
-
- void setup() {
- project.getProjectEvaluationBroadcaster() >> listener
- }
-
- void "nothing happens if project was already configured"() {
- state.executed >> true
-
- when:
- evaluator.evaluate(project, state)
-
- then:
- 0 * delegate._
- }
-
- void "nothing happens if project is being configured now"() {
- state.executing >> true
-
- when:
- evaluator.evaluate(project, state)
-
- then:
- 0 * delegate._
- }
-
- void "evaluates the project firing all necessary listeners and updating the state"() {
- when:
- evaluator.evaluate(project, state)
-
- then:
- 1 * listener.beforeEvaluate(project)
- 1 * state.setExecuting(true)
-
- then:
- 1 * delegate.evaluate(project, state)
-
- then:
- 1 * state.setExecuting(false)
- 1 * state.executed()
- 1 * listener.afterEvaluate(project, state)
- }
-
- void "notifies listeners and updates states even if there was evaluation failure"() {
- def failure = new RuntimeException()
-
- when:
- evaluator.evaluate(project, state)
-
- then:
- def ex = thrown(RuntimeException)
- ex == failure
-
- and:
- delegate.evaluate(project, state) >> { throw failure }
-
- and:
- 1 * state.setExecuting(false)
- 1 * state.executed()
- 1 * listener.afterEvaluate(project, state)
- }
-}
diff --git a/subprojects/core/src/test/groovy/org/gradle/configuration/ProjectDependencies2TaskResolverTest.groovy b/subprojects/core/src/test/groovy/org/gradle/configuration/ProjectDependencies2TaskResolverTest.groovy
deleted file mode 100644
index b11e6a8..0000000
--- a/subprojects/core/src/test/groovy/org/gradle/configuration/ProjectDependencies2TaskResolverTest.groovy
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2007 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.configuration
-
-import org.gradle.util.HelperUtil
-import spock.lang.Specification
-
-/**
- * @author Hans Dockter
- */
-class ProjectDependencies2TaskResolverTest extends Specification {
- private root = HelperUtil.createRootProject()
- private child = HelperUtil.createChildProject(root, "child")
- private rootTask = root.tasks.add('compile')
- private childTask = child.tasks.add('compile')
-
- private resolver = new ProjectDependencies2TaskResolver()
-
- void "resolves task dependencies"() {
- child.dependsOn(root.path, false)
- when:
- resolver.afterEvaluate(child, null)
- then:
- childTask.taskDependencies.getDependencies(childTask) == [rootTask] as Set
- }
-}
diff --git a/subprojects/core/src/test/groovy/org/gradle/configuration/project/BuildScriptProcessorTest.groovy b/subprojects/core/src/test/groovy/org/gradle/configuration/project/BuildScriptProcessorTest.groovy
new file mode 100644
index 0000000..f5ce95a
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/configuration/project/BuildScriptProcessorTest.groovy
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.configuration.project
+
+import org.gradle.api.internal.project.ProjectInternal
+import org.gradle.configuration.ScriptPlugin
+import org.gradle.configuration.ScriptPluginFactory
+import org.gradle.groovy.scripts.ScriptSource
+import spock.lang.Specification
+
+public class BuildScriptProcessorTest extends Specification {
+ def project = Mock(ProjectInternal)
+ def scriptSource = Mock(ScriptSource)
+ def configurerFactory = Mock(ScriptPluginFactory)
+ def scriptPlugin = Mock(ScriptPlugin)
+ def BuildScriptProcessor buildScriptProcessor = new BuildScriptProcessor(configurerFactory);
+
+ def "setup"() {
+ _ * project.buildScriptSource >> scriptSource
+ }
+
+ def configuresProjectUsingBuildScript() {
+ when:
+ buildScriptProcessor.execute(project)
+
+ then:
+ 1 * configurerFactory.create(scriptSource) >> scriptPlugin
+ 1 * scriptPlugin.apply(project)
+ }
+}
\ No newline at end of file
diff --git a/subprojects/core/src/test/groovy/org/gradle/configuration/project/ConfigureActionsProjectEvaluatorTest.groovy b/subprojects/core/src/test/groovy/org/gradle/configuration/project/ConfigureActionsProjectEvaluatorTest.groovy
new file mode 100644
index 0000000..ebde2fe
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/configuration/project/ConfigureActionsProjectEvaluatorTest.groovy
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.configuration.project
+
+import org.gradle.api.internal.project.ProjectInternal
+import org.gradle.api.internal.project.ProjectStateInternal
+import spock.lang.Specification
+
+class ConfigureActionsProjectEvaluatorTest extends Specification {
+ final def project = Mock(ProjectInternal)
+ final def state = Mock(ProjectStateInternal)
+ final def action1 = Mock(ProjectConfigureAction)
+ final def action2 = Mock(ProjectConfigureAction)
+ final def evaluator = new ConfigureActionsProjectEvaluator(action1, action2)
+
+ def "executes all configuration actions"() {
+ def project = Mock(ProjectInternal)
+
+ when:
+ evaluator.evaluate(project, state)
+
+ then:
+ 1 * action1.execute(project)
+ 1 * action2.execute(project)
+ 0 * _._
+ }
+
+ def "does not continue executing actions when action fails"() {
+ def project = Mock(ProjectInternal)
+ def failure = new RuntimeException("Configure action failed")
+
+ when:
+ evaluator.evaluate(project, state)
+
+ then:
+ 1 * action1.execute(project) >> {
+ throw failure
+ }
+ 0 * _._
+
+ and:
+ def t = thrown(RuntimeException)
+ t == failure
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/configuration/project/DefaultProjectConfigurationActionContainerTest.groovy b/subprojects/core/src/test/groovy/org/gradle/configuration/project/DefaultProjectConfigurationActionContainerTest.groovy
new file mode 100644
index 0000000..30be9e5
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/configuration/project/DefaultProjectConfigurationActionContainerTest.groovy
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.configuration.project
+
+import org.gradle.api.Action
+import org.gradle.api.internal.project.ProjectInternal
+import spock.lang.Specification
+
+class DefaultProjectConfigurationActionContainerTest extends Specification {
+ def container = new DefaultProjectConfigurationActionContainer()
+
+ def "can add action to container"() {
+ def action = Mock(Action)
+
+ when:
+ container.add(action)
+
+ then:
+ container.actions == [action]
+ }
+
+ def "can add action as closure"() {
+ def run = false
+ def action = { run = true }
+
+ when:
+ container.add(action)
+
+ then:
+ container.actions.size() == 1
+
+ when:
+ container.actions[0].execute(Stub(ProjectInternal))
+
+ then:
+ run
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/configuration/project/DelayedConfigurationActionsTest.groovy b/subprojects/core/src/test/groovy/org/gradle/configuration/project/DelayedConfigurationActionsTest.groovy
new file mode 100644
index 0000000..4670551
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/configuration/project/DelayedConfigurationActionsTest.groovy
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.configuration.project
+
+import org.gradle.api.Action
+import org.gradle.api.internal.project.ProjectInternal
+import spock.lang.Specification
+
+class DelayedConfigurationActionsTest extends Specification {
+ final container = Mock(ProjectConfigurationActionContainer)
+ final project = Stub(ProjectInternal) {
+ getConfigurationActions() >> container
+ }
+ final action = new DelayedConfigurationActions()
+
+ def "runs actions and discards actions when finished"() {
+ def action1 = Mock(Action)
+ def action2 = Mock(Action)
+
+ given:
+ container.actions >> [action1, action2]
+
+ when:
+ action.execute(project)
+
+ then:
+ 1 * action1.execute(project)
+ 1 * action2.execute(project)
+
+ and:
+ 1 * container.finished()
+ }
+
+ def "discards actions on failure"() {
+ def action1 = Mock(Action)
+ def action2 = Mock(Action)
+ def failure = new RuntimeException()
+
+ given:
+ container.actions >> [action1, action2]
+
+ when:
+ action.execute(project)
+
+ then:
+ def e = thrown(RuntimeException)
+ e == failure
+
+ and:
+ 1 * action1.execute(project) >> { throw failure }
+ 0 * action2._
+
+ and:
+ 1 * container.finished()
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/configuration/project/LifecycleProjectEvaluatorTest.groovy b/subprojects/core/src/test/groovy/org/gradle/configuration/project/LifecycleProjectEvaluatorTest.groovy
new file mode 100644
index 0000000..76697ad
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/configuration/project/LifecycleProjectEvaluatorTest.groovy
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.configuration.project
+
+import org.gradle.api.ProjectConfigurationException
+import org.gradle.api.ProjectEvaluationListener
+import org.gradle.api.internal.project.ProjectInternal
+import org.gradle.api.internal.project.ProjectStateInternal
+import spock.lang.Specification
+
+public class LifecycleProjectEvaluatorTest extends Specification {
+ private project = Mock(ProjectInternal)
+ private listener = Mock(ProjectEvaluationListener)
+ private delegate = Mock(ProjectEvaluator)
+ private state = Mock(ProjectStateInternal)
+ private evaluator = new LifecycleProjectEvaluator(delegate)
+
+ void setup() {
+ project.getProjectEvaluationBroadcaster() >> listener
+ project.toString() >> "project1"
+ }
+
+ void "nothing happens if project was already configured"() {
+ state.executed >> true
+
+ when:
+ evaluator.evaluate(project, state)
+
+ then:
+ 0 * delegate._
+ }
+
+ void "nothing happens if project is being configured now"() {
+ state.executing >> true
+
+ when:
+ evaluator.evaluate(project, state)
+
+ then:
+ 0 * delegate._
+ }
+
+ void "evaluates the project firing all necessary listeners and updating the state"() {
+ when:
+ evaluator.evaluate(project, state)
+
+ then:
+ 1 * listener.beforeEvaluate(project)
+ 1 * state.setExecuting(true)
+
+ then:
+ 1 * delegate.evaluate(project, state)
+
+ then:
+ 1 * state.setExecuting(false)
+ 1 * state.executed()
+ 1 * listener.afterEvaluate(project, state)
+ }
+
+ void "notifies listeners and updates state on evaluation failure"() {
+ def failure = new RuntimeException()
+
+ when:
+ evaluator.evaluate(project, state)
+
+ then:
+ delegate.evaluate(project, state) >> { throw failure }
+
+ and:
+ 1 * state.executed({
+ assertIsConfigurationFailure(it, failure)
+ })
+ 1 * state.setExecuting(false)
+ 1 * listener.afterEvaluate(project, state)
+ }
+
+ void "updates state and does not delegate when beforeEvaluate action fails"() {
+ def failure = new RuntimeException()
+
+ when:
+ evaluator.evaluate(project, state)
+
+ then:
+ 1 * listener.beforeEvaluate(project) >> { throw failure }
+ 1 * state.executed({
+ assertIsConfigurationFailure(it, failure)
+ })
+ 0 * delegate._
+ 0 * listener._
+ }
+
+ void "updates state when afterEvaluate action fails"() {
+ def failure = new RuntimeException()
+
+ when:
+ evaluator.evaluate(project, state)
+
+ then:
+ delegate.evaluate(project, state)
+
+ and:
+ 1 * state.setExecuting(false)
+ 1 * state.executed()
+
+ then:
+ 1 * listener.afterEvaluate(project, state) >> { throw failure }
+ 1 * state.executed({
+ assertIsConfigurationFailure(it, failure)
+ })
+ }
+
+ def assertIsConfigurationFailure(def it, def cause) {
+ assert it instanceof ProjectConfigurationException
+ assert it.message == "A problem occurred configuring project1."
+ assert it.cause == cause
+ true
+ }
+
+ void "notifies listeners and updates state on evaluation failure even if afterEvaluate fails"() {
+ def failure = new RuntimeException()
+
+ when:
+ evaluator.evaluate(project, state)
+
+ then:
+ delegate.evaluate(project, state) >> { throw failure }
+
+ and:
+ _ * project.toString() >> "project1"
+ 1 * state.executed(_)
+ 1 * state.setExecuting(false)
+
+ then:
+ 1 * listener.afterEvaluate(project, state) >> { throw new RuntimeException("afterEvaluate")}
+ 1 * state.hasFailure() >> true
+ 0 * state.executed(_)
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/configuration/project/PluginsProjectConfigureActionsTest.groovy b/subprojects/core/src/test/groovy/org/gradle/configuration/project/PluginsProjectConfigureActionsTest.groovy
new file mode 100644
index 0000000..d4ec1aa
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/configuration/project/PluginsProjectConfigureActionsTest.groovy
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.configuration.project
+import org.gradle.api.internal.project.ProjectInternal
+import spock.lang.Specification
+
+class PluginsProjectConfigureActionsTest extends Specification {
+ final def pluginsClassLoader = Mock(ClassLoader)
+ final def evaluator = new PluginsProjectConfigureActions(pluginsClassLoader)
+
+ def "executes all implicit configuration actions"() {
+ def project = Mock(ProjectInternal)
+
+ when:
+ evaluator.execute(project)
+
+ then:
+ 1 * pluginsClassLoader.getResources('META-INF/services/org.gradle.configuration.project.ProjectConfigureAction') >> resources()
+ 1 * pluginsClassLoader.loadClass('ConfigureActionClass') >> TestConfigureAction
+ 1 * project.setVersion(12)
+ 0 * _._
+ }
+
+ def resources() {
+ URLStreamHandler handler = Mock()
+ URLConnection connection = Mock()
+ URL url = new URL("custom", "host", 12, "file", handler)
+ _ * handler.openConnection(url) >> connection
+ _ * connection.getInputStream() >> new ByteArrayInputStream("ConfigureActionClass".bytes)
+ return Collections.enumeration([url])
+ }
+
+ static class TestConfigureAction implements ProjectConfigureAction {
+ void execute(ProjectInternal project) {
+ project.version = 12
+ }
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/configuration/project/ProjectDependencies2TaskResolverTest.groovy b/subprojects/core/src/test/groovy/org/gradle/configuration/project/ProjectDependencies2TaskResolverTest.groovy
new file mode 100644
index 0000000..9be41ed
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/configuration/project/ProjectDependencies2TaskResolverTest.groovy
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2007 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.configuration.project
+
+import org.gradle.util.TestUtil
+import spock.lang.Specification
+
+class ProjectDependencies2TaskResolverTest extends Specification {
+ private root = TestUtil.createRootProject()
+ private child = TestUtil.createChildProject(root, "child")
+ private rootTask = root.tasks.create('compile')
+ private childTask = child.tasks.create('compile')
+
+ private resolver = new ProjectDependencies2TaskResolver()
+
+ void "resolves task dependencies"() {
+ child.dependsOn(root.path, false)
+ when:
+ resolver.execute(child)
+ then:
+ childTask.taskDependencies.getDependencies(childTask) == [rootTask] as Set
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/execution/ProjectEvaluatingActionTest.groovy b/subprojects/core/src/test/groovy/org/gradle/execution/ProjectEvaluatingActionTest.groovy
index 7ffe1f2..abd3159 100644
--- a/subprojects/core/src/test/groovy/org/gradle/execution/ProjectEvaluatingActionTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/execution/ProjectEvaluatingActionTest.groovy
@@ -21,9 +21,6 @@ import org.gradle.api.internal.GradleInternal
import org.gradle.api.internal.project.DefaultProject
import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 1/8/13
- */
class ProjectEvaluatingActionTest extends Specification {
private evaluator = Mock(TaskPathProjectEvaluator)
diff --git a/subprojects/core/src/test/groovy/org/gradle/execution/TaskNameResolverTest.groovy b/subprojects/core/src/test/groovy/org/gradle/execution/TaskNameResolverTest.groovy
index 1f56ba4..f9dda3a 100644
--- a/subprojects/core/src/test/groovy/org/gradle/execution/TaskNameResolverTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/execution/TaskNameResolverTest.groovy
@@ -27,15 +27,15 @@ class TaskNameResolverTest extends Specification {
ProjectInternal project = Mock()
TaskContainerInternal tasks = Mock()
_ * project.tasks >> tasks
-
Task task = task('task')
+ 1 * tasks.getByName('task') >> task
when:
def candidates = resolver.select('task', project)
then:
1 * tasks.findByName('task') >> task
- candidates.get('task') == [task] as Set
+ asTasks(candidates.get("task")) == [task] as Set
}
def selectsImplicitTaskForSingleProjectWhenThereIsAnExactMatchOnName() {
@@ -46,6 +46,7 @@ class TaskNameResolverTest extends Specification {
_ * project.implicitTasks >> implicitTasks
Task task = task('task')
+ 1 * implicitTasks.getByName('task') >> task
when:
def candidates = resolver.select('task', project)
@@ -53,7 +54,7 @@ class TaskNameResolverTest extends Specification {
then:
1 * tasks.findByName('task') >> null
1 * implicitTasks.findByName('task') >> task
- candidates.get('task') == [task] as Set
+ asTasks(candidates.get('task')) == [task] as Set
}
def selectsAllTasksForSingleProjectWhenThereIsNoExactMatchOnName() {
@@ -65,7 +66,8 @@ class TaskNameResolverTest extends Specification {
Task task1 = task('task1')
Task task2 = task('task2')
- Task hidden = task('task1')
+ 1 * tasks.getByName('task1') >> task1
+ 1 * implicitTasks.getByName('task2') >> task2
when:
def candidates = resolver.select('task', project)
@@ -73,12 +75,13 @@ class TaskNameResolverTest extends Specification {
then:
1 * tasks.findByName('task') >> null
1 * implicitTasks.findByName('task') >> null
- 1 * tasks.iterator() >> [task1].iterator()
- 1 * implicitTasks.iterator() >> [task2, hidden].iterator()
- candidates.get('task1') == [task1] as Set
- candidates.get('task2') == [task2] as Set
+ 1 * tasks.names >> (['task1'] as SortedSet)
+ 1 * implicitTasks.names >> (['task2', 'task1'] as SortedSet)
+ asTasks(candidates.get('task1')) == [task1] as Set
+ asTasks(candidates.get('task2')) == [task2] as Set
}
+
def selectsTasksForMultipleProjectsWhenThereIsAnExactMatchOnName() {
ProjectInternal project = Mock()
TaskContainerInternal tasks = Mock()
@@ -89,7 +92,9 @@ class TaskNameResolverTest extends Specification {
_ * childProject.tasks >> childProjectTasks
Task task1 = task('task')
+ _ * tasks.getByName('task') >> task1
Task task2 = task('task')
+ _ * childProjectTasks.getByName('task') >> task2
when:
def candidates = resolver.selectAll('task', project)
@@ -97,7 +102,7 @@ class TaskNameResolverTest extends Specification {
then:
1 * tasks.findByName('task') >> task1
1 * childProjectTasks.findByName('task') >> task2
- candidates.get('task') == [task1, task2] as Set
+ asTasks(candidates.get('task')) == [task1, task2] as Set
}
def selectsImplicitTaskForMultipleProjectsWhenThereIsAnExactMatchOnName() {
@@ -112,7 +117,9 @@ class TaskNameResolverTest extends Specification {
_ * childProject.tasks >> childProjectTasks
Task task1 = task('task')
+ _ * implicitTasks.getByName('task') >> task1
Task task2 = task('task')
+ _ * childProjectTasks.getByName('task') >> task2
when:
def candidates = resolver.selectAll('task', project)
@@ -121,7 +128,7 @@ class TaskNameResolverTest extends Specification {
1 * tasks.findByName('task') >> null
1 * implicitTasks.findByName('task') >> task1
1 * childProjectTasks.findByName('task') >> task2
- candidates.get('task') == [task1, task2] as Set
+ asTasks(candidates.get('task')) == [task1, task2] as Set
}
def selectsAllTasksForMultipleProjectsWhenThereIsNoExactMatchOnName() {
@@ -139,6 +146,13 @@ class TaskNameResolverTest extends Specification {
Task task2 = task('name2')
Task task3 = task('name1')
Task task4 = task('name2')
+ Task task5 = task('name3')
+
+ _ * childProjectTasks.getByName(task3.name) >> task3
+ _ * childProjectTasks.getByName(task4.name) >> task4
+ _ * childProjectTasks.getByName(task5.name) >> task5
+ _ * tasks.getByName(task1.name) >> task1
+ _ * implicitTasks.getByName(task2.name) >> task2
when:
def candidates = resolver.selectAll('task', project)
@@ -147,11 +161,13 @@ class TaskNameResolverTest extends Specification {
1 * tasks.findByName('task') >> null
1 * implicitTasks.findByName('task') >> null
1 * childProjectTasks.findByName('task') >> null
- 1 * tasks.iterator() >> [task1].iterator()
- 1 * implicitTasks.iterator() >> [task2].iterator()
- 1 * childProjectTasks.iterator() >> [task3, task4].iterator()
- candidates.get('name1') == [task1, task3] as Set
- candidates.get('name2') == [task2, task4] as Set
+ 1 * tasks.names >> ([task1.name] as SortedSet)
+ 1 * implicitTasks.names >> ([task2.name] as SortedSet)
+ 1 * childProjectTasks.names >> ([task3.name, task4.name, task5.name] as SortedSet)
+
+ asTasks(candidates.get('name1')) == [task1, task3] as Set
+ asTasks(candidates.get('name2')) == [task2, task4] as Set
+ asTasks(candidates.get('name3')) == [task5] as Set
}
def task(String name) {
@@ -159,4 +175,8 @@ class TaskNameResolverTest extends Specification {
_ * task.name >> name
return task
}
+
+ Set<Task> asTasks(Set<TaskSelectionResult> taskSelectionResults) {
+ taskSelectionResults.collect { it.getTask() }.toSet()
+ }
}
diff --git a/subprojects/core/src/test/groovy/org/gradle/execution/TaskNameResolvingBuildConfigurationActionTest.java b/subprojects/core/src/test/groovy/org/gradle/execution/TaskNameResolvingBuildConfigurationActionTest.java
index 7314ea3..de4e2b0 100644
--- a/subprojects/core/src/test/groovy/org/gradle/execution/TaskNameResolvingBuildConfigurationActionTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/execution/TaskNameResolvingBuildConfigurationActionTest.java
@@ -42,7 +42,7 @@ import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
- at RunWith (org.jmock.integration.junit4.JMock.class)
+ at RunWith(org.jmock.integration.junit4.JMock.class)
public class TaskNameResolvingBuildConfigurationActionTest {
private final JUnit4Mockery context = new JUnit4GroovyMockery();
private final ProjectInternal project = context.mock(AbstractProject.class, "[project]");
@@ -57,7 +57,7 @@ public class TaskNameResolvingBuildConfigurationActionTest {
@Before
public void setUp() {
- context.checking(new Expectations(){{
+ context.checking(new Expectations() {{
allowing(executionContext).getGradle();
will(returnValue(gradle));
allowing(gradle).getDefaultProject();
@@ -132,13 +132,13 @@ public class TaskNameResolvingBuildConfigurationActionTest {
action.configure(executionContext);
}
-
+
@Test
public void selectsTaskWithMatchingRelativePath() {
final Task task1 = task("b");
final Task task2 = task("a");
- context.checking(new Expectations(){{
+ context.checking(new Expectations() {{
allowing(startParameter).getTaskNames();
will(returnValue(toList("a:b")));
@@ -158,7 +158,7 @@ public class TaskNameResolvingBuildConfigurationActionTest {
final Task task1 = task("b");
final Task task2 = task("a");
- context.checking(new Expectations(){{
+ context.checking(new Expectations() {{
allowing(startParameter).getTaskNames();
will(returnValue(toList(":b")));
@@ -178,7 +178,7 @@ public class TaskNameResolvingBuildConfigurationActionTest {
final Task task1 = task("b");
final Task task2 = task("a");
- context.checking(new Expectations(){{
+ context.checking(new Expectations() {{
allowing(startParameter).getTaskNames();
will(returnValue(toList(":a:b")));
@@ -200,7 +200,7 @@ public class TaskNameResolvingBuildConfigurationActionTest {
final Task task1 = task("someTask");
final Task task2 = task("other");
- context.checking(new Expectations(){{
+ context.checking(new Expectations() {{
allowing(startParameter).getTaskNames();
will(returnValue(toList("anotherProject:soTa")));
@@ -220,7 +220,7 @@ public class TaskNameResolvingBuildConfigurationActionTest {
final Task task1 = task("someTask");
final Task task2 = task("other");
- context.checking(new Expectations(){{
+ context.checking(new Expectations() {{
allowing(startParameter).getTaskNames();
will(returnValue(toList("anPr:soTa")));
@@ -384,27 +384,40 @@ public class TaskNameResolvingBuildConfigurationActionTest {
private <T extends Task> T task(final String name, Class<T> taskType) {
final T task = context.mock(taskType);
- context.checking(new Expectations(){{
+ context.checking(new Expectations() {{
allowing(task).getName();
will(returnValue(name));
}});
return task;
}
- private Multimap<String, Task> tasks(Task... tasks) {
+ private Multimap<String, TaskSelectionResult> tasks(Task... tasks) {
return tasks(Arrays.asList(tasks));
}
- private Multimap<String, Task> tasks(Iterable<Task> tasks) {
- Multimap<String, Task> map = LinkedHashMultimap.create();
- for (Task task : tasks) {
- map.put(task.getName(), task);
+ private Multimap<String, TaskSelectionResult> tasks(Iterable<Task> tasks) {
+ Multimap<String, TaskSelectionResult> map = LinkedHashMultimap.create();
+ for (final Task task : tasks) {
+ map.put(task.getName(), new SimpleTaskSelectionResult(task));
}
return map;
}
+ private static class SimpleTaskSelectionResult implements TaskSelectionResult {
+ private final Task task;
+
+ public SimpleTaskSelectionResult(Task task) {
+ this.task = task;
+ }
+
+ public Task getTask() {
+ return task;
+ }
+ }
+
public abstract class TaskWithBooleanProperty implements Task {
@CommandLineOption(options = "all", description = "Some boolean flag")
- public void setSomeFlag(boolean flag) { }
+ public void setSomeFlag(boolean flag) {
+ }
}
}
diff --git a/subprojects/core/src/test/groovy/org/gradle/execution/TaskPathProjectEvaluatorTest.groovy b/subprojects/core/src/test/groovy/org/gradle/execution/TaskPathProjectEvaluatorTest.groovy
index 4a8306c..214d9bb 100644
--- a/subprojects/core/src/test/groovy/org/gradle/execution/TaskPathProjectEvaluatorTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/execution/TaskPathProjectEvaluatorTest.groovy
@@ -21,9 +21,6 @@ import org.gradle.execution.taskpath.ResolvedTaskPath
import org.gradle.execution.taskpath.TaskPathResolver
import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 1/8/13
- */
class TaskPathProjectEvaluatorTest extends Specification {
private resolver = Mock(TaskPathResolver)
diff --git a/subprojects/core/src/test/groovy/org/gradle/execution/commandline/CommandLineTaskConfigurerSpec.groovy b/subprojects/core/src/test/groovy/org/gradle/execution/commandline/CommandLineTaskConfigurerSpec.groovy
index 8742df0..db442aa 100644
--- a/subprojects/core/src/test/groovy/org/gradle/execution/commandline/CommandLineTaskConfigurerSpec.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/execution/commandline/CommandLineTaskConfigurerSpec.groovy
@@ -27,9 +27,6 @@ import org.gradle.execution.TaskSelector
import org.gradle.testfixtures.ProjectBuilder
import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 10/8/12
- */
class CommandLineTaskConfigurerSpec extends Specification {
Project project = new ProjectBuilder().build()
diff --git a/subprojects/core/src/test/groovy/org/gradle/execution/commandline/CommandLineTaskParserSpec.groovy b/subprojects/core/src/test/groovy/org/gradle/execution/commandline/CommandLineTaskParserSpec.groovy
index 269f3ad..6523fe7 100644
--- a/subprojects/core/src/test/groovy/org/gradle/execution/commandline/CommandLineTaskParserSpec.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/execution/commandline/CommandLineTaskParserSpec.groovy
@@ -19,6 +19,7 @@ package org.gradle.execution.commandline
import org.gradle.api.DefaultTask
import org.gradle.api.Project
import org.gradle.api.tasks.TaskAction
+import org.gradle.execution.TaskSelectionResult
import org.gradle.execution.TaskSelector
import org.gradle.testfixtures.ProjectBuilder
import spock.lang.Specification
@@ -26,9 +27,6 @@ import spock.lang.Specification
import static com.google.common.collect.Sets.newHashSet
import static java.util.Collections.emptyList
-/**
- * by Szczepan Faber, created at: 10/8/12
- */
class CommandLineTaskParserSpec extends Specification {
Project project = new ProjectBuilder().build()
@@ -50,7 +48,7 @@ class CommandLineTaskParserSpec extends Specification {
def "parses a single task"() {
given:
- selector.getSelection('foo') >> new TaskSelector.TaskSelection('foo task', [task] as Set)
+ selector.getSelection('foo') >> new TaskSelector.TaskSelection('foo task', asTaskSelectionResults(task))
when:
def out = parser.parseTasks(['foo'], selector)
@@ -60,9 +58,17 @@ class CommandLineTaskParserSpec extends Specification {
out.get('foo task') == [task] as Set
}
+ Set<TaskSelectionResult> asTaskSelectionResults(SomeTask... someTasks) {
+ return someTasks.collect {task ->
+ TaskSelectionResult mock = Mock(TaskSelectionResult)
+ _ * mock.task >> task
+ mock
+ }
+ }
+
def "parses single task with multiple matches"() {
given:
- selector.getSelection('foo') >> new TaskSelector.TaskSelection('foo task', [task, task2] as Set)
+ selector.getSelection('foo') >> new TaskSelector.TaskSelection('foo task', asTaskSelectionResults(task, task2))
when:
def out = parser.parseTasks(['foo'], selector)
@@ -74,8 +80,8 @@ class CommandLineTaskParserSpec extends Specification {
def "parses multiple matching tasks"() {
given:
- selector.getSelection('foo') >> new TaskSelector.TaskSelection('foo task', [task, task2] as Set)
- selector.getSelection('bar') >> new TaskSelector.TaskSelection('bar task', [task3] as Set)
+ selector.getSelection('foo') >> new TaskSelector.TaskSelection('foo task', asTaskSelectionResults(task, task2))
+ selector.getSelection('bar') >> new TaskSelector.TaskSelection('bar task', asTaskSelectionResults(task3))
when:
def out = parser.parseTasks(['foo', 'bar'], selector)
@@ -88,9 +94,9 @@ class CommandLineTaskParserSpec extends Specification {
def "configures tasks if configuration options specified"() {
given:
- selector.getSelection('foo') >> new TaskSelector.TaskSelection('foo task', [task, task2] as Set)
- selector.getSelection('bar') >> new TaskSelector.TaskSelection('bar task', [task3] as Set)
- selector.getSelection('lastTask') >> new TaskSelector.TaskSelection('last task', [task3] as Set)
+ selector.getSelection('foo') >> new TaskSelector.TaskSelection('foo task', asTaskSelectionResults(task, task2))
+ selector.getSelection('bar') >> new TaskSelector.TaskSelection('bar task', asTaskSelectionResults(task3))
+ selector.getSelection('lastTask') >> new TaskSelector.TaskSelection('last task', asTaskSelectionResults(task3))
when:
def out = parser.parseTasks(['foo', '--all', 'bar', '--include', 'stuff', 'lastTask'], selector)
diff --git a/subprojects/core/src/test/groovy/org/gradle/execution/taskgraph/DefaultTaskExecutionPlanTest.groovy b/subprojects/core/src/test/groovy/org/gradle/execution/taskgraph/DefaultTaskExecutionPlanTest.groovy
index fc8f67e..86215cf 100644
--- a/subprojects/core/src/test/groovy/org/gradle/execution/taskgraph/DefaultTaskExecutionPlanTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/execution/taskgraph/DefaultTaskExecutionPlanTest.groovy
@@ -14,83 +14,86 @@
* limitations under the License.
*/
-package org.gradle.execution.taskgraph;
-
+package org.gradle.execution.taskgraph
import org.gradle.api.CircularReferenceException
import org.gradle.api.Task
import org.gradle.api.internal.TaskInternal
-import org.gradle.api.internal.changedetection.TaskArtifactStateCacheAccess
-import org.gradle.api.internal.project.ProjectInternal
+import org.gradle.api.internal.project.DefaultProject
import org.gradle.api.specs.Spec
-import org.gradle.api.specs.Specs
import org.gradle.api.tasks.TaskDependency
import org.gradle.api.tasks.TaskState
-import org.gradle.cache.PersistentIndexedCache
import org.gradle.execution.TaskFailureHandler
-import org.gradle.internal.Factory
-import org.gradle.messaging.serialize.Serializer
-import org.hamcrest.Description
-import org.jmock.api.Invocation
+import org.gradle.util.TextUtil
import spock.lang.Specification
-import static org.gradle.util.HelperUtil.createRootProject
+import static org.gradle.util.TestUtil.createChildProject
+import static org.gradle.util.TestUtil.createRootProject
import static org.gradle.util.WrapUtil.toList
-import static org.gradle.util.WrapUtil.toSet
public class DefaultTaskExecutionPlanTest extends Specification {
DefaultTaskExecutionPlan executionPlan
- ProjectInternal root;
- Spec<TaskInfo> anyTask = Specs.satisfyAll();
+ DefaultProject root;
def setup() {
root = createRootProject();
executionPlan = new DefaultTaskExecutionPlan()
}
- def "returns tasks in dependency order"() {
+ private void addToGraphAndPopulate(List tasks) {
+ executionPlan.addToTaskGraph(tasks)
+ executionPlan.determineExecutionPlan()
+ }
+
+ private TaskFailureHandler createIgnoreTaskFailureHandler(Task task) {
+ Mock(TaskFailureHandler) {
+ onTaskFailure(task) >> {}
+ }
+ }
+
+ def "schedules tasks in dependency order"() {
given:
Task a = task("a");
- Task b = task("b", a);
- Task c = task("c", b, a);
- Task d = task("d", c);
+ Task b = task("b", dependsOn: [a]);
+ Task c = task("c", dependsOn: [b, a]);
+ Task d = task("d", dependsOn: [c]);
when:
- executionPlan.addToTaskGraph(toList(d))
+ addToGraphAndPopulate([d])
then:
- executedTasks == [a, b, c, d]
+ executes(a, b, c, d)
}
- def "returns task dependencies in name order"() {
+ def "schedules task dependencies in name order when there are no dependencies between them"() {
given:
Task a = task("a");
Task b = task("b");
Task c = task("c");
- Task d = task("d", b, a, c);
+ Task d = task("d", dependsOn: [b, a, c]);
when:
- executionPlan.addToTaskGraph(toList(d));
+ addToGraphAndPopulate([d])
then:
- executedTasks == [a, b, c, d]
+ executes(a, b, c, d)
}
- def "returns a single batch of tasks in name order"() {
+ def "schedules a single batch of tasks in name order"() {
given:
Task a = task("a");
Task b = task("b");
Task c = task("c");
when:
- executionPlan.addToTaskGraph(toList(b, c, a));
+ addToGraphAndPopulate(toList(b, c, a));
then:
- executedTasks == [a, b, c]
+ executes(a, b, c)
}
- def "returns separately added tasks in order added"() {
+ def "schedules separately added tasks in order added"() {
given:
Task a = task("a");
Task b = task("b");
@@ -99,73 +102,287 @@ public class DefaultTaskExecutionPlanTest extends Specification {
when:
executionPlan.addToTaskGraph(toList(c, b));
- executionPlan.addToTaskGraph(toList(d, a));
+ executionPlan.addToTaskGraph(toList(d, a))
+ executionPlan.determineExecutionPlan()
+
+ then:
+ executes(b, c, a, d)
+ }
+
+ def "schedules must run after task dependencies in name order"() {
+ given:
+ Task a = task("a");
+ Task b = task("b");
+ Task c = task("c", mustRunAfter: [b, a]);
+ Task d = task("d", dependsOn: [b, a]);
+
+ when:
+ addToGraphAndPopulate([c, d]);
then:
- executedTasks == [b, c, a, d];
+ executes(a, b, c, d)
}
- def "common tasks in separate batches are returned only once"() {
+ def "common tasks in separate batches are schedules only once"() {
Task a = task("a");
Task b = task("b");
- Task c = task("c", a, b);
+ Task c = task("c", dependsOn: [a, b]);
Task d = task("d");
- Task e = task("e", b, d);
+ Task e = task("e", dependsOn: [b, d]);
when:
executionPlan.addToTaskGraph(toList(c));
executionPlan.addToTaskGraph(toList(e));
+ executionPlan.determineExecutionPlan();
then:
- executedTasks == [a, b, c, d, e];
+ executes(a, b, c, d, e)
}
- def "all dependencies added when adding tasks"() {
+ def "all dependencies scheduled when adding tasks"() {
Task a = task("a");
- Task b = task("b", a);
- Task c = task("c", b, a);
- Task d = task("d", c);
+ Task b = task("b", dependsOn: [a]);
+ Task c = task("c", dependsOn: [b, a]);
+ Task d = task("d", dependsOn: [c]);
when:
- executionPlan.addToTaskGraph(toList(d));
+ addToGraphAndPopulate(toList(d));
then:
- executionPlan.getTasks() == [a, b, c, d];
- executedTasks == [a, b, c, d]
+ executes(a, b, c, d)
}
- def "getAllTasks returns tasks in execution order"() {
- Task d = task("d");
- Task c = task("c");
- Task b = task("b", d, c);
- Task a = task("a", b);
+ def "must run after ordering is honoured for tasks added separately to graph"() {
+ Task a = task("a")
+ Task b = task("b", dependsOn: [a])
+ Task c = task("c", mustRunAfter: [b])
+
+ when:
+ executionPlan.addToTaskGraph([c])
+ executionPlan.addToTaskGraph([b])
+ executionPlan.determineExecutionPlan()
+
+ then:
+ executes(a, b, c)
+ }
+
+ def "must run after ordering is honoured for dependencies"() {
+ Task b = task("b")
+ Task a = task("a", mustRunAfter: [b])
+ Task c = task("c", dependsOn: [a, b])
+
+ when:
+ addToGraphAndPopulate([c])
+
+ then:
+ executes(b, a, c)
+ }
+
+ def "mustRunAfter dependencies are scheduled before regular dependencies"() {
+ Task a = task("a")
+ Task b = task("b")
+ Task c = task("c", dependsOn: [a], mustRunAfter: [b])
+ Task d = task("d", dependsOn: [b])
+
+ when:
+ addToGraphAndPopulate([c, d])
+
+ then:
+ executes(b, a, c, d)
+ }
+
+ def "must run after does not pull in tasks that are not in the graph"() {
+ Task a = task("a")
+ Task b = task("b", mustRunAfter: [a])
+
+ when:
+ addToGraphAndPopulate([b])
+
+ then:
+ executes(b)
+ }
+
+ def "finalizer tasks are executed if a finalized task is added to the graph"() {
+ Task finalizer = task("a")
+ Task finalized = task("b", finalizedBy: [finalizer])
+
+ when:
+ addToGraphAndPopulate([finalized])
+
+ then:
+ executes(finalized, finalizer)
+ }
+
+ def "finalizer tasks and their dependencies are executed even in case of a task failure"() {
+ Task finalizerDependency = task("finalizerDependency")
+ Task finalizer1 = task("finalizer1", dependsOn: [finalizerDependency])
+ Task finalized1 = task("finalized1", finalizedBy: [finalizer1])
+ Task finalizer2 = task("finalizer2")
+ Task finalized2 = task("finalized2", finalizedBy: [finalizer2], failure: new RuntimeException("failure"))
+
+ when:
+ addToGraphAndPopulate([finalized1, finalized2])
+
+ then:
+ executes(finalized1, finalizerDependency, finalizer1, finalized2, finalizer2)
+ }
+
+ def "finalizer task is not added to the graph if it is filtered"() {
+ given:
+ Task finalizer = filteredTask("finalizer")
+ Task finalized = task("finalized", finalizedBy: [finalizer])
+ Spec<Task> filter = Mock() {
+ isSatisfiedBy(_) >> { Task t -> t != finalizer }
+ }
+
+ when:
+ executionPlan.useFilter(filter);
+ addToGraphAndPopulate([finalized])
+
+ then:
+ executes(finalized)
+ }
+
+ def "finalizer tasks and their dependencies are not executed if finalized task did not run"() {
+ Task finalizerDependency = task("finalizerDependency")
+ Task finalizer = task("finalizer", dependsOn: [finalizerDependency])
+ Task finalizedDependency = task("finalizedDependency", failure: new RuntimeException("failure"))
+ Task finalized = task("finalized", dependsOn: [finalizedDependency], finalizedBy: [finalizer])
+
+ when:
+ addToGraphAndPopulate([finalized])
+
+ then:
+ executionPlan.tasks == [finalizedDependency, finalized, finalizerDependency, finalizer]
+ executedTasks == [finalizedDependency]
+ }
+
+ def "finalizer tasks and their dependencies are executed if they are previously required even if the finalized task did not run"() {
+ Task finalizerDependency = task("finalizerDependency")
+ Task finalizer = task("finalizer", dependsOn: [finalizerDependency])
+ Task finalizedDependency = task("finalizedDependency", failure: new RuntimeException("failure"))
+ Task finalized = task("finalized", dependsOn: [finalizedDependency], finalizedBy: [finalizer])
+ executionPlan.useFailureHandler(createIgnoreTaskFailureHandler(finalizedDependency));
+
+ when:
+ addToGraphAndPopulate([finalizer, finalized])
+
+ then:
+ executionPlan.tasks == [finalizedDependency, finalized, finalizerDependency, finalizer]
+ executedTasks == [finalizedDependency, finalizerDependency, finalizer]
+ }
+
+ def "finalizer tasks and their dependencies are executed if they are later required via dependency even if the finalized task did not do any work"() {
+ Task finalizerDependency = task("finalizerDependency")
+ Task finalizer = task("finalizer", dependsOn: [finalizerDependency])
+ Task dependsOnFinalizer = task("dependsOnFinalizer", dependsOn: [finalizer])
+ Task finalized = task("finalized", finalizedBy: [finalizer], didWork: false)
when:
- executionPlan.addToTaskGraph(toList(a));
+ executionPlan.addToTaskGraph([finalized])
+ executionPlan.addToTaskGraph([dependsOnFinalizer])
+ executionPlan.determineExecutionPlan()
then:
- executionPlan.getTasks() == [c, d, b, a]
- executedTasks == [c, d, b, a]
+ executes(finalized, finalizerDependency, finalizer, dependsOnFinalizer)
+ }
+
+ def "finalizer tasks run as soon as possible for tasks that depend on finalized tasks"() {
+ Task finalizer = task("finalizer")
+ Task finalized = task("finalized", finalizedBy: [finalizer])
+ Task dependsOnFinalized = task("dependsOnFinalized", dependsOn: [finalized])
+
+ when:
+ addToGraphAndPopulate([dependsOnFinalized])
+
+ then:
+ executes(finalized, finalizer, dependsOnFinalized)
+ }
+
+ def "finalizer tasks run as soon as possible for tasks that must run after finalized tasks"() {
+ Task finalizer = task("finalizer")
+ Task finalized = task("finalized", finalizedBy: [finalizer])
+ Task mustRunAfterFinalized = task("mustRunAfterFinalized", mustRunAfter: [finalized])
+
+ when:
+ addToGraphAndPopulate([mustRunAfterFinalized, finalized])
+
+ then:
+ executes(finalized, finalizer, mustRunAfterFinalized)
}
def "cannot add task with circular reference"() {
- Task a = createTask("a");
- Task b = task("b", a);
- Task c = task("c", b);
- dependsOn(a, c);
+ Task a = createTask("a")
+ Task b = task("b", dependsOn: [a])
+ Task c = task("c", dependsOn: [b])
+ Task d = task("d")
+ relationships(a, dependsOn: [c, d])
when:
- executionPlan.addToTaskGraph([c])
+ addToGraphAndPopulate([c])
then:
- thrown CircularReferenceException
+ def e = thrown CircularReferenceException
+ e.message == TextUtil.toPlatformLineSeparators("""Circular dependency between the following tasks:
+:a
+\\--- :c
+ \\--- :b
+ \\--- :a (*)
+
+(*) - details omitted (listed previously)
+""")
+ }
+
+ def "cannot add a task with must run after induced circular reference"() {
+ Task a = createTask("a")
+ Task b = task("b", mustRunAfter: [a])
+ Task c = task("c", dependsOn: [b])
+ relationships(a, dependsOn: [c])
+
+ when:
+ addToGraphAndPopulate([a])
+
+ then:
+ def e = thrown CircularReferenceException
+ e.message == TextUtil.toPlatformLineSeparators("""Circular dependency between the following tasks:
+:a
+\\--- :c
+ \\--- :b
+ \\--- :a (*)
+
+(*) - details omitted (listed previously)
+""")
+ }
+
+ def "cannot add a task with must run after induced circular reference that was previously in graph but not required"() {
+ Task a = createTask("a")
+ Task b = task("b", mustRunAfter: [a])
+ Task c = task("c", dependsOn: [b])
+ Task d = task("d", dependsOn: [c])
+ relationships(a, mustRunAfter: [c])
+ executionPlan.addToTaskGraph([d])
+
+ when:
+ executionPlan.addToTaskGraph([a])
+ executionPlan.determineExecutionPlan()
+
+ then:
+ def e = thrown CircularReferenceException
+ e.message == TextUtil.toPlatformLineSeparators("""Circular dependency between the following tasks:
+:a
+\\--- :c
+ \\--- :b
+ \\--- :a (*)
+
+(*) - details omitted (listed previously)
+""")
}
def "stops returning tasks on task execution failure"() {
RuntimeException failure = new RuntimeException("failure");
Task a = task("a");
Task b = task("b");
- executionPlan.addToTaskGraph([a, b])
+ addToGraphAndPopulate([a, b])
when:
def taskInfoA = taskToExecute
@@ -184,16 +401,16 @@ public class DefaultTaskExecutionPlanTest extends Specification {
}
protected TaskInfo getTaskToExecute() {
- executionPlan.getTaskToExecute(anyTask)
+ executionPlan.getTaskToExecute()
}
def "stops returning tasks on first task failure when no failure handler provided"() {
RuntimeException failure = new RuntimeException("failure");
- Task a = brokenTask("a", failure);
+ Task a = task("a", failure: failure);
Task b = task("b");
when:
- executionPlan.addToTaskGraph([a, b])
+ addToGraphAndPopulate([a, b])
then:
executedTasks == [a]
@@ -208,10 +425,10 @@ public class DefaultTaskExecutionPlanTest extends Specification {
def "stops execution on task failure when failure handler indicates that execution should stop"() {
RuntimeException failure = new RuntimeException("failure");
- Task a = brokenTask("a", failure);
+ Task a = task("a", failure: failure);
Task b = task("b");
- executionPlan.addToTaskGraph([a, b])
+ addToGraphAndPopulate([a, b])
TaskFailureHandler handler = Mock()
RuntimeException wrappedFailure = new RuntimeException("wrapped");
@@ -235,16 +452,32 @@ public class DefaultTaskExecutionPlanTest extends Specification {
def "continues to return tasks and rethrows failure on completion when failure handler indicates that execution should continue"() {
RuntimeException failure = new RuntimeException();
- Task a = brokenTask("a", failure);
+ Task a = task("a", failure: failure);
Task b = task("b");
- executionPlan.addToTaskGraph([a, b])
+ addToGraphAndPopulate([a, b])
- TaskFailureHandler handler = Mock()
- handler.onTaskFailure(a) >> {
- }
+ when:
+ executionPlan.useFailureHandler(createIgnoreTaskFailureHandler(a));
+
+ then:
+ executedTasks == [a, b]
when:
- executionPlan.useFailureHandler(handler);
+ executionPlan.awaitCompletion()
+
+ then:
+ RuntimeException e = thrown()
+ e == failure
+ }
+
+ def "continues to return tasks when failure handler does not abort execution and task are mustRunAfter dependent"() {
+ RuntimeException failure = new RuntimeException();
+ Task a = task("a", failure: failure);
+ Task b = task("b", mustRunAfter: [a]);
+ addToGraphAndPopulate([a, b])
+
+ when:
+ executionPlan.useFailureHandler(createIgnoreTaskFailureHandler(a));
then:
executedTasks == [a, b]
@@ -259,18 +492,13 @@ public class DefaultTaskExecutionPlanTest extends Specification {
def "does not attempt to execute tasks whose dependencies failed to execute"() {
RuntimeException failure = new RuntimeException()
- final Task a = brokenTask("a", failure)
- final Task b = task("b", a)
+ final Task a = task("a", failure: failure)
+ final Task b = task("b", dependsOn: [a])
final Task c = task("c")
- executionPlan.addToTaskGraph([b, c])
-
- TaskFailureHandler handler = Mock()
- handler.onTaskFailure(a) >> {
- // Ignore failure
- }
+ addToGraphAndPopulate([b, c])
when:
- executionPlan.useFailureHandler(handler)
+ executionPlan.useFailureHandler(createIgnoreTaskFailureHandler(a))
then:
executedTasks == [a, c]
@@ -288,108 +516,206 @@ public class DefaultTaskExecutionPlanTest extends Specification {
Task a = task("a");
when:
- executionPlan.addToTaskGraph(toList(a));
+ addToGraphAndPopulate(toList(a));
executionPlan.clear()
then:
- executionPlan.getTasks() == []
+ executionPlan.tasks == []
executedTasks == []
}
- def getExecutedTasks() {
- def tasks = []
- def taskInfo
- while ((taskInfo = taskToExecute) != null) {
- tasks << taskInfo.task
- executionPlan.taskComplete(taskInfo)
- }
- return tasks
- }
-
def "can add additional tasks after execution and clear"() {
given:
Task a = task("a")
Task b = task("b")
when:
- executionPlan.addToTaskGraph([a])
+ addToGraphAndPopulate([a])
then:
- executedTasks == [a]
+ executes(a)
when:
executionPlan.clear()
- executionPlan.addToTaskGraph([b])
+ addToGraphAndPopulate([b])
then:
- executedTasks == [b]
+ executes(b)
}
- def "does not execute filtered tasks"() {
+ def "does not build graph for or execute filtered tasks"() {
given:
- Task a = task("a", task("a-dep"))
+ Task a = filteredTask("a")
Task b = task("b")
+ Spec<Task> filter = Mock()
+
+ and:
+ filter.isSatisfiedBy(_) >> { Task t -> t != a }
when:
- executionPlan.useFilter({ it != a } as Spec<Task>);
- executionPlan.addToTaskGraph([a, b])
+ executionPlan.useFilter(filter);
+ addToGraphAndPopulate([a, b])
then:
- executionPlan.getTasks() == [b]
- executedTasks == [b]
+ executes(b)
}
- def "does not execute filtered dependencies"() {
+ def "does not build graph for or execute filtered dependencies"() {
given:
- Task a = task("a", task("a-dep"))
+ Task a = filteredTask("a")
Task b = task("b")
- Task c = task("c", a, b)
+ Task c = task("c", dependsOn: [a, b])
+ Spec<Task> filter = Mock()
+
+ and:
+ filter.isSatisfiedBy(_) >> { Task t -> t != a }
when:
+ executionPlan.useFilter(filter)
+ addToGraphAndPopulate([c])
- executionPlan.useFilter({ it != a } as Spec<Task>)
- executionPlan.addToTaskGraph([c])
+ then:
+ executes(b, c)
+ }
+
+ def "does not build graph for or execute filtered tasks reachable via task ordering"() {
+ given:
+ Task a = filteredTask("a")
+ Task b = task("b", mustRunAfter: [a])
+ Task c = task("c", dependsOn: [a])
+ Spec<Task> filter = Mock()
+
+ and:
+ filter.isSatisfiedBy(_) >> { Task t -> t != a }
+
+ when:
+ executionPlan.useFilter(filter)
+ addToGraphAndPopulate([b, c])
then:
- executionPlan.tasks == [b, c]
- executedTasks == [b, c]
+ executes(b, c)
}
def "will execute a task whose dependencies have been filtered"() {
given:
- Task b = task("b")
- Task c = task("c", b)
+ Task b = filteredTask("b")
+ Task c = task("c", dependsOn: [b])
+ Spec<Task> filter = Mock()
+
+ and:
+ filter.isSatisfiedBy(_) >> { Task t -> t != b }
+
+ when:
+ executionPlan.useFilter(filter)
+ addToGraphAndPopulate([c]);
+
+ then:
+ executes(c)
+ }
+
+ def "one parallel task per project is allowed"() {
+ given:
+ //2 projects, 2 tasks each
+ def projectA = createChildProject(root, "a")
+ def projectB = createChildProject(root, "b")
+
+ def fooA = projectA.task("foo")
+ def barA = projectA.task("bar")
+
+ def fooB = projectB.task("foo")
+ def barB = projectB.task("bar")
+
+ addToGraphAndPopulate([fooA, barA, fooB, barB])
+
+ when:
+ def t1 = executionPlan.getTaskToExecute()
+ def t2 = executionPlan.getTaskToExecute()
+
+ then:
+ t1.task.project != t2.task.project
when:
- executionPlan.useFilter({ it != b } as Spec<Task>)
- executionPlan.addToTaskGraph([c]);
+ executionPlan.taskComplete(t1)
+ executionPlan.taskComplete(t2)
+ def t3 = executionPlan.getTaskToExecute()
+ def t4 = executionPlan.getTaskToExecute()
then:
- executedTasks == [c]
+ t3.task.project != t4.task.project
}
- private void dependsOn(TaskInternal task, final Task... dependsOnTasks) {
- TaskDependency taskDependency = Mock()
- task.getTaskDependencies() >> taskDependency
- taskDependency.getDependencies(task) >> toSet(dependsOnTasks)
+ void executes(Task... expectedTasks) {
+ assert executionPlan.tasks == expectedTasks as List
+ assert expectedTasks == expectedTasks as List
+ }
+
+ def getExecutedTasks() {
+ def tasks = []
+ def taskInfo
+ while ((taskInfo = taskToExecute) != null) {
+ tasks << taskInfo.task
+ executionPlan.taskComplete(taskInfo)
+ }
+ return tasks
+ }
+
+ private TaskDependency taskDependencyResolvingTo(TaskInternal task, List<Task> tasks) {
+ Mock(TaskDependency) {
+ getDependencies(task) >> tasks
+ }
+ }
+
+ private TaskDependency brokenDependencies() {
+ Mock(TaskDependency) {
+ 0 * getDependencies(_)
+ }
+ }
+
+ private void dependsOn(TaskInternal task, List<Task> dependsOnTasks) {
+ task.getTaskDependencies() >> taskDependencyResolvingTo(task, dependsOnTasks)
}
-
- private Task brokenTask(String name, final RuntimeException failure, final Task... dependsOnTasks) {
- final TaskInternal task = createTask(name);
- dependsOn(task, dependsOnTasks);
+ private void mustRunAfter(TaskInternal task, List<Task> mustRunAfterTasks) {
+ task.getMustRunAfter() >> taskDependencyResolvingTo(task, mustRunAfterTasks)
+ }
+
+ private void finalizedBy(TaskInternal task, List<Task> finalizedByTasks) {
+ task.getFinalizedBy() >> taskDependencyResolvingTo(task, finalizedByTasks)
+ }
+
+ private void failure(TaskInternal task, final RuntimeException failure) {
task.state.getFailure() >> failure
task.state.rethrowFailure() >> { throw failure }
- return task;
}
- private TaskInternal task(final String name, final Task... dependsOnTasks) {
+ private TaskInternal task(final String name) {
+ task([:], name)
+ }
+
+ private TaskInternal task(Map options, final String name) {
+ def task = createTask(name)
+ relationships(options, task)
+ if (options.failure) {
+ failure(task, options.failure)
+ }
+ task.getDidWork() >> (options.containsKey('didWork') ? options.didWork : true)
+ return task
+ }
+
+ private void relationships(Map options, TaskInternal task) {
+ dependsOn(task, options.dependsOn ?: [])
+ mustRunAfter(task, options.mustRunAfter ?: [])
+ finalizedBy(task, options.finalizedBy ?: [])
+ }
+
+ private TaskInternal filteredTask(final String name) {
def task = createTask(name);
- dependsOn(task, dependsOnTasks);
- task.state.getFailure() >> null
- return task;
+ task.getTaskDependencies() >> brokenDependencies()
+ task.getMustRunAfter() >> brokenDependencies()
+ task.getFinalizedBy() >> taskDependencyResolvingTo(task, [])
+ return task
}
-
+
private TaskInternal createTask(final String name) {
TaskInternal task = Mock()
TaskState state = Mock()
@@ -403,44 +729,5 @@ public class DefaultTaskExecutionPlanTest extends Specification {
}
return task;
}
-
- private class ExecuteTaskAction implements org.jmock.api.Action {
- private final TaskInternal task;
-
- public ExecuteTaskAction(TaskInternal task) {
- this.task = task;
- }
-
- public Object invoke(Invocation invocation) throws Throwable {
- executedTasks.add(task);
- return null;
- }
-
- public void describeTo(Description description) {
- description.appendText("execute task");
- }
- }
-
- private static class DirectCacheAccess implements TaskArtifactStateCacheAccess {
- public void useCache(String operationDisplayName, Runnable action) {
- action.run();
- }
-
- public void longRunningOperation(String operationDisplayName, Runnable action) {
- action.run();
- }
-
- public <K, V> PersistentIndexedCache createCache(String cacheName, Class<K> keyType, Class<V> valueType) {
- throw new UnsupportedOperationException();
- }
-
- public <T> T useCache(String operationDisplayName, Factory<? extends T> action) {
- throw new UnsupportedOperationException();
- }
-
- public <K, V> PersistentIndexedCache<K, V> createCache(String cacheName, Class<K> keyType, Class<V> valueType, Serializer<V> valueSerializer) {
- throw new UnsupportedOperationException();
- }
- }
}
diff --git a/subprojects/core/src/test/groovy/org/gradle/execution/taskgraph/DefaultTaskGraphExecuterTest.java b/subprojects/core/src/test/groovy/org/gradle/execution/taskgraph/DefaultTaskGraphExecuterTest.java
index 291bf8d..b673c42 100644
--- a/subprojects/core/src/test/groovy/org/gradle/execution/taskgraph/DefaultTaskGraphExecuterTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/execution/taskgraph/DefaultTaskGraphExecuterTest.java
@@ -22,8 +22,9 @@ import org.gradle.api.Task;
import org.gradle.api.execution.TaskExecutionGraphListener;
import org.gradle.api.execution.TaskExecutionListener;
import org.gradle.api.internal.TaskInternal;
-import org.gradle.api.internal.changedetection.TaskArtifactStateCacheAccess;
+import org.gradle.api.internal.changedetection.state.TaskArtifactStateCacheAccess;
import org.gradle.api.internal.project.ProjectInternal;
+import org.gradle.api.internal.tasks.DefaultTaskDependency;
import org.gradle.api.internal.tasks.TaskStateInternal;
import org.gradle.api.specs.Spec;
import org.gradle.api.tasks.TaskDependency;
@@ -41,6 +42,7 @@ import org.jmock.Expectations;
import org.jmock.api.Invocation;
import org.jmock.integration.junit4.JMock;
import org.jmock.integration.junit4.JUnit4Mockery;
+import org.jmock.lib.action.CustomAction;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -48,21 +50,18 @@ import org.junit.runner.RunWith;
import java.util.ArrayList;
import java.util.List;
-import static org.gradle.util.HelperUtil.createRootProject;
-import static org.gradle.util.HelperUtil.toClosure;
+import static org.gradle.util.TestUtil.createRootProject;
+import static org.gradle.util.TestUtil.toClosure;
import static org.gradle.util.WrapUtil.toList;
import static org.gradle.util.WrapUtil.toSet;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
-/**
- * @author Hans Dockter
- */
@RunWith(JMock.class)
public class DefaultTaskGraphExecuterTest {
-
- JUnit4Mockery context = new JUnit4GroovyMockery();
- private final ListenerManager listenerManager = context.mock(ListenerManager.class);
+ final JUnit4Mockery context = new JUnit4GroovyMockery();
+ final ListenerManager listenerManager = context.mock(ListenerManager.class);
+ final TaskArtifactStateCacheAccess taskArtifactStateCacheAccess = context.mock(TaskArtifactStateCacheAccess.class);
DefaultTaskGraphExecuter taskExecuter;
ProjectInternal root;
List<Task> executedTasks = new ArrayList<Task>();
@@ -75,8 +74,16 @@ public class DefaultTaskGraphExecuterTest {
will(returnValue(new ListenerBroadcast<TaskExecutionGraphListener>(TaskExecutionGraphListener.class)));
one(listenerManager).createAnonymousBroadcaster(TaskExecutionListener.class);
will(returnValue(new ListenerBroadcast<TaskExecutionListener>(TaskExecutionListener.class)));
+ allowing(taskArtifactStateCacheAccess).longRunningOperation(with(notNullValue(String.class)), with(notNullValue(Runnable.class)));
+ will(new CustomAction("run action") {
+ public Object invoke(Invocation invocation) throws Throwable {
+ Runnable action = (Runnable) invocation.getParameter(1);
+ action.run();
+ return null;
+ }
+ });
}});
- taskExecuter = new org.gradle.execution.taskgraph.DefaultTaskGraphExecuter(listenerManager, new DefaultTaskPlanExecutor());
+ taskExecuter = new DefaultTaskGraphExecuter(listenerManager, new DefaultTaskPlanExecutor(taskArtifactStateCacheAccess));
}
@Test
@@ -244,8 +251,9 @@ public class DefaultTaskGraphExecuterTest {
Task c = task("c", b);
dependsOn(a, c);
+ taskExecuter.addTasks(toList(c));
try {
- taskExecuter.addTasks(toList(c));
+ taskExecuter.execute();
fail();
} catch (CircularReferenceException e) {
// Expected
@@ -524,6 +532,12 @@ public class DefaultTaskGraphExecuterTest {
will(returnValue(":" + name));
allowing(task).getState();
will(returnValue(state));
+ allowing(task).getMustRunAfter();
+ will(returnValue(new DefaultTaskDependency()));
+ allowing(task).getFinalizedBy();
+ will(returnValue(new DefaultTaskDependency()));
+ allowing(task).getDidWork();
+ will(returnValue(true));
allowing(task).compareTo(with(notNullValue(TaskInternal.class)));
will(new org.jmock.api.Action() {
public Object invoke(Invocation invocation) throws Throwable {
diff --git a/subprojects/core/src/test/groovy/org/gradle/execution/taskgraph/ParallelTaskExecutionPlanTest.groovy b/subprojects/core/src/test/groovy/org/gradle/execution/taskgraph/ParallelTaskExecutionPlanTest.groovy
deleted file mode 100644
index afcb0ee..0000000
--- a/subprojects/core/src/test/groovy/org/gradle/execution/taskgraph/ParallelTaskExecutionPlanTest.groovy
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2013 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.execution.taskgraph;
-
-
-public class ParallelTaskExecutionPlanTest extends DefaultTaskExecutionPlanTest {
-
- protected TaskInfo getTaskToExecute() {
- executionPlan.getTaskToExecute()
- }
-}
-
diff --git a/subprojects/core/src/test/groovy/org/gradle/execution/taskgraph/TaskDependencyGraphTest.groovy b/subprojects/core/src/test/groovy/org/gradle/execution/taskgraph/TaskDependencyGraphTest.groovy
new file mode 100644
index 0000000..9f3c713
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/execution/taskgraph/TaskDependencyGraphTest.groovy
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.execution.taskgraph
+
+import org.gradle.api.internal.TaskInternal
+import spock.lang.Specification
+
+class TaskDependencyGraphTest extends Specification {
+ def graph = new TaskDependencyGraph()
+ def a = task('a')
+ def b = task('b')
+ def c = task('c')
+ def d = task('d')
+ def e = task('e')
+
+ private TaskInternal task(String name) {
+ Mock(TaskInternal) {
+ getName() >> name
+ compareTo(_) >> { args -> name.compareTo(args[0].name)}
+ }
+ }
+
+ void 'can create a node for a task'() {
+ when:
+ def node = graph.addNode(a)
+
+ then:
+ !node.inKnownState
+ node.hardPredecessors.empty
+ node.softSuccessors.empty
+ node.hardSuccessors.empty
+ node.finalizers.empty
+ }
+
+ void 'caches node for a given task'() {
+ when:
+ def node = graph.addNode(a)
+
+ then:
+ graph.getNode(a).is(node)
+ graph.addNode(a).is(node)
+ }
+
+ void 'can add multiple nodes'() {
+ when:
+ graph.addNode(a)
+ graph.addNode(b)
+
+ then:
+ graph.tasks == [a, b] as Set
+ }
+
+ void 'clear'() {
+ when:
+ graph.addNode(a)
+ graph.addNode(b)
+ graph.addNode(c)
+ graph.clear()
+
+ then:
+ !graph.tasks
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/execution/taskgraph/TaskPlanExecutorFactoryTest.groovy b/subprojects/core/src/test/groovy/org/gradle/execution/taskgraph/TaskPlanExecutorFactoryTest.groovy
index f7a921a..67cdb5c 100644
--- a/subprojects/core/src/test/groovy/org/gradle/execution/taskgraph/TaskPlanExecutorFactoryTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/execution/taskgraph/TaskPlanExecutorFactoryTest.groovy
@@ -17,7 +17,7 @@
package org.gradle.execution.taskgraph;
-import org.gradle.api.internal.changedetection.TaskArtifactStateCacheAccess
+import org.gradle.api.internal.changedetection.state.TaskArtifactStateCacheAccess
import spock.lang.Specification
public class TaskPlanExecutorFactoryTest extends Specification {
diff --git a/subprojects/core/src/test/groovy/org/gradle/execution/taskpath/ProjectFinderByTaskPathTest.groovy b/subprojects/core/src/test/groovy/org/gradle/execution/taskpath/ProjectFinderByTaskPathTest.groovy
index 2120e88..eef22f6 100644
--- a/subprojects/core/src/test/groovy/org/gradle/execution/taskpath/ProjectFinderByTaskPathTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/execution/taskpath/ProjectFinderByTaskPathTest.groovy
@@ -17,20 +17,17 @@
package org.gradle.execution.taskpath
import org.gradle.api.internal.project.DefaultProject
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 1/8/13
- */
class ProjectFinderByTaskPathTest extends Specification {
def finder = new ProjectFinderByTaskPath()
//root->foo->bar
- DefaultProject root = HelperUtil.createRootProject()
- DefaultProject foo = HelperUtil.createChildProject(root, "foo")
- DefaultProject bar = HelperUtil.createChildProject(foo, "bar")
+ DefaultProject root = TestUtil.createRootProject()
+ DefaultProject foo = TestUtil.createChildProject(root, "foo")
+ DefaultProject bar = TestUtil.createChildProject(foo, "bar")
def "finds root"() {
expect:
diff --git a/subprojects/core/src/test/groovy/org/gradle/execution/taskpath/ResolvedTaskPathTest.groovy b/subprojects/core/src/test/groovy/org/gradle/execution/taskpath/ResolvedTaskPathTest.groovy
index 6b65fa9..af61b10 100644
--- a/subprojects/core/src/test/groovy/org/gradle/execution/taskpath/ResolvedTaskPathTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/execution/taskpath/ResolvedTaskPathTest.groovy
@@ -19,9 +19,6 @@ package org.gradle.execution.taskpath
import org.gradle.api.internal.project.ProjectInternal
import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 1/29/13
- */
class ResolvedTaskPathTest extends Specification {
def "knows if path is qualified"() {
diff --git a/subprojects/core/src/test/groovy/org/gradle/execution/taskpath/TaskPathResolverTest.groovy b/subprojects/core/src/test/groovy/org/gradle/execution/taskpath/TaskPathResolverTest.groovy
index c2acb52..5628a0c 100644
--- a/subprojects/core/src/test/groovy/org/gradle/execution/taskpath/TaskPathResolverTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/execution/taskpath/TaskPathResolverTest.groovy
@@ -19,9 +19,6 @@ package org.gradle.execution.taskpath
import org.gradle.api.internal.project.ProjectInternal
import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 1/29/13
- */
class TaskPathResolverTest extends Specification {
private finder = Mock(ProjectFinderByTaskPath)
diff --git a/subprojects/core/src/test/groovy/org/gradle/groovy/scripts/DefaultScriptTest.groovy b/subprojects/core/src/test/groovy/org/gradle/groovy/scripts/DefaultScriptTest.groovy
index 0a32cd1..fe64d3e 100644
--- a/subprojects/core/src/test/groovy/org/gradle/groovy/scripts/DefaultScriptTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/groovy/scripts/DefaultScriptTest.groovy
@@ -21,19 +21,18 @@ package org.gradle.groovy.scripts
import org.codehaus.groovy.control.CompilerConfiguration
import org.gradle.api.initialization.dsl.ScriptHandler
import org.gradle.api.internal.project.DefaultProject
-import org.gradle.internal.service.ServiceRegistry
import org.gradle.api.logging.LoggingManager
+import org.gradle.internal.reflect.Instantiator
+import org.gradle.internal.service.ServiceRegistry
import org.gradle.logging.StandardOutputCapture
-import org.gradle.util.HelperUtil
import org.gradle.util.JUnit4GroovyMockery
+import org.gradle.util.TestUtil
import org.jmock.integration.junit4.JMock
import org.junit.Test
import org.junit.runner.RunWith
-import static org.junit.Assert.*
-/**
- * @author Hans Dockter
- */
+import static org.junit.Assert.assertEquals
+
@RunWith(JMock)
class DefaultScriptTest {
private final JUnit4GroovyMockery context = new JUnit4GroovyMockery()
@@ -47,10 +46,12 @@ class DefaultScriptTest {
will(returnValue(context.mock(StandardOutputCapture.class)))
allowing(serviceRegistryMock).get(LoggingManager.class)
will(returnValue(context.mock(LoggingManager.class)))
+ allowing(serviceRegistryMock).get(Instantiator)
+ will(returnValue(context.mock(Instantiator)))
}
DefaultScript script = new GroovyShell(createBaseCompilerConfiguration()).parse(testScriptText)
- DefaultProject testProject = HelperUtil.createRootProject()
+ DefaultProject testProject = TestUtil.createRootProject()
testProject.custom = 'true'
script.setScriptSource(new StringScriptSource('script', '//'))
script.init(testProject, serviceRegistryMock)
diff --git a/subprojects/core/src/test/groovy/org/gradle/groovy/scripts/EmptyScript.java b/subprojects/core/src/test/groovy/org/gradle/groovy/scripts/EmptyScript.java
index 17a7b8e..d314f2d 100644
--- a/subprojects/core/src/test/groovy/org/gradle/groovy/scripts/EmptyScript.java
+++ b/subprojects/core/src/test/groovy/org/gradle/groovy/scripts/EmptyScript.java
@@ -15,9 +15,6 @@
*/
package org.gradle.groovy.scripts;
-/**
- * @author Hans Dockter
- */
public class EmptyScript extends groovy.lang.Script {
public Object run() {
return null;
diff --git a/subprojects/core/src/test/groovy/org/gradle/groovy/scripts/internal/DefaultScriptCompilationHandlerTest.java b/subprojects/core/src/test/groovy/org/gradle/groovy/scripts/internal/DefaultScriptCompilationHandlerTest.java
index d960ced..3ced662 100644
--- a/subprojects/core/src/test/groovy/org/gradle/groovy/scripts/internal/DefaultScriptCompilationHandlerTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/groovy/scripts/internal/DefaultScriptCompilationHandlerTest.java
@@ -50,9 +50,6 @@ import static org.gradle.util.Matchers.isA;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
-/**
- * @author Hans Dockter
- */
@RunWith(JMock.class)
public class DefaultScriptCompilationHandlerTest {
diff --git a/subprojects/core/src/test/groovy/org/gradle/initialization/BuildFileProjectSpecTest.java b/subprojects/core/src/test/groovy/org/gradle/initialization/BuildFileProjectSpecTest.java
index 69ce214..3ce9934 100644
--- a/subprojects/core/src/test/groovy/org/gradle/initialization/BuildFileProjectSpecTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/initialization/BuildFileProjectSpecTest.java
@@ -16,7 +16,7 @@
package org.gradle.initialization;
import org.gradle.api.InvalidUserDataException;
-import org.gradle.api.internal.project.IProjectRegistry;
+import org.gradle.api.internal.project.ProjectRegistry;
import org.gradle.api.internal.project.ProjectIdentifier;
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider;
import org.jmock.Expectations;
@@ -100,8 +100,8 @@ public class BuildFileProjectSpecTest {
}
}
- private IProjectRegistry<ProjectIdentifier> registry(final ProjectIdentifier... projects) {
- final IProjectRegistry<ProjectIdentifier> registry = context.mock(IProjectRegistry.class, String.valueOf(counter++));
+ private ProjectRegistry<ProjectIdentifier> registry(final ProjectIdentifier... projects) {
+ final ProjectRegistry<ProjectIdentifier> registry = context.mock(ProjectRegistry.class, String.valueOf(counter++));
context.checking(new Expectations(){{
allowing(registry).getAllProjects();
will(returnValue(toSet(projects)));
diff --git a/subprojects/core/src/test/groovy/org/gradle/initialization/BuildLayoutParametersTest.groovy b/subprojects/core/src/test/groovy/org/gradle/initialization/BuildLayoutParametersTest.groovy
new file mode 100644
index 0000000..4954dc8
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/initialization/BuildLayoutParametersTest.groovy
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.initialization
+
+import org.gradle.StartParameter
+import org.gradle.internal.SystemProperties
+import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
+import org.gradle.util.SetSystemProperties
+import org.junit.Rule
+import spock.lang.Specification
+
+import static org.gradle.util.GFileUtils.canonicalise
+
+class BuildLayoutParametersTest extends Specification {
+
+ @Rule SetSystemProperties props = new SetSystemProperties()
+ @Rule TestNameTestDirectoryProvider temp = new TestNameTestDirectoryProvider()
+
+ def "has reasonable defaults"() {
+ expect:
+ def params = new BuildLayoutParameters()
+ params.searchUpwards
+ params.gradleUserHomeDir == canonicalise(StartParameter.DEFAULT_GRADLE_USER_HOME)
+ params.projectDir == canonicalise(SystemProperties.getCurrentDir())
+ }
+
+ def "reads gradle user home dir from system property"() {
+ def dir = temp.createDir("someGradleUserHomePath")
+ System.setProperty(StartParameter.GRADLE_USER_HOME_PROPERTY_KEY, dir.absolutePath)
+
+ when:
+ def params = new BuildLayoutParameters()
+
+ then:
+ params.gradleUserHomeDir == dir
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/initialization/BuildSourceBuilderTest.groovy b/subprojects/core/src/test/groovy/org/gradle/initialization/BuildSourceBuilderTest.groovy
deleted file mode 100644
index 8f86e87..0000000
--- a/subprojects/core/src/test/groovy/org/gradle/initialization/BuildSourceBuilderTest.groovy
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.initialization
-
-import org.gradle.BuildResult
-import org.gradle.GradleLauncher
-import org.gradle.StartParameter
-import org.gradle.api.Project
-import org.gradle.api.file.FileCollection
-import org.gradle.api.internal.plugins.EmbeddableJavaProject
-import org.gradle.api.invocation.Gradle
-import org.gradle.api.plugins.Convention
-import org.gradle.cache.CacheBuilder
-import org.gradle.cache.CacheRepository
-import org.gradle.cache.DirectoryCacheBuilder
-import org.gradle.cache.PersistentCache
-import org.gradle.cache.internal.FileLockManager
-import org.gradle.test.fixtures.file.TestFile
-import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
-import org.gradle.util.JUnit4GroovyMockery
-import org.jmock.api.Action
-import org.junit.runner.RunWith
-import org.junit.*
-
-import static org.hamcrest.Matchers.*
-import static org.junit.Assert.assertEquals
-
-/**
- * @author Hans Dockter
- */
- at RunWith(org.jmock.integration.junit4.JMock)
- at Ignore //TODO SF spockify
-class BuildSourceBuilderTest {
- @Rule public TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider();
- JUnit4GroovyMockery context = new JUnit4GroovyMockery()
- BuildSourceBuilder buildSourceBuilder
- GradleLauncherFactory gradleFactoryMock = context.mock(GradleLauncherFactory.class)
- GradleLauncher gradleMock = context.mock(GradleLauncher.class)
- Project rootProjectMock = context.mock(Project.class)
- FileCollection configurationMock = context.mock(FileCollection.class)
- TestFile rootDir = tmpDir.createDir('root')
- TestFile testBuildSrcDir = rootDir.file('buildSrc').createDir()
- TestFile buildSrcCache = testBuildSrcDir.createDir(".gradle/noVersion/buildSrc");
- List testDependencies
- StartParameter expectedStartParameter
- CacheRepository cacheRepository = context.mock(CacheRepository.class)
- PersistentCache persistentCache = context.mock(PersistentCache.class)
- BuildResult expectedBuildResult
- Gradle build = context.mock(Gradle.class)
- EmbeddableJavaProject projectMetaInfo = context.mock(EmbeddableJavaProject.class)
-
- @Before public void setUp() {
- buildSourceBuilder = new BuildSourceBuilder(gradleFactoryMock, context.mock(ClassLoaderRegistry.class), cacheRepository)
- expectedStartParameter = new StartParameter(currentDir: testBuildSrcDir)
- testDependencies = ['dep1' as File, 'dep2' as File]
-
- Convention convention = context.mock(Convention)
- context.checking {
- allowing(build).getRootProject(); will(returnValue(rootProjectMock))
- allowing(build).getStartParameter(); will(returnValue(expectedStartParameter))
- allowing(rootProjectMock).getConvention(); will(returnValue(convention))
- allowing(convention).getPlugin(EmbeddableJavaProject);
- will(returnValue(projectMetaInfo))
- allowing(projectMetaInfo).getRuntimeClasspath(); will(returnValue(configurationMock))
- allowing(configurationMock).getFiles(); will(returnValue(testDependencies as Set))
- }
- expectedBuildResult = new BuildResult(build, null)
- }
-
- @Test public void testCreateClasspathWhenBuildSrcDirExistsAndHasNotBeenBuiltBefore() {
- expectMarkerFileFetchedFromCache(false)
- context.checking {
- one(projectMetaInfo).getRebuildTasks(); will(returnValue(['clean', 'build']))
- one(gradleFactoryMock).newInstance((StartParameter) withParam(notNullValue()));
- will(returnValue(gradleMock))
- one(gradleMock).addListener(withParam(not(nullValue()))); will(notifyProjectsEvaluated())
- one(gradleMock).run(); will(returnValue(expectedBuildResult))
- }
- expectMarkerFileInCache()
-
- createBuildFile()
- def actualClasspath = buildSourceBuilder.createBuildSourceClasspath(expectedStartParameter).asFiles
- assertEquals(testDependencies, actualClasspath)
- }
-
- @Test public void testCreateClasspathWhenBuildSrcDirExistsAndHasBeenBuiltBefore() {
- expectMarkerFileFetchedFromCache(true)
- context.checking {
- one(projectMetaInfo).getBuildTasks(); will(returnValue(['build']))
- one(gradleFactoryMock).newInstance((StartParameter) withParam(notNullValue()))
- will(returnValue(gradleMock))
- one(gradleMock).addListener(withParam(not(nullValue()))); will(notifyProjectsEvaluated())
- one(gradleMock).run(); will(returnValue(expectedBuildResult))
- }
- expectMarkerFileInCache()
-
- def actualClasspath = buildSourceBuilder.createBuildSourceClasspath(expectedStartParameter).asFiles
- assertEquals(testDependencies, actualClasspath)
- }
-
- @Test public void testCreateClasspathWhenBuildSrcDirDoesNotExist() {
- expectedStartParameter = expectedStartParameter.newInstance()
- expectedStartParameter.setCurrentDir(new File('nonexisting'));
- assertEquals([], buildSourceBuilder.createBuildSourceClasspath(expectedStartParameter).asFiles)
- }
-
- private expectMarkerFileFetchedFromCache(boolean markerFileExists) {
- if (markerFileExists) {
- buildSrcCache.createFile("built.bin");
- } else {
- new File(buildSrcCache, "built.bin").delete()
- }
- context.checking {
- DirectoryCacheBuilder builder = context.mock(DirectoryCacheBuilder.class)
- one(cacheRepository).cache('buildSrc')
- will(returnValue(builder))
-
- one(builder).forObject(testBuildSrcDir)
- will(returnValue(builder))
-
- one(builder).withLockMode(FileLockManager.LockMode.None)
- will(returnValue(builder))
-
- one(builder).withVersionStrategy(CacheBuilder.VersionStrategy.SharedCacheInvalidateOnVersionChange)
- will(returnValue(builder))
-
- one(builder).open()
- will(returnValue(persistentCache))
-
- one(persistentCache).getBaseDir()
- will(returnValue(buildSrcCache))
- one(persistentCache).useCache(withParam(equalTo("rebuild buildSrc")), (org.gradle.internal.Factory) withParam(any(org.gradle.internal.Factory.class)))
- will(executeBuildSrcBuild())
- }
- }
-
- private expectMarkerFileInCache() {
- buildSrcCache.file("buildSrc.lock").exists()
- }
-
- private createBuildFile() {
- new File(testBuildSrcDir, Project.DEFAULT_BUILD_FILE).createNewFile()
- }
-
- private Action executeBuildSrcBuild() {
- return [invoke: {invocation -> invocation.getParameter(1).create()},
- describeTo: {description -> }] as Action
- }
-
- private Action notifyProjectsEvaluated() {
- return [invoke: {invocation -> invocation.getParameter(0).projectsEvaluated(build)},
- describeTo: {description -> }] as Action
- }
-
- @After public void cleanup() {
- buildSrcCache.file("buildSrc.lock").delete()
- }
-}
diff --git a/subprojects/core/src/test/groovy/org/gradle/initialization/DefaultCommandLineConverterTest.java b/subprojects/core/src/test/groovy/org/gradle/initialization/DefaultCommandLineConverterTest.java
index 553cc21..231e265 100644
--- a/subprojects/core/src/test/groovy/org/gradle/initialization/DefaultCommandLineConverterTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/initialization/DefaultCommandLineConverterTest.java
@@ -37,9 +37,6 @@ import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
-/**
- * @author Hans Dockter
- */
public class DefaultCommandLineConverterTest {
@Rule
public TestNameTestDirectoryProvider testDir = new TestNameTestDirectoryProvider();
diff --git a/subprojects/core/src/test/groovy/org/gradle/initialization/DefaultGradleLauncherFactoryTest.groovy b/subprojects/core/src/test/groovy/org/gradle/initialization/DefaultGradleLauncherFactoryTest.groovy
index 0a4f694..001d241 100644
--- a/subprojects/core/src/test/groovy/org/gradle/initialization/DefaultGradleLauncherFactoryTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/initialization/DefaultGradleLauncherFactoryTest.groovy
@@ -17,12 +17,15 @@ package org.gradle.initialization
import org.gradle.GradleLauncher
import org.gradle.StartParameter
+import org.gradle.internal.service.scopes.GlobalScopeServices
import org.gradle.cli.CommandLineConverter
+import org.gradle.internal.service.ServiceRegistry
import spock.lang.Specification
class DefaultGradleLauncherFactoryTest extends Specification {
final CommandLineConverter<StartParameter> parameterConverter = Mock()
- final DefaultGradleLauncherFactory factory = new DefaultGradleLauncherFactory();
+ final ServiceRegistry sharedServices = new GlobalScopeServices()
+ final DefaultGradleLauncherFactory factory = new DefaultGradleLauncherFactory(sharedServices)
def setup() {
factory.setCommandLineConverter(parameterConverter);
diff --git a/subprojects/core/src/test/groovy/org/gradle/initialization/DefaultGradleLauncherTest.java b/subprojects/core/src/test/groovy/org/gradle/initialization/DefaultGradleLauncherTest.java
index 3e42d2b..09edbe7 100644
--- a/subprojects/core/src/test/groovy/org/gradle/initialization/DefaultGradleLauncherTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/initialization/DefaultGradleLauncherTest.java
@@ -24,13 +24,15 @@ import org.gradle.api.initialization.ProjectDescriptor;
import org.gradle.api.internal.ExceptionAnalyser;
import org.gradle.api.internal.GradleInternal;
import org.gradle.api.internal.SettingsInternal;
+import org.gradle.api.internal.file.BaseDirFileResolver;
import org.gradle.api.internal.project.DefaultProject;
import org.gradle.configuration.BuildConfigurer;
import org.gradle.execution.BuildExecuter;
import org.gradle.execution.TaskGraphExecuter;
+import org.gradle.internal.nativeplatform.filesystem.FileSystems;
import org.gradle.logging.LoggingManagerInternal;
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider;
-import org.gradle.util.HelperUtil;
+import org.gradle.util.TestUtil;
import org.gradle.util.JUnit4GroovyMockery;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
@@ -47,9 +49,6 @@ import java.io.File;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertThat;
-/**
- * @author Hans Dockter
- */
@RunWith(org.jmock.integration.junit4.JMock.class)
public class DefaultGradleLauncherTest {
private BuildLoader buildLoaderMock;
@@ -96,9 +95,10 @@ public class DefaultGradleLauncherTest {
File expectedRootDir = tmpDir.file("rootDir");
File expectedCurrentDir = new File(expectedRootDir, "currentDir");
- expectedRootProjectDescriptor = new DefaultProjectDescriptor(null, "someName", new File("somedir"), new DefaultProjectDescriptorRegistry());
- expectedRootProject = HelperUtil.createRootProject(expectedRootDir);
- expectedCurrentProject = HelperUtil.createRootProject(expectedCurrentDir);
+ expectedRootProjectDescriptor = new DefaultProjectDescriptor(null, "someName", new File("somedir"), new DefaultProjectDescriptorRegistry(),
+ new BaseDirFileResolver(FileSystems.getDefault(), expectedRootDir));
+ expectedRootProject = TestUtil.createRootProject(expectedRootDir);
+ expectedCurrentProject = TestUtil.createRootProject(expectedCurrentDir);
expectedStartParams = new StartParameter();
expectedStartParams.setCurrentDir(expectedCurrentDir);
diff --git a/subprojects/core/src/test/groovy/org/gradle/initialization/DefaultGradlePropertiesLoaderTest.java b/subprojects/core/src/test/groovy/org/gradle/initialization/DefaultGradlePropertiesLoaderTest.java
index bc19764..0401418 100644
--- a/subprojects/core/src/test/groovy/org/gradle/initialization/DefaultGradlePropertiesLoaderTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/initialization/DefaultGradlePropertiesLoaderTest.java
@@ -32,9 +32,6 @@ import java.util.Properties;
import static org.junit.Assert.*;
-/**
- * @author Hans Dockter
- */
public class DefaultGradlePropertiesLoaderTest {
private DefaultGradlePropertiesLoader gradlePropertiesLoader;
private File gradleUserHomeDir;
diff --git a/subprojects/core/src/test/groovy/org/gradle/initialization/DefaultProjectDescriptorRegistryTest.java b/subprojects/core/src/test/groovy/org/gradle/initialization/DefaultProjectDescriptorRegistryTest.java
index c5f6a32..6755bd4 100644
--- a/subprojects/core/src/test/groovy/org/gradle/initialization/DefaultProjectDescriptorRegistryTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/initialization/DefaultProjectDescriptorRegistryTest.java
@@ -15,25 +15,28 @@
*/
package org.gradle.initialization;
+import org.gradle.api.internal.file.BaseDirFileResolver;
+import org.gradle.api.internal.file.FileResolver;
+import org.gradle.internal.nativeplatform.filesystem.FileSystems;
import org.gradle.util.Path;
import org.junit.Test;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.*;
-import static org.hamcrest.Matchers.*;
import java.io.File;
-/**
- * @author Hans Dockter
- */
+import static org.hamcrest.Matchers.nullValue;
+import static org.hamcrest.Matchers.sameInstance;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertThat;
+
public class DefaultProjectDescriptorRegistryTest {
private static final File TEST_DIR = new File("testDir");
+ private static final FileResolver FILE_RESOLVER = new BaseDirFileResolver(FileSystems.getDefault(), TEST_DIR.getAbsoluteFile());
private final DefaultProjectDescriptorRegistry registry = new DefaultProjectDescriptorRegistry();
@Test
public void addProjectDescriptor() {
- DefaultProjectDescriptor rootProject = new DefaultProjectDescriptor(null, "testName", TEST_DIR, registry);
+ DefaultProjectDescriptor rootProject = new DefaultProjectDescriptor(null, "testName", TEST_DIR, registry, FILE_RESOLVER);
registry.addProject(rootProject);
assertSame(rootProject, registry.getProject(rootProject.getPath()));
@@ -42,7 +45,7 @@ public class DefaultProjectDescriptorRegistryTest {
@Test
public void changeProjectDescriptorPath() {
- DefaultProjectDescriptor project = new DefaultProjectDescriptor(null, "name", TEST_DIR, registry);
+ DefaultProjectDescriptor project = new DefaultProjectDescriptor(null, "name", TEST_DIR, registry, FILE_RESOLVER);
registry.addProject(project);
registry.changeDescriptorPath(Path.path(":"), Path.path(":newPath"));
diff --git a/subprojects/core/src/test/groovy/org/gradle/initialization/DefaultProjectDescriptorTest.java b/subprojects/core/src/test/groovy/org/gradle/initialization/DefaultProjectDescriptorTest.java
index 54c121d..d8b47c6 100644
--- a/subprojects/core/src/test/groovy/org/gradle/initialization/DefaultProjectDescriptorTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/initialization/DefaultProjectDescriptorTest.java
@@ -15,29 +15,30 @@
*/
package org.gradle.initialization;
+import org.gradle.api.Project;
+import org.gradle.api.internal.file.BaseDirFileResolver;
+import org.gradle.api.internal.file.FileResolver;
+import org.gradle.internal.nativeplatform.filesystem.FileSystems;
+import org.gradle.internal.os.OperatingSystem;
import org.gradle.util.Path;
+import org.jmock.Expectations;
+import org.jmock.integration.junit4.JUnit4Mockery;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import org.gradle.api.Project;
-import org.jmock.integration.junit4.JUnit4Mockery;
-import org.jmock.Expectations;
import java.io.File;
import java.io.IOException;
-/**
- * @author Hans Dockter
- */
+import static org.junit.Assert.*;
+
@RunWith(org.jmock.integration.junit4.JMock.class)
public class DefaultProjectDescriptorTest {
private DefaultProjectDescriptor projectDescriptor;
private DefaultProjectDescriptor parentProjectDescriptor;
private static final String TEST_NAME = "testName";
private static final File TEST_DIR = new File("testDir");
+ private static final FileResolver FILE_RESOLVER = new BaseDirFileResolver(FileSystems.getDefault(), TEST_DIR.getAbsoluteFile());
private DefaultProjectDescriptorRegistry testProjectDescriptorRegistry;
private JUnit4Mockery context = new JUnit4Mockery();
@@ -45,9 +46,9 @@ public class DefaultProjectDescriptorTest {
public void setUp() {
testProjectDescriptorRegistry = new DefaultProjectDescriptorRegistry();
parentProjectDescriptor = new DefaultProjectDescriptor(null, "somename", new File("somefile"),
- testProjectDescriptorRegistry);
+ testProjectDescriptorRegistry, FILE_RESOLVER);
projectDescriptor = new DefaultProjectDescriptor(parentProjectDescriptor, TEST_NAME, TEST_DIR,
- testProjectDescriptorRegistry);
+ testProjectDescriptorRegistry, FILE_RESOLVER);
}
@Test
@@ -70,7 +71,7 @@ public class DefaultProjectDescriptorTest {
@Test
public void setName() {
final String newName = "newName";
- final IProjectDescriptorRegistry projectDescriptorRegistryMock = context.mock(IProjectDescriptorRegistry.class);
+ final ProjectDescriptorRegistry projectDescriptorRegistryMock = context.mock(ProjectDescriptorRegistry.class);
projectDescriptor.setProjectDescriptorRegistry(projectDescriptorRegistryMock);
context.checking(new Expectations() {{
one(projectDescriptorRegistryMock).changeDescriptorPath(Path.path(TEST_NAME), Path.path(Project.PATH_SEPARATOR + newName));
@@ -80,6 +81,24 @@ public class DefaultProjectDescriptorTest {
}
@Test
+ public void setProjectDirRelative() {
+ final ProjectDescriptorRegistry projectDescriptorRegistryMock = context.mock(ProjectDescriptorRegistry.class);
+ projectDescriptor.setProjectDescriptorRegistry(projectDescriptorRegistryMock);
+ projectDescriptor.setProjectDir(new File("relative/path"));
+ final String expectedPath = new File(TEST_DIR, "relative/path").getAbsolutePath();
+ assertEquals(expectedPath, projectDescriptor.getProjectDir().getAbsolutePath());
+ }
+
+ @Test
+ public void setProjectDirAbsolute() {
+ final ProjectDescriptorRegistry projectDescriptorRegistryMock = context.mock(ProjectDescriptorRegistry.class);
+ projectDescriptor.setProjectDescriptorRegistry(projectDescriptorRegistryMock);
+ String absolutePath = OperatingSystem.current().isWindows() ? "C:\\absolute\\path" : "/absolute/path";
+ projectDescriptor.setProjectDir(new File(absolutePath));
+ assertEquals(absolutePath, projectDescriptor.getProjectDir().getAbsolutePath());
+ }
+
+ @Test
public void buildFileIsBuiltFromBuildFileNameAndProjectDir() throws IOException {
projectDescriptor.setBuildFileName("project.gradle");
assertEquals(new File(TEST_DIR, "project.gradle").getCanonicalFile(), projectDescriptor.getBuildFile());
diff --git a/subprojects/core/src/test/groovy/org/gradle/initialization/DefaultSettingsTest.groovy b/subprojects/core/src/test/groovy/org/gradle/initialization/DefaultSettingsTest.groovy
index ff540a4..cda19f2 100644
--- a/subprojects/core/src/test/groovy/org/gradle/initialization/DefaultSettingsTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/initialization/DefaultSettingsTest.groovy
@@ -20,21 +20,24 @@ import org.gradle.StartParameter
import org.gradle.api.Project
import org.gradle.api.UnknownProjectException
import org.gradle.api.initialization.ProjectDescriptor
+import org.gradle.api.initialization.Settings
+import org.gradle.api.internal.GradleInternal
+import org.gradle.api.internal.ThreadGlobalInstantiator
+import org.gradle.api.internal.file.FileResolver
+import org.gradle.api.plugins.PluginContainer
+import org.gradle.configuration.ScriptPluginFactory
import org.gradle.groovy.scripts.ScriptSource
+import org.gradle.internal.service.scopes.ServiceRegistryFactory
import org.gradle.util.JUnit4GroovyMockery
import org.jmock.integration.junit4.JMock
import org.jmock.lib.legacy.ClassImposteriser
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+
import static org.junit.Assert.*
-import org.gradle.api.internal.GradleInternal
-import org.gradle.api.internal.ThreadGlobalInstantiator
-/**
- * @author Hans Dockter
- */
- at RunWith (JMock)
+ at RunWith(JMock)
class DefaultSettingsTest {
File settingsDir
StartParameter startParameter
@@ -44,9 +47,14 @@ class DefaultSettingsTest {
GradleInternal gradleMock
DefaultSettings settings
JUnit4GroovyMockery context = new JUnit4GroovyMockery()
- DefaultProjectDescriptorRegistry projectDescriptorRegistry
-
- @Before public void setUp() {
+ ProjectDescriptorRegistry projectDescriptorRegistry
+ ServiceRegistryFactory serviceRegistryFactory
+ PluginContainer pluginContainer
+ FileResolver fileResolver
+ ScriptPluginFactory scriptPluginFactory;
+
+ @Before
+ public void setUp() {
context.setImposteriser(ClassImposteriser.INSTANCE)
settingsDir = new File('/somepath/root').absoluteFile
gradleProperties = [someGradleProp: 'someValue']
@@ -55,14 +63,32 @@ class DefaultSettingsTest {
scriptSourceMock = context.mock(ScriptSource)
gradleMock = context.mock(GradleInternal)
-
+ serviceRegistryFactory = context.mock(ServiceRegistryFactory.class)
+ pluginContainer = context.mock(PluginContainer.class)
+ scriptPluginFactory = context.mock(ScriptPluginFactory.class)
+ fileResolver = context.mock(FileResolver.class)
projectDescriptorRegistry = new DefaultProjectDescriptorRegistry()
- settings = ThreadGlobalInstantiator.orCreate.newInstance(DefaultSettings,
- gradleMock, projectDescriptorRegistry, expectedClassLoader, settingsDir, scriptSourceMock, startParameter
- )
- }
- @Test public void testSettings() {
+ ServiceRegistryFactory settingsServices = context.mock(ServiceRegistryFactory.class)
+ context.checking{
+ one(serviceRegistryFactory).createFor(with(any(Settings.class)));
+ will(returnValue(settingsServices));
+ one(settingsServices).get(PluginContainer.class);
+ will(returnValue(pluginContainer));
+ one(settingsServices).get(FileResolver.class);
+ will(returnValue(fileResolver));
+ one(settingsServices).get(ScriptPluginFactory.class);
+ will(returnValue(scriptPluginFactory));
+ one(settingsServices).get(ProjectDescriptorRegistry.class);
+ will(returnValue(projectDescriptorRegistry));
+ }
+ settings = ThreadGlobalInstantiator.orCreate.newInstance(DefaultSettings, serviceRegistryFactory,
+ gradleMock, expectedClassLoader, settingsDir, scriptSourceMock, startParameter);
+
+ }
+
+ @Test
+ public void testSettings() {
assert settings.startParameter.is(startParameter)
assertSame(settings, settings.getSettings())
assertEquals(settingsDir, settings.getSettingsDir())
@@ -74,7 +100,8 @@ class DefaultSettingsTest {
assertSame(gradleMock, settings.gradle)
}
- @Test public void testInclude() {
+ @Test
+ public void testInclude() {
ProjectDescriptor rootProjectDescriptor = settings.getRootProject();
String projectA = "a"
String projectB = "b"
@@ -90,7 +117,8 @@ class DefaultSettingsTest {
testDescriptor(settings.project(":$projectB:$projectC"), projectC, new File(settingsDir, "$projectB/$projectC"))
}
- @Test public void testIncludeFlat() {
+ @Test
+ public void testIncludeFlat() {
ProjectDescriptor rootProjectDescriptor = settings.getRootProject();
String projectA = "a"
String projectB = "b"
@@ -106,7 +134,8 @@ class DefaultSettingsTest {
assertEquals(projectDir, descriptor.getProjectDir())
}
- @Test public void testCreateProjectDescriptor() {
+ @Test
+ public void testCreateProjectDescriptor() {
String testName = "testname"
File testDir = new File("testDir")
DefaultProjectDescriptor projectDescriptor = settings.createProjectDescriptor(settings.getRootProject(), testName, testDir)
@@ -116,19 +145,22 @@ class DefaultSettingsTest {
assertEquals(testDir.canonicalFile, projectDescriptor.getProjectDir())
}
- @Test public void testFindDescriptorByPath() {
+ @Test
+ public void testFindDescriptorByPath() {
DefaultProjectDescriptor projectDescriptor = createTestDescriptor();
DefaultProjectDescriptor foundProjectDescriptor = settings.project(projectDescriptor.getPath())
assertSame(foundProjectDescriptor, projectDescriptor)
}
- @Test public void testFindDescriptorByProjectDir() {
+ @Test
+ public void testFindDescriptorByProjectDir() {
DefaultProjectDescriptor projectDescriptor = createTestDescriptor()
DefaultProjectDescriptor foundProjectDescriptor = settings.project(projectDescriptor.getProjectDir())
assertSame(foundProjectDescriptor, projectDescriptor)
}
- @Test (expected = UnknownProjectException) public void testDescriptorByPath() {
+ @Test(expected = UnknownProjectException)
+ public void testDescriptorByPath() {
DefaultProjectDescriptor projectDescriptor = createTestDescriptor()
DefaultProjectDescriptor foundProjectDescriptor = settings.project(projectDescriptor.getPath())
assertSame(foundProjectDescriptor, projectDescriptor)
@@ -136,7 +168,8 @@ class DefaultSettingsTest {
}
- @Test (expected = UnknownProjectException) public void testDescriptorByProjectDir() {
+ @Test(expected = UnknownProjectException)
+ public void testDescriptorByProjectDir() {
DefaultProjectDescriptor projectDescriptor = createTestDescriptor()
DefaultProjectDescriptor foundProjectDescriptor = settings.project(projectDescriptor.getProjectDir())
assertSame(foundProjectDescriptor, projectDescriptor)
@@ -153,27 +186,32 @@ class DefaultSettingsTest {
return [name: 'someName']
}
- @Test public void testCreateClassLoader() {
+ @Test
+ public void testCreateClassLoader() {
StartParameter expectedStartParameter = settings.startParameter.newInstance()
expectedStartParameter.setCurrentDir(new File(settingsDir, DefaultSettings.DEFAULT_BUILD_SRC_DIR))
- URLClassLoader createdClassLoader = settings.getClassLoader()
+ def createdClassLoader = settings.getClassLoader()
assertSame(createdClassLoader, expectedClassLoader)
}
- @Test public void testCanGetAndSetDynamicProperties() {
+ @Test
+ public void testCanGetAndSetDynamicProperties() {
settings.dynamicProp = 'value'
assertEquals('value', settings.dynamicProp)
}
- @Test (expected = MissingPropertyException) public void testPropertyMissing() {
+ @Test(expected = MissingPropertyException)
+ public void testPropertyMissing() {
settings.unknownProp
}
- @Test public void testGetRootDir() {
+ @Test
+ public void testGetRootDir() {
assertEquals(settingsDir, settings.rootDir);
}
- @Test public void testHasUsefulToString() {
+ @Test
+ public void testHasUsefulToString() {
assertEquals('settings \'root\'', settings.toString())
}
}
diff --git a/subprojects/core/src/test/groovy/org/gradle/initialization/InstantiatingBuildLoaderTest.groovy b/subprojects/core/src/test/groovy/org/gradle/initialization/InstantiatingBuildLoaderTest.groovy
index 7a20c8f..4d37b1c 100644
--- a/subprojects/core/src/test/groovy/org/gradle/initialization/InstantiatingBuildLoaderTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/initialization/InstantiatingBuildLoaderTest.groovy
@@ -19,12 +19,14 @@ package org.gradle.initialization
import org.gradle.StartParameter
import org.gradle.api.initialization.ProjectDescriptor
import org.gradle.api.internal.GradleInternal
+import org.gradle.api.internal.file.BaseDirFileResolver
import org.gradle.api.internal.project.DefaultProject
import org.gradle.api.internal.project.IProjectFactory
import org.gradle.api.internal.project.ProjectInternal
+import org.gradle.internal.nativeplatform.filesystem.FileSystems
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
-import org.gradle.util.HelperUtil
import org.gradle.util.JUnit4GroovyMockery
+import org.gradle.util.TestUtil
import org.jmock.integration.junit4.JMock
import org.junit.Before
import org.junit.Rule
@@ -34,9 +36,6 @@ import org.junit.runner.RunWith
import static org.hamcrest.Matchers.*
import static org.junit.Assert.assertThat
-/**
- * @author Hans Dockter
- */
@RunWith(JMock.class)
class InstantiatingBuildLoaderTest {
@@ -45,7 +44,7 @@ class InstantiatingBuildLoaderTest {
File testDir
File rootProjectDir
File childProjectDir
- IProjectDescriptorRegistry projectDescriptorRegistry = new DefaultProjectDescriptorRegistry()
+ ProjectDescriptorRegistry projectDescriptorRegistry = new DefaultProjectDescriptorRegistry()
StartParameter startParameter = new StartParameter()
ProjectDescriptor rootDescriptor
ProjectInternal rootProject
@@ -126,15 +125,15 @@ class InstantiatingBuildLoaderTest {
}
private ProjectDescriptor descriptor(String name, ProjectDescriptor parent, File projectDir) {
- new DefaultProjectDescriptor(parent, name, projectDir, projectDescriptorRegistry)
+ new DefaultProjectDescriptor(parent, name, projectDir, projectDescriptorRegistry, new BaseDirFileResolver(FileSystems.default, rootProjectDir))
}
private ProjectInternal project(ProjectDescriptor descriptor, ProjectInternal parent) {
DefaultProject project
if (parent) {
- project = HelperUtil.createChildProject(parent, descriptor.name, descriptor.projectDir)
+ project = TestUtil.createChildProject(parent, descriptor.name, descriptor.projectDir)
} else {
- project = HelperUtil.createRootProject(descriptor.projectDir)
+ project = TestUtil.createRootProject(descriptor.projectDir)
}
project
}
diff --git a/subprojects/core/src/test/groovy/org/gradle/initialization/LayoutCommandLineConverterTest.groovy b/subprojects/core/src/test/groovy/org/gradle/initialization/LayoutCommandLineConverterTest.groovy
index 8d307e3..367bc65 100644
--- a/subprojects/core/src/test/groovy/org/gradle/initialization/LayoutCommandLineConverterTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/initialization/LayoutCommandLineConverterTest.groovy
@@ -16,14 +16,18 @@
package org.gradle.initialization
+import org.gradle.StartParameter
+import org.gradle.internal.SystemProperties
+import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
+import org.junit.Rule
import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 2/19/13
- */
+import static org.gradle.util.GFileUtils.canonicalise
+
class LayoutCommandLineConverterTest extends Specification {
- def converter = new LayoutCommandLineConverter();
+ def converter = new LayoutCommandLineConverter()
+ @Rule TestNameTestDirectoryProvider temp = new TestNameTestDirectoryProvider()
def convert(String... args) {
converter.convert(Arrays.asList(args))
@@ -31,9 +35,9 @@ class LayoutCommandLineConverterTest extends Specification {
def "has reasonable defaults"() {
expect:
- convert().projectDir
- !convert().gradleUserHomeDir
- convert().searchUpwards == null
+ convert().projectDir == canonicalise(SystemProperties.getCurrentDir())
+ convert().gradleUserHomeDir == canonicalise(StartParameter.DEFAULT_GRADLE_USER_HOME)
+ convert().searchUpwards
}
def "converts"() {
@@ -42,4 +46,31 @@ class LayoutCommandLineConverterTest extends Specification {
convert("-g", "bar").gradleUserHomeDir.name == "bar"
!convert("-u").searchUpwards
}
+
+ def "converts relatively to the target dir"() {
+ given:
+ def root = temp.createDir('root')
+ def target = new BuildLayoutParameters().setProjectDir(root)
+
+ when:
+ converter.convert(['-p', 'projectDir', '-g', 'gradleDir'], target)
+
+ then:
+ target.gradleUserHomeDir == temp.file("root/gradleDir")
+ target.projectDir == temp.file("root/projectDir")
+ }
+
+ def "converts absolute paths"() {
+ given:
+ def root = temp.createDir('root')
+ def other = temp.createDir('other')
+ def target = new BuildLayoutParameters().setProjectDir(root)
+
+ when:
+ converter.convert(['-p', other.file('projectDir').absolutePath, '-g', other.file('gradleDir').absolutePath], target)
+
+ then:
+ target.gradleUserHomeDir == temp.file("other/gradleDir")
+ target.projectDir == temp.file("other/projectDir")
+ }
}
diff --git a/subprojects/core/src/test/groovy/org/gradle/initialization/ProjectDirectoryProjectSpecTest.java b/subprojects/core/src/test/groovy/org/gradle/initialization/ProjectDirectoryProjectSpecTest.java
index d2aae08..d6f2b1e 100644
--- a/subprojects/core/src/test/groovy/org/gradle/initialization/ProjectDirectoryProjectSpecTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/initialization/ProjectDirectoryProjectSpecTest.java
@@ -16,7 +16,7 @@
package org.gradle.initialization;
import org.gradle.api.InvalidUserDataException;
-import org.gradle.api.internal.project.IProjectRegistry;
+import org.gradle.api.internal.project.ProjectRegistry;
import org.gradle.api.internal.project.ProjectIdentifier;
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider;
import org.gradle.util.GFileUtils;
@@ -101,8 +101,8 @@ public class ProjectDirectoryProjectSpecTest {
}
}
- private IProjectRegistry<ProjectIdentifier> registry(final ProjectIdentifier... projects) {
- final IProjectRegistry<ProjectIdentifier> registry = context.mock(IProjectRegistry.class, String.valueOf(counter++));
+ private ProjectRegistry<ProjectIdentifier> registry(final ProjectIdentifier... projects) {
+ final ProjectRegistry<ProjectIdentifier> registry = context.mock(ProjectRegistry.class, String.valueOf(counter++));
context.checking(new Expectations(){{
allowing(registry).getAllProjects();
will(returnValue(toSet(projects)));
diff --git a/subprojects/core/src/test/groovy/org/gradle/initialization/ProjectPropertySettingBuildLoaderTest.groovy b/subprojects/core/src/test/groovy/org/gradle/initialization/ProjectPropertySettingBuildLoaderTest.groovy
index 76a3594..57fcd61 100644
--- a/subprojects/core/src/test/groovy/org/gradle/initialization/ProjectPropertySettingBuildLoaderTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/initialization/ProjectPropertySettingBuildLoaderTest.groovy
@@ -14,12 +14,11 @@
* limitations under the License.
*/
package org.gradle.initialization
-
import org.gradle.api.Project
import org.gradle.api.initialization.ProjectDescriptor
import org.gradle.api.internal.GradleInternal
+import org.gradle.api.internal.plugins.ExtensionContainerInternal
import org.gradle.api.internal.project.ProjectInternal
-import org.gradle.api.plugins.ExtensionContainer
import org.gradle.api.plugins.ExtraPropertiesExtension
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
import org.gradle.util.GUtil
@@ -37,9 +36,9 @@ class ProjectPropertySettingBuildLoaderTest extends Specification {
final File rootProjectDir = tmpDir.createDir('root')
final File childProjectDir = tmpDir.createDir('child')
final ProjectPropertySettingBuildLoader loader = new ProjectPropertySettingBuildLoader(propertiesLoader, target)
- final ExtensionContainer rootExtension = Mock()
+ final ExtensionContainerInternal rootExtension = Mock()
final ExtraPropertiesExtension rootProperties = Mock()
- final ExtensionContainer childExtension = Mock()
+ final ExtensionContainerInternal childExtension = Mock()
final ExtraPropertiesExtension childProperties = Mock()
def setup() {
diff --git a/subprojects/core/src/test/groovy/org/gradle/initialization/ScriptEvaluatingSettingsProcessorTest.groovy b/subprojects/core/src/test/groovy/org/gradle/initialization/ScriptEvaluatingSettingsProcessorTest.groovy
index 41c5c60..b0f7e5a 100644
--- a/subprojects/core/src/test/groovy/org/gradle/initialization/ScriptEvaluatingSettingsProcessorTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/initialization/ScriptEvaluatingSettingsProcessorTest.groovy
@@ -16,34 +16,30 @@
package org.gradle.initialization
-import groovy.mock.interceptor.MockFor
import org.gradle.StartParameter
import org.gradle.api.internal.GradleInternal
+import org.gradle.api.internal.SettingsInternal
import org.gradle.configuration.ScriptPlugin
import org.gradle.configuration.ScriptPluginFactory
import org.gradle.groovy.scripts.ScriptSource
import org.gradle.util.JUnit4GroovyMockery
import org.junit.Before
import org.junit.Test
+
import static org.junit.Assert.assertSame
-/**
- * @author Hans Dockter
- */
class ScriptEvaluatingSettingsProcessorTest {
static final File TEST_ROOT_DIR = new File('rootDir')
- static final File TEST_CURRENT_DIR = new File('currentDir')
ScriptEvaluatingSettingsProcessor settingsProcessor
DefaultSettingsFinder expectedSettingsFinder
SettingsFactory settingsFactory
StartParameter expectedStartParameter
- DefaultSettings expectedSettings
- MockFor settingsFactoryMocker
+ SettingsInternal expectedSettings
ScriptSource scriptSourceMock
IGradlePropertiesLoader propertiesLoaderMock
ScriptPluginFactory configurerFactoryMock
Map expectedGradleProperties
- URLClassLoader urlClassLoader
+ ClassLoader urlClassLoader
GradleInternal gradleMock
SettingsLocation settingsLocation
@@ -65,16 +61,14 @@ class ScriptEvaluatingSettingsProcessorTest {
}
private void initExpectedSettings() {
- expectedSettings = new DefaultSettings()
- DefaultProjectDescriptorRegistry projectDescriptorRegistry = new DefaultProjectDescriptorRegistry()
- expectedSettings.setRootProjectDescriptor(new DefaultProjectDescriptor(null, TEST_ROOT_DIR.name,
- TEST_ROOT_DIR, projectDescriptorRegistry))
- expectedSettings.setProjectDescriptorRegistry(projectDescriptorRegistry)
- expectedSettings.setStartParameter(expectedStartParameter)
+ expectedSettings = context.mock(SettingsInternal.class)
context.checking {
one(settingsFactory).createSettings(gradleMock, TEST_ROOT_DIR, scriptSourceMock, expectedGradleProperties, expectedStartParameter, urlClassLoader)
will(returnValue(expectedSettings))
-
+
+ allowing(expectedSettings).getClassLoader()
+ will(returnValue(urlClassLoader))
+
one(settingsLocation).getSettingsDir()
will(returnValue(TEST_ROOT_DIR))
allowing(settingsLocation).getSettingsScriptSource()
diff --git a/subprojects/core/src/test/groovy/org/gradle/initialization/SettingsFactoryTest.java b/subprojects/core/src/test/groovy/org/gradle/initialization/SettingsFactoryTest.java
index f9a12fe..d437bc5 100644
--- a/subprojects/core/src/test/groovy/org/gradle/initialization/SettingsFactoryTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/initialization/SettingsFactoryTest.java
@@ -16,13 +16,19 @@
package org.gradle.initialization;
import org.gradle.StartParameter;
+import org.gradle.api.initialization.Settings;
import org.gradle.api.internal.DynamicObjectAware;
import org.gradle.api.internal.GradleInternal;
import org.gradle.api.internal.ThreadGlobalInstantiator;
+import org.gradle.api.internal.file.FileResolver;
+import org.gradle.api.plugins.PluginContainer;
+import org.gradle.configuration.ScriptPluginFactory;
import org.gradle.groovy.scripts.ScriptSource;
+import org.gradle.internal.service.scopes.ServiceRegistryFactory;
+import org.gradle.util.JUnit4GroovyMockery;
import org.gradle.util.WrapUtil;
+import org.jmock.Expectations;
import org.jmock.integration.junit4.JUnit4Mockery;
-import org.jmock.lib.legacy.ClassImposteriser;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -34,23 +40,40 @@ import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
-/**
- * @author Hans Dockter
- */
@RunWith(org.jmock.integration.junit4.JMock.class)
public class SettingsFactoryTest {
- private JUnit4Mockery context = new JUnit4Mockery() {{
- setImposteriser(ClassImposteriser.INSTANCE);
- }};
+ private JUnit4Mockery context = new JUnit4GroovyMockery();
@Test
public void createSettings() {
final File expectedSettingsDir = new File("settingsDir");
ScriptSource expectedScriptSource = context.mock(ScriptSource.class);
Map<String, String> expectedGradleProperties = WrapUtil.toMap("key", "myvalue");
- IProjectDescriptorRegistry expectedProjectDescriptorRegistry = new DefaultProjectDescriptorRegistry();
StartParameter expectedStartParameter = new StartParameter();
- SettingsFactory settingsFactory = new SettingsFactory(expectedProjectDescriptorRegistry, ThreadGlobalInstantiator.getOrCreate());
+ final ServiceRegistryFactory serviceRegistryFactory = context.mock(ServiceRegistryFactory.class);
+ final ServiceRegistryFactory settingsInternallServiceRegistry = context.mock(ServiceRegistryFactory.class);
+ final PluginContainer pluginContainer = context.mock(PluginContainer.class);
+ final FileResolver fileResolver = context.mock(FileResolver.class);
+ final ScriptPluginFactory scriptPluginFactory = context.mock(ScriptPluginFactory.class);
+
+ final ProjectDescriptorRegistry expectedProjectDescriptorRegistry = context.mock(ProjectDescriptorRegistry.class);
+
+ context.checking(new Expectations() {{
+ one(serviceRegistryFactory).createFor(with(any(Settings.class)));
+ will(returnValue(settingsInternallServiceRegistry));
+ one(settingsInternallServiceRegistry).get(PluginContainer.class);
+ will(returnValue(pluginContainer));
+ one(settingsInternallServiceRegistry).get(FileResolver.class);
+ will(returnValue(fileResolver));
+ one(settingsInternallServiceRegistry).get(ScriptPluginFactory.class);
+ will(returnValue(scriptPluginFactory));
+ one(settingsInternallServiceRegistry).get(ProjectDescriptorRegistry.class);
+ will(returnValue(expectedProjectDescriptorRegistry));
+ one(expectedProjectDescriptorRegistry).addProject(with(any(DefaultProjectDescriptor.class)));
+ }});
+
+
+ SettingsFactory settingsFactory = new SettingsFactory(ThreadGlobalInstantiator.getOrCreate(), serviceRegistryFactory);
final URLClassLoader urlClassLoader = new URLClassLoader(new URL[0]);
GradleInternal gradle = context.mock(GradleInternal.class);
@@ -60,7 +83,7 @@ public class SettingsFactoryTest {
assertSame(gradle, settings.getGradle());
assertSame(expectedProjectDescriptorRegistry, settings.getProjectDescriptorRegistry());
for (Map.Entry<String, String> entry : expectedGradleProperties.entrySet()) {
- assertEquals(entry.getValue(), ((DynamicObjectAware)settings).getAsDynamicObject().getProperty(entry.getKey()));
+ assertEquals(entry.getValue(), ((DynamicObjectAware) settings).getAsDynamicObject().getProperty(entry.getKey()));
}
assertSame(expectedSettingsDir, settings.getSettingsDir());
diff --git a/subprojects/core/src/test/groovy/org/gradle/initialization/SettingsHandlerTest.java b/subprojects/core/src/test/groovy/org/gradle/initialization/SettingsHandlerTest.java
index c50b8dc..0c83cba 100644
--- a/subprojects/core/src/test/groovy/org/gradle/initialization/SettingsHandlerTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/initialization/SettingsHandlerTest.java
@@ -18,9 +18,11 @@ package org.gradle.initialization;
import org.gradle.StartParameter;
import org.gradle.api.internal.GradleInternal;
import org.gradle.api.internal.SettingsInternal;
-import org.gradle.api.internal.project.IProjectRegistry;
+import org.gradle.api.internal.project.ProjectRegistry;
+import org.gradle.internal.service.scopes.ServiceRegistryFactory;
+import org.gradle.initialization.buildsrc.BuildSourceBuilder;
+import org.gradle.invocation.BuildClassLoaderRegistry;
import org.gradle.util.GFileUtils;
-import org.gradle.util.MultiParentClassLoader;
import org.gradle.util.WrapUtil;
import org.hamcrest.Description;
import org.hamcrest.Factory;
@@ -38,9 +40,6 @@ import java.net.URLClassLoader;
import static org.hamcrest.Matchers.sameInstance;
import static org.junit.Assert.assertThat;
-/**
- * @author Hans Dockter
- */
public class SettingsHandlerTest {
private JUnit4Mockery context = new JUnit4Mockery() {{
setImposteriser(ClassImposteriser.INSTANCE);
@@ -53,7 +52,6 @@ public class SettingsHandlerTest {
private ISettingsFinder settingsFinder = context.mock(ISettingsFinder.class);
private SettingsProcessor settingsProcessor = context.mock(SettingsProcessor.class);
private BuildSourceBuilder buildSourceBuilder = context.mock(BuildSourceBuilder.class);
- private MultiParentClassLoader scriptClassLoader = context.mock(MultiParentClassLoader.class);
private SettingsHandler settingsHandler = new SettingsHandler(settingsFinder, settingsProcessor,
buildSourceBuilder);
@@ -69,8 +67,10 @@ public class SettingsHandlerTest {
}
private void prepareForExistingSettings() {
- final IProjectRegistry projectRegistry = context.mock(IProjectRegistry.class);
+ final ProjectRegistry projectRegistry = context.mock(ProjectRegistry.class);
final DefaultProjectDescriptor projectDescriptor = context.mock(DefaultProjectDescriptor.class);
+ final ServiceRegistryFactory services = context.mock(ServiceRegistryFactory.class);
+ final BuildClassLoaderRegistry classLoaderRegistry = context.mock(BuildClassLoaderRegistry.class);
startParameter.setCurrentDir(settingsLocation.getSettingsDir());
context.checking(new Expectations() {{
@@ -89,19 +89,22 @@ public class SettingsHandlerTest {
allowing(settings).getClassLoader();
will(returnValue(urlClassLoader));
- allowing(gradle).getScriptClassLoader();
- will(returnValue(scriptClassLoader));
+ allowing(services).get(BuildClassLoaderRegistry.class);
+ will(returnValue(classLoaderRegistry));
allowing(gradle).getStartParameter();
will(returnValue(startParameter));
+ allowing(gradle).getServices();
+ will(returnValue(services));
+
allowing(settingsFinder).find(startParameter);
will(returnValue(settingsLocation));
one(settingsProcessor).process(gradle, settingsLocation, urlClassLoader, startParameter);
will(returnValue(settings));
- one(scriptClassLoader).addParent(urlClassLoader);
+ one(classLoaderRegistry).addRootClassLoader(urlClassLoader);
}});
}
diff --git a/subprojects/core/src/test/groovy/org/gradle/initialization/buildsrc/BuildSourceBuilderTest.groovy b/subprojects/core/src/test/groovy/org/gradle/initialization/buildsrc/BuildSourceBuilderTest.groovy
new file mode 100644
index 0000000..75925ad
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/initialization/buildsrc/BuildSourceBuilderTest.groovy
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.initialization.buildsrc
+
+import org.gradle.StartParameter
+import org.gradle.cache.CacheRepository
+import org.gradle.cache.PersistentCache
+import org.gradle.initialization.ClassLoaderRegistry
+import org.gradle.initialization.GradleLauncherFactory
+import org.gradle.internal.classpath.ClassPath
+import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
+import org.junit.Rule
+import spock.lang.Specification
+
+class BuildSourceBuilderTest extends Specification {
+
+ @Rule TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider()
+
+ GradleLauncherFactory launcherFactory = Mock()
+ ClassLoaderRegistry loaderRegistry = Mock()
+ CacheRepository cacheRepository = Mock()
+ BuildSourceBuilder buildSourceBuilder = Spy(BuildSourceBuilder, constructorArgs: [launcherFactory, loaderRegistry, cacheRepository])
+
+ StartParameter parameter = new StartParameter()
+
+ void "creates classpath when build src does not exist"() {
+ when:
+ parameter.setCurrentDir(new File('nonexisting'));
+ then:
+ buildSourceBuilder.createBuildSourceClasspath(parameter).asFiles == []
+ }
+
+ void "creates classpath when build src exists"() {
+ def cache = Mock(PersistentCache)
+ def classpath = Mock(ClassPath)
+ buildSourceBuilder.createCache(parameter) >> cache
+ cache.useCache(_ as String, _ as BuildSrcUpdateFactory) >> classpath
+
+ when:
+ parameter.setCurrentDir(tmpDir.createDir("someDir"));
+
+ then:
+ buildSourceBuilder.createBuildSourceClasspath(parameter) == classpath
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/initialization/buildsrc/BuildSrcBuildListenerFactoryTest.groovy b/subprojects/core/src/test/groovy/org/gradle/initialization/buildsrc/BuildSrcBuildListenerFactoryTest.groovy
new file mode 100644
index 0000000..8e0c913
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/initialization/buildsrc/BuildSrcBuildListenerFactoryTest.groovy
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.initialization.buildsrc
+
+import spock.lang.Specification
+import org.gradle.api.internal.GradleInternal
+import org.gradle.api.internal.project.ProjectInternal
+import org.gradle.api.plugins.Convention
+import org.gradle.api.internal.plugins.EmbeddableJavaProject
+import org.gradle.StartParameter
+
+class BuildSrcBuildListenerFactoryTest extends Specification {
+
+ def startParameter = Mock(StartParameter)
+ def plugin = Stub(EmbeddableJavaProject)
+ def convention = Mock(Convention) {
+ getPlugin(EmbeddableJavaProject) >> plugin
+ }
+ def project = Mock(ProjectInternal) {
+ getConvention() >> convention
+ }
+ def gradle = Mock(GradleInternal) {
+ getStartParameter() >> startParameter
+ getRootProject() >> project
+ }
+
+ def "configures task names when rebuild on"() {
+ def listener = new BuildSrcBuildListenerFactory().create(true)
+ plugin.getRebuildTasks() >> ['fooBuild']
+
+ when:
+ listener.onConfigure(gradle)
+
+ then:
+ 1 * startParameter.setTaskNames(['fooBuild'])
+ }
+
+ def "configures task names when rebuild off"() {
+ def listener = new BuildSrcBuildListenerFactory().create(false)
+ plugin.getBuildTasks() >> ['barBuild']
+
+ when:
+ listener.onConfigure(gradle)
+
+ then:
+ 1 * startParameter.setTaskNames(['barBuild'])
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/initialization/buildsrc/BuildSrcUpdateFactoryTest.groovy b/subprojects/core/src/test/groovy/org/gradle/initialization/buildsrc/BuildSrcUpdateFactoryTest.groovy
new file mode 100644
index 0000000..ce52264
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/initialization/buildsrc/BuildSrcUpdateFactoryTest.groovy
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.initialization.buildsrc
+
+import org.gradle.GradleLauncher
+import org.gradle.cache.PersistentCache
+import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
+import org.junit.Rule
+import spock.lang.Specification
+
+class BuildSrcUpdateFactoryTest extends Specification {
+
+ @Rule TestNameTestDirectoryProvider temp = new TestNameTestDirectoryProvider()
+
+ def cache = Stub(PersistentCache)
+ def launcher = Stub(GradleLauncher)
+ def listener = Stub(BuildSrcBuildListenerFactory.Listener)
+ def listenerFactory = Mock(BuildSrcBuildListenerFactory)
+ def factory = new BuildSrcUpdateFactory(cache, launcher, listenerFactory)
+
+ def "creates classpath"() {
+ cache.getBaseDir() >> temp.testDirectory
+ listener.getRuntimeClasspath() >> [new File("dummy")]
+
+ when:
+ def classpath = factory.create()
+
+ then:
+ classpath.asFiles == [new File("dummy")]
+ 1 * listenerFactory.create(_) >> listener
+ }
+
+ def "uses listener with rebuild off when marker file present"() {
+ temp.createFile("built.bin")
+ cache.getBaseDir() >> temp.testDirectory
+
+ when:
+ factory.create()
+
+ then:
+ 1 * listenerFactory.create(false) >> listener
+ }
+
+ def "uses listener with rebuild on when marker file not present"() {
+ cache.getBaseDir() >> temp.createDir("empty")
+
+ when:
+ factory.create()
+
+ then:
+ 1 * listenerFactory.create(true) >> listener
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/internal/featurelifecycle/DeprecatedFeatureUsageTest.groovy b/subprojects/core/src/test/groovy/org/gradle/internal/featurelifecycle/DeprecatedFeatureUsageTest.groovy
new file mode 100644
index 0000000..d642ee7
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/internal/featurelifecycle/DeprecatedFeatureUsageTest.groovy
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.featurelifecycle
+
+import spock.lang.Specification
+
+class DeprecatedFeatureUsageTest extends Specification {
+ def "can create copy with stack-trace filled in"() {
+ def usage = new DeprecatedFeatureUsage("message", DeprecatedFeatureUsageTest)
+
+ expect:
+ usage.stack.empty
+ def copy = usage.withStackTrace()
+ copy.message == usage.message
+ !copy.stack.empty
+ }
+
+ def "returns self when stack-trace already filled in"() {
+ def usage = new DeprecatedFeatureUsage("message", DeprecatedFeatureUsageTest).withStackTrace()
+
+ expect:
+ usage.withStackTrace() == usage
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/internal/featurelifecycle/LoggingDeprecatedFeatureHandlerTest.groovy b/subprojects/core/src/test/groovy/org/gradle/internal/featurelifecycle/LoggingDeprecatedFeatureHandlerTest.groovy
new file mode 100644
index 0000000..353eaa6
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/internal/featurelifecycle/LoggingDeprecatedFeatureHandlerTest.groovy
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.featurelifecycle
+
+import org.gradle.logging.ConfigureLogging
+import org.gradle.logging.TestAppender
+import org.gradle.util.SetSystemProperties
+import org.gradle.util.TextUtil
+import org.junit.Rule
+import spock.lang.Specification
+
+class LoggingDeprecatedFeatureHandlerTest extends Specification {
+ final appender = new TestAppender()
+ @Rule final ConfigureLogging logging = new ConfigureLogging(appender)
+ @Rule SetSystemProperties systemProperties = new SetSystemProperties()
+ final locationReporter = Mock(UsageLocationReporter)
+ final handler = new LoggingDeprecatedFeatureHandler(locationReporter)
+
+ def "logs each deprecation warning once only"() {
+ when:
+ handler.deprecatedFeatureUsed(new DeprecatedFeatureUsage("feature1", LoggingDeprecatedFeatureHandlerTest))
+ handler.deprecatedFeatureUsed(new DeprecatedFeatureUsage("feature2", LoggingDeprecatedFeatureHandlerTest))
+ handler.deprecatedFeatureUsed(new DeprecatedFeatureUsage("feature2", LoggingDeprecatedFeatureHandlerTest))
+
+ then:
+ appender.toString() == '[WARN feature1][WARN feature2]'
+ }
+
+ def "location reporter can prepend text"() {
+ def usage = new DeprecatedFeatureUsage("feature", LoggingDeprecatedFeatureHandlerTest)
+
+ when:
+ handler.deprecatedFeatureUsed(usage)
+
+ then:
+ 1 * locationReporter.reportLocation(_, _) >> { DeprecatedFeatureUsage param1, StringBuilder message ->
+ message.append("location")
+ }
+
+ and:
+ appender.toString() == TextUtil.toPlatformLineSeparators('[WARN location\nfeature]')
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/internal/featurelifecycle/ScriptUsageLocationReporterTest.groovy b/subprojects/core/src/test/groovy/org/gradle/internal/featurelifecycle/ScriptUsageLocationReporterTest.groovy
new file mode 100644
index 0000000..8613b91
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/internal/featurelifecycle/ScriptUsageLocationReporterTest.groovy
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.featurelifecycle
+
+import org.gradle.groovy.scripts.ScriptSource
+import spock.lang.Specification
+import org.gradle.groovy.scripts.Script
+
+class ScriptUsageLocationReporterTest extends Specification {
+ final reporter = new ScriptUsageLocationReporter()
+
+ def "does nothing when no caller is a script"() {
+ def stack = [
+ new StackTraceElement("SomeClass", "method", "SomeClass.java", 12),
+ new StackTraceElement("SomeClass", "method", "SomeClass.java", 77)]
+ def usage = Stub(DeprecatedFeatureUsage) {
+ getStack() >> stack
+ }
+ def result = new StringBuilder()
+
+ when:
+ reporter.reportLocation(usage, result)
+
+ then:
+ result.length() == 0
+ }
+
+ def "reports location when immediate caller is a script"() {
+ def scriptSource = Stub(ScriptSource) {
+ getFileName() >> "some-file.gradle"
+ getDisplayName() >> "build script 'some-file.gradle'"
+ }
+ def script = Stub(Script) {
+ getScriptSource() >> scriptSource
+ }
+ def stack = [
+ new StackTraceElement("SomeClass", "method", "some-file.gradle", 12),
+ new StackTraceElement("SomeClass", "method", "some-file.gradle", 77)]
+ def usage = Stub(DeprecatedFeatureUsage) {
+ getStack() >> stack
+ }
+ def result = new StringBuilder()
+
+ given:
+ reporter.beforeScript(script)
+ reporter.afterScript(script, null)
+
+ when:
+ reporter.reportLocation(usage, result)
+
+ then:
+ result.toString() == /Build script 'some-file.gradle': line 12/
+ }
+
+ def "reports location when second caller is a script"() {
+ def scriptSource = Stub(ScriptSource) {
+ getFileName() >> "some-file.gradle"
+ getDisplayName() >> "build script 'some-file.gradle'"
+ }
+ def script = Stub(Script) {
+ getScriptSource() >> scriptSource
+ }
+ def stack = [
+ new StackTraceElement("SomeLibrary", "method", "SomeLibrary.java", 103),
+ new StackTraceElement("SomeLibrary", "method", "SomeLibrary.java", 67),
+ new StackTraceElement("SomeClass", "method", "some-file.gradle", 12)
+ ]
+ def usage = Stub(DeprecatedFeatureUsage) {
+ getStack() >> stack
+ }
+ def result = new StringBuilder()
+
+ given:
+ reporter.beforeScript(script)
+ reporter.afterScript(script, null)
+
+ when:
+ reporter.reportLocation(usage, result)
+
+ then:
+ result.toString() == /Build script 'some-file.gradle': line 12/
+ }
+
+ def "does not report location when subsequent caller is a script"() {
+ def scriptSource = Stub(ScriptSource) {
+ getFileName() >> "some-file.gradle"
+ getDisplayName() >> "build script 'some-file.gradle'"
+ }
+ def script = Stub(Script) {
+ getScriptSource() >> scriptSource
+ }
+ def stack = [
+ new StackTraceElement("SomeLibrary", "method", "SomeLibrary.java", 103),
+ new StackTraceElement("OtherLibrary", "method", "OtherLibrary.java", 67),
+ new StackTraceElement("SomeClass", "method", "some-file.gradle", 12)
+ ]
+ def usage = Stub(DeprecatedFeatureUsage) {
+ getStack() >> stack
+ }
+ def result = new StringBuilder()
+
+ given:
+ reporter.beforeScript(script)
+ reporter.afterScript(script, null)
+
+ when:
+ reporter.reportLocation(usage, result)
+
+ then:
+ result.length() == 0
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/internal/graph/CachingDirectedGraphWalkerTest.groovy b/subprojects/core/src/test/groovy/org/gradle/internal/graph/CachingDirectedGraphWalkerTest.groovy
new file mode 100644
index 0000000..654e59c
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/internal/graph/CachingDirectedGraphWalkerTest.groovy
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.graph
+
+import spock.lang.Specification
+
+class CachingDirectedGraphWalkerTest extends Specification {
+ private final DirectedGraphWithEdgeValues<Integer, String> graph = Mock()
+ private final CachingDirectedGraphWalker walker = new CachingDirectedGraphWalker(graph)
+
+ def collectsValuesForASingleNode() {
+ when:
+ walker.add(1)
+ def values = walker.findValues()
+
+ then:
+ 1 * graph.getNodeValues(1, _, _) >> { args -> args[1] << '1' }
+ 0 * _._
+ values == ['1'] as Set
+ }
+
+ def collectsValuesForEachSuccessorNode() {
+ when:
+ walker.add(1)
+ def values = walker.findValues()
+
+ then:
+ 1 * graph.getNodeValues(1, _, _) >> { args -> args[1] << '1'; args[2] << 2; args[2] << 3 }
+ 1 * graph.getNodeValues(2, _, _) >> { args -> args[1] << '2'; args[2] << 3 }
+ 1 * graph.getNodeValues(3, _, _) >> { args -> args[1] << '3' }
+ 3 * graph.getEdgeValues(_, _, _)
+ 0 * _._
+ values == ['1', '2', '3'] as Set
+ }
+
+ def collectsValuesForEachEdgeTraversed() {
+ when:
+ walker.add(1)
+ def values = walker.findValues()
+
+ then:
+ 1 * graph.getNodeValues(1, _, _) >> { args -> args[2] << 2; args[2] << 3 }
+ 1 * graph.getEdgeValues(1, 2, _) >> { args -> args[2] << '1->2' }
+ 1 * graph.getEdgeValues(1, 3, _) >> { args -> args[2] << '1->3' }
+ 1 * graph.getNodeValues(2, _, _) >> { args -> args[2] << 3 }
+ 1 * graph.getEdgeValues(2, 3, _) >> { args -> args[2] << '2->3' }
+ 1 * graph.getNodeValues(3, _, _)
+ 0 * _._
+ values == ['1->2', '1->3', '2->3'] as Set
+ }
+
+ def collectsValuesForAllStartNodes() {
+ when:
+ walker.add(1, 2)
+ def values = walker.findValues()
+
+ then:
+ 1 * graph.getNodeValues(1, _, _) >> { args -> args[1] << '1'; args[2] << 3 }
+ 1 * graph.getNodeValues(2, _, _) >> { args -> args[1] << '2'; args[2] << 3 }
+ 1 * graph.getNodeValues(3, _, _) >> { args -> args[1] << '3' }
+ 2 * graph.getEdgeValues(_, _, _)
+ 0 * _._
+ values == ['1', '2', '3'] as Set
+ }
+
+ def collectsValuesWhenCycleIsPresentInGraph() {
+ when:
+ walker.add(1)
+ def values = walker.findValues()
+
+ then:
+ 1 * graph.getNodeValues(1, _, _) >> { args -> args[1] << '1'; args[2] << 2 }
+ 1 * graph.getEdgeValues(1, 2, _) >> { args -> args[2] << '1->2' }
+ 1 * graph.getNodeValues(2, _, _) >> { args -> args[1] << '2'; args[2] << 3 }
+ 1 * graph.getEdgeValues(2, 3, _) >> { args -> args[2] << '2->3' }
+ 1 * graph.getNodeValues(3, _, _) >> { args -> args[1] << '3'; args[2] << 1 }
+ 1 * graph.getEdgeValues(3, 1, _) >> { args -> args[2] << '3->1' }
+ 0 * _._
+ values == ['1', '1->2', '2', '2->3', '3', '3->1'] as Set
+ }
+
+ def collectsValuesWhenNodeConnectedToItself() {
+ when:
+ walker.add(1)
+ def values = walker.findValues()
+
+ then:
+ 1 * graph.getNodeValues(1, _, _) >> { args -> args[1] << '1'; args[2] << 1 }
+ 1 * graph.getEdgeValues(1, 1, _) >> { args -> args[2] << '1->1' }
+ 0 * _._
+ values == ['1', '1->1'] as Set
+ }
+
+ def collectsValuesWhenMultipleCyclesInGraph() {
+ when:
+ walker.add(1)
+ def values = walker.findValues()
+
+ then:
+ 1 * graph.getNodeValues(1, _, _) >> { args -> args[1] << '1'; args[2] << 1; args[2] << 2 }
+ 1 * graph.getNodeValues(2, _, _) >> { args -> args[1] << '2'; args[2] << 3; args[2] << 4 }
+ 1 * graph.getNodeValues(3, _, _) >> { args -> args[1] << '3'; args[2] << 2 }
+ 1 * graph.getNodeValues(4, _, _) >> { args -> args[1] << '4' }
+ 5 * graph.getEdgeValues(_, _, _) >> { args -> args[2] << "${args[0]}->${args[1]}".toString() }
+ 0 * _._
+ values == ['1', '1->1', '1->2', '2', '2->3', '2->4', '3', '3->2', '4'] as Set
+ }
+
+ def locatesCyclesWhenSingleCycleInGraph() {
+ when:
+ walker.add(1)
+ def values = walker.findCycles()
+
+ then:
+ 1 * graph.getNodeValues(1, _, _) >> { args -> args[2] << 2 }
+ 1 * graph.getNodeValues(2, _, _) >> { args -> args[2] << 3 }
+ 1 * graph.getNodeValues(3, _, _) >> { args -> args[2] << 1; args[2] << 4 }
+ 1 * graph.getNodeValues(4, _, _) >> { args -> }
+ _ * graph.getEdgeValues(_, _, _)
+ 0 * _._
+
+ and:
+ values == [[1, 2, 3] as Set]
+ }
+
+ def locatesCyclesWhenCycleContainsASingleNode() {
+ when:
+ walker.add(1)
+ def values = walker.findCycles()
+
+ then:
+ 1 * graph.getNodeValues(1, _, _) >> { args -> args[2] << 2 }
+ 1 * graph.getNodeValues(2, _, _) >> { args -> args[2] << 2 }
+ _ * graph.getEdgeValues(_, _, _)
+ 0 * _._
+
+ and:
+ values == [[2] as Set]
+ }
+
+ def locatesCyclesWhenCycleContainsCycles() {
+ when:
+ walker.add(1)
+ def values = walker.findCycles()
+
+ then:
+ 1 * graph.getNodeValues(1, _, _) >> { args -> args[2] << 2 }
+ 1 * graph.getNodeValues(2, _, _) >> { args -> args[2] << 3 }
+ 1 * graph.getNodeValues(3, _, _) >> { args -> args[2] << 4; args[2] << 1 }
+ 1 * graph.getNodeValues(4, _, _) >> { args -> args[2] << 3; args[2] << 5 }
+ 1 * graph.getNodeValues(5, _, _) >> { args -> args[2] << 4; args[2] << 1 }
+ _ * graph.getEdgeValues(_, _, _)
+ 0 * _._
+
+ and:
+ values == [[1, 2, 3, 4, 5] as Set]
+ }
+
+ def locatesCyclesWhenMultipleCyclesInGraph() {
+ when:
+ walker.add(1)
+ def values = walker.findCycles()
+
+ then:
+ 1 * graph.getNodeValues(1, _, _) >> { args -> args[2] << 1; args[2] << 2 }
+ 1 * graph.getNodeValues(2, _, _) >> { args -> args[2] << 3 }
+ 1 * graph.getNodeValues(3, _, _) >> { args -> args[2] << 1; args[2] << 4 }
+ 1 * graph.getNodeValues(4, _, _) >> { args -> args[2] << 4; args[2] << 5; }
+ 1 * graph.getNodeValues(5, _, _) >> { args -> args[2] << 6 }
+ 1 * graph.getNodeValues(6, _, _) >> { args -> args[2] << 5 }
+ _ * graph.getEdgeValues(_, _, _)
+ 0 * _._
+
+ and:
+ values == [[5, 6] as Set, [4] as Set, [1, 2, 3] as Set]
+ }
+
+ def canReuseWalkerForMultipleSearches() {
+ when:
+ walker.add(1)
+ def values = walker.findValues()
+
+ then:
+ 1 * graph.getNodeValues(1, _, _) >> { args -> args[1] << '1'; args[2] << 2; args[2] << 3 }
+ 1 * graph.getNodeValues(2, _, _) >> { args -> args[1] << '2'; args[2] << 3 }
+ 1 * graph.getNodeValues(3, _, _) >> { args -> args[1] << '3' }
+ 3 * graph.getEdgeValues(_, _, _)
+ 0 * _._
+ values == ['1', '2', '3'] as Set
+
+ // Cached node (1) is reachable via 2 separate new paths (4->5->1 and 4->6->1)
+ when:
+ walker.add(4)
+ values = walker.findValues()
+
+ then:
+ 1 * graph.getNodeValues(4, _, _) >> { args -> args[1] << '4'; args[2] << 5; args[2] << 6 }
+ 1 * graph.getNodeValues(5, _, _) >> { args -> args[1] << '5'; args[2] << 1 }
+ 1 * graph.getNodeValues(6, _, _) >> { args -> args[1] << '6'; args[2] << 1 }
+ 4 * graph.getEdgeValues(_, _, _) >> { args -> args[2] << "${args[0]}->${args[1]}".toString() }
+ 0 * _._
+ values == ['4', '4->5', '4->6', '5', '5->1', '6', '6->1', '1', '2', '3'] as Set
+
+ when:
+ walker.add(2)
+ values = walker.findValues()
+
+ then:
+ values == ['2', '3'] as Set
+ }
+
+ def canReuseWalkerWhenGraphContainsACycle() {
+ when:
+ walker.add(1)
+ walker.findValues()
+
+ then:
+ 1 * graph.getNodeValues(1, _, _) >> { args -> args[1] << '1'; args[2] << 2 }
+ 1 * graph.getNodeValues(2, _, _) >> { args -> args[1] << '2'; args[2] << 3 }
+ 1 * graph.getNodeValues(3, _, _) >> { args -> args[1] << '3'; args[2] << 1; args[2] << 4 }
+ 1 * graph.getNodeValues(4, _, _) >> { args -> args[1] << '4'; args[2] << 2 }
+ 5 * graph.getEdgeValues(_, _, _)
+ 0 * _._
+
+ when:
+ walker.add(1)
+ def values = walker.findValues()
+
+ then:
+ values == ['1', '2', '3', '4'] as Set
+
+ when:
+ walker.add(2)
+ values = walker.findValues()
+
+ then:
+ values == ['1', '2', '3', '4'] as Set
+
+ when:
+ walker.add(3)
+ values = walker.findValues()
+
+ then:
+ values == ['1', '2', '3', '4'] as Set
+
+ when:
+ walker.add(4)
+ values = walker.findValues()
+
+ then:
+ values == ['1', '2', '3', '4'] as Set
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/internal/graph/DirectedGraphRendererTest.groovy b/subprojects/core/src/test/groovy/org/gradle/internal/graph/DirectedGraphRendererTest.groovy
new file mode 100644
index 0000000..c11fb3c
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/internal/graph/DirectedGraphRendererTest.groovy
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.graph
+
+import org.gradle.logging.StyledTextOutput
+import org.gradle.logging.TestStyledTextOutput
+import org.gradle.util.TextUtil
+import spock.lang.Specification
+
+class DirectedGraphRendererTest extends Specification {
+ final DirectedGraph<String, Void> graph = Mock(DirectedGraph)
+ final GraphNodeRenderer<String> nodeRenderer = Stub(GraphNodeRenderer) {
+ renderTo(_, _) >> { String node, StyledTextOutput output -> output.text("[$node]")}
+ }
+ final DirectedGraphRenderer<String> renderer = new DirectedGraphRenderer<String>(nodeRenderer, graph)
+ final TestStyledTextOutput output = new TestStyledTextOutput()
+
+ def "renders a graph with a single root node"() {
+ given:
+ 1 * graph.getNodeValues("1", _, _) >> { args -> }
+
+ when:
+ renderer.renderTo("1", output)
+
+ then:
+ output.value == """[1]
+"""
+ }
+
+ def "renders a tree"() {
+ given:
+ 1 * graph.getNodeValues("1", _, _) >> { args -> args[2] << "2"; args[2] << "3" }
+ 1 * graph.getNodeValues("2", _, _) >> { args -> args[2] << "4" }
+ 1 * graph.getNodeValues("3", _, _) >> { args -> }
+ 1 * graph.getNodeValues("4", _, _) >> { args -> args[2] << "5" }
+ 1 * graph.getNodeValues("5", _, _) >> { args -> }
+
+ when:
+ renderer.renderTo("1", output)
+
+ then:
+ output.value == """[1]
+{info}+--- {normal}[2]
+{info}| \\--- {normal}[4]
+{info}| \\--- {normal}[5]
+{info}\\--- {normal}[3]
+"""
+ }
+
+ def "renders a graph that contains nodes with multiple incoming edges"() {
+ given:
+ 1 * graph.getNodeValues("1", _, _) >> { args -> args[2] << "2"; args[2] << "3" }
+ 1 * graph.getNodeValues("2", _, _) >> { args -> args[2] << "4" }
+ 1 * graph.getNodeValues("3", _, _) >> { args -> args[2] << "2" }
+ 1 * graph.getNodeValues("4", _, _) >> { args -> }
+
+ when:
+ renderer.renderTo("1", output)
+
+ then:
+ output.value == """[1]
+{info}+--- {normal}[2]
+{info}| \\--- {normal}[4]
+{info}\\--- {normal}[3]
+{info} \\--- {normal}[2] (*)
+
+{info}(*) - details omitted (listed previously){normal}
+"""
+ }
+
+ def "renders a graph that contains cycles"() {
+ given:
+ 1 * graph.getNodeValues("1", _, _) >> { args -> args[2] << "2"; args[2] << "3" }
+ 1 * graph.getNodeValues("2", _, _) >> { args -> args[2] << "3" }
+ 1 * graph.getNodeValues("3", _, _) >> { args -> args[2] << "2" }
+
+ when:
+ renderer.renderTo("1", output)
+
+ then:
+ output.value == """[1]
+{info}+--- {normal}[2]
+{info}| \\--- {normal}[3]
+{info}| \\--- {normal}[2] (*)
+{info}\\--- {normal}[3] (*)
+
+{info}(*) - details omitted (listed previously){normal}
+"""
+ }
+
+ def "renders a graph that contains a single node with an edge to itself"() {
+ given:
+ 1 * graph.getNodeValues("1", _, _) >> { args -> args[2] << "1" }
+
+ when:
+ renderer.renderTo("1", output)
+
+ then:
+ output.value == """[1]
+{info}\\--- {normal}[1] (*)
+
+{info}(*) - details omitted (listed previously){normal}
+"""
+ }
+
+ def "renders to an appendable"() {
+ given:
+ 1 * graph.getNodeValues("1", _, _) >> { args -> args[2] << "2"; args[2] << "3" }
+ 1 * graph.getNodeValues("2", _, _) >> { args -> args[2] << "4" }
+ 1 * graph.getNodeValues("3", _, _) >> { args -> }
+ 1 * graph.getNodeValues("4", _, _) >> { args -> args[2] << "5" }
+ 1 * graph.getNodeValues("5", _, _) >> { args -> }
+
+ when:
+ StringWriter writer = new StringWriter()
+ renderer.renderTo("1", writer)
+
+ then:
+ writer.toString() == TextUtil.toPlatformLineSeparators("""[1]
++--- [2]
+| \\--- [4]
+| \\--- [5]
+\\--- [3]
+""")
+ }
+
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/internal/graph/GraphAggregatorTest.groovy b/subprojects/core/src/test/groovy/org/gradle/internal/graph/GraphAggregatorTest.groovy
new file mode 100644
index 0000000..9faebe9
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/internal/graph/GraphAggregatorTest.groovy
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.graph
+
+import spock.lang.Specification
+
+class GraphAggregatorTest extends Specification {
+ private final DirectedGraph<String, String> graph = Mock()
+ private final GraphAggregator aggregator = new GraphAggregator(graph)
+
+ def groupsNodeWithTheEntryNodeItIsReachableFrom() {
+ when:
+ def result = aggregator.group(['a'], ['a', 'b'])
+
+ then:
+ 1 * graph.getNodeValues('a', !null, !null) >> { args -> args[2].add('b') }
+ result.getNodes('a') == ['a', 'b'] as Set
+ }
+
+ def groupsNodeWithTheClosesEntryNodeItIsReachableFrom() {
+ when:
+ def result = aggregator.group(['a', 'b'], ['a', 'b', 'c'])
+
+ then:
+ 1 * graph.getNodeValues('a', !null, !null) >> { args -> args[2].add('b') }
+ 1 * graph.getNodeValues('b', !null, !null) >> { args -> args[2].add('c') }
+ result.getNodes('a') == ['a'] as Set
+ result.getNodes('b') == ['b', 'c'] as Set
+ }
+
+ def groupsNodeWithMultipleEntryNodesWhenTheNodeHasMultipleClosesNodes() {
+ when:
+ def result = aggregator.group(['a', 'b'], ['a', 'b', 'c'])
+
+ then:
+ 1 * graph.getNodeValues('a', !null, !null) >> { args -> args[2].add('c') }
+ 1 * graph.getNodeValues('b', !null, !null) >> { args -> args[2].add('c') }
+ result.getNodes('a') == ['a', 'c'] as Set
+ result.getNodes('b') == ['b', 'c'] as Set
+ }
+
+ def groupsNodesWhichAreNotReachableFromStartNodes() {
+ when:
+ def result = aggregator.group(['a', 'b'], ['a', 'b', 'c', 'd'])
+
+ then:
+ 1 * graph.getNodeValues('a', !null, !null) >> { args -> args[2].add('b') }
+ 1 * graph.getNodeValues('c', !null, !null) >> { args -> args[2].add('d') }
+ result.topLevelNodes == ['a', 'b', 'c'] as Set
+ result.getNodes('c') == ['c', 'd'] as Set
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/internal/service/scopes/BuildScopeServicesTest.groovy b/subprojects/core/src/test/groovy/org/gradle/internal/service/scopes/BuildScopeServicesTest.groovy
new file mode 100644
index 0000000..73b0c0b
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/internal/service/scopes/BuildScopeServicesTest.groovy
@@ -0,0 +1,270 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.service.scopes
+
+import org.gradle.StartParameter
+import org.gradle.api.internal.*
+import org.gradle.api.internal.classpath.DefaultModuleRegistry
+import org.gradle.api.internal.classpath.ModuleRegistry
+import org.gradle.api.internal.classpath.PluginModuleRegistry
+import org.gradle.api.internal.file.FileResolver
+import org.gradle.api.internal.project.DefaultIsolatedAntBuilder
+import org.gradle.api.internal.project.IProjectFactory
+import org.gradle.api.internal.project.IsolatedAntBuilder
+import org.gradle.api.internal.project.ProjectFactory
+import org.gradle.cache.CacheRepository
+import org.gradle.cache.internal.CacheFactory
+import org.gradle.cache.internal.DefaultCacheRepository
+import org.gradle.configuration.BuildConfigurer
+import org.gradle.configuration.DefaultBuildConfigurer
+import org.gradle.configuration.DefaultScriptPluginFactory
+import org.gradle.configuration.ScriptPluginFactory
+import org.gradle.groovy.scripts.DefaultScriptCompilerFactory
+import org.gradle.groovy.scripts.ScriptCompilerFactory
+import org.gradle.initialization.*
+import org.gradle.internal.Factory
+import org.gradle.internal.reflect.Instantiator
+import org.gradle.internal.service.ServiceRegistry
+import org.gradle.invocation.BuildClassLoaderRegistry
+import org.gradle.invocation.DefaultBuildClassLoaderRegistry
+import org.gradle.listener.DefaultListenerManager
+import org.gradle.listener.ListenerManager
+import org.gradle.logging.LoggingManagerInternal
+import org.gradle.messaging.remote.MessagingServer
+import org.gradle.process.internal.DefaultWorkerProcessFactory
+import org.gradle.process.internal.WorkerProcessBuilder
+import org.gradle.profile.ProfileEventAdapter
+import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
+import org.gradle.internal.classloader.ClassLoaderFactory
+import org.gradle.internal.classloader.MultiParentClassLoader
+import org.junit.Rule
+import spock.lang.Specification
+import spock.lang.Timeout
+
+import static org.hamcrest.Matchers.instanceOf
+import static org.hamcrest.Matchers.sameInstance
+import static org.junit.Assert.assertThat
+
+public class BuildScopeServicesTest extends Specification {
+ @Rule
+ TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider()
+ StartParameter startParameter = new StartParameter()
+ ServiceRegistry parent = Mock()
+ Factory<CacheFactory> cacheFactoryFactory = Mock()
+ ClosableCacheFactory cacheFactory = Mock()
+ ClassLoaderRegistry classLoaderRegistry = Mock()
+
+ BuildScopeServices registry = new BuildScopeServices(parent, startParameter)
+
+ def setup() {
+ startParameter.gradleUserHomeDir = tmpDir.testDirectory
+ parent.getFactory(CacheFactory) >> cacheFactoryFactory
+ cacheFactoryFactory.create() >> cacheFactory
+ parent.get(ClassLoaderRegistry) >> classLoaderRegistry
+ parent.getFactory(LoggingManagerInternal) >> Stub(Factory)
+ parent.get(ModuleRegistry) >> new DefaultModuleRegistry()
+ parent.get(PluginModuleRegistry) >> Stub(PluginModuleRegistry)
+ parent.get(Instantiator) >> ThreadGlobalInstantiator.getOrCreate()
+ parent.get(FileResolver) >> Stub(FileResolver)
+ }
+
+ def delegatesToParentForUnknownService() {
+ setup:
+ parent.get(String) >> "value"
+
+ expect:
+ registry.get(String) == "value"
+ }
+
+ def throwsExceptionForUnknownDomainObject() {
+ when:
+ registry.createFor("string")
+ then:
+ def e = thrown(IllegalArgumentException)
+ e.message == "Cannot create services for unknown domain object of type String."
+ }
+
+ def canCreateServicesForAGradleInstance() {
+ setup:
+ GradleInternal gradle = Mock()
+ ServiceRegistryFactory registry = this.registry.createFor(gradle)
+ expect:
+ registry instanceof GradleScopeServices
+ }
+
+ def providesAListenerManager() {
+ setup:
+ ListenerManager listenerManager = expectListenerManagerCreated()
+ expect:
+ assertThat(registry.get(ListenerManager), sameInstance(listenerManager))
+ }
+
+ @Timeout(5)
+ def providesAScriptCompilerFactory() {
+ setup:
+ expectListenerManagerCreated()
+
+ expect:
+ registry.get(ScriptCompilerFactory) instanceof DefaultScriptCompilerFactory
+ registry.get(ScriptCompilerFactory) == registry.get(ScriptCompilerFactory)
+ }
+
+ def providesACacheRepositoryAndCleansUpOnClose() {
+ setup:
+ 1 * cacheFactory.close()
+
+ expect:
+ registry.get(CacheRepository) instanceof DefaultCacheRepository
+ registry.get(CacheRepository) == registry.get(CacheRepository)
+ registry.close()
+ }
+
+ def providesAnInitScriptHandler() {
+ setup:
+ allowGetCoreImplClassLoader()
+ expectScriptClassLoaderCreated()
+ expectListenerManagerCreated()
+ allowGetGradleDistributionLocator()
+
+ expect:
+ registry.get(InitScriptHandler) instanceof InitScriptHandler
+ registry.get(InitScriptHandler) == registry.get(InitScriptHandler)
+ }
+
+ def providesAScriptObjectConfigurerFactory() {
+ setup:
+ allowGetCoreImplClassLoader()
+ expectListenerManagerCreated()
+ expectScriptClassLoaderCreated()
+ expect:
+ assertThat(registry.get(ScriptPluginFactory), instanceOf(DefaultScriptPluginFactory))
+ assertThat(registry.get(ScriptPluginFactory), sameInstance(registry.get(ScriptPluginFactory)))
+ }
+
+ def providesASettingsProcessor() {
+ setup:
+ allowGetCoreImplClassLoader()
+ expectListenerManagerCreated()
+ expectScriptClassLoaderCreated()
+ expect:
+ assertThat(registry.get(SettingsProcessor), instanceOf(PropertiesLoadingSettingsProcessor))
+ assertThat(registry.get(SettingsProcessor), sameInstance(registry.get(SettingsProcessor)))
+ }
+
+ def providesAnExceptionAnalyser() {
+ setup:
+ expectListenerManagerCreated()
+ expect:
+ assertThat(registry.get(ExceptionAnalyser), instanceOf(MultipleBuildFailuresExceptionAnalyser))
+ assertThat(registry.get(ExceptionAnalyser).delegate, instanceOf(DefaultExceptionAnalyser))
+ assertThat(registry.get(ExceptionAnalyser), sameInstance(registry.get(ExceptionAnalyser)))
+ }
+
+ def providesAWorkerProcessFactory() {
+ setup:
+ expectParentServiceLocated(MessagingServer)
+ allowGetCoreImplClassLoader()
+
+ expect:
+ assertThat(registry.getFactory(WorkerProcessBuilder), instanceOf(DefaultWorkerProcessFactory))
+ }
+
+ def providesAnIsolatedAntBuilder() {
+ setup:
+ expectParentServiceLocated(ClassLoaderFactory)
+ allowGetCoreImplClassLoader()
+ expect:
+
+ assertThat(registry.get(IsolatedAntBuilder), instanceOf(DefaultIsolatedAntBuilder))
+ assertThat(registry.get(IsolatedAntBuilder), sameInstance(registry.get(IsolatedAntBuilder)))
+ }
+
+ def providesAProjectFactory() {
+ setup:
+ expectParentServiceLocated(Instantiator)
+ expectParentServiceLocated(ClassGenerator)
+ expect:
+ assertThat(registry.get(IProjectFactory), instanceOf(ProjectFactory))
+ assertThat(registry.get(IProjectFactory), sameInstance(registry.get(IProjectFactory)))
+ }
+
+ def providesABuildConfigurer() {
+ expect:
+ assertThat(registry.get(BuildConfigurer), instanceOf(DefaultBuildConfigurer))
+ assertThat(registry.get(BuildConfigurer), sameInstance(registry.get(BuildConfigurer)))
+ }
+
+ def providesAPropertiesLoader() {
+ expect:
+ assertThat(registry.get(IGradlePropertiesLoader), instanceOf(DefaultGradlePropertiesLoader))
+ assertThat(registry.get(IGradlePropertiesLoader), sameInstance(registry.get(IGradlePropertiesLoader)))
+ }
+
+ def providesABuildLoader() {
+ setup:
+ expectParentServiceLocated(Instantiator)
+ expect:
+ assertThat(registry.get(BuildLoader), instanceOf(ProjectPropertySettingBuildLoader))
+ assertThat(registry.get(BuildLoader), sameInstance(registry.get(BuildLoader)))
+ }
+
+ def providesAProfileEventAdapter() {
+ setup:
+ expectParentServiceLocated(BuildRequestMetaData)
+ expectListenerManagerCreated()
+
+ expect:
+ assertThat(registry.get(ProfileEventAdapter), instanceOf(ProfileEventAdapter))
+ assertThat(registry.get(ProfileEventAdapter), sameInstance(registry.get(ProfileEventAdapter)))
+ }
+
+ def providesABuildClassLoaderRegistry() {
+ expect:
+ assertThat(registry.get(BuildClassLoaderRegistry), instanceOf(DefaultBuildClassLoaderRegistry))
+ assertThat(registry.get(BuildClassLoaderRegistry), sameInstance(registry.get(BuildClassLoaderRegistry)))
+ }
+
+ private <T> T expectParentServiceLocated(Class<T> type) {
+ T t = Mock(type)
+ parent.get(type) >> t
+ t
+ }
+
+ private ListenerManager expectListenerManagerCreated() {
+ final ListenerManager listenerManager = new DefaultListenerManager()
+ final ListenerManager listenerManagerParent = Mock()
+ parent.get(ListenerManager) >> listenerManagerParent
+ 1 * listenerManagerParent.createChild() >> listenerManager
+ listenerManager
+ }
+
+ private void allowGetCoreImplClassLoader() {
+ classLoaderRegistry.getCoreImplClassLoader() >> new ClassLoader() {}
+ }
+
+ private void expectScriptClassLoaderCreated() {
+ 1 * classLoaderRegistry.gradleApiClassLoader >> new MultiParentClassLoader()
+ }
+
+ private void allowGetGradleDistributionLocator() {
+ parent.get(GradleDistributionLocator) >> Mock(GradleDistributionLocator)
+ }
+
+ public interface ClosableCacheFactory extends CacheFactory {
+ void close()
+ }
+}
\ No newline at end of file
diff --git a/subprojects/core/src/test/groovy/org/gradle/internal/service/scopes/GlobalScopeServicesTest.java b/subprojects/core/src/test/groovy/org/gradle/internal/service/scopes/GlobalScopeServicesTest.java
new file mode 100755
index 0000000..54b0309
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/internal/service/scopes/GlobalScopeServicesTest.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.service.scopes;
+
+import org.gradle.api.internal.*;
+import org.gradle.api.internal.classpath.DefaultModuleRegistry;
+import org.gradle.api.internal.classpath.DefaultPluginModuleRegistry;
+import org.gradle.api.internal.classpath.ModuleRegistry;
+import org.gradle.api.internal.classpath.PluginModuleRegistry;
+import org.gradle.api.internal.file.FileResolver;
+import org.gradle.api.internal.file.IdentityFileResolver;
+import org.gradle.cache.internal.CacheFactory;
+import org.gradle.cache.internal.DefaultCacheFactory;
+import org.gradle.cache.internal.DefaultFileLockManager;
+import org.gradle.cache.internal.FileLockManager;
+import org.gradle.cli.CommandLineConverter;
+import org.gradle.initialization.*;
+import org.gradle.internal.concurrent.DefaultExecutorFactory;
+import org.gradle.internal.concurrent.ExecutorFactory;
+import org.gradle.internal.nativeplatform.ProcessEnvironment;
+import org.gradle.internal.nativeplatform.filesystem.FileSystem;
+import org.gradle.listener.DefaultListenerManager;
+import org.gradle.listener.ListenerManager;
+import org.gradle.logging.LoggingManagerInternal;
+import org.gradle.logging.ProgressLoggerFactory;
+import org.gradle.logging.internal.DefaultLoggingManagerFactory;
+import org.gradle.logging.internal.DefaultProgressLoggerFactory;
+import org.gradle.messaging.remote.MessagingServer;
+import org.gradle.internal.classloader.ClassLoaderFactory;
+import org.gradle.internal.classloader.DefaultClassLoaderFactory;
+import org.junit.Test;
+import spock.lang.Shared;
+
+import static org.hamcrest.Matchers.instanceOf;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.junit.Assert.assertThat;
+
+public class GlobalScopeServicesTest {
+ @Shared
+ private final GlobalScopeServices registry = new GlobalScopeServices();
+
+ @Test
+ public void providesAGradleLauncherFactory() {
+ assertThat(registry.get(GradleLauncherFactory.class), instanceOf(DefaultGradleLauncherFactory.class));
+ }
+
+ @Test
+ public void providesCommandLineArgsConverter() {
+ assertThat(registry.get(CommandLineConverter.class), instanceOf(
+ DefaultCommandLineConverter.class));
+ }
+
+ @Test
+ public void providesACacheFactoryFactory() {
+ assertThat(registry.getFactory(CacheFactory.class), instanceOf(DefaultCacheFactory.class));
+ }
+
+ @Test
+ public void providesAModuleRegistry() {
+ assertThat(registry.get(ModuleRegistry.class), instanceOf(DefaultModuleRegistry.class));
+ }
+
+ @Test
+ public void providesAPluginModuleRegistry() {
+ assertThat(registry.get(PluginModuleRegistry.class), instanceOf(DefaultPluginModuleRegistry.class));
+ }
+
+ @Test
+ public void providesAClassPathRegistry() {
+ assertThat(registry.get(ClassPathRegistry.class), instanceOf(DefaultClassPathRegistry.class));
+ }
+
+ @Test
+ public void providesAClassLoaderRegistry() {
+ assertThat(registry.get(ClassLoaderRegistry.class), instanceOf(DefaultClassLoaderRegistry.class));
+ }
+
+ @Test
+ public void providesALoggingManagerFactory() {
+ assertThat(registry.getFactory(LoggingManagerInternal.class), instanceOf(DefaultLoggingManagerFactory.class));
+ }
+
+ @Test
+ public void providesAListenerManager() {
+ assertThat(registry.get(ListenerManager.class), instanceOf(DefaultListenerManager.class));
+ }
+
+ @Test
+ public void providesAProgressLoggerFactory() {
+ assertThat(registry.get(ProgressLoggerFactory.class), instanceOf(DefaultProgressLoggerFactory.class));
+ }
+
+ @Test
+ public void providesAGradleDistributionLocator() {
+ assertThat(registry.get(GradleDistributionLocator.class), instanceOf(DefaultModuleRegistry.class));
+ }
+
+ @Test
+ public void providesAClassLoaderFactory() {
+ assertThat(registry.get(ClassLoaderFactory.class), instanceOf(DefaultClassLoaderFactory.class));
+ }
+
+ @Test
+ public void providesAMessagingServer() {
+ assertThat(registry.get(MessagingServer.class), instanceOf(MessagingServer.class));
+ }
+
+ @Test
+ public void providesAClassGenerator() {
+ assertThat(registry.get(ClassGenerator.class), instanceOf(AsmBackedClassGenerator.class));
+ }
+
+ @Test
+ public void providesAnInstantiator() {
+ assertThat(registry.get(org.gradle.internal.reflect.Instantiator.class), instanceOf(ClassGeneratorBackedInstantiator.class));
+ }
+
+ @Test
+ public void providesAnExecutorFactory() {
+ assertThat(registry.get(ExecutorFactory.class), instanceOf(DefaultExecutorFactory.class));
+ }
+
+ @Test
+ public void providesAFileLockManager() {
+ assertThat(registry.get(FileLockManager.class), instanceOf(DefaultFileLockManager.class));
+ }
+
+ @Test
+ public void providesAProcessEnvironment() {
+ assertThat(registry.get(ProcessEnvironment.class), notNullValue());
+ }
+
+ @Test
+ public void providesAFileSystem() {
+ assertThat(registry.get(FileSystem.class), notNullValue());
+ }
+
+ @Test
+ public void providesAFileResolver() {
+ assertThat(registry.get(FileResolver.class), instanceOf(IdentityFileResolver.class));
+ }
+
+ @Test
+ public void providesADocumentationRegistry() throws Exception {
+ assertThat(registry.get(DocumentationRegistry.class), instanceOf(DocumentationRegistry.class));
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/internal/service/scopes/GradleScopeServicesTest.groovy b/subprojects/core/src/test/groovy/org/gradle/internal/service/scopes/GradleScopeServicesTest.groovy
new file mode 100644
index 0000000..c91a3bb
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/internal/service/scopes/GradleScopeServicesTest.groovy
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.service.scopes
+
+import org.gradle.StartParameter
+import org.gradle.api.internal.GradleInternal
+import org.gradle.api.internal.plugins.DefaultPluginContainer
+import org.gradle.api.internal.plugins.PluginRegistry
+import org.gradle.api.internal.project.DefaultProjectRegistry
+import org.gradle.api.internal.project.ProjectInternal
+import org.gradle.api.internal.project.ProjectRegistry
+import org.gradle.api.plugins.PluginContainer
+import org.gradle.cache.CacheRepository
+import org.gradle.execution.BuildExecuter
+import org.gradle.execution.DefaultBuildExecuter
+import org.gradle.execution.TaskGraphExecuter
+import org.gradle.execution.taskgraph.DefaultTaskGraphExecuter
+import org.gradle.internal.classloader.MultiParentClassLoader
+import org.gradle.internal.service.ServiceRegistry
+import org.gradle.invocation.BuildClassLoaderRegistry
+import org.gradle.listener.ListenerManager
+import spock.lang.Specification
+
+import static org.hamcrest.Matchers.sameInstance
+
+public class GradleScopeServicesTest extends Specification {
+ private GradleInternal gradle = Mock()
+ private ServiceRegistry parent = Mock()
+ private ListenerManager listenerManager = Mock()
+ private CacheRepository cacheRepository = Mock()
+ private GradleScopeServices registry = new GradleScopeServices(parent, gradle)
+ private StartParameter startParameter = new StartParameter()
+ private PluginRegistry pluginRegistryParent = Mock()
+ private PluginRegistry pluginRegistryChild = Mock()
+
+ public void setup() {
+ parent.get(StartParameter) >> Mock(StartParameter)
+ parent.get(ListenerManager) >> listenerManager
+ parent.get(CacheRepository) >> cacheRepository
+ parent.get(PluginRegistry) >> pluginRegistryParent
+ parent.get(BuildClassLoaderRegistry) >> Stub(BuildClassLoaderRegistry)
+ gradle.getStartParameter() >> startParameter
+ gradle.getScriptClassLoader() >> new MultiParentClassLoader()
+ pluginRegistryParent.createChild(_, _) >> pluginRegistryChild
+ }
+
+ def "can create services for a project instance"() {
+ ProjectInternal project = Mock()
+
+ when:
+ ServiceRegistryFactory serviceRegistry = registry.createFor(project)
+
+ then:
+ serviceRegistry instanceof ProjectScopeServices
+ }
+
+ def "provides a project registry"() {
+ when:
+ def projectRegistry = registry.get(ProjectRegistry)
+ def secondRegistry = registry.get(ProjectRegistry)
+
+ then:
+ projectRegistry instanceof DefaultProjectRegistry
+ projectRegistry sameInstance(secondRegistry)
+ }
+
+ def "provides a plugin registry"() {
+ when:
+ def pluginRegistry = registry.get(PluginRegistry)
+ def secondRegistry = registry.get(PluginRegistry)
+
+ then:
+ pluginRegistry == pluginRegistryChild
+ secondRegistry sameInstance(pluginRegistry)
+ }
+
+ def "provides a build executer"() {
+ when:
+ def buildExecuter = registry.get(BuildExecuter)
+ def secondExecuter = registry.get(BuildExecuter)
+
+ then:
+ buildExecuter instanceof DefaultBuildExecuter
+ buildExecuter sameInstance(secondExecuter)
+ }
+
+ def "provides a plugin container"() {
+ when:
+ def pluginContainer = registry.get(PluginContainer)
+ def secondPluginContainer = registry.get(PluginContainer)
+
+ then:
+ pluginContainer instanceof DefaultPluginContainer
+ secondPluginContainer sameInstance(pluginContainer)
+ }
+
+ def "provides a task graph executer"() {
+ when:
+ def graphExecuter = registry.get(TaskGraphExecuter)
+ def secondExecuter = registry.get(TaskGraphExecuter)
+
+ then:
+ graphExecuter instanceof DefaultTaskGraphExecuter
+ graphExecuter sameInstance(secondExecuter)
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/internal/service/scopes/ProjectScopeServicesTest.groovy b/subprojects/core/src/test/groovy/org/gradle/internal/service/scopes/ProjectScopeServicesTest.groovy
new file mode 100644
index 0000000..3b5cffa
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/internal/service/scopes/ProjectScopeServicesTest.groovy
@@ -0,0 +1,222 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.service.scopes
+
+import org.gradle.api.AntBuilder
+import org.gradle.api.artifacts.dsl.ArtifactHandler
+import org.gradle.api.artifacts.dsl.DependencyHandler
+import org.gradle.api.artifacts.dsl.RepositoryHandler
+import org.gradle.api.initialization.dsl.ScriptHandler
+import org.gradle.api.internal.*
+import org.gradle.api.internal.artifacts.ArtifactPublicationServices
+import org.gradle.api.internal.artifacts.DependencyManagementServices
+import org.gradle.api.internal.artifacts.DependencyResolutionServices
+import org.gradle.api.internal.artifacts.configurations.ConfigurationContainerInternal
+import org.gradle.api.internal.artifacts.dsl.dependencies.DependencyFactory
+import org.gradle.api.internal.file.*
+import org.gradle.api.internal.initialization.DefaultScriptHandler
+import org.gradle.api.internal.initialization.ScriptClassLoaderProvider
+import org.gradle.api.internal.plugins.DefaultPluginContainer
+import org.gradle.api.internal.plugins.PluginRegistry
+import org.gradle.api.internal.project.DefaultAntBuilderFactory
+import org.gradle.api.internal.project.ProjectInternal
+import org.gradle.api.internal.project.taskfactory.ITaskFactory
+import org.gradle.api.internal.tasks.DefaultTaskContainerFactory
+import org.gradle.api.internal.tasks.TaskContainerInternal
+import org.gradle.api.logging.LoggingManager
+import org.gradle.api.plugins.PluginContainer
+import org.gradle.configuration.project.DefaultProjectConfigurationActionContainer
+import org.gradle.configuration.project.ProjectConfigurationActionContainer
+import org.gradle.groovy.scripts.ScriptSource
+import org.gradle.initialization.ProjectAccessListener
+import org.gradle.internal.Factory
+import org.gradle.internal.reflect.DirectInstantiator
+import org.gradle.internal.reflect.Instantiator
+import org.gradle.internal.service.ServiceRegistry
+import org.gradle.internal.nativeplatform.filesystem.FileSystem
+import org.gradle.invocation.BuildClassLoaderRegistry
+import org.gradle.logging.LoggingManagerInternal
+import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry
+import org.gradle.tooling.provider.model.internal.DefaultToolingModelBuilderRegistry
+
+import spock.lang.Specification
+
+class ProjectScopeServicesTest extends Specification {
+ ProjectInternal project = Mock()
+ ConfigurationContainerInternal configurationContainer = Mock()
+ GradleInternal gradle = Mock()
+ DependencyManagementServices dependencyManagementServices = Mock()
+ ITaskFactory taskFactory = Mock()
+ DependencyFactory dependencyFactory = Mock()
+ ServiceRegistry parent = Stub()
+ ProjectScopeServices registry = new ProjectScopeServices(parent, project)
+ PluginRegistry pluginRegistry = Mock()
+ DependencyResolutionServices dependencyResolutionServices = Stub()
+ RepositoryHandler repositoryHandler = Mock()
+ ArtifactPublicationServices publicationServices = Mock()
+ DependencyHandler dependencyHandler = Mock()
+ ArtifactHandler artifactHandler = Mock()
+
+ def setup() {
+ project.gradle >> gradle
+ project.projectDir >> new File("project-dir").absoluteFile
+ project.buildScriptSource >> Stub(ScriptSource)
+ parent.get(ITaskFactory) >> taskFactory
+ parent.get(DependencyFactory) >> dependencyFactory
+ parent.get(PluginRegistry) >> pluginRegistry
+ parent.get(DependencyManagementServices) >> dependencyManagementServices
+ parent.get(Instantiator) >> new DirectInstantiator()
+ parent.get(FileSystem) >> Stub(FileSystem)
+ parent.get(ClassGenerator) >> Stub(ClassGenerator)
+ parent.get(ProjectAccessListener) >> Stub(ProjectAccessListener)
+ parent.get(BuildClassLoaderRegistry) >> Stub(BuildClassLoaderRegistry) {
+ getScriptClassLoader() >> new ClassLoader() { }
+ }
+ }
+
+ def "creates a registry for a task"() {
+ expect:
+ registry.createFor(Stub(TaskInternal)) instanceof TaskScopeServices
+ }
+
+ def "provides a TaskContainerFactory"() {
+ 1 * taskFactory.createChild({ it.is project }, { it instanceof ClassGeneratorBackedInstantiator }) >> Stub(ITaskFactory)
+
+ expect:
+ registry.getFactory(TaskContainerInternal) instanceof DefaultTaskContainerFactory
+ }
+
+ def "provides a PluginContainer"() {
+ expectScriptClassLoaderProviderCreated()
+
+ 1 * pluginRegistry.createChild(!null, _ as DependencyInjectingInstantiator) >> Stub(PluginRegistry)
+
+ expect:
+ provides(PluginContainer, DefaultPluginContainer)
+ }
+
+ def "provides a ToolingModelBuilderRegistry"() {
+ expect:
+ provides(ToolingModelBuilderRegistry, DefaultToolingModelBuilderRegistry)
+ }
+
+ def "provides an ArtifactPublicationServices factory"() {
+ expectDependencyResolutionServicesCreated()
+
+ expect:
+ registry.get(ArtifactPublicationServices).is publicationServices
+ }
+
+ def "provides a RepositoryHandler"() {
+ expectDependencyResolutionServicesCreated()
+
+ expect:
+ registry.get(RepositoryHandler).is repositoryHandler
+ registry.get(RepositoryHandler).is registry.get(RepositoryHandler)
+ }
+
+ def "provides a ConfigurationContainer"() {
+ expectDependencyResolutionServicesCreated()
+
+ expect:
+ registry.get(ConfigurationContainerInternal).is configurationContainer
+ registry.get(ConfigurationContainerInternal).is registry.get(ConfigurationContainerInternal)
+ }
+
+ def "provides an ArtifactHandler"() {
+ expectDependencyResolutionServicesCreated()
+
+ registry.get(ArtifactHandler).is artifactHandler
+ registry.get(ArtifactHandler).is registry.get(ArtifactHandler)
+ }
+
+ def "provides a DependencyHandler"() {
+ expectDependencyResolutionServicesCreated()
+
+ expect:
+ registry.get(DependencyHandler).is dependencyHandler
+ registry.get(DependencyHandler).is registry.get(DependencyHandler)
+ }
+
+ def "provides an AntBuilder factory"() {
+ expect:
+ registry.getFactory(AntBuilder) instanceof DefaultAntBuilderFactory
+ registry.getFactory(AntBuilder).is registry.getFactory(AntBuilder)
+ }
+
+ def "provides a ScriptHandler and ScriptClassLoaderProvider"() {
+ expectScriptClassLoaderProviderCreated()
+
+ expect:
+ provides(ScriptHandler, DefaultScriptHandler)
+ registry.get(ScriptClassLoaderProvider).is registry.get(ScriptHandler)
+ }
+
+ def "provides a FileResolver"() {
+ expect:
+ provides(FileResolver, BaseDirFileResolver)
+ }
+
+ def "provides a FileOperations instance"() {
+ 1 * project.tasks
+
+ expect:
+ provides(FileOperations, DefaultFileOperations)
+ }
+
+ def "provides a TemporaryFileProvider"() {
+ expect:
+ provides(TemporaryFileProvider, DefaultTemporaryFileProvider)
+ }
+
+ def "provides a ProjectConfigurationActionContainer"() {
+ expect:
+ provides(ProjectConfigurationActionContainer, DefaultProjectConfigurationActionContainer)
+ }
+
+ def "provides a LoggingManager"() {
+ Factory<LoggingManagerInternal> loggingManagerFactory = Mock()
+ LoggingManager loggingManager = Mock(LoggingManagerInternal)
+
+ parent.getFactory(LoggingManagerInternal) >> loggingManagerFactory
+ 1 * loggingManagerFactory.create() >> loggingManager
+
+ expect:
+ registry.get(LoggingManager).is loggingManager
+ registry.get(LoggingManager).is registry.get(LoggingManager)
+ }
+
+ void provides(Class<?> contractType, Class<?> implementationType) {
+ assert implementationType.isInstance(registry.get(contractType))
+ assert registry.get(contractType).is(registry.get(contractType))
+ }
+
+ private void expectScriptClassLoaderProviderCreated() {
+ 1 * dependencyManagementServices.create(!null, !null, !null, !null) >> dependencyResolutionServices
+ // return mock rather than stub; workaround for fact that Spock doesn't substitute generic method return type as it should
+ dependencyResolutionServices.configurationContainer >> Mock(ConfigurationContainerInternal)
+ }
+
+ private void expectDependencyResolutionServicesCreated() {
+ 1 * dependencyManagementServices.create(!null, !null, !null, !null) >> dependencyResolutionServices
+ dependencyResolutionServices.resolveRepositoryHandler >> repositoryHandler
+ dependencyResolutionServices.createArtifactPublicationServices() >> publicationServices
+ dependencyResolutionServices.configurationContainer >> configurationContainer
+ dependencyResolutionServices.dependencyHandler >> dependencyHandler
+ dependencyResolutionServices.artifactHandler >> artifactHandler
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/internal/service/scopes/SettingsScopeServicesTest.groovy b/subprojects/core/src/test/groovy/org/gradle/internal/service/scopes/SettingsScopeServicesTest.groovy
new file mode 100644
index 0000000..6a0d578
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/internal/service/scopes/SettingsScopeServicesTest.groovy
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.service.scopes
+
+import org.gradle.api.internal.SettingsInternal
+import org.gradle.api.internal.file.BaseDirFileResolver
+import org.gradle.api.internal.file.FileResolver
+import org.gradle.api.internal.plugins.DefaultPluginContainer
+import org.gradle.api.internal.plugins.PluginRegistry
+import org.gradle.api.plugins.PluginContainer
+import org.gradle.internal.service.ServiceRegistry
+import spock.lang.Specification
+
+import static org.hamcrest.Matchers.sameInstance
+
+class SettingsScopeServicesTest extends Specification {
+ private SettingsInternal settings = Mock()
+ private ServiceRegistry parent = Stub()
+ private SettingsScopeServices registry = new SettingsScopeServices(parent, settings)
+ private PluginRegistry pluginRegistryParent = Mock()
+ private PluginRegistry pluginRegistryChild = Mock()
+
+ def setup() {
+ settings.getSettingsDir() >> new File("settings-dir").absoluteFile
+ parent.get(org.gradle.internal.nativeplatform.filesystem.FileSystem) >> Stub(org.gradle.internal.nativeplatform.filesystem.FileSystem)
+ parent.get(PluginRegistry) >> pluginRegistryParent
+ pluginRegistryParent.createChild(_, _) >> pluginRegistryChild
+ }
+
+
+ def "provides a plugin container"() {
+ when:
+ def pluginContainer = registry.get(PluginContainer)
+ def secondPluginContainer = registry.get(PluginContainer)
+
+ then:
+ pluginContainer instanceof DefaultPluginContainer
+ secondPluginContainer sameInstance(pluginContainer)
+ }
+
+ def "provides a file resolver"() {
+ when:
+ def fileResolver = registry.get(FileResolver)
+ def secondFileResolver = registry.get(FileResolver)
+
+ then:
+ fileResolver instanceof BaseDirFileResolver
+ secondFileResolver sameInstance(fileResolver)
+ }
+
+
+ def "provides a plugin registry"() {
+ when:
+ def pluginRegistry = registry.get(PluginRegistry)
+ def secondPluginRegistry = registry.get(PluginRegistry)
+
+ then:
+ pluginRegistry == pluginRegistryChild
+ secondPluginRegistry sameInstance(pluginRegistry)
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/internal/service/scopes/TaskExecutionServicesTest.groovy b/subprojects/core/src/test/groovy/org/gradle/internal/service/scopes/TaskExecutionServicesTest.groovy
new file mode 100644
index 0000000..69cdfaf
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/internal/service/scopes/TaskExecutionServicesTest.groovy
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.service.scopes
+
+import org.gradle.StartParameter
+import org.gradle.api.internal.tasks.TaskExecuter
+import org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter
+import org.gradle.api.invocation.Gradle
+import org.gradle.cache.CacheRepository
+import org.gradle.cache.DirectoryCacheBuilder
+import org.gradle.cache.PersistentCache
+import org.gradle.internal.reflect.Instantiator
+import org.gradle.internal.service.ServiceRegistry
+import org.gradle.listener.ListenerManager
+import spock.lang.Specification
+
+class TaskExecutionServicesTest extends Specification {
+ final ServiceRegistry parent = Mock()
+ final Gradle gradle = Mock()
+ final TaskExecutionServices services = new TaskExecutionServices(parent, gradle)
+
+ def "makes a TaskExecutor available"() {
+ given:
+ ListenerManager listenerManager = Mock()
+ StartParameter startParameter = Mock()
+ CacheRepository cacheRepository = Mock()
+ Instantiator instantiator = Mock();
+ DirectoryCacheBuilder cacheBuilder = Mock()
+ PersistentCache cache = Mock()
+ _ * parent.get(ListenerManager) >> listenerManager
+ _ * parent.get(StartParameter) >> startParameter
+ _ * parent.get(CacheRepository) >> cacheRepository
+ _ * parent.get(Instantiator) >> instantiator
+ _ * cacheRepository.cache(!null) >> cacheBuilder
+ _ * cacheBuilder.forObject(gradle) >> cacheBuilder
+ _ * cacheBuilder.withDisplayName(!null) >> cacheBuilder
+ _ * cacheBuilder.withLockMode(!null) >> cacheBuilder
+ _ * cacheBuilder.open() >> cache
+
+ expect:
+ services.get(TaskExecuter) instanceof ExecuteAtMostOnceTaskExecuter
+ services.get(TaskExecuter).is(services.get(TaskExecuter))
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/internal/service/scopes/TaskScopeServicesTest.java b/subprojects/core/src/test/groovy/org/gradle/internal/service/scopes/TaskScopeServicesTest.java
new file mode 100644
index 0000000..eda529d
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/internal/service/scopes/TaskScopeServicesTest.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.service.scopes;
+
+import org.gradle.api.internal.TaskInternal;
+import org.gradle.api.internal.TaskOutputsInternal;
+import org.gradle.api.internal.file.FileResolver;
+import org.gradle.api.internal.project.ProjectInternal;
+import org.gradle.api.internal.tasks.DefaultTaskInputs;
+import org.gradle.api.internal.tasks.DefaultTaskOutputs;
+import org.gradle.api.internal.tasks.TaskStatusNagger;
+import org.gradle.api.logging.LoggingManager;
+import org.gradle.api.tasks.TaskInputs;
+import org.gradle.internal.Factory;
+import org.gradle.internal.service.ServiceRegistry;
+import org.gradle.logging.LoggingManagerInternal;
+import org.jmock.Expectations;
+import org.jmock.integration.junit4.JMock;
+import org.jmock.integration.junit4.JUnit4Mockery;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static junit.framework.Assert.assertSame;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.hamcrest.Matchers.sameInstance;
+import static org.junit.Assert.assertThat;
+
+ at RunWith(JMock.class)
+public class TaskScopeServicesTest {
+ private final JUnit4Mockery context = new JUnit4Mockery();
+ private final ServiceRegistry parent = context.mock(ServiceRegistry.class);
+ private final ProjectInternal project = context.mock(ProjectInternal.class);
+ private final TaskInternal task = context.mock(TaskInternal.class);
+ private final TaskScopeServices registry = new TaskScopeServices(parent, project, task);
+
+ @Before
+ public void setUp() {
+ context.checking(new Expectations() {{
+ allowing(project).getFileResolver();
+ will(returnValue(context.mock(FileResolver.class)));
+ }});
+ }
+
+ @Test
+ public void createsATaskInputsInstance() {
+ TaskInputs inputs = registry.get(TaskInputs.class);
+ assertThat(inputs, instanceOf(DefaultTaskInputs.class));
+ }
+
+ @Test
+ public void createsATaskOutputsInternalInstance() {
+ TaskOutputsInternal outputs = registry.get(TaskOutputsInternal.class);
+ assertThat(outputs, instanceOf(DefaultTaskOutputs.class));
+ }
+
+ @Test
+ public void createsATaskStatusNaggerInstance() {
+ TaskStatusNagger nagger = registry.get(TaskStatusNagger.class);
+ assertSame(nagger, registry.get(TaskStatusNagger.class));
+ }
+
+ @Test
+ public void createsALoggingManagerAndStdOutputCapture() {
+ final Factory<LoggingManagerInternal> loggingManagerFactory = context.mock(Factory.class);
+ final LoggingManager loggingManager = context.mock(LoggingManagerInternal.class);
+
+ context.checking(new Expectations() {{
+ allowing(parent).getFactory(LoggingManagerInternal.class);
+ will(returnValue(loggingManagerFactory));
+ one(loggingManagerFactory).create();
+ will(returnValue(loggingManager));
+ }});
+
+ assertThat(registry.get(LoggingManager.class), sameInstance(loggingManager));
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/invocation/DefaultBuildClassLoaderRegistryTest.groovy b/subprojects/core/src/test/groovy/org/gradle/invocation/DefaultBuildClassLoaderRegistryTest.groovy
new file mode 100644
index 0000000..1ea1697
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/invocation/DefaultBuildClassLoaderRegistryTest.groovy
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.invocation
+
+import org.gradle.initialization.ClassLoaderRegistry
+import org.gradle.internal.classloader.CachingClassLoader
+import org.gradle.internal.classloader.MultiParentClassLoader
+import spock.lang.Specification
+
+class DefaultBuildClassLoaderRegistryTest extends Specification {
+ final globalRegistry = Mock(ClassLoaderRegistry)
+
+ def "wires up build classloaders"() {
+ def rootClassLoader = Mock(ClassLoader)
+ def additionalClassLoader = Mock(ClassLoader)
+
+ given:
+ globalRegistry.gradleApiClassLoader >> rootClassLoader
+
+ when:
+ def registry = new DefaultBuildClassLoaderRegistry(globalRegistry)
+ def scriptLoader = registry.scriptClassLoader
+
+ then:
+ scriptLoader instanceof CachingClassLoader
+ scriptLoader.parent instanceof MultiParentClassLoader
+ scriptLoader.parent.parents == [rootClassLoader]
+
+ when:
+ registry.addRootClassLoader(additionalClassLoader)
+
+ then:
+ scriptLoader.parent.parents == [rootClassLoader, additionalClassLoader]
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/invocation/DefaultGradleTest.java b/subprojects/core/src/test/groovy/org/gradle/invocation/DefaultGradleTest.java
index f9c084e..355b2ee 100644
--- a/subprojects/core/src/test/groovy/org/gradle/invocation/DefaultGradleTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/invocation/DefaultGradleTest.java
@@ -24,20 +24,23 @@ import org.gradle.api.Project;
import org.gradle.api.ProjectEvaluationListener;
import org.gradle.api.initialization.dsl.ScriptHandler;
import org.gradle.api.internal.GradleDistributionLocator;
+import org.gradle.api.internal.file.FileResolver;
import org.gradle.api.internal.initialization.ScriptClassLoaderProvider;
import org.gradle.api.internal.plugins.PluginRegistry;
-import org.gradle.api.internal.project.IProjectRegistry;
+import org.gradle.api.internal.project.ProjectRegistry;
import org.gradle.api.internal.project.ProjectInternal;
-import org.gradle.api.internal.project.ServiceRegistryFactory;
+import org.gradle.internal.service.scopes.ServiceRegistryFactory;
import org.gradle.api.invocation.Gradle;
+import org.gradle.api.plugins.PluginContainer;
+import org.gradle.configuration.ScriptPluginFactory;
import org.gradle.execution.TaskGraphExecuter;
import org.gradle.listener.ClosureBackedMethodInvocationDispatch;
import org.gradle.listener.ListenerBroadcast;
import org.gradle.listener.ListenerManager;
import org.gradle.util.GradleVersion;
-import org.gradle.util.HelperUtil;
+import org.gradle.util.TestUtil;
import org.gradle.util.JUnit4GroovyMockery;
-import org.gradle.util.MultiParentClassLoader;
+import org.gradle.internal.classloader.MultiParentClassLoader;
import org.jmock.Expectations;
import org.jmock.integration.junit4.JMock;
import org.jmock.integration.junit4.JUnit4Mockery;
@@ -60,7 +63,7 @@ public class DefaultGradleTest {
private final ScriptHandler scriptHandlerMock = context.mock(ScriptHandler.class);
private final ServiceRegistryFactory serviceRegistryFactoryMock = context.mock(ServiceRegistryFactory.class, "parent");
private final ServiceRegistryFactory gradleServiceRegistryMock = context.mock(ServiceRegistryFactory.class, "gradle");
- private final IProjectRegistry projectRegistry = context.mock(IProjectRegistry.class);
+ private final ProjectRegistry projectRegistry = context.mock(ProjectRegistry.class);
private final PluginRegistry pluginRegistry = context.mock(PluginRegistry.class);
private final TaskGraphExecuter taskExecuter = context.mock(TaskGraphExecuter.class);
private final ListenerManager listenerManager = context.mock(ListenerManager.class);
@@ -69,6 +72,10 @@ public class DefaultGradleTest {
private final GradleDistributionLocator gradleDistributionLocatorMock = context.mock(GradleDistributionLocator.class);
private final ListenerBroadcast<BuildListener> buildListenerBroadcast = new ListenerBroadcast<BuildListener>(BuildListener.class);
private final ListenerBroadcast<ProjectEvaluationListener> projectEvaluationListenerBroadcast = context.mock(ListenerBroadcast.class);
+ private final FileResolver fileResolverMock = context.mock(FileResolver.class);
+ private final PluginContainer pluginContainer = context.mock(PluginContainer.class);
+ private final ScriptPluginFactory scriptPluginFactory= context.mock(ScriptPluginFactory.class);
+
private DefaultGradle gradle;
@Before
@@ -80,7 +87,7 @@ public class DefaultGradleTest {
will(returnValue(scriptHandlerMock));
allowing(gradleServiceRegistryMock).get(ScriptClassLoaderProvider.class);
will(returnValue(context.mock(ScriptClassLoaderProvider.class)));
- allowing(gradleServiceRegistryMock).get(IProjectRegistry.class);
+ allowing(gradleServiceRegistryMock).get(ProjectRegistry.class);
will(returnValue(projectRegistry));
allowing(gradleServiceRegistryMock).get(PluginRegistry.class);
will(returnValue(pluginRegistry));
@@ -92,6 +99,12 @@ public class DefaultGradleTest {
will(returnValue(scriptClassLoaderMock));
allowing(gradleServiceRegistryMock).get(GradleDistributionLocator.class);
will(returnValue(gradleDistributionLocatorMock));
+ allowing(gradleServiceRegistryMock).get(PluginContainer.class);
+ will(returnValue(pluginContainer));
+ allowing(gradleServiceRegistryMock).get(FileResolver.class);
+ will(returnValue(fileResolverMock));
+ allowing(gradleServiceRegistryMock).get(ScriptPluginFactory.class);
+ will(returnValue(scriptPluginFactory));
allowing(listenerManager).createAnonymousBroadcaster(BuildListener.class);
will(returnValue(buildListenerBroadcast));
allowing(listenerManager).createAnonymousBroadcaster(ProjectEvaluationListener.class);
@@ -145,7 +158,7 @@ public class DefaultGradleTest {
@Test
public void broadcastsBeforeProjectEvaluateEventsToClosures() {
- final Closure closure = HelperUtil.TEST_CLOSURE;
+ final Closure closure = TestUtil.TEST_CLOSURE;
context.checking(new Expectations() {{
one(projectEvaluationListenerBroadcast).add(new ClosureBackedMethodInvocationDispatch("beforeEvaluate", closure));
}});
@@ -155,7 +168,7 @@ public class DefaultGradleTest {
@Test
public void broadcastsAfterProjectEvaluateEventsToClosures() {
- final Closure closure = HelperUtil.TEST_CLOSURE;
+ final Closure closure = TestUtil.TEST_CLOSURE;
context.checking(new Expectations() {{
one(projectEvaluationListenerBroadcast).add(new ClosureBackedMethodInvocationDispatch("afterEvaluate", closure));
}});
diff --git a/subprojects/core/src/test/groovy/org/gradle/logging/internal/DefaultLoggingManagerTest.java b/subprojects/core/src/test/groovy/org/gradle/logging/internal/DefaultLoggingManagerTest.java
index ebc82e4..920e5c3 100644
--- a/subprojects/core/src/test/groovy/org/gradle/logging/internal/DefaultLoggingManagerTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/logging/internal/DefaultLoggingManagerTest.java
@@ -25,11 +25,9 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
-/**
- * @author Hans Dockter
- */
@RunWith(JMock.class)
public class DefaultLoggingManagerTest {
@Rule
diff --git a/subprojects/core/src/test/groovy/org/gradle/logging/internal/LoggingCommandLineConverterTest.groovy b/subprojects/core/src/test/groovy/org/gradle/logging/internal/LoggingCommandLineConverterTest.groovy
index 0ee9f1e..e77d3cf 100644
--- a/subprojects/core/src/test/groovy/org/gradle/logging/internal/LoggingCommandLineConverterTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/logging/internal/LoggingCommandLineConverterTest.groovy
@@ -61,7 +61,7 @@ class LoggingCommandLineConverterTest extends Specification {
}
def convertsShowStacktrace() {
- expectedConfig.showStacktrace = ShowStacktrace.ALWAYS;
+ expectedConfig.showStacktrace = ShowStacktrace.ALWAYS
expect:
checkConversion(['-s'])
@@ -69,17 +69,25 @@ class LoggingCommandLineConverterTest extends Specification {
}
def convertsShowFullStacktrace() {
- expectedConfig.showStacktrace = ShowStacktrace.ALWAYS_FULL;
+ expectedConfig.showStacktrace = ShowStacktrace.ALWAYS_FULL
expect:
checkConversion(['-S'])
checkConversion(['--full-stacktrace'])
}
+ def usesLastLogLevelAndStacktraceOption() {
+ expectedConfig.showStacktrace = ShowStacktrace.ALWAYS_FULL
+ expectedConfig.logLevel = LogLevel.QUIET
+
+ expect:
+ checkConversion(['-s', '--debug', '-q', '--full-stacktrace'])
+ }
+
def providesLogLevelOptions() {
expect:
- converter.logLevelOptions.containsAll(["d", "q", "i"])
- converter.logLevelOptions.size() == 3
+ converter.logLevelOptions == ["d", "q", "i"] as Set
+ converter.logLevels == [LogLevel.DEBUG, LogLevel.INFO, LogLevel.LIFECYCLE, LogLevel.QUIET] as Set
}
void checkConversion(List<String> args) {
diff --git a/subprojects/core/src/test/groovy/org/gradle/model/internal/PersistentModelObjectRegistryTest.groovy b/subprojects/core/src/test/groovy/org/gradle/model/internal/PersistentModelObjectRegistryTest.groovy
new file mode 100644
index 0000000..8860477
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/model/internal/PersistentModelObjectRegistryTest.groovy
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.model.internal
+
+import org.gradle.model.ModelType
+import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
+import org.junit.Rule
+import spock.lang.Ignore
+import spock.lang.Specification
+
+class PersistentModelObjectRegistryTest extends Specification {
+ @Rule TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider()
+
+ def "persists the public properties of a Groovy model object"() {
+ def model = new GroovyTestModel(prop1: "value", prop2: 12, prop3: ["a", "b", "c"])
+ def storeFile = tmpDir.file("model.bin")
+
+ when:
+ def writeRegistry = new PersistentModelObjectRegistry(storeFile)
+ writeRegistry.put("a", model)
+ writeRegistry.close()
+
+ def readRegistry = new PersistentModelObjectRegistry(storeFile)
+ def result = readRegistry.get("a", GroovyTestModel)
+ readRegistry.close()
+
+ then:
+ result instanceof GroovyTestModel
+ result != model
+ result.prop1 == model.prop1
+ result.prop2 == model.prop2
+ result.prop3 == model.prop3
+ }
+
+ def "persists the public properties of a Java model object"() {
+ def model = new TestModel(prop1: "value", prop2: 12, prop3: ["a", "b", "c"])
+ def storeFile = tmpDir.file("model.bin")
+
+ when:
+ def writeRegistry = new PersistentModelObjectRegistry(storeFile)
+ writeRegistry.put("a", model)
+ writeRegistry.close()
+
+ def readRegistry = new PersistentModelObjectRegistry(storeFile)
+ def result = readRegistry.get("a", TestModel)
+ readRegistry.close()
+
+ then:
+ result instanceof TestModel
+ result != model
+ result.prop1 == model.prop1
+ result.prop2 == model.prop2
+ result.prop3 == model.prop3
+ }
+
+ def "cannot put an object which is not a model object"() {
+ def storeFile = tmpDir.file("model.bin")
+ def registry = new PersistentModelObjectRegistry(storeFile)
+
+ when:
+ registry.put("a", 12)
+
+ then:
+ IllegalArgumentException e = thrown()
+ e.message == 'Cannot persist object of class Integer, as this class is not marked @ModelType'
+
+ cleanup:
+ registry.close()
+ }
+
+ def "model object can reference another model object"() {
+ def storeFile = tmpDir.file("model.bin")
+ def child = new TestModel(prop1: "child")
+ def parent = new ParentModel(child: child, child2: child)
+
+ when:
+ def writeRegistry = new PersistentModelObjectRegistry(storeFile)
+ writeRegistry.put("child", child)
+ writeRegistry.put("parent", parent)
+ writeRegistry.close()
+
+ def readRegistry = new PersistentModelObjectRegistry(storeFile)
+ def result = readRegistry.get("parent", ParentModel)
+ readRegistry.close()
+
+ then:
+ result.child instanceof TestModel
+ result.child.prop1 == "child"
+ result.child.is(result.child2)
+ }
+
+ def "model object instance is reused"() {
+ def storeFile = tmpDir.file("model.bin")
+ def child = new TestModel(prop1: "child")
+ def parent1 = new ParentModel(child: child)
+ def parent2 = new ParentModel(child: child)
+
+ when:
+ def writeRegistry = new PersistentModelObjectRegistry(storeFile)
+ writeRegistry.put("child", child)
+ writeRegistry.put("parent1", parent1)
+ writeRegistry.put("parent2", parent2)
+ writeRegistry.close()
+
+ def readRegistry = new PersistentModelObjectRegistry(storeFile)
+ def result1 = readRegistry.get("parent1", ParentModel)
+ def result2 = readRegistry.get("parent2", ParentModel)
+ readRegistry.close()
+
+ then:
+ result1.child.is(result2.child)
+ }
+
+ def "returns null when object with given identifier is not present"() {
+ def storeFile = tmpDir.file("model.bin")
+ def registry = new PersistentModelObjectRegistry(storeFile)
+
+ expect:
+ registry.get("some-id", TestModel) == null
+
+ cleanup:
+ registry.close()
+ }
+
+ @Ignore
+ def "rethrows failure to get the value of a property"() {
+ expect: false
+ }
+
+ @Ignore
+ def "rethrows failure to construct an instance"() {
+ expect: false
+ }
+
+ @Ignore
+ def "rethrows failure to set the value of a property"() {
+ expect: false
+ }
+
+ @ModelType
+ static class GroovyTestModel {
+ String prop1
+ int prop2
+ List<String> prop3
+ }
+
+ @ModelType
+ static class ParentModel {
+ Object child
+ Object child2
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/model/internal/TestModel.java b/subprojects/core/src/test/groovy/org/gradle/model/internal/TestModel.java
new file mode 100644
index 0000000..18489e6
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/model/internal/TestModel.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.model.internal;
+
+import org.gradle.model.ModelType;
+
+import java.util.List;
+
+ at ModelType
+public class TestModel {
+ private String prop1;
+ private int prop2;
+ private List<String> prop3;
+
+ public String getProp1() {
+ return prop1;
+ }
+
+ public void setProp1(String prop1) {
+ this.prop1 = prop1;
+ }
+
+ public int getProp2() {
+ return prop2;
+ }
+
+ public void setProp2(int prop2) {
+ this.prop2 = prop2;
+ }
+
+ public List<String> getProp3() {
+ return prop3;
+ }
+
+ public void setProp3(List<String> prop3) {
+ this.prop3 = prop3;
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/process/internal/DefaultExecHandleSpec.groovy b/subprojects/core/src/test/groovy/org/gradle/process/internal/DefaultExecHandleSpec.groovy
index 8707311..93f9470 100644
--- a/subprojects/core/src/test/groovy/org/gradle/process/internal/DefaultExecHandleSpec.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/process/internal/DefaultExecHandleSpec.groovy
@@ -28,9 +28,6 @@ import spock.lang.Timeout
import java.util.concurrent.Callable
-/**
- * @author Tom Eyckmans, Szczepan Faber
- */
@Timeout(60)
class DefaultExecHandleSpec extends Specification {
@Rule final TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider();
diff --git a/subprojects/core/src/test/groovy/org/gradle/process/internal/DefaultWorkerProcessTest.groovy b/subprojects/core/src/test/groovy/org/gradle/process/internal/DefaultWorkerProcessTest.groovy
index 2265f3c..e7d06f9 100644
--- a/subprojects/core/src/test/groovy/org/gradle/process/internal/DefaultWorkerProcessTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/process/internal/DefaultWorkerProcessTest.groovy
@@ -82,7 +82,7 @@ class DefaultWorkerProcessTest extends MultithreadedTestCase {
workerProcess.start()
fail()
} catch (ExecException e) {
- assertThat(e.message, equalTo("Timeout after waiting 1.0 seconds for $execHandle (STARTED, running: true) to connect." as String))
+ assertThat(e.message, equalTo(String.format("Timeout after waiting %.1f seconds for $execHandle (STARTED, running: true) to connect." as String, 1d)))
}
}
}
diff --git a/subprojects/core/src/test/groovy/org/gradle/process/internal/JavaExecHandleBuilderTest.groovy b/subprojects/core/src/test/groovy/org/gradle/process/internal/JavaExecHandleBuilderTest.groovy
index 53c3f7f..6431379 100644
--- a/subprojects/core/src/test/groovy/org/gradle/process/internal/JavaExecHandleBuilderTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/process/internal/JavaExecHandleBuilderTest.groovy
@@ -13,20 +13,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.gradle.process.internal;
+package org.gradle.process.internal
-
-import org.gradle.api.internal.file.FileResolver
-import org.gradle.api.internal.file.IdentityFileResolver
+import org.gradle.api.internal.file.TestFiles
import org.gradle.internal.jvm.Jvm
import spock.lang.Specification
-import static java.util.Arrays.asList
-import java.nio.charset.Charset
import spock.lang.Unroll
+import java.nio.charset.Charset
+
+import static java.util.Arrays.asList
+
public class JavaExecHandleBuilderTest extends Specification {
- FileResolver fileResolver = new IdentityFileResolver()
- JavaExecHandleBuilder builder = new JavaExecHandleBuilder(fileResolver)
+ JavaExecHandleBuilder builder = new JavaExecHandleBuilder(TestFiles.resolver())
public void cannotSetAllJvmArgs() {
when:
diff --git a/subprojects/core/src/test/groovy/org/gradle/process/internal/JvmOptionsTest.groovy b/subprojects/core/src/test/groovy/org/gradle/process/internal/JvmOptionsTest.groovy
index 9f2837f..b8ba5be 100755
--- a/subprojects/core/src/test/groovy/org/gradle/process/internal/JvmOptionsTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/process/internal/JvmOptionsTest.groovy
@@ -18,14 +18,12 @@
package org.gradle.process.internal
-import org.gradle.api.internal.file.IdentityFileResolver
-import spock.lang.Specification
+import org.gradle.api.internal.file.TestFiles
import org.gradle.process.JavaForkOptions
+import spock.lang.Specification
+
import java.nio.charset.Charset
-/**
- * by Szczepan Faber, created at: 2/13/12
- */
class JvmOptionsTest extends Specification {
final String defaultCharset = Charset.defaultCharset().name()
@@ -186,7 +184,7 @@ class JvmOptionsTest extends Specification {
}
private JvmOptions createOpts() {
- return new JvmOptions(new IdentityFileResolver())
+ return new JvmOptions(TestFiles.resolver())
}
private JvmOptions parse(String optsString) {
diff --git a/subprojects/core/src/test/groovy/org/gradle/process/internal/child/ImplementationClassLoaderWorkerTest.java b/subprojects/core/src/test/groovy/org/gradle/process/internal/child/ImplementationClassLoaderWorkerTest.java
index 5847570..42ebb24 100644
--- a/subprojects/core/src/test/groovy/org/gradle/process/internal/child/ImplementationClassLoaderWorkerTest.java
+++ b/subprojects/core/src/test/groovy/org/gradle/process/internal/child/ImplementationClassLoaderWorkerTest.java
@@ -20,7 +20,7 @@ import org.gradle.api.Action;
import org.gradle.api.logging.LogLevel;
import org.gradle.logging.LoggingManagerInternal;
import org.gradle.util.JUnit4GroovyMockery;
-import org.gradle.util.MutableURLClassLoader;
+import org.gradle.internal.classloader.MutableURLClassLoader;
import org.jmock.Expectations;
import org.jmock.integration.junit4.JMock;
import org.jmock.integration.junit4.JUnit4Mockery;
diff --git a/subprojects/core/src/test/groovy/org/gradle/process/internal/child/SerializableMockHelper.groovy b/subprojects/core/src/test/groovy/org/gradle/process/internal/child/SerializableMockHelper.groovy
index 252a31a..5061b8c 100644
--- a/subprojects/core/src/test/groovy/org/gradle/process/internal/child/SerializableMockHelper.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/process/internal/child/SerializableMockHelper.groovy
@@ -20,17 +20,15 @@ package org.gradle.process.internal.child
import groovyjarjarasm.asm.ClassVisitor
import groovyjarjarasm.asm.ClassWriter
-import java.util.concurrent.atomic.AtomicInteger
import org.codehaus.groovy.ast.ClassNode
import org.codehaus.groovy.control.CompilationUnit
import org.codehaus.groovy.control.CompilationUnit.ClassgenCallback
import org.codehaus.groovy.control.Phases
import org.gradle.api.Action
-class SerializableMockHelper { /**
- * @author Hans Dockter
- */
- static final Map ACTIONS = [:]
+import java.util.concurrent.atomic.AtomicInteger
+
+class SerializableMockHelper { static final Map ACTIONS = [:]
private final AtomicInteger counter = new AtomicInteger()
/**
diff --git a/subprojects/core/src/test/groovy/org/gradle/profile/BuildProfileTest.groovy b/subprojects/core/src/test/groovy/org/gradle/profile/BuildProfileTest.groovy
index 68a51da..2d6ac7c 100644
--- a/subprojects/core/src/test/groovy/org/gradle/profile/BuildProfileTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/profile/BuildProfileTest.groovy
@@ -15,52 +15,82 @@
*/
package org.gradle.profile
+import org.gradle.StartParameter
+import org.gradle.api.tasks.TaskState
import spock.lang.Specification
-import org.gradle.api.invocation.Gradle
-import org.gradle.api.artifacts.ResolvableDependencies
-import org.gradle.api.Project
class BuildProfileTest extends Specification {
- final Gradle gradle = Mock()
- final BuildProfile profile = new BuildProfile(gradle)
+ private profile = new BuildProfile(new StartParameter())
def "creates dependency set profile on first get"() {
+ expect:
+ def dependencyProfile = profile.getDependencySetProfile("path")
+ dependencyProfile != null
+ profile.getDependencySetProfile("path") == dependencyProfile
+ }
+
+ def "provides sorted dependency set profiles"() {
given:
- ResolvableDependencies deps = dependencySet("path")
+ def a = profile.getDependencySetProfile("a").setStart(100).setFinish(200)
+ def b = profile.getDependencySetProfile("b").setStart(200).setFinish(400)
+ def c = profile.getDependencySetProfile("c").setStart(400).setFinish(600)
+ def d = profile.getDependencySetProfile("d").setStart(600).setFinish(601)
expect:
- def dependencyProfile = profile.getDependencySetProfile(deps)
- dependencyProfile != null
- profile.getDependencySetProfile(deps) == dependencyProfile
+ profile.dependencySets.operations == [b, c, a, d]
}
- def "can get all dependency set profiles"() {
+ def "provides sorted configuration profiles"() {
given:
- def a = profile.getDependencySetProfile(dependencySet("a"))
- def b = profile.getDependencySetProfile(dependencySet("b"))
+ def a = profile.getProjectProfile("a").configurationOperation.setStart(100).setFinish(200)
+ def b = profile.getProjectProfile("b").configurationOperation.setStart(200).setFinish(500)
+ def c = profile.getProjectProfile("c").configurationOperation.setStart(500).setFinish(800)
+ def d = profile.getProjectProfile("d").configurationOperation.setStart(800).setFinish(850)
expect:
- profile.dependencySets.operations == [a, b]
+ profile.projectConfiguration.operations == [b, c, a, d]
}
- def "can get all project configuration profiles"() {
+ def "provides sorted project profiles"() {
given:
- def a = profile.getProjectProfile(project("a"))
- def b = profile.getProjectProfile(project("b"))
+ profile.getProjectProfile("a").getTaskProfile("a:x").completed(Stub(TaskState)).setStart(100).setFinish(300)
+ profile.getProjectProfile("b").getTaskProfile("b:x").completed(Stub(TaskState)).setStart(300).setFinish(300)
+ profile.getProjectProfile("c").getTaskProfile("c:x").completed(Stub(TaskState)).setStart(300).setFinish(300)
+ profile.getProjectProfile("d").getTaskProfile("d:x").completed(Stub(TaskState)).setStart(301).setFinish(302)
expect:
- profile.projectConfiguration.operations == [a.evaluation, b.evaluation]
+ profile.projects == [profile.getProjectProfile("a"), profile.getProjectProfile("d"), profile.getProjectProfile("b"), profile.getProjectProfile("c")]
+ }
+
+ def "contains build description"() {
+ given:
+ def param = new StartParameter()
+ param.setTaskNames(["foo", "bar"])
+ param.setExcludedTaskNames(["one", "two"])
+
+ when:
+ profile = new BuildProfile(param)
+
+ then:
+ profile.buildDescription.contains(" -x one -x two foo bar")
}
- def dependencySet(String path) {
- ResolvableDependencies dependencies = Mock()
- _ * dependencies.path >> path
- return dependencies
+ def "build description looks nice even if no tasks specified"() {
+ given:
+ def param = new StartParameter()
+
+ when:
+ profile = new BuildProfile(param)
+
+ then:
+ profile.buildDescription.contains(" (no tasks specified)")
}
- def project(String path) {
- Project project = Mock()
- _ * project.path >> path
- return project
+ def "provides start time description"() {
+ when:
+ profile.buildStarted = new GregorianCalendar(2010, 1, 1, 12, 25).getTimeInMillis()
+
+ then:
+ profile.buildStartedDescription == "Started on: 2010/02/01 - 12:25:00"
}
}
diff --git a/subprojects/core/src/test/groovy/org/gradle/profile/ProfileReportRendererTest.groovy b/subprojects/core/src/test/groovy/org/gradle/profile/ProfileReportRendererTest.groovy
new file mode 100644
index 0000000..dd95aa3
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/profile/ProfileReportRendererTest.groovy
@@ -0,0 +1,227 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.profile
+
+import org.gradle.StartParameter
+import org.gradle.api.tasks.TaskState
+import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
+import org.junit.Rule
+import spock.lang.Specification
+
+import static org.gradle.util.TextUtil.toPlatformLineSeparators
+
+class ProfileReportRendererTest extends Specification {
+
+ @Rule TestNameTestDirectoryProvider temp = new TestNameTestDirectoryProvider()
+
+ def "renders report"() {
+ def model = new BuildProfile(new StartParameter())
+ def file = temp.file("report.html")
+
+ model.profilingStarted = time(12, 20, 0)
+ model.buildStarted = time(12, 20, 0, 700)
+ model.settingsEvaluated = time(12, 20, 3)
+ model.projectsLoaded = time(12, 20, 6)
+
+ model.buildFinished = time(12, 35, 30)
+
+ model.getDependencySetProfile("compile").start = time(12, 22, 0)
+ model.getDependencySetProfile("compile").finish = time(12, 23, 30)
+
+ model.getDependencySetProfile("runtime").start = time(12, 24, 0)
+ model.getDependencySetProfile("runtime").finish = time(12, 24, 30)
+
+ model.getProjectProfile("a").configurationOperation.start = time(12, 20, 7)
+ model.getProjectProfile("a").configurationOperation.finish = time(12, 20, 10)
+ model.getProjectProfile("a").getTaskProfile("a:foo").completed(Stub(TaskState)).setStart(time(12, 25, 0)).setFinish(time(12, 26, 30))
+ model.getProjectProfile("a").getTaskProfile("a:bar").completed(Stub(TaskState)).setStart(time(12, 26, 30)).setFinish(time(12, 27, 0))
+
+ model.getProjectProfile("b").configurationOperation.start = time(12, 20, 10)
+ model.getProjectProfile("b").configurationOperation.finish = time(12, 20, 15)
+ //let's say they run in parallel, hence same start time
+ model.getProjectProfile("b").getTaskProfile("b:foo").completed(Stub(TaskState)).setStart(time(12, 27, 0)).setFinish(time(12, 29, 30))
+ model.getProjectProfile("b").getTaskProfile("b:bar").completed(Stub(TaskState)).setStart(time(12, 27, 0)).setFinish(time(12, 29, 0))
+
+ when:
+ new ProfileReportRenderer().writeTo(model, file)
+
+ then:
+ println file
+ println file.text
+ file.text.contains(toPlatformLineSeparators("""<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<meta httpEquiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>Profile report</title>
+<link href="base-style.css" rel="stylesheet" type="text/css"/>
+<link href="style.css" rel="stylesheet" type="text/css"/>
+<script src="report.js" type="text/javascript"></script>
+</head>
+<body>
+<div id="content">
+<h1>Profile report</h1>
+<div id="header">
+<p>Profiled build: (no tasks specified)</p>
+<p>Started on: 2010/02/05 - 12:20:00</p>
+</div>
+<div id="tabs">
+<ul class="tabLinks">
+<li>
+<a href="#tab0">Summary</a>
+</li>
+<li>
+<a href="#tab1">Configuration</a>
+</li>
+<li>
+<a href="#tab2">Dependency Resolution</a>
+</li>
+<li>
+<a href="#tab3">Task Execution</a>
+</li>
+</ul>
+<div class="tab" id="tab0">
+<h2>Summary</h2>
+<table>
+<thead>
+<tr>
+<th>Description</th>
+<th class="numeric">Duration</th>
+</tr>
+</thead>
+<tr>
+<td>Total Build Time</td>
+<td class="numeric">15m30.00s</td>
+</tr>
+<tr>
+<td>Startup</td>
+<td class="numeric">0.700s</td>
+</tr>
+<tr>
+<td>Settings and BuildSrc</td>
+<td class="numeric">2.300s</td>
+</tr>
+<tr>
+<td>Loading Projects</td>
+<td class="numeric">3.000s</td>
+</tr>
+<tr>
+<td>Configuring Projects</td>
+<td class="numeric">8.000s</td>
+</tr>
+<tr>
+<td>Task Execution</td>
+<td class="numeric">6m30.00s</td>
+</tr>
+</table>
+</div>
+<div class="tab" id="tab1">
+<h2>Configuration</h2>
+<table>
+<thead>
+<tr>
+<th>Project</th>
+<th class="numeric">Duration</th>
+</tr>
+</thead>
+<tr>
+<td>All projects</td>
+<td class="numeric">8.000s</td>
+</tr>
+<tr>
+<td>b</td>
+<td class="numeric">5.000s</td>
+</tr>
+<tr>
+<td>a</td>
+<td class="numeric">3.000s</td>
+</tr>
+</table>
+</div>
+<div class="tab" id="tab2">
+<h2>Dependency Resolution</h2>
+<table>
+<thead>
+<tr>
+<th>Dependencies</th>
+<th class="numeric">Duration</th>
+</tr>
+</thead>
+<tr>
+<td>All dependencies</td>
+<td class="numeric">2m0.00s</td>
+</tr>
+<tr>
+<td>compile</td>
+<td class="numeric">1m30.00s</td>
+</tr>
+<tr>
+<td>runtime</td>
+<td class="numeric">30.000s</td>
+</tr>
+</table>
+</div>
+<div class="tab" id="tab3">
+<h2>Task Execution</h2>
+<table>
+<thead>
+<tr>
+<th>Task</th>
+<th class="numeric">Duration</th>
+<th>Result</th>
+</tr>
+</thead>
+<tr>
+<td>b</td>
+<td class="numeric">4m30.00s</td>
+<td>(total)</td>
+</tr>
+<tr>
+<td class="indentPath">b:foo</td>
+<td class="numeric">2m30.00s</td>
+<td>Did No Work</td>
+</tr>
+<tr>
+<td class="indentPath">b:bar</td>
+<td class="numeric">2m0.00s</td>
+<td>Did No Work</td>
+</tr>
+<tr>
+<td>a</td>
+<td class="numeric">2m0.00s</td>
+<td>(total)</td>
+</tr>
+<tr>
+<td class="indentPath">a:foo</td>
+<td class="numeric">1m30.00s</td>
+<td>Did No Work</td>
+</tr>
+<tr>
+<td class="indentPath">a:bar</td>
+<td class="numeric">30.000s</td>
+<td>Did No Work</td>
+</tr>
+</table>
+</div>
+</div>"""))
+ }
+
+ private long time(int hour, int mins, int secs, int ms = 0) {
+ def cal = new GregorianCalendar(2010, 1, 5, hour, mins, secs)
+ cal.add(Calendar.MILLISECOND, ms)
+ cal.getTimeInMillis()
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/profile/ProjectProfileTest.groovy b/subprojects/core/src/test/groovy/org/gradle/profile/ProjectProfileTest.groovy
new file mode 100644
index 0000000..a737dfa
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/profile/ProjectProfileTest.groovy
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.profile
+
+import org.gradle.api.tasks.TaskState
+import spock.lang.Specification
+
+class ProjectProfileTest extends Specification {
+
+ def "provides sorted tasks"() {
+ def profile = new ProjectProfile(":foo")
+ def a = profile.getTaskProfile("foo:a").completed(Stub(TaskState)).setStart(100).setFinish(300)
+ def b = profile.getTaskProfile("foo:b").completed(Stub(TaskState)).setStart(300).setFinish(300)
+ def c = profile.getTaskProfile("foo:c").completed(Stub(TaskState)).setStart(300).setFinish(300)
+ def d = profile.getTaskProfile("foo:d").completed(Stub(TaskState)).setStart(301).setFinish(302)
+
+ expect:
+ profile.tasks.operations == [a, d, b, c]
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/profile/TaskExecutionTest.groovy b/subprojects/core/src/test/groovy/org/gradle/profile/TaskExecutionTest.groovy
new file mode 100644
index 0000000..ac227ea
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/profile/TaskExecutionTest.groovy
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.profile
+
+import org.gradle.api.tasks.TaskState
+import spock.lang.Specification
+
+class TaskExecutionTest extends Specification {
+
+ def "knows task status"() {
+ def skipped = Stub(TaskState) {
+ getSkipped() >> true
+ getSkipMessage() >> "Skipped for a good reason."
+ }
+ def busy = Stub(TaskState) {
+ getSkipped() >> false
+ getDidWork() >> true
+ }
+ def noWork = Stub(TaskState) {
+ getSkipped() >> false
+ getDidWork() >> false
+ }
+
+ expect:
+ new TaskExecution("a").completed(skipped).status == "Skipped for a good reason."
+ new TaskExecution("a").completed(busy).status == ""
+ new TaskExecution("a").completed(noWork).status == TaskExecution.NO_WORK_MESSAGE
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/tooling/provider/model/internal/DefaultToolingModelBuilderRegistryTest.groovy b/subprojects/core/src/test/groovy/org/gradle/tooling/provider/model/internal/DefaultToolingModelBuilderRegistryTest.groovy
new file mode 100644
index 0000000..9fbb7d9
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/tooling/provider/model/internal/DefaultToolingModelBuilderRegistryTest.groovy
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.provider.model.internal
+
+import org.gradle.api.internal.project.ProjectInternal
+import org.gradle.tooling.provider.model.ToolingModelBuilder
+import org.gradle.tooling.provider.model.UnknownModelException
+import spock.lang.Specification
+
+class DefaultToolingModelBuilderRegistryTest extends Specification {
+ final def registy = new DefaultToolingModelBuilderRegistry()
+
+ def "finds model builder for requested model"() {
+ def builder1 = Mock(ToolingModelBuilder)
+ def builder2 = Mock(ToolingModelBuilder)
+
+ given:
+ registy.register(builder1)
+ registy.register(builder2)
+
+ and:
+ builder1.canBuild("model") >> false
+ builder2.canBuild("model") >> true
+
+ expect:
+ registy.getBuilder("model") == builder2
+ }
+
+ def "includes a simple implementation for the Void model"() {
+ expect:
+ registy.getBuilder(Void.class.name).buildAll(Void.class.name, Mock(ProjectInternal)) == null
+ }
+
+ def "fails when no builder is available for requested model"() {
+ when:
+ registy.getBuilder("model")
+
+ then:
+ UnknownModelException e = thrown()
+ e.message == "No builders are available to build a model of type 'model'."
+ }
+
+ def "fails when multiple builders are available for requested model"() {
+ def builder1 = Mock(ToolingModelBuilder)
+ def builder2 = Mock(ToolingModelBuilder)
+
+ given:
+ registy.register(builder1)
+ registy.register(builder2)
+
+ and:
+ builder1.canBuild("model") >> true
+ builder2.canBuild("model") >> true
+
+ when:
+ registy.getBuilder("model")
+
+ then:
+ UnsupportedOperationException e = thrown()
+ e.message == "Multiple builders are available to build a model of type 'model'."
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/util/DefaultClassLoaderFactoryTest.groovy b/subprojects/core/src/test/groovy/org/gradle/util/DefaultClassLoaderFactoryTest.groovy
deleted file mode 100644
index 38737a6..0000000
--- a/subprojects/core/src/test/groovy/org/gradle/util/DefaultClassLoaderFactoryTest.groovy
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.util
-
-import spock.lang.Specification
-
-class DefaultClassLoaderFactoryTest extends Specification {
- final DefaultClassLoaderFactory factory = new DefaultClassLoaderFactory()
- ClassLoader original
-
- def setup() {
- original = Thread.currentThread().contextClassLoader
- }
-
- def cleanup() {
- Thread.currentThread().contextClassLoader = original
- }
-
- def "classes from specified URLs are visible in isolated ClassLoader"() {
- when:
- def cl = factory.createIsolatedClassLoader(classpath)
- def c = cl.loadClass(DefaultClassLoaderFactoryTestHelper.name)
-
- then:
- c.name == DefaultClassLoaderFactoryTestHelper.name
- c != DefaultClassLoaderFactoryTestHelper
- }
-
- def "application classes are not visible in isolated ClassLoader"() {
- when:
- def cl = factory.createIsolatedClassLoader(classpath)
- cl.loadClass(Closure.name)
-
- then:
- thrown(ClassNotFoundException)
- }
-
- def "can use XML APIs from isolated ClassLoader when application classes include an XML provider"() {
- assert ClassLoader.getSystemResource("META-INF/services/javax.xml.parsers.SAXParserFactory")
-
- when:
- def cl = factory.createIsolatedClassLoader(classpath)
- def c = cl.loadClass(DefaultClassLoaderFactoryTestHelper.name)
-
- then:
- c != DefaultClassLoaderFactoryTestHelper
-
- when:
- Thread.currentThread().contextClassLoader = cl
- c.newInstance().doStuff()
-
- then:
- notThrown()
- }
-
- def "can use XML APIs from filtering ClassLoader when application classes include an XML provider"() {
- assert ClassLoader.getSystemResource("META-INF/services/javax.xml.parsers.SAXParserFactory")
-
- when:
- def cl = new URLClassLoader(classpath.collect { it.toURL() } as URL[], factory.createFilteringClassLoader(getClass().classLoader))
- def c = cl.loadClass(DefaultClassLoaderFactoryTestHelper.name)
-
- then:
- c != DefaultClassLoaderFactoryTestHelper
-
- when:
- Thread.currentThread().contextClassLoader = cl
- c.newInstance().doStuff()
-
- then:
- notThrown()
- }
-
- def getClasspath() {
- return [ClasspathUtil.getClasspathForClass(DefaultClassLoaderFactoryTestHelper)].collect { it.toURI() }
- }
-}
-
diff --git a/subprojects/core/src/test/groovy/org/gradle/util/DefaultClassLoaderFactoryTestHelper.java b/subprojects/core/src/test/groovy/org/gradle/util/DefaultClassLoaderFactoryTestHelper.java
deleted file mode 100644
index 0d52d2b..0000000
--- a/subprojects/core/src/test/groovy/org/gradle/util/DefaultClassLoaderFactoryTestHelper.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.util;
-
-import javax.xml.XMLConstants;
-import javax.xml.datatype.DatatypeFactory;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.SAXParserFactory;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.validation.SchemaFactory;
-import javax.xml.xpath.XPathFactory;
-
-public class DefaultClassLoaderFactoryTestHelper {
- public void doStuff() throws Exception {
- SAXParserFactory.newInstance().newSAXParser();
- DocumentBuilderFactory.newInstance().newDocumentBuilder();
- DatatypeFactory.newInstance().newXMLGregorianCalendar();
- TransformerFactory.newInstance().newTransformer();
- SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
- XPathFactory.newInstance().newXPath();
- }
-}
diff --git a/subprojects/core/src/test/groovy/org/gradle/util/FilteringClassLoaderTest.groovy b/subprojects/core/src/test/groovy/org/gradle/util/FilteringClassLoaderTest.groovy
deleted file mode 100644
index d4f778e..0000000
--- a/subprojects/core/src/test/groovy/org/gradle/util/FilteringClassLoaderTest.groovy
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.util
-
-import org.hamcrest.Matcher
-import org.jmock.integration.junit4.JMock
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.BlockJUnit4ClassRunner
-import static org.hamcrest.Matchers.*
-import static org.junit.Assert.*
-import org.junit.Before
-
- at RunWith(JMock.class)
-class FilteringClassLoaderTest {
- private final JUnit4GroovyMockery context = new JUnit4GroovyMockery()
- private final FilteringClassLoader classLoader = new FilteringClassLoader(FilteringClassLoaderTest.class.getClassLoader())
-
- @Test
- void passesThroughSystemClasses() {
- assertThat(classLoader.loadClass(String.class.name), sameInstance(String.class))
- }
-
- @Test
- void passesThroughSystemPackages() {
- assertThat(classLoader.getPackage('java.lang'), notNullValue(Package.class))
- assertThat(classLoader.getPackages(), hasPackage('java.lang'))
- }
-
- private Matcher<Package[]> hasPackage(String name) {
- Matcher matcher = [matches: {Package p -> p.name == name }, describeTo: {description -> description.appendText("has package '$name'")}] as Matcher
- return hasItemInArray(matcher)
- }
-
- @Test
- void passesThroughSystemResources() {
- assertThat(classLoader.getResource('com/sun/jndi/ldap/jndiprovider.properties'), notNullValue())
- assertThat(classLoader.getResourceAsStream('com/sun/jndi/ldap/jndiprovider.properties'), notNullValue())
- assertTrue(classLoader.getResources('com/sun/jndi/ldap/jndiprovider.properties').hasMoreElements())
- }
-
- @Test
- void filtersClasses() {
- classLoader.parent.loadClass(Test.class.name)
-
- try {
- classLoader.loadClass(Test.class.name, false)
- fail()
- } catch (ClassNotFoundException e) {
- assertThat(e.message, equalTo("$Test.name not found.".toString()))
- }
- try {
- classLoader.loadClass(Test.class.name)
- fail()
- } catch (ClassNotFoundException e) {
- assertThat(e.message, equalTo("$Test.name not found.".toString()))
- }
- }
-
- @Test
- void filtersPackages() {
- assertThat(classLoader.parent.getPackage('org.junit'), notNullValue())
-
- assertThat(classLoader.getPackage('org.junit'), nullValue())
- assertThat(classLoader.getPackages(), not(hasPackage('org.junit')))
- }
-
- @Test
- void filtersResources() {
- assertThat(classLoader.parent.getResource('org/gradle/util/ClassLoaderTest.txt'), notNullValue())
- assertThat(classLoader.getResource('org/gradle/util/ClassLoaderTest.txt'), nullValue())
- assertThat(classLoader.getResourceAsStream('org/gradle/util/ClassLoaderTest.txt'), nullValue())
- assertFalse(classLoader.getResources('org/gradle/util/ClassLoaderTest.txt').hasMoreElements())
- }
-
- @Test
- void passesThroughClassesInSpecifiedPackages() {
- classLoader.allowPackage('org.junit')
- assertThat(classLoader.loadClass(Test.class.name), sameInstance(Test.class))
- assertThat(classLoader.loadClass(Test.class.name, false), sameInstance(Test.class))
- assertThat(classLoader.loadClass(BlockJUnit4ClassRunner.class.name), sameInstance(BlockJUnit4ClassRunner.class))
- }
-
- @Test
- void passesThroughSpecifiedClasses() {
- classLoader.allowClass(Test.class)
- assertThat(classLoader.loadClass(Test.class.name), sameInstance(Test.class))
- try {
- classLoader.loadClass(Before.class.name)
- fail()
- } catch (ClassNotFoundException e) {
- // expected
- }
- }
-
- @Test
- void filtersSpecifiedClasses() {
- classLoader.allowPackage("org.junit")
- classLoader.disallowClass("org.junit.Test")
-
- canLoadClass(Before)
- cannotLoadClass(Test)
- }
-
- @Test
- void disallowClassWinsOverAllowClass() {
- classLoader.allowClass(Test)
- classLoader.disallowClass(Test.name)
-
- cannotLoadClass(Test)
- }
-
- @Test
- void passesThroughSpecifiedPackages() {
- assertThat(classLoader.getPackage('org.junit'), nullValue())
- assertThat(classLoader.getPackages(), not(hasPackage('org.junit')))
-
- classLoader.allowPackage('org.junit')
-
- assertThat(classLoader.getPackage('org.junit'), notNullValue())
- assertThat(classLoader.getPackages(), hasPackage('org.junit'))
- assertThat(classLoader.getPackage('org.junit.runner'), notNullValue())
- assertThat(classLoader.getPackages(), hasPackage('org.junit.runner'))
- }
-
- @Test
- void passesThroughResourcesInSpecifiedPackages() {
- assertThat(classLoader.getResource('org/gradle/util/ClassLoaderTest.txt'), nullValue())
-
- classLoader.allowPackage('org.gradle')
-
- assertThat(classLoader.getResource('org/gradle/util/ClassLoaderTest.txt'), notNullValue())
- assertThat(classLoader.getResourceAsStream('org/gradle/util/ClassLoaderTest.txt'), notNullValue())
- assertTrue(classLoader.getResources('org/gradle/util/ClassLoaderTest.txt').hasMoreElements())
- }
-
- @Test
- void passesThroughResourcesWithSpecifiedPrefix() {
- assertThat(classLoader.getResource('org/gradle/util/ClassLoaderTest.txt'), nullValue())
-
- classLoader.allowResources('org/gradle')
-
- assertThat(classLoader.getResource('org/gradle/util/ClassLoaderTest.txt'), notNullValue())
- assertThat(classLoader.getResourceAsStream('org/gradle/util/ClassLoaderTest.txt'), notNullValue())
- assertTrue(classLoader.getResources('org/gradle/util/ClassLoaderTest.txt').hasMoreElements())
- }
-
- @Test
- void passesThroughSpecifiedResources() {
- assertThat(classLoader.getResource('org/gradle/util/ClassLoaderTest.txt'), nullValue())
-
- classLoader.allowResource('org/gradle/util/ClassLoaderTest.txt')
-
- assertThat(classLoader.getResource('org/gradle/util/ClassLoaderTest.txt'), notNullValue())
- assertThat(classLoader.getResourceAsStream('org/gradle/util/ClassLoaderTest.txt'), notNullValue())
- assertTrue(classLoader.getResources('org/gradle/util/ClassLoaderTest.txt').hasMoreElements())
- }
-
- void canLoadClass(Class<?> clazz) {
- assert classLoader.loadClass(clazz.name) == clazz
- }
-
- void cannotLoadClass(Class<?> clazz) {
- try {
- classLoader.loadClass(clazz.name)
- fail()
- } catch (ClassNotFoundException expected) {}
- }
-}
diff --git a/subprojects/core/src/test/groovy/org/gradle/util/GFileUtilsTest.groovy b/subprojects/core/src/test/groovy/org/gradle/util/GFileUtilsTest.groovy
index e241b24..03a221c 100644
--- a/subprojects/core/src/test/groovy/org/gradle/util/GFileUtilsTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/util/GFileUtilsTest.groovy
@@ -24,9 +24,6 @@ import spock.lang.Specification
import static org.gradle.util.GFileUtils.mkdirs
import static org.gradle.util.GFileUtils.parentMkdirs
-/**
- * by Szczepan Faber, created at: 2/28/12
- */
class GFileUtilsTest extends Specification {
@Rule TestNameTestDirectoryProvider temp
diff --git a/subprojects/core/src/test/groovy/org/gradle/util/GStreamUtilTest.groovy b/subprojects/core/src/test/groovy/org/gradle/util/GStreamUtilTest.groovy
new file mode 100644
index 0000000..93cef4d
--- /dev/null
+++ b/subprojects/core/src/test/groovy/org/gradle/util/GStreamUtilTest.groovy
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.util
+
+import spock.lang.Specification
+
+class GStreamUtilTest extends Specification {
+
+ def "skips bytes"() {
+ def bytes = new ByteArrayOutputStream()
+ bytes.write(5)
+ bytes.write(10)
+ bytes.write(15)
+ bytes.write(20)
+
+ when:
+ def is = new DataInputStream(new ByteArrayInputStream(bytes.toByteArray()))
+ def skipped = GStreamUtil.skipBytes(2, is)
+
+ then:
+ skipped == 2
+ is.read() == 15
+ GStreamUtil.skipBytes(123, is) == 1
+ }
+}
diff --git a/subprojects/core/src/test/groovy/org/gradle/util/GradleVersionTest.groovy b/subprojects/core/src/test/groovy/org/gradle/util/GradleVersionTest.groovy
index c0de292..21b25af 100644
--- a/subprojects/core/src/test/groovy/org/gradle/util/GradleVersionTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/util/GradleVersionTest.groovy
@@ -24,22 +24,33 @@ import org.gradle.internal.os.OperatingSystem
import spock.lang.Issue
import spock.lang.Specification
-/**
- * @author Hans Dockter
- */
class GradleVersionTest extends Specification {
final GradleVersion version = GradleVersion.current()
- def "valid versions"() {
- expect:
- version.valid
- !GradleVersion.version("asdfasdfas").valid
- GradleVersion.version("1.0").valid
+ def "parsing fails for unrecognized version string"() {
+ when:
+ GradleVersion.version(versionString)
+
+ then:
+ IllegalArgumentException e = thrown()
+ e.message == "'$versionString' is not a valid Gradle version string (examples: '1.0', '1.0-rc-1')"
+
+ where:
+ versionString << [
+ "",
+ "something",
+ "1",
+ "1-beta",
+ "1.0-\n"
+ ]
}
- def currentVersionHasNonNullVersion() {
+ def "current version has non-null parts"() {
expect:
version.version
+ version.buildTime
+ version.nextMajor
+ version.baseVersion
}
@Issue("http://issues.gradle.org/browse/GRADLE-1892")
@@ -96,28 +107,6 @@ class GradleVersionTest extends Specification {
'1.2.1']
}
- def canOnlyQueryVersionStringForUnrecognizedVersion(String version) {
- def gradleVersion = GradleVersion.version(version)
-
- expect:
- gradleVersion.version == version
- gradleVersion.snapshot
-
- when:
- gradleVersion > GradleVersion.version('1.2')
-
- then:
- IllegalArgumentException e = thrown()
- e.message == "Cannot compare unrecognized Gradle version '${version}'."
-
- where:
- version << [
- 'abc',
- '3.0-status-5-master',
- 'user-master',
- ]
- }
-
def canCompareMajorVersions() {
expect:
GradleVersion.version(a) > GradleVersion.version(b)
@@ -173,8 +162,9 @@ class GradleVersionTest extends Specification {
a | b
'1.0-milestone-2' | '1.0-milestone-1'
'1.0-preview-2' | '1.0-preview-1'
- '1.0-rc-2' | '1.0-rc-1'
'1.0-preview-1' | '1.0-milestone-7'
+ '1.0-rc-1' | '1.0-milestone-7'
+ '1.0-rc-2' | '1.0-rc-1'
'1.0-rc-7' | '1.0-rc-1'
'1.0' | '1.0-rc-7'
}
@@ -215,28 +205,53 @@ class GradleVersionTest extends Specification {
def "can get version base"() {
expect:
- GradleVersion.version(v).versionBase == base
+ GradleVersion.version(v).baseVersion == GradleVersion.version(base)
where:
- v | base
- "1.0" | "1.0"
- "1.0-rc-1" | "1.0"
- '0.9-20101220100000+1000' | "0.9"
- '0.9-20101220100000' | "0.9"
- "asdfasd" | null
+ v | base
+ "1.0" | "1.0"
+ "1.0-rc-1" | "1.0"
+ "1.2.3.4" | "1.2.3.4"
+ '0.9' | "0.9"
+ '0.9.2' | "0.9.2"
+ '0.9-20101220100000+1000' | "0.9"
+ '0.9-20101220100000' | "0.9"
+ '20.17-20101220100000+1000' | "20.17"
}
- def "can get version major"() {
+ def "milestones are treated as base versions"() {
expect:
- GradleVersion.version(v).major == major
+ GradleVersion.version(v).baseVersion == GradleVersion.version(base)
where:
- v | major
- "1.0" | 1
- "1.0-rc-1" | 1
- '0.9-20101220100000+1000' | 0
- '0.9-20101220100000' | 0
- "asdfasd" | -1
+ v | base
+ '1.0-milestone-3' | "1.0-milestone-3"
+ '1.0-milestone-3-20121012100000+1000' | "1.0-milestone-3"
+ '2.0-milestone-3' | "2.0-milestone-3"
+ }
+
+ def "can get next major version"() {
+ expect:
+ GradleVersion.version(v).nextMajor == GradleVersion.version(major)
+
+ where:
+ v | major
+ "1.0" | "2.0"
+ "1.0-rc-1" | "2.0"
+ '0.9-20101220100000+1000' | "1.0"
+ '0.9-20101220100000' | "1.0"
+ '20.17-20101220100000+1000' | "21.0"
+ }
+
+ def "milestones are part of previous major version"() {
+ expect:
+ GradleVersion.version(v).nextMajor == GradleVersion.version(major)
+
+ where:
+ v | major
+ '1.0-milestone-3' | "1.0"
+ '1.0-milestone-3-20121012100000+1000' | "1.0"
+ '2.0-milestone-3' | "2.0" // not that we're planning to do this
}
def prettyPrint() {
@@ -245,12 +260,15 @@ class GradleVersionTest extends Specification {
Gradle $version.version
------------------------------------------------------------
-Gradle build time: $version.buildTime
-Groovy: $InvokerHelper.version
-Ant: $Main.antVersion
-Ivy: ${Ivy.ivyVersion}
-JVM: ${Jvm.current()}
-OS: ${OperatingSystem.current()}
+Build time: $version.buildTime
+Build number: $version.buildNumber
+Revision: $version.commitId
+
+Groovy: $InvokerHelper.version
+Ant: $Main.antVersion
+Ivy: ${Ivy.ivyVersion}
+JVM: ${Jvm.current()}
+OS: ${OperatingSystem.current()}
"""
expect:
version.prettyPrint() == expectedText
diff --git a/subprojects/core/src/test/groovy/org/gradle/util/JavaMethodTest.java b/subprojects/core/src/test/groovy/org/gradle/util/JavaMethodTest.java
deleted file mode 100644
index 850778b..0000000
--- a/subprojects/core/src/test/groovy/org/gradle/util/JavaMethodTest.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.util;
-
-import org.jmock.Expectations;
-import org.jmock.integration.junit4.JMock;
-import org.jmock.integration.junit4.JUnit4Mockery;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static org.hamcrest.Matchers.*;
-import static org.junit.Assert.*;
-
- at RunWith(JMock.class)
-public class JavaMethodTest {
- private final JUnit4Mockery context = new JUnit4Mockery();
-
- @Test
- public void invokesMethodOnObject() {
- JavaMethod<CharSequence, CharSequence> method = JavaMethod.create(CharSequence.class, CharSequence.class, "subSequence", int.class, int.class);
- assertThat(method.invoke("string", 0, 3), equalTo((CharSequence) "str"));
- }
-
- @Test
- public void propagatesExceptionThrownByMethod() {
- final CharSequence mock = context.mock(CharSequence.class);
- final RuntimeException failure = new RuntimeException();
- context.checking(new Expectations() {{
- one(mock).subSequence(0, 3);
- will(throwException(failure));
- }});
-
- JavaMethod<CharSequence, CharSequence> method = JavaMethod.create(CharSequence.class, CharSequence.class, "subSequence", int.class, int.class);
- try {
- method.invoke(mock, 0, 3);
- fail();
- } catch (RuntimeException e) {
- assertThat(e, sameInstance(failure));
- }
- }
-
- @Test
- public void canAccessProtectedMethod() {
- final Package[] packages = new Package[0];
- ClassLoader classLoader = new ClassLoader() {
- @Override
- protected Package[] getPackages() {
- return packages;
- }
- };
-
- JavaMethod<ClassLoader, Package[]> method = JavaMethod.create(ClassLoader.class, Package[].class, "getPackages");
- assertThat(method.invoke(classLoader), sameInstance(packages));
- }
-}
diff --git a/subprojects/core/src/test/groovy/org/gradle/util/MatchersTest.groovy b/subprojects/core/src/test/groovy/org/gradle/util/MatchersTest.groovy
index 7c7dbbe..3cb9951 100644
--- a/subprojects/core/src/test/groovy/org/gradle/util/MatchersTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/util/MatchersTest.groovy
@@ -22,9 +22,6 @@ import java.util.regex.Pattern
import static org.gradle.util.Matchers.matchesRegexp
-/**
- * by Szczepan Faber, created at: 12/17/12
- */
class MatchersTest extends Specification {
def "matches regex"() {
diff --git a/subprojects/core/src/test/groovy/org/gradle/util/MultiParentClassLoaderTest.groovy b/subprojects/core/src/test/groovy/org/gradle/util/MultiParentClassLoaderTest.groovy
deleted file mode 100644
index 6efd696..0000000
--- a/subprojects/core/src/test/groovy/org/gradle/util/MultiParentClassLoaderTest.groovy
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.util
-
-import org.jmock.integration.junit4.JMock
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import static org.hamcrest.Matchers.*
-import static org.junit.Assert.*
-
- at RunWith(JMock.class)
-class MultiParentClassLoaderTest {
- private final JUnit4GroovyMockery context = new JUnit4GroovyMockery()
- private ClassLoader parent1
- private ClassLoader parent2
- private MultiParentClassLoader loader
-
- @Before
- public void setup() {
- parent1 = context.mock(ClassLoader)
- parent2 = context.mock(ClassLoader)
- loader = new MultiParentClassLoader(parent1, parent2)
- }
-
- @Test
- public void parentsAreNotVisibleViaSuperClass() {
- assertThat(loader.parent, nullValue())
- }
-
- @Test
- public void loadsClassFromParentsInOrderSpecified() {
- Class stringClass = String.class
- Class integerClass = Integer.class
-
- context.checking {
- allowing(parent1).loadClass('string')
- will(returnValue(stringClass))
- allowing(parent1).loadClass('integer')
- will(throwException(new ClassNotFoundException()))
- allowing(parent2).loadClass('integer')
- will(returnValue(integerClass))
- }
-
- assertThat(loader.loadClass('string'), equalTo(String.class))
- assertThat(loader.loadClass('string', true), equalTo(String.class))
- assertThat(loader.loadClass('integer'), equalTo(Integer.class))
- assertThat(loader.loadClass('integer', true), equalTo(Integer.class))
- }
-
- @Test
- public void throwsCNFExceptionWhenClassNotFound() {
- context.checking {
- allowing(parent1).loadClass('string')
- will(throwException(new ClassNotFoundException()))
- allowing(parent2).loadClass('string')
- will(throwException(new ClassNotFoundException()))
- }
-
- try {
- loader.loadClass('string')
- fail()
- } catch (ClassNotFoundException e) {
- assertThat(e.message, equalTo('string not found.'))
- }
- }
-
- @Test
- public void loadsPackageFromParentsInOrderSpecified() {
- Package stringPackage = String.class.getPackage()
- Package listPackage = List.class.getPackage()
-
- context.checking {
- allowing(parent1).getPackage('string')
- will(returnValue(stringPackage))
- allowing(parent1).getPackage('list')
- will(returnValue(null))
- allowing(parent2).getPackage('list')
- will(returnValue(listPackage))
- }
-
- assertThat(loader.getPackage('string'), sameInstance(stringPackage))
- assertThat(loader.getPackage('list'), sameInstance(listPackage))
- }
-
- @Test
- public void containsUnionOfPackagesFromAllParents() {
- Package package1 = context.mock(Package.class, 'p1')
- Package package2 = context.mock(Package.class, 'p2')
-
- context.checking {
- allowing(parent1).getPackages()
- will(returnValue([package1] as Package[]))
- allowing(parent2).getPackages()
- will(returnValue([package2] as Package[]))
- }
-
- assertThat(loader.getPackages(), hasItemInArray(package1))
- assertThat(loader.getPackages(), hasItemInArray(package2))
- }
-
- @Test
- public void loadsResourceFromParentsInOrderSpecified() {
- URL resource1 = new File('res1').toURI().toURL()
- URL resource2 = new File('res2').toURI().toURL()
-
- context.checking {
- allowing(parent1).getResource('resource1')
- will(returnValue(resource1))
- allowing(parent1).getResource('resource2')
- will(returnValue(null))
- allowing(parent2).getResource('resource2')
- will(returnValue(resource2))
- }
-
- assertThat(loader.getResource('resource1'), equalTo(resource1))
- assertThat(loader.getResource('resource2'), equalTo(resource2))
- }
-
- @Test
- public void containsUnionOfResourcesFromAllParents() {
- URL resource1 = new File('res1').toURI().toURL()
- URL resource2 = new File('res2').toURI().toURL()
-
- context.checking {
- allowing(parent1).getResources('resource1')
- will(returnValue(Collections.enumeration([resource1])))
- allowing(parent2).getResources('resource1')
- will(returnValue(Collections.enumeration([resource2, resource1])))
- }
-
- Enumeration resources = loader.getResources('resource1')
- assertTrue(resources.hasMoreElements())
- assertThat(resources.nextElement(), sameInstance(resource1))
- assertTrue(resources.hasMoreElements())
- assertThat(resources.nextElement(), sameInstance(resource2))
- assertFalse(resources.hasMoreElements())
- }
-}
diff --git a/subprojects/core/src/test/groovy/org/gradle/util/PathTest.groovy b/subprojects/core/src/test/groovy/org/gradle/util/PathTest.groovy
index 23c5052..5928d69 100644
--- a/subprojects/core/src/test/groovy/org/gradle/util/PathTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/util/PathTest.groovy
@@ -17,11 +17,9 @@
package org.gradle.util
import spock.lang.Specification
-import static org.gradle.util.Matchers.*
-/**
- * @author Hans Dockter
- */
+import static org.gradle.util.Matchers.strictlyEquals
+
class PathTest extends Specification {
def construction() {
expect:
diff --git a/subprojects/core/src/test/groovy/org/gradle/util/SingleMessageLoggerTest.groovy b/subprojects/core/src/test/groovy/org/gradle/util/SingleMessageLoggerTest.groovy
index c8b198e..81da2f9 100644
--- a/subprojects/core/src/test/groovy/org/gradle/util/SingleMessageLoggerTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/util/SingleMessageLoggerTest.groovy
@@ -19,24 +19,31 @@ package org.gradle.util
import org.gradle.internal.Factory
import org.gradle.logging.ConfigureLogging
import org.gradle.logging.TestAppender
+import org.gradle.test.fixtures.concurrent.ConcurrentSpec
import org.junit.Rule
-import spock.lang.Specification
-class SingleMessageLoggerTest extends Specification {
+class SingleMessageLoggerTest extends ConcurrentSpec {
final TestAppender appender = new TestAppender()
@Rule final ConfigureLogging logging = new ConfigureLogging(appender)
- public void cleanup() {
+ def cleanup() {
SingleMessageLogger.reset()
}
- def "logs deprecation warning once"() {
+ def "logs deprecation warning once until reset"() {
when:
SingleMessageLogger.nagUserWith("nag")
SingleMessageLogger.nagUserWith("nag")
then:
appender.toString() == '[WARN nag]'
+
+ when:
+ SingleMessageLogger.reset()
+ SingleMessageLogger.nagUserWith("nag")
+
+ then:
+ appender.toString() == '[WARN nag][WARN nag]'
}
def "does not log warning while disabled with factory"() {
@@ -54,6 +61,9 @@ class SingleMessageLoggerTest extends Specification {
return "result"
}
0 * _._
+
+ and:
+ appender.toString().length() == 0
}
def "does not log warning while disabled with action"() {
@@ -65,19 +75,40 @@ class SingleMessageLoggerTest extends Specification {
then:
1 * action.run()
0 * _._
+
+ and:
+ appender.toString().length() == 0
+ }
+
+ def "warnings are disabled for the current thread only"() {
+ when:
+ async {
+ start {
+ thread.blockUntil.disabled
+ SingleMessageLogger.nagUserWith("nag")
+ instant.logged
+ }
+ start {
+ SingleMessageLogger.whileDisabled {
+ instant.disabled
+ SingleMessageLogger.nagUserWith("ignored")
+ thread.blockUntil.logged
+ }
+ }
+ }
+
+ then:
+ appender.toString() == '[WARN nag]'
}
def "deprecation message has next major version"() {
given:
- def major = GradleVersion.current().major
-
- expect:
- major != -1
+ def major = GradleVersion.current().nextMajor
when:
SingleMessageLogger.nagUserOfDeprecated("foo", "bar")
then:
- appender.toString() == "[WARN foo has been deprecated and is scheduled to be removed in Gradle ${major + 1}.0. bar.]"
+ appender.toString() == "[WARN foo has been deprecated and is scheduled to be removed in Gradle ${major.version}. bar.]"
}
}
diff --git a/subprojects/core/src/test/groovy/org/gradle/util/StageTest.groovy b/subprojects/core/src/test/groovy/org/gradle/util/StageTest.groovy
index e501cdb..ac5227f 100644
--- a/subprojects/core/src/test/groovy/org/gradle/util/StageTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/util/StageTest.groovy
@@ -19,9 +19,6 @@ package org.gradle.util
import org.gradle.util.GradleVersion.Stage
import spock.lang.Specification
-/**
- * @author Szczepan Faber
- */
class StageTest extends Specification {
def "builds simple stage"() {
when:
diff --git a/subprojects/core/src/test/groovy/org/gradle/util/TextUtilTest.groovy b/subprojects/core/src/test/groovy/org/gradle/util/TextUtilTest.groovy
index ac097c6..dffd28e 100644
--- a/subprojects/core/src/test/groovy/org/gradle/util/TextUtilTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/util/TextUtilTest.groovy
@@ -29,6 +29,8 @@ class TextUtilTest extends Specification {
where:
original | converted
+ "" | ""
+ "none" | "none"
"one\rtwo\nthree\r\nfour\n\rfive" | "one${sep}two${sep}three${sep}four${sep}${sep}five"
}
@@ -38,10 +40,24 @@ class TextUtilTest extends Specification {
where:
original | converted
+ "" | ""
+ "none" | "none"
"one\rtwo\nthree\r\nfour\n\rfive" | "one${platformSep}two${platformSep}three${platformSep}four${platformSep}${platformSep}five"
"\n\n" | "${platformSep}${platformSep}"
}
+ def normaliseLineSeparators() {
+ expect:
+ TextUtil.normaliseLineSeparators(original) == converted
+
+ where:
+ original | converted
+ "" | ""
+ "none" | "none"
+ "one\rtwo\nthree\r\nfour\n\rfive" | "one\ntwo\nthree\nfour\n\nfive"
+ "\r\n\n\r" | "\n\n\n"
+ }
+
def containsWhitespace() {
expect:
TextUtil.containsWhitespace(str) == whitespace
@@ -62,11 +78,11 @@ class TextUtilTest extends Specification {
TextUtil.indent(text, indent) == result
where:
- text | indent | result
- "" | "" | ""
- "abc" | " " | " abc"
- "abc" | "def" | "defabc"
- "abc\ndef\nghi" | " " | " abc\n def\n ghi"
+ text | indent | result
+ "" | "" | ""
+ "abc" | " " | " abc"
+ "abc" | "def" | "defabc"
+ "abc\ndef\nghi" | " " | " abc\n def\n ghi"
"abc\n\t\n \nghi" | "X" | "Xabc\n\t\n \nXghi"
}
}
diff --git a/subprojects/core/src/test/groovy/org/gradle/util/VersionNumberTest.groovy b/subprojects/core/src/test/groovy/org/gradle/util/VersionNumberTest.groovy
index 96bc172..3287063 100644
--- a/subprojects/core/src/test/groovy/org/gradle/util/VersionNumberTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/util/VersionNumberTest.groovy
@@ -73,7 +73,7 @@ class VersionNumberTest extends Specification {
new VersionNumber(2, 1, 1, null) != new VersionNumber(1, 1, 1, null)
new VersionNumber(1, 2, 1, null) != new VersionNumber(1, 1, 1, null)
new VersionNumber(1, 1, 2, null) != new VersionNumber(1, 1, 1, null)
- new VersionNumber(1, 1, 1, "foo") != new VersionNumber(1, 1, 1, null)
+ new VersionNumber(1, 1, 1, "rc") != new VersionNumber(1, 1, 1, null)
}
def "comparison"() {
@@ -83,14 +83,22 @@ class VersionNumberTest extends Specification {
new VersionNumber(2, 1, 1, null) > new VersionNumber(1, 1, 1, null)
new VersionNumber(1, 2, 1, null) > new VersionNumber(1, 1, 1, null)
new VersionNumber(1, 1, 2, null) > new VersionNumber(1, 1, 1, null)
- new VersionNumber(1, 1, 1, "foo") > new VersionNumber(1, 1, 1, null)
- new VersionNumber(1, 1, 1, "b") > new VersionNumber(1, 1, 1, "a")
+ new VersionNumber(1, 1, 1, "rc") < new VersionNumber(1, 1, 1, null)
+ new VersionNumber(1, 1, 1, "beta") > new VersionNumber(1, 1, 1, "alpha")
+ new VersionNumber(1, 1, 1, "RELEASE") > new VersionNumber(1, 1, 1, "beta")
new VersionNumber(1, 1, 1, null) < new VersionNumber(2, 1, 1, null)
new VersionNumber(1, 1, 1, null) < new VersionNumber(1, 2, 1, null)
new VersionNumber(1, 1, 1, null) < new VersionNumber(1, 1, 2, null)
- new VersionNumber(1, 1, 1, null) < new VersionNumber(1, 1, 1, "foo")
- new VersionNumber(1, 1, 1, "a") < new VersionNumber(1, 1, 1, "b")
+ new VersionNumber(1, 1, 1, null) > new VersionNumber(1, 1, 1, "rc")
+ new VersionNumber(1, 1, 1, "alpha") < new VersionNumber(1, 1, 1, "beta")
+ new VersionNumber(1, 1, 1, "beta") < new VersionNumber(1, 1, 1, "RELEASE")
+ }
+
+ def "base version"() {
+ expect:
+ new VersionNumber(1, 2, 3, null).baseVersion == new VersionNumber(1, 2, 3, null)
+ new VersionNumber(1, 2, 3, "beta").baseVersion == new VersionNumber(1, 2, 3, null)
}
}
diff --git a/subprojects/core/src/test/groovy/org/gradle/util/internal/ArgumentsSplitterTest.groovy b/subprojects/core/src/test/groovy/org/gradle/util/internal/ArgumentsSplitterTest.groovy
index 4d88fd7..aab8018 100644
--- a/subprojects/core/src/test/groovy/org/gradle/util/internal/ArgumentsSplitterTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/util/internal/ArgumentsSplitterTest.groovy
@@ -17,11 +17,9 @@
package org.gradle.util.internal
import spock.lang.Specification
+
import static org.gradle.util.internal.ArgumentsSplitter.split
-/**
- * by Szczepan Faber, created at: 2/29/12
- */
class ArgumentsSplitterTest extends Specification {
def breaksUpEmptyCommandLineIntoEmptyList() {
diff --git a/subprojects/core/src/test/groovy/org/gradle/util/internal/LimitedDescriptionTest.groovy b/subprojects/core/src/test/groovy/org/gradle/util/internal/LimitedDescriptionTest.groovy
index e31a6ce..c37064d 100644
--- a/subprojects/core/src/test/groovy/org/gradle/util/internal/LimitedDescriptionTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/util/internal/LimitedDescriptionTest.groovy
@@ -18,9 +18,6 @@ package org.gradle.util.internal
import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 2/28/12
- */
class LimitedDescriptionTest extends Specification {
def desc = new LimitedDescription(2)
diff --git a/subprojects/core/src/testFixtures/groovy/org/gradle/api/internal/file/TestFiles.java b/subprojects/core/src/testFixtures/groovy/org/gradle/api/internal/file/TestFiles.java
index 7517678..052b3b5 100644
--- a/subprojects/core/src/testFixtures/groovy/org/gradle/api/internal/file/TestFiles.java
+++ b/subprojects/core/src/testFixtures/groovy/org/gradle/api/internal/file/TestFiles.java
@@ -15,7 +15,8 @@
*/
package org.gradle.api.internal.file;
-import org.gradle.internal.nativeplatform.filesystem.FileSystems;
+import org.gradle.internal.nativeplatform.filesystem.FileSystem;
+import org.gradle.internal.nativeplatform.services.NativeServices;
import java.io.File;
@@ -24,13 +25,13 @@ public class TestFiles {
* Returns a resolver with no base directory.
*/
public static FileResolver resolver() {
- return new IdentityFileResolver();
+ return new IdentityFileResolver(NativeServices.getInstance().get(FileSystem.class));
}
/**
* Returns a resolver with the given base directory.
*/
public static FileResolver resolver(File baseDir) {
- return new BaseDirFileResolver(FileSystems.getDefault(), baseDir);
+ return resolver().withBaseDir(baseDir);
}
}
diff --git a/subprojects/core/src/testFixtures/groovy/org/gradle/api/internal/file/copy/CopyActionExecuterUtil.java b/subprojects/core/src/testFixtures/groovy/org/gradle/api/internal/file/copy/CopyActionExecuterUtil.java
new file mode 100644
index 0000000..2bcc283
--- /dev/null
+++ b/subprojects/core/src/testFixtures/groovy/org/gradle/api/internal/file/copy/CopyActionExecuterUtil.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.file.copy;
+
+import org.gradle.api.internal.file.CopyActionProcessingStreamAction;
+import org.gradle.api.tasks.WorkResult;
+
+import java.util.Arrays;
+
+public class CopyActionExecuterUtil {
+
+ public static WorkResult visit(CopyAction visitor, final Iterable<FileCopyDetailsInternal> detailses) {
+ return visitor.execute(new CopyActionProcessingStream() {
+ public void process(CopyActionProcessingStreamAction action) {
+ for (FileCopyDetailsInternal detailsInternal : detailses) {
+ action.processFile(detailsInternal);
+ }
+ }
+ });
+ }
+
+ public static WorkResult visit(CopyAction visitor, final FileCopyDetailsInternal... detailses) {
+ return visit(visitor, Arrays.asList(detailses));
+ }
+
+}
diff --git a/subprojects/core/src/testFixtures/groovy/org/gradle/api/tasks/AbstractConventionTaskTest.java b/subprojects/core/src/testFixtures/groovy/org/gradle/api/tasks/AbstractConventionTaskTest.java
index 3172e06..a2bf3d5 100644
--- a/subprojects/core/src/testFixtures/groovy/org/gradle/api/tasks/AbstractConventionTaskTest.java
+++ b/subprojects/core/src/testFixtures/groovy/org/gradle/api/tasks/AbstractConventionTaskTest.java
@@ -13,9 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
+
package org.gradle.api.tasks;
+import org.gradle.api.internal.AbstractTask;
import org.gradle.api.internal.ConventionAwareHelper;
import org.gradle.api.internal.ConventionTask;
import org.junit.Test;
@@ -24,16 +25,13 @@ import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.sameInstance;
import static org.junit.Assert.assertThat;
-/**
- * @author Hans Dockter
- */
public abstract class AbstractConventionTaskTest extends AbstractTaskTest {
- public abstract ConventionTask getTask();
-
+ public abstract AbstractTask getTask();
+
@Test
public void testConventionAwareness() {
- ConventionTask task = getTask();
+ ConventionTask task = (ConventionTask) getTask();
assertThat(task.getConventionMapping(), instanceOf(ConventionAwareHelper.class));
ConventionAwareHelper conventionMapping = (ConventionAwareHelper) task.getConventionMapping();
assertThat(conventionMapping.getConvention(), sameInstance(getProject().getConvention()));
diff --git a/subprojects/core/src/testFixtures/groovy/org/gradle/api/tasks/AbstractCopyTaskContractTest.groovy b/subprojects/core/src/testFixtures/groovy/org/gradle/api/tasks/AbstractCopyTaskContractTest.groovy
new file mode 100644
index 0000000..e95cbf5
--- /dev/null
+++ b/subprojects/core/src/testFixtures/groovy/org/gradle/api/tasks/AbstractCopyTaskContractTest.groovy
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.tasks
+
+import org.gradle.api.Action
+import org.gradle.api.file.FileCopyDetails
+import org.gradle.api.internal.DynamicObject
+import org.junit.Test
+import spock.lang.Unroll
+
+/**
+ * Tests that different types of copy tasks correctly expose DSL enhanced objects.
+ */
+abstract class AbstractCopyTaskContractTest extends AbstractConventionTaskTest {
+
+ abstract AbstractCopyTask getTask()
+
+ @Unroll
+ @Test
+ public void rootLevelFileCopyDetailsIsDslEnhanced() {
+ task.eachFile {
+ assert delegate instanceof DynamicObject
+ }
+ task.eachFile(new Action<FileCopyDetails>() {
+ void execute(FileCopyDetails fcd) {
+ assert fcd instanceof DynamicObject
+ }
+ })
+ }
+}
diff --git a/subprojects/core/src/testFixtures/groovy/org/gradle/api/tasks/AbstractSpockTaskTest.groovy b/subprojects/core/src/testFixtures/groovy/org/gradle/api/tasks/AbstractSpockTaskTest.groovy
index d6f57ef..94d2805 100644
--- a/subprojects/core/src/testFixtures/groovy/org/gradle/api/tasks/AbstractSpockTaskTest.groovy
+++ b/subprojects/core/src/testFixtures/groovy/org/gradle/api/tasks/AbstractSpockTaskTest.groovy
@@ -29,13 +29,14 @@ import org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFacto
import org.gradle.api.internal.project.taskfactory.ITaskFactory
import org.gradle.api.internal.project.taskfactory.TaskFactory
import org.gradle.api.internal.tasks.TaskExecuter
+import org.gradle.api.internal.tasks.TaskExecutionContext
import org.gradle.api.internal.tasks.TaskStateInternal
import org.gradle.api.specs.Spec
import org.gradle.internal.reflect.DirectInstantiator
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
import org.gradle.util.GUtil
-import org.gradle.util.HelperUtil
import org.gradle.util.Matchers
+import org.gradle.util.TestUtil
import org.junit.Rule
import spock.lang.Specification
@@ -43,15 +44,12 @@ import java.util.concurrent.atomic.AtomicBoolean
import static org.junit.Assert.assertFalse
-/**
- * @author Hans Dockter
- */
public abstract class AbstractSpockTaskTest extends Specification {
public static final String TEST_TASK_NAME = "taskname"
@Rule
public TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider()
- private AbstractProject project = HelperUtil.createRootProject()
+ private AbstractProject project = TestUtil.createRootProject()
private static final ITaskFactory TASK_FACTORY = new AnnotationProcessingTaskFactory(new TaskFactory(new AsmBackedClassGenerator()))
@@ -87,10 +85,10 @@ public abstract class AbstractSpockTaskTest extends Specification {
}
def testPath() {
- DefaultProject rootProject = HelperUtil.createRootProject();
- DefaultProject childProject = HelperUtil.createChildProject(rootProject, "child");
+ DefaultProject rootProject = TestUtil.createRootProject();
+ DefaultProject childProject = TestUtil.createChildProject(rootProject, "child");
childProject.getProjectDir().mkdirs();
- DefaultProject childchildProject = HelperUtil.createChildProject(childProject, "childchild");
+ DefaultProject childchildProject = TestUtil.createChildProject(childProject, "childchild");
childchildProject.getProjectDir().mkdirs();
when:
@@ -164,7 +162,7 @@ public abstract class AbstractSpockTaskTest extends Specification {
task.execute()
then:
- 1 * executer.execute(task, _ as TaskStateInternal)
+ 1 * executer.execute(task, _ as TaskStateInternal, _ as TaskExecutionContext)
}
@@ -192,7 +190,7 @@ public abstract class AbstractSpockTaskTest extends Specification {
task.getOnlyIf().isSatisfiedBy(task)
when:
- task.onlyIf(HelperUtil.toClosure("{ task -> false }"));
+ task.onlyIf(TestUtil.toClosure("{ task -> false }"));
then:
assertFalse(task.getOnlyIf().isSatisfiedBy(task));
diff --git a/subprojects/core/src/testFixtures/groovy/org/gradle/api/tasks/AbstractTaskTest.java b/subprojects/core/src/testFixtures/groovy/org/gradle/api/tasks/AbstractTaskTest.java
index 329f2de..2230e43 100644
--- a/subprojects/core/src/testFixtures/groovy/org/gradle/api/tasks/AbstractTaskTest.java
+++ b/subprojects/core/src/testFixtures/groovy/org/gradle/api/tasks/AbstractTaskTest.java
@@ -29,13 +29,14 @@ import org.gradle.api.internal.project.DefaultProject;
import org.gradle.api.internal.project.ProjectInternal;
import org.gradle.api.internal.project.taskfactory.ITaskFactory;
import org.gradle.api.internal.tasks.TaskExecuter;
+import org.gradle.api.internal.tasks.TaskExecutionContext;
import org.gradle.api.internal.tasks.TaskStateInternal;
import org.gradle.api.specs.Spec;
import org.gradle.internal.reflect.Instantiator;
import org.gradle.internal.service.DefaultServiceRegistry;
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider;
import org.gradle.util.GUtil;
-import org.gradle.util.HelperUtil;
+import org.gradle.util.TestUtil;
import org.gradle.util.JUnit4GroovyMockery;
import org.jmock.Expectations;
import org.jmock.lib.legacy.ClassImposteriser;
@@ -49,11 +50,8 @@ import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.sameInstance;
import static org.junit.Assert.*;
-/**
- * @author Hans Dockter
- */
public abstract class AbstractTaskTest {
- public static final String TEST_TASK_NAME = "taskname";
+ public static final String TEST_TASK_NAME = "testTask";
@Rule
public TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider();
@@ -65,7 +63,7 @@ public abstract class AbstractTaskTest {
protected Instantiator instantiator = new DependencyInjectingInstantiator(serviceRegistry);
- private AbstractProject project = HelperUtil.createRootProject();
+ private AbstractProject project = TestUtil.createRootProject();
public abstract AbstractTask getTask();
@@ -103,10 +101,10 @@ public abstract class AbstractTaskTest {
@Test
public void testPath() {
- DefaultProject rootProject = HelperUtil.createRootProject();
- DefaultProject childProject = HelperUtil.createChildProject(rootProject, "child");
+ DefaultProject rootProject = TestUtil.createRootProject();
+ DefaultProject childProject = TestUtil.createChildProject(rootProject, "child");
childProject.getProjectDir().mkdirs();
- DefaultProject childchildProject = HelperUtil.createChildProject(childProject, "childchild");
+ DefaultProject childchildProject = TestUtil.createChildProject(childProject, "childchild");
childchildProject.getProjectDir().mkdirs();
Task task = createTask(rootProject, TEST_TASK_NAME);
@@ -145,7 +143,7 @@ public abstract class AbstractTaskTest {
task.setExecuter(executer);
context.checking(new Expectations() {{
- one(executer).execute(with(sameInstance(task)), with(notNullValue(TaskStateInternal.class)));
+ one(executer).execute(with(sameInstance(task)), with(notNullValue(TaskStateInternal.class)), with(notNullValue(TaskExecutionContext.class)));
}});
task.execute();
@@ -171,7 +169,7 @@ public abstract class AbstractTaskTest {
AbstractTask task = getTask();
assertTrue(task.getOnlyIf().isSatisfiedBy(task));
- task.onlyIf(HelperUtil.toClosure("{ task -> false }"));
+ task.onlyIf(TestUtil.toClosure("{ task -> false }"));
assertFalse(task.getOnlyIf().isSatisfiedBy(task));
}
diff --git a/subprojects/core/src/testFixtures/groovy/org/gradle/api/tasks/bundling/AbstractArchiveTaskTest.groovy b/subprojects/core/src/testFixtures/groovy/org/gradle/api/tasks/bundling/AbstractArchiveTaskTest.groovy
index be42d17..8c2d36a 100644
--- a/subprojects/core/src/testFixtures/groovy/org/gradle/api/tasks/bundling/AbstractArchiveTaskTest.groovy
+++ b/subprojects/core/src/testFixtures/groovy/org/gradle/api/tasks/bundling/AbstractArchiveTaskTest.groovy
@@ -16,24 +16,20 @@
package org.gradle.api.tasks.bundling
-import org.gradle.api.internal.ConventionTask
import org.gradle.api.internal.file.FileResolver
-import org.gradle.api.tasks.AbstractConventionTaskTest
+import org.gradle.api.tasks.AbstractCopyTaskContractTest
import org.junit.Test
import static org.junit.Assert.assertEquals
import static org.junit.Assert.assertTrue
-/**
- * @author Hans Dockter
- */
-abstract class AbstractArchiveTaskTest extends AbstractConventionTaskTest {
+abstract class AbstractArchiveTaskTest extends AbstractCopyTaskContractTest {
FileResolver resolver = [resolve: {it as File}] as FileResolver
abstract AbstractArchiveTask getArchiveTask()
- ConventionTask getTask() {
+ AbstractArchiveTask getTask() {
archiveTask
}
diff --git a/subprojects/core/src/testFixtures/groovy/org/gradle/cache/internal/DefaultFileLockManagerTestHelper.groovy b/subprojects/core/src/testFixtures/groovy/org/gradle/cache/internal/DefaultFileLockManagerTestHelper.groovy
index 125fd31..fbab657 100644
--- a/subprojects/core/src/testFixtures/groovy/org/gradle/cache/internal/DefaultFileLockManagerTestHelper.groovy
+++ b/subprojects/core/src/testFixtures/groovy/org/gradle/cache/internal/DefaultFileLockManagerTestHelper.groovy
@@ -16,6 +16,8 @@
package org.gradle.cache.internal
+import org.gradle.cache.internal.locklistener.NoOpFileLockContentionHandler
+
abstract class DefaultFileLockManagerTestHelper {
private static class AnException extends RuntimeException {}
@@ -51,13 +53,13 @@ abstract class DefaultFileLockManagerTestHelper {
String getProcessDisplayName() {
return "process"
}
- })
+ }, new NoOpFileLockContentionHandler())
}
static FileLock createDefaultFileLock(File file, FileLockManager.LockMode mode = FileLockManager.LockMode.Exclusive, DefaultFileLockManager manager = createDefaultFileLockManager()) {
- manager.lock(file, mode, "test lock")
+ manager.lock(file, mode, "test lock")
}
-
+
static File getLockFile(File target) {
new File(target.absolutePath + ".lock")
}
diff --git a/subprojects/core/src/testFixtures/groovy/org/gradle/util/ConcurrentSpecification.groovy b/subprojects/core/src/testFixtures/groovy/org/gradle/util/ConcurrentSpecification.groovy
index 5e334f5..0ad11fb 100644
--- a/subprojects/core/src/testFixtures/groovy/org/gradle/util/ConcurrentSpecification.groovy
+++ b/subprojects/core/src/testFixtures/groovy/org/gradle/util/ConcurrentSpecification.groovy
@@ -19,9 +19,6 @@ import org.gradle.test.fixtures.ConcurrentTestUtil
import org.junit.Rule
import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 12/8/11
- */
class ConcurrentSpecification extends Specification {
@Rule @Delegate ConcurrentTestUtil concurrent = new ConcurrentTestUtil()
}
diff --git a/subprojects/core/src/testFixtures/groovy/org/gradle/util/HelperUtil.groovy b/subprojects/core/src/testFixtures/groovy/org/gradle/util/HelperUtil.groovy
deleted file mode 100644
index 8b24c26..0000000
--- a/subprojects/core/src/testFixtures/groovy/org/gradle/util/HelperUtil.groovy
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.util
-
-import org.apache.ivy.core.module.descriptor.Configuration
-import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor
-import org.apache.ivy.core.module.id.ModuleRevisionId
-import org.codehaus.groovy.control.CompilerConfiguration
-import org.gradle.api.Task
-import org.gradle.api.internal.project.DefaultProject
-import org.gradle.api.internal.project.ProjectInternal
-import org.gradle.api.internal.project.taskfactory.ITaskFactory
-import org.gradle.groovy.scripts.DefaultScript
-import org.gradle.groovy.scripts.Script
-import org.gradle.groovy.scripts.ScriptSource
-import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
-import org.gradle.testfixtures.ProjectBuilder
-
-import java.rmi.server.UID
-
-/**
- * @author Hans Dockter
- */
-class HelperUtil {
- public static final Closure TEST_CLOSURE = {}
-
- static <T extends Task> T createTask(Class<T> type) {
- return createTask(type, createRootProject())
- }
-
- static <T extends Task> T createTask(Class<T> type, Map taskFields) {
- def task = createTask(type, createRootProject())
- hackInTaskProperties(type, task, taskFields)
- return task
- }
-
- private static void hackInTaskProperties(Class type, Task task, Map args) {
- args.each { k, v ->
- def field = type.getDeclaredField(k)
- field.setAccessible(true)
- field.set(task, v)
- }
- }
-
- static <T extends Task> T createTask(Class<T> type, ProjectInternal project) {
- return createTask(type, project, 'name')
- }
-
- static <T extends Task> T createTask(Class<T> type, ProjectInternal project, String name) {
- return project.services.get(ITaskFactory).createTask([name: name, type: type])
- }
-
- static ProjectBuilder builder() {
- return ProjectBuilder.builder().withProjectDir(TestNameTestDirectoryProvider.newInstance().testDirectory)
- }
-
- static DefaultProject createRootProject() {
- createRootProject(TestNameTestDirectoryProvider.newInstance().testDirectory)
- }
-
- static DefaultProject createRootProject(File rootDir) {
- return ProjectBuilder
- .builder()
- .withProjectDir(rootDir)
- .build()
- }
-
- static DefaultProject createChildProject(DefaultProject parent, String name, File projectDir = null) {
- return ProjectBuilder
- .builder()
- .withName(name)
- .withParent(parent)
- .withProjectDir(projectDir)
- .build();
- }
-
- static DefaultModuleDescriptor createModuleDescriptor(Set confs) {
- DefaultModuleDescriptor moduleDescriptor = new DefaultModuleDescriptor(ModuleRevisionId.newInstance('org', 'name', 'rev'), "status", null)
- confs.each { moduleDescriptor.addConfiguration(new Configuration(it)) }
- return moduleDescriptor;
- }
-
- static groovy.lang.Script createScript(String code) {
- new GroovyShell().parse(code)
- }
-
- static Object call(String text, Object... params) {
- toClosure(text).call(*params)
- }
-
- static Closure toClosure(String text) {
- return new GroovyShell().evaluate("return " + text)
- }
-
- static Closure toClosure(ScriptSource source) {
- CompilerConfiguration configuration = new CompilerConfiguration();
- configuration.setScriptBaseClass(TestScript.getName());
-
- GroovyShell shell = new GroovyShell(configuration)
- Script script = shell.parse(source.resource.text)
- script.setScriptSource(source)
- return script.run()
- }
-
- static Closure toClosure(TestClosure closure) {
- return { param -> closure.call(param) }
- }
-
- static Closure returns(Object value) {
- return { value }
- }
-
- static Closure createSetterClosure(String name, String value) {
- return {
- "set$name"(value)
- }
- }
-
- static String createUniqueId() {
- return new UID().toString();
- }
- }
-
-
-interface TestClosure {
- Object call(Object param);
-}
-
-abstract class TestScript extends DefaultScript {
-}
diff --git a/subprojects/core/src/testFixtures/groovy/org/gradle/util/TestTask.groovy b/subprojects/core/src/testFixtures/groovy/org/gradle/util/TestTask.groovy
index eadda17..eb6d41a 100644
--- a/subprojects/core/src/testFixtures/groovy/org/gradle/util/TestTask.groovy
+++ b/subprojects/core/src/testFixtures/groovy/org/gradle/util/TestTask.groovy
@@ -18,9 +18,6 @@ package org.gradle.util
import org.gradle.api.internal.ConventionTask
-/**
- * @author Hans Dockter
- */
class TestTask extends ConventionTask {
TestTask self
String customProp
diff --git a/subprojects/core/src/testFixtures/groovy/org/gradle/util/TestUtil.groovy b/subprojects/core/src/testFixtures/groovy/org/gradle/util/TestUtil.groovy
new file mode 100644
index 0000000..12f568c
--- /dev/null
+++ b/subprojects/core/src/testFixtures/groovy/org/gradle/util/TestUtil.groovy
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.util
+
+import org.apache.ivy.core.module.descriptor.Configuration
+import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor
+import org.apache.ivy.core.module.id.ModuleRevisionId
+import org.codehaus.groovy.control.CompilerConfiguration
+import org.gradle.api.Task
+import org.gradle.api.internal.project.DefaultProject
+import org.gradle.api.internal.project.ProjectInternal
+import org.gradle.api.internal.project.taskfactory.ITaskFactory
+import org.gradle.groovy.scripts.DefaultScript
+import org.gradle.groovy.scripts.Script
+import org.gradle.groovy.scripts.ScriptSource
+import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
+import org.gradle.testfixtures.ProjectBuilder
+
+import java.rmi.server.UID
+
+class TestUtil {
+ public static final Closure TEST_CLOSURE = {}
+
+ static <T extends Task> T createTask(Class<T> type) {
+ return createTask(type, createRootProject())
+ }
+
+ static <T extends Task> T createTask(Class<T> type, Map taskFields) {
+ def task = createTask(type, createRootProject())
+ hackInTaskProperties(type, task, taskFields)
+ return task
+ }
+
+ private static void hackInTaskProperties(Class type, Task task, Map args) {
+ args.each { k, v ->
+ def field = type.getDeclaredField(k)
+ field.setAccessible(true)
+ field.set(task, v)
+ }
+ }
+
+ static <T extends Task> T createTask(Class<T> type, ProjectInternal project) {
+ return createTask(type, project, 'name')
+ }
+
+ static <T extends Task> T createTask(Class<T> type, ProjectInternal project, String name) {
+ return project.services.get(ITaskFactory).createTask([name: name, type: type])
+ }
+
+ static ProjectBuilder builder() {
+ return ProjectBuilder.builder().withProjectDir(TestNameTestDirectoryProvider.newInstance().testDirectory)
+ }
+
+ static DefaultProject createRootProject() {
+ createRootProject(TestNameTestDirectoryProvider.newInstance().testDirectory)
+ }
+
+ static DefaultProject createRootProject(File rootDir) {
+ return ProjectBuilder
+ .builder()
+ .withProjectDir(rootDir)
+ .build()
+ }
+
+ static DefaultProject createChildProject(DefaultProject parent, String name, File projectDir = null) {
+ return ProjectBuilder
+ .builder()
+ .withName(name)
+ .withParent(parent)
+ .withProjectDir(projectDir)
+ .build();
+ }
+
+ static DefaultModuleDescriptor createModuleDescriptor(Set confs) {
+ DefaultModuleDescriptor moduleDescriptor = new DefaultModuleDescriptor(ModuleRevisionId.newInstance('org', 'name', 'rev'), "status", null)
+ confs.each { moduleDescriptor.addConfiguration(new Configuration(it)) }
+ return moduleDescriptor;
+ }
+
+ static groovy.lang.Script createScript(String code) {
+ new GroovyShell().parse(code)
+ }
+
+ static Object call(String text, Object... params) {
+ toClosure(text).call(*params)
+ }
+
+ static Closure toClosure(String text) {
+ return new GroovyShell().evaluate("return " + text)
+ }
+
+ static Closure toClosure(ScriptSource source) {
+ CompilerConfiguration configuration = new CompilerConfiguration();
+ configuration.setScriptBaseClass(TestScript.getName());
+
+ GroovyShell shell = new GroovyShell(configuration)
+ Script script = shell.parse(source.resource.text)
+ script.setScriptSource(source)
+ return script.run()
+ }
+
+ static Closure toClosure(TestClosure closure) {
+ return { param -> closure.call(param) }
+ }
+
+ static Closure returns(Object value) {
+ return { value }
+ }
+
+ static Closure createSetterClosure(String name, String value) {
+ return {
+ "set$name"(value)
+ }
+ }
+
+ static String createUniqueId() {
+ return new UID().toString();
+ }
+ }
+
+
+interface TestClosure {
+ Object call(Object param);
+}
+
+abstract class TestScript extends DefaultScript {
+}
diff --git a/subprojects/cpp/cpp.gradle b/subprojects/cpp/cpp.gradle
index 0bfc388..d377cf8 100644
--- a/subprojects/cpp/cpp.gradle
+++ b/subprojects/cpp/cpp.gradle
@@ -15,10 +15,11 @@
*/
dependencies {
- groovy libraries.groovy
+ compile libraries.groovy
compile project(':core')
compile project(":plugins")
compile project(":ide")
+ compile libraries.commons_io
integTestRuntime project(":maven")
}
@@ -30,3 +31,4 @@ integTestTasks.all {
}
useTestFixtures()
+//useClassycle()
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/AbstractLanguageIncrementalBuildIntegrationTest.groovy b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/AbstractLanguageIncrementalBuildIntegrationTest.groovy
new file mode 100755
index 0000000..1622573
--- /dev/null
+++ b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/AbstractLanguageIncrementalBuildIntegrationTest.groovy
@@ -0,0 +1,327 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp
+
+import org.gradle.internal.os.OperatingSystem
+import org.gradle.nativecode.language.cpp.fixtures.AbstractInstalledToolChainIntegrationSpec
+import org.gradle.nativecode.language.cpp.fixtures.app.IncrementalHelloWorldApp
+import org.gradle.test.fixtures.file.TestFile
+import org.gradle.util.Requires
+import org.gradle.util.TestPrecondition
+
+import static org.gradle.util.TextUtil.escapeString
+
+abstract class AbstractLanguageIncrementalBuildIntegrationTest extends AbstractInstalledToolChainIntegrationSpec {
+ IncrementalHelloWorldApp app
+ String mainCompileTask
+ String libraryCompileTask
+ TestFile sourceFile
+ TestFile headerFile
+ List<TestFile> librarySourceFiles = []
+
+ abstract IncrementalHelloWorldApp getHelloWorldApp();
+
+ def "setup"() {
+ app = getHelloWorldApp()
+ mainCompileTask = ":compileMainExecutableMain${app.sourceType}"
+ libraryCompileTask = ":compileHelloSharedLibraryHello${app.sourceType}"
+
+ buildFile << """
+ apply plugin: 'cpp'
+
+ sources {
+ main {}
+ hello {}
+ }
+
+ executables {
+ main {
+ source sources.main
+ }
+ }
+ libraries {
+ hello {
+ source sources.hello
+ binaries.withType(SharedLibraryBinary) {
+ define "DLL_EXPORT"
+ }
+ }
+ }
+ sources.main.cpp.lib libraries.hello
+ """
+ settingsFile << "rootProject.name = 'test'"
+
+ sourceFile = app.mainSource.writeToDir(file("src/main"))
+ headerFile = app.libraryHeader.writeToDir(file("src/hello"))
+ app.librarySources.each {
+ librarySourceFiles << it.writeToDir(file("src/hello"))
+ }
+
+ run "installMainExecutable"
+ }
+
+ def "does not re-execute build with no change"() {
+ when:
+ run "installMainExecutable"
+
+ then:
+ nonSkippedTasks.empty
+ }
+
+ @Requires(TestPrecondition.CAN_INSTALL_EXECUTABLE)
+ def "rebuilds binary with source file change"() {
+ given:
+ def install = installation("build/install/mainExecutable")
+
+ when:
+ sourceFile.text = app.alternateMainSource.content
+
+ and:
+ run "installMainExecutable"
+
+ then:
+ skipped libraryCompileTask
+ skipped ":linkHelloSharedLibrary"
+ skipped ":helloSharedLibrary"
+ executedAndNotSkipped mainCompileTask
+ executedAndNotSkipped ":linkMainExecutable"
+ executedAndNotSkipped ":mainExecutable"
+ executedAndNotSkipped ":installMainExecutable"
+
+ and:
+ install.assertInstalled()
+ install.exec().out == app.alternateOutput
+ }
+
+ @Requires(TestPrecondition.CAN_INSTALL_EXECUTABLE)
+ def "relinks binary with library source file change"() {
+ // sleep for 1 second to ensure generated binaries have different timestamp
+ sleep(1000)
+
+ when:
+ def install = installation("build/install/mainExecutable")
+ for (int i = 0; i < librarySourceFiles.size(); i++) {
+ TestFile sourceFile = librarySourceFiles.get(i);
+ sourceFile.text = app.alternateLibrarySources[i].content
+ }
+
+ and:
+ run "installMainExecutable"
+
+ then:
+ executedAndNotSkipped libraryCompileTask
+ executedAndNotSkipped ":linkHelloSharedLibrary"
+ executedAndNotSkipped ":helloSharedLibrary"
+ skipped mainCompileTask
+ executedAndNotSkipped ":linkMainExecutable"
+ executedAndNotSkipped ":mainExecutable"
+ executedAndNotSkipped ":installMainExecutable"
+
+ and:
+ install.assertInstalled()
+ install.exec().out == app.alternateLibraryOutput
+ }
+
+ def "recompiles binary when header file changes in a way that does not affect the object files"() {
+ if (toolChain.visualCpp) {
+ return // Visual C++ compiler embeds a timestamp in every object file, so relinking is always required after recompiling
+ }
+
+ when:
+ headerFile << """
+// Comment added to the end of the header file
+"""
+
+ run "installMainExecutable"
+
+ then:
+ executedAndNotSkipped libraryCompileTask
+ skipped ":linkHelloSharedLibrary"
+ skipped ":helloSharedLibrary"
+ executedAndNotSkipped mainCompileTask
+ skipped ":linkMainExecutable"
+ skipped ":mainExecutable"
+ skipped ":installMainExecutable"
+ }
+
+ @Requires(TestPrecondition.CAN_INSTALL_EXECUTABLE)
+ def "rebuilds binary with compiler option change"() {
+ when:
+ def install = installation("build/install/mainExecutable")
+
+ and:
+ buildFile << """
+ libraries {
+ hello {
+ binaries.all { compilerArgs '-DFRENCH' }
+ }
+ }
+"""
+
+ run "installMainExecutable"
+
+ then:
+ executedAndNotSkipped libraryCompileTask
+ executedAndNotSkipped ":linkHelloSharedLibrary"
+ executedAndNotSkipped ":helloSharedLibrary"
+ skipped mainCompileTask
+ executedAndNotSkipped ":linkMainExecutable"
+ executedAndNotSkipped ":mainExecutable"
+ executedAndNotSkipped ":installMainExecutable"
+
+ and:
+ install.assertInstalled()
+ install.exec().out == app.frenchOutput
+ }
+
+ def "relinks binary when set of input libraries changes"() {
+ def executable = executable("build/binaries/mainExecutable/main")
+ def snapshot = executable.snapshot()
+
+ when:
+ buildFile << """
+ executables {
+ main {
+ binaries.all {
+ lib libraries.hello.static
+ }
+ }
+ }
+"""
+
+ run "installMainExecutable"
+
+ then:
+ skipped libraryCompileTask
+ skipped ":linkHelloSharedLibrary"
+ skipped ":helloSharedLibrary"
+ skipped mainCompileTask
+ executedAndNotSkipped ":linkMainExecutable"
+ executedAndNotSkipped ":mainExecutable"
+ executedAndNotSkipped ":installMainExecutable"
+
+ and:
+ executable.assertHasChangedSince(snapshot)
+ }
+
+ def "relinks binary but does not recompile when linker option changed"() {
+ when:
+ def executable = executable("build/binaries/mainExecutable/main")
+ def snapshot = executable.snapshot()
+
+ and:
+ def linkerArgs = toolChain.isVisualCpp() ? "'/DEBUG'" : OperatingSystem.current().isMacOsX() ? "'-no_pie'" : "'-q'";
+ linkerArgs = escapeString(linkerArgs)
+ buildFile << """
+ executables {
+ main {
+ binaries.all { linkerArgs ${escapeString(linkerArgs)} }
+ }
+ }
+"""
+
+ run "installMainExecutable"
+
+ then:
+ skipped libraryCompileTask
+ skipped ":linkHelloSharedLibrary"
+ skipped ":helloSharedLibrary"
+ skipped mainCompileTask
+ executedAndNotSkipped ":linkMainExecutable"
+ executedAndNotSkipped ":mainExecutable"
+ executedAndNotSkipped ":installMainExecutable"
+
+ and:
+ executable.assertExists()
+ executable.assertHasChangedSince(snapshot)
+ }
+
+ def "recompiles source but does not relink binary with source comment change"() {
+ if (toolChain.visualCpp) {
+ return // Visual C++ compiler embeds a timestamp in every object file, so relinking is always required after recompiling
+ }
+ when:
+ sourceFile.text = sourceFile.text.replaceFirst("// Simple hello world app", "// Comment is changed")
+ run "installMainExecutable"
+
+ then:
+ skipped libraryCompileTask
+ skipped ":linkHelloSharedLibrary"
+ skipped ":helloSharedLibrary"
+ executedAndNotSkipped mainCompileTask
+ skipped ":linkMainExecutable"
+ skipped ":mainExecutable"
+ skipped ":installMainExecutable"
+ }
+
+ def "cleans up stale object files when source file renamed"() {
+ def oldObjFile = objectFile("build/objectFiles/mainExecutable/main${app.sourceType}/main")
+ def newObjFile = objectFile("build/objectFiles/mainExecutable/main${app.sourceType}/changed_main")
+ assert oldObjFile.file
+ assert !newObjFile.file
+
+ when:
+ sourceFile.renameTo("${sourceFile.parentFile.absolutePath}/changed_${sourceFile.name}")
+ run "mainExecutable"
+
+ then:
+ skipped libraryCompileTask
+ skipped ":linkHelloSharedLibrary"
+ skipped ":helloSharedLibrary"
+ executedAndNotSkipped mainCompileTask
+ executedAndNotSkipped ":linkMainExecutable"
+ executedAndNotSkipped ":mainExecutable"
+
+ and:
+ !oldObjFile.file
+ newObjFile.file
+ }
+
+ def "cleans up stale debug files when changing from debug to non-debug"() {
+ if (!toolChain.visualCpp) {
+ return
+ }
+
+ given:
+ buildFile << """
+ binaries.all { compilerArgs '/Zi'; linkerArgs '/DEBUG'; }
+ """
+ run "mainExecutable"
+
+ def executable = executable("build/binaries/mainExecutable/main")
+ executable.assertDebugFileExists()
+
+ when:
+ buildFile << """
+ binaries.all { compilerArgs.clear(); linkerArgs.clear(); }
+ """
+ run "mainExecutable"
+
+ then:
+ executedAndNotSkipped libraryCompileTask
+ executedAndNotSkipped ":helloSharedLibrary"
+ executedAndNotSkipped mainCompileTask
+ executedAndNotSkipped ":linkMainExecutable"
+ executedAndNotSkipped ":mainExecutable"
+
+ and:
+ executable.assertDebugFileDoesNotExist()
+ }
+}
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/AbstractLanguageIntegrationTest.groovy b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/AbstractLanguageIntegrationTest.groovy
new file mode 100755
index 0000000..2eaf887
--- /dev/null
+++ b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/AbstractLanguageIntegrationTest.groovy
@@ -0,0 +1,208 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp
+import org.gradle.nativecode.language.cpp.fixtures.AbstractInstalledToolChainIntegrationSpec
+import org.gradle.nativecode.language.cpp.fixtures.app.HelloWorldApp
+import org.gradle.util.Requires
+import org.gradle.util.TestPrecondition
+
+abstract class AbstractLanguageIntegrationTest extends AbstractInstalledToolChainIntegrationSpec {
+
+ abstract HelloWorldApp getHelloWorldApp()
+
+ def "compile and link executable"() {
+ given:
+ buildFile << """
+ apply plugin: "cpp"
+ sources {
+ main {}
+ }
+ executables {
+ main {
+ source sources.main
+ }
+ }
+ binaries.all {
+ $helloWorldApp.customArgs
+ }
+ """
+
+ and:
+ helloWorldApp.writeSources(file("src/main"))
+
+ when:
+ run "mainExecutable"
+
+ then:
+ def mainExecutable = executable("build/binaries/mainExecutable/main")
+ mainExecutable.assertExists()
+ mainExecutable.exec().out == helloWorldApp.englishOutput
+ }
+
+ def "build executable with custom compiler arg"() {
+ given:
+ buildFile << """
+ apply plugin: "cpp"
+ sources {
+ main {}
+ }
+ executables {
+ main {
+ source sources.main
+ binaries.all {
+ compilerArgs "-DFRENCH"
+ }
+ }
+ }
+ binaries.all {
+ $helloWorldApp.customArgs
+ }
+ """
+
+ and:
+ helloWorldApp.writeSources(file("src/main"))
+
+ when:
+ run "mainExecutable"
+
+ then:
+ def mainExecutable = executable("build/binaries/mainExecutable/main")
+ mainExecutable.assertExists()
+ mainExecutable.exec().out == helloWorldApp.frenchOutput
+ }
+
+ def "build executable with macro defined"() {
+ given:
+ buildFile << """
+ apply plugin: "cpp"
+ sources {
+ main {}
+ }
+ executables {
+ main {
+ source sources.main
+ binaries.all {
+ define "FRENCH"
+ }
+ }
+ }
+ binaries.all {
+ $helloWorldApp.customArgs
+ }
+ """
+
+ and:
+ helloWorldApp.writeSources(file("src/main"))
+
+ when:
+ run "mainExecutable"
+
+ then:
+ def mainExecutable = executable("build/binaries/mainExecutable/main")
+ mainExecutable.assertExists()
+ mainExecutable.exec().out == helloWorldApp.frenchOutput
+ }
+
+ @Requires(TestPrecondition.CAN_INSTALL_EXECUTABLE)
+ def "build shared library and link into executable"() {
+ given:
+ buildFile << """
+ apply plugin: "cpp"
+
+ sources {
+ main {}
+ hello {}
+ }
+ executables {
+ main {
+ source sources.main
+ }
+ }
+ libraries {
+ hello {
+ source sources.hello
+ }
+ }
+ sources.main.c.lib libraries.hello
+ binaries.all {
+ $helloWorldApp.customArgs
+ }
+ """
+
+ and:
+ helloWorldApp.writeSources(file("src/main"), file("src/hello"))
+
+ when:
+ run "installMainExecutable"
+
+ then:
+ sharedLibrary("build/binaries/helloSharedLibrary/hello").assertExists()
+ executable("build/binaries/mainExecutable/main").assertExists()
+
+ def install = installation("build/install/mainExecutable")
+ install.assertInstalled()
+ install.assertIncludesLibraries("hello")
+ install.exec().out == helloWorldApp.englishOutput
+ }
+
+ @Requires(TestPrecondition.CAN_INSTALL_EXECUTABLE)
+ def "build static library and link into executable"() {
+ given:
+ buildFile << """
+ apply plugin: "cpp"
+
+ sources {
+ main {}
+ hello {}
+ }
+ executables {
+ main {
+ source sources.main
+ }
+ }
+ libraries {
+ hello {
+ source sources.hello
+ binaries.withType(StaticLibraryBinary) {
+ define "FRENCH"
+ }
+ }
+ }
+ sources.main.c.lib libraries.hello.static
+ binaries.all {
+ $helloWorldApp.customArgs
+ }
+ """
+
+ and:
+ helloWorldApp.writeSources(file("src/main"), file("src/hello"))
+
+ when:
+ run "installMainExecutable"
+
+ then:
+ staticLibrary("build/binaries/helloStaticLibrary/hello").assertExists()
+ executable("build/binaries/mainExecutable/main").assertExists()
+
+ and:
+ def install = installation("build/install/mainExecutable")
+ install.assertInstalled()
+ install.exec().out == helloWorldApp.frenchOutput
+ }
+}
+
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/AssemblyLanguageIntegrationTest.groovy b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/AssemblyLanguageIntegrationTest.groovy
new file mode 100755
index 0000000..15aae95
--- /dev/null
+++ b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/AssemblyLanguageIntegrationTest.groovy
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp
+
+import org.gradle.nativecode.language.cpp.fixtures.AvailableToolChains
+import org.gradle.nativecode.language.cpp.fixtures.app.HelloWorldApp
+import org.gradle.nativecode.language.cpp.fixtures.app.MixedLanguageHelloWorldApp
+import org.gradle.nativecode.language.cpp.fixtures.app.SourceFile
+
+class AssemblyLanguageIntegrationTest extends AbstractLanguageIntegrationTest {
+
+ HelloWorldApp helloWorldApp = new AssemblerWithCHelloWorldApp(toolChain)
+
+ def "build fails when compilation fails"() {
+ given:
+ buildFile << """
+ apply plugin: "cpp"
+ sources {
+ main {}
+ }
+ executables {
+ main {
+ source sources.main
+ }
+ }
+ """
+
+ and:
+ file("src/main/asm/broken.s") << """
+.section __TEXT,__text,regular,pure_instructions
+.globl _sum
+.align 4, 0x90
+_sum:
+pushl
+"""
+
+ expect:
+ fails "mainExecutable"
+ failure.assertHasDescription("Execution failed for task ':assembleMainExecutableMainAsm'.");
+ failure.assertHasCause("Assembler failed; see the error output for details.")
+ }
+
+ static class AssemblerWithCHelloWorldApp extends MixedLanguageHelloWorldApp {
+ AssemblerWithCHelloWorldApp(AvailableToolChains.InstalledToolChain toolChain) {
+ super(toolChain)
+ }
+
+ @Override
+ SourceFile getMainSource() {
+ return new SourceFile("c", "main.c", """
+ #include <stdio.h>
+ #include "hello.h"
+
+ int main () {
+ sayHello();
+ printf("%d", sum(5, 7));
+ return 0;
+ }
+ """);
+ }
+ }
+}
+
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/BinaryFlavorsIntegrationTest.groovy b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/BinaryFlavorsIntegrationTest.groovy
new file mode 100755
index 0000000..d7583c9
--- /dev/null
+++ b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/BinaryFlavorsIntegrationTest.groovy
@@ -0,0 +1,217 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp
+import org.gradle.nativecode.language.cpp.fixtures.AbstractInstalledToolChainIntegrationSpec
+import org.gradle.nativecode.language.cpp.fixtures.app.CppHelloWorldApp
+import org.gradle.util.Requires
+import org.gradle.util.TestPrecondition
+
+class BinaryFlavorsIntegrationTest extends AbstractInstalledToolChainIntegrationSpec {
+ def helloWorldApp = new CppHelloWorldApp()
+
+ def "setup"() {
+ settingsFile << "rootProject.name = 'test'"
+
+ helloWorldApp.writeSources(file("src/main"), file("src/hello"))
+ }
+
+ @Requires(TestPrecondition.CAN_INSTALL_EXECUTABLE)
+ def "build multiple flavors of executable binary and link library with no defined flavor"() {
+ when:
+ buildFile << """
+ apply plugin: "cpp"
+ sources {
+ main {}
+ hello {}
+ }
+ libraries {
+ hello {
+ source sources.hello
+ binaries.withType(StaticLibraryBinary) {
+ define "FRENCH"
+ }
+ }
+ }
+ executables {
+ main {
+ source sources.main
+ flavors {
+ english {}
+ french {}
+ }
+ binaries.all {
+ if (flavor == flavors.french) {
+ lib libraries.hello.static
+ } else {
+ lib libraries.hello.shared
+ }
+ }
+ }
+ }
+ """
+
+ and:
+ succeeds "installEnglishMainExecutable"
+
+ then:
+ installation("build/install/mainExecutable/english").exec().out == helloWorldApp.englishOutput
+
+ when:
+ succeeds "installFrenchMainExecutable"
+
+ then:
+ installation("build/install/mainExecutable/french").exec().out == helloWorldApp.frenchOutput
+ }
+
+ @Requires(TestPrecondition.CAN_INSTALL_EXECUTABLE)
+ def "build multiple flavors of shared library binary and link into executable with same flavor"() {
+ when:
+ buildFile << """
+ apply plugin: "cpp"
+ sources {
+ main {}
+ hello {}
+ }
+ libraries {
+ hello {
+ source sources.hello
+ flavors {
+ english {}
+ french {}
+ }
+ binaries.all {
+ if (flavor == flavors.french) {
+ define "FRENCH"
+ }
+ }
+ }
+ }
+ executables {
+ main {
+ source sources.main
+ flavors {
+ english {}
+ french {}
+ }
+ binaries.all {
+ lib libraries.hello
+ }
+ }
+ }
+ """
+
+ and:
+ succeeds "installEnglishMainExecutable"
+
+ then:
+ installation("build/install/mainExecutable/english").assertInstalled().exec().out == helloWorldApp.englishOutput
+
+ when:
+ succeeds "installFrenchMainExecutable"
+
+ then:
+ installation("build/install/mainExecutable/french").assertInstalled().exec().out == helloWorldApp.frenchOutput
+ }
+
+ def "build multiple flavors of static library binary and link into executable with same flavor"() {
+ when:
+ buildFile << """
+ apply plugin: "cpp"
+ sources {
+ main {}
+ hello {}
+ }
+ libraries {
+ hello {
+ source sources.hello
+ flavors {
+ english {}
+ french {}
+ }
+ binaries.all {
+ if (flavor == flavors.french) {
+ define "FRENCH"
+ }
+ }
+ }
+ }
+ executables {
+ main {
+ source sources.main
+ flavors {
+ english {}
+ french {}
+ }
+ binaries.all {
+ lib libraries.hello.static
+ }
+ }
+ }
+ """
+
+ and:
+ succeeds "englishMainExecutable"
+
+ then:
+ executable("build/binaries/mainExecutable/english/main").exec().out == helloWorldApp.englishOutput
+
+ when:
+ succeeds "frenchMainExecutable"
+
+ then:
+ executable("build/binaries/mainExecutable/french/main").exec().out == helloWorldApp.frenchOutput
+ }
+
+ def "build fails when library has no matching flavour"() {
+ when:
+ buildFile << """
+ apply plugin: "cpp"
+ sources {
+ main {}
+ hello {}
+ }
+ libraries {
+ hello {
+ source sources.hello
+ flavors {
+ english {}
+ french {}
+ }
+ }
+ }
+ executables {
+ main {
+ source sources.main
+ flavors {
+ english {}
+ german {}
+ }
+ binaries.all {
+ lib libraries.hello
+ }
+ }
+ }
+ """
+
+ and:
+ // TODO:DAZ Fix the exception reporting
+ executer.withStackTraceChecksDisabled()
+
+ then:
+ fails "germanMainExecutable"
+ failure.assertHasCause("No shared library binary available for library 'hello' with flavor 'german'")
+ }
+}
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/CCallingCppLanguageIntegrationTest.groovy b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/CCallingCppLanguageIntegrationTest.groovy
new file mode 100755
index 0000000..9ef741e
--- /dev/null
+++ b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/CCallingCppLanguageIntegrationTest.groovy
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp
+
+import org.gradle.nativecode.language.cpp.fixtures.app.CCallingCppHelloWorldApp
+import org.gradle.nativecode.language.cpp.fixtures.app.HelloWorldApp
+
+class CCallingCppLanguageIntegrationTest extends AbstractLanguageIntegrationTest {
+ HelloWorldApp helloWorldApp = new CCallingCppHelloWorldApp()
+}
+
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/CLanguageIncrementalBuildIntegrationTest.groovy b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/CLanguageIncrementalBuildIntegrationTest.groovy
new file mode 100755
index 0000000..5980fc9
--- /dev/null
+++ b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/CLanguageIncrementalBuildIntegrationTest.groovy
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp
+
+import org.gradle.nativecode.language.cpp.fixtures.app.CHelloWorldApp
+import org.gradle.nativecode.language.cpp.fixtures.app.IncrementalHelloWorldApp
+
+class CLanguageIncrementalBuildIntegrationTest extends AbstractLanguageIncrementalBuildIntegrationTest {
+ @Override
+ IncrementalHelloWorldApp getHelloWorldApp() {
+ new CHelloWorldApp()
+ }
+}
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/CLanguageIntegrationTest.groovy b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/CLanguageIntegrationTest.groovy
new file mode 100755
index 0000000..9f228cf
--- /dev/null
+++ b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/CLanguageIntegrationTest.groovy
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp
+
+import org.gradle.nativecode.language.cpp.fixtures.app.CHelloWorldApp
+import org.gradle.nativecode.language.cpp.fixtures.app.HelloWorldApp
+
+class CLanguageIntegrationTest extends AbstractLanguageIntegrationTest {
+
+ HelloWorldApp helloWorldApp = new CHelloWorldApp()
+
+ def "build fails when compilation fails"() {
+ given:
+ buildFile << """
+ apply plugin: "cpp"
+ sources {
+ main {}
+ }
+ executables {
+ main {
+ source sources.main
+ }
+ }
+ """
+
+ and:
+ file("src/main/c/broken.c") << """
+ #include <stdio.h>
+
+ 'broken
+"""
+
+ expect:
+ fails "mainExecutable"
+ failure.assertHasDescription("Execution failed for task ':compileMainExecutableMainC'.");
+ failure.assertHasCause("C compiler failed; see the error output for details.")
+ }
+}
+
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/CppBinariesIntegrationTest.groovy b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/CppBinariesIntegrationTest.groovy
new file mode 100755
index 0000000..d794ea2
--- /dev/null
+++ b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/CppBinariesIntegrationTest.groovy
@@ -0,0 +1,219 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp
+
+import org.gradle.nativecode.language.cpp.fixtures.AbstractInstalledToolChainIntegrationSpec
+import org.gradle.util.Requires
+import org.gradle.util.TestPrecondition
+
+class CppBinariesIntegrationTest extends AbstractInstalledToolChainIntegrationSpec {
+ def "can configure the binaries of a C++ application"() {
+ given:
+ buildFile << """
+ apply plugin: "cpp-exe"
+
+ executables {
+ main {
+ binaries.all {
+ outputFile file('${executable("build/test").toURI()}')
+ define 'ENABLE_GREETING'
+ }
+ }
+ }
+ """
+ settingsFile << "rootProject.name = 'test'"
+
+ and:
+ file("src/main/cpp/helloworld.cpp") << """
+ #include <iostream>
+
+ int main () {
+ #ifdef ENABLE_GREETING
+ std::cout << "Hello!";
+ #endif
+ return 0;
+ }
+ """
+
+ when:
+ run "mainExecutable"
+
+ then:
+ def executable = executable("build/test")
+ executable.exec().out == "Hello!"
+ }
+
+ def "can build debug binaries for a C++ executable"() {
+ given:
+ buildFile << """
+ apply plugin: "cpp-exe"
+
+ executables {
+ main {
+ binaries.all {
+ if (toolChain in VisualCpp) {
+ compilerArgs '/Zi'
+ linkerArgs '/DEBUG'
+ } else {
+ compilerArgs '-g'
+ }
+ }
+ }
+ }
+ """
+ settingsFile << "rootProject.name = 'test'"
+
+ and:
+ file("src/main/cpp/helloworld.cpp") << """
+ #include <iostream>
+
+ int main () {
+ std::cout << "Hello!";
+ return 0;
+ }
+ """
+
+ when:
+ run "mainExecutable"
+
+ then:
+ def executable = executable("build/binaries/mainExecutable/test")
+ executable.exec().out == "Hello!"
+ executable.assertDebugFileExists()
+ // TODO - need to verify that the debug info ended up in the binary
+ }
+
+ @Requires(TestPrecondition.CAN_INSTALL_EXECUTABLE)
+ def "can configure the binaries of a C++ library"() {
+ given:
+ buildFile << """
+ apply plugin: "cpp-exe"
+
+ sources {
+ hello {}
+ }
+ libraries {
+ hello {
+ source sources.hello.cpp
+ binaries.all {
+ outputFile file('${staticLibrary("build/hello").toURI()}')
+ define 'ENABLE_GREETING'
+ }
+ }
+ }
+ executables {
+ main {
+ binaries.all {
+ lib libraries.hello.static
+ }
+ }
+ }
+ """
+ settingsFile << "rootProject.name = 'test'"
+
+ and:
+ file("src/hello/cpp/hello.cpp") << """
+ #include <iostream>
+
+ void hello(const char* str) {
+ #ifdef ENABLE_GREETING
+ std::cout << str;
+ #endif
+ }
+ """
+
+ and:
+ file("src/hello/headers/hello.h") << """
+ void hello(const char* str);
+ """
+
+ and:
+ file("src/main/cpp/main.cpp") << """
+ #include "hello.h"
+
+ int main () {
+ hello("Hello!");
+ return 0;
+ }
+ """
+
+ when:
+ run "installMainExecutable"
+
+ then:
+ staticLibrary("build/hello").assertExists()
+ installation("build/install/mainExecutable").exec().out == "Hello!"
+ }
+
+ def "can configure a binary to use additional source sets"() {
+ given:
+ buildFile << """
+ apply plugin: "cpp"
+
+ sources {
+ main {
+ cpp {
+ exportedHeaders.srcDir "src/shared/headers"
+ }
+ }
+ util {
+ cpp {
+ exportedHeaders.srcDir "src/shared/headers"
+ }
+ }
+ }
+ executables {
+ main {
+ source sources.main.cpp
+ binaries.all {
+ source sources.util.cpp
+ }
+ }
+ }
+ """
+ settingsFile << "rootProject.name = 'test'"
+
+ and:
+ file("src/shared/headers/greeting.h") << """
+ void greeting();
+"""
+
+ file("src/util/cpp/greeting.cpp") << """
+ #include <iostream>
+ #include "greeting.h"
+
+ void greeting() {
+ std::cout << "Hello!";
+ }
+ """
+
+ file("src/main/cpp/helloworld.cpp") << """
+ #include "greeting.h"
+
+ int main() {
+ greeting();
+ return 0;
+ }
+ """
+
+ when:
+ run "mainExecutable"
+
+ then:
+ def executable = executable("build/binaries/mainExecutable/main")
+ executable.exec().out == "Hello!"
+ }
+}
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/CppCallingCLanguageIntegrationTest.groovy b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/CppCallingCLanguageIntegrationTest.groovy
new file mode 100755
index 0000000..b16d5d9
--- /dev/null
+++ b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/CppCallingCLanguageIntegrationTest.groovy
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp
+
+import org.gradle.nativecode.language.cpp.fixtures.app.CppCallingCHelloWorldApp
+import org.gradle.nativecode.language.cpp.fixtures.app.HelloWorldApp
+
+class CppCallingCLanguageIntegrationTest extends AbstractLanguageIntegrationTest {
+ HelloWorldApp helloWorldApp = new CppCallingCHelloWorldApp()
+}
+
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/CppExePluginGoodBehaviourTest.groovy b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/CppExePluginGoodBehaviourTest.groovy
new file mode 100644
index 0000000..2d38fc4
--- /dev/null
+++ b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/CppExePluginGoodBehaviourTest.groovy
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp
+
+import org.gradle.integtests.fixtures.WellBehavedPluginTest
+
+class CppExePluginGoodBehaviourTest extends WellBehavedPluginTest {
+ @Override
+ def String getPluginId() {
+ return "cpp-exe"
+ }
+}
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/CppExePluginIntegrationTest.groovy b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/CppExePluginIntegrationTest.groovy
new file mode 100644
index 0000000..925e0af
--- /dev/null
+++ b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/CppExePluginIntegrationTest.groovy
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp
+
+import org.gradle.nativecode.language.cpp.fixtures.AbstractInstalledToolChainIntegrationSpec
+import org.gradle.util.Requires
+import org.gradle.util.TestPrecondition
+
+class CppExePluginIntegrationTest extends AbstractInstalledToolChainIntegrationSpec {
+ @Requires(TestPrecondition.CAN_INSTALL_EXECUTABLE)
+ def "build, install and execute simple c++ application that uses conventional layout"() {
+ given:
+ buildFile << """
+ apply plugin: "cpp-exe"
+ """
+ settingsFile << "rootProject.name = 'test'"
+
+ and:
+ file("src/main/headers/helloworld.h") << """
+ #define MESSAGE "Hello world!"
+ """
+
+ file("src/main/cpp/helloworld.cpp") << """
+ #include <iostream>
+ #include "helloworld.h"
+
+ int main () {
+ std::cout << MESSAGE;
+ return 0;
+ }
+ """
+
+ when:
+ run "mainExecutable"
+
+ then:
+ def executable = executable("build/binaries/mainExecutable/test")
+ executable.assertExists()
+ executable.exec().out == "Hello world!"
+
+ when:
+ run "installMainExecutable"
+
+ then:
+ def installation = installation("build/install/mainExecutable")
+ installation.assertInstalled()
+ installation.exec().out == "Hello world!"
+ }
+}
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/CppLanguageIncrementalBuildIntegrationTest.groovy b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/CppLanguageIncrementalBuildIntegrationTest.groovy
new file mode 100755
index 0000000..7621a6b
--- /dev/null
+++ b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/CppLanguageIncrementalBuildIntegrationTest.groovy
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp
+import org.gradle.nativecode.language.cpp.fixtures.app.CppHelloWorldApp
+import org.gradle.nativecode.language.cpp.fixtures.app.IncrementalHelloWorldApp
+
+class CppLanguageIncrementalBuildIntegrationTest extends AbstractLanguageIncrementalBuildIntegrationTest {
+ IncrementalHelloWorldApp getHelloWorldApp() {
+ new CppHelloWorldApp()
+ }
+}
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/CppLanguageIntegrationTest.groovy b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/CppLanguageIntegrationTest.groovy
new file mode 100755
index 0000000..3339007
--- /dev/null
+++ b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/CppLanguageIntegrationTest.groovy
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp
+
+import org.gradle.nativecode.language.cpp.fixtures.app.CppHelloWorldApp
+import org.gradle.nativecode.language.cpp.fixtures.app.HelloWorldApp
+
+class CppLanguageIntegrationTest extends AbstractLanguageIntegrationTest {
+
+ HelloWorldApp helloWorldApp = new CppHelloWorldApp()
+
+ def "build fails when compilation fails"() {
+ given:
+ buildFile << """
+ apply plugin: "cpp"
+ sources {
+ main {}
+ }
+ executables {
+ main {
+ source sources.main
+ }
+ }
+ """
+
+ and:
+ file("src/main/cpp/broken.cpp") << """
+ #include <iostream>
+
+ 'broken
+"""
+
+ expect:
+ fails "mainExecutable"
+ failure.assertHasDescription("Execution failed for task ':compileMainExecutableMainCpp'.");
+ failure.assertHasCause("C++ compiler failed; see the error output for details.")
+ }
+}
+
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/CppLibPluginGoodBehaviourTest.groovy b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/CppLibPluginGoodBehaviourTest.groovy
new file mode 100644
index 0000000..788199a
--- /dev/null
+++ b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/CppLibPluginGoodBehaviourTest.groovy
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp
+
+import org.gradle.integtests.fixtures.WellBehavedPluginTest
+
+class CppLibPluginGoodBehaviourTest extends WellBehavedPluginTest {
+ @Override
+ def String getPluginId() {
+ return "cpp-lib"
+ }
+}
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/CppLibPluginIntegrationTest.groovy b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/CppLibPluginIntegrationTest.groovy
new file mode 100644
index 0000000..d66c148
--- /dev/null
+++ b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/CppLibPluginIntegrationTest.groovy
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp
+
+import org.gradle.nativecode.language.cpp.fixtures.AbstractInstalledToolChainIntegrationSpec
+
+class CppLibPluginIntegrationTest extends AbstractInstalledToolChainIntegrationSpec {
+ def "build simple c++ library that uses conventional layout"() {
+ given:
+ buildFile << """
+ apply plugin: "cpp-lib"
+ """
+ settingsFile << "rootProject.name = 'test'"
+
+ and:
+ file("src/main/headers/helloworld.h") << """
+ #ifdef _WIN32
+ #define LIB_FUNC __declspec(dllexport)
+ #else
+ #define LIB_FUNC
+ #endif
+
+ void LIB_FUNC greeting();
+ """
+
+ file("src/main/cpp/helloworld.cpp") << """
+ #include <iostream>
+ #include "helloworld.h"
+
+ void greeting() {
+ std::cout << "Hello world!";
+ }
+ """
+
+ when:
+ run "mainSharedLibrary"
+
+ then:
+ sharedLibrary("build/binaries/mainSharedLibrary/test").assertExists()
+
+ when:
+ run "mainStaticLibrary"
+
+ then:
+ staticLibrary("build/binaries/mainStaticLibrary/test").assertExists()
+ }
+}
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/CppPluginGoodBehaviourTest.groovy b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/CppPluginGoodBehaviourTest.groovy
new file mode 100644
index 0000000..85f44b5
--- /dev/null
+++ b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/CppPluginGoodBehaviourTest.groovy
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp
+
+import org.gradle.integtests.fixtures.WellBehavedPluginTest
+
+class CppPluginGoodBehaviourTest extends WellBehavedPluginTest {
+ @Override
+ def String getPluginId() {
+ return "cpp"
+ }
+}
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/CppPluginIntegrationTest.groovy b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/CppPluginIntegrationTest.groovy
new file mode 100755
index 0000000..deaded1
--- /dev/null
+++ b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/CppPluginIntegrationTest.groovy
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp
+
+import org.gradle.nativecode.language.cpp.fixtures.AbstractInstalledToolChainIntegrationSpec
+import org.gradle.nativecode.language.cpp.fixtures.app.CppHelloWorldApp
+
+class CppPluginIntegrationTest extends AbstractInstalledToolChainIntegrationSpec {
+
+ static final HELLO_WORLD = "Hello, World!"
+ static final HELLO_WORLD_FRENCH = "Bonjour, Monde!"
+
+ def "can explicitly configure tool chain in path"() {
+ def helloWorld = new CppHelloWorldApp()
+
+ given:
+ buildFile << """
+ apply plugin: "cpp-exe"
+
+ toolChains {
+ test(${toolChain.getImplementationClass()})
+ }
+"""
+ settingsFile << "rootProject.name = 'test'"
+
+ helloWorld.writeSources(file("src/main"))
+
+ when:
+ run "mainExecutable"
+
+ then:
+ def executable = executable("build/binaries/mainExecutable/test")
+ executable.assertExists()
+ executable.exec().out == helloWorld.englishOutput
+ }
+
+ def "build and execute program with non-conventional source layout"() {
+ given:
+ buildFile << """
+ apply plugin: "cpp"
+ sources {
+ main {
+ cpp {
+ source {
+ srcDirs "src"
+ include "**/*.cpp"
+ }
+ exportedHeaders {
+ srcDirs "src/hello", "include"
+ }
+ }
+ c {
+ source {
+ srcDirs "src", "include"
+ include "**/*.c"
+ }
+ exportedHeaders {
+ srcDirs "src/hello", "include"
+ }
+ }
+ }
+ }
+ executables {
+ main {
+ source sources.main
+ }
+ }
+ """
+ settingsFile << "rootProject.name = 'test'"
+
+ and:
+ file("src", "hello", "hello.cpp") << """
+ #include <iostream>
+
+ void hello () {
+ std::cout << "${HELLO_WORLD}";
+ }
+ """
+
+ and:
+ file("src", "hello", "french", "bonjour.c") << """
+ #include <stdio.h>
+ #include "otherProject/bonjour.h"
+
+ void bonjour() {
+ printf("${HELLO_WORLD_FRENCH}");
+ }
+ """
+
+ and:
+ file("src", "hello", "hello.h") << """
+ void hello();
+ """
+
+ and:
+ file("src", "app", "main", "main.cpp") << """
+ #include "hello.h"
+ extern "C" {
+ #include "otherProject/bonjour.h"
+ }
+
+ int main () {
+ hello();
+ bonjour();
+ return 0;
+ }
+ """
+
+ and:
+ file("include", "otherProject", "bonjour.h") << """
+ void bonjour();
+ """
+
+ and:
+ file("include", "otherProject", "bonjour.cpp") << """
+ THIS FILE WON'T BE COMPILED
+ """
+
+ when:
+ run "mainExecutable"
+
+ then:
+ executable("build/binaries/mainExecutable/main").exec().out == HELLO_WORLD + HELLO_WORLD_FRENCH
+ }
+}
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/CppSamplesIntegrationTest.groovy b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/CppSamplesIntegrationTest.groovy
new file mode 100755
index 0000000..6a76356
--- /dev/null
+++ b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/CppSamplesIntegrationTest.groovy
@@ -0,0 +1,189 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp
+import org.gradle.integtests.fixtures.Sample
+import org.gradle.nativecode.language.cpp.fixtures.AbstractInstalledToolChainIntegrationSpec
+import org.gradle.util.Requires
+import org.gradle.util.TestPrecondition
+import org.junit.Rule
+
+ at Requires(TestPrecondition.CAN_INSTALL_EXECUTABLE)
+class CppSamplesIntegrationTest extends AbstractInstalledToolChainIntegrationSpec {
+ @Rule public final Sample c = new Sample(temporaryFolder, 'cpp/c')
+ @Rule public final Sample asm = new Sample(temporaryFolder, 'cpp/c-with-assembler')
+ @Rule public final Sample cpp = new Sample(temporaryFolder, 'cpp/cpp')
+ @Rule public final Sample cppExe = new Sample(temporaryFolder, 'cpp/cpp-exe')
+ @Rule public final Sample cppLib = new Sample(temporaryFolder, 'cpp/cpp-lib')
+ @Rule public final Sample multiProject = new Sample(temporaryFolder, 'cpp/multi-project')
+ @Rule public final Sample variants = new Sample(temporaryFolder, 'cpp/variants')
+ @Rule public final Sample dependencies = new Sample(temporaryFolder, 'cpp/dependencies')
+
+ def "asm"() {
+ given:
+ sample asm
+
+ when:
+ run "installMainExecutable"
+
+ then:
+ executedAndNotSkipped ":assembleMainExecutableMainAsm", ":compileMainExecutableMainC", ":linkMainExecutable", ":mainExecutable"
+
+ and:
+ installation("cpp/c-with-assembler/build/install/mainExecutable").exec().out == "5 + 7 = 12\n"
+ }
+
+ def "c"() {
+ given:
+ sample c
+
+ when:
+ run "installMainExecutable"
+
+ then:
+ executedAndNotSkipped ":compileHelloSharedLibraryLibC", ":linkHelloSharedLibrary", ":helloSharedLibrary",
+ ":compileMainExecutableExeC", ":linkMainExecutable", ":mainExecutable"
+
+ and:
+ installation("cpp/c/build/install/mainExecutable").exec().out == "Hello world!"
+ }
+
+ def "cpp"() {
+ given:
+ sample cpp
+
+ when:
+ run "installMainExecutable"
+
+ then:
+ executedAndNotSkipped ":compileHelloSharedLibraryLibCpp", ":linkHelloSharedLibrary", ":helloSharedLibrary",
+ ":compileMainExecutableExeCpp", ":linkMainExecutable", ":mainExecutable"
+
+ and:
+ installation("cpp/cpp/build/install/mainExecutable").exec().out == "Hello world!\n"
+ }
+
+ def "exe"() {
+ given:
+ sample cppExe
+
+ when:
+ run "installMain"
+
+ then:
+ executedAndNotSkipped ":compileMainExecutableMainCpp", ":linkMainExecutable", ":stripMainExecutable", ":mainExecutable"
+
+ and:
+ executable("cpp/cpp-exe/build/binaries/mainExecutable/sampleExe").exec().out == "Hello, World!\n"
+ installation("cpp/cpp-exe/build/install/mainExecutable").exec().out == "Hello, World!\n"
+ }
+
+ def "lib"() {
+ given:
+ sample cppLib
+
+ when:
+ run "mainSharedLibrary"
+
+ then:
+ executedAndNotSkipped ":compileMainSharedLibraryMainCpp", ":linkMainSharedLibrary", ":mainSharedLibrary"
+
+ and:
+ sharedLibrary("cpp/cpp-lib/build/binaries/mainSharedLibrary/sampleLib").assertExists()
+
+ when:
+ sample cppLib
+ run "mainStaticLibrary"
+
+ then:
+ executedAndNotSkipped ":compileMainStaticLibraryMainCpp", ":createMainStaticLibrary", ":mainStaticLibrary"
+
+ and:
+ staticLibrary("cpp/cpp-lib/build/binaries/mainStaticLibrary/sampleLib").assertExists()
+ }
+
+ def "variants"() {
+ when:
+ sample variants
+ run "installEnglishMainExecutable"
+
+ then:
+ executedAndNotSkipped ":compileEnglishHelloSharedLibraryLibCpp", ":linkEnglishHelloSharedLibrary", ":englishHelloSharedLibrary"
+ executedAndNotSkipped ":compileEnglishMainExecutableExeCpp", ":linkEnglishMainExecutable", ":englishMainExecutable"
+
+ and:
+ executable("cpp/variants/build/binaries/mainExecutable/english/main").assertExists()
+ sharedLibrary("cpp/variants/build/binaries/helloSharedLibrary/english/hello").assertExists()
+
+ and:
+ installation("cpp/variants/build/install/mainExecutable/english").exec().out == "Hello world!\n"
+
+ when:
+ sample variants
+ run "installFrenchMainExecutable"
+
+ then:
+ executedAndNotSkipped ":compileFrenchHelloSharedLibraryLibCpp", ":linkFrenchHelloSharedLibrary", ":frenchHelloSharedLibrary"
+ executedAndNotSkipped ":compileFrenchMainExecutableExeCpp", ":linkFrenchMainExecutable", ":frenchMainExecutable"
+
+ and:
+ executable("cpp/variants/build/binaries/mainExecutable/french/main").assertExists()
+ sharedLibrary("cpp/variants/build/binaries/helloSharedLibrary/french/hello").assertExists()
+
+ and:
+ installation("cpp/variants/build/install/mainExecutable/french").exec().out == "Bonjour monde!\n"
+ }
+
+ def multiProject() {
+ given:
+ sample multiProject
+
+ when:
+ run "installMainExecutable"
+
+ then:
+ ":exe:mainExecutable" in executedTasks
+
+ and:
+ sharedLibrary("cpp/multi-project/lib/build/binaries/mainSharedLibrary/lib").assertExists()
+ executable("cpp/multi-project/exe/build/binaries/mainExecutable/exe").assertExists()
+ installation("cpp/multi-project/exe/build/install/mainExecutable").exec().out == "Hello, World!\n"
+ }
+
+ // Does not work on windows, due to GRADLE-2118
+ @Requires(TestPrecondition.NOT_WINDOWS)
+ def "dependencies"() {
+ when:
+ sample dependencies
+ run ":lib:uploadArchives"
+
+ then:
+ sharedLibrary("cpp/dependencies/lib/build/binaries/mainSharedLibrary/lib").assertExists()
+ file("cpp/dependencies/lib/build/repo/some-org/some-lib/1.0/some-lib-1.0-so.so").isFile()
+
+ when:
+ sample dependencies
+ run ":exe:uploadArchives"
+
+ then:
+ ":exe:mainCppExtractHeaders" in nonSkippedTasks
+ ":exe:mainExecutable" in nonSkippedTasks
+
+ and:
+ executable("cpp/dependencies/exe/build/binaries/mainExecutable/exe").assertExists()
+ file("cpp/dependencies/exe/build/repo/dependencies/exe/1.0/exe-1.0.exe").exists()
+ }
+
+}
\ No newline at end of file
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/MixedLanguageIntegrationTest.groovy b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/MixedLanguageIntegrationTest.groovy
new file mode 100755
index 0000000..d3360cb
--- /dev/null
+++ b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/MixedLanguageIntegrationTest.groovy
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp
+
+import org.gradle.nativecode.language.cpp.fixtures.app.HelloWorldApp
+import org.gradle.nativecode.language.cpp.fixtures.app.MixedLanguageHelloWorldApp
+import org.gradle.nativecode.language.cpp.fixtures.app.SourceFile
+
+class MixedLanguageIntegrationTest extends AbstractLanguageIntegrationTest {
+
+ HelloWorldApp helloWorldApp = new MixedLanguageHelloWorldApp(toolChain)
+
+ def "can have all source files co-located in a common directory"() {
+ given:
+ buildFile << """
+ apply plugin: "cpp"
+ sources {
+ main {
+ cpp {
+ source {
+ srcDirs "src/main/flat"
+ include "**/*.cpp"
+ }
+ }
+ c {
+ source {
+ srcDirs "src/main/flat"
+ include "**/*.c"
+ }
+ exportedHeaders {
+ srcDirs "src/main/flat"
+ }
+ }
+ asm {
+ source {
+ srcDirs "src/main/flat"
+ include "**/*.s"
+ }
+ }
+ }
+ }
+ executables {
+ main {
+ source sources.main
+ }
+ }
+ binaries.all {
+ $helloWorldApp.customArgs
+ }
+ """
+
+ and:
+ helloWorldApp.sourceFiles.each { SourceFile sourceFile ->
+ file("src/main/flat/${sourceFile.name}") << sourceFile.content
+ }
+
+ when:
+ run "mainExecutable"
+
+ then:
+ def mainExecutable = executable("build/binaries/mainExecutable/main")
+ mainExecutable.assertExists()
+ mainExecutable.exec().out == helloWorldApp.englishOutput
+ }
+
+}
+
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/MultipleToolChainIntegrationTest.groovy b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/MultipleToolChainIntegrationTest.groovy
new file mode 100755
index 0000000..8833248
--- /dev/null
+++ b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/MultipleToolChainIntegrationTest.groovy
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp
+
+import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+import org.gradle.internal.os.OperatingSystem
+import org.gradle.nativecode.language.cpp.fixtures.AvailableToolChains
+import org.gradle.nativecode.language.cpp.fixtures.app.CppHelloWorldApp
+import org.gradle.util.Requires
+import org.gradle.util.TestPrecondition
+
+class MultipleToolChainIntegrationTest extends AbstractIntegrationSpec {
+ def helloWorld = new CppHelloWorldApp()
+
+ @Requires(TestPrecondition.CAN_INSTALL_EXECUTABLE)
+ def "can build with all available tool chains"() {
+ List<AvailableToolChains.InstalledToolChain> installedToolChains = []
+ for (AvailableToolChains.ToolChainCandidate toolChainCandidate : AvailableToolChains.getToolChains()) {
+ if (toolChainCandidate.isAvailable()) {
+ installedToolChains << toolChainCandidate
+ }
+ }
+
+ def toolChainConfig = installedToolChains.collect({it.buildScriptConfig}).join("\n")
+
+ when:
+ buildFile << """
+ apply plugin: "cpp"
+
+ toolChains {
+${toolChainConfig}
+
+ unavailable(Gcc) {
+ linker.exe = "does_not_exist"
+ }
+ }
+
+ sources {
+ main {}
+ }
+ executables {
+ main {
+ source sources.main
+ }
+ }
+"""
+
+ helloWorld.writeSources(file("src/main"))
+
+ then:
+ def tasks = installedToolChains.collect { "install${it.id.capitalize()}MainExecutable" }
+ succeeds tasks as String[]
+
+ and:
+ installedToolChains.each { toolChain ->
+ checkInstall("build/install/mainExecutable/${toolChain.id}/main", toolChain.runtimeEnv)
+ }
+ }
+
+ @Requires(TestPrecondition.CAN_INSTALL_EXECUTABLE)
+ def "includes tool chain in task names and binary paths with two defined and one available"() {
+ AvailableToolChains.InstalledToolChain toolChain = AvailableToolChains.getToolChains().get(0) as AvailableToolChains.InstalledToolChain
+
+ given:
+ buildFile << """
+ apply plugin: "cpp"
+
+ toolChains {
+${toolChain.buildScriptConfig}
+
+ unavailable(Gcc) {
+ linker.exe = "does_not_exist"
+ }
+ }
+
+ sources {
+ main {}
+ }
+ executables {
+ main {
+ source sources.main
+ }
+ }
+"""
+
+ helloWorld.writeSources(file("src/main"))
+
+ when:
+ succeeds "install${toolChain.id.capitalize()}MainExecutable"
+
+ then:
+ checkInstall("build/install/mainExecutable/${toolChain.id}/main", toolChain.runtimeEnv)
+ }
+
+ def checkInstall(String path, List runtimeEnv) {
+ def executable = file(OperatingSystem.current().getScriptName(path))
+ executable.assertExists()
+ assert executable.execute([], runtimeEnv).out == helloWorld.englishOutput
+ return true
+ }
+}
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/NativeBinariesPluginIntegrationTest.groovy b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/NativeBinariesPluginIntegrationTest.groovy
new file mode 100755
index 0000000..907a68b
--- /dev/null
+++ b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/NativeBinariesPluginIntegrationTest.groovy
@@ -0,0 +1,222 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp
+
+import org.gradle.nativecode.language.cpp.fixtures.AbstractInstalledToolChainIntegrationSpec
+import org.gradle.nativecode.language.cpp.fixtures.app.CppCallingCHelloWorldApp
+
+class NativeBinariesPluginIntegrationTest extends AbstractInstalledToolChainIntegrationSpec {
+ def helloWorldApp = new CppCallingCHelloWorldApp()
+
+ def "setup"() {
+ settingsFile << "rootProject.name = 'test'"
+ }
+
+ def "skips building executable binary with no source"() {
+ given:
+ buildFile << """
+ apply plugin: "cpp"
+ executables {
+ main {}
+ }
+ """
+
+ when:
+ succeeds "mainExecutable"
+
+ then:
+ executable("build/binaries/mainExecutable/main").assertDoesNotExist()
+ }
+
+ def "assemble executable from component with multiple language source sets"() {
+ given:
+ useMixedSources()
+
+ when:
+ buildFile << """
+ apply plugin: "cpp"
+ sources {
+ main {}
+ }
+ executables {
+ main {
+ source sources.main.cpp
+ source sources.main.c
+ }
+ }
+ """
+
+ then:
+ succeeds "mainExecutable"
+
+ and:
+ executable("build/binaries/mainExecutable/main").exec().out == helloWorldApp.englishOutput
+ }
+
+ def "assemble executable binary directly from language source sets"() {
+ given:
+ useMixedSources()
+
+ when:
+ buildFile << """
+ apply plugin: "cpp"
+ sources {
+ main {}
+ }
+ executables {
+ main {}
+ }
+ binaries.all {
+ source sources.main.cpp
+ source sources.main.c
+ }
+ """
+
+ then:
+ succeeds "mainExecutable"
+
+ and:
+ executable("build/binaries/mainExecutable/main").exec().out == helloWorldApp.englishOutput
+ }
+
+ def "assemble executable binary directly from functional source set"() {
+ given:
+ useMixedSources()
+
+ when:
+ buildFile << """
+ apply plugin: "cpp"
+ sources {
+ main {}
+ }
+ executables {
+ main {}
+ }
+ binaries.all {
+ source sources.main
+ }
+ """
+
+ then:
+ succeeds "mainExecutable"
+
+ and:
+ executable("build/binaries/mainExecutable/main").exec().out == helloWorldApp.englishOutput
+ }
+
+ def "ignores java sources added to binary"() {
+ given:
+ useMixedSources()
+ file("src/main/java/HelloWorld.java") << """
+ This would not compile
+"""
+
+ when:
+ buildFile << """
+ apply plugin: "cpp"
+ apply plugin: "java"
+ sources {
+ main {}
+ }
+ executables {
+ main {
+ source sources.main.cpp
+ source sources.main.c
+ source sources.main.java
+ }
+ }
+ """
+
+ then:
+ succeeds "mainExecutable"
+
+ and:
+ executable("build/binaries/mainExecutable/main").exec().out == helloWorldApp.englishOutput
+ }
+
+ private def useMixedSources() {
+ helloWorldApp.writeSources(file("src/main"))
+ }
+
+ def "build fails when link executable fails"() {
+ given:
+ buildFile << """
+ apply plugin: "cpp-exe"
+ """
+
+ and:
+ file("src", "main", "cpp", "helloworld.cpp") << """
+ int thing() { return 0; }
+ """
+
+ expect:
+ fails "mainExecutable"
+ failure.assertHasDescription("Execution failed for task ':linkMainExecutable'.");
+ failure.assertHasCause("Linker failed; see the error output for details.")
+ }
+
+ def "build fails when link library fails"() {
+ given:
+ buildFile << """
+ apply plugin: "cpp-lib"
+ binaries.all {
+ linkerArgs "--not-an-option"
+ }
+ """
+
+ and:
+ file("src/main/cpp/hello.cpp") << """
+ #include "test.h"
+ void hello() {
+ test();
+ }
+"""
+ // Header file available, but no implementation to link
+ file("src/main/cpp/test.h") << """
+ int test();
+"""
+
+ when:
+ fails "mainSharedLibrary"
+
+ then:
+ failure.assertHasDescription("Execution failed for task ':linkMainSharedLibrary'.");
+ failure.assertHasCause("Linker failed; see the error output for details.")
+ }
+
+ def "build fails when create static library fails"() {
+ given:
+ buildFile << """
+ apply plugin: "cpp-lib"
+ binaries.withType(StaticLibraryBinary) {
+ staticLibArgs "not_a_file"
+ }
+ """
+
+ and:
+ file("src/main/cpp/hello.cpp") << """
+ void hello() {
+ }
+"""
+
+ when:
+ fails "mainStaticLibrary"
+
+ then:
+ failure.assertHasDescription("Execution failed for task ':createMainStaticLibrary'.");
+ failure.assertHasCause("Static library archiver failed; see the error output for details.")
+ }
+}
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/AbstractInstalledToolChainIntegrationSpec.groovy b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/AbstractInstalledToolChainIntegrationSpec.groovy
new file mode 100755
index 0000000..7f181ce
--- /dev/null
+++ b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/AbstractInstalledToolChainIntegrationSpec.groovy
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp.fixtures
+
+import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+import org.gradle.test.fixtures.file.TestFile
+import org.junit.runner.RunWith
+/**
+ * Runs a test separately for each installed tool chain.
+ */
+ at RunWith(SingleToolChainTestRunner.class)
+abstract class AbstractInstalledToolChainIntegrationSpec extends AbstractIntegrationSpec {
+ static AvailableToolChains.InstalledToolChain toolChain
+
+ def NativeInstallationFixture installation(Object installDir) {
+ return new NativeInstallationFixture(file(installDir))
+ }
+
+ def ExecutableFixture executable(Object path) {
+ return toolChain.executable(file(path))
+ }
+
+ def TestFile objectFile(Object path) {
+ if (toolChain.visualCpp) {
+ return file("${path}.obj")
+ }
+ return file("${path}.o")
+ }
+
+ def SharedLibraryFixture sharedLibrary(Object path) {
+ return toolChain.sharedLibrary(file(path))
+ }
+
+ def NativeBinaryFixture staticLibrary(Object path) {
+ return toolChain.staticLibrary(file(path))
+ }
+}
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/AvailableToolChains.java b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/AvailableToolChains.java
new file mode 100755
index 0000000..7bbe71b
--- /dev/null
+++ b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/AvailableToolChains.java
@@ -0,0 +1,312 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp.fixtures;
+
+import com.google.common.base.Joiner;
+import org.gradle.internal.nativeplatform.ProcessEnvironment;
+import org.gradle.internal.nativeplatform.services.NativeServices;
+import org.gradle.internal.os.OperatingSystem;
+import org.gradle.nativecode.toolchain.Gcc;
+import org.gradle.nativecode.toolchain.VisualCpp;
+import org.gradle.nativecode.toolchain.internal.gpp.version.GppVersionDeterminer;
+import org.gradle.nativecode.toolchain.internal.msvcpp.VisualStudioInstall;
+import org.gradle.test.fixtures.file.TestFile;
+import org.gradle.util.TextUtil;
+
+import java.io.File;
+import java.util.*;
+
+public class AvailableToolChains {
+ /**
+ * @return A list of all tool chains for this platform, with the default tool chain listed first.
+ */
+ public static List<ToolChainCandidate> getToolChains() {
+ List<ToolChainCandidate> compilers = new ArrayList<ToolChainCandidate>();
+ if (OperatingSystem.current().isWindows()) {
+ compilers.add(findVisualCpp());
+ compilers.add(findMinGW());
+ compilers.add(findCygwin());
+ } else {
+ // GCC4.x must be on the path
+ compilers.add(findGpp("4", null));
+ // CI servers have GCC4.4 installed additionally
+ compilers.add(findGpp("4.4", "/opt/gcc/4.4/bin/g++"));
+
+ // It's easy to get GCC4.8 installed on OSX, and symlink to this location
+ // Not available on CI servers, so only add it if it's available
+ ToolChainCandidate gpp48 = findGpp("4.8", "/opt/gcc/4.8/bin/g++");
+ if (gpp48.isAvailable()) {
+ compilers.add(gpp48);
+ }
+
+ // TODO:DAZ Make a GCC3 install available for testing
+ }
+ return compilers;
+ }
+
+ static private ToolChainCandidate findVisualCpp() {
+ // Search first in path, then in the standard installation locations
+ File compilerExe = OperatingSystem.current().findInPath("cl.exe");
+ if (compilerExe != null) {
+ return new InstalledVisualCpp("visual c++");
+ }
+
+ VisualStudioInstall install = new VisualStudioInstall(new File("C:/Program Files (x86)/Microsoft Visual Studio 10.0"));
+ if (!install.isInstalled()) {
+ install = new VisualStudioInstall(new File("C:/Program Files/Microsoft Visual Studio 10.0"));
+ }
+
+ if (install.isInstalled()) {
+ return new InstalledVisualCpp("visual c++").withInstall(install);
+ }
+
+ return new UnavailableToolChain("visual c++");
+ }
+
+ static private ToolChainCandidate findMinGW() {
+ // Search in the standard installation locations
+ File compilerExe = new File("C:/MinGW/bin/g++.exe");
+ if (compilerExe.isFile()) {
+ return new InstalledGcc("mingw").inPath(compilerExe.getParentFile());
+ }
+
+ return new UnavailableToolChain("mingw");
+ }
+
+ static private ToolChainCandidate findCygwin() {
+ // Search in the standard installation locations
+ File compilerExe = new File("C:/cygwin/bin/g++.exe");
+ if (compilerExe.isFile()) {
+ return new InstalledGcc("g++ cygwin").inPath(compilerExe.getParentFile());
+ }
+
+ return new UnavailableToolChain("g++ cygwin");
+ }
+
+ static private ToolChainCandidate findGpp(String versionPrefix, String hardcodedFallback) {
+ String name = String.format("g++ %s", versionPrefix);
+ GppVersionDeterminer versionDeterminer = new GppVersionDeterminer();
+
+ List<File> gppCandidates = OperatingSystem.current().findAllInPath("g++");
+ for (int i = 0; i < gppCandidates.size(); i++) {
+ File candidate = gppCandidates.get(i);
+ if (versionDeterminer.transform(candidate).startsWith(versionPrefix)) {
+ InstalledGcc gcc = new InstalledGcc(name);
+ if (i > 0) {
+ // Not the first g++ in the path, needs the path variable updated
+ gcc.inPath(candidate.getParentFile());
+ }
+ return gcc;
+ }
+ }
+
+ if (hardcodedFallback != null) {
+ File fallback = new File(hardcodedFallback);
+ if (fallback.isFile()) {
+ return new InstalledGcc(name).inPath(fallback.getParentFile());
+ }
+ }
+
+ return new UnavailableToolChain(name);
+ }
+
+ public static abstract class ToolChainCandidate {
+ @Override
+ public String toString() {
+ return getDisplayName();
+ }
+
+ public abstract String getDisplayName();
+
+ public abstract boolean isAvailable();
+
+ public abstract void initialiseEnvironment();
+
+ public abstract void resetEnvironment();
+
+ public ExecutableFixture executable(Object path) {
+ return new ExecutableFixture(new TestFile(OperatingSystem.current().getExecutableName(path.toString())), this);
+ }
+
+ public SharedLibraryFixture sharedLibrary(Object path) {
+ return new SharedLibraryFixture(new TestFile(OperatingSystem.current().getSharedLibraryName(path.toString())), this);
+ }
+
+ public NativeBinaryFixture staticLibrary(Object path) {
+ return new NativeBinaryFixture(new TestFile(OperatingSystem.current().getStaticLibraryName(path.toString())), this);
+ }
+ }
+
+ public abstract static class InstalledToolChain extends ToolChainCandidate {
+ private static final ProcessEnvironment PROCESS_ENVIRONMENT = NativeServices.getInstance().get(ProcessEnvironment.class);
+ protected final List<File> pathEntries = new ArrayList<File>();
+ protected final Map<String, String> environmentVars = new HashMap<String, String>();
+ private final String name;
+ private final String pathVarName;
+ private String originalPath;
+
+ public InstalledToolChain(String name) {
+ this.name = name;
+ this.pathVarName = OperatingSystem.current().getPathVar();
+ }
+
+ InstalledToolChain inPath(File... pathEntries) {
+ Collections.addAll(this.pathEntries, pathEntries);
+ return this;
+ }
+
+ @Override
+ public String getDisplayName() {
+ return name;
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return true;
+ }
+
+ public void initialiseEnvironment() {
+ String compilerPath = Joiner.on(File.pathSeparator).join(pathEntries);
+
+ if (compilerPath.length() > 0) {
+ originalPath = System.getenv(pathVarName);
+ String path = compilerPath + File.pathSeparator + originalPath;
+ System.out.println(String.format("Using path %s", path));
+ PROCESS_ENVIRONMENT.setEnvironmentVariable(pathVarName, path);
+ }
+
+ for (Map.Entry<String, String> entry : environmentVars.entrySet()) {
+ System.out.println(String.format("Using environment var %s -> %s", entry.getKey(), entry.getValue()));
+ PROCESS_ENVIRONMENT.setEnvironmentVariable(entry.getKey(), entry.getValue());
+ }
+ }
+
+ public void resetEnvironment() {
+ if (originalPath != null) {
+ PROCESS_ENVIRONMENT.setEnvironmentVariable(pathVarName, originalPath);
+ }
+ }
+
+ public abstract String getBuildScriptConfig();
+
+ public abstract String getImplementationClass();
+
+ public boolean isVisualCpp() {
+ return false;
+ }
+
+ public List<File> getPathEntries() {
+ return pathEntries;
+ }
+
+ /**
+ * The environment required to execute a binary created by this toolchain.
+ */
+ // TODO:DAZ This isn't quite right (only required for MinGW and cygwin, and preferably not even those)
+ public List<String> getRuntimeEnv() {
+ if (pathEntries.isEmpty()) {
+ return Collections.emptyList();
+ }
+
+ String path = Joiner.on(File.pathSeparator).join(pathEntries) + File.pathSeparator + System.getenv(pathVarName);
+ return Collections.singletonList(pathVarName + "=" + path);
+ }
+
+ public String getId() {
+ return name.replaceAll("\\W", "");
+ }
+ }
+
+ public static class InstalledGcc extends InstalledToolChain {
+ public InstalledGcc(String name) {
+ super(name);
+ }
+
+ @Override
+ public String getBuildScriptConfig() {
+ String config = String.format("%s(%s)\n", getId(), getImplementationClass());
+ for (File pathEntry : getPathEntries()) {
+ config += String.format("%s.path file('%s')", getId(), TextUtil.normaliseFileSeparators(pathEntry.getAbsolutePath()));
+ }
+ return config;
+ }
+
+ public String getImplementationClass() {
+ return Gcc.class.getSimpleName();
+ }
+ }
+
+ public static class InstalledVisualCpp extends InstalledToolChain {
+ private File installDir;
+
+ public InstalledVisualCpp(String name) {
+ super(name);
+ }
+
+ public InstalledVisualCpp withInstall(VisualStudioInstall install) {
+ pathEntries.addAll(install.getPathEntries());
+ environmentVars.putAll(install.getEnvironment());
+ installDir = install.getInstallDir();
+ return this;
+ }
+
+ @Override
+ public String getBuildScriptConfig() {
+ String config = String.format("%s(%s)\n", getId(), getImplementationClass());
+ if (installDir != null) {
+ config += String.format("%s.installDir = file('%s')", getId(), TextUtil.normaliseFileSeparators(installDir.getAbsolutePath()));
+ }
+ return config;
+ }
+
+ public String getImplementationClass() {
+ return VisualCpp.class.getSimpleName();
+ }
+
+ public boolean isVisualCpp() {
+ return true;
+ }
+ }
+
+ public static class UnavailableToolChain extends ToolChainCandidate {
+ private final String name;
+
+ public UnavailableToolChain(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String getDisplayName() {
+ return name;
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return false;
+ }
+
+ @Override
+ public void initialiseEnvironment() {
+ throw new UnsupportedOperationException("Toolchain is not available");
+ }
+
+ @Override
+ public void resetEnvironment() {
+ throw new UnsupportedOperationException("Toolchain is not available");
+ }
+ }
+}
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/ExecutableFixture.groovy b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/ExecutableFixture.groovy
new file mode 100644
index 0000000..039214a
--- /dev/null
+++ b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/ExecutableFixture.groovy
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp.fixtures
+import org.gradle.nativecode.language.cpp.fixtures.AvailableToolChains.ToolChainCandidate
+import org.gradle.test.fixtures.file.ExecOutput
+import org.gradle.test.fixtures.file.TestFile
+
+class ExecutableFixture extends NativeBinaryFixture {
+ ExecutableFixture(TestFile file, ToolChainCandidate toolChain) {
+ super(file, toolChain)
+ }
+
+ public ExecOutput exec(Object... args) {
+ assertExists()
+ return file.exec(args)
+ }
+}
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/NativeBinaryFixture.groovy b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/NativeBinaryFixture.groovy
new file mode 100644
index 0000000..5238f7b
--- /dev/null
+++ b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/NativeBinaryFixture.groovy
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp.fixtures
+
+import org.gradle.test.fixtures.file.TestFile
+
+class NativeBinaryFixture {
+ protected final TestFile file
+ protected final AvailableToolChains.ToolChainCandidate toolChain
+
+ NativeBinaryFixture(TestFile file, AvailableToolChains.ToolChainCandidate toolChain) {
+ this.file = file
+ this.toolChain = toolChain
+ }
+
+ URI toURI() {
+ file.toURI()
+ }
+
+ TestFile.Snapshot snapshot() {
+ file.snapshot()
+ }
+
+ void assertHasChangedSince(TestFile.Snapshot snapshot) {
+ file.assertHasChangedSince(snapshot)
+ }
+
+ void assertExists() {
+ file.assertIsFile()
+ }
+
+ void assertDoesNotExist() {
+ file.assertDoesNotExist()
+ }
+
+ // Does nothing when tool chain does not generate a separate debug file
+ void assertDebugFileExists() {
+ if (toolChain.visualCpp) {
+ getDebugFile().assertIsFile()
+ }
+ }
+
+ // Does nothing when tool chain does not generate a separate debug file
+ void assertDebugFileDoesNotExist() {
+ if (toolChain.visualCpp) {
+ getDebugFile().assertDoesNotExist()
+ }
+ }
+
+ private TestFile getDebugFile() {
+ return file.withExtension("pdb")
+ }
+}
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/NativeInstallationFixture.groovy b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/NativeInstallationFixture.groovy
new file mode 100644
index 0000000..97adecc
--- /dev/null
+++ b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/NativeInstallationFixture.groovy
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp.fixtures
+
+import org.gradle.internal.os.OperatingSystem
+import org.gradle.test.fixtures.file.ExecOutput
+import org.gradle.test.fixtures.file.TestFile
+
+class NativeInstallationFixture {
+ private final TestFile installDir
+ private final OperatingSystem os = OperatingSystem.current()
+
+ NativeInstallationFixture(TestFile installDir) {
+ this.installDir = installDir
+ }
+
+ ExecOutput exec(Object... args) {
+ assertInstalled()
+ return scriptFile().exec(args)
+ }
+
+ private TestFile scriptFile() {
+ if (os.windows) {
+ return installDir.listFiles().find { it.file && it.name.endsWith(".bat") }
+ } else {
+ return installDir.listFiles().find { it.file }
+ }
+ }
+
+ NativeInstallationFixture assertInstalled() {
+ installDir.assertIsDir()
+ final script = scriptFile()
+ assert script
+
+ def libDir = installDir.file("lib")
+ libDir.assertIsDir()
+ libDir.file(os.getExecutableName(script.name)).assertIsFile()
+ this
+ }
+
+ NativeInstallationFixture assertIncludesLibraries(String... names) {
+ def expected = names.collect { os.getSharedLibraryName(it) } as Set
+ assert libraryFiles.collect { it.name } as Set == expected as Set
+ this
+ }
+
+ private ArrayList<TestFile> getLibraryFiles() {
+ installDir.assertIsDir()
+ def libDir = installDir.file("lib")
+ libDir.assertIsDir()
+ def libFiles
+ if (os.windows) {
+ libFiles = libDir.listFiles().findAll { it.file && !it.name.endsWith(".exe") }
+ } else {
+ libFiles = libDir.listFiles().findAll { it.file && it.name.contains(".") }
+ }
+ libFiles
+ }
+}
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/SharedLibraryFixture.groovy b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/SharedLibraryFixture.groovy
new file mode 100644
index 0000000..d197bdc
--- /dev/null
+++ b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/SharedLibraryFixture.groovy
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp.fixtures
+
+import org.gradle.test.fixtures.file.TestFile
+
+class SharedLibraryFixture extends NativeBinaryFixture {
+ SharedLibraryFixture(TestFile file, AvailableToolChains.ToolChainCandidate toolChain) {
+ super(file, toolChain)
+ }
+
+ @Override
+ void assertExists() {
+ super.assertExists()
+ if (toolChain.visualCpp) {
+ file.withExtension("lib").assertIsFile()
+ file.withExtension("exp").assertIsFile()
+ }
+ }
+
+ @Override
+ void assertDoesNotExist() {
+ super.assertDoesNotExist()
+ if (toolChain.visualCpp) {
+ file.withExtension("lib").assertDoesNotExist()
+ file.withExtension("exp").assertDoesNotExist()
+ }
+ }
+}
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/SingleToolChainTestRunner.java b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/SingleToolChainTestRunner.java
new file mode 100755
index 0000000..e7deca2
--- /dev/null
+++ b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/SingleToolChainTestRunner.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp.fixtures;
+
+import org.gradle.integtests.fixtures.AbstractMultiTestRunner;
+
+import java.util.List;
+
+public class SingleToolChainTestRunner extends AbstractMultiTestRunner {
+ private static final String TOOLCHAINS_SYSPROP_NAME = "org.gradle.integtest.cpp.toolChains";
+
+ public SingleToolChainTestRunner(Class<? extends AbstractInstalledToolChainIntegrationSpec> target) {
+ super(target);
+ }
+
+ @Override
+ protected void createExecutions() {
+ boolean enableAllToolChains = "all".equals(System.getProperty(TOOLCHAINS_SYSPROP_NAME, "default"));
+ List<AvailableToolChains.ToolChainCandidate> toolChains = AvailableToolChains.getToolChains();
+ for (int i = 0; i < toolChains.size(); i++) {
+ boolean enabled = enableAllToolChains || i == 0;
+ add(new ToolChainExecution(toolChains.get(i), enabled));
+ }
+ }
+
+ private static class ToolChainExecution extends Execution {
+ private final AvailableToolChains.ToolChainCandidate toolChain;
+ private final boolean enabled;
+
+ public ToolChainExecution(AvailableToolChains.ToolChainCandidate toolChain, boolean enabled) {
+ this.toolChain = toolChain;
+ this.enabled = enabled;
+ }
+
+ @Override
+ protected String getDisplayName() {
+ return toolChain.getDisplayName();
+ }
+
+ @Override
+ protected boolean isTestEnabled(TestDetails testDetails) {
+ return enabled;
+ }
+
+ @Override
+ protected void assertCanExecute() {
+ assert toolChain.isAvailable() : String.format("Tool chain %s not available", toolChain.getDisplayName());
+ }
+
+ @Override
+ protected void before() {
+ System.out.println(String.format("Using tool chain %s", toolChain.getDisplayName()));
+ toolChain.initialiseEnvironment();
+ AbstractInstalledToolChainIntegrationSpec.setToolChain((AvailableToolChains.InstalledToolChain) toolChain);
+ }
+
+ @Override
+ protected void after() {
+ toolChain.resetEnvironment();
+ }
+ }
+}
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/app/CCallingCppHelloWorldApp.groovy b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/app/CCallingCppHelloWorldApp.groovy
new file mode 100644
index 0000000..0a01b3f
--- /dev/null
+++ b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/app/CCallingCppHelloWorldApp.groovy
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp.fixtures.app;
+
+public class CCallingCppHelloWorldApp extends HelloWorldApp {
+ @Override
+ SourceFile getMainSource() {
+ sourceFile("c", "main.c", """
+ #include <stdio.h>
+ #include "hello.h"
+
+ int main () {
+ sayHello();
+ printf("%d", sum(5, 7));
+ return 0;
+ }
+ """)
+ }
+
+ @Override
+ SourceFile getLibraryHeader() {
+ sourceFile("headers", "hello.h", """
+ #ifdef _WIN32
+ #define DLL_FUNC __declspec(dllexport)
+ #else
+ #define DLL_FUNC
+ #endif
+
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+
+ void DLL_FUNC sayHello();
+ int DLL_FUNC sum(int a, int b);
+
+ #ifdef __cplusplus
+ }
+ #endif
+ """)
+ }
+
+
+ List<SourceFile> librarySources = [
+ sourceFile("cpp", "hello.cpp", """
+ #include <iostream>
+ #include "hello.h"
+
+ void DLL_FUNC sayHello() {
+ #ifdef FRENCH
+ std::cout << "${HELLO_WORLD_FRENCH}" << std::endl;
+ #else
+ std::cout << "${HELLO_WORLD}" << std::endl;
+ #endif
+ }
+
+ int DLL_FUNC sum(int a, int b) {
+ return a + b;
+ }
+""")
+ ]
+}
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/app/CHelloWorldApp.groovy b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/app/CHelloWorldApp.groovy
new file mode 100644
index 0000000..3f898c3
--- /dev/null
+++ b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/app/CHelloWorldApp.groovy
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp.fixtures.app
+
+class CHelloWorldApp extends IncrementalHelloWorldApp {
+
+ @Override
+ SourceFile getMainSource() {
+ sourceFile("c", "main.c", """
+ // Simple hello world app
+ #include <stdio.h>
+ #include "hello.h"
+
+ int main () {
+ sayHello();
+ printf("%d", sum(5, 7));
+ return 0;
+ }
+ """);
+ }
+
+ @Override
+ SourceFile getLibraryHeader() {
+ sourceFile("headers", "hello.h", """
+ #ifdef _WIN32
+ #define DLL_FUNC __declspec(dllexport)
+ #else
+ #define DLL_FUNC
+ #endif
+
+ void DLL_FUNC sayHello();
+ int DLL_FUNC sum(int a, int b);
+ """);
+ }
+
+ List<SourceFile> librarySources = [
+ sourceFile("c", "hello.c", """
+ #include <stdio.h>
+ #include "hello.h"
+
+ #ifdef FRENCH
+ char* greeting() {
+ return "${HELLO_WORLD_FRENCH}";
+ }
+ #endif
+ void DLL_FUNC sayHello() {
+ #ifdef FRENCH
+ printf("%s\\n", greeting());
+ #else
+ printf("${HELLO_WORLD}\\n");
+ #endif
+ fflush(stdout);
+ }
+ """),
+ sourceFile("c", "sum.c","""
+ #include "hello.h"
+
+ int DLL_FUNC sum(int a, int b) {
+ return a + b;
+ }
+ """)
+ ]
+
+ SourceFile getAlternateMainSource() {
+ sourceFile("c", "main.c", """
+ #include "hello.h"
+
+ int main () {
+ sayHello();
+ printf("goodbye");
+ return 0;
+ }
+ """)
+ }
+
+ String alternateOutput = "$HELLO_WORLD\ngoodbye"
+
+ List<SourceFile> alternateLibrarySources = [
+ sourceFile("c", "hello.c", """
+ #include <stdio.h>
+ #include "hello.h"
+
+ void DLL_FUNC sayHello() {
+ printf("[${HELLO_WORLD} - ${HELLO_WORLD_FRENCH}]\\n");
+ fflush(stdout);
+ }
+ """),
+ sourceFile("c", "sum.c","""
+ #include "hello.h"
+
+ int DLL_FUNC sum(int a, int b) {
+ return a + b;
+ }
+ """)
+ ]
+
+ String alternateLibraryOutput = "[${HELLO_WORLD} - ${HELLO_WORLD_FRENCH}]\n12"
+}
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/app/CppCallingCHelloWorldApp.groovy b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/app/CppCallingCHelloWorldApp.groovy
new file mode 100644
index 0000000..620cc00
--- /dev/null
+++ b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/app/CppCallingCHelloWorldApp.groovy
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp.fixtures.app;
+
+public class CppCallingCHelloWorldApp extends HelloWorldApp {
+ @Override
+ SourceFile getMainSource() {
+ sourceFile("cpp", "main.cpp", """
+ #include <iostream>
+ extern "C" {
+ #include "hello.h"
+ }
+
+ int main () {
+ sayHello();
+ std::cout << sum(5, 7);
+ return 0;
+ }
+ """)
+ }
+
+ @Override
+ SourceFile getLibraryHeader() {
+ sourceFile("headers", "hello.h", """
+ #ifdef _WIN32
+ #define DLL_FUNC __declspec(dllexport)
+ #else
+ #define DLL_FUNC
+ #endif
+
+ void DLL_FUNC sayHello();
+ int DLL_FUNC sum(int a, int b);
+ """);
+ }
+
+ List<SourceFile> librarySources = [
+ sourceFile("c", "hello.c", """
+ #include <stdio.h>
+ #include "hello.h"
+
+ void DLL_FUNC sayHello() {
+ #ifdef FRENCH
+ printf("${HELLO_WORLD_FRENCH}\\n");
+ #else
+ printf("${HELLO_WORLD}\\n");
+ #endif
+ fflush(stdout);
+ }
+
+ int DLL_FUNC sum(int a, int b) {
+ return a + b;
+ }
+ """)
+ ]
+
+}
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/app/CppHelloWorldApp.groovy b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/app/CppHelloWorldApp.groovy
new file mode 100644
index 0000000..3cb212e
--- /dev/null
+++ b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/app/CppHelloWorldApp.groovy
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp.fixtures.app
+
+class CppHelloWorldApp extends IncrementalHelloWorldApp {
+ @Override
+ SourceFile getMainSource() {
+ return sourceFile("cpp", "main.cpp", """
+ // Simple hello world app
+ #include <iostream>
+ #include "hello.h"
+
+ int main () {
+ sayHello();
+ std::cout << sum(5, 7);
+ return 0;
+ }
+ """);
+ }
+
+ SourceFile getAlternateMainSource() {
+ sourceFile("cpp", "main.cpp", """
+ #include <iostream>
+ #include "hello.h"
+
+ int main () {
+ sayHello();
+ return 0;
+ }
+ """)
+ }
+
+ String alternateOutput = "$HELLO_WORLD\n"
+
+ @Override
+ SourceFile getLibraryHeader() {
+ return sourceFile("headers", "hello.h", """
+ #ifdef _WIN32
+ #define DLL_FUNC __declspec(dllexport)
+ #else
+ #define DLL_FUNC
+ #endif
+
+ void DLL_FUNC sayHello();
+ int DLL_FUNC sum(int a, int b);
+ """);
+ }
+
+ List<SourceFile> librarySources = [
+ sourceFile("cpp", "hello.cpp", """
+ #include <iostream>
+ #include "hello.h"
+
+ #ifdef FRENCH
+ const char* greeting() {
+ return "${HELLO_WORLD_FRENCH}";
+ }
+ #endif
+
+ void DLL_FUNC sayHello() {
+ #ifdef FRENCH
+ std::cout << greeting() << std::endl;
+ #else
+ std::cout << "${HELLO_WORLD}" << std::endl;
+ #endif
+ }
+ """),
+ sourceFile("cpp", "sum.cpp", """
+ #include "hello.h"
+
+ int DLL_FUNC sum(int a, int b) {
+ return a + b;
+ }
+ """)
+ ]
+
+ List<SourceFile> alternateLibrarySources = [
+ sourceFile("cpp", "hello.cpp", """
+ #include <iostream>
+ #include "hello.h"
+
+ void DLL_FUNC sayHello() {
+ std::cout << "[${HELLO_WORLD} - ${HELLO_WORLD_FRENCH}]" << std::endl;
+ }
+ """),
+ sourceFile("cpp", "sum.cpp", """
+ #include "hello.h"
+
+ int DLL_FUNC sum(int a, int b) {
+ return a + b;
+ }
+ """)
+ ]
+
+ String alternateLibraryOutput = "[${HELLO_WORLD} - ${HELLO_WORLD_FRENCH}]\n12"
+
+}
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/app/HelloWorldApp.java b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/app/HelloWorldApp.java
new file mode 100644
index 0000000..e089767
--- /dev/null
+++ b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/app/HelloWorldApp.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp.fixtures.app;
+
+import org.gradle.test.fixtures.file.TestFile;
+import org.gradle.util.GUtil;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public abstract class HelloWorldApp {
+ public static final String HELLO_WORLD = "Hello, World!";
+ public static final String HELLO_WORLD_FRENCH = "Bonjour, Monde!";
+
+ public String getEnglishOutput() {
+ return HELLO_WORLD + "\n12";
+ }
+
+ public String getFrenchOutput() {
+ return HELLO_WORLD_FRENCH + "\n12";
+ }
+
+ public String getCustomArgs() {
+ return "";
+ }
+
+ public String getSourceType() {
+ return GUtil.toCamelCase(getMainSource().getPath());
+ }
+
+ public abstract SourceFile getMainSource();
+ public abstract SourceFile getLibraryHeader();
+ public abstract List<SourceFile> getLibrarySources();
+
+ public List<SourceFile> getSourceFiles() {
+ ArrayList<SourceFile> sourceFiles = new ArrayList<SourceFile>();
+ sourceFiles.add(getMainSource());
+ sourceFiles.add(getLibraryHeader());
+ sourceFiles.addAll(getLibrarySources());
+ return sourceFiles;
+ }
+
+ protected SourceFile sourceFile(String path, String name, String content) {
+ return new SourceFile(path, name, content);
+ }
+
+ public void writeSources(TestFile mainSourceDir) {
+ writeSources(mainSourceDir, mainSourceDir);
+ }
+
+ public void writeSources(TestFile mainSourceDir, TestFile librarySourceDir) {
+ getMainSource().writeToDir(mainSourceDir);
+ getLibraryHeader().writeToDir(librarySourceDir);
+ for (SourceFile sourceFile : getLibrarySources()) {
+ sourceFile.writeToDir(librarySourceDir);
+ }
+ }
+
+}
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/app/IncrementalHelloWorldApp.java b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/app/IncrementalHelloWorldApp.java
new file mode 100644
index 0000000..f8f26d8
--- /dev/null
+++ b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/app/IncrementalHelloWorldApp.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp.fixtures.app;
+
+import java.util.List;
+
+public abstract class IncrementalHelloWorldApp extends HelloWorldApp {
+ public abstract SourceFile getAlternateMainSource();
+ public abstract String getAlternateOutput();
+
+ public abstract List<SourceFile> getAlternateLibrarySources();
+ public abstract String getAlternateLibraryOutput();
+}
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/app/MixedLanguageHelloWorldApp.groovy b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/app/MixedLanguageHelloWorldApp.groovy
new file mode 100644
index 0000000..92c0e33
--- /dev/null
+++ b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/app/MixedLanguageHelloWorldApp.groovy
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp.fixtures.app;
+
+import org.gradle.internal.os.OperatingSystem
+import org.gradle.nativecode.language.cpp.fixtures.AvailableToolChains;
+
+public class MixedLanguageHelloWorldApp extends HelloWorldApp {
+ private final AvailableToolChains.InstalledToolChain toolChain
+
+ MixedLanguageHelloWorldApp(AvailableToolChains.InstalledToolChain toolChain) {
+ this.toolChain = toolChain
+ }
+
+ String getCustomArgs() {
+ if (!toolChain.isVisualCpp()) {
+ // 32bit assembly on osx
+ if (OperatingSystem.current().isMacOsX()) {
+ return """
+ compilerArgs "-m32"
+ assemblerArgs "-arch", "i386"
+ linkerArgs "-no_pie", "-arch", "i386"
+ """
+ }
+ // 32bit gcc assembly on windows
+ if (OperatingSystem.current().isWindows()) {
+ return """
+ compilerArgs "-m32"
+ assemblerArgs "-march", "i386"
+ """
+ }
+ }
+ return super.getCustomArgs()
+ }
+
+ SourceFile getMainSource() {
+ return new SourceFile("cpp", "main.cpp", """
+ #include <iostream>
+ extern "C" {
+ #include "hello.h"
+ }
+
+ int main () {
+ sayHello();
+ std::cout << sum(5, 7);
+ return 0;
+ }
+""")
+ }
+
+ SourceFile getLibraryHeader() {
+ return new SourceFile("headers", "hello.h", """
+ #ifdef _WIN32
+ #define DLL_FUNC __declspec(dllexport)
+ #else
+ #define DLL_FUNC
+ #endif
+
+ void DLL_FUNC sayHello();
+ int DLL_FUNC sum(int a, int b);
+""")
+ }
+
+ List<SourceFile> getLibrarySources() {
+ return [
+ new SourceFile("c", "hello.c", """
+ #include <stdio.h>
+ #include "hello.h"
+
+ void DLL_FUNC sayHello() {
+ #ifdef FRENCH
+ printf("${HELLO_WORLD_FRENCH}\\n");
+ #else
+ printf("${HELLO_WORLD}\\n");
+ #endif
+
+ fflush(stdout);
+ }
+
+ int DLL_FUNC sum(int a, int b) {
+ return sumx(a, b);
+ }
+"""),
+ new SourceFile("asm", "sum.s", getAsmSource())
+ ]
+ }
+
+ protected def getAsmSource() {
+ def os = OperatingSystem.current()
+ if (os.isMacOsX()) {
+ return osxAsmSource
+ } else if (os.isWindows()) {
+ if (toolChain.isVisualCpp()) {
+ return windowsMasmSource
+ } else {
+ return i386GnuAsmSource;
+ }
+ } else {
+ return x64GnuAsmSource
+ }
+ }
+
+ private static String osxAsmSource = '''
+.section __TEXT,__text,regular,pure_instructions
+.globl _sumx
+.align 4
+_sumx:
+movl 8(%esp), %eax
+addl 4(%esp), %eax
+ret
+
+.subsections_via_symbols
+'''
+
+ private static String windowsMasmSource = '''
+.386
+.model flat
+
+PUBLIC _sumx
+_TEXT SEGMENT
+_sumx PROC
+mov eax, DWORD PTR 4[esp]
+add eax, DWORD PTR 8[esp]
+ret 0
+_sumx ENDP
+_TEXT ENDS
+END
+'''
+
+ private static String i386GnuAsmSource = '''
+ .text
+ .globl _sumx
+_sumx:
+ movl 8(%esp), %eax
+ addl 4(%esp), %eax
+ ret
+'''
+
+ private static String x64GnuAsmSource = '''
+ .text
+ .p2align 4,,15
+.globl sumx
+ .type sumx, @function
+sumx:
+ leal (%rsi,%rdi), %eax
+ ret
+'''
+}
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/app/SourceFile.java b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/app/SourceFile.java
new file mode 100644
index 0000000..3046c11
--- /dev/null
+++ b/subprojects/cpp/src/integTest/groovy/org/gradle/nativecode/language/cpp/fixtures/app/SourceFile.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp.fixtures.app;
+
+import org.gradle.test.fixtures.file.TestFile;
+
+public class SourceFile {
+ private final String path;
+ private final String name;
+ private final String content;
+
+ public SourceFile(String path, String name, String content) {
+ this.content = content;
+ this.path = path;
+ this.name = name;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getContent() {
+ return content;
+ }
+
+ public TestFile writeToDir(TestFile base) {
+ TestFile file = base.file(path, name);
+ if (file.exists()) {
+ file.write("");
+ }
+ file.write(content);
+ return file;
+ }
+}
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/plugins/cpp/AbstractBinariesIntegrationSpec.groovy b/subprojects/cpp/src/integTest/groovy/org/gradle/plugins/cpp/AbstractBinariesIntegrationSpec.groovy
deleted file mode 100755
index 4df0c8d..0000000
--- a/subprojects/cpp/src/integTest/groovy/org/gradle/plugins/cpp/AbstractBinariesIntegrationSpec.groovy
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp
-
-import org.gradle.integtests.fixtures.AbstractIntegrationSpec
-import org.gradle.internal.os.OperatingSystem
-import org.gradle.test.fixtures.file.TestFile
-import org.junit.runner.RunWith
-
- at RunWith(CppIntegrationTestRunner)
-abstract class AbstractBinariesIntegrationSpec extends AbstractIntegrationSpec {
- def TestFile executable(Object path) {
- return file(OperatingSystem.current().getExecutableName(path.toString()))
- }
-
- def TestFile sharedLibrary(Object path) {
- return file(OperatingSystem.current().getSharedLibraryName(path.toString()))
- }
-}
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/plugins/cpp/AvailableCompilers.java b/subprojects/cpp/src/integTest/groovy/org/gradle/plugins/cpp/AvailableCompilers.java
deleted file mode 100755
index bfe89e7..0000000
--- a/subprojects/cpp/src/integTest/groovy/org/gradle/plugins/cpp/AvailableCompilers.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp;
-
-import org.gradle.internal.os.OperatingSystem;
-import org.gradle.plugins.cpp.gpp.internal.version.GppVersionDeterminer;
-
-import java.io.File;
-import java.util.*;
-
-public class AvailableCompilers {
- static List<CompilerCandidate> getCompilers() {
- List<CompilerCandidate> compilers = new ArrayList<CompilerCandidate>();
- if (OperatingSystem.current().isWindows()) {
- compilers.add(findVisualCpp());
- compilers.add(findMinGW());
- } else {
- compilers.add(findGpp("3", "/opt/gcc/3.4.6/g++"));
- compilers.add(findGpp("4", null));
- }
- return compilers;
- }
-
- static private CompilerCandidate findVisualCpp() {
- // Search first in path, then in the standard installation locations
- File compilerExe = OperatingSystem.current().findInPath("cl.exe");
- if (compilerExe != null) {
- return new InstalledCompiler("visual c++");
- }
-
- compilerExe = new File("C:/Program Files (x86)/Microsoft Visual Studio 10.0/VC/bin/cl.exe");
- if (compilerExe.isFile()) {
- File binDir = compilerExe.getParentFile();
- File vcDir = binDir.getParentFile();
- File baseDir = vcDir.getParentFile();
- File sdkDir = new File(baseDir.getParentFile(), "Microsoft SDKs/Windows/v7.0A");
- return new InstalledCompiler("visual c++",
- new File(baseDir, "Common7/IDE"),
- binDir,
- new File(baseDir, "Common7/Tools"),
- new File(vcDir, "VCPackages"),
- new File(sdkDir, "Bin"))
- .envVar("INCLUDE", new File(vcDir, "include").getAbsolutePath())
- .envVar("LIB", new File(vcDir, "lib").getAbsolutePath() + File.pathSeparator + new File(sdkDir, "lib").getAbsolutePath());
- }
-
- return new UnavailableCompiler("visual c++");
- }
-
- static private CompilerCandidate findMinGW() {
- // Search in the standard installation locations (doesn't yet work with cygwin g++ in path)
- File compilerExe = new File("C:/MinGW/bin/g++.exe");
- if (compilerExe.isFile()) {
- return new InstalledCompiler("mingw", compilerExe.getParentFile());
- }
-
- return new UnavailableCompiler("mingw");
- }
-
- static private CompilerCandidate findGpp(String versionPrefix, String hardcodedFallback) {
- String name = String.format("g++ (%s)", versionPrefix);
- GppVersionDeterminer versionDeterminer = new GppVersionDeterminer();
- for (File candidate : OperatingSystem.current().findAllInPath("g++")) {
- if (versionDeterminer.transform(candidate).startsWith(versionPrefix)) {
- return new InstalledCompiler(name, candidate.getParentFile());
- }
- }
-
- if (hardcodedFallback != null) {
- File fallback = new File(hardcodedFallback);
- if (fallback.isFile()) {
- return new InstalledCompiler(name, fallback.getParentFile());
- }
- }
-
- return new UnavailableCompiler(name);
- }
-
- public static abstract class CompilerCandidate {
- @Override
- public String toString() {
- return getDisplayName();
- }
-
- public abstract String getDisplayName();
-
- public abstract boolean isAvailable();
-
- public abstract List<File> getPathEntries();
-
- public abstract Map<String, String> getEnvironmentVars();
- }
-
- public static class InstalledCompiler extends CompilerCandidate {
- private final List<File> pathEntries;
- private final Map<String, String> environmentVars = new HashMap<String, String>();
- private final String name;
-
- public InstalledCompiler(String name, File... pathEntries) {
- this.name = name;
- this.pathEntries = Arrays.asList(pathEntries);
- }
-
- InstalledCompiler envVar(String key, String value) {
- environmentVars.put(key, value);
- return this;
- }
-
- @Override
- public String getDisplayName() {
- return name;
- }
-
- @Override
- public boolean isAvailable() {
- return true;
- }
-
- @Override
- public List<File> getPathEntries() {
- return pathEntries;
- }
-
- @Override
- public Map<String, String> getEnvironmentVars() {
- return environmentVars;
- }
- }
-
- public static class UnavailableCompiler extends CompilerCandidate {
- private final String name;
-
- public UnavailableCompiler(String name) {
- this.name = name;
- }
-
- @Override
- public String getDisplayName() {
- return name;
- }
-
- @Override
- public boolean isAvailable() {
- return false;
- }
-
- @Override
- public List<File> getPathEntries() {
- throw new UnsupportedOperationException("This compiler is not installed.");
- }
-
- @Override
- public Map<String, String> getEnvironmentVars() {
- throw new UnsupportedOperationException("This compiler is not installed.");
- }
- }
-}
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/plugins/cpp/CppExePluginGoodBehaviourTest.groovy b/subprojects/cpp/src/integTest/groovy/org/gradle/plugins/cpp/CppExePluginGoodBehaviourTest.groovy
deleted file mode 100644
index 1401efb..0000000
--- a/subprojects/cpp/src/integTest/groovy/org/gradle/plugins/cpp/CppExePluginGoodBehaviourTest.groovy
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp
-
-import org.gradle.integtests.fixtures.WellBehavedPluginTest
-
-class CppExePluginGoodBehaviourTest extends WellBehavedPluginTest {
- @Override
- def String getPluginId() {
- return "cpp-exe"
- }
-}
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/plugins/cpp/CppIntegrationTestRunner.java b/subprojects/cpp/src/integTest/groovy/org/gradle/plugins/cpp/CppIntegrationTestRunner.java
deleted file mode 100755
index ee6733d..0000000
--- a/subprojects/cpp/src/integTest/groovy/org/gradle/plugins/cpp/CppIntegrationTestRunner.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp;
-
-import com.google.common.base.Joiner;
-import org.gradle.integtests.fixtures.AbstractMultiTestRunner;
-import org.gradle.internal.nativeplatform.*;
-import org.gradle.internal.nativeplatform.services.NativeServices;
-import org.gradle.internal.os.OperatingSystem;
-
-import java.io.File;
-import java.util.List;
-import java.util.Map;
-
-public class CppIntegrationTestRunner extends AbstractMultiTestRunner {
- public CppIntegrationTestRunner(Class<?> target) {
- super(target);
- }
-
- @Override
- protected void createExecutions() {
- List<AvailableCompilers.CompilerCandidate> compilers = AvailableCompilers.getCompilers();
- for (AvailableCompilers.CompilerCandidate compiler : compilers) {
- add(new CompilerExecution(compiler));
- }
- }
-
- private static class CompilerExecution extends Execution {
- private static final ProcessEnvironment PROCESS_ENVIRONMENT = NativeServices.getInstance().get(ProcessEnvironment.class);
- private final AvailableCompilers.CompilerCandidate compiler;
- private String originalPath;
- private final String pathVarName;
-
-
- public CompilerExecution(AvailableCompilers.CompilerCandidate compiler) {
- this.compiler = compiler;
- this.pathVarName = !OperatingSystem.current().isWindows() ? "Path" : "PATH";
- }
-
- @Override
- protected boolean isEnabled() {
- return compiler.isAvailable() && canDoNecessaryEnvironmentManipulation();
- }
-
- private boolean canDoNecessaryEnvironmentManipulation() {
- return (compiler.getEnvironmentVars().isEmpty() && compiler.getPathEntries().isEmpty())
- || PROCESS_ENVIRONMENT.maybeSetEnvironmentVariable(pathVarName, System.getenv(pathVarName));
- }
-
- @Override
- protected String getDisplayName() {
- return compiler.getDisplayName();
- }
-
- @Override
- protected void before() {
- System.out.println(String.format("Using compiler %s", compiler.getDisplayName()));
-
- String compilerPath = Joiner.on(File.pathSeparator).join(compiler.getPathEntries());
-
-
- if (compilerPath.length() > 0) {
- originalPath = System.getenv(pathVarName);
- String path = compilerPath + File.pathSeparator + originalPath;
- System.out.println(String.format("Using path %s", path));
- PROCESS_ENVIRONMENT.setEnvironmentVariable(pathVarName, path);
- }
-
- for (Map.Entry<String, String> entry : compiler.getEnvironmentVars().entrySet()) {
- System.out.println(String.format("Using environment var %s -> %s", entry.getKey(), entry.getValue()));
- PROCESS_ENVIRONMENT.setEnvironmentVariable(entry.getKey(), entry.getValue());
- }
- }
-
- @Override
- protected void after() {
- if (originalPath != null) {
- PROCESS_ENVIRONMENT.setEnvironmentVariable(pathVarName, originalPath);
- }
- }
- }
-}
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/plugins/cpp/CppLibPluginGoodBehaviourTest.groovy b/subprojects/cpp/src/integTest/groovy/org/gradle/plugins/cpp/CppLibPluginGoodBehaviourTest.groovy
deleted file mode 100644
index 134b5d5..0000000
--- a/subprojects/cpp/src/integTest/groovy/org/gradle/plugins/cpp/CppLibPluginGoodBehaviourTest.groovy
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp
-
-import org.gradle.integtests.fixtures.WellBehavedPluginTest
-
-class CppLibPluginGoodBehaviourTest extends WellBehavedPluginTest {
- @Override
- def String getPluginId() {
- return "cpp-lib"
- }
-}
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/plugins/cpp/CppPluginIntegrationTest.groovy b/subprojects/cpp/src/integTest/groovy/org/gradle/plugins/cpp/CppPluginIntegrationTest.groovy
deleted file mode 100755
index a4a3f22..0000000
--- a/subprojects/cpp/src/integTest/groovy/org/gradle/plugins/cpp/CppPluginIntegrationTest.groovy
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp
-
-import static org.gradle.util.TextUtil.escapeString
-
-class CppPluginIntegrationTest extends AbstractBinariesIntegrationSpec {
-
- static final HELLO_WORLD = "Hello, World!"
-
- def "build and execute simple cpp program"() {
- given:
- buildFile << """
- apply plugin: "cpp-exe"
- """
- settingsFile << "rootProject.name = 'test'"
-
- and:
- file("src", "main", "cpp", "helloworld.cpp") << """
- #include <iostream>
-
- int main () {
- std::cout << "${escapeString(HELLO_WORLD)}";
- return 0;
- }
- """
-
- when:
- run "compileMain"
-
- then:
- def executable = executable("build/binaries/test")
- executable.isFile()
- executable.exec().out == HELLO_WORLD
- }
-
- def "build simple cpp library"() {
- given:
- buildFile << """
- apply plugin: "cpp-lib"
- """
- settingsFile << "rootProject.name = 'test'"
-
- and:
- file("src", "main", "cpp", "helloworld.cpp") << """
- #include <iostream>
- #ifdef _WIN32
- #define DLL_FUNC __declspec(dllexport)
- #else
- #define DLL_FUNC
- #endif
-
- int DLL_FUNC main () {
- std::cout << "${escapeString(HELLO_WORLD)}";
- return 0;
- }
- """
-
- when:
- run "compileMain"
-
- then:
- sharedLibrary("build/binaries/test").isFile()
- }
-
- def "build fails when compilation fails"() {
- given:
- buildFile << """
- apply plugin: "cpp-exe"
- """
- settingsFile << "rootProject.name = 'test'"
-
- and:
- file("src", "main", "cpp", "helloworld.cpp") << """
- #include <iostream>
-
- 'broken
- """
-
- expect:
- fails "compileMain"
- }
-
- def "build fails when link fails"() {
- given:
- buildFile << """
- apply plugin: "cpp-exe"
- """
- settingsFile << "rootProject.name = 'test'"
-
- and:
- file("src", "main", "cpp", "helloworld.cpp") << """
- int thing() { return 0; }
- """
-
- expect:
- fails "compileMain"
- }
-
- def "build and execute program from multiple source files"() {
- given:
- buildFile << """
- apply plugin: "cpp-exe"
- """
- settingsFile << "rootProject.name = 'test'"
-
- and:
- file("src", "main", "cpp", "hello.cpp") << """
- #include <iostream>
-
- void hello () {
- std::cout << "${escapeString(HELLO_WORLD)}";
- }
- """
-
- and:
- file("src", "main", "headers", "hello.h") << """
- void hello();
- """
-
- and:
- file("src", "main", "cpp", "main.cpp") << """
- #include "hello.h"
-
- int main () {
- hello();
- return 0;
- }
- """
-
- when:
- run "compileMain"
-
- then:
- executable("build/binaries/test").exec().out == HELLO_WORLD
- }
-
- def "build, install and execute program with shared library"() {
- given:
- buildFile << """
- apply plugin: "cpp-exe"
-
- cpp {
- sourceSets {
- hello {}
- }
- }
- libraries {
- hello {
- sourceSets << cpp.sourceSets.hello
- }
- }
- cpp.sourceSets.main.libs << libraries.hello
- """
- settingsFile << "rootProject.name = 'test'"
-
- and:
- file("src/hello/cpp/hello.cpp") << """
- #include <iostream>
- #ifdef _WIN32
- #define DLL_FUNC __declspec(dllexport)
- #else
- #define DLL_FUNC
- #endif
-
- void DLL_FUNC hello(const char* str) {
- std::cout << str;
- }
- """
-
- and:
- file("src/hello/headers/hello.h") << """
- void hello(const char* str);
- """
-
- and:
- file("src/main/cpp/main.cpp") << """
- #include <iostream>
- #include "hello.h"
-
- int main (int argc, char** argv) {
- hello("${escapeString(HELLO_WORLD)}");
- for ( int i = 1; i < argc; i++ ) {
- std::cout << "[" << argv[i] << "]";
- }
- return 0;
- }
- """
-
- when:
- run "installMain"
-
- then:
- sharedLibrary("build/binaries/hello").isFile()
- executable("build/binaries/test").isFile()
-
- executable("build/install/main/test").exec().out == HELLO_WORLD
- executable("build/install/main/test").exec("a", "1 2 3").out.contains("[a][1 2 3]")
-
- // Ensure installed binary is not dependent on the libraries in their original locations
- when:
- file("build/binaries").deleteDir()
-
- then:
- executable("build/install/main/test").exec().out == HELLO_WORLD
- }
-}
diff --git a/subprojects/cpp/src/integTest/groovy/org/gradle/plugins/cpp/CppSamplesIntegrationTest.groovy b/subprojects/cpp/src/integTest/groovy/org/gradle/plugins/cpp/CppSamplesIntegrationTest.groovy
deleted file mode 100755
index 5531fe7..0000000
--- a/subprojects/cpp/src/integTest/groovy/org/gradle/plugins/cpp/CppSamplesIntegrationTest.groovy
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp
-
-import org.gradle.integtests.fixtures.Sample
-import org.gradle.util.Requires
-import org.gradle.util.TestPrecondition
-import org.junit.Rule
-
-import static org.gradle.util.TextUtil.toPlatformLineSeparators
-
-class CppSamplesIntegrationTest extends AbstractBinariesIntegrationSpec {
- @Rule public final Sample exewithlib = new Sample(temporaryFolder, 'cpp/exewithlib')
- @Rule public final Sample dependencies = new Sample(temporaryFolder, 'cpp/dependencies')
- @Rule public final Sample exe = new Sample(temporaryFolder, 'cpp/exe')
-
- def "exe with lib"() {
- given:
- sample exewithlib
-
- when:
- run "installMain"
-
- then:
- ":exe:compileMain" in executedTasks
-
- and:
- sharedLibrary("cpp/exewithlib/lib/build/binaries/lib").isFile()
- executable("cpp/exewithlib/exe/build/binaries/exe").isFile()
- executable("cpp/exewithlib/exe/build/install/main/exe").exec().out == toPlatformLineSeparators("Hello, World!\n")
- }
-
- // Does not work on windows, due to GRADLE-2118
- @Requires(TestPrecondition.NOT_WINDOWS)
- def "dependencies"() {
- when:
- sample dependencies
- run ":lib:uploadArchives"
-
- then:
- sharedLibrary("cpp/dependencies/lib/build/binaries/lib").isFile()
- file("cpp/dependencies/lib/build/repo/some-org/some-lib/1.0/some-lib-1.0-so.so").isFile()
-
- when:
- sample dependencies
- run ":exe:uploadArchives"
-
- then:
- ":exe:mainExtractHeaders" in nonSkippedTasks
- ":exe:compileMain" in nonSkippedTasks
-
- and:
- executable("cpp/dependencies/exe/build/binaries/exe").isFile()
- file("cpp/dependencies/exe/build/repo/dependencies/exe/1.0/exe-1.0.exe").exists()
- }
-
- def "exe"() {
- given:
- sample exe
-
- when:
- run "installMain"
-
- then:
- ":compileMain" in nonSkippedTasks
-
- and:
- executable("cpp/exe/build/binaries/exe").exec().out == toPlatformLineSeparators("Hello, World!\n")
- executable("cpp/exe/build/install/main/exe").exec().out == toPlatformLineSeparators("Hello, World!\n")
- }
-
-}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/DependentSourceSet.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/DependentSourceSet.java
new file mode 100644
index 0000000..bc2b1e1
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/DependentSourceSet.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base;
+
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * A source set that depends on one or more {@link NativeDependencySet}s to be built.
+ */
+public interface DependentSourceSet {
+ /**
+ * The libraries that this source set requires.
+ */
+ Collection<?> getLibs();
+
+ /**
+ * Adds a library that this source set requires. This method accepts the following types:
+ *
+ * <ul>
+ * <li>A {@link Library}</li>
+ * <li>A {@link LibraryBinary}</li>
+ * <li>A {@link NativeDependencySet}</li>
+ * </ul>
+ */
+ void lib(Object library);
+
+ /**
+ * Add a dependency to this source set.
+ */
+ void dependency(Map<?, ?> dep);
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/Executable.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/Executable.java
new file mode 100644
index 0000000..5af455e
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/Executable.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base;
+
+import org.gradle.api.Incubating;
+
+/**
+ * The logical representation of an executable native component.
+ */
+ at Incubating
+public interface Executable extends NativeComponent {
+
+}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/ExecutableBinary.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/ExecutableBinary.java
new file mode 100644
index 0000000..6733bfb
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/ExecutableBinary.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base;
+
+import org.gradle.api.Incubating;
+
+/**
+ * A binary artifact that is built from of a {@link Executable}, targeted at a particular platform with specific configuration.
+ */
+ at Incubating
+public interface ExecutableBinary extends NativeBinary {
+ Executable getComponent();
+}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/ExecutableContainer.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/ExecutableContainer.java
new file mode 100644
index 0000000..b4cd50e
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/ExecutableContainer.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base;
+
+import org.gradle.api.NamedDomainObjectSet;
+
+/**
+ * A container of native executables.
+ */
+public interface ExecutableContainer extends NamedDomainObjectSet<Executable> {
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/Flavor.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/Flavor.java
new file mode 100644
index 0000000..16ae1f3
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/Flavor.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base;
+
+import org.gradle.api.Incubating;
+import org.gradle.api.Named;
+import org.gradle.nativecode.base.internal.DefaultFlavor;
+
+/**
+ * Defines a custom variant that can be built for a {@link NativeComponent}.
+ */
+ at Incubating
+public interface Flavor extends Named {
+ Flavor DEFAULT = new DefaultFlavor("default", true);
+
+ /**
+ * Is this the automatically created default flavor for the component?
+ */
+ boolean isDefault();
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/FlavorContainer.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/FlavorContainer.java
new file mode 100644
index 0000000..3aea240
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/FlavorContainer.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base;
+
+import org.gradle.api.NamedDomainObjectContainer;
+
+/**
+ * A container of flavors.
+ * If now flavor is explicitly configured, will contain a single {@link Flavor#DEFAULT}.
+ * Any flavors explicitly configured will overwrite the default flavor.
+ */
+public interface FlavorContainer extends NamedDomainObjectContainer<Flavor> {
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/HeaderExportingSourceSet.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/HeaderExportingSourceSet.java
new file mode 100644
index 0000000..66e686f
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/HeaderExportingSourceSet.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base;
+
+import org.gradle.api.Action;
+import org.gradle.api.Incubating;
+import org.gradle.api.file.SourceDirectorySet;
+import org.gradle.language.base.LanguageSourceSet;
+
+/**
+ * A source set that exposes headers
+ */
+ at Incubating
+public interface HeaderExportingSourceSet extends LanguageSourceSet {
+
+ /**
+ * Configure the exported header directories.
+ */
+ void exportedHeaders(Action<SourceDirectorySet> config);
+
+ /**
+ * The headers as a directory set.
+ */
+ SourceDirectorySet getExportedHeaders();
+}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/Library.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/Library.java
new file mode 100644
index 0000000..6083d83
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/Library.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base;
+
+import org.gradle.api.Incubating;
+import org.gradle.api.file.SourceDirectorySet;
+
+/**
+ * The logical representation of an library native component.
+ */
+ at Incubating
+public interface Library extends NativeComponent {
+ /**
+ * The headers exported by this library.
+ */
+ SourceDirectorySet getHeaders();
+
+ /**
+ * Converts this library to a native dependency that uses the shared library variant. This is the default.
+ */
+ LibraryResolver getShared();
+
+ /**
+ * Converts this library to a native dependency that uses the static library variant.
+ */
+ LibraryResolver getStatic();
+}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/LibraryBinary.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/LibraryBinary.java
new file mode 100644
index 0000000..5680ebe
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/LibraryBinary.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base;
+
+import org.gradle.api.Incubating;
+
+/**
+ * A physical representation of a {@link Library} component.
+ */
+ at Incubating
+public interface LibraryBinary extends NativeBinary, LibraryResolver {
+ /**
+ * The Library that this binary represents.
+ */
+ Library getComponent();
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/LibraryContainer.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/LibraryContainer.java
new file mode 100644
index 0000000..47025a1
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/LibraryContainer.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base;
+
+import org.gradle.api.NamedDomainObjectSet;
+
+/**
+ * A container of C++ libraries.
+ */
+public interface LibraryContainer extends NamedDomainObjectSet<Library> {
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/LibraryResolver.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/LibraryResolver.java
new file mode 100644
index 0000000..2bd1819
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/LibraryResolver.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base;
+
+import org.gradle.api.Incubating;
+
+// TODO:DAZ Needs a better name
+/**
+ * Resolves a library to a single binary to use as a dependency.
+ */
+ at Incubating
+public interface LibraryResolver {
+
+ /**
+ * Resolves the library to a dependency set.
+ */
+ NativeDependencySet resolve();
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/NativeBinary.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/NativeBinary.java
new file mode 100644
index 0000000..cfb57c2
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/NativeBinary.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base;
+
+import org.gradle.api.DomainObjectSet;
+import org.gradle.api.Incubating;
+import org.gradle.api.internal.HasInternalProtocol;
+import org.gradle.language.base.Binary;
+import org.gradle.language.base.LanguageSourceSet;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.List;
+
+// TODO:DAZ These don't apply to all binary subtypes: look at splitting this up in to a number of smaller facets / functional interfaces
+/**
+ * Represents a particular binary artifact that is the result of building a native component.
+ */
+ at Incubating @HasInternalProtocol
+public interface NativeBinary extends Binary {
+
+ /**
+ * The flavor that this binary was built with.
+ */
+ Flavor getFlavor();
+
+ /**
+ * The file where this binary will be created.
+ */
+ File getOutputFile();
+
+ /**
+ * Sets the file where this binary will be created.
+ */
+ void setOutputFile(File outputFile);
+
+ /**
+ * The source sets used to compile this binary.
+ */
+ DomainObjectSet<LanguageSourceSet> getSource();
+
+ /**
+ * Adds one or more {@link LanguageSourceSet}s that are used to compile this binary.
+ * <p/>
+ * This method accepts the following types:
+ *
+ * <ul>
+ * <li>A {@link org.gradle.language.base.FunctionalSourceSet}</li>
+ * <li>A {@link LanguageSourceSet}</li>
+ * <li>A Collection of {@link LanguageSourceSet}s</li>
+ * </ul>
+ */
+ void source(Object source);
+
+ /**
+ * Returns the {@link ToolChain} that will be used to build this binary.
+ */
+ ToolChain getToolChain();
+
+ /**
+ * The libraries that should be linked into this binary.
+ */
+ Collection<NativeDependencySet> getLibs();
+
+ /**
+ * Adds a library as input to this binary.
+ * <p/>
+ * This method accepts the following types:
+ *
+ * <ul>
+ * <li>A {@link Library}</li>
+ * <li>A {@link LibraryBinary}</li>
+ * <li>A {@link NativeDependencySet}</li>
+ * </ul>
+ */
+ void lib(Object library);
+
+ /**
+ * The set of preprocessor macros to define when compiling this binary.
+ */
+ List<Object> getMacros();
+
+ /**
+ * Adds a number of preprocessor macros to define when compiling this binary.
+ */
+ void define(Object... defines);
+
+ /**
+ * The arguments passed when compiling this binary.
+ */
+ List<Object> getCompilerArgs();
+
+ /**
+ * Adds a number of arguments to be passed to the compiler.
+ */
+ void compilerArgs(Object... args);
+
+ /**
+ * The arguments passed when assembling this binary.
+ */
+ List<Object> getAssemblerArgs();
+
+ /**
+ * Adds a number of arguments to be passed to the assembler.
+ */
+ void assemblerArgs(Object... args);
+
+ /**
+ * The arguments passed when linking this binary.
+ */
+ List<Object> getLinkerArgs();
+
+ /**
+ * Adds a number of arguments to be passed to the linker.
+ */
+ void linkerArgs(Object... args);
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/NativeComponent.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/NativeComponent.java
new file mode 100644
index 0000000..4fa0507
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/NativeComponent.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base;
+
+import org.gradle.api.Action;
+import org.gradle.api.DomainObjectSet;
+import org.gradle.api.Incubating;
+import org.gradle.api.Named;
+import org.gradle.language.base.LanguageSourceSet;
+
+/**
+ * Represents a logical software component, which may be built in a number of variant binaries.
+ */
+ at Incubating
+public interface NativeComponent extends Named {
+
+ /**
+ * The source sets that are used to build this component.
+ */
+ DomainObjectSet<LanguageSourceSet> getSource();
+
+ /**
+ * Adds one or more {@link LanguageSourceSet}s that are used to compile this binary.
+ * <p/>
+ * This method accepts the following types:
+ *
+ * <ul>
+ * <li>A {@link org.gradle.language.base.FunctionalSourceSet}</li>
+ * <li>A {@link LanguageSourceSet}</li>
+ * <li>A Collection of {@link LanguageSourceSet}s</li>
+ * </ul>
+ */
+ void source(Object source);
+
+ /**
+ * The binaries that are built for this component. You can use this to configure the binaries for this component.
+ */
+ DomainObjectSet<NativeBinary> getBinaries();
+
+ /**
+ * The name that is used to construct the output file names when building this component.
+ */
+ String getBaseName();
+
+ /**
+ * Sets the name that is used to construct the output file names when building this component.
+ */
+ void setBaseName(String baseName);
+
+ /**
+ * The set of flavors defined for this component. All components automatically have a default flavor named "default".
+ */
+ FlavorContainer getFlavors();
+
+ /**
+ * Configure the flavors for this component.
+ */
+ void flavors(Action<FlavorContainer> config);
+
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/NativeDependencySet.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/NativeDependencySet.java
new file mode 100644
index 0000000..3395f1c
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/NativeDependencySet.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base;
+
+import org.gradle.api.Incubating;
+import org.gradle.api.file.FileCollection;
+
+/**
+ * Models a collection of native type dependencies.
+ */
+ at Incubating
+public interface NativeDependencySet {
+ /**
+ * Returns the header file directories to use at compile time.
+ */
+ FileCollection getIncludeRoots();
+
+ /**
+ * Returns the files to use at link time.
+ */
+ FileCollection getLinkFiles();
+
+ /**
+ * Returns the files to use at runtime.
+ */
+ FileCollection getRuntimeFiles();
+}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/SharedLibraryBinary.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/SharedLibraryBinary.java
new file mode 100644
index 0000000..9844891
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/SharedLibraryBinary.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base;
+
+import org.gradle.api.Incubating;
+
+/**
+ * A {@link Library} that has been compiled and linked as a shared library.
+ */
+ at Incubating
+public interface SharedLibraryBinary extends LibraryBinary {
+}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/StaticLibraryBinary.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/StaticLibraryBinary.java
new file mode 100644
index 0000000..1bb3b27
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/StaticLibraryBinary.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base;
+
+import org.gradle.api.Incubating;
+
+import java.util.List;
+
+/**
+ * A {@link Library} that has been compiled and archived into a static library.
+ */
+ at Incubating
+public interface StaticLibraryBinary extends LibraryBinary {
+ /**
+ * The arguments passed when creating a this binary.
+ */
+ List<Object> getStaticLibArgs();
+
+ /**
+ * Adds a number of arguments to be passed when creating this static library.
+ */
+ void staticLibArgs(Object... args);
+}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/ToolChain.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/ToolChain.java
new file mode 100644
index 0000000..2732f22
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/ToolChain.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base;
+
+import org.gradle.api.Incubating;
+import org.gradle.api.Named;
+import org.gradle.api.internal.HasInternalProtocol;
+
+/**
+ * A set of compilers and linkers that are used together to construct a native binary.
+ */
+ at Incubating @HasInternalProtocol
+public interface ToolChain extends Named {
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/ToolChainRegistry.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/ToolChainRegistry.java
new file mode 100644
index 0000000..461c15f
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/ToolChainRegistry.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base;
+
+import org.gradle.api.ExtensiblePolymorphicDomainObjectContainer;
+import org.gradle.api.Incubating;
+
+import java.util.List;
+
+/**
+ * A container for {@link ToolChain}s.
+ */
+ at Incubating
+public interface ToolChainRegistry extends ExtensiblePolymorphicDomainObjectContainer<ToolChain> {
+ /**
+ * Registers a default ToolChain. If no tool chain currently exists, and the registered tool
+ * chain is available, then a default instance is added to the registry.
+ * Creating or adding a ToolChain directly will replace a default instance.
+ */
+ void registerDefaultToolChain(String name, Class<? extends ToolChain> type);
+
+ /**
+ * Returns all registered {@link ToolChain}s that are available.
+ */
+ List<? extends ToolChain> getAvailableToolChains();
+
+ /**
+ * Returns the first registered {@link ToolChain} that is available.
+ */
+ ToolChain getDefaultToolChain();
+}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/AbstractToolChain.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/AbstractToolChain.java
new file mode 100644
index 0000000..c6d2ad3
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/AbstractToolChain.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.internal;
+
+import org.gradle.api.internal.file.FileResolver;
+import org.gradle.internal.os.OperatingSystem;
+import org.gradle.nativecode.toolchain.ConfigurableToolChain;
+import org.gradle.nativecode.toolchain.Tool;
+import org.gradle.nativecode.toolchain.internal.ToolRegistry;
+import org.gradle.nativecode.toolchain.internal.ToolType;
+
+import java.io.File;
+import java.util.List;
+
+public abstract class AbstractToolChain implements ToolChainInternal, ConfigurableToolChain {
+ private final String name;
+ protected final OperatingSystem operatingSystem;
+ protected final ToolRegistry tools;
+ private final FileResolver fileResolver;
+ private ToolChainAvailability availability;
+
+ protected AbstractToolChain(String name, OperatingSystem operatingSystem, ToolRegistry tools, FileResolver fileResolver) {
+ this.name = name;
+ this.operatingSystem = operatingSystem;
+ this.tools = tools;
+ this.fileResolver = fileResolver;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ protected abstract String getTypeName();
+
+ @Override
+ public String toString() {
+ return String.format("ToolChain '%s' (%s)", getName(), getTypeName());
+ }
+
+ public ToolChainAvailability getAvailability() {
+ if (availability == null) {
+ availability = new ToolChainAvailability();
+ checkAvailable(availability);
+ }
+ return availability;
+ }
+
+ protected void checkAvailable() {
+ if (!getAvailability().isAvailable()) {
+ throw new IllegalStateException(String.format("Tool chain %s is not available", getName()));
+ }
+ }
+
+ public String getOutputType() {
+ return String.format("%s-%s", getName(), operatingSystem.getName());
+ }
+
+ protected abstract void checkAvailable(ToolChainAvailability availability);
+
+ public String getExecutableName(String executablePath) {
+ return operatingSystem.getExecutableName(executablePath);
+ }
+
+ public String getSharedLibraryName(String libraryName) {
+ return operatingSystem.getSharedLibraryName(libraryName);
+ }
+
+ public String getSharedLibraryLinkFileName(String libraryName) {
+ return getSharedLibraryName(libraryName);
+ }
+
+ public String getStaticLibraryName(String libraryName) {
+ return operatingSystem.getStaticLibraryName(libraryName);
+ }
+
+ public List<File> getPaths() {
+ return tools.getPath();
+ }
+
+ public void path(Object... paths) {
+ for (Object path : paths) {
+ tools.path(resolve(path));
+ }
+ }
+
+ protected File resolve(Object path) {
+ return fileResolver.resolve(path);
+ }
+
+ public Tool getCppCompiler() {
+ return new DefaultTool(ToolType.CPP_COMPILER);
+ }
+
+ public Tool getCCompiler() {
+ return new DefaultTool(ToolType.C_COMPILER);
+ }
+
+ public Tool getAssembler() {
+ return new DefaultTool(ToolType.ASSEMBLER);
+ }
+
+ public Tool getLinker() {
+ return new DefaultTool(ToolType.LINKER);
+ }
+
+ public Tool getStaticLibArchiver() {
+ return new DefaultTool(ToolType.STATIC_LIB_ARCHIVER);
+ }
+
+ private class DefaultTool implements Tool {
+ private final ToolType toolType;
+
+ private DefaultTool(ToolType toolType) {
+ this.toolType = toolType;
+ }
+
+ public String getExe() {
+ return tools.getExeName(toolType);
+ }
+
+ public void setExe(String file) {
+ tools.setExeName(toolType, file);
+ }
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/BinaryToolSpec.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/BinaryToolSpec.java
new file mode 100644
index 0000000..b70fac5
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/BinaryToolSpec.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.internal;
+
+import org.gradle.api.internal.tasks.compile.CompileSpec;
+
+import java.io.File;
+
+public interface BinaryToolSpec extends CompileSpec {
+ File getTempDir();
+
+ void setTempDir(File tempDir);
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/ConfigurableLibraryResolver.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/ConfigurableLibraryResolver.java
new file mode 100644
index 0000000..37235a7
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/ConfigurableLibraryResolver.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.internal;
+
+import org.gradle.nativecode.base.Flavor;
+import org.gradle.nativecode.base.LibraryBinary;
+import org.gradle.nativecode.base.LibraryResolver;
+
+public interface ConfigurableLibraryResolver extends LibraryResolver {
+ ConfigurableLibraryResolver withType(Class<? extends LibraryBinary> type);
+
+ ConfigurableLibraryResolver withFlavor(Flavor flavor);
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/ConfigurationBasedNativeDependencySet.groovy b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/ConfigurationBasedNativeDependencySet.groovy
new file mode 100644
index 0000000..4d431c8
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/ConfigurationBasedNativeDependencySet.groovy
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.internal
+
+import org.gradle.nativecode.base.NativeDependencySet
+import org.gradle.api.Project
+import org.gradle.api.Task
+import org.gradle.api.file.FileCollection
+import org.gradle.api.artifacts.Configuration
+
+class ConfigurationBasedNativeDependencySet implements NativeDependencySet {
+
+ private final String baseName
+ final String headersConfigurationName
+ final String filesConfigurationName // files is a bad name
+ final Project project
+ private Task headerExtractionTask
+
+ ConfigurationBasedNativeDependencySet(Project project, String baseName = "main") {
+ this.baseName = baseName
+ this.headersConfigurationName = baseName + "HeaderDependencies"
+ this.filesConfigurationName = baseName + "FileDependencies"
+ this.project = project
+
+ createConfigurations()
+ initHeaderExtractionTask()
+ }
+
+ private createConfigurations() {
+ project.configurations.with {
+ create(headersConfigurationName)
+ create(filesConfigurationName)
+ }
+ }
+
+ private initHeaderExtractionTask() {
+ def headersConfiguration = getHeadersConfiguration()
+ def dir = project.file("$project.buildDir/dependency-headers/$baseName")
+ headerExtractionTask = project.task(baseName + "ExtractHeaders") {
+ inputs.files headersConfiguration
+ outputs.files { dir.listFiles() }
+ doLast {
+ headersConfiguration.each { headerZip ->
+ project.copy {
+ from project.zipTree(headerZip)
+ into "$dir/${headerZip.name - '.zip'}"
+ }
+ }
+ }
+ }
+ }
+
+ Configuration getHeadersConfiguration() {
+ project.configurations[headersConfigurationName]
+ }
+
+ FileCollection getIncludeRoots() {
+ headerExtractionTask.outputs.files
+ }
+
+ FileCollection getLinkFiles() {
+ project.configurations[filesConfigurationName]
+ }
+
+ FileCollection getRuntimeFiles() {
+ return getLinkFiles()
+ }
+
+ void add(Map dep) {
+ // hackity hack hack
+ project.dependencies {
+ def m = { classifier, ext -> [classifier: classifier, ext: ext] }
+ delegate."$headersConfigurationName"(dep + m("headers", "zip"))
+ delegate."$filesConfigurationName"(dep + m("so", "so"))
+ }
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/CreateNativeBinariesAction.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/CreateNativeBinariesAction.java
new file mode 100644
index 0000000..0c6a7c4
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/CreateNativeBinariesAction.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.internal;
+
+import org.gradle.api.Action;
+import org.gradle.api.internal.project.ProjectInternal;
+import org.gradle.internal.reflect.Instantiator;
+import org.gradle.language.base.BinaryContainer;
+import org.gradle.nativecode.base.*;
+
+import java.util.List;
+
+public class CreateNativeBinariesAction implements Action<ProjectInternal> {
+ private final Instantiator instantiator;
+
+ public CreateNativeBinariesAction(Instantiator instantiator) {
+ this.instantiator = instantiator;
+ }
+
+ public void execute(ProjectInternal project) {
+ ToolChainRegistry toolChains = project.getExtensions().getByType(ToolChainRegistry.class);
+ ExecutableContainer executables = project.getExtensions().getByType(ExecutableContainer.class);
+ LibraryContainer libraries = project.getExtensions().getByType(LibraryContainer.class);
+ BinaryContainer binaries = project.getExtensions().getByType(BinaryContainer.class);
+
+ NativeBinaryFactory factory = new NativeBinaryFactory(instantiator, project, toolChains);
+ List<? extends ToolChain> availableToolChains = toolChains.getAvailableToolChains();
+ for (ToolChain toolChain : availableToolChains) {
+ for (Library library : libraries) {
+ for (Flavor flavor : library.getFlavors()) {
+ binaries.add(factory.createNativeBinary(DefaultSharedLibraryBinary.class, library, toolChain, flavor));
+ binaries.add(factory.createNativeBinary(DefaultStaticLibraryBinary.class, library, toolChain, flavor));
+ }
+ }
+ for (Executable executable : executables) {
+ for (Flavor flavor : executable.getFlavors()) {
+ binaries.add(factory.createNativeBinary(DefaultExecutableBinary.class, executable, toolChain, flavor));
+ }
+ }
+ }
+ }
+
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/DefaultExecutable.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/DefaultExecutable.java
new file mode 100755
index 0000000..b6223d0
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/DefaultExecutable.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.internal;
+
+import org.gradle.internal.reflect.Instantiator;
+import org.gradle.nativecode.base.Executable;
+
+public class DefaultExecutable extends DefaultNativeComponent implements Executable {
+ public DefaultExecutable(String name, Instantiator instantiator) {
+ super(name, instantiator);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("executable '%s'", getName());
+ }
+}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/DefaultExecutableBinary.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/DefaultExecutableBinary.java
new file mode 100644
index 0000000..dcb9144
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/DefaultExecutableBinary.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.internal;
+
+import org.gradle.language.base.internal.DefaultBinaryNamingScheme;
+import org.gradle.nativecode.base.Executable;
+import org.gradle.nativecode.base.ExecutableBinary;
+import org.gradle.nativecode.base.Flavor;
+
+public class DefaultExecutableBinary extends DefaultNativeBinary implements ExecutableBinary {
+ private final Executable executable;
+
+ public DefaultExecutableBinary(Executable executable, Flavor flavor, ToolChainInternal toolChain, DefaultBinaryNamingScheme namingScheme) {
+ super(executable, flavor, toolChain, namingScheme.withTypeString("Executable"));
+ this.executable = executable;
+ }
+
+ public Executable getComponent() {
+ return executable;
+ }
+
+ public String getOutputFileName() {
+ return getToolChain().getExecutableName(getComponent().getBaseName());
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/DefaultExecutableContainer.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/DefaultExecutableContainer.java
new file mode 100644
index 0000000..62aa6b5
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/DefaultExecutableContainer.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.internal;
+
+import org.gradle.api.internal.AbstractNamedDomainObjectContainer;
+import org.gradle.internal.reflect.Instantiator;
+import org.gradle.nativecode.base.Executable;
+import org.gradle.nativecode.base.ExecutableContainer;
+
+public class DefaultExecutableContainer extends AbstractNamedDomainObjectContainer<Executable> implements ExecutableContainer {
+ public DefaultExecutableContainer(Instantiator instantiator) {
+ super(Executable.class, instantiator);
+ }
+
+ @Override
+ protected Executable doCreate(String name) {
+ return getInstantiator().newInstance(DefaultExecutable.class, name, getInstantiator());
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/DefaultFlavor.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/DefaultFlavor.java
new file mode 100644
index 0000000..56063be
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/DefaultFlavor.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.internal;
+
+import org.gradle.nativecode.base.Flavor;
+
+public class DefaultFlavor implements Flavor {
+ private final String name;
+ private final boolean isDefault;
+
+ public DefaultFlavor(String name) {
+ this(name, false);
+ }
+
+ public DefaultFlavor(String name, boolean isDefault) {
+ this.name = name;
+ this.isDefault = isDefault;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public boolean isDefault() {
+ return isDefault;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("flavor '%s'", name);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof DefaultFlavor)) {
+ return false;
+ }
+
+ DefaultFlavor that = (DefaultFlavor) o;
+ return name.equals(that.name);
+
+ }
+
+ @Override
+ public int hashCode() {
+ return name.hashCode();
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/DefaultFlavorContainer.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/DefaultFlavorContainer.java
new file mode 100644
index 0000000..6f9df27
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/DefaultFlavorContainer.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.internal;
+
+import org.gradle.api.internal.AbstractNamedDomainObjectContainer;
+import org.gradle.internal.reflect.Instantiator;
+import org.gradle.nativecode.base.Flavor;
+import org.gradle.nativecode.base.FlavorContainer;
+
+import java.util.Collection;
+
+public class DefaultFlavorContainer extends AbstractNamedDomainObjectContainer<Flavor> implements FlavorContainer {
+ boolean hasDefault;
+ public DefaultFlavorContainer(Instantiator instantiator) {
+ super(Flavor.class, instantiator);
+ add(Flavor.DEFAULT);
+ hasDefault = true;
+ }
+
+ @Override
+ public boolean add(Flavor o) {
+ removeDefault();
+ return super.add(o);
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends Flavor> c) {
+ removeDefault();
+ return super.addAll(c);
+ }
+
+ private void removeDefault() {
+ if (hasDefault) {
+ remove(Flavor.DEFAULT);
+ hasDefault = false;
+ }
+ }
+
+ @Override
+ protected Flavor doCreate(String name) {
+ return getInstantiator().newInstance(DefaultFlavor.class, name);
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/DefaultLibrary.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/DefaultLibrary.java
new file mode 100755
index 0000000..9ca9cad
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/DefaultLibrary.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.internal;
+
+import org.gradle.api.Action;
+import org.gradle.api.DomainObjectSet;
+import org.gradle.api.file.SourceDirectorySet;
+import org.gradle.api.internal.file.DefaultSourceDirectorySet;
+import org.gradle.api.internal.file.FileResolver;
+import org.gradle.internal.reflect.Instantiator;
+import org.gradle.nativecode.base.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class DefaultLibrary extends DefaultNativeComponent implements Library {
+ private final DefaultSourceDirectorySet headers;
+
+ public DefaultLibrary(String name, Instantiator instantiator, FileResolver fileResolver) {
+ super(name, instantiator);
+ this.headers = new DefaultSourceDirectorySet("headers", String.format("Exported headers for native library '%s'", name), fileResolver);
+ initExportedHeaderTracking();
+ }
+
+ @Override
+ public String toString() {
+ return String.format("library '%s'", getName());
+ }
+
+ public SourceDirectorySet getHeaders() {
+ return headers;
+ }
+
+ public ConfigurableLibraryResolver getShared() {
+ return new DefaultLibraryResolver(this).withType(SharedLibraryBinary.class);
+ }
+
+ public ConfigurableLibraryResolver getStatic() {
+ return new DefaultLibraryResolver(this).withType(StaticLibraryBinary.class);
+ }
+
+ private void initExportedHeaderTracking() {
+ // TODO - headers.srcDirs() should allow a Callable<SourceDirectorySet> for lazy calculation
+ final DomainObjectSet<HeaderExportingSourceSet> headerExportingSourceSets = getSource().withType(HeaderExportingSourceSet.class);
+ headerExportingSourceSets.all(new Action<HeaderExportingSourceSet>() {
+ public void execute(HeaderExportingSourceSet headerExportingSourceSet) {
+ updateHeaderDirs(headerExportingSourceSets, headers);
+ }
+ });
+ headerExportingSourceSets.whenObjectRemoved(new Action<HeaderExportingSourceSet>() {
+ public void execute(HeaderExportingSourceSet headerExportingSourceSet) {
+ updateHeaderDirs(headerExportingSourceSets, headers);
+ }
+ });
+ }
+
+ private void updateHeaderDirs(DomainObjectSet<HeaderExportingSourceSet> sourceSets, DefaultSourceDirectorySet headers) {
+ List<SourceDirectorySet> headerDirs = new ArrayList<SourceDirectorySet>();
+ for (HeaderExportingSourceSet sourceSet : sourceSets) {
+ headerDirs.add(sourceSet.getExportedHeaders());
+ }
+ headers.setSrcDirs(headerDirs);
+ }
+}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/DefaultLibraryContainer.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/DefaultLibraryContainer.java
new file mode 100644
index 0000000..b9fe4ae
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/DefaultLibraryContainer.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.internal;
+
+import org.gradle.api.internal.AbstractNamedDomainObjectContainer;
+import org.gradle.api.internal.file.FileResolver;
+import org.gradle.internal.reflect.Instantiator;
+import org.gradle.nativecode.base.Library;
+import org.gradle.nativecode.base.LibraryContainer;
+
+public class DefaultLibraryContainer extends AbstractNamedDomainObjectContainer<Library> implements LibraryContainer {
+ private final FileResolver fileResolver;
+
+ public DefaultLibraryContainer(Instantiator instantiator, FileResolver fileResolver) {
+ super(Library.class, instantiator);
+ this.fileResolver = fileResolver;
+ }
+
+ @Override
+ protected Library doCreate(String name) {
+ return getInstantiator().newInstance(DefaultLibrary.class, name, getInstantiator(), fileResolver);
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/DefaultLibraryResolver.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/DefaultLibraryResolver.java
new file mode 100644
index 0000000..ab7d8ea
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/DefaultLibraryResolver.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.internal;
+
+import org.gradle.api.InvalidUserDataException;
+import org.gradle.nativecode.base.*;
+
+class DefaultLibraryResolver implements ConfigurableLibraryResolver {
+ private Flavor flavor = Flavor.DEFAULT;
+ private Class<? extends LibraryBinary> type = SharedLibraryBinary.class;
+ private Library library;
+
+ public DefaultLibraryResolver(Library library) {
+ this.library = library;
+ }
+
+ public ConfigurableLibraryResolver withFlavor(Flavor flavor) {
+ this.flavor = flavor;
+ return this;
+ }
+
+ public ConfigurableLibraryResolver withType(Class<? extends LibraryBinary> type) {
+ this.type = type;
+ return this;
+ }
+
+ public NativeDependencySet resolve() {
+ for (LibraryBinary candidate : library.getBinaries().withType(type)) {
+ // If the library has only 1 flavor, then flavor is not important
+ if (library.getFlavors().size() == 1) {
+ return candidate.resolve();
+ }
+ // Otherwise match on the flavor
+ if (flavor.equals(candidate.getFlavor())) {
+ return candidate.resolve();
+ }
+ }
+
+ String typeName = type == SharedLibraryBinary.class ? "shared" : "static";
+ throw new InvalidUserDataException(String.format("No %s library binary available for %s with %s", typeName, library, flavor));
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/DefaultNativeBinary.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/DefaultNativeBinary.java
new file mode 100644
index 0000000..9b06538
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/DefaultNativeBinary.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.internal;
+
+import org.gradle.api.Action;
+import org.gradle.api.DomainObjectSet;
+import org.gradle.api.internal.DefaultDomainObjectSet;
+import org.gradle.api.internal.notations.api.NotationParser;
+import org.gradle.language.base.LanguageSourceSet;
+import org.gradle.language.base.internal.AbstractBuildableModelElement;
+import org.gradle.language.base.internal.BinaryNamingScheme;
+import org.gradle.language.base.internal.DefaultBinaryNamingScheme;
+import org.gradle.nativecode.base.Flavor;
+import org.gradle.nativecode.base.NativeComponent;
+import org.gradle.nativecode.base.NativeDependencySet;
+import org.gradle.nativecode.base.tasks.BuildBinaryTask;
+
+import java.io.File;
+import java.util.*;
+
+public abstract class DefaultNativeBinary extends AbstractBuildableModelElement implements NativeBinaryInternal {
+ private final NotationParser<Set<LanguageSourceSet>> sourcesNotationParser = SourceSetNotationParser.parser();
+ private final ResolvableNativeDependencySet libs = new ResolvableNativeDependencySet();
+ private final DomainObjectSet<LanguageSourceSet> source = new DefaultDomainObjectSet<LanguageSourceSet>(LanguageSourceSet.class);
+ private final ArrayList<Object> compilerArgs = new ArrayList<Object>();
+ private final ArrayList<Object> assemblerArgs = new ArrayList<Object>();
+ private final ArrayList<Object> linkerArgs = new ArrayList<Object>();
+ private final ArrayList<Object> defines = new ArrayList<Object>();
+ private final BinaryNamingScheme namingScheme;
+ private final Flavor flavor;
+ private final ToolChainInternal toolChain;
+ private BuildBinaryTask builderTask;
+ private File outputFile;
+
+ protected DefaultNativeBinary(NativeComponent owner, Flavor flavor, ToolChainInternal toolChain, DefaultBinaryNamingScheme namingScheme) {
+ this.namingScheme = namingScheme;
+ this.flavor = flavor;
+ this.toolChain = toolChain;
+ owner.getSource().all(new Action<LanguageSourceSet>() {
+ public void execute(LanguageSourceSet sourceSet) {
+ source.add(sourceSet);
+ }
+ });
+ }
+
+ @Override
+ public String toString() {
+ return namingScheme.getDescription();
+ }
+
+ public Flavor getFlavor() {
+ return flavor;
+ }
+
+ public BuildBinaryTask getBuilderTask() {
+ return builderTask;
+ }
+
+ public void setBuilderTask(BuildBinaryTask builderTask) {
+ this.builderTask = builderTask;
+ dependsOn(builderTask);
+ }
+
+ public String getName() {
+ return namingScheme.getLifecycleTaskName();
+ }
+
+ public ToolChainInternal getToolChain() {
+ return toolChain;
+ }
+
+ public File getOutputFile() {
+ return outputFile;
+ }
+
+ public void setOutputFile(File outputFile) {
+ this.outputFile = outputFile;
+ }
+
+ public DomainObjectSet<LanguageSourceSet> getSource() {
+ return source;
+ }
+
+ public void source(Object sources) {
+ source.addAll(sourcesNotationParser.parseNotation(sources));
+ }
+
+ public List<Object> getMacros() {
+ return defines;
+ }
+
+ public void define(Object... defines) {
+ Collections.addAll(this.defines, defines);
+ }
+
+ public List<Object> getCompilerArgs() {
+ return compilerArgs;
+ }
+
+ public void compilerArgs(Object... args) {
+ Collections.addAll(compilerArgs, args);
+ }
+
+ public List<Object> getAssemblerArgs() {
+ return assemblerArgs;
+ }
+
+ public void assemblerArgs(Object... args) {
+ Collections.addAll(assemblerArgs, args);
+ }
+
+ public List<Object> getLinkerArgs() {
+ return linkerArgs;
+ }
+
+ public void linkerArgs(Object... args) {
+ Collections.addAll(linkerArgs, args);
+ }
+
+ public BinaryNamingScheme getNamingScheme() {
+ return namingScheme;
+ }
+
+ public Collection<NativeDependencySet> getLibs() {
+ return libs.resolve(this);
+ }
+
+ public void lib(Object notation) {
+ libs.add(notation);
+ }
+
+ public abstract String getOutputFileName();
+
+ protected abstract NativeComponent getComponent();
+
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/DefaultNativeComponent.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/DefaultNativeComponent.java
new file mode 100644
index 0000000..5ecb2d9
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/DefaultNativeComponent.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.internal;
+
+import org.gradle.api.Action;
+import org.gradle.api.DomainObjectSet;
+import org.gradle.api.internal.DefaultDomainObjectSet;
+import org.gradle.api.internal.notations.api.NotationParser;
+import org.gradle.internal.reflect.Instantiator;
+import org.gradle.language.base.LanguageSourceSet;
+import org.gradle.nativecode.base.FlavorContainer;
+import org.gradle.nativecode.base.NativeBinary;
+import org.gradle.nativecode.base.NativeComponent;
+import org.gradle.util.GUtil;
+
+import java.util.Set;
+
+public class DefaultNativeComponent implements NativeComponent {
+ private final NotationParser<Set<LanguageSourceSet>> sourcesNotationParser = SourceSetNotationParser.parser();
+ private final String name;
+ private final DomainObjectSet<LanguageSourceSet> sourceSets;
+ private final DefaultDomainObjectSet<NativeBinary> binaries;
+ private final DefaultFlavorContainer flavors;
+ private String baseName;
+
+ public DefaultNativeComponent(String name, Instantiator instantiator) {
+ this.name = name;
+ this.sourceSets = new DefaultDomainObjectSet<LanguageSourceSet>(LanguageSourceSet.class);
+ binaries = new DefaultDomainObjectSet<NativeBinary>(NativeBinary.class);
+ flavors = instantiator.newInstance(DefaultFlavorContainer.class, instantiator);
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public DomainObjectSet<LanguageSourceSet> getSource() {
+ return sourceSets;
+ }
+
+ public void source(Object sources) {
+ sourceSets.addAll(sourcesNotationParser.parseNotation(sources));
+ }
+
+ public DomainObjectSet<NativeBinary> getBinaries() {
+ return binaries;
+ }
+
+ public String getBaseName() {
+ return GUtil.elvis(baseName, name);
+ }
+
+ public void setBaseName(String baseName) {
+ this.baseName = baseName;
+ }
+
+ public FlavorContainer getFlavors() {
+ return flavors;
+ }
+
+ public void flavors(Action<FlavorContainer> config) {
+ config.execute(flavors);
+ }
+}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/DefaultSharedLibraryBinary.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/DefaultSharedLibraryBinary.java
new file mode 100644
index 0000000..ce8dcd6
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/DefaultSharedLibraryBinary.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.internal;
+
+import org.gradle.api.Buildable;
+import org.gradle.api.file.FileCollection;
+import org.gradle.api.internal.file.collections.FileCollectionAdapter;
+import org.gradle.api.internal.file.collections.MinimalFileSet;
+import org.gradle.api.tasks.TaskDependency;
+import org.gradle.language.base.internal.DefaultBinaryNamingScheme;
+import org.gradle.nativecode.base.*;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.Set;
+
+public class DefaultSharedLibraryBinary extends DefaultNativeBinary implements SharedLibraryBinary {
+ private final Library library;
+
+ public DefaultSharedLibraryBinary(Library library, Flavor flavor, ToolChainInternal toolChain, DefaultBinaryNamingScheme namingScheme) {
+ super(library, flavor, toolChain, namingScheme.withTypeString("SharedLibrary"));
+ this.library = library;
+ }
+
+ public Library getComponent() {
+ return library;
+ }
+
+ public String getOutputFileName() {
+ return getToolChain().getSharedLibraryName(getComponent().getBaseName());
+ }
+
+ private File getLinkFile() {
+ return new File(getToolChain().getSharedLibraryLinkFileName(getOutputFile().getPath()));
+ }
+
+ public NativeDependencySet resolve() {
+ return new NativeDependencySet() {
+ public FileCollection getIncludeRoots() {
+ return library.getHeaders();
+ }
+
+ public FileCollection getLinkFiles() {
+ return new FileCollectionAdapter(new RuntimeFiles(getLinkFile()));
+ }
+
+ public FileCollection getRuntimeFiles() {
+ return new FileCollectionAdapter(new RuntimeFiles(getOutputFile()));
+ }
+ };
+ }
+
+ private class RuntimeFiles implements MinimalFileSet, Buildable {
+ private final File outputFile;
+
+ private RuntimeFiles(File outputFile) {
+ this.outputFile = outputFile;
+ }
+
+ public Set<File> getFiles() {
+ return Collections.singleton(outputFile);
+ }
+
+ public String getDisplayName() {
+ return DefaultSharedLibraryBinary.this.toString();
+ }
+
+ public TaskDependency getBuildDependencies() {
+ return DefaultSharedLibraryBinary.this.getBuildDependencies();
+ }
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/DefaultStaticLibraryBinary.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/DefaultStaticLibraryBinary.java
new file mode 100644
index 0000000..346fd3b
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/DefaultStaticLibraryBinary.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.internal;
+
+import org.gradle.api.Buildable;
+import org.gradle.api.file.FileCollection;
+import org.gradle.api.internal.file.collections.FileCollectionAdapter;
+import org.gradle.api.internal.file.collections.MinimalFileSet;
+import org.gradle.api.internal.file.collections.SimpleFileCollection;
+import org.gradle.api.tasks.TaskDependency;
+import org.gradle.language.base.internal.DefaultBinaryNamingScheme;
+import org.gradle.nativecode.base.Flavor;
+import org.gradle.nativecode.base.Library;
+import org.gradle.nativecode.base.NativeDependencySet;
+import org.gradle.nativecode.base.StaticLibraryBinary;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+public class DefaultStaticLibraryBinary extends DefaultNativeBinary implements StaticLibraryBinary {
+ private final Library library;
+ private final ArrayList<Object> staticLibArgs = new ArrayList<Object>();
+
+ public DefaultStaticLibraryBinary(Library library, Flavor flavor, ToolChainInternal toolChain, DefaultBinaryNamingScheme namingScheme) {
+ super(library, flavor, toolChain, namingScheme.withTypeString("StaticLibrary"));
+ this.library = library;
+ }
+
+ public Library getComponent() {
+ return library;
+ }
+
+ public String getOutputFileName() {
+ return getToolChain().getStaticLibraryName(getComponent().getBaseName());
+ }
+
+ public List<Object> getStaticLibArgs() {
+ return staticLibArgs;
+ }
+
+ public void staticLibArgs(Object... args) {
+ Collections.addAll(staticLibArgs, args);
+ }
+
+ public NativeDependencySet resolve() {
+ return new NativeDependencySet() {
+ public FileCollection getIncludeRoots() {
+ return library.getHeaders();
+ }
+
+ public FileCollection getLinkFiles() {
+ return new FileCollectionAdapter(new LibraryFile());
+ }
+
+ public FileCollection getRuntimeFiles() {
+ return new SimpleFileCollection() {
+ @Override
+ public String getDisplayName() {
+ return DefaultStaticLibraryBinary.this.toString();
+ }
+ };
+ }
+ };
+ }
+
+ private class LibraryFile implements MinimalFileSet, Buildable {
+ public Set<File> getFiles() {
+ return Collections.singleton(getOutputFile());
+ }
+
+ public String getDisplayName() {
+ return DefaultStaticLibraryBinary.this.toString();
+ }
+
+ public TaskDependency getBuildDependencies() {
+ return DefaultStaticLibraryBinary.this.getBuildDependencies();
+ }
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/DefaultToolChainRegistry.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/DefaultToolChainRegistry.java
new file mode 100755
index 0000000..3ab1d4c
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/DefaultToolChainRegistry.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.internal;
+
+import groovy.lang.Closure;
+import org.gradle.api.InvalidUserDataException;
+import org.gradle.api.internal.AbstractNamedDomainObjectContainer;
+import org.gradle.api.internal.DefaultPolymorphicDomainObjectContainer;
+import org.gradle.api.internal.tasks.compile.Compiler;
+import org.gradle.internal.os.OperatingSystem;
+import org.gradle.internal.reflect.Instantiator;
+import org.gradle.nativecode.base.ToolChain;
+import org.gradle.nativecode.base.ToolChainRegistry;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+// TODO:DAZ Need a better way of having a container with defaults. Similar for FlavorContainer.
+// Probably need a separate container for defaults and registered, and then have a simple delegating container, or factory.
+public class DefaultToolChainRegistry extends DefaultPolymorphicDomainObjectContainer<ToolChain> implements ToolChainRegistry {
+ private ToolChain defaultToolChain;
+
+ public DefaultToolChainRegistry(Instantiator instantiator) {
+ super(ToolChain.class, instantiator);
+ }
+
+ @Override
+ protected void handleAttemptToAddItemWithNonUniqueName(ToolChain toolChain) {
+ throw new InvalidUserDataException(String.format("ToolChain with name '%s' added multiple times", toolChain.getName()));
+ }
+
+ public void registerDefaultToolChain(String name, Class<? extends ToolChain> type) {
+ if (isEmpty()) {
+ assertCanAdd(name);
+ ToolChain added = doCreate(name, type);
+ ToolChainInternal candidate = (ToolChainInternal) added;
+ if (candidate.getAvailability().isAvailable()) {
+ add(candidate);
+ }
+ defaultToolChain = candidate;
+ }
+ }
+
+ @Override
+ public boolean add(ToolChain o) {
+ removeDefault();
+ return super.add(o);
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends ToolChain> c) {
+ removeDefault();
+ return super.addAll(c);
+ }
+
+ @Override
+ public AbstractNamedDomainObjectContainer<ToolChain> configure(Closure configureClosure) {
+ removeDefault();
+ return super.configure(configureClosure);
+ }
+
+ private void removeDefault() {
+ if (defaultToolChain != null) {
+ remove(defaultToolChain);
+ defaultToolChain = null;
+ }
+ }
+
+ public List<ToolChainInternal> getAvailableToolChains() {
+ List<ToolChainInternal> availableToolChains = new ArrayList<ToolChainInternal>();
+ List<String> messages = new ArrayList<String>();
+ for (ToolChainInternal toolChain : this.withType(ToolChainInternal.class)) {
+ ToolChainAvailability availability = toolChain.getAvailability();
+ if (availability.isAvailable()) {
+ availableToolChains.add(toolChain);
+ }
+ messages.add(String.format("Could not load '%s': %s", toolChain.getName(), availability.getUnavailableMessage()));
+ }
+ if (availableToolChains.isEmpty()) {
+ availableToolChains.add(new UnavailableToolChain(messages));
+ }
+ return availableToolChains;
+ }
+
+ public ToolChainInternal getDefaultToolChain() {
+ return getAvailableToolChains().get(0);
+ }
+
+ private static class UnavailableToolChain implements ToolChainInternal {
+ private final List<String> messages;
+ private final OperatingSystem operatingSystem = OperatingSystem.current();
+
+ public UnavailableToolChain(List<String> messages) {
+ this.messages = messages;
+ }
+
+ public String getName() {
+ return "unavailable";
+ }
+
+ private IllegalStateException failure() {
+ return new IllegalStateException(String.format("No tool chain is available: %s", messages));
+ }
+
+ public <T extends BinaryToolSpec> Compiler<T> createCppCompiler() {
+ throw failure();
+ }
+
+ public <T extends BinaryToolSpec> Compiler<T> createCCompiler() {
+ throw failure();
+ }
+
+ public <T extends BinaryToolSpec> Compiler<T> createAssembler() {
+ throw failure();
+ }
+
+ public <T extends LinkerSpec> Compiler<T> createLinker() {
+ throw failure();
+ }
+
+ public <T extends StaticLibraryArchiverSpec> Compiler<T> createStaticLibraryArchiver() {
+ throw failure();
+ }
+
+ public ToolChainAvailability getAvailability() {
+ return new ToolChainAvailability().unavailable("No tool chain is available.");
+ }
+
+ public String getExecutableName(String executablePath) {
+ return operatingSystem.getExecutableName(executablePath);
+ }
+
+ public String getSharedLibraryName(String libraryName) {
+ return operatingSystem.getSharedLibraryName(libraryName);
+ }
+
+ public String getSharedLibraryLinkFileName(String libraryName) {
+ return getSharedLibraryName(libraryName);
+ }
+
+ public String getStaticLibraryName(String libraryName) {
+ return operatingSystem.getStaticLibraryName(libraryName);
+ }
+
+ public String getOutputType() {
+ throw failure();
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/ExecutableLinkerSpec.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/ExecutableLinkerSpec.java
new file mode 100644
index 0000000..f046c1e
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/ExecutableLinkerSpec.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.internal;
+
+public interface ExecutableLinkerSpec extends LinkerSpec {
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/LinkerSpec.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/LinkerSpec.java
new file mode 100644
index 0000000..240750f
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/LinkerSpec.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.internal;
+
+import java.io.File;
+
+/**
+ * A high level interface to the compiler, specifying what is to be compiled and how.
+ */
+public interface LinkerSpec extends BinaryToolSpec {
+
+ Iterable<File> getSource();
+
+ void setSource(Iterable<File> source);
+
+ Iterable<File> getLibs();
+
+ void setLibs(Iterable<File> libs);
+
+ Iterable<String> getArgs();
+
+ void setArgs(Iterable<String> args);
+
+ File getOutputFile();
+
+ void setOutputFile(File outputFile);
+
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/NativeBinaryFactory.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/NativeBinaryFactory.java
new file mode 100644
index 0000000..06ab153
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/NativeBinaryFactory.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.internal;
+
+import org.gradle.api.Project;
+import org.gradle.internal.reflect.Instantiator;
+import org.gradle.language.base.internal.DefaultBinaryNamingScheme;
+import org.gradle.nativecode.base.Flavor;
+import org.gradle.nativecode.base.NativeComponent;
+import org.gradle.nativecode.base.ToolChain;
+
+import java.io.File;
+import java.util.Collection;
+
+class NativeBinaryFactory {
+ private final Instantiator instantiator;
+ private final Project project;
+ private final boolean useToolChainDimension;
+
+ public NativeBinaryFactory(Instantiator instantiator, Project project, Collection<? extends ToolChain> allToolChains) {
+ this.instantiator = instantiator;
+ this.project = project;
+ this.useToolChainDimension = allToolChains.size() > 1;
+ }
+
+ public <T extends DefaultNativeBinary> T createNativeBinary(Class<T> type, NativeComponent component, ToolChain toolChain, Flavor flavor) {
+ DefaultBinaryNamingScheme namingScheme = createNamingScheme(component, useToolChainDimension, toolChain, flavor);
+ T nativeBinary = instantiator.newInstance(type, component, flavor, toolChain, namingScheme);
+ setupDefaults(project, nativeBinary);
+ component.getBinaries().add(nativeBinary);
+ return nativeBinary;
+ }
+
+ private DefaultBinaryNamingScheme createNamingScheme(NativeComponent component, boolean useToolChainDimension, ToolChain toolChain, Flavor flavor) {
+ DefaultBinaryNamingScheme namingScheme = new DefaultBinaryNamingScheme(component.getName());
+ if (useToolChainDimension) {
+ namingScheme = namingScheme.withVariantDimension(toolChain.getName());
+ }
+ if (component.getFlavors().size() > 1) {
+ namingScheme = namingScheme.withVariantDimension(flavor.getName());
+ }
+ return namingScheme;
+ }
+
+
+ private void setupDefaults(Project project, DefaultNativeBinary nativeBinary) {
+ nativeBinary.setOutputFile(new File(project.getBuildDir(), "binaries/" + nativeBinary.getNamingScheme().getOutputDirectoryBase() + "/" + nativeBinary.getOutputFileName()));
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/NativeBinaryInternal.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/NativeBinaryInternal.java
new file mode 100644
index 0000000..f294c1e
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/NativeBinaryInternal.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.internal;
+
+import org.gradle.language.base.internal.BinaryInternal;
+import org.gradle.nativecode.base.NativeBinary;
+import org.gradle.nativecode.base.tasks.BuildBinaryTask;
+
+public interface NativeBinaryInternal extends NativeBinary, BinaryInternal {
+ // TODO:DAZ Develop this concept further, so we can do eg. 'executable.tasks.link'
+ void setBuilderTask(BuildBinaryTask task);
+ BuildBinaryTask getBuilderTask();
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/ResolvableNativeDependencySet.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/ResolvableNativeDependencySet.java
new file mode 100644
index 0000000..f5253f4
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/ResolvableNativeDependencySet.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.internal;
+
+import org.gradle.api.InvalidUserDataException;
+import org.gradle.nativecode.base.Library;
+import org.gradle.nativecode.base.LibraryResolver;
+import org.gradle.nativecode.base.NativeBinary;
+import org.gradle.nativecode.base.NativeDependencySet;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+public class ResolvableNativeDependencySet {
+ private final List<Object> libs = new ArrayList<Object>();
+
+ public void add(Object lib) {
+ this.libs.add(lib);
+ }
+
+ public Collection<NativeDependencySet> resolve(NativeBinary target) {
+ List<NativeDependencySet> result = new ArrayList<NativeDependencySet>();
+ for (Object lib : libs) {
+ result.add(resolve(target, lib));
+ resolve(target, lib);
+ }
+ return result;
+ }
+
+ private NativeDependencySet resolve(NativeBinary target, Object lib) {
+ if (lib instanceof NativeDependencySet) {
+ return (NativeDependencySet) lib;
+ }
+ if (lib instanceof Library) {
+ return resolve(target, ((Library) lib).getShared());
+ }
+ if (lib instanceof ConfigurableLibraryResolver) {
+ return ((ConfigurableLibraryResolver) lib).withFlavor(target.getFlavor()).resolve();
+ }
+ if (lib instanceof LibraryResolver) {
+ return ((LibraryResolver) lib).resolve();
+ }
+
+ throw new InvalidUserDataException("Not a valid type for a library dependency: " + lib);
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/SharedLibraryLinkerSpec.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/SharedLibraryLinkerSpec.java
new file mode 100644
index 0000000..9a673cd
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/SharedLibraryLinkerSpec.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.internal;
+
+public interface SharedLibraryLinkerSpec extends LinkerSpec {
+ String getInstallName();
+
+ void setInstallName(String path);
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/SourceSetNotationParser.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/SourceSetNotationParser.java
new file mode 100644
index 0000000..c6a68bb
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/SourceSetNotationParser.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.internal;
+
+import org.gradle.api.internal.notations.NotationParserBuilder;
+import org.gradle.api.internal.notations.TypeInfo;
+import org.gradle.api.internal.notations.api.NotationParser;
+import org.gradle.api.internal.notations.parsers.TypedNotationParser;
+import org.gradle.language.base.FunctionalSourceSet;
+import org.gradle.language.base.LanguageSourceSet;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+public class SourceSetNotationParser {
+ public static NotationParser<Set<LanguageSourceSet>> parser() {
+ return new NotationParserBuilder<Set<LanguageSourceSet>>()
+ .resultingType(new TypeInfo<Set<LanguageSourceSet>>(Set.class))
+ .parser(new FunctionalSourceSetConverter())
+ .parser(new SingleLanguageSourceSetConverter())
+ .parser(new LanguageSourceSetCollectionConverter())
+ .toComposite();
+ }
+
+ private static class FunctionalSourceSetConverter extends TypedNotationParser<FunctionalSourceSet, Set<LanguageSourceSet>> {
+ private FunctionalSourceSetConverter() {
+ super(FunctionalSourceSet.class);
+ }
+
+ @Override
+ protected Set<LanguageSourceSet> parseType(FunctionalSourceSet notation) {
+ return notation;
+ }
+ }
+
+ private static class SingleLanguageSourceSetConverter extends TypedNotationParser<LanguageSourceSet, Set<LanguageSourceSet>> {
+ private SingleLanguageSourceSetConverter() {
+ super(LanguageSourceSet.class);
+ }
+
+ @Override
+ protected Set<LanguageSourceSet> parseType(LanguageSourceSet notation) {
+ return Collections.singleton(notation);
+ }
+ }
+
+ private static class LanguageSourceSetCollectionConverter extends TypedNotationParser<Collection<LanguageSourceSet>, Set<LanguageSourceSet>> {
+ private LanguageSourceSetCollectionConverter() {
+ super(new TypeInfo<Collection<LanguageSourceSet>>(Collection.class));
+ }
+
+ @Override
+ protected Set<LanguageSourceSet> parseType(Collection<LanguageSourceSet> notation) {
+ return new HashSet<LanguageSourceSet>(notation);
+ }
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/StaticLibraryArchiverSpec.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/StaticLibraryArchiverSpec.java
new file mode 100644
index 0000000..051ca97
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/StaticLibraryArchiverSpec.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.internal;
+
+import java.io.File;
+
+public interface StaticLibraryArchiverSpec extends BinaryToolSpec {
+
+ Iterable<File> getSource();
+
+ void setSource(Iterable<File> source);
+
+ File getOutputFile();
+
+ void setOutputFile(File outputFile);
+
+ Iterable<String> getArgs();
+
+ void setArgs(Iterable<String> args);
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/ToolChainAvailability.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/ToolChainAvailability.java
new file mode 100644
index 0000000..0cc344c
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/ToolChainAvailability.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.internal;
+
+import java.io.File;
+
+public class ToolChainAvailability {
+ private String unavailableMessage;
+
+ public ToolChainAvailability() {
+ unavailableMessage = null;
+ }
+
+ public boolean isAvailable() {
+ return unavailableMessage == null;
+ }
+
+ public String getUnavailableMessage() {
+ return unavailableMessage;
+ }
+
+ public void mustExist(String toolName, File tool) {
+ if (this.unavailableMessage == null && (tool == null || !tool.exists())) {
+ this.unavailableMessage = String.format("%s cannot be found", toolName);
+ }
+ }
+
+ public ToolChainAvailability unavailable(String unavailableMessage) {
+ if (this.unavailableMessage == null) {
+ this.unavailableMessage = unavailableMessage;
+ }
+ return this;
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/ToolChainInternal.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/ToolChainInternal.java
new file mode 100644
index 0000000..0f9456a
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/internal/ToolChainInternal.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.internal;
+
+import org.gradle.api.internal.tasks.compile.Compiler;
+import org.gradle.nativecode.base.ToolChain;
+
+public interface ToolChainInternal extends ToolChain {
+ ToolChainAvailability getAvailability();
+
+ <T extends BinaryToolSpec> Compiler<T> createCppCompiler();
+
+ <T extends BinaryToolSpec> Compiler<T> createCCompiler();
+
+ <T extends BinaryToolSpec> Compiler<T> createAssembler();
+
+ <T extends LinkerSpec> Compiler<T> createLinker();
+
+ <T extends StaticLibraryArchiverSpec> Compiler<T> createStaticLibraryArchiver();
+
+ String getExecutableName(String executablePath);
+
+ String getSharedLibraryName(String libraryPath);
+
+ String getSharedLibraryLinkFileName(String libraryPath);
+
+ String getStaticLibraryName(String libraryPath);
+
+ /**
+ * Returns a unique identifier for the output produced by this toolchain on the current platform.
+ */
+ String getOutputType();
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/package-info.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/package-info.java
new file mode 100644
index 0000000..6f1dc97
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+/**
+ * Classes that model aspects of native component projects.
+ */
+package org.gradle.nativecode.base;
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/plugins/NativeBinariesModelPlugin.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/plugins/NativeBinariesModelPlugin.java
new file mode 100644
index 0000000..fb862d7
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/plugins/NativeBinariesModelPlugin.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.plugins;
+
+import org.gradle.api.*;
+import org.gradle.api.internal.file.FileResolver;
+import org.gradle.api.plugins.BasePlugin;
+import org.gradle.configuration.project.ProjectConfigurationActionContainer;
+import org.gradle.internal.reflect.Instantiator;
+import org.gradle.language.base.plugins.LanguageBasePlugin;
+import org.gradle.nativecode.base.internal.*;
+
+import javax.inject.Inject;
+
+/**
+ * A plugin that sets up the infrastructure for defining native binaries.
+ */
+ at Incubating
+public class NativeBinariesModelPlugin implements Plugin<Project> {
+ private final Instantiator instantiator;
+ private final ProjectConfigurationActionContainer configurationActions;
+ private final FileResolver fileResolver;
+
+ @Inject
+ public NativeBinariesModelPlugin(Instantiator instantiator, ProjectConfigurationActionContainer configurationActions, FileResolver fileResolver) {
+ this.instantiator = instantiator;
+ this.configurationActions = configurationActions;
+ this.fileResolver = fileResolver;
+ }
+
+ public void apply(final Project project) {
+ project.getPlugins().apply(BasePlugin.class);
+ project.getPlugins().apply(LanguageBasePlugin.class);
+
+ project.getExtensions().create("toolChains",
+ DefaultToolChainRegistry.class,
+ instantiator
+ );
+ project.getExtensions().create(
+ "executables",
+ DefaultExecutableContainer.class,
+ instantiator
+ );
+
+ project.getExtensions().create(
+ "libraries",
+ DefaultLibraryContainer.class,
+ instantiator,
+ fileResolver
+ );
+
+ configurationActions.add(new CreateNativeBinariesAction(instantiator));
+ }
+
+}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/plugins/NativeBinariesPlugin.groovy b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/plugins/NativeBinariesPlugin.groovy
new file mode 100644
index 0000000..f781e95
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/plugins/NativeBinariesPlugin.groovy
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.plugins
+
+import org.gradle.api.Incubating
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.api.internal.project.ProjectInternal
+import org.gradle.api.plugins.BasePlugin
+import org.gradle.language.base.BinaryContainer
+import org.gradle.nativecode.base.*
+import org.gradle.nativecode.base.internal.NativeBinaryInternal
+import org.gradle.nativecode.base.tasks.*
+
+/**
+ * A plugin that creates tasks used for constructing native binaries.
+ */
+ at Incubating
+public class NativeBinariesPlugin implements Plugin<Project> {
+
+ public void apply(final Project project) {
+ project.getPlugins().apply(NativeBinariesModelPlugin.class);
+ final BinaryContainer binaries = project.getExtensions().getByType(BinaryContainer.class);
+
+ binaries.withType(NativeBinary) { NativeBinaryInternal binary ->
+ bindSourceSetLibsToBinary(binary)
+ createTasks(project, binary)
+ }
+ }
+
+ private static void bindSourceSetLibsToBinary(NativeBinaryInternal binary) {
+ // TODO:DAZ Move this logic into NativeBinary (once we have laziness sorted)
+ binary.source.withType(DependentSourceSet).all { DependentSourceSet sourceSet ->
+ sourceSet.libs.each { lib ->
+ binary.lib lib
+ }
+ }
+ }
+
+ def createTasks(ProjectInternal project, NativeBinaryInternal binary) {
+ BuildBinaryTask buildBinaryTask
+ if (binary instanceof StaticLibraryBinary) {
+ buildBinaryTask = createStaticLibraryTask(project, binary)
+ } else {
+ buildBinaryTask = createLinkTask(project, binary)
+ }
+ binary.builderTask = buildBinaryTask
+
+ if (binary instanceof ExecutableBinary) {
+ createInstallTask(project, (NativeBinaryInternal) binary);
+ }
+ }
+
+ private AbstractLinkTask createLinkTask(ProjectInternal project, NativeBinaryInternal binary) {
+ AbstractLinkTask linkTask = project.task(binary.namingScheme.getTaskName("link"), type: linkTaskType(binary)) {
+ description = "Links ${binary}"
+ group = BasePlugin.BUILD_GROUP
+ }
+
+ linkTask.toolChain = binary.toolChain
+
+ binary.libs.each { NativeDependencySet lib ->
+ linkTask.lib lib.linkFiles
+ }
+
+ linkTask.conventionMapping.outputFile = { binary.outputFile }
+ linkTask.conventionMapping.linkerArgs = { binary.linkerArgs }
+ return linkTask
+ }
+
+ private static Class<? extends AbstractLinkTask> linkTaskType(NativeBinary binary) {
+ if (binary instanceof SharedLibraryBinary) {
+ return LinkSharedLibrary
+ }
+ return LinkExecutable
+ }
+
+ private CreateStaticLibrary createStaticLibraryTask(ProjectInternal project, StaticLibraryBinary binary) {
+ def namingScheme = ((NativeBinaryInternal) binary).namingScheme
+ CreateStaticLibrary task = project.task(namingScheme.getTaskName("create"), type: CreateStaticLibrary) {
+ description = "Creates ${binary}"
+ group = BasePlugin.BUILD_GROUP
+ }
+
+ task.toolChain = binary.toolChain
+ task.conventionMapping.outputFile = { binary.outputFile }
+ task.conventionMapping.staticLibArgs = { binary.staticLibArgs }
+ return task
+ }
+
+ def createInstallTask(ProjectInternal project, NativeBinaryInternal executable) {
+ InstallExecutable installTask = project.task(executable.namingScheme.getTaskName("install"), type: InstallExecutable) {
+ description = "Installs a development image of $executable"
+ group = BasePlugin.BUILD_GROUP
+ }
+
+ installTask.toolChain = executable.toolChain
+ installTask.conventionMapping.destinationDir = { project.file("${project.buildDir}/install/$executable.namingScheme.outputDirectoryBase") }
+
+ installTask.conventionMapping.executable = { executable.outputFile }
+ installTask.lib { executable.libs*.runtimeFiles }
+
+ installTask.dependsOn(executable)
+ }
+}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/plugins/package-info.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/plugins/package-info.java
new file mode 100644
index 0000000..914053b
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/plugins/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+/**
+ * Plugins for building native component projects.
+ */
+package org.gradle.nativecode.base.plugins;
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/tasks/AbstractLinkTask.groovy b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/tasks/AbstractLinkTask.groovy
new file mode 100644
index 0000000..4af99c9
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/tasks/AbstractLinkTask.groovy
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.tasks
+
+import org.gradle.api.DefaultTask
+import org.gradle.api.Incubating
+import org.gradle.api.file.FileCollection
+import org.gradle.api.tasks.*
+import org.gradle.language.jvm.internal.SimpleStaleClassCleaner
+import org.gradle.nativecode.base.ToolChain
+import org.gradle.nativecode.base.internal.LinkerSpec
+
+import javax.inject.Inject
+
+ at Incubating
+abstract class AbstractLinkTask extends DefaultTask implements BuildBinaryTask {
+ private FileCollection source
+
+ @Inject
+ AbstractLinkTask() {
+ libs = project.files()
+ source = project.files()
+ }
+
+ /**
+ * The tool chain used for linking.
+ */
+ ToolChain toolChain
+
+ // Invalidate output when the tool chain output changes
+ @Input
+ def getOutputType() {
+ return toolChain.outputType
+ }
+
+ // To pick up auxiliary files produced alongside the main output file
+ @OutputDirectory
+ File getDestinationDir() {
+ return getOutputFile().parentFile
+ }
+
+ /**
+ * The file where the linked binary will be located.
+ */
+ @OutputFile
+ File outputFile
+
+ /**
+ * Additional arguments passed to the linker.
+ */
+ @Input
+ List<String> linkerArgs
+
+ /**
+ * The source object files to be passed to the linker.
+ */
+ @InputFiles @SkipWhenEmpty // Can't use field due to GRADLE-2026
+ FileCollection getSource() {
+ source
+ }
+
+ /**
+ * The library files to be passed to the linker.
+ */
+ @InputFiles
+ FileCollection libs
+
+ /**
+ * Adds a set of object files to be linked.
+ * The provided source object is evaluated as per {@link org.gradle.api.Project#files(Object...)}.
+ */
+ void source(Object source) {
+ this.source.from source
+ }
+
+ /**
+ * Adds a set of library files to be linked.
+ * The provided libs object is evaluated as per {@link org.gradle.api.Project#files(Object...)}.
+ */
+ void lib(Object libs) {
+ this.libs.from libs
+ }
+
+ @TaskAction
+ void link() {
+ def cleaner = new SimpleStaleClassCleaner(getOutputs())
+ cleaner.setDestinationDir(getDestinationDir())
+ cleaner.execute()
+
+ def spec = createLinkerSpec()
+ spec.tempDir = getTemporaryDir()
+
+ spec.outputFile = getOutputFile()
+ spec.source = getSource()
+ spec.libs = getLibs()
+ spec.args = getLinkerArgs()
+
+ def result = toolChain.createLinker().execute(spec)
+ didWork = result.didWork
+ }
+
+ protected abstract LinkerSpec createLinkerSpec();
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/tasks/BuildBinaryTask.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/tasks/BuildBinaryTask.java
new file mode 100644
index 0000000..2ce0e3f
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/tasks/BuildBinaryTask.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.tasks;
+
+/**
+ * A task that combines a set of object files into a single binary.
+ */
+public interface BuildBinaryTask {
+ /**
+ * Adds a set of object files to be combined into the file binary.
+ * The provided source object is evaluated as per {@link org.gradle.api.Project#files(Object...)}.
+ */
+ void source(Object source);
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/tasks/CreateStaticLibrary.groovy b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/tasks/CreateStaticLibrary.groovy
new file mode 100644
index 0000000..ffea788
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/tasks/CreateStaticLibrary.groovy
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.tasks
+
+import org.gradle.api.DefaultTask
+import org.gradle.api.Incubating
+import org.gradle.api.file.FileCollection
+import org.gradle.api.tasks.Input
+import org.gradle.api.tasks.InputFiles
+import org.gradle.api.tasks.OutputFile
+import org.gradle.api.tasks.SkipWhenEmpty
+import org.gradle.api.tasks.TaskAction
+import org.gradle.nativecode.base.ToolChain
+import org.gradle.nativecode.base.internal.StaticLibraryArchiverSpec
+
+import javax.inject.Inject
+
+/**
+ * Assembles a static library from object files.
+ */
+ at Incubating
+class CreateStaticLibrary extends DefaultTask implements BuildBinaryTask {
+ private FileCollection source
+
+ @Inject
+ CreateStaticLibrary() {
+ source = project.files()
+ }
+
+ /**
+ * The tool chain used for creating the static library.
+ */
+ ToolChain toolChain
+
+ // Invalidate output when the tool chain output changes
+ @Input
+ def getOutputType() {
+ return toolChain.outputType
+ }
+
+ /**
+ * The file where the output binary will be located.
+ */
+ @OutputFile
+ File outputFile
+
+ /**
+ * The source object files to be passed to the archiver.
+ */
+ @InputFiles @SkipWhenEmpty // Can't use field due to GRADLE-2026
+ FileCollection getSource() {
+ source
+ }
+
+ /**
+ * Adds a set of object files to be linked.
+ * <p>
+ * The provided source object is evaluated as per {@link org.gradle.api.Project#files(Object...)}.
+ */
+ void source(Object source) {
+ this.source.from source
+ }
+
+ /**
+ * Additional arguments passed to the archiver.
+ */
+ @Input
+ List<String> staticLibArgs
+
+ @TaskAction
+ void link() {
+ def spec = new Spec()
+ spec.tempDir = getTemporaryDir()
+
+ spec.outputFile = getOutputFile()
+ spec.source = getSource()
+ spec.args = getStaticLibArgs()
+
+ def result = toolChain.createStaticLibraryArchiver().execute(spec)
+ didWork = result.didWork
+ }
+
+ private static class Spec implements StaticLibraryArchiverSpec {
+ Iterable<File> source;
+ File outputFile;
+ File tempDir;
+ Iterable<String> args = new ArrayList<String>();
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/tasks/InstallExecutable.groovy b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/tasks/InstallExecutable.groovy
new file mode 100644
index 0000000..3d25648
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/tasks/InstallExecutable.groovy
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.tasks
+import org.gradle.api.Action
+import org.gradle.api.DefaultTask
+import org.gradle.api.Incubating
+import org.gradle.api.file.CopySpec
+import org.gradle.api.file.FileCollection
+import org.gradle.api.internal.file.FileOperations
+import org.gradle.api.tasks.InputFile
+import org.gradle.api.tasks.InputFiles
+import org.gradle.api.tasks.OutputDirectory
+import org.gradle.api.tasks.TaskAction
+import org.gradle.internal.nativeplatform.filesystem.FileSystem
+import org.gradle.internal.os.OperatingSystem
+import org.gradle.internal.reflect.Instantiator
+import org.gradle.nativecode.base.ToolChain
+import org.gradle.nativecode.toolchain.Gcc
+
+import javax.inject.Inject
+/**
+ * Installs an executable with it's dependent libraries so it can be easily executed.
+ */
+ at Incubating
+public class InstallExecutable extends DefaultTask {
+
+ private final Instantiator instantiator
+ private final FileOperations fileOperations
+
+ @Inject
+ InstallExecutable(Instantiator instantiator, FileOperations fileOperations) {
+ this.instantiator = instantiator
+ this.fileOperations = fileOperations
+ this.libs = project.files()
+ }
+
+ /**
+ * The tool chain used for linking.
+ */
+ ToolChain toolChain
+
+ /**
+ * The directory to install files into.
+ */
+ @OutputDirectory
+ File destinationDir
+
+ /**
+ * The executable file to install.
+ */
+ @InputFile
+ File executable
+
+ /**
+ * The library files that should be installed.
+ */
+ @InputFiles
+ FileCollection libs
+
+ /**
+ * Adds a set of library files to be installed.
+ * The provided libs object is evaluated as per {@link org.gradle.api.Project#files(Object...)}.
+ */
+ void lib(Object libs) {
+ this.libs.from libs
+ }
+
+ // TODO:DAZ Once we introduce a public type for OperatingSystem, make it configurable here
+ private OperatingSystem os = OperatingSystem.current()
+
+ @TaskAction
+ void install() {
+ if (os.windows) {
+ installWindows()
+ } else {
+ installUnix()
+ }
+ }
+
+ private void installWindows() {
+ final destination = getDestinationDir()
+ final File executable = getExecutable()
+
+ installToDir(new File(destination, "lib"))
+
+ StringBuilder toolChainPath = new StringBuilder()
+ if (toolChain in Gcc) {
+ // Gcc on windows requires the path to be set
+ toolChainPath.append("SET PATH=")
+ for (File path : ((Gcc) toolChain).paths) {
+ toolChainPath.append(path.absolutePath).append(";")
+ }
+ toolChainPath.append("%PATH%")
+ }
+
+ File script = new File(destination, os.getScriptName(executable.name));
+ script.text = """
+ at echo off
+SETLOCAL
+$toolChainPath
+CALL "%~dp0lib\\${executable.name}"
+
+ENDLOCAL
+"""
+ }
+
+ private void installUnix() {
+ final destination = getDestinationDir()
+ final executable = getExecutable()
+
+ installToDir(new File(destination, "lib"))
+
+ File script = new File(destination, executable.name);
+ script.text = """
+#/bin/sh
+APP_BASE_NAME=`dirname "\$0"`
+export DYLD_LIBRARY_PATH="\$APP_BASE_NAME/lib"
+export LD_LIBRARY_PATH="\$APP_BASE_NAME/lib"
+exec "\$APP_BASE_NAME/lib/${executable.name}" \"\$@\"
+"""
+
+ FileSystem fileSystem = getServices().get(FileSystem.class);
+ fileSystem.chmod(script, 0755)
+ }
+
+ private void installToDir(File binaryDir) {
+ fileOperations.sync(new Action<CopySpec>() {
+ void execute(CopySpec copySpec) {
+ copySpec.into(binaryDir)
+ copySpec.from(getExecutable())
+ copySpec.from(getLibs())
+ }
+ })
+ }
+
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/tasks/LinkExecutable.groovy b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/tasks/LinkExecutable.groovy
new file mode 100644
index 0000000..710cbbf
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/tasks/LinkExecutable.groovy
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.tasks
+import org.gradle.api.Incubating
+import org.gradle.nativecode.base.internal.ExecutableLinkerSpec
+import org.gradle.nativecode.base.internal.LinkerSpec
+
+/**
+ * Links a binary executable from object files and libraries.
+ */
+ at Incubating
+class LinkExecutable extends AbstractLinkTask {
+
+ @Override
+ protected LinkerSpec createLinkerSpec() {
+ return new Spec()
+ }
+
+ private static class Spec implements ExecutableLinkerSpec {
+ Iterable<File> libs;
+ Iterable<File> source;
+ File outputFile;
+ File tempDir;
+ Iterable<String> args = new ArrayList<String>();
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/tasks/LinkSharedLibrary.groovy b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/tasks/LinkSharedLibrary.groovy
new file mode 100644
index 0000000..b850d5a
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/tasks/LinkSharedLibrary.groovy
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.tasks
+import org.gradle.api.Incubating
+import org.gradle.nativecode.base.internal.LinkerSpec
+import org.gradle.nativecode.base.internal.SharedLibraryLinkerSpec
+
+/**
+ * Links a binary shared library from object files and imported libraries.
+ */
+ at Incubating
+class LinkSharedLibrary extends AbstractLinkTask {
+ @Override
+ protected LinkerSpec createLinkerSpec() {
+ return new Spec()
+ }
+
+ private static class Spec implements SharedLibraryLinkerSpec {
+ Iterable<File> libs;
+ Iterable<File> source;
+ File outputFile;
+ File tempDir;
+ Iterable<String> args = new ArrayList<String>();
+ String installName;
+
+ public String getInstallName() {
+ return installName == null ? getOutputFile().getName() : installName;
+ }
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/tasks/package-info.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/tasks/package-info.java
new file mode 100644
index 0000000..1aeb2d3
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/base/tasks/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+/**
+ * Tasks for building native component projects.
+ */
+package org.gradle.nativecode.base.tasks;
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/cdt/CdtIdePlugin.groovy b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/cdt/CdtIdePlugin.groovy
new file mode 100644
index 0000000..3601699
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/cdt/CdtIdePlugin.groovy
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.cdt
+
+import org.gradle.api.Incubating
+import org.gradle.api.Project
+import org.gradle.api.Plugin
+import org.gradle.api.InvalidUserDataException
+import org.gradle.api.tasks.Delete
+
+import org.gradle.nativecode.cdt.model.ProjectSettings
+import org.gradle.nativecode.cdt.model.ProjectDescriptor
+import org.gradle.nativecode.cdt.model.CprojectSettings
+import org.gradle.nativecode.cdt.model.CprojectDescriptor
+
+import org.gradle.nativecode.cdt.tasks.GenerateMetadataFileTask
+
+ at Incubating
+class CdtIdePlugin implements Plugin<Project> {
+
+ void apply(Project project) {
+ project.apply(plugin: "binaries")
+ def metadataFileTasks = [addCreateProjectDescriptor(project), addCreateCprojectDescriptor(project)]
+
+ project.task("cleanCdt", type: Delete) {
+ delete metadataFileTasks*.outputs*.files
+ }
+
+ project.task("cdt", dependsOn: metadataFileTasks)
+ }
+
+ private addCreateProjectDescriptor(Project project) {
+ project.task("cdtProject", type: GenerateMetadataFileTask) {
+ inputFile = project.file(".project")
+ outputFile = project.file(".project")
+ factory { new ProjectDescriptor() }
+ onConfigure { new ProjectSettings(name: project.name).applyTo(it) }
+ }
+ }
+
+ private addCreateCprojectDescriptor(Project project) {
+ project.task("cdtCproject", type: GenerateMetadataFileTask) { task ->
+
+ [project.executables, project.libraries]*.all { binary ->
+ if (binary.name == "main") {
+ task.settings = new CprojectSettings(binary, project)
+ }
+ }
+
+ doFirst {
+ if (task.settings == null) {
+ throw new InvalidUserDataException("There is neither a main binary or library")
+ }
+ }
+
+ inputs.files { task.settings.includeRoots }
+ inputFile = project.file(".cproject")
+ outputFile = project.file(".cproject")
+ factory { new CprojectDescriptor() }
+ onConfigure { descriptor ->
+ task.settings.applyTo(descriptor)
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/cdt/model/CprojectDescriptor.groovy b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/cdt/model/CprojectDescriptor.groovy
new file mode 100644
index 0000000..a0c01bf
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/cdt/model/CprojectDescriptor.groovy
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.cdt.model
+
+import org.gradle.api.Incubating
+import org.gradle.api.internal.xml.XmlTransformer
+import org.gradle.plugins.ide.internal.generator.XmlPersistableConfigurationObject
+
+/**
+ * The actual .cproject descriptor file.
+ */
+ at Incubating
+class CprojectDescriptor extends XmlPersistableConfigurationObject {
+
+ private static final boolean LINUX_NOT_MACOS = true
+
+ static public final String GNU_COMPILER_TOOL_ID_PREFIX = "cdt.managedbuild.tool.gnu.cpp.compiler"
+ static public final String GNU_COMPILER_TOOL_INCLUDE_PATHS_OPTION_PREFIX = "gnu.cpp.compiler.option.include.paths"
+
+ // linux
+ static public final String GNU_LINKER_TOOL_ID_PREFIX = LINUX_NOT_MACOS ? "cdt.managedbuild.tool.gnu.cpp.linker" : "cdt.managedbuild.tool.macosx.cpp.linker.macosx"
+ static public final String GNU_LINKER_TOOL_LIBS_PATHS_OPTION_PREFIX = LINUX_NOT_MACOS ? "gnu.cpp.link.option.userobjs" : "macosx.cpp.link.option.userobjs"
+
+ CprojectDescriptor() {
+ super(new XmlTransformer())
+ }
+
+ protected String getDefaultResourceName() {
+ LINUX_NOT_MACOS ? 'defaultCproject-linux.xml' : 'defaultCproject-macos.xml'
+ }
+
+ NodeList getConfigurations() {
+ new NodeList(xml.storageModule.cconfiguration.storageModule.findAll { it. at moduleId == "cdtBuildSystem" }.collect { it.configuration[0] })
+ }
+
+ NodeList getRootToolChains() {
+ new NodeList(configurations.folderInfo.findAll { it. at resourcePath == "" }).toolChain
+ }
+
+ NodeList getRootCppCompilerTools() {
+ new NodeList(rootToolChains.tool.findAll { isGnuCompilerTool(it) })
+ }
+
+ NodeList getRootCppLinkerTools() {
+ new NodeList(rootToolChains.tool.findAll { isGnuLinkerTool(it) })
+ }
+
+ boolean isGnuCompilerTool(Node node) {
+ node.name() == "tool" && node. at id.startsWith(GNU_COMPILER_TOOL_ID_PREFIX)
+ }
+
+ boolean isGnuLinkerTool(Node node) {
+ node.name() == "tool" && node. at id.startsWith(GNU_LINKER_TOOL_ID_PREFIX)
+ }
+
+ Node getOrCreateIncludePathsOption(compilerToolNode) {
+ if (!isGnuCompilerTool(compilerToolNode)) {
+ throw new IllegalArgumentException("Arg must be a gnu compiler tool def, was $compilerToolNode")
+ }
+
+ def includePathsOption = compilerToolNode.option.find { it. at id.startsWith(GNU_COMPILER_TOOL_INCLUDE_PATHS_OPTION_PREFIX) }
+ if (!includePathsOption) {
+ includePathsOption = compilerToolNode.appendNode(
+ "option", [
+ id: createId(GNU_COMPILER_TOOL_INCLUDE_PATHS_OPTION_PREFIX),
+ superClass: GNU_COMPILER_TOOL_INCLUDE_PATHS_OPTION_PREFIX,
+ valueType: "includePath"
+ ]
+ )
+ }
+
+ includePathsOption
+ }
+
+ Node getOrCreateLibsOption(linkerToolNode) {
+ if (!isGnuLinkerTool(linkerToolNode)) {
+ throw new IllegalArgumentException("Arg must be a gnu linker tool def, was $linkerToolNode")
+ }
+
+ def libsOption = linkerToolNode.option.find { it. at id.startsWith(GNU_LINKER_TOOL_LIBS_PATHS_OPTION_PREFIX) }
+ if (!libsOption) {
+ libsOption = linkerToolNode.appendNode(
+ "option", [
+ id: createId(GNU_LINKER_TOOL_LIBS_PATHS_OPTION_PREFIX),
+ superClass: GNU_LINKER_TOOL_LIBS_PATHS_OPTION_PREFIX,
+ valueType: "userObjs"
+ ]
+ )
+ }
+
+ libsOption
+ }
+
+ String createId(String prefix) {
+ prefix + "." + new java.text.SimpleDateFormat("yyMMddHHmmssS").format(new Date())
+ }
+
+ protected void store(Node xml) {
+ transformAction {
+ StringBuilder xmlString = it.asString()
+ xmlString.insert(xmlString.indexOf("\n") + 1, "<?fileVersion 4.0.0?>\n")
+ }
+ }
+}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/cdt/model/CprojectSettings.groovy b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/cdt/model/CprojectSettings.groovy
new file mode 100644
index 0000000..132c2d2
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/cdt/model/CprojectSettings.groovy
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.cdt.model
+
+import org.gradle.api.Incubating
+import org.gradle.api.file.ConfigurableFileCollection
+import org.gradle.api.internal.project.ProjectInternal
+import org.gradle.nativecode.base.Executable
+import org.gradle.nativecode.base.HeaderExportingSourceSet
+import org.gradle.nativecode.base.Library
+import org.gradle.nativecode.base.NativeComponent
+import org.gradle.nativecode.base.NativeDependencySet
+import org.gradle.nativecode.language.cpp.CppSourceSet
+
+/**
+ * Exposes a more logical view of the actual .cproject descriptor file
+ */
+ at Incubating
+// TODO:DAZ I'm sure this is now broken
+class CprojectSettings {
+
+ NativeComponent binary
+ private final ConfigurableFileCollection includeRoots
+ private final ConfigurableFileCollection libs
+
+ CprojectSettings(NativeComponent binary, ProjectInternal project) {
+ this.binary = binary
+ includeRoots = project.files()
+ libs = project.files()
+
+ binary.source.withType(HeaderExportingSourceSet).all {
+ includeRoots.builtBy(it.exportedHeaders) // have to manually add because we use srcDirs in from, not the real collection
+ includeRoots.from(it.exportedHeaders.srcDirs)
+ }
+
+ binary.source.withType(CppSourceSet).all { sourceSet ->
+ sourceSet.libs.each { NativeDependencySet lib ->
+ this.libs.from(lib.linkFiles)
+ this.includeRoots.from(lib.includeRoots)
+ }
+ }
+ }
+
+ void applyTo(CprojectDescriptor descriptor) {
+ if (binary) {
+ applyBinaryTo(descriptor)
+ } else {
+ throw new IllegalStateException("no binary set")
+ }
+ }
+
+ private applyBinaryTo(CprojectDescriptor descriptor) {
+ descriptor.rootCppCompilerTools.each { compiler ->
+ def includePathsOption = descriptor.getOrCreateIncludePathsOption(compiler)
+ new LinkedList(includePathsOption.children()).each { includePathsOption.remove(it) }
+ includeRoots.each { includeRoot ->
+ includePathsOption.appendNode("listOptionValue", [builtIn: "false", value: includeRoot.absolutePath])
+ }
+ }
+
+ descriptor.rootCppLinkerTools.each { linker ->
+ def libsOption = descriptor.getOrCreateLibsOption(linker)
+ new LinkedList(libsOption.children()).each { libsOption.remove(it) }
+ libs.each { lib ->
+ libsOption.appendNode("listOptionValue", [builtIn: "false", value: lib.absolutePath])
+ }
+ }
+
+ def extension = ""
+ def type
+ if (binary instanceof Library) {
+ type = "org.eclipse.cdt.build.core.buildArtefactType.sharedLib"
+ } else if (binary instanceof Executable) {
+ type = "org.eclipse.cdt.build.core.buildArtefactType.exe"
+ } else {
+ throw new IllegalStateException("The binary $binary is of a type that we don't know about")
+ }
+
+ descriptor.configurations.each { conf ->
+ conf. at buildArtefactType = type
+ conf. at artifactExtension = extension
+ def buildPropsPairs = conf. at buildProperties.split(",")
+ def buildProps = [:]
+ buildPropsPairs.each {
+ def parts = it.split("=", 2)
+ buildProps[parts[0]] = parts[1]
+ }
+ buildProps["org.eclipse.cdt.build.core.buildArtefactType"] = type
+ buildPropsPairs = buildProps.collect { k, v -> "$k=$v"}
+ conf. at buildProperties = buildPropsPairs.join(",")
+ }
+ }
+}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/cdt/model/ProjectDescriptor.groovy b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/cdt/model/ProjectDescriptor.groovy
new file mode 100644
index 0000000..6df3b54
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/cdt/model/ProjectDescriptor.groovy
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.cdt.model
+
+import org.gradle.api.Incubating
+import org.gradle.api.internal.xml.XmlTransformer
+import org.gradle.plugins.ide.internal.generator.XmlPersistableConfigurationObject
+
+/**
+ * The actual .project descriptor file.
+ */
+ at Incubating
+class ProjectDescriptor extends XmlPersistableConfigurationObject {
+
+ ProjectDescriptor() {
+ super(new XmlTransformer())
+ }
+
+ protected String getDefaultResourceName() {
+ 'defaultProject.xml'
+ }
+
+ Node getOrCreate(String name) {
+ getOrCreate(xml, name)
+ }
+
+ Node findBuildCommand(Closure predicate) {
+ xml.buildSpec[0].buildCommand.find(predicate)
+ }
+
+ Node getOrCreate(Node parent, String name) {
+ def node = parent.get(name)
+ node ? node.first() : parent.appendNode(name)
+ }
+}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/cdt/model/ProjectSettings.groovy b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/cdt/model/ProjectSettings.groovy
new file mode 100644
index 0000000..8dd00b4
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/cdt/model/ProjectSettings.groovy
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.cdt.model
+
+import org.gradle.api.Incubating
+
+/**
+ * Gradle model element, the configurable parts of the .project file.
+ */
+ at Incubating
+class ProjectSettings {
+ String name
+
+ /**
+ * Apply this logical model to the physical descriptor
+ */
+ void applyTo(ProjectDescriptor descriptor) {
+ descriptor.getOrCreate("name").value = name
+
+ // not anywhere close to right at all, very hardcoded.
+ def genMakeBuilderBuildCommand = descriptor.findBuildCommand { it.name[0].text() == "org.eclipse.cdt.managedbuilder.core.genmakebuilder" }
+ if (genMakeBuilderBuildCommand) {
+ def dict = genMakeBuilderBuildCommand.arguments[0].dictionary.find { it.key[0].text() == "org.eclipse.cdt.make.core.buildLocation" }
+ if (dict) {
+ dict.value[0].value = "\${workspace_loc:/$name/Debug}"
+ }
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/cdt/tasks/GenerateMetadataFileTask.groovy b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/cdt/tasks/GenerateMetadataFileTask.groovy
new file mode 100644
index 0000000..62889a4
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/cdt/tasks/GenerateMetadataFileTask.groovy
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.cdt.tasks
+
+import org.gradle.api.Incubating
+import org.gradle.api.internal.ClosureBackedAction
+import org.gradle.internal.Factory
+import org.gradle.listener.ActionBroadcast
+import org.gradle.nativecode.cdt.model.CprojectSettings
+import org.gradle.plugins.ide.api.GeneratorTask
+import org.gradle.plugins.ide.internal.generator.generator.PersistableConfigurationObject
+import org.gradle.plugins.ide.internal.generator.generator.PersistableConfigurationObjectGenerator
+
+ at Incubating
+class GenerateMetadataFileTask<T extends PersistableConfigurationObject> extends GeneratorTask<T> {
+
+ Factory<T> factory
+ ActionBroadcast<T> configures = new ActionBroadcast<T>()
+ CprojectSettings settings
+
+ GenerateMetadataFileTask() {
+ generator = new PersistableConfigurationObjectGenerator() {
+ public create() {
+ GenerateMetadataFileTask.this.factory.create();
+ }
+
+ public void configure(object) {
+ GenerateMetadataFileTask.this.configures.execute(object);
+ }
+ }
+ }
+
+ void factory(Closure factory) {
+ this.factory = factory as Factory
+ }
+
+ void onConfigure(Closure configure) {
+ configures.add(new ClosureBackedAction(configure))
+ }
+}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/asm/AssemblerSourceSet.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/asm/AssemblerSourceSet.java
new file mode 100644
index 0000000..7d3a769
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/asm/AssemblerSourceSet.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.asm;
+
+import org.gradle.language.base.LanguageSourceSet;
+
+/**
+ * A set of assembly language sources.
+ */
+public interface AssemblerSourceSet extends LanguageSourceSet {
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/asm/internal/AssembleSpec.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/asm/internal/AssembleSpec.java
new file mode 100644
index 0000000..adca9c9
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/asm/internal/AssembleSpec.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.asm.internal;
+
+import org.gradle.nativecode.base.internal.BinaryToolSpec;
+
+import java.io.File;
+
+/**
+ * A compile spec that will be used to generate object files for combining into a native binary.
+ */
+public interface AssembleSpec extends BinaryToolSpec {
+ File getObjectFileDir();
+
+ void setObjectFileDir(File objectFileDir);
+
+ Iterable<File> getSource();
+
+ void setSource(Iterable<File> source);
+
+ Iterable<String> getArgs();
+
+ void setArgs(Iterable<String> args);
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/asm/internal/DefaultAssembleSpec.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/asm/internal/DefaultAssembleSpec.java
new file mode 100644
index 0000000..6f9af42
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/asm/internal/DefaultAssembleSpec.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.asm.internal;
+
+import org.gradle.nativecode.language.base.internal.AbstractBaseCompileSpec;
+
+public class DefaultAssembleSpec extends AbstractBaseCompileSpec implements AssembleSpec {
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/asm/internal/DefaultAssemblerSourceSet.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/asm/internal/DefaultAssemblerSourceSet.java
new file mode 100644
index 0000000..1bccc94
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/asm/internal/DefaultAssemblerSourceSet.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.asm.internal;
+
+import org.gradle.api.internal.project.ProjectInternal;
+import org.gradle.language.base.FunctionalSourceSet;
+import org.gradle.nativecode.language.asm.AssemblerSourceSet;
+import org.gradle.nativecode.language.base.internal.AbstractBaseSourceSet;
+
+public class DefaultAssemblerSourceSet extends AbstractBaseSourceSet implements AssemblerSourceSet {
+ public DefaultAssemblerSourceSet(String name, FunctionalSourceSet parent, ProjectInternal project) {
+ super(name, parent, project, "Assembler");
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/asm/package-info.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/asm/package-info.java
new file mode 100644
index 0000000..89e04b4
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/asm/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+/**
+ * Classes that model aspects of C++ projects.
+ */
+package org.gradle.nativecode.language.asm;
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/asm/plugins/AssemblerLangPlugin.groovy b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/asm/plugins/AssemblerLangPlugin.groovy
new file mode 100644
index 0000000..07034f1
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/asm/plugins/AssemblerLangPlugin.groovy
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.asm.plugins
+
+import org.gradle.api.Incubating
+import org.gradle.api.Plugin
+import org.gradle.api.internal.project.ProjectInternal
+import org.gradle.internal.reflect.Instantiator
+import org.gradle.language.base.plugins.LanguageBasePlugin
+import org.gradle.nativecode.base.NativeBinary
+import org.gradle.nativecode.base.internal.NativeBinaryInternal
+import org.gradle.nativecode.language.asm.AssemblerSourceSet
+import org.gradle.nativecode.language.asm.tasks.Assemble
+
+import javax.inject.Inject
+
+ at Incubating
+class AssemblerLangPlugin implements Plugin<ProjectInternal> {
+ private final Instantiator instantiator;
+
+ @Inject
+ public AssemblerLangPlugin(Instantiator instantiator) {
+ this.instantiator = instantiator;
+ }
+
+ void apply(ProjectInternal project) {
+ project.getPlugins().apply(LanguageBasePlugin.class);
+
+ project.binaries.withType(NativeBinary) { NativeBinaryInternal binary ->
+ binary.source.withType(AssemblerSourceSet).all { AssemblerSourceSet sourceSet ->
+ def compileTask = createAssembleTask(project, binary, sourceSet)
+ binary.builderTask.source compileTask.outputs.files.asFileTree.matching { include '**/*.obj', '**/*.o' }
+ }
+ }
+ }
+
+ private def createAssembleTask(ProjectInternal project, NativeBinaryInternal binary, def sourceSet) {
+ def assembleTask = project.task(binary.namingScheme.getTaskName("assemble", sourceSet.fullName), type: Assemble) {
+ description = "Assembles the $sourceSet sources of $binary"
+ }
+
+ assembleTask.toolChain = binary.toolChain
+
+ assembleTask.source sourceSet.source
+
+ assembleTask.conventionMapping.objectFileDir = { project.file("${project.buildDir}/objectFiles/${binary.namingScheme.outputDirectoryBase}/${sourceSet.fullName}") }
+ assembleTask.conventionMapping.assemblerArgs = { binary.assemblerArgs }
+
+ assembleTask
+ }
+}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/asm/tasks/Assemble.groovy b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/asm/tasks/Assemble.groovy
new file mode 100644
index 0000000..32f7734
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/asm/tasks/Assemble.groovy
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.asm.tasks
+import org.gradle.api.DefaultTask
+import org.gradle.api.Incubating
+import org.gradle.api.file.FileCollection
+import org.gradle.api.tasks.*
+import org.gradle.language.jvm.internal.SimpleStaleClassCleaner
+import org.gradle.nativecode.base.ToolChain
+import org.gradle.nativecode.language.asm.internal.DefaultAssembleSpec
+
+import javax.inject.Inject
+
+/**
+ * Translates Assembly language source files into object files.
+ */
+ at Incubating
+class Assemble extends DefaultTask {
+ private FileCollection source
+
+ ToolChain toolChain
+
+ /**
+ * The directory where object files will be generated.
+ */
+ @OutputDirectory
+ File objectFileDir
+
+ @InputFiles @SkipWhenEmpty // Workaround for GRADLE-2026
+ FileCollection getSource() {
+ source
+ }
+
+ // Invalidate output when the tool chain output changes
+ @Input
+ def getOutputType() {
+ return toolChain.outputType
+ }
+
+ /**
+ * Additional arguments to provide to the assembler.
+ */
+ @Input
+ List<String> assemblerArgs
+
+ @Inject
+ Assemble() {
+ source = project.files()
+ }
+
+ @TaskAction
+ void assemble() {
+ def cleaner = new SimpleStaleClassCleaner(getOutputs())
+ cleaner.setDestinationDir(getObjectFileDir())
+ cleaner.execute()
+
+ def spec = new DefaultAssembleSpec()
+ spec.tempDir = getTemporaryDir()
+
+ spec.objectFileDir = getObjectFileDir()
+ spec.source = getSource()
+ spec.args = getAssemblerArgs()
+
+ def result = toolChain.createAssembler().execute(spec)
+ didWork = result.didWork
+ }
+
+ /**
+ * Adds a set of assembler sources files to be translated.
+ * The provided sourceFiles object is evaluated as per {@link org.gradle.api.Project#files(Object...)}.
+ */
+ void source(Object sourceFiles) {
+ source.from sourceFiles
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/base/internal/AbstractBaseCompileSpec.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/base/internal/AbstractBaseCompileSpec.java
new file mode 100644
index 0000000..4cd560c
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/base/internal/AbstractBaseCompileSpec.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.base.internal;
+
+import java.io.File;
+import java.util.ArrayList;
+
+public abstract class AbstractBaseCompileSpec {
+
+ private Iterable<File> includeRoots;
+ private Iterable<File> source;
+ private Iterable<String> macros = new ArrayList<String>();
+ private Iterable<String> args = new ArrayList<String>();
+ private File objectFileDir;
+ private File tempDir;
+
+ public Iterable<File> getIncludeRoots() {
+ return includeRoots;
+ }
+
+ public void setIncludeRoots(Iterable<File> includeRoots) {
+ this.includeRoots = includeRoots;
+ }
+
+ public Iterable<File> getSource() {
+ return source;
+ }
+
+ public void setSource(Iterable<File> source) {
+ this.source = source;
+ }
+
+ public File getObjectFileDir() {
+ return objectFileDir;
+ }
+
+ public void setObjectFileDir(File objectFileDir) {
+ this.objectFileDir = objectFileDir;
+ }
+
+ public File getTempDir() {
+ return tempDir;
+ }
+
+ public void setTempDir(File tempDir) {
+ this.tempDir = tempDir;
+ }
+
+ public Iterable<String> getMacros() {
+ return macros;
+ }
+
+ public void setMacros(Iterable<String> macros) {
+ this.macros = macros;
+ }
+
+ public void setArgs(Iterable<String> args) {
+ this.args = args;
+ }
+
+ public Iterable<String> getArgs() {
+ return args;
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/base/internal/AbstractBaseSourceSet.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/base/internal/AbstractBaseSourceSet.java
new file mode 100644
index 0000000..892dd5c
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/base/internal/AbstractBaseSourceSet.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.base.internal;
+
+import org.apache.commons.lang.StringUtils;
+import org.gradle.api.Action;
+import org.gradle.api.file.SourceDirectorySet;
+import org.gradle.api.internal.file.DefaultSourceDirectorySet;
+import org.gradle.api.internal.project.ProjectInternal;
+import org.gradle.api.internal.tasks.DefaultTaskDependency;
+import org.gradle.api.tasks.TaskDependency;
+import org.gradle.language.base.FunctionalSourceSet;
+import org.gradle.language.base.internal.LanguageSourceSetInternal;
+import org.gradle.nativecode.base.internal.ConfigurationBasedNativeDependencySet;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A convenience base class for implementing language source sets.
+ * Note that this class 'implements' all required methods for {@link org.gradle.nativecode.base.HeaderExportingSourceSet}
+ * and {@link org.gradle.nativecode.base.DependentSourceSet} but does not add those types to the API.
+ */
+public abstract class AbstractBaseSourceSet implements LanguageSourceSetInternal {
+
+ private final String name;
+ private final String fullName;
+ private final String typeName;
+
+ private final DefaultSourceDirectorySet exportedHeaders;
+ private final DefaultSourceDirectorySet source;
+ private final List<Object> libs = new ArrayList<Object>();
+ private final ConfigurationBasedNativeDependencySet configurationDependencySet;
+
+ public AbstractBaseSourceSet(String name, FunctionalSourceSet parent, ProjectInternal project, String typeName) {
+ this.name = name;
+ this.fullName = parent.getName() + StringUtils.capitalize(name);
+ this.typeName = typeName;
+
+ this.exportedHeaders = new DefaultSourceDirectorySet("exported headers", project.getFileResolver());
+ this.source = new DefaultSourceDirectorySet("source", project.getFileResolver());
+ this.configurationDependencySet = new ConfigurationBasedNativeDependencySet(project, fullName);
+
+ libs.add(configurationDependencySet);
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getFullName() {
+ return fullName;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%s source '%s'", typeName, getFullName());
+ }
+
+ public TaskDependency getBuildDependencies() {
+ // TODO -
+ return new DefaultTaskDependency();
+ }
+
+ public SourceDirectorySet getExportedHeaders() {
+ return exportedHeaders;
+ }
+
+ public void exportedHeaders(Action<SourceDirectorySet> config) {
+ config.execute(getExportedHeaders());
+ }
+
+ public SourceDirectorySet getSource() {
+ return source;
+ }
+
+ public void source(Action<SourceDirectorySet> config) {
+ config.execute(getSource());
+ }
+
+ public Collection<?> getLibs() {
+ return libs;
+ }
+
+ public void lib(Object library) {
+ libs.add(library);
+ }
+
+ public void dependency(Map<?, ?> dep) {
+ configurationDependencySet.add(dep);
+ }
+}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/base/internal/NativeCompileSpec.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/base/internal/NativeCompileSpec.java
new file mode 100644
index 0000000..38a8bc3
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/base/internal/NativeCompileSpec.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.base.internal;
+
+import org.gradle.nativecode.base.internal.BinaryToolSpec;
+
+import java.io.File;
+
+/**
+ * A compile spec that will be used to generate object files for combining into a native binary.
+ */
+public interface NativeCompileSpec extends BinaryToolSpec {
+ File getObjectFileDir();
+
+ void setObjectFileDir(File objectFileDir);
+
+ Iterable<File> getIncludeRoots();
+
+ void setIncludeRoots(Iterable<File> includeRoots);
+
+ Iterable<File> getSource();
+
+ void setSource(Iterable<File> source);
+
+ Iterable<String> getMacros();
+
+ void setMacros(Iterable<String> macros);
+
+ Iterable<String> getArgs();
+
+ void setArgs(Iterable<String> args);
+
+ boolean isPositionIndependentCode();
+
+ void setPositionIndependentCode(boolean flag);
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/base/tasks/AbstractNativeCompileTask.groovy b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/base/tasks/AbstractNativeCompileTask.groovy
new file mode 100644
index 0000000..d5a2f84
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/base/tasks/AbstractNativeCompileTask.groovy
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.base.tasks
+import org.gradle.api.DefaultTask
+import org.gradle.api.Incubating
+import org.gradle.api.file.FileCollection
+import org.gradle.api.file.SourceDirectorySet
+import org.gradle.api.tasks.*
+import org.gradle.language.jvm.internal.SimpleStaleClassCleaner
+import org.gradle.nativecode.base.ToolChain
+import org.gradle.nativecode.base.internal.ToolChainInternal
+import org.gradle.nativecode.language.base.internal.NativeCompileSpec
+
+import javax.inject.Inject
+/**
+ * Compiles native source files into object files.
+ */
+ at Incubating
+abstract class AbstractNativeCompileTask extends DefaultTask {
+ private FileCollection source
+
+ ToolChain toolChain
+
+ /**
+ * Should the compiler generate position independent code?
+ */
+ @Input
+ boolean positionIndependentCode
+
+ /**
+ * The directory where object files will be generated.
+ */
+ @OutputDirectory
+ File objectFileDir
+
+ @InputFiles
+ FileCollection includes
+
+ @InputFiles @SkipWhenEmpty // Workaround for GRADLE-2026
+ FileCollection getSource() {
+ source
+ }
+
+ // Invalidate output when the tool chain output changes
+ @Input
+ def getOutputType() {
+ return toolChain.outputType
+ }
+
+ /**
+ * Macros that should be defined for the compiler.
+ */
+ @Input
+ List<String> macros
+
+ /**
+ * Additional arguments to provide to the compiler.
+ */
+ @Input
+ List<String> compilerArgs
+
+ @Inject
+ AbstractNativeCompileTask() {
+ includes = project.files()
+ source = project.files()
+ }
+
+ @TaskAction
+ void compile() {
+ def cleaner = new SimpleStaleClassCleaner(getOutputs())
+ cleaner.setDestinationDir(getObjectFileDir())
+ cleaner.execute()
+
+ def spec = createCompileSpec()
+ spec.tempDir = getTemporaryDir()
+
+ spec.objectFileDir = getObjectFileDir()
+ spec.includeRoots = getIncludes()
+ spec.source = getSource()
+ spec.macros = getMacros()
+ spec.args = getCompilerArgs()
+ spec.positionIndependentCode = isPositionIndependentCode()
+
+ def result = execute(toolChain as ToolChainInternal, spec)
+ didWork = result.didWork
+ }
+
+ protected abstract NativeCompileSpec createCompileSpec();
+
+ protected abstract WorkResult execute(ToolChainInternal toolChain, NativeCompileSpec spec);
+
+ /**
+ * Add locations where the compiler should search for header files.
+ */
+ void includes(SourceDirectorySet dirs) {
+ includes.from({dirs.srcDirs})
+ }
+
+ /**
+ * Add directories where the compiler should search for header files.
+ */
+ void includes(FileCollection includeRoots) {
+ includes.from(includeRoots)
+ }
+
+ /**
+ * Adds a set of source files to be compiled.
+ * The provided sourceFiles object is evaluated as per {@link org.gradle.api.Project#files(Object...)}.
+ */
+ void source(Object sourceFiles) {
+ source.from sourceFiles
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/c/CSourceSet.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/c/CSourceSet.java
new file mode 100644
index 0000000..147962e
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/c/CSourceSet.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.c;
+
+import org.gradle.api.Incubating;
+import org.gradle.language.base.LanguageSourceSet;
+import org.gradle.nativecode.base.DependentSourceSet;
+import org.gradle.nativecode.base.HeaderExportingSourceSet;
+
+/**
+ * A representation of a unit of C source.
+ */
+ at Incubating
+public interface CSourceSet extends HeaderExportingSourceSet, LanguageSourceSet, DependentSourceSet {
+}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/c/internal/CCompileSpec.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/c/internal/CCompileSpec.java
new file mode 100644
index 0000000..dcf2081
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/c/internal/CCompileSpec.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.c.internal;
+
+import org.gradle.nativecode.language.base.internal.NativeCompileSpec;
+
+public interface CCompileSpec extends NativeCompileSpec {
+
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/c/internal/DefaultCCompileSpec.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/c/internal/DefaultCCompileSpec.java
new file mode 100644
index 0000000..4e3cdea
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/c/internal/DefaultCCompileSpec.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.c.internal;
+
+import org.gradle.nativecode.language.base.internal.AbstractBaseCompileSpec;
+
+public class DefaultCCompileSpec extends AbstractBaseCompileSpec implements CCompileSpec {
+ private boolean positionIndependentCode;
+
+ public boolean isPositionIndependentCode() {
+ return positionIndependentCode;
+ }
+
+ public void setPositionIndependentCode(boolean positionIndependentCode) {
+ this.positionIndependentCode = positionIndependentCode;
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/c/internal/DefaultCSourceSet.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/c/internal/DefaultCSourceSet.java
new file mode 100644
index 0000000..ddcf45b
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/c/internal/DefaultCSourceSet.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.c.internal;
+
+import org.gradle.api.internal.project.ProjectInternal;
+import org.gradle.language.base.FunctionalSourceSet;
+import org.gradle.nativecode.language.base.internal.AbstractBaseSourceSet;
+import org.gradle.nativecode.language.c.CSourceSet;
+
+public class DefaultCSourceSet extends AbstractBaseSourceSet implements CSourceSet {
+ public DefaultCSourceSet(String name, FunctionalSourceSet parent, ProjectInternal project) {
+ super(name, parent, project, "C");
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/c/package-info.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/c/package-info.java
new file mode 100644
index 0000000..1d24572
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/c/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+/**
+ * Classes that model aspects of C++ projects.
+ */
+package org.gradle.nativecode.language.c;
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/c/plugins/CLangPlugin.groovy b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/c/plugins/CLangPlugin.groovy
new file mode 100644
index 0000000..5141a20
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/c/plugins/CLangPlugin.groovy
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.c.plugins
+
+import org.gradle.api.Incubating
+import org.gradle.api.Plugin
+import org.gradle.api.internal.project.ProjectInternal
+import org.gradle.internal.reflect.Instantiator
+import org.gradle.language.base.plugins.LanguageBasePlugin
+import org.gradle.nativecode.base.NativeBinary
+import org.gradle.nativecode.base.NativeDependencySet
+import org.gradle.nativecode.base.SharedLibraryBinary
+import org.gradle.nativecode.base.internal.NativeBinaryInternal
+import org.gradle.nativecode.language.c.CSourceSet
+import org.gradle.nativecode.language.c.tasks.CCompile
+
+import javax.inject.Inject
+
+ at Incubating
+class CLangPlugin implements Plugin<ProjectInternal> {
+ private final Instantiator instantiator;
+
+ @Inject
+ public CLangPlugin(Instantiator instantiator) {
+ this.instantiator = instantiator;
+ }
+
+ void apply(ProjectInternal project) {
+ project.getPlugins().apply(LanguageBasePlugin.class);
+
+ project.binaries.withType(NativeBinary) { NativeBinaryInternal binary ->
+ binary.source.withType(CSourceSet).all { CSourceSet sourceSet ->
+ def compileTask = createCompileTask(project, binary, sourceSet)
+ binary.builderTask.source compileTask.outputs.files.asFileTree.matching { include '**/*.obj', '**/*.o' }
+ }
+ }
+ }
+
+ private def createCompileTask(ProjectInternal project, NativeBinaryInternal binary, def sourceSet) {
+ def compileTask = project.task(binary.namingScheme.getTaskName("compile", sourceSet.fullName), type: CCompile) {
+ description = "Compiles the $sourceSet sources of $binary"
+ }
+
+ compileTask.toolChain = binary.toolChain
+ compileTask.positionIndependentCode = binary instanceof SharedLibraryBinary
+
+ compileTask.includes sourceSet.exportedHeaders
+ compileTask.source sourceSet.source
+ binary.libs.each { NativeDependencySet deps ->
+ compileTask.includes deps.includeRoots
+ }
+
+ compileTask.conventionMapping.objectFileDir = { project.file("${project.buildDir}/objectFiles/${binary.namingScheme.outputDirectoryBase}/${sourceSet.fullName}") }
+ compileTask.conventionMapping.macros = { binary.macros }
+ compileTask.conventionMapping.compilerArgs = { binary.compilerArgs }
+
+ compileTask
+ }
+}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/c/tasks/CCompile.groovy b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/c/tasks/CCompile.groovy
new file mode 100644
index 0000000..dabd5a2
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/c/tasks/CCompile.groovy
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.c.tasks
+
+import org.gradle.api.Incubating
+import org.gradle.api.tasks.WorkResult
+import org.gradle.nativecode.base.internal.ToolChainInternal
+import org.gradle.nativecode.language.base.internal.NativeCompileSpec
+import org.gradle.nativecode.language.c.internal.DefaultCCompileSpec
+import org.gradle.nativecode.language.base.tasks.AbstractNativeCompileTask
+
+/**
+ * Compiles C source files into object files.
+ */
+ at Incubating
+class CCompile extends AbstractNativeCompileTask {
+ @Override
+ protected NativeCompileSpec createCompileSpec() {
+ new DefaultCCompileSpec()
+ }
+
+ @Override
+ protected WorkResult execute(ToolChainInternal toolChain, NativeCompileSpec spec) {
+ return toolChain.createCCompiler().execute(spec)
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/cpp/CppSourceSet.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/cpp/CppSourceSet.java
new file mode 100644
index 0000000..dbdc55f
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/cpp/CppSourceSet.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp;
+
+import org.gradle.api.Incubating;
+import org.gradle.language.base.LanguageSourceSet;
+import org.gradle.nativecode.base.DependentSourceSet;
+import org.gradle.nativecode.base.HeaderExportingSourceSet;
+
+/**
+ * A representation of a unit of C++ source.
+ */
+ at Incubating
+public interface CppSourceSet extends HeaderExportingSourceSet, LanguageSourceSet, DependentSourceSet {
+}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/cpp/internal/CppCompileSpec.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/cpp/internal/CppCompileSpec.java
new file mode 100644
index 0000000..706cf11
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/cpp/internal/CppCompileSpec.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp.internal;
+
+import org.gradle.nativecode.language.base.internal.NativeCompileSpec;
+
+public interface CppCompileSpec extends NativeCompileSpec {
+
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/cpp/internal/DefaultCppCompileSpec.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/cpp/internal/DefaultCppCompileSpec.java
new file mode 100644
index 0000000..c50807e
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/cpp/internal/DefaultCppCompileSpec.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp.internal;
+
+import org.gradle.nativecode.language.base.internal.AbstractBaseCompileSpec;
+
+public class DefaultCppCompileSpec extends AbstractBaseCompileSpec implements CppCompileSpec {
+ private boolean positionIndependentCode;
+
+ public boolean isPositionIndependentCode() {
+ return positionIndependentCode;
+ }
+
+ public void setPositionIndependentCode(boolean positionIndependentCode) {
+ this.positionIndependentCode = positionIndependentCode;
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/cpp/internal/DefaultCppSourceSet.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/cpp/internal/DefaultCppSourceSet.java
new file mode 100644
index 0000000..c3e76cc
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/cpp/internal/DefaultCppSourceSet.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp.internal;
+
+import org.gradle.api.internal.project.ProjectInternal;
+import org.gradle.language.base.FunctionalSourceSet;
+import org.gradle.nativecode.language.base.internal.AbstractBaseSourceSet;
+import org.gradle.nativecode.language.cpp.CppSourceSet;
+
+public class DefaultCppSourceSet extends AbstractBaseSourceSet implements CppSourceSet {
+ public DefaultCppSourceSet(String name, FunctionalSourceSet parent, ProjectInternal project) {
+ super(name, parent, project, "C++");
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/cpp/package-info.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/cpp/package-info.java
new file mode 100644
index 0000000..4a87e2c
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/cpp/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+/**
+ * Classes that model aspects of C++ projects.
+ */
+package org.gradle.nativecode.language.cpp;
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/cpp/plugins/CppExeConventionPlugin.groovy b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/cpp/plugins/CppExeConventionPlugin.groovy
new file mode 100644
index 0000000..88e79f7
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/cpp/plugins/CppExeConventionPlugin.groovy
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp.plugins
+
+import org.gradle.api.Incubating
+import org.gradle.api.Project
+import org.gradle.api.Plugin
+
+import org.gradle.api.internal.artifacts.publish.DefaultPublishArtifact
+import org.gradle.api.internal.plugins.DefaultArtifactPublicationSet
+import org.gradle.configuration.project.ProjectConfigurationActionContainer
+
+import javax.inject.Inject
+
+/**
+ * A convention-based plugin that automatically adds a single C++ source set named "main" and wires it into a {@link org.gradle.nativecode.base.Executable} named "main".
+ */
+ at Incubating
+class CppExeConventionPlugin implements Plugin<Project> {
+ private final ProjectConfigurationActionContainer configureActions
+
+ @Inject
+ CppExeConventionPlugin(ProjectConfigurationActionContainer configureActions) {
+ this.configureActions = configureActions
+ }
+
+ void apply(Project project) {
+ project.plugins.apply(CppPlugin)
+
+ project.with {
+ sources {
+ main {}
+ }
+ executables {
+ main {
+ baseName = project.name
+ source sources.main.cpp
+ }
+ }
+ }
+
+ configureActions.add {
+ project.with {
+ def exeArtifact = new DefaultPublishArtifact(
+ archivesBaseName, // name
+ "exe", // ext
+ "exe", // type
+ null, // classifier
+ null, // date
+
+ // needs to be more general and not peer into the spec
+ binaries.mainExecutable.outputFile,
+ binaries.mainExecutable
+ )
+
+ extensions.getByType(DefaultArtifactPublicationSet).addCandidate(exeArtifact)
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/cpp/plugins/CppLangPlugin.groovy b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/cpp/plugins/CppLangPlugin.groovy
new file mode 100644
index 0000000..60e487e
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/cpp/plugins/CppLangPlugin.groovy
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp.plugins
+import org.gradle.api.Incubating
+import org.gradle.api.Plugin
+import org.gradle.api.internal.project.ProjectInternal
+import org.gradle.internal.reflect.Instantiator
+import org.gradle.language.base.plugins.LanguageBasePlugin
+import org.gradle.nativecode.base.NativeBinary
+import org.gradle.nativecode.base.NativeDependencySet
+import org.gradle.nativecode.base.SharedLibraryBinary
+import org.gradle.nativecode.base.internal.NativeBinaryInternal
+import org.gradle.nativecode.language.cpp.CppSourceSet
+import org.gradle.nativecode.language.cpp.tasks.CppCompile
+
+import javax.inject.Inject
+
+ at Incubating
+class CppLangPlugin implements Plugin<ProjectInternal> {
+ private final Instantiator instantiator;
+
+ @Inject
+ public CppLangPlugin(Instantiator instantiator) {
+ this.instantiator = instantiator;
+ }
+
+ void apply(ProjectInternal project) {
+ project.getPlugins().apply(LanguageBasePlugin.class);
+
+ project.binaries.withType(NativeBinary) { NativeBinaryInternal binary ->
+ binary.source.withType(CppSourceSet).all { CppSourceSet sourceSet ->
+ def compileTask = createCompileTask(project, binary, sourceSet)
+ binary.builderTask.source compileTask.outputs.files.asFileTree.matching { include '**/*.obj', '**/*.o' }
+ }
+ }
+ }
+
+ private def createCompileTask(ProjectInternal project, NativeBinaryInternal binary, def sourceSet) {
+ def compileTask = project.task(binary.namingScheme.getTaskName("compile", sourceSet.fullName), type: CppCompile) {
+ description = "Compiles the $sourceSet sources of $binary"
+ }
+
+ compileTask.toolChain = binary.toolChain
+ compileTask.positionIndependentCode = binary instanceof SharedLibraryBinary
+
+ compileTask.includes sourceSet.exportedHeaders
+ compileTask.source sourceSet.source
+ binary.libs.each { NativeDependencySet deps ->
+ compileTask.includes deps.includeRoots
+ }
+
+ compileTask.conventionMapping.objectFileDir = { project.file("${project.buildDir}/objectFiles/${binary.namingScheme.outputDirectoryBase}/${sourceSet.fullName}") }
+ compileTask.conventionMapping.macros = { binary.macros }
+ compileTask.conventionMapping.compilerArgs = { binary.compilerArgs }
+
+ compileTask
+ }
+}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/cpp/plugins/CppLibConventionPlugin.groovy b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/cpp/plugins/CppLibConventionPlugin.groovy
new file mode 100644
index 0000000..de8a3c6
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/cpp/plugins/CppLibConventionPlugin.groovy
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp.plugins
+
+import org.gradle.api.Incubating
+import org.gradle.api.Project
+import org.gradle.api.Plugin
+import org.gradle.api.tasks.bundling.Zip
+
+import org.gradle.api.internal.artifacts.publish.DefaultPublishArtifact
+import org.gradle.api.internal.artifacts.publish.ArchivePublishArtifact
+import org.gradle.api.internal.plugins.DefaultArtifactPublicationSet
+import org.gradle.configuration.project.ProjectConfigurationActionContainer
+
+import javax.inject.Inject
+
+/**
+ * A convention-based plugin that automatically adds a single C++ source set named "main" and wires it into a {@link org.gradle.nativecode.base.Library} named "main".
+ */
+ at Incubating
+class CppLibConventionPlugin implements Plugin<Project> {
+ private final ProjectConfigurationActionContainer configureActions
+
+ @Inject
+ CppLibConventionPlugin(ProjectConfigurationActionContainer configureActions) {
+ this.configureActions = configureActions
+ }
+
+ void apply(Project project) {
+ project.plugins.apply(CppPlugin)
+
+ project.with {
+ sources {
+ main {}
+ }
+ libraries {
+ main {
+ baseName = project.name
+ source sources.main.cpp
+ }
+ }
+ }
+
+ configureActions.add {
+ project.with {
+ def libArtifact = new DefaultPublishArtifact(
+ archivesBaseName, // name
+ "so", // ext
+ "so", // type
+ "so", // classifier
+ null, // date
+
+ // needs to be more general and not peer into the spec
+ binaries.mainSharedLibrary.outputFile,
+ binaries.mainSharedLibrary
+ )
+
+ task("assembleHeaders", type: Zip) {
+ from libraries.main.headers
+ classifier = "headers"
+ }
+
+ def headerArtifact = new ArchivePublishArtifact(assembleHeaders)
+
+ extensions.getByType(DefaultArtifactPublicationSet).addCandidate(libArtifact)
+ extensions.getByType(DefaultArtifactPublicationSet).addCandidate(headerArtifact)
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/cpp/plugins/CppPlugin.groovy b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/cpp/plugins/CppPlugin.groovy
new file mode 100644
index 0000000..3ad3588
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/cpp/plugins/CppPlugin.groovy
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp.plugins
+import org.gradle.api.Action
+import org.gradle.api.Incubating
+import org.gradle.api.Plugin
+import org.gradle.api.internal.file.FileResolver
+import org.gradle.api.internal.project.ProjectInternal
+import org.gradle.internal.reflect.Instantiator
+import org.gradle.language.base.FunctionalSourceSet
+import org.gradle.language.base.ProjectSourceSet
+import org.gradle.nativecode.base.ExecutableBinary
+import org.gradle.nativecode.base.NativeBinary
+import org.gradle.nativecode.base.plugins.NativeBinariesPlugin
+import org.gradle.nativecode.base.tasks.CreateStaticLibrary
+import org.gradle.nativecode.base.tasks.LinkExecutable
+import org.gradle.nativecode.base.tasks.LinkSharedLibrary
+import org.gradle.nativecode.language.asm.AssemblerSourceSet
+import org.gradle.nativecode.language.asm.internal.DefaultAssemblerSourceSet
+import org.gradle.nativecode.language.asm.plugins.AssemblerLangPlugin
+import org.gradle.nativecode.language.c.CSourceSet
+import org.gradle.nativecode.language.c.internal.DefaultCSourceSet
+import org.gradle.nativecode.language.c.plugins.CLangPlugin
+import org.gradle.nativecode.language.cpp.CppSourceSet
+import org.gradle.nativecode.language.cpp.internal.DefaultCppSourceSet
+import org.gradle.nativecode.language.cpp.tasks.CppCompile
+import org.gradle.nativecode.toolchain.plugins.GppCompilerPlugin
+import org.gradle.nativecode.toolchain.plugins.MicrosoftVisualCppPlugin
+
+import javax.inject.Inject
+/**
+ * A plugin for projects wishing to build custom components from C++ sources.
+ * <p>Automatically includes {@link MicrosoftVisualCppPlugin} and {@link GppCompilerPlugin} for core toolchain support.</p>
+ *
+ * <p>
+ * For each {@link NativeBinary} found, this plugin will:
+ * <ul>
+ * <li>Create a {@link CppCompile} task named "compile${binary-name}" to compile the C++ sources.</li>
+ * <li>Create a {@link LinkExecutable} or {@link LinkSharedLibrary} task named "link${binary-name}
+ * or a {@link CreateStaticLibrary} task name "create${binary-name}" to create the binary artifact.</li>
+ * <li>Create an InstallTask named "install${Binary-name}" to install any {@link ExecutableBinary} artifact.
+ * </ul>
+ * </p>
+ */
+ at Incubating
+class CppPlugin implements Plugin<ProjectInternal> {
+ private final Instantiator instantiator;
+ private final FileResolver fileResolver;
+
+ @Inject
+ public CppPlugin(Instantiator instantiator, FileResolver fileResolver) {
+ this.instantiator = instantiator;
+ this.fileResolver = fileResolver;
+ }
+
+ void apply(ProjectInternal project) {
+ project.plugins.apply(NativeBinariesPlugin)
+ project.plugins.apply(MicrosoftVisualCppPlugin)
+ project.plugins.apply(GppCompilerPlugin)
+
+ ProjectSourceSet projectSourceSet = project.getExtensions().getByType(ProjectSourceSet.class);
+ projectSourceSet.all(new Action<FunctionalSourceSet>() {
+ public void execute(final FunctionalSourceSet functionalSourceSet) {
+ applyCppConventions(project, functionalSourceSet)
+ applyCConventions(project, functionalSourceSet)
+ applyAssemblerConventions(project, functionalSourceSet)
+ }
+ });
+
+ project.plugins.apply(CppLangPlugin)
+ project.plugins.apply(CLangPlugin)
+ project.plugins.apply(AssemblerLangPlugin)
+ }
+
+ private void applyCppConventions(ProjectInternal project, FunctionalSourceSet functionalSourceSet) {
+ // Defaults for all cpp source sets
+ functionalSourceSet.withType(CppSourceSet).all(new Action<CppSourceSet>() {
+ void execute(CppSourceSet sourceSet) {
+ sourceSet.exportedHeaders.srcDir "src/${functionalSourceSet.name}/headers"
+ sourceSet.source.srcDir "src/${functionalSourceSet.name}/cpp"
+ }
+ })
+
+ // Create a single C++ source set
+ functionalSourceSet.add(instantiator.newInstance(DefaultCppSourceSet.class, "cpp", functionalSourceSet, project));
+ }
+
+ private void applyCConventions(ProjectInternal project, FunctionalSourceSet functionalSourceSet) {
+ // Defaults for all c source sets
+ functionalSourceSet.withType(CSourceSet).all(new Action<CSourceSet>() {
+ void execute(CSourceSet sourceSet) {
+ sourceSet.exportedHeaders.srcDir "src/${functionalSourceSet.name}/headers"
+ sourceSet.source.srcDir "src/${functionalSourceSet.name}/c"
+ }
+ })
+
+ // Create a single C source set
+ functionalSourceSet.add(instantiator.newInstance(DefaultCSourceSet.class, "c", functionalSourceSet, project));
+ }
+
+ private void applyAssemblerConventions(ProjectInternal project, FunctionalSourceSet functionalSourceSet) {
+ // Defaults for all assembler source sets
+ functionalSourceSet.withType(AssemblerSourceSet).all(new Action<AssemblerSourceSet>() {
+ void execute(AssemblerSourceSet sourceSet) {
+ sourceSet.source.srcDir "src/${functionalSourceSet.name}/asm"
+ }
+ })
+
+ // Create a single assembler source set
+ functionalSourceSet.add(instantiator.newInstance(DefaultAssemblerSourceSet.class, "asm", functionalSourceSet, project));
+ }
+}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/cpp/plugins/package-info.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/cpp/plugins/package-info.java
new file mode 100644
index 0000000..c692538
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/cpp/plugins/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+/**
+ * Plugins for buildings C++ projects.
+ */
+package org.gradle.nativecode.language.cpp.plugins;
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/cpp/tasks/CppCompile.groovy b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/cpp/tasks/CppCompile.groovy
new file mode 100644
index 0000000..4ee53a2
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/cpp/tasks/CppCompile.groovy
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp.tasks
+
+import org.gradle.api.Incubating
+import org.gradle.api.tasks.WorkResult
+import org.gradle.nativecode.base.internal.ToolChainInternal
+import org.gradle.nativecode.language.base.tasks.AbstractNativeCompileTask
+import org.gradle.nativecode.language.cpp.internal.DefaultCppCompileSpec
+import org.gradle.nativecode.language.base.internal.NativeCompileSpec
+
+/**
+ * Compiles C++ source files into object files.
+ */
+ at Incubating
+class CppCompile extends AbstractNativeCompileTask {
+ @Override
+ protected NativeCompileSpec createCompileSpec() {
+ new DefaultCppCompileSpec()
+ }
+
+ @Override
+ protected WorkResult execute(ToolChainInternal toolChain, NativeCompileSpec spec) {
+ return toolChain.createCppCompiler().execute(spec)
+ }
+}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/cpp/tasks/package-info.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/cpp/tasks/package-info.java
new file mode 100644
index 0000000..f289fcd
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/language/cpp/tasks/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+/**
+ * Tasks for building C++ projects.
+ */
+package org.gradle.nativecode.language.cpp.tasks;
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/ConfigurableToolChain.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/ConfigurableToolChain.java
new file mode 100644
index 0000000..c8d7597
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/ConfigurableToolChain.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.toolchain;
+
+import org.gradle.api.Incubating;
+import org.gradle.nativecode.base.ToolChain;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ * A tool chain that allows the individual tools to be configured.
+ */
+ at Incubating
+public interface ConfigurableToolChain extends ToolChain {
+ /**
+ * The paths setting required for executing the tool chain.
+ */
+ List<File> getPaths();
+ // TODO:DAZ Add a setter
+
+ /**
+ * Add an entry or entries to the tool chain path.
+ */
+ void path(Object... pathEntry);
+
+ /**
+ * The C++ compiler.
+ */
+ Tool getCCompiler();
+
+ /**
+ * The C compiler.
+ */
+ Tool getCppCompiler();
+
+ /**
+ * The assembler.
+ */
+ Tool getAssembler();
+
+ /**
+ * The linker.
+ */
+ Tool getLinker();
+
+ /**
+ * The static library archiver.
+ */
+ Tool getStaticLibArchiver();
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/Gcc.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/Gcc.java
new file mode 100644
index 0000000..a0e86aa
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/Gcc.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.toolchain;
+
+import org.gradle.api.Incubating;
+
+/**
+ * The Visual C++ tool chain.
+ */
+ at Incubating
+public interface Gcc extends ConfigurableToolChain {
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/Tool.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/Tool.java
new file mode 100644
index 0000000..819535b
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/Tool.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.toolchain;
+
+import org.gradle.api.Incubating;
+
+/**
+ * An executable tool that forms part of a tool chain.
+ */
+ at Incubating
+public interface Tool {
+ /**
+ * The name of the executable file for this tool.
+ */
+ String getExe();
+
+ /**
+ * Set the name of the executable file for this tool.
+ * The executable will be located in the tool chain path.
+ */
+ void setExe(String file);
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/VisualCpp.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/VisualCpp.java
new file mode 100644
index 0000000..8d70545
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/VisualCpp.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.toolchain;
+
+import org.gradle.api.Incubating;
+
+import java.io.File;
+
+/**
+ * The Visual C++ tool chain.
+ */
+ at Incubating
+public interface VisualCpp extends ConfigurableToolChain {
+ /**
+ * The directory where Visual Studio or Visual C++ is installed.
+ */
+ File getInstallDir();
+
+ /**
+ * The directory where Visual Studio or Visual C++ is installed.
+ * Setting the installDir will overwrite any paths added previously via {@link ConfigurableToolChain#path(Object)}.
+ */
+ void setInstallDir(Object installDir);
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/CommandLineCompilerArgumentsToOptionFile.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/CommandLineCompilerArgumentsToOptionFile.java
new file mode 100644
index 0000000..9f721fc
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/CommandLineCompilerArgumentsToOptionFile.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.toolchain.internal;
+
+import org.gradle.api.Transformer;
+import org.gradle.api.UncheckedIOException;
+import org.gradle.api.internal.tasks.compile.ArgCollector;
+import org.gradle.api.internal.tasks.compile.ArgWriter;
+import org.gradle.api.internal.tasks.compile.CompileSpecToArguments;
+import org.gradle.nativecode.base.internal.BinaryToolSpec;
+import org.gradle.util.GFileUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+public class CommandLineCompilerArgumentsToOptionFile<T extends BinaryToolSpec> implements CompileSpecToArguments<T> {
+
+ private final Transformer<ArgWriter, PrintWriter> argWriterFactory;
+ private final CompileSpecToArguments<T> toArguments;
+
+ public CommandLineCompilerArgumentsToOptionFile(Transformer<ArgWriter, PrintWriter> argWriterFactory, CompileSpecToArguments<T> toArguments) {
+ this.argWriterFactory = argWriterFactory;
+ this.toArguments = toArguments;
+ }
+
+ public void collectArguments(T spec, ArgCollector collector) {
+ GFileUtils.mkdirs(spec.getTempDir());
+ File optionsFile = new File(spec.getTempDir(), "compiler-options.txt");
+ try {
+ PrintWriter writer = new PrintWriter(optionsFile);
+ ArgWriter argWriter = argWriterFactory.transform(writer);
+ try {
+ toArguments.collectArguments(spec, argWriter);
+ } finally {
+ writer.close();
+ }
+ } catch (IOException e) {
+ throw new UncheckedIOException(String.format("Could not write compiler options file '%s'.", optionsFile.getAbsolutePath()), e);
+ }
+
+ collector.args(String.format("@%s", optionsFile.getAbsolutePath()));
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/CommandLineTool.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/CommandLineTool.java
new file mode 100755
index 0000000..5a77d5e
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/CommandLineTool.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.toolchain.internal;
+
+import com.google.common.base.Joiner;
+import org.gradle.api.GradleException;
+import org.gradle.api.internal.tasks.SimpleWorkResult;
+import org.gradle.api.internal.tasks.compile.CompileSpec;
+import org.gradle.api.internal.tasks.compile.CompileSpecToArguments;
+import org.gradle.api.internal.tasks.compile.ExecSpecBackedArgCollector;
+import org.gradle.api.tasks.WorkResult;
+import org.gradle.internal.Factory;
+import org.gradle.internal.os.OperatingSystem;
+import org.gradle.process.internal.ExecAction;
+import org.gradle.process.internal.ExecException;
+import org.gradle.util.GFileUtils;
+import org.gradle.util.GUtil;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class CommandLineTool<T extends CompileSpec> {
+ private final String action;
+ private final File executable;
+ private final Factory<ExecAction> execActionFactory;
+ private final Map<String, String> environment = new HashMap<String, String>();
+ private CompileSpecToArguments<T> toArguments;
+ private File workDir;
+ private String path;
+
+ public CommandLineTool(String action, File executable, Factory<ExecAction> execActionFactory) {
+ this.action = action;
+ this.executable = executable;
+ this.execActionFactory = execActionFactory;
+ }
+
+ public CommandLineTool<T> inWorkDirectory(File workDir) {
+ GFileUtils.mkdirs(workDir);
+ this.workDir = workDir;
+ return this;
+ }
+
+ public CommandLineTool<T> withPath(List<File> pathEntries) {
+ path = Joiner.on(File.pathSeparator).join(pathEntries);
+ return this;
+ }
+
+ public CommandLineTool<T> withEnvironment(Map<String, String> environment) {
+ this.environment.putAll(environment);
+ return this;
+ }
+
+ public CommandLineTool<T> withArguments(CompileSpecToArguments<T> arguments) {
+ this.toArguments = arguments;
+ return this;
+ }
+
+ public WorkResult execute(T spec) {
+ ExecAction compiler = execActionFactory.create();
+ compiler.executable(executable);
+ if (workDir != null) {
+ compiler.workingDir(workDir);
+ }
+
+ toArguments.collectArguments(spec, new ExecSpecBackedArgCollector(compiler));
+
+ if (GUtil.isTrue(path)) {
+ String pathVar = OperatingSystem.current().getPathVar();
+ String compilerPath = path + File.pathSeparator + System.getenv(pathVar);
+ compiler.environment(pathVar, compilerPath);
+ }
+
+ compiler.environment(environment);
+
+ try {
+ compiler.execute();
+ } catch (ExecException e) {
+ throw new GradleException(String.format("%s failed; see the error output for details.", action), e);
+ }
+ return new SimpleWorkResult(true);
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/ToolRegistry.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/ToolRegistry.java
new file mode 100644
index 0000000..dca2914
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/ToolRegistry.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.toolchain.internal;
+
+import org.gradle.internal.os.OperatingSystem;
+
+import java.io.File;
+import java.util.*;
+
+public class ToolRegistry {
+ private final Map<ToolType, String> executableNames = new HashMap<ToolType, String>();
+ private final Map<String, File> executables = new HashMap<String, File>();
+ private final List<File> pathEntries = new ArrayList<File>();
+
+ private final OperatingSystem operatingSystem;
+
+ public ToolRegistry(OperatingSystem operatingSystem) {
+ this.operatingSystem = operatingSystem;
+ }
+
+ public List<File> getPath() {
+ return pathEntries;
+ }
+
+ public void setPath(List<File> pathEntries) {
+ this.pathEntries.clear();
+ this.pathEntries.addAll(pathEntries);
+ executables.clear();
+ }
+
+ public void path(File pathEntry) {
+ pathEntries.add(pathEntry);
+ executables.clear();
+ }
+
+ public String getExeName(ToolType key) {
+ return executableNames.get(key);
+ }
+
+ public void setExeName(ToolType key, String name) {
+ executableNames.put(key, name);
+ }
+
+ public File locate(ToolType key) {
+ String exeName = executableNames.get(key);
+ if (executables.containsKey(exeName)) {
+ return executables.get(exeName);
+ }
+ File exe = findExecutable(operatingSystem, exeName);
+ executables.put(exeName, exe);
+ return exe;
+ }
+
+ protected File findExecutable(OperatingSystem operatingSystem, String name) {
+ String exeName = operatingSystem.getExecutableName(name);
+ for (File pathEntry : pathEntries) {
+ File candidate = new File(pathEntry, exeName);
+ if (candidate.isFile()) {
+ return candidate;
+ }
+ }
+ return operatingSystem.findInPath(name);
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/ToolType.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/ToolType.java
new file mode 100644
index 0000000..74f9eaf
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/ToolType.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.toolchain.internal;
+
+import org.gradle.util.GUtil;
+
+public enum ToolType {
+ CPP_COMPILER("C++ compiler"),
+ C_COMPILER("C compiler"),
+ ASSEMBLER("Assembler"),
+ LINKER("Linker"),
+ STATIC_LIB_ARCHIVER("Static library archiver");
+
+ private final String toolName;
+
+ ToolType(String toolName) {
+ this.toolName = toolName;
+ }
+
+ public String getToolName() {
+ return toolName;
+ }
+
+ @Override
+ public String toString() {
+ return GUtil.toLowerCamelCase(name());
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/gpp/ArStaticLibraryArchiver.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/gpp/ArStaticLibraryArchiver.java
new file mode 100755
index 0000000..e07e814
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/gpp/ArStaticLibraryArchiver.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.toolchain.internal.gpp;
+
+import org.gradle.api.internal.tasks.compile.ArgCollector;
+import org.gradle.api.internal.tasks.compile.CompileSpecToArguments;
+import org.gradle.api.internal.tasks.compile.Compiler;
+import org.gradle.api.tasks.WorkResult;
+import org.gradle.nativecode.base.internal.StaticLibraryArchiverSpec;
+import org.gradle.nativecode.toolchain.internal.CommandLineTool;
+
+import java.io.File;
+
+/**
+ * A static library linker based on the GNU 'ar' utility
+ */
+
+class ArStaticLibraryArchiver implements Compiler<StaticLibraryArchiverSpec> {
+ private final CommandLineTool<StaticLibraryArchiverSpec> commandLineTool;
+
+ public ArStaticLibraryArchiver(CommandLineTool<StaticLibraryArchiverSpec> commandLineTool) {
+ this.commandLineTool = commandLineTool.withArguments(new ArchiverSpecToArguments());
+ }
+
+ public WorkResult execute(StaticLibraryArchiverSpec spec) {
+ return commandLineTool.execute(spec);
+ }
+
+ private static class ArchiverSpecToArguments implements CompileSpecToArguments<StaticLibraryArchiverSpec> {
+ public void collectArguments(StaticLibraryArchiverSpec spec, ArgCollector collector) {
+ collector.args("-rc", spec.getOutputFile().getAbsolutePath());
+ collector.args(spec.getArgs());
+ for (File file : spec.getSource()) {
+ collector.args(file.getAbsolutePath());
+ }
+ }
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/gpp/Assembler.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/gpp/Assembler.java
new file mode 100755
index 0000000..cec664a
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/gpp/Assembler.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.toolchain.internal.gpp;
+
+import org.gradle.api.internal.tasks.SimpleWorkResult;
+import org.gradle.api.internal.tasks.compile.ArgCollector;
+import org.gradle.api.internal.tasks.compile.CompileSpecToArguments;
+import org.gradle.api.internal.tasks.compile.Compiler;
+import org.gradle.api.tasks.WorkResult;
+import org.gradle.nativecode.language.asm.internal.AssembleSpec;
+import org.gradle.nativecode.toolchain.internal.CommandLineTool;
+
+import java.io.File;
+
+class Assembler implements Compiler<AssembleSpec> {
+
+ private final CommandLineTool<AssembleSpec> commandLineTool;
+
+ public Assembler(CommandLineTool<AssembleSpec> commandLineTool) {
+ this.commandLineTool = commandLineTool;
+ }
+
+ public WorkResult execute(AssembleSpec spec) {
+ boolean didWork = false;
+ CommandLineTool<AssembleSpec> commandLineAssembler = commandLineTool.inWorkDirectory(spec.getObjectFileDir());
+ for (File sourceFile : spec.getSource()) {
+ WorkResult result = commandLineAssembler.withArguments(new AssemblerSpecToArguments(sourceFile)).execute(spec);
+ didWork = didWork || result.getDidWork();
+ }
+ return new SimpleWorkResult(didWork);
+ }
+
+
+ private static class AssemblerSpecToArguments implements CompileSpecToArguments<AssembleSpec> {
+ private final File inputFile;
+ private final String outputFileName;
+
+ public AssemblerSpecToArguments(File inputFile) {
+ this.inputFile = inputFile;
+ this.outputFileName = inputFile.getName() + ".o";
+ }
+
+ public void collectArguments(AssembleSpec spec, ArgCollector collector) {
+ for (String rawArg : spec.getArgs()) {
+ collector.args(rawArg);
+ }
+ collector.args("-o", outputFileName);
+ collector.args(inputFile.getAbsolutePath());
+ }
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/gpp/CCompiler.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/gpp/CCompiler.java
new file mode 100755
index 0000000..7ad2fd2
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/gpp/CCompiler.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.toolchain.internal.gpp;
+
+import org.gradle.api.internal.tasks.compile.ArgCollector;
+import org.gradle.api.internal.tasks.compile.Compiler;
+import org.gradle.api.tasks.WorkResult;
+import org.gradle.nativecode.language.c.internal.CCompileSpec;
+import org.gradle.nativecode.toolchain.internal.CommandLineTool;
+
+class CCompiler implements Compiler<CCompileSpec> {
+
+ private final CommandLineTool<CCompileSpec> commandLineTool;
+
+ public CCompiler(CommandLineTool<CCompileSpec> commandLineTool, boolean useCommandFile) {
+ GccCompileSpecToArguments<CCompileSpec> specToArguments = new GccCompileSpecToArguments<CCompileSpec>(
+ new CCompileOptionsToArguments(),
+ new GccCompileSourcesToArguments<CCompileSpec>(),
+ useCommandFile
+ );
+ this.commandLineTool = commandLineTool.withArguments(specToArguments);
+ }
+
+ public WorkResult execute(CCompileSpec spec) {
+ return commandLineTool.inWorkDirectory(spec.getObjectFileDir()).execute(spec);
+ }
+
+ private static class CCompileOptionsToArguments extends GeneralGccCompileOptionsToArguments<CCompileSpec> {
+ public void collectArguments(CCompileSpec spec, ArgCollector collector) {
+ // C-compiling options
+ collector.args("-x", "c");
+
+ super.collectArguments(spec, collector);
+ }
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/gpp/CppCompiler.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/gpp/CppCompiler.java
new file mode 100755
index 0000000..ccf45e0
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/gpp/CppCompiler.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.toolchain.internal.gpp;
+
+import org.gradle.api.internal.tasks.compile.ArgCollector;
+import org.gradle.api.internal.tasks.compile.Compiler;
+import org.gradle.api.tasks.WorkResult;
+import org.gradle.nativecode.language.cpp.internal.CppCompileSpec;
+import org.gradle.nativecode.toolchain.internal.CommandLineTool;
+
+class CppCompiler implements Compiler<CppCompileSpec> {
+
+ private final CommandLineTool<CppCompileSpec> commandLineTool;
+
+ public CppCompiler(CommandLineTool<CppCompileSpec> commandLineTool, boolean useCommandFile) {
+ GccCompileSpecToArguments<CppCompileSpec> specToArguments = new GccCompileSpecToArguments<CppCompileSpec>(
+ new CppCompileOptionsToArguments(),
+ new GccCompileSourcesToArguments<CppCompileSpec>(),
+ useCommandFile
+ );
+ this.commandLineTool = commandLineTool.withArguments(specToArguments);
+ }
+
+ public WorkResult execute(CppCompileSpec spec) {
+ return commandLineTool.inWorkDirectory(spec.getObjectFileDir()).execute(spec);
+ }
+
+ // Certain options do not function correctly via an option file, so only use option file for headers and sources
+ private static class CppCompileOptionsToArguments extends GeneralGccCompileOptionsToArguments<CppCompileSpec> {
+ @Override
+ public void collectArguments(CppCompileSpec spec, ArgCollector collector) {
+ // C++-compiling options
+ collector.args("-x", "c++");
+
+ super.collectArguments(spec, collector);
+ }
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/gpp/GccCompileSourcesToArguments.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/gpp/GccCompileSourcesToArguments.java
new file mode 100644
index 0000000..a1059ea
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/gpp/GccCompileSourcesToArguments.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.toolchain.internal.gpp;
+
+import org.gradle.api.internal.tasks.compile.ArgCollector;
+import org.gradle.api.internal.tasks.compile.CompileSpecToArguments;
+import org.gradle.nativecode.language.base.internal.NativeCompileSpec;
+
+import java.io.File;
+
+class GccCompileSourcesToArguments<T extends NativeCompileSpec> implements CompileSpecToArguments<T> {
+ public void collectArguments(T spec, ArgCollector collector) {
+ for (File file : spec.getIncludeRoots()) {
+ collector.args("-I");
+ collector.args(file.getAbsolutePath());
+ }
+ for (File file : spec.getSource()) {
+ collector.args(file.getAbsolutePath());
+ }
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/gpp/GccCompileSpecToArguments.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/gpp/GccCompileSpecToArguments.java
new file mode 100644
index 0000000..a15b4aa
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/gpp/GccCompileSpecToArguments.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.toolchain.internal.gpp;
+
+import org.gradle.api.internal.tasks.compile.ArgCollector;
+import org.gradle.api.internal.tasks.compile.ArgWriter;
+import org.gradle.api.internal.tasks.compile.CompileSpecToArguments;
+import org.gradle.nativecode.base.internal.BinaryToolSpec;
+import org.gradle.nativecode.toolchain.internal.CommandLineCompilerArgumentsToOptionFile;
+
+/**
+ * Some GCC options do not function correctly when included in an option file, so only use the option file for include paths and source files.
+ */
+public class GccCompileSpecToArguments<T extends BinaryToolSpec> implements CompileSpecToArguments<T> {
+ private final CompileSpecToArguments<T> optionsToArguments;
+ private final CompileSpecToArguments<T> sourcesToArguments;
+
+ public GccCompileSpecToArguments(CompileSpecToArguments<T> optionsToArguments, CompileSpecToArguments<T> sourcesToArguments, boolean useOptionFile) {
+ this.optionsToArguments = optionsToArguments;
+
+ // Only use an option file for header paths and source files (some other options don't function correctly in option file
+ if (useOptionFile) {
+ this.sourcesToArguments = withOptionFile(sourcesToArguments);
+ } else {
+ this.sourcesToArguments = sourcesToArguments;
+ }
+ }
+
+ private CommandLineCompilerArgumentsToOptionFile<T> withOptionFile(CompileSpecToArguments<T> sourcesToArguments) {
+ return new CommandLineCompilerArgumentsToOptionFile<T>(ArgWriter.unixStyleFactory(), sourcesToArguments);
+ }
+
+ public void collectArguments(T spec, ArgCollector collector) {
+ optionsToArguments.collectArguments(spec, collector);
+ sourcesToArguments.collectArguments(spec, collector);
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/gpp/GccToolRegistry.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/gpp/GccToolRegistry.java
new file mode 100644
index 0000000..ec692b1
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/gpp/GccToolRegistry.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.toolchain.internal.gpp;
+
+import org.gradle.internal.os.OperatingSystem;
+import org.gradle.nativecode.toolchain.internal.ToolRegistry;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.List;
+
+public class GccToolRegistry extends ToolRegistry {
+ public GccToolRegistry(OperatingSystem operatingSystem) {
+ super(operatingSystem);
+ }
+
+ @Override
+ protected File findExecutable(OperatingSystem operatingSystem, String name) {
+ List<String> candidates;
+ if (operatingSystem.isWindows()) {
+ // Under Cygwin, g++/gcc is a Cygwin symlink to either g++-3 or g++-4. We can't run g++ directly
+ candidates = Arrays.asList(name + "-4", name + "-3", name);
+ } else {
+ candidates = Arrays.asList(name);
+ }
+ for (String candidate : candidates) {
+ File executable = super.findExecutable(operatingSystem, candidate);
+ if (executable != null) {
+ return executable;
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/gpp/GeneralGccCompileOptionsToArguments.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/gpp/GeneralGccCompileOptionsToArguments.java
new file mode 100644
index 0000000..95a2e33
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/gpp/GeneralGccCompileOptionsToArguments.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.toolchain.internal.gpp;
+
+import org.gradle.api.internal.tasks.compile.ArgCollector;
+import org.gradle.api.internal.tasks.compile.CompileSpecToArguments;
+import org.gradle.internal.os.OperatingSystem;
+import org.gradle.nativecode.language.base.internal.NativeCompileSpec;
+
+/**
+ * Maps common options for C/C++ compiling with GCC
+ */
+class GeneralGccCompileOptionsToArguments<T extends NativeCompileSpec> implements CompileSpecToArguments<T> {
+ public void collectArguments(T spec, ArgCollector collector) {
+ for (String macro : spec.getMacros()) {
+ collector.args("-D" + macro);
+ }
+ collector.args(spec.getArgs());
+ collector.args("-c");
+ if (spec.isPositionIndependentCode()) {
+ if (!OperatingSystem.current().isWindows()) {
+ collector.args("-fPIC");
+ }
+ }
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/gpp/GppLinker.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/gpp/GppLinker.java
new file mode 100755
index 0000000..48960ed
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/gpp/GppLinker.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.toolchain.internal.gpp;
+
+import org.gradle.api.internal.tasks.compile.ArgCollector;
+import org.gradle.api.internal.tasks.compile.ArgWriter;
+import org.gradle.api.internal.tasks.compile.CompileSpecToArguments;
+import org.gradle.api.internal.tasks.compile.Compiler;
+import org.gradle.api.tasks.WorkResult;
+import org.gradle.internal.os.OperatingSystem;
+import org.gradle.nativecode.base.internal.LinkerSpec;
+import org.gradle.nativecode.base.internal.SharedLibraryLinkerSpec;
+import org.gradle.nativecode.toolchain.internal.CommandLineCompilerArgumentsToOptionFile;
+import org.gradle.nativecode.toolchain.internal.CommandLineTool;
+
+import java.io.File;
+
+class GppLinker implements Compiler<LinkerSpec> {
+
+ private final CommandLineTool<LinkerSpec> commandLineTool;
+
+ public GppLinker(CommandLineTool<LinkerSpec> commandLineTool, boolean useCommandFile) {
+ this.commandLineTool = commandLineTool.withArguments(useCommandFile ? viaCommandFile() : withoutCommandFile());
+ }
+
+ private static GppLinkerSpecToArguments withoutCommandFile() {
+ return new GppLinkerSpecToArguments();
+ }
+
+ private static CommandLineCompilerArgumentsToOptionFile<LinkerSpec> viaCommandFile() {
+ return new CommandLineCompilerArgumentsToOptionFile<LinkerSpec>(
+ ArgWriter.unixStyleFactory(), new GppLinkerSpecToArguments()
+ );
+ }
+
+ public WorkResult execute(LinkerSpec spec) {
+ return commandLineTool.execute(spec);
+ }
+
+ private static class GppLinkerSpecToArguments implements CompileSpecToArguments<LinkerSpec> {
+
+ public void collectArguments(LinkerSpec spec, ArgCollector collector) {
+ for (String rawArg : spec.getArgs()) {
+ collector.args("-Xlinker", rawArg);
+ }
+ if (spec instanceof SharedLibraryLinkerSpec) {
+ collector.args("-shared");
+ if (!OperatingSystem.current().isWindows()) {
+ String installName = ((SharedLibraryLinkerSpec) spec).getInstallName();
+ if (OperatingSystem.current().isMacOsX()) {
+ collector.args("-Wl,-install_name," + installName);
+ } else {
+ collector.args("-Wl,-soname," + installName);
+ }
+ }
+ }
+ collector.args("-o", spec.getOutputFile().getAbsolutePath());
+ for (File file : spec.getSource()) {
+ collector.args(file.getAbsolutePath());
+ }
+ for (File file : spec.getLibs()) {
+ collector.args(file.getAbsolutePath());
+ }
+ }
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/gpp/GppToolChain.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/gpp/GppToolChain.java
new file mode 100755
index 0000000..cef886f
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/gpp/GppToolChain.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.toolchain.internal.gpp;
+
+import org.gradle.api.Transformer;
+import org.gradle.api.internal.file.FileResolver;
+import org.gradle.api.internal.tasks.compile.Compiler;
+import org.gradle.internal.Factory;
+import org.gradle.internal.os.OperatingSystem;
+import org.gradle.nativecode.base.internal.*;
+import org.gradle.nativecode.language.asm.internal.AssembleSpec;
+import org.gradle.nativecode.language.c.internal.CCompileSpec;
+import org.gradle.nativecode.language.cpp.internal.CppCompileSpec;
+import org.gradle.nativecode.toolchain.Gcc;
+import org.gradle.nativecode.toolchain.internal.CommandLineTool;
+import org.gradle.nativecode.toolchain.internal.ToolType;
+import org.gradle.nativecode.toolchain.internal.gpp.version.GppVersionDeterminer;
+import org.gradle.process.internal.ExecAction;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+
+/**
+ * Compiler adapter for GCC.
+ */
+public class GppToolChain extends AbstractToolChain implements Gcc {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(GppToolChain.class);
+
+ public static final String DEFAULT_NAME = "gcc";
+
+ private final Factory<ExecAction> execActionFactory;
+ private final Transformer<String, File> versionDeterminer;
+
+ private String version;
+
+ public GppToolChain(String name, OperatingSystem operatingSystem, FileResolver fileResolver, Factory<ExecAction> execActionFactory) {
+ super(name, operatingSystem, new GccToolRegistry(operatingSystem), fileResolver);
+ this.execActionFactory = execActionFactory;
+ this.versionDeterminer = new GppVersionDeterminer();
+
+ tools.setExeName(ToolType.CPP_COMPILER, "g++");
+ tools.setExeName(ToolType.C_COMPILER, "gcc");
+ tools.setExeName(ToolType.ASSEMBLER, "as");
+ tools.setExeName(ToolType.LINKER, "g++");
+ tools.setExeName(ToolType.STATIC_LIB_ARCHIVER, "ar");
+ }
+
+ @Override
+ protected String getTypeName() {
+ return "GNU G++";
+ }
+
+ @Override
+ protected void checkAvailable(ToolChainAvailability availability) {
+ for (ToolType key : ToolType.values()) {
+ availability.mustExist(key.getToolName(), tools.locate(key));
+ }
+ determineVersion();
+ if (version == null) {
+ availability.unavailable("Could not determine G++ version");
+ }
+ }
+
+ public <T extends BinaryToolSpec> Compiler<T> createCppCompiler() {
+ checkAvailable();
+ CommandLineTool<CppCompileSpec> commandLineTool = commandLineTool(ToolType.CPP_COMPILER);
+ return (Compiler<T>) new CppCompiler(commandLineTool, canUseCommandFile());
+ }
+
+ public <T extends BinaryToolSpec> Compiler<T> createCCompiler() {
+ checkAvailable();
+ CommandLineTool<CCompileSpec> commandLineTool = commandLineTool(ToolType.C_COMPILER);
+ return (Compiler<T>) new CCompiler(commandLineTool, canUseCommandFile());
+ }
+
+ public <T extends BinaryToolSpec> Compiler<T> createAssembler() {
+ checkAvailable();
+ CommandLineTool<AssembleSpec> commandLineTool = commandLineTool(ToolType.ASSEMBLER);
+ return (Compiler<T>) new Assembler(commandLineTool);
+ }
+
+ public <T extends LinkerSpec> Compiler<T> createLinker() {
+ checkAvailable();
+ CommandLineTool<LinkerSpec> commandLineTool = commandLineTool(ToolType.LINKER);
+ return (Compiler<T>) new GppLinker(commandLineTool, canUseCommandFile());
+ }
+
+ public <T extends StaticLibraryArchiverSpec> Compiler<T> createStaticLibraryArchiver() {
+ checkAvailable();
+ CommandLineTool<StaticLibraryArchiverSpec> commandLineTool = commandLineTool(ToolType.STATIC_LIB_ARCHIVER);
+ return (Compiler<T>) new ArStaticLibraryArchiver(commandLineTool);
+ }
+
+ private <T extends BinaryToolSpec> CommandLineTool<T> commandLineTool(ToolType key) {
+ CommandLineTool<T> commandLineTool = new CommandLineTool<T>(key.getToolName(), tools.locate(key), execActionFactory);
+ commandLineTool.withPath(getPaths());
+ return commandLineTool;
+ }
+
+ private void determineVersion() {
+ version = determineVersion(tools.locate(ToolType.CPP_COMPILER));
+ if (version == null) {
+ LOGGER.info("Did not find {} on system", ToolType.CPP_COMPILER.getToolName());
+ } else {
+ LOGGER.info("Found {} with version {}", ToolType.CPP_COMPILER.getToolName(), version);
+ }
+ }
+
+ private String determineVersion(File executable) {
+ return executable == null ? null : versionDeterminer.transform(executable);
+ }
+
+ private boolean canUseCommandFile() {
+ String[] components = version.split("\\.");
+ int majorVersion;
+ try {
+ majorVersion = Integer.valueOf(components[0]);
+ } catch (NumberFormatException e) {
+ throw new IllegalStateException(String.format("Unable to determine major g++ version from version number %s.", version), e);
+ }
+ return majorVersion >= 4;
+ }
+
+}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/gpp/version/GppVersionDeterminer.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/gpp/version/GppVersionDeterminer.java
new file mode 100644
index 0000000..1bacb34
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/gpp/version/GppVersionDeterminer.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.toolchain.internal.gpp.version;
+
+import org.gradle.api.Transformer;
+import org.gradle.api.internal.file.IdentityFileResolver;
+import org.gradle.internal.Factory;
+import org.gradle.process.ExecResult;
+import org.gradle.process.internal.ExecHandle;
+import org.gradle.process.internal.ExecHandleBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Given a File pointing to an (existing) g++ binary, extracts the version number by running with -v and scraping the output.
+ */
+public class GppVersionDeterminer implements Transformer<String, File> {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(GppVersionDeterminer.class);
+
+ private final Transformer<String, String> outputScraper;
+ private final Transformer<String, File> outputProducer;
+
+ public GppVersionDeterminer() {
+ this(new GppVersionOutputProducer(new Factory<ExecHandleBuilder>() {
+ public ExecHandleBuilder create() {
+ return new ExecHandleBuilder(new IdentityFileResolver());
+ }
+ }), new GppVersionOutputScraper());
+ }
+
+ GppVersionDeterminer(Transformer<String, File> outputProducer, Transformer<String, String> outputScraper) {
+ this.outputProducer = outputProducer;
+ this.outputScraper = outputScraper;
+ }
+
+ static class GppVersionOutputScraper implements Transformer<String, String> {
+ public String transform(String output) {
+ Pattern pattern = Pattern.compile(".*gcc version (\\S+).*", Pattern.DOTALL);
+ Matcher matcher = pattern.matcher(output);
+ if (matcher.matches()) {
+ String scrapedVersion = matcher.group(1);
+ LOGGER.debug("Extracted version {} from g++ -v output", scrapedVersion);
+ return scrapedVersion;
+ } else {
+ LOGGER.warn("Unable to extract g++ version number from \"{}\" with pattern \"{}\"", output, pattern);
+ return null;
+ }
+ }
+ }
+
+ static class GppVersionOutputProducer implements Transformer<String, File> {
+
+ private final Factory<ExecHandleBuilder> execHandleBuilderFactory;
+
+ GppVersionOutputProducer(Factory<ExecHandleBuilder> execHandleBuilderFactory) {
+ this.execHandleBuilderFactory = execHandleBuilderFactory;
+ }
+
+ public String transform(File gppBinary) {
+ ExecHandleBuilder exec = execHandleBuilderFactory.create();
+ exec.executable(gppBinary.getAbsolutePath());
+ exec.setWorkingDir(gppBinary.getParentFile());
+ exec.args("-v");
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ exec.setErrorOutput(baos);
+ ExecHandle handle = exec.build();
+ ExecResult result = handle.start().waitForFinish();
+
+ int exitValue = result.getExitValue();
+ if (exitValue == 0) {
+ String output = new String(baos.toByteArray());
+ LOGGER.debug("Output from '{} -v {}", gppBinary.getPath(), output);
+ return output;
+ } else {
+ LOGGER.warn("Executing '{} -v' return exit code {}, cannot use", gppBinary.getPath(), exitValue);
+ return null;
+ }
+ }
+ }
+
+ public String transform(File gppBinary) {
+ String output = outputProducer.transform(gppBinary);
+ return output == null ? null : outputScraper.transform(output);
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/msvcpp/Assembler.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/msvcpp/Assembler.java
new file mode 100755
index 0000000..14c5d1b
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/msvcpp/Assembler.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.toolchain.internal.msvcpp;
+
+import org.gradle.api.internal.tasks.SimpleWorkResult;
+import org.gradle.api.internal.tasks.compile.ArgCollector;
+import org.gradle.api.internal.tasks.compile.CompileSpecToArguments;
+import org.gradle.api.internal.tasks.compile.Compiler;
+import org.gradle.api.tasks.WorkResult;
+import org.gradle.nativecode.language.asm.internal.AssembleSpec;
+import org.gradle.nativecode.toolchain.internal.CommandLineTool;
+
+import java.io.File;
+
+class Assembler implements Compiler<AssembleSpec> {
+
+ private final CommandLineTool<AssembleSpec> commandLineTool;
+
+ public Assembler(CommandLineTool<AssembleSpec> commandLineTool) {
+ this.commandLineTool = commandLineTool;
+ }
+
+ public WorkResult execute(AssembleSpec spec) {
+ boolean didWork = false;
+ CommandLineTool<AssembleSpec> commandLineAssembler = commandLineTool.inWorkDirectory(spec.getObjectFileDir());
+ for (File sourceFile : spec.getSource()) {
+ WorkResult result = commandLineAssembler.withArguments(new AssemblerSpecToArguments(sourceFile)).execute(spec);
+ didWork = didWork || result.getDidWork();
+ }
+ return new SimpleWorkResult(didWork);
+ }
+
+
+ private static class AssemblerSpecToArguments implements CompileSpecToArguments<AssembleSpec> {
+ private final File inputFile;
+
+ public AssemblerSpecToArguments(File inputFile) {
+ this.inputFile = inputFile;
+ }
+
+ public void collectArguments(AssembleSpec spec, ArgCollector collector) {
+ for (String rawArg : spec.getArgs()) {
+ collector.args(rawArg);
+ }
+ collector.args("/nologo");
+ collector.args("/c");
+ collector.args(inputFile.getAbsolutePath());
+ }
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/msvcpp/CCompiler.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/msvcpp/CCompiler.java
new file mode 100755
index 0000000..764f25c
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/msvcpp/CCompiler.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.toolchain.internal.msvcpp;
+
+import org.gradle.api.internal.tasks.compile.ArgCollector;
+import org.gradle.api.internal.tasks.compile.ArgWriter;
+import org.gradle.api.internal.tasks.compile.Compiler;
+import org.gradle.api.tasks.WorkResult;
+import org.gradle.nativecode.language.c.internal.CCompileSpec;
+import org.gradle.nativecode.toolchain.internal.CommandLineCompilerArgumentsToOptionFile;
+import org.gradle.nativecode.toolchain.internal.CommandLineTool;
+
+class CCompiler implements Compiler<CCompileSpec> {
+
+ private final CommandLineTool<CCompileSpec> commandLineTool;
+
+ CCompiler(CommandLineTool<CCompileSpec> commandLineTool) {
+ this.commandLineTool = commandLineTool
+ .withArguments(new CommandLineCompilerArgumentsToOptionFile<CCompileSpec>(
+ ArgWriter.windowsStyleFactory(), new CCompileSpecToArguments()
+ ));
+ }
+
+ public WorkResult execute(CCompileSpec spec) {
+ return commandLineTool.inWorkDirectory(spec.getObjectFileDir()).execute(spec);
+ }
+
+ private static class CCompileSpecToArguments extends GeneralVisualCppCompileSpecToArguments<CCompileSpec> {
+ public void collectArguments(CCompileSpec spec, ArgCollector collector) {
+ // C-compiling options
+ collector.args("/TC");
+
+ super.collectArguments(spec, collector);
+ }
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/msvcpp/CppCompiler.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/msvcpp/CppCompiler.java
new file mode 100755
index 0000000..a06eaba
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/msvcpp/CppCompiler.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.toolchain.internal.msvcpp;
+
+import org.gradle.api.internal.tasks.compile.ArgCollector;
+import org.gradle.api.internal.tasks.compile.ArgWriter;
+import org.gradle.api.internal.tasks.compile.Compiler;
+import org.gradle.api.tasks.WorkResult;
+import org.gradle.nativecode.language.cpp.internal.CppCompileSpec;
+import org.gradle.nativecode.toolchain.internal.CommandLineCompilerArgumentsToOptionFile;
+import org.gradle.nativecode.toolchain.internal.CommandLineTool;
+
+class CppCompiler implements Compiler<CppCompileSpec> {
+
+ private final CommandLineTool<CppCompileSpec> commandLineTool;
+
+ CppCompiler(CommandLineTool<CppCompileSpec> commandLineTool) {
+ this.commandLineTool = commandLineTool.withArguments(
+ new CommandLineCompilerArgumentsToOptionFile<CppCompileSpec>(ArgWriter.windowsStyleFactory(), new CppCompileSpecToArguments())
+ );
+ }
+
+ public WorkResult execute(CppCompileSpec spec) {
+ return commandLineTool.inWorkDirectory(spec.getObjectFileDir()).execute(spec);
+ }
+
+ private static class CppCompileSpecToArguments extends GeneralVisualCppCompileSpecToArguments<CppCompileSpec> {
+ public void collectArguments(CppCompileSpec spec, ArgCollector collector) {
+ // C++-compiling options
+ collector.args("/TP");
+
+ super.collectArguments(spec, collector);
+ }
+ }
+ }
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/msvcpp/GeneralVisualCppCompileSpecToArguments.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/msvcpp/GeneralVisualCppCompileSpecToArguments.java
new file mode 100644
index 0000000..9ba900b
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/msvcpp/GeneralVisualCppCompileSpecToArguments.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.toolchain.internal.msvcpp;
+
+import org.gradle.api.internal.tasks.compile.ArgCollector;
+import org.gradle.api.internal.tasks.compile.CompileSpecToArguments;
+import org.gradle.nativecode.language.base.internal.NativeCompileSpec;
+
+import java.io.File;
+
+class GeneralVisualCppCompileSpecToArguments<T extends NativeCompileSpec> implements CompileSpecToArguments<T> {
+ public void collectArguments(T spec, ArgCollector collector) {
+ collector.args("/nologo");
+ for (String macro : spec.getMacros()) {
+ collector.args("/D" + macro);
+ }
+ collector.args(spec.getArgs());
+ collector.args("/c");
+ if (spec.isPositionIndependentCode()) {
+ collector.args("/LD"); // TODO:DAZ Not sure if this has any effect at compile time
+ }
+ for (File file : spec.getIncludeRoots()) {
+ collector.args("/I", file.getAbsolutePath());
+ }
+ for (File file : spec.getSource()) {
+ collector.args(file);
+ }
+ }
+
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/msvcpp/LibExeStaticLibraryArchiver.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/msvcpp/LibExeStaticLibraryArchiver.java
new file mode 100755
index 0000000..8e5da69
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/msvcpp/LibExeStaticLibraryArchiver.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.toolchain.internal.msvcpp;
+
+import org.gradle.api.internal.tasks.compile.ArgCollector;
+import org.gradle.api.internal.tasks.compile.ArgWriter;
+import org.gradle.api.internal.tasks.compile.CompileSpecToArguments;
+import org.gradle.api.internal.tasks.compile.Compiler;
+import org.gradle.api.tasks.WorkResult;
+import org.gradle.nativecode.base.internal.StaticLibraryArchiverSpec;
+import org.gradle.nativecode.toolchain.internal.CommandLineCompilerArgumentsToOptionFile;
+import org.gradle.nativecode.toolchain.internal.CommandLineTool;
+
+import java.io.File;
+
+class LibExeStaticLibraryArchiver implements Compiler<StaticLibraryArchiverSpec> {
+ private final CommandLineTool<StaticLibraryArchiverSpec> commandLineTool;
+
+ public LibExeStaticLibraryArchiver(CommandLineTool<StaticLibraryArchiverSpec> commandLineTool) {
+ this.commandLineTool = commandLineTool
+ .withArguments(new CommandLineCompilerArgumentsToOptionFile<StaticLibraryArchiverSpec>(ArgWriter.windowsStyleFactory(), new LibExeSpecToArguments()
+ ));
+ }
+
+ public WorkResult execute(StaticLibraryArchiverSpec spec) {
+ return commandLineTool.execute(spec);
+ }
+
+ private static class LibExeSpecToArguments implements CompileSpecToArguments<StaticLibraryArchiverSpec> {
+ public void collectArguments(StaticLibraryArchiverSpec spec, ArgCollector collector) {
+ collector.args("/OUT:" + spec.getOutputFile().getAbsolutePath());
+ collector.args("/NOLOGO");
+ collector.args(spec.getArgs());
+ for (File file : spec.getSource()) {
+ collector.args(file.getAbsolutePath());
+ }
+ }
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/msvcpp/LinkExeLinker.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/msvcpp/LinkExeLinker.java
new file mode 100755
index 0000000..417922a
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/msvcpp/LinkExeLinker.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.toolchain.internal.msvcpp;
+
+import org.gradle.api.internal.tasks.compile.ArgCollector;
+import org.gradle.api.internal.tasks.compile.ArgWriter;
+import org.gradle.api.internal.tasks.compile.CompileSpecToArguments;
+import org.gradle.api.internal.tasks.compile.Compiler;
+import org.gradle.api.tasks.WorkResult;
+import org.gradle.nativecode.base.internal.LinkerSpec;
+import org.gradle.nativecode.base.internal.SharedLibraryLinkerSpec;
+import org.gradle.nativecode.toolchain.internal.CommandLineCompilerArgumentsToOptionFile;
+import org.gradle.nativecode.toolchain.internal.CommandLineTool;
+
+import java.io.File;
+
+class LinkExeLinker implements Compiler<LinkerSpec> {
+
+ private final CommandLineTool<LinkerSpec> commandLineTool;
+
+ public LinkExeLinker(CommandLineTool<LinkerSpec> commandLineTool) {
+ this.commandLineTool = commandLineTool
+ .withArguments(new CommandLineCompilerArgumentsToOptionFile<LinkerSpec>(
+ ArgWriter.windowsStyleFactory(), new VisualCppLinkerSpecArguments()
+ ));
+ }
+
+ public WorkResult execute(LinkerSpec spec) {
+ return commandLineTool.execute(spec);
+ }
+
+ private static class VisualCppLinkerSpecArguments implements CompileSpecToArguments<LinkerSpec> {
+
+ public void collectArguments(LinkerSpec spec, ArgCollector collector) {
+ collector.args(spec.getArgs());
+ collector.args("/OUT:" + spec.getOutputFile().getAbsolutePath());
+ collector.args("/NOLOGO");
+ if (spec instanceof SharedLibraryLinkerSpec) {
+ collector.args("/DLL");
+ }
+ for (File file : spec.getSource()) {
+ collector.args(file.getAbsolutePath());
+ }
+ for (File file : spec.getLibs()) {
+ collector.args(file.getAbsolutePath());
+ }
+ }
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/msvcpp/VisualCppToolChain.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/msvcpp/VisualCppToolChain.java
new file mode 100755
index 0000000..0fefdf9
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/msvcpp/VisualCppToolChain.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.toolchain.internal.msvcpp;
+
+import org.gradle.api.internal.file.FileResolver;
+import org.gradle.api.internal.tasks.compile.Compiler;
+import org.gradle.internal.Factory;
+import org.gradle.internal.os.OperatingSystem;
+import org.gradle.nativecode.base.internal.*;
+import org.gradle.nativecode.language.asm.internal.AssembleSpec;
+import org.gradle.nativecode.language.c.internal.CCompileSpec;
+import org.gradle.nativecode.language.cpp.internal.CppCompileSpec;
+import org.gradle.nativecode.toolchain.VisualCpp;
+import org.gradle.nativecode.toolchain.internal.CommandLineTool;
+import org.gradle.nativecode.toolchain.internal.ToolRegistry;
+import org.gradle.nativecode.toolchain.internal.ToolType;
+import org.gradle.process.internal.ExecAction;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+
+public class VisualCppToolChain extends AbstractToolChain implements VisualCpp {
+
+ public static final String DEFAULT_NAME = "visualCpp";
+
+ private final Factory<ExecAction> execActionFactory;
+ private final Map<String, String> environment = new HashMap<String, String>();
+
+ private File installDir;
+
+ public VisualCppToolChain(String name, OperatingSystem operatingSystem, FileResolver fileResolver, Factory<ExecAction> execActionFactory) {
+ super(name, operatingSystem, new ToolRegistry(operatingSystem), fileResolver);
+ this.execActionFactory = execActionFactory;
+
+ tools.setExeName(ToolType.CPP_COMPILER, "cl.exe");
+ tools.setExeName(ToolType.C_COMPILER, "cl.exe");
+ tools.setExeName(ToolType.ASSEMBLER, "ml.exe");
+ tools.setExeName(ToolType.LINKER, "link.exe");
+ tools.setExeName(ToolType.STATIC_LIB_ARCHIVER, "lib.exe");
+ }
+
+ @Override
+ protected String getTypeName() {
+ return "Visual C++";
+ }
+
+ @Override
+ protected void checkAvailable(ToolChainAvailability availability) {
+ if (!operatingSystem.isWindows()) {
+ availability.unavailable("Not available on this operating system.");
+ return;
+ }
+ for (ToolType key : ToolType.values()) {
+ availability.mustExist(key.getToolName(), tools.locate(key));
+ }
+ }
+
+ @Override
+ public String getSharedLibraryLinkFileName(String libraryName) {
+ return getSharedLibraryName(libraryName).replaceFirst("\\.dll$", ".lib");
+ }
+
+ public <T extends BinaryToolSpec> Compiler<T> createCppCompiler() {
+ checkAvailable();
+ CommandLineTool<CppCompileSpec> commandLineTool = commandLineTool(ToolType.CPP_COMPILER);
+ return (Compiler<T>) new CppCompiler(commandLineTool);
+ }
+
+ public <T extends BinaryToolSpec> Compiler<T> createCCompiler() {
+ checkAvailable();
+ CommandLineTool<CCompileSpec> commandLineTool = commandLineTool(ToolType.C_COMPILER);
+ return (Compiler<T>) new CCompiler(commandLineTool);
+ }
+
+ public <T extends BinaryToolSpec> Compiler<T> createAssembler() {
+ checkAvailable();
+ CommandLineTool<AssembleSpec> commandLineTool = commandLineTool(ToolType.ASSEMBLER);
+ return (Compiler<T>) new Assembler(commandLineTool);
+ }
+
+ public <T extends LinkerSpec> Compiler<T> createLinker() {
+ checkAvailable();
+ CommandLineTool<LinkerSpec> commandLineTool = commandLineTool(ToolType.LINKER);
+ return (Compiler<T>) new LinkExeLinker(commandLineTool);
+ }
+
+ public <T extends StaticLibraryArchiverSpec> Compiler<T> createStaticLibraryArchiver() {
+ checkAvailable();
+ CommandLineTool<StaticLibraryArchiverSpec> commandLineTool = commandLineTool(ToolType.STATIC_LIB_ARCHIVER);
+ return (Compiler<T>) new LibExeStaticLibraryArchiver(commandLineTool);
+ }
+
+ private <T extends BinaryToolSpec> CommandLineTool<T> commandLineTool(ToolType key) {
+ CommandLineTool<T> commandLineTool = new CommandLineTool<T>(key.getToolName(), tools.locate(key), execActionFactory);
+ commandLineTool.withPath(tools.getPath());
+ commandLineTool.withEnvironment(environment);
+ return commandLineTool;
+ }
+
+ public File getInstallDir() {
+ return installDir;
+ }
+
+ public void setInstallDir(Object installDirPath) {
+ this.installDir = resolve(installDirPath);
+
+ VisualStudioInstall install = new VisualStudioInstall(this.installDir);
+ tools.setPath(install.getPathEntries());
+ environment.clear();
+ environment.putAll(install.getEnvironment());
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/msvcpp/VisualStudioInstall.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/msvcpp/VisualStudioInstall.java
new file mode 100644
index 0000000..03f8c8d
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/internal/msvcpp/VisualStudioInstall.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.toolchain.internal.msvcpp;
+
+import java.io.File;
+import java.util.*;
+
+public class VisualStudioInstall {
+ private final File installDir;
+ private final File baseDir;
+ private final List<File> pathEntries = new ArrayList<File>();
+ private final Map<String, String> environment = new HashMap<String, String>();
+
+ public VisualStudioInstall(File installDir) {
+ this.installDir = installDir;
+ this.baseDir = locateBaseDir(installDir);
+
+ File vcDir = new File(baseDir, "VC");
+ File sdkDir = new File(baseDir.getParentFile(), "Microsoft SDKs/Windows/v7.0A");
+
+ addPathEntries(
+ new File(baseDir, "Common7/IDE"),
+ new File(vcDir, "bin"),
+ new File(baseDir, "Common7/Tools"),
+ new File(vcDir, "VCPackages"),
+ new File(sdkDir, "Bin")
+ );
+
+ environment.put("INCLUDE", new File(vcDir, "include").getAbsolutePath());
+ environment.put("LIB", new File(vcDir, "lib").getAbsolutePath() + File.pathSeparator + new File(sdkDir, "lib").getAbsolutePath());
+ }
+
+ private File locateBaseDir(File installDir) {
+ // Handle the visual studio install, VC, or VC/bin directories.
+ if (new File(installDir, "cl.exe").isFile()) {
+ return installDir.getParentFile().getParentFile();
+ } else if (new File(installDir, "bin/cl.exe").isFile()) {
+ return installDir.getParentFile();
+ }
+ return installDir;
+ }
+
+ private void addPathEntries(File... entry) {
+ pathEntries.addAll(Arrays.asList(entry));
+ }
+
+ public File getInstallDir() {
+ return installDir;
+ }
+
+ public List<File> getPathEntries() {
+ return pathEntries;
+ }
+
+ public Map<String, String> getEnvironment() {
+ return environment;
+ }
+
+ public boolean isInstalled() {
+ return new File(baseDir, "VC/bin/cl.exe").isFile();
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/package-info.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/package-info.java
new file mode 100644
index 0000000..aa4cf13
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+/**
+ * Classes that allow C++ tool chains to be configured.
+ */
+package org.gradle.nativecode.toolchain;
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/plugins/GppCompilerPlugin.groovy b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/plugins/GppCompilerPlugin.groovy
new file mode 100644
index 0000000..5514929
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/plugins/GppCompilerPlugin.groovy
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.toolchain.plugins
+import org.gradle.api.Incubating
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.api.internal.file.FileResolver
+import org.gradle.internal.Factory
+import org.gradle.internal.os.OperatingSystem
+import org.gradle.nativecode.base.ToolChainRegistry
+import org.gradle.nativecode.base.plugins.NativeBinariesPlugin
+import org.gradle.nativecode.toolchain.Gcc
+import org.gradle.nativecode.toolchain.internal.gpp.GppToolChain
+import org.gradle.process.internal.DefaultExecAction
+import org.gradle.process.internal.ExecAction
+
+import javax.inject.Inject
+/**
+ * A {@link Plugin} which makes the <a href="http://gcc.gnu.org/">GNU G++ compiler</a> available for compiling C/C++ code.
+ */
+ at Incubating
+class GppCompilerPlugin implements Plugin<Project> {
+ private final FileResolver fileResolver
+
+ @Inject
+ GppCompilerPlugin(FileResolver fileResolver) {
+ this.fileResolver = fileResolver
+ }
+
+ void apply(Project project) {
+ project.plugins.apply(NativeBinariesPlugin)
+
+ final toolChainRegistry = project.extensions.getByType(ToolChainRegistry)
+ toolChainRegistry.registerFactory(Gcc, { String name ->
+ return new GppToolChain(name, OperatingSystem.current(), fileResolver, new Factory<ExecAction>() {
+ ExecAction create() {
+ return new DefaultExecAction(fileResolver);
+ }
+ })
+ })
+ toolChainRegistry.registerDefaultToolChain(GppToolChain.DEFAULT_NAME, Gcc)
+ }
+
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/plugins/MicrosoftVisualCppPlugin.groovy b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/plugins/MicrosoftVisualCppPlugin.groovy
new file mode 100755
index 0000000..e4a1a2c
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/plugins/MicrosoftVisualCppPlugin.groovy
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.toolchain.plugins
+import org.gradle.api.Incubating
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.api.internal.file.FileResolver
+import org.gradle.internal.Factory
+import org.gradle.internal.os.OperatingSystem
+import org.gradle.nativecode.base.ToolChainRegistry
+import org.gradle.nativecode.base.plugins.NativeBinariesPlugin
+import org.gradle.nativecode.toolchain.VisualCpp
+import org.gradle.nativecode.toolchain.internal.msvcpp.VisualCppToolChain
+import org.gradle.process.internal.DefaultExecAction
+import org.gradle.process.internal.ExecAction
+
+import javax.inject.Inject
+/**
+ * A {@link Plugin} which makes the Microsoft Visual C++ compiler available to compile C/C++ code.
+ */
+ at Incubating
+class MicrosoftVisualCppPlugin implements Plugin<Project> {
+ private final FileResolver fileResolver;
+
+ @Inject
+ MicrosoftVisualCppPlugin(FileResolver fileResolver) {
+ this.fileResolver = fileResolver
+ }
+
+ void apply(Project project) {
+ project.plugins.apply(NativeBinariesPlugin)
+
+ def toolChainRegistry = project.extensions.getByType(ToolChainRegistry)
+
+ toolChainRegistry.registerFactory(VisualCpp, { String name ->
+ return new VisualCppToolChain(name, OperatingSystem.current(), fileResolver, new Factory<ExecAction>() {
+ ExecAction create() {
+ return new DefaultExecAction(fileResolver)
+ }
+ })
+ })
+ toolChainRegistry.registerDefaultToolChain(VisualCppToolChain.DEFAULT_NAME, VisualCpp)
+ }
+}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/plugins/package-info.java b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/plugins/package-info.java
new file mode 100644
index 0000000..cd5c53a
--- /dev/null
+++ b/subprojects/cpp/src/main/groovy/org/gradle/nativecode/toolchain/plugins/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+/**
+ * Integration with the gpp (gcc frontend) compiler.
+ */
+package org.gradle.nativecode.toolchain.plugins;
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/BinariesPlugin.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/BinariesPlugin.java
deleted file mode 100644
index 07aac93..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/BinariesPlugin.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.binaries;
-
-import org.gradle.api.Plugin;
-import org.gradle.api.internal.FactoryNamedDomainObjectContainer;
-import org.gradle.internal.reflect.Instantiator;
-import org.gradle.api.internal.ReflectiveNamedDomainObjectFactory;
-import org.gradle.api.internal.project.ProjectInternal;
-import org.gradle.api.plugins.BasePlugin;
-import org.gradle.plugins.binaries.model.Executable;
-import org.gradle.plugins.binaries.model.Library;
-import org.gradle.plugins.binaries.model.internal.DefaultCompilerRegistry;
-import org.gradle.plugins.binaries.model.internal.DefaultExecutable;
-import org.gradle.plugins.binaries.model.internal.DefaultLibrary;
-
-import javax.inject.Inject;
-
-/**
- * temp plugin, not sure what will provide the binaries container and model elements
- */
-public class BinariesPlugin implements Plugin<ProjectInternal> {
- private final Instantiator instantiator;
-
- @Inject
- public BinariesPlugin(Instantiator instantiator) {
- this.instantiator = instantiator;
- }
-
- public void apply(final ProjectInternal project) {
- project.getPlugins().apply(BasePlugin.class);
-
- project.getExtensions().create("compilers",
- DefaultCompilerRegistry.class,
- instantiator
- );
- DefaultCompilerRegistry registry = project.getExtensions().getByType(DefaultCompilerRegistry.class);
-
- project.getExtensions().create("executables",
- FactoryNamedDomainObjectContainer.class,
- Executable.class,
- instantiator,
- new ReflectiveNamedDomainObjectFactory<Executable>(DefaultExecutable.class, project, registry)
- );
- project.getExtensions().create("libraries",
- FactoryNamedDomainObjectContainer.class,
- Library.class,
- instantiator,
- new ReflectiveNamedDomainObjectFactory<Library>(DefaultLibrary.class, project, registry)
- );
- }
-
-}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/Binary.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/Binary.java
deleted file mode 100644
index 1dd4a8e..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/Binary.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.binaries.model;
-
-import org.gradle.api.Buildable;
-import org.gradle.api.Named;
-import org.gradle.api.Project;
-import org.gradle.api.DomainObjectSet;
-
-/**
- * Something to be created.
- */
-public interface Binary extends Named, Buildable {
-
- CompileSpec getSpec();
-
- /**
- * Returns the project that this binary is built by.
- *
- * @deprecated No replacement
- */
- @Deprecated
- Project getProject();
-
- DomainObjectSet<SourceSet> getSourceSets();
-}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/CompileSpec.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/CompileSpec.java
deleted file mode 100644
index f990edb..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/CompileSpec.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.binaries.model;
-
-import org.gradle.api.Named;
-
-import java.io.File;
-
-/**
- * A high level interface to the compiler, specifying what is to be compiled and how.
- */
-public interface CompileSpec extends Named {
-
- /**
- * The ultimate output of the compilation.
- */
- File getOutputFile();
-
- /**
- * Do the compile.
- *
- * @deprecated No replacement
- */
- @Deprecated
- void compile();
-
- /**
- * Configures the spec to include the source set
- */
- // void from(SourceSet sourceSet);
- /*
- notes on from():
-
- The CompileSpec interface is likely to just have from(SourceSet) which the default impl of which would be to throw
- unsupported operation exception, with implementations overriding this method to handle different kinds of source sets
- */
-
-}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/Compiler.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/Compiler.java
deleted file mode 100644
index fefdcfa..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/Compiler.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.binaries.model;
-
-import org.gradle.api.Named;
-
-/**
- * A kind of compiler
- */
-public interface Compiler extends Named {
-}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/CompilerRegistry.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/CompilerRegistry.java
deleted file mode 100644
index 019563c..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/CompilerRegistry.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.binaries.model;
-
-import org.gradle.api.NamedDomainObjectSet;
-
-/**
- * A container for compiler adapters
- */
-public interface CompilerRegistry extends NamedDomainObjectSet<Compiler> {
-
- /**
- * Somehow picks what the default compiler to use is.
- *
- * @return null when there is no default compiler available.
- */
- Compiler getDefaultCompiler();
-}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/Executable.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/Executable.java
deleted file mode 100644
index 1f64a13..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/Executable.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.binaries.model;
-
-/**
- * An executable binary
- */
-public interface Executable extends Binary {
-
-}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/HeaderExportingSourceSet.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/HeaderExportingSourceSet.java
deleted file mode 100644
index 0725aa6..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/HeaderExportingSourceSet.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.binaries.model;
-
-import org.gradle.api.file.SourceDirectorySet;
-
-/**
- * A source set that exposes headers
- */
-public interface HeaderExportingSourceSet extends SourceSet {
-
- SourceDirectorySet getExportedHeaders();
-
-}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/Library.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/Library.java
deleted file mode 100644
index 73dacda..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/Library.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.binaries.model;
-
-import org.gradle.api.file.SourceDirectorySet;
-
-/**
- * A library
- */
-public interface Library extends Binary {
- LibraryCompileSpec getSpec();
-
- SourceDirectorySet getHeaders();
-}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/LibraryCompileSpec.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/LibraryCompileSpec.java
deleted file mode 100644
index 111e091..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/LibraryCompileSpec.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.binaries.model;
-
-/**
- * A high level interface to the compiler, specifying what is to be compiled and how.
- */
-public interface LibraryCompileSpec extends CompileSpec {
- /**
- * <p>Returns the <i>install name</i> for the library. This is the location where this library will be installed on the target
- * system, and where clients of this library should look for the library.
- *
- * <p>On Linux systems, this corresponds to the <i>soname</i> for the library.</p>
- */
- String getInstallName();
-
- void setInstallName(String path);
-}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/NativeDependencyCapableSourceSet.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/NativeDependencyCapableSourceSet.java
deleted file mode 100644
index d834aba..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/NativeDependencyCapableSourceSet.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.binaries.model;
-
-import org.gradle.api.DomainObjectSet;
-
-/**
- * Source set capability
- */
-public interface NativeDependencyCapableSourceSet extends SourceSet {
- DomainObjectSet<NativeDependencySet> getNativeDependencySets();
-}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/NativeDependencySet.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/NativeDependencySet.java
deleted file mode 100644
index 5db2b81..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/NativeDependencySet.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.binaries.model;
-
-import org.gradle.api.file.FileCollection;
-
-/**
- * Models a collection of native type dependencies.
- */
-public interface NativeDependencySet {
-
- FileCollection getIncludeRoots();
- FileCollection getFiles();
-
-}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/SourceSet.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/SourceSet.java
deleted file mode 100644
index 6bba25a..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/SourceSet.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.binaries.model;
-
-import org.gradle.api.Named;
-
-/**
- * A generic model of a collection of source
- */
-public interface SourceSet extends Named {
-
-}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/internal/BinaryCompileSpec.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/internal/BinaryCompileSpec.java
deleted file mode 100644
index 8d0734e..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/internal/BinaryCompileSpec.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.binaries.model.internal;
-
-import org.gradle.api.Buildable;
-import org.gradle.api.internal.tasks.compile.CompileSpec;
-
-public interface BinaryCompileSpec extends org.gradle.plugins.binaries.model.CompileSpec, CompileSpec, Buildable {
-}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/internal/BinaryCompileSpecFactory.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/internal/BinaryCompileSpecFactory.java
deleted file mode 100644
index de9fe6d..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/internal/BinaryCompileSpecFactory.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.binaries.model.internal;
-
-import org.gradle.api.internal.tasks.compile.Compiler;
-import org.gradle.plugins.binaries.model.Binary;
-
-/**
- * This is ugly. Currently, the CompileSpec impls need access to a Compiler, so we need use this interface to provide one at construction time.
- */
-public interface BinaryCompileSpecFactory {
- BinaryCompileSpec create(Binary binary, Compiler<?> compiler);
-}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/internal/CompileSpecFactory.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/internal/CompileSpecFactory.java
deleted file mode 100644
index 2f010fb..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/internal/CompileSpecFactory.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.binaries.model.internal;
-
-import org.gradle.plugins.binaries.model.Binary;
-
-/**
- * Producer of compile specs
- */
-public interface CompileSpecFactory {
-
- /**
- * Create a new spec to compile this binary
- */
- BinaryCompileSpec create(Binary binary);
-}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/internal/CompileTaskAware.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/internal/CompileTaskAware.java
deleted file mode 100644
index 41760f1..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/internal/CompileTaskAware.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.binaries.model.internal;
-
-import org.gradle.plugins.cpp.CppCompile;
-
-public interface CompileTaskAware {
- void configure(CppCompile compileTask);
-}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/internal/CompilerAdapter.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/internal/CompilerAdapter.java
deleted file mode 100644
index b3726b8..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/internal/CompilerAdapter.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.binaries.model.internal;
-
-import org.gradle.plugins.binaries.model.Binary;
-import org.gradle.plugins.binaries.model.Compiler;
-
-public interface CompilerAdapter<T extends BinaryCompileSpec> extends Compiler {
- /**
- * Creates a compiler which can compile the given binary. Should only be called if {@link #isAvailable()} has returned true.
- */
- org.gradle.api.internal.tasks.compile.Compiler<T> createCompiler(Binary binary);
-
- /**
- * Returns true if this compiler is available.
- */
- boolean isAvailable();
-}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/internal/ConfigurationBasedNativeDependencySet.groovy b/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/internal/ConfigurationBasedNativeDependencySet.groovy
deleted file mode 100644
index d9d46ab..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/internal/ConfigurationBasedNativeDependencySet.groovy
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.binaries.model.internal
-
-import org.gradle.plugins.binaries.model.NativeDependencySet
-import org.gradle.api.Project
-import org.gradle.api.Task
-import org.gradle.api.file.FileCollection
-import org.gradle.api.artifacts.Configuration
-
-class ConfigurationBasedNativeDependencySet implements NativeDependencySet {
-
- private final String baseName
- final String headersConfigurationName
- final String filesConfigurationName // files is a bad name
- final Project project
- private Task headerExtractionTask
-
- ConfigurationBasedNativeDependencySet(Project project, String baseName = "main") {
- this.baseName = baseName
- this.headersConfigurationName = baseName + "HeaderDependencies"
- this.filesConfigurationName = baseName + "FileDependencies"
- this.project = project
-
- createConfigurations()
- initHeaderExtractionTask()
- }
-
- private createConfigurations() {
- project.configurations.with {
- create(headersConfigurationName)
- create(filesConfigurationName)
- }
- }
-
- private initHeaderExtractionTask() {
- def headersConfiguration = getHeadersConfiguration()
- def dir = project.file("$project.buildDir/dependency-headers/$baseName")
- headerExtractionTask = project.task(baseName + "ExtractHeaders") {
- inputs.files headersConfiguration
- outputs.files { dir.listFiles() }
- doLast {
- headersConfiguration.each { headerZip ->
- project.copy {
- from project.zipTree(headerZip)
- into "$dir/${headerZip.name - '.zip'}"
- }
- }
- }
- }
- }
-
- Configuration getHeadersConfiguration() {
- project.configurations[headersConfigurationName]
- }
-
- FileCollection getIncludeRoots() {
- headerExtractionTask.outputs.files
- }
-
- FileCollection getFiles() {
- project.configurations[filesConfigurationName]
- }
-
- void add(Map dep) {
- // hackity hack hack
- project.dependencies {
- def m = { classifier, ext -> [classifier: classifier, ext: ext] }
- delegate."$headersConfigurationName"(dep + m("headers", "zip"))
- delegate."$filesConfigurationName"(dep + m("so", "so"))
- }
- }
-}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/internal/DefaultBinary.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/internal/DefaultBinary.java
deleted file mode 100644
index 64d04f0..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/internal/DefaultBinary.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.binaries.model.internal;
-
-import groovy.lang.Closure;
-import org.gradle.api.DomainObjectSet;
-import org.gradle.api.internal.DefaultDomainObjectSet;
-import org.gradle.api.internal.project.ProjectInternal;
-import org.gradle.api.tasks.TaskDependency;
-import org.gradle.plugins.binaries.model.Binary;
-import org.gradle.plugins.binaries.model.CompileSpec;
-import org.gradle.plugins.binaries.model.SourceSet;
-import org.gradle.util.ConfigureUtil;
-import org.gradle.util.DeprecationLogger;
-
-public class DefaultBinary implements Binary {
- private final String name;
- private final ProjectInternal project;
- private final BinaryCompileSpec spec;
- private final DomainObjectSet<SourceSet> sourceSets;
-
- public DefaultBinary(String name, ProjectInternal project, CompileSpecFactory specFactory) {
- this.name = name;
- this.project = project;
- this.sourceSets = new DefaultDomainObjectSet<SourceSet>(SourceSet.class);
- this.spec = specFactory.create(this);
- }
-
- public String getName() {
- return name;
- }
-
- public TaskDependency getBuildDependencies() {
- return spec.getBuildDependencies();
- }
-
- public ProjectInternal getProject() {
- DeprecationLogger.nagUserOfDiscontinuedMethod("Binary.getProject()");
- return project;
- }
-
- public CompileSpec getSpec() {
- return spec;
- }
-
- public DomainObjectSet<SourceSet> getSourceSets() {
- return sourceSets;
- }
-
- public CompileSpec spec(Closure closure) {
- return ConfigureUtil.configure(closure, spec);
- }
-}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/internal/DefaultCompilerRegistry.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/internal/DefaultCompilerRegistry.java
deleted file mode 100755
index 1052812..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/internal/DefaultCompilerRegistry.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.binaries.model.internal;
-
-import com.google.common.base.Joiner;
-import org.gradle.api.Action;
-import org.gradle.api.internal.DefaultNamedDomainObjectSet;
-import org.gradle.internal.reflect.Instantiator;
-import org.gradle.api.tasks.WorkResult;
-import org.gradle.plugins.binaries.model.Binary;
-import org.gradle.plugins.binaries.model.Compiler;
-import org.gradle.plugins.binaries.model.CompilerRegistry;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class DefaultCompilerRegistry extends DefaultNamedDomainObjectSet<Compiler> implements CompilerRegistry, CompileSpecFactory {
- private static final Logger LOGGER = LoggerFactory.getLogger(DefaultCompilerRegistry.class);
- private BinaryCompileSpecFactory specFactory;
- private final List<Compiler> searchOrder = new ArrayList<Compiler>();
-
- public DefaultCompilerRegistry(Instantiator instantiator) {
- super(Compiler.class, instantiator);
- whenObjectAdded(new Action<Compiler>() {
- public void execute(Compiler compiler) {
- searchOrder.add(compiler);
- }
- });
- whenObjectRemoved(new Action<Compiler>() {
- public void execute(Compiler compiler) {
- searchOrder.remove(compiler);
- }
- });
- }
-
- public List<Compiler> getSearchOrder() {
- return searchOrder;
- }
-
- public void setSpecFactory(BinaryCompileSpecFactory specFactory) {
- this.specFactory = specFactory;
- }
-
- public CompilerAdapter<BinaryCompileSpec> getDefaultCompiler() {
- for (Compiler compiler : searchOrder) {
- CompilerAdapter<BinaryCompileSpec> adapter = (CompilerAdapter<BinaryCompileSpec>) compiler;
- if (adapter.isAvailable()) {
- return adapter;
- }
- }
- return null;
- }
-
- public BinaryCompileSpec create(final Binary binary) {
- org.gradle.api.internal.tasks.compile.Compiler<BinaryCompileSpec> lazyCompiler = new LazyCompiler(binary);
- return specFactory.create(binary, lazyCompiler);
- }
-
- private class LazyCompiler implements org.gradle.api.internal.tasks.compile.Compiler<BinaryCompileSpec> {
- private final Binary binary;
-
- public LazyCompiler(Binary binary) {
- this.binary = binary;
- }
-
- public WorkResult execute(BinaryCompileSpec spec) {
- CompilerAdapter<BinaryCompileSpec> compiler = getDefaultCompiler();
- if (compiler == null) {
- throw new IllegalStateException(String.format("No compiler is available to compile %s. Searched for %s.", binary, Joiner.on(", ").join(searchOrder)));
- }
- LOGGER.info("Using " + compiler + " to compile " + binary);
- return compiler.createCompiler(binary).execute(spec);
- }
- }
-}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/internal/DefaultExecutable.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/internal/DefaultExecutable.java
deleted file mode 100755
index e7a4f73..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/internal/DefaultExecutable.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.binaries.model.internal;
-
-import org.gradle.plugins.binaries.model.Executable;
-
-import org.gradle.api.internal.project.ProjectInternal;
-
-public class DefaultExecutable extends DefaultBinary implements Executable {
- public DefaultExecutable(String name, ProjectInternal project, CompileSpecFactory specFactory) {
- super(name, project, specFactory);
- }
-
- @Override
- public String toString() {
- return String.format("executable '%s'", getName());
- }
-}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/internal/DefaultLibrary.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/internal/DefaultLibrary.java
deleted file mode 100755
index fb15888..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/internal/DefaultLibrary.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.binaries.model.internal;
-
-import org.gradle.api.Action;
-import org.gradle.api.DomainObjectSet;
-import org.gradle.api.file.SourceDirectorySet;
-import org.gradle.api.internal.file.DefaultSourceDirectorySet;
-import org.gradle.api.internal.project.ProjectInternal;
-import org.gradle.plugins.binaries.model.HeaderExportingSourceSet;
-import org.gradle.plugins.binaries.model.Library;
-import org.gradle.plugins.binaries.model.LibraryCompileSpec;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class DefaultLibrary extends DefaultBinary implements Library {
- private final DefaultSourceDirectorySet headers;
-
- public DefaultLibrary(String name, ProjectInternal project, CompileSpecFactory specFactory) {
- super(name, project, specFactory);
- this.headers = new DefaultSourceDirectorySet("headers", String.format("Exported headers for native library '%s'", name), project.getFileResolver());
-
- initExportedHeaderTracking();
- }
-
- @Override
- public String toString() {
- return String.format("library '%s'", getName());
- }
-
- public LibraryCompileSpec getSpec() {
- return (LibraryCompileSpec) super.getSpec();
- }
-
- public SourceDirectorySet getHeaders() {
- return headers;
- }
-
- private void initExportedHeaderTracking() {
- // TODO - headers.srcDirs() should allow a Callable<SourceDirectorySet> for lazy calculation
- final DomainObjectSet<HeaderExportingSourceSet> headerExportingSourceSets = getSourceSets().withType(HeaderExportingSourceSet.class);
- headerExportingSourceSets.all(new Action<HeaderExportingSourceSet>() {
- public void execute(HeaderExportingSourceSet headerExportingSourceSet) {
- updateHeaderDirs(headerExportingSourceSets, headers);
- }
- });
- headerExportingSourceSets.whenObjectRemoved(new Action<HeaderExportingSourceSet>() {
- public void execute(HeaderExportingSourceSet headerExportingSourceSet) {
- updateHeaderDirs(headerExportingSourceSets, headers);
- }
- });
- }
-
- private void updateHeaderDirs(DomainObjectSet<HeaderExportingSourceSet> sourceSets, DefaultSourceDirectorySet headers) {
- List<SourceDirectorySet> headerDirs = new ArrayList<SourceDirectorySet>();
- for (HeaderExportingSourceSet sourceSet : sourceSets) {
- headerDirs.add(sourceSet.getExportedHeaders());
- }
- headers.setSrcDirs(headerDirs);
- }
-}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/internal/package-info.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/internal/package-info.java
deleted file mode 100644
index 75ff69f..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/internal/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.
- */
-
-/**
- * Implementations of the native model classes.
- */
-package org.gradle.plugins.binaries.model.internal;
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/package-info.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/package-info.java
deleted file mode 100644
index 73d2a48..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/model/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.
- */
-
-/**
- * Classes that model aspects of C++ projects.
- */
-package org.gradle.plugins.binaries.model;
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/package-info.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/package-info.java
deleted file mode 100644
index a260db0..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.
- */
-
-/**
- * Provides the binaries container and some generic model elements
- */
-package org.gradle.plugins.binaries;
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/tasks/package-info.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/tasks/package-info.java
deleted file mode 100644
index 8a2cad0..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/binaries/tasks/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.
- */
-
-/**
- * Tasks for building native projects.
- */
-package org.gradle.plugins.binaries.tasks;
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/CppCompile.groovy b/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/CppCompile.groovy
deleted file mode 100644
index b280684..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/CppCompile.groovy
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp
-
-import org.gradle.api.DefaultTask
-import org.gradle.api.internal.tasks.compile.Compiler
-import org.gradle.api.tasks.TaskAction
-import org.gradle.plugins.binaries.model.CompileSpec
-
-class CppCompile extends DefaultTask {
- CompileSpec spec
- Compiler compiler
-
- @TaskAction
- void compile() {
- def result = compiler.execute(spec)
- didWork = result.didWork
- }
-}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/CppExeConventionPlugin.groovy b/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/CppExeConventionPlugin.groovy
deleted file mode 100644
index 80320d8..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/CppExeConventionPlugin.groovy
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp
-
-import org.gradle.api.Project
-import org.gradle.api.Plugin
-
-import org.gradle.api.internal.artifacts.publish.DefaultPublishArtifact
-import org.gradle.api.internal.plugins.DefaultArtifactPublicationSet
-
-class CppExeConventionPlugin implements Plugin<Project> {
-
- void apply(Project project) {
- project.plugins.apply(CppPlugin)
-
- project.with {
- cpp {
- sourceSets {
- main {}
- }
- }
- executables {
- main {
- spec.baseName = project.name
- sourceSets << project.cpp.sourceSets.main
- }
- }
-
- def exeArtifact = new DefaultPublishArtifact(
- archivesBaseName, // name
- "exe", // ext
- "exe", // type
- null, // classifier
- null, // date
-
- // needs to be more general and not peer into the spec
- executables.main.spec.outputFile,
- executables.main
- )
-
- extensions.getByType(DefaultArtifactPublicationSet).addCandidate(exeArtifact)
- }
- }
-
-}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/CppExtension.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/CppExtension.java
deleted file mode 100644
index e4b68e1..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/CppExtension.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp;
-
-import groovy.lang.Closure;
-import org.gradle.api.NamedDomainObjectContainer;
-import org.gradle.api.internal.FactoryNamedDomainObjectContainer;
-import org.gradle.internal.reflect.Instantiator;
-import org.gradle.api.internal.ReflectiveNamedDomainObjectFactory;
-import org.gradle.api.internal.project.ProjectInternal;
-import org.gradle.plugins.cpp.internal.DefaultCppSourceSet;
-
-/**
- * Adds a source set container.
- */
-public class CppExtension {
-
- final private NamedDomainObjectContainer<CppSourceSet> sourceSets;
-
- public CppExtension(final ProjectInternal project) {
- Instantiator instantiator = project.getServices().get(Instantiator.class);
- sourceSets = instantiator.newInstance(
- FactoryNamedDomainObjectContainer.class,
- CppSourceSet.class,
- instantiator,
- new ReflectiveNamedDomainObjectFactory<CppSourceSet>(DefaultCppSourceSet.class, project)
- );
- }
-
- public NamedDomainObjectContainer<CppSourceSet> sourceSets(Closure closure) {
- return sourceSets.configure(closure);
- }
-
- public NamedDomainObjectContainer<CppSourceSet> getSourceSets() {
- return sourceSets;
- }
-}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/CppLibConventionPlugin.groovy b/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/CppLibConventionPlugin.groovy
deleted file mode 100644
index 9eacc50..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/CppLibConventionPlugin.groovy
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp
-
-import org.gradle.api.Project
-import org.gradle.api.Plugin
-import org.gradle.api.tasks.bundling.Zip
-
-import org.gradle.api.internal.artifacts.publish.DefaultPublishArtifact
-import org.gradle.api.internal.artifacts.publish.ArchivePublishArtifact
-import org.gradle.api.internal.plugins.DefaultArtifactPublicationSet
-
-class CppLibConventionPlugin implements Plugin<Project> {
-
- void apply(Project project) {
- project.plugins.apply(CppPlugin)
-
- project.with {
- cpp {
- sourceSets {
- main {}
- }
- }
- libraries {
- main {
- sourceSets << project.cpp.sourceSets.main
- spec.baseName = project.name
- }
- }
-
- def libArtifact = new DefaultPublishArtifact(
- archivesBaseName, // name
- "so", // ext
- "so", // type
- "so", // classifier
- null, // date
-
- // needs to be more general and not peer into the spec
- libraries.main.spec.outputFile,
- libraries.main
- )
-
- task("assembleHeaders", type: Zip) {
- from libraries.main.headers
- classifier = "headers"
- }
-
- def headerArtifact = new ArchivePublishArtifact(assembleHeaders)
-
- extensions.getByType(DefaultArtifactPublicationSet).addCandidate(libArtifact)
- extensions.getByType(DefaultArtifactPublicationSet).addCandidate(headerArtifact)
- }
- }
-
-}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/CppPlugin.groovy b/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/CppPlugin.groovy
deleted file mode 100644
index d5d4862..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/CppPlugin.groovy
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp
-
-import org.gradle.api.Plugin
-import org.gradle.api.internal.project.ProjectInternal
-import org.gradle.api.plugins.BasePlugin
-import org.gradle.api.tasks.Sync
-import org.gradle.internal.os.OperatingSystem
-import org.gradle.plugins.binaries.BinariesPlugin
-import org.gradle.plugins.binaries.model.Binary
-import org.gradle.plugins.binaries.model.Executable
-import org.gradle.plugins.binaries.model.internal.DefaultCompilerRegistry
-import org.gradle.plugins.cpp.gpp.GppCompilerPlugin
-import org.gradle.plugins.cpp.gpp.internal.GppCompileSpecFactory
-import org.gradle.plugins.cpp.msvcpp.MicrosoftVisualCppPlugin
-import org.gradle.util.GUtil
-
-class CppPlugin implements Plugin<ProjectInternal> {
-
- void apply(ProjectInternal project) {
- project.plugins.apply(BinariesPlugin)
- project.plugins.apply(MicrosoftVisualCppPlugin)
- project.plugins.apply(GppCompilerPlugin)
- project.extensions.create("cpp", CppExtension, project)
-
- project.extensions.getByType(DefaultCompilerRegistry).specFactory = new GppCompileSpecFactory(project)
-
- // Defaults for all cpp source sets
- project.cpp.sourceSets.all { sourceSet ->
- sourceSet.source.srcDir "src/${sourceSet.name}/cpp"
- sourceSet.exportedHeaders.srcDir "src/${sourceSet.name}/headers"
- }
-
- // Defaults for all executables
- project.executables.all { executable ->
- configureExecutable(project, executable)
- }
-
- // Defaults for all libraries
- project.libraries.all { library ->
- configureBinary(project, library)
- }
- }
-
- def configureExecutable(ProjectInternal project, Executable executable) {
- configureBinary(project, executable)
-
- def baseName = GUtil.toCamelCase(executable.name).capitalize()
- project.task("install${baseName}", type: Sync) {
- description = "Installs a development image of $executable"
- into { project.file("${project.buildDir}/install/$executable.name") }
- dependsOn executable
- if (OperatingSystem.current().windows) {
- from { executable.spec.outputFile }
- from { executable.sourceSets*.libs*.spec*.outputFile }
- } else {
- into("lib") {
- from { executable.spec.outputFile }
- from { executable.sourceSets*.libs*.spec*.outputFile }
- }
- doLast {
- def script = new File(destinationDir, executable.spec.outputFile.name)
- script.text = """
-#/bin/sh
-APP_BASE_NAME=`dirname "\$0"`
-export DYLD_LIBRARY_PATH="\$APP_BASE_NAME/lib"
-export LD_LIBRARY_PATH="\$APP_BASE_NAME/lib"
-exec "\$APP_BASE_NAME/lib/${executable.spec.outputFile.name}" \"\$@\"
- """
- ant.chmod(perm: 'u+x', file: script)
- }
- }
- }
- }
-
- def configureBinary(ProjectInternal project, Binary binary) {
- def baseName = GUtil.toCamelCase(binary.name).capitalize()
-
- def task = project.task("compile${baseName}", type: CppCompile) {
- description = "Compiles and links $binary"
- group = BasePlugin.BUILD_GROUP
- }
- binary.spec.configure(task)
- }
-}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/CppSourceSet.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/CppSourceSet.java
deleted file mode 100644
index 0d0d066..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/CppSourceSet.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp;
-
-import org.gradle.plugins.binaries.model.Library;
-import org.gradle.plugins.binaries.model.HeaderExportingSourceSet;
-import org.gradle.plugins.binaries.model.NativeDependencyCapableSourceSet;
-
-import org.gradle.api.Named;
-import org.gradle.api.DomainObjectSet;
-import org.gradle.api.file.SourceDirectorySet;
-
-import groovy.lang.Closure;
-
-import java.util.Map;
-
-/**
- * A representation of a unit of cpp source
- */
-public interface CppSourceSet extends HeaderExportingSourceSet, NativeDependencyCapableSourceSet, Named {
-
- /**
- * The headers.
- */
- SourceDirectorySet getExportedHeaders();
-
- /**
- * The headers.
- */
- CppSourceSet exportedHeaders(Closure closure);
-
- /**
- * The source.
- */
- SourceDirectorySet getSource();
-
- /**
- * The source.
- */
- CppSourceSet source(Closure closure);
-
- /**
- * Libs this source set requires
- */
- DomainObjectSet<Library> getLibs();
-
- /**
- * Add a dependency to this source set
- */
- void dependency(Map<?, ?> dep);
-
-}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/cdt/CdtIdePlugin.groovy b/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/cdt/CdtIdePlugin.groovy
deleted file mode 100644
index d17dc4c..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/cdt/CdtIdePlugin.groovy
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp.cdt
-
-import org.gradle.api.Project
-import org.gradle.api.Plugin
-import org.gradle.api.InvalidUserDataException
-import org.gradle.api.tasks.Delete
-
-import org.gradle.plugins.cpp.cdt.model.ProjectSettings
-import org.gradle.plugins.cpp.cdt.model.ProjectDescriptor
-import org.gradle.plugins.cpp.cdt.model.CprojectSettings
-import org.gradle.plugins.cpp.cdt.model.CprojectDescriptor
-
-import org.gradle.plugins.cpp.cdt.tasks.GenerateMetadataFileTask
-
-class CdtIdePlugin implements Plugin<Project> {
-
- void apply(Project project) {
- project.apply(plugin: "binaries")
- def metadataFileTasks = [addCreateProjectDescriptor(project), addCreateCprojectDescriptor(project)]
-
- project.task("cleanCdt", type: Delete) {
- delete metadataFileTasks*.outputs*.files
- }
-
- project.task("cdt", dependsOn: metadataFileTasks)
- }
-
- private addCreateProjectDescriptor(Project project) {
- project.task("cdtProject", type: GenerateMetadataFileTask) {
- inputFile = project.file(".project")
- outputFile = project.file(".project")
- factory { new ProjectDescriptor() }
- onConfigure { new ProjectSettings(name: project.name).applyTo(it) }
- }
- }
-
- private addCreateCprojectDescriptor(Project project) {
- project.task("cdtCproject", type: GenerateMetadataFileTask) { task ->
-
- [project.executables, project.libraries]*.all { binary ->
- if (binary.name == "main") {
- task.settings = new CprojectSettings(binary, project)
- }
- }
-
- doFirst {
- if (task.settings == null) {
- throw new InvalidUserDataException("There is neither a main binary or library")
- }
- }
-
- inputs.files { task.settings.includeRoots }
- inputFile = project.file(".cproject")
- outputFile = project.file(".cproject")
- factory { new CprojectDescriptor() }
- onConfigure { descriptor ->
- task.settings.applyTo(descriptor)
- }
- }
- }
-
-}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/cdt/model/CprojectDescriptor.groovy b/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/cdt/model/CprojectDescriptor.groovy
deleted file mode 100644
index 860c149..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/cdt/model/CprojectDescriptor.groovy
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp.cdt.model
-
-import org.gradle.api.internal.xml.XmlTransformer
-import org.gradle.plugins.ide.internal.generator.XmlPersistableConfigurationObject
-
-/**
- * The actual .cproject descriptor file.
- */
-class CprojectDescriptor extends XmlPersistableConfigurationObject {
-
- private static final boolean LINUX_NOT_MACOS = true
-
- static public final String GNU_COMPILER_TOOL_ID_PREFIX = "cdt.managedbuild.tool.gnu.cpp.compiler"
- static public final String GNU_COMPILER_TOOL_INCLUDE_PATHS_OPTION_PREFIX = "gnu.cpp.compiler.option.include.paths"
-
- // linux
- static public final String GNU_LINKER_TOOL_ID_PREFIX = LINUX_NOT_MACOS ? "cdt.managedbuild.tool.gnu.cpp.linker" : "cdt.managedbuild.tool.macosx.cpp.linker.macosx"
- static public final String GNU_LINKER_TOOL_LIBS_PATHS_OPTION_PREFIX = LINUX_NOT_MACOS ? "gnu.cpp.link.option.userobjs" : "macosx.cpp.link.option.userobjs"
-
- CprojectDescriptor() {
- super(new XmlTransformer())
- }
-
- protected String getDefaultResourceName() {
- LINUX_NOT_MACOS ? 'defaultCproject-linux.xml' : 'defaultCproject-macos.xml'
- }
-
- NodeList getConfigurations() {
- new NodeList(xml.storageModule.cconfiguration.storageModule.findAll { it. at moduleId == "cdtBuildSystem" }.collect { it.configuration[0] })
- }
-
- NodeList getRootToolChains() {
- new NodeList(configurations.folderInfo.findAll { it. at resourcePath == "" }).toolChain
- }
-
- NodeList getRootCppCompilerTools() {
- new NodeList(rootToolChains.tool.findAll { isGnuCompilerTool(it) })
- }
-
- NodeList getRootCppLinkerTools() {
- new NodeList(rootToolChains.tool.findAll { isGnuLinkerTool(it) })
- }
-
- boolean isGnuCompilerTool(Node node) {
- node.name() == "tool" && node. at id.startsWith(GNU_COMPILER_TOOL_ID_PREFIX)
- }
-
- boolean isGnuLinkerTool(Node node) {
- node.name() == "tool" && node. at id.startsWith(GNU_LINKER_TOOL_ID_PREFIX)
- }
-
- Node getOrCreateIncludePathsOption(compilerToolNode) {
- if (!isGnuCompilerTool(compilerToolNode)) {
- throw new IllegalArgumentException("Arg must be a gnu compiler tool def, was $compilerToolNode")
- }
-
- def includePathsOption = compilerToolNode.option.find { it. at id.startsWith(GNU_COMPILER_TOOL_INCLUDE_PATHS_OPTION_PREFIX) }
- if (!includePathsOption) {
- includePathsOption = compilerToolNode.appendNode(
- "option", [
- id: createId(GNU_COMPILER_TOOL_INCLUDE_PATHS_OPTION_PREFIX),
- superClass: GNU_COMPILER_TOOL_INCLUDE_PATHS_OPTION_PREFIX,
- valueType: "includePath"
- ]
- )
- }
-
- includePathsOption
- }
-
- Node getOrCreateLibsOption(linkerToolNode) {
- if (!isGnuLinkerTool(linkerToolNode)) {
- throw new IllegalArgumentException("Arg must be a gnu linker tool def, was $linkerToolNode")
- }
-
- def libsOption = linkerToolNode.option.find { it. at id.startsWith(GNU_LINKER_TOOL_LIBS_PATHS_OPTION_PREFIX) }
- if (!libsOption) {
- libsOption = linkerToolNode.appendNode(
- "option", [
- id: createId(GNU_LINKER_TOOL_LIBS_PATHS_OPTION_PREFIX),
- superClass: GNU_LINKER_TOOL_LIBS_PATHS_OPTION_PREFIX,
- valueType: "userObjs"
- ]
- )
- }
-
- libsOption
- }
-
- String createId(String prefix) {
- prefix + "." + new java.text.SimpleDateFormat("yyMMddHHmmssS").format(new Date())
- }
-
- protected void store(Node xml) {
- transformAction {
- StringBuilder xmlString = it.asString()
- xmlString.insert(xmlString.indexOf("\n") + 1, "<?fileVersion 4.0.0?>\n")
- }
- }
-}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/cdt/model/CprojectSettings.groovy b/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/cdt/model/CprojectSettings.groovy
deleted file mode 100644
index c39a8bb..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/cdt/model/CprojectSettings.groovy
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp.cdt.model
-
-import org.gradle.api.file.ConfigurableFileCollection
-import org.gradle.api.internal.project.ProjectInternal
-import org.gradle.plugins.cpp.CppSourceSet
-import org.gradle.plugins.binaries.model.*
-
-/**
- * Exposes a more logical view of the actual .cproject descriptor file
- */
-class CprojectSettings {
-
- Binary binary
- private final ConfigurableFileCollection includeRoots
- private final ConfigurableFileCollection libs
-
- CprojectSettings(Binary binary, ProjectInternal project) {
- this.binary = binary
- includeRoots = project.files()
- libs = project.files()
-
- binary.sourceSets.withType(HeaderExportingSourceSet).all {
- includeRoots.builtBy(it.exportedHeaders) // have to manually add because we use srcDirs in from, not the real collection
- includeRoots.from(it.exportedHeaders.srcDirs)
- }
-
- binary.sourceSets.withType(NativeDependencyCapableSourceSet).all {
- it.nativeDependencySets.all {
- this.includeRoots.from(it.includeRoots)
- this.libs.from(it.files)
- }
- }
-
- binary.sourceSets.withType(CppSourceSet).all { sourceSet ->
- sourceSet.libs.all { lib ->
- this.libs.from(lib.spec.outputFile)
- this.libs.builtBy(lib.spec.task)
- this.includeRoots.from(lib.headers.srcDirs)
- }
- }
- }
-
- void applyTo(CprojectDescriptor descriptor) {
- if (binary) {
- applyBinaryTo(descriptor)
- } else {
- throw new IllegalStateException("no binary set")
- }
- }
-
- private applyBinaryTo(CprojectDescriptor descriptor) {
- descriptor.rootCppCompilerTools.each { compiler ->
- def includePathsOption = descriptor.getOrCreateIncludePathsOption(compiler)
- new LinkedList(includePathsOption.children()).each { includePathsOption.remove(it) }
- includeRoots.each { includeRoot ->
- includePathsOption.appendNode("listOptionValue", [builtIn: "false", value: includeRoot.absolutePath])
- }
- }
-
- descriptor.rootCppLinkerTools.each { linker ->
- def libsOption = descriptor.getOrCreateLibsOption(linker)
- new LinkedList(libsOption.children()).each { libsOption.remove(it) }
- libs.each { lib ->
- libsOption.appendNode("listOptionValue", [builtIn: "false", value: lib.absolutePath])
- }
- }
-
- def extension = binary.spec.extension ?: ""
- def type
- if (binary instanceof Library) {
- type = "org.eclipse.cdt.build.core.buildArtefactType.sharedLib"
- } else if (binary instanceof Executable) {
- type = "org.eclipse.cdt.build.core.buildArtefactType.exe"
- } else {
- throw new IllegalStateException("The binary $binary is of a type that we don't know about")
- }
-
- descriptor.configurations.each { conf ->
- conf. at buildArtefactType = type
- conf. at artifactExtension = extension
- def buildPropsPairs = conf. at buildProperties.split(",")
- def buildProps = [:]
- buildPropsPairs.each {
- def parts = it.split("=", 2)
- buildProps[parts[0]] = parts[1]
- }
- buildProps["org.eclipse.cdt.build.core.buildArtefactType"] = type
- buildPropsPairs = buildProps.collect { k, v -> "$k=$v"}
- conf. at buildProperties = buildPropsPairs.join(",")
- }
- }
-}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/cdt/model/ProjectDescriptor.groovy b/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/cdt/model/ProjectDescriptor.groovy
deleted file mode 100644
index 7f32bb4..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/cdt/model/ProjectDescriptor.groovy
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp.cdt.model
-
-import org.gradle.api.internal.xml.XmlTransformer
-import org.gradle.plugins.ide.internal.generator.XmlPersistableConfigurationObject
-
-/**
- * The actual .project descriptor file.
- */
-class ProjectDescriptor extends XmlPersistableConfigurationObject {
-
- ProjectDescriptor() {
- super(new XmlTransformer())
- }
-
- protected String getDefaultResourceName() {
- 'defaultProject.xml'
- }
-
- Node getOrCreate(String name) {
- getOrCreate(xml, name)
- }
-
- Node findBuildCommand(Closure predicate) {
- xml.buildSpec[0].buildCommand.find(predicate)
- }
-
- Node getOrCreate(Node parent, String name) {
- def node = parent.get(name)
- node ? node.first() : parent.appendNode(name)
- }
-}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/cdt/model/ProjectSettings.groovy b/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/cdt/model/ProjectSettings.groovy
deleted file mode 100644
index 6a8726a..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/cdt/model/ProjectSettings.groovy
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp.cdt.model
-
-/**
- * Gradle model element, the configurable parts of the .project file.
- */
-class ProjectSettings {
- String name
-
- /**
- * Apply this logical model to the physical descriptor
- */
- void applyTo(ProjectDescriptor descriptor) {
- descriptor.getOrCreate("name").value = name
-
- // not anywhere close to right at all, very hardcoded.
- def genMakeBuilderBuildCommand = descriptor.findBuildCommand { it.name[0].text() == "org.eclipse.cdt.managedbuilder.core.genmakebuilder" }
- if (genMakeBuilderBuildCommand) {
- def dict = genMakeBuilderBuildCommand.arguments[0].dictionary.find { it.key[0].text() == "org.eclipse.cdt.make.core.buildLocation" }
- if (dict) {
- dict.value[0].value = "\${workspace_loc:/$name/Debug}"
- }
- }
-
- }
-}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/cdt/tasks/GenerateMetadataFileTask.groovy b/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/cdt/tasks/GenerateMetadataFileTask.groovy
deleted file mode 100644
index 8f25b5e..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/cdt/tasks/GenerateMetadataFileTask.groovy
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp.cdt.tasks
-
-import org.gradle.api.internal.ClosureBackedAction
-import org.gradle.internal.Factory
-import org.gradle.listener.ActionBroadcast
-import org.gradle.plugins.cpp.cdt.model.CprojectSettings
-import org.gradle.plugins.ide.api.GeneratorTask
-import org.gradle.plugins.ide.internal.generator.generator.PersistableConfigurationObject
-import org.gradle.plugins.ide.internal.generator.generator.PersistableConfigurationObjectGenerator
-
-class GenerateMetadataFileTask<T extends PersistableConfigurationObject> extends GeneratorTask<T> {
-
- Factory<T> factory
- ActionBroadcast<T> configures = new ActionBroadcast<T>()
- CprojectSettings settings
-
- GenerateMetadataFileTask() {
- generator = new PersistableConfigurationObjectGenerator() {
- public create() {
- GenerateMetadataFileTask.this.factory.create();
- }
-
- public void configure(object) {
- GenerateMetadataFileTask.this.configures.execute(object);
- }
- }
- }
-
- void factory(Closure factory) {
- this.factory = factory as Factory
- }
-
- void onConfigure(Closure configure) {
- configures.add(new ClosureBackedAction(configure))
- }
-}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/compiler/capability/AgainstLibrary.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/compiler/capability/AgainstLibrary.java
deleted file mode 100644
index aba90f3..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/compiler/capability/AgainstLibrary.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp.compiler.capability;
-
-import org.gradle.plugins.binaries.model.Library;
-
-/**
- * Can compile against libraries
- */
-public interface AgainstLibrary {
-
- /**
- * Compile against the given libs (collection must be live, i.e. changes respected)
- */
- void libs(Iterable<Library> libs);
-
-
-}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/compiler/capability/CompilesCpp.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/compiler/capability/CompilesCpp.java
deleted file mode 100644
index 1165fb8..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/compiler/capability/CompilesCpp.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp.compiler.capability;
-
-import org.gradle.plugins.cpp.CppSourceSet;
-
-/**
- * Capable of compiling cpp source from a cpp source set
- */
-public interface CompilesCpp {
-
- /**
- * Use the source set
- */
- void from(CppSourceSet sourceSet);
-
-}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/compiler/capability/StandardCppCompiler.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/compiler/capability/StandardCppCompiler.java
deleted file mode 100644
index eee8d78..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/compiler/capability/StandardCppCompiler.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp.compiler.capability;
-
-/**
- * Wraps up the standard capabilities you'd expect a cpp compiler to have
- */
-public interface StandardCppCompiler extends AgainstLibrary, CompilesCpp {
-
-}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/compiler/capability/package-info.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/compiler/capability/package-info.java
deleted file mode 100644
index bfb0501..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/compiler/capability/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.
- */
-
-/**
- * Interfaces for compiler capabilities for cpp
- */
-package org.gradle.plugins.cpp.compiler.capability;
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/compiler/internal/CommandLineCppCompiler.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/compiler/internal/CommandLineCppCompiler.java
deleted file mode 100755
index b6e4738..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/compiler/internal/CommandLineCppCompiler.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp.compiler.internal;
-
-import groovy.lang.Closure;
-import org.gradle.api.internal.tasks.compile.CompileSpecToArguments;
-import org.gradle.api.internal.tasks.compile.ExecSpecBackedArgCollector;
-import org.gradle.api.internal.tasks.compile.SimpleWorkResult;
-import org.gradle.api.tasks.WorkResult;
-import org.gradle.internal.Factory;
-import org.gradle.plugins.cpp.internal.CppCompileSpec;
-import org.gradle.process.internal.ExecAction;
-import org.gradle.util.GFileUtils;
-
-import java.io.File;
-
-public class CommandLineCppCompiler<T extends CppCompileSpec> implements CppCompiler<T> {
- private final File executable;
- private final Factory<ExecAction> execActionFactory;
- private final CompileSpecToArguments<T> toArguments;
-
- public CommandLineCppCompiler(File executable, Factory<ExecAction> execActionFactory, CompileSpecToArguments<T> toArguments) {
- this.executable = executable;
- this.execActionFactory = execActionFactory;
- this.toArguments = toArguments;
- }
-
- public WorkResult execute(T spec) {
- File workDir = spec.getWorkDir();
-
- ensureDirsExist(workDir, spec.getOutputFile().getParentFile());
-
- ExecAction compiler = execActionFactory.create();
- compiler.executable(executable);
- compiler.workingDir(workDir);
-
- toArguments.collectArguments(spec, new ExecSpecBackedArgCollector(compiler));
-
- // Apply all of the settings
- for (Closure closure : spec.getSettings()) {
- closure.call(compiler);
- }
-
- compiler.execute();
- return new SimpleWorkResult(true);
- }
-
- private void ensureDirsExist(File... dirs) {
- for (File dir : dirs) {
- GFileUtils.mkdirs(dir);
- }
- }
-
-}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/compiler/internal/CommandLineCppCompilerAdapter.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/compiler/internal/CommandLineCppCompilerAdapter.java
deleted file mode 100644
index 24e5dfa..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/compiler/internal/CommandLineCppCompilerAdapter.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp.compiler.internal;
-
-import org.gradle.internal.Factory;
-import org.gradle.internal.os.OperatingSystem;
-import org.gradle.plugins.binaries.model.internal.CompilerAdapter;
-import org.gradle.plugins.cpp.internal.CppCompileSpec;
-import org.gradle.process.internal.ExecAction;
-
-import java.io.File;
-
-abstract public class CommandLineCppCompilerAdapter<T extends CppCompileSpec> implements CompilerAdapter<T> {
-
- private final File executable;
- private final Factory<ExecAction> execActionFactory;
- private OperatingSystem operatingSystem;
-
- protected CommandLineCppCompilerAdapter(String executableName, OperatingSystem operatingSystem, Factory<ExecAction> execActionFactory) {
- this(operatingSystem.findInPath(executableName), operatingSystem, execActionFactory);
- }
-
- protected CommandLineCppCompilerAdapter(File executable, OperatingSystem operatingSystem, Factory<ExecAction> execActionFactory) {
- this.executable = executable;
- this.operatingSystem = operatingSystem;
- this.execActionFactory = execActionFactory;
- }
-
- protected File getExecutable() {
- return executable;
- }
-
- protected Factory<ExecAction> getExecActionFactory() {
- return execActionFactory;
- }
-
- public OperatingSystem getOperatingSystem() {
- return operatingSystem;
- }
-
- public boolean isAvailable() {
- return executable != null && executable.exists();
- }
-
-}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/compiler/internal/CommandLineCppCompilerArgumentsToOptionFile.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/compiler/internal/CommandLineCppCompilerArgumentsToOptionFile.java
deleted file mode 100644
index 1ae0174..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/compiler/internal/CommandLineCppCompilerArgumentsToOptionFile.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp.compiler.internal;
-
-import org.gradle.api.Transformer;
-import org.gradle.api.UncheckedIOException;
-import org.gradle.api.internal.tasks.compile.ArgCollector;
-import org.gradle.api.internal.tasks.compile.ArgWriter;
-import org.gradle.api.internal.tasks.compile.CompileSpecToArguments;
-import org.gradle.plugins.cpp.internal.CppCompileSpec;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.PrintWriter;
-
-public class CommandLineCppCompilerArgumentsToOptionFile<T extends CppCompileSpec> implements CompileSpecToArguments<T> {
-
- private final Transformer<ArgWriter, PrintWriter> argWriterFactory;
- private final CompileSpecToArguments<T> toArguments;
-
- public CommandLineCppCompilerArgumentsToOptionFile(Transformer<ArgWriter, PrintWriter> argWriterFactory, CompileSpecToArguments<T> toArguments) {
- this.argWriterFactory = argWriterFactory;
- this.toArguments = toArguments;
- }
-
- public void collectArguments(T spec, ArgCollector collector) {
- File optionsFile = new File(spec.getWorkDir(), "compiler-options.txt");
- try {
- PrintWriter writer = new PrintWriter(optionsFile);
- ArgWriter argWriter = argWriterFactory.transform(writer);
- try {
- toArguments.collectArguments(spec, argWriter);
- } finally {
- writer.close();
- }
- } catch (IOException e) {
- throw new UncheckedIOException(String.format("Could not write compiler options file '%s'.", optionsFile.getAbsolutePath()), e);
- }
-
- collector.args(String.format("@%s", optionsFile.getAbsolutePath()));
- }
-}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/compiler/internal/CppCompiler.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/compiler/internal/CppCompiler.java
deleted file mode 100644
index b4347c2..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/compiler/internal/CppCompiler.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp.compiler.internal;
-
-import org.gradle.api.internal.tasks.compile.Compiler;
-import org.gradle.plugins.cpp.internal.CppCompileSpec;
-
-public interface CppCompiler<T extends CppCompileSpec> extends Compiler<T> {
-
-}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/gpp/GppCompileSpec.groovy b/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/gpp/GppCompileSpec.groovy
deleted file mode 100755
index 65efb5b..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/gpp/GppCompileSpec.groovy
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp.gpp
-
-import org.gradle.api.file.FileCollection
-import org.gradle.api.file.SourceDirectorySet
-import org.gradle.api.internal.project.ProjectInternal
-import org.gradle.api.internal.tasks.compile.Compiler
-import org.gradle.internal.os.OperatingSystem
-import org.gradle.plugins.binaries.model.Binary
-import org.gradle.plugins.binaries.model.CompileSpec
-import org.gradle.plugins.binaries.model.Library
-import org.gradle.plugins.binaries.model.internal.CompileTaskAware
-import org.gradle.plugins.cpp.CppSourceSet
-import org.gradle.plugins.cpp.compiler.capability.StandardCppCompiler
-import org.gradle.plugins.cpp.internal.CppCompileSpec
-import org.gradle.util.DeprecationLogger
-import org.gradle.api.file.ConfigurableFileCollection
-
-import org.gradle.api.tasks.TaskDependency
-import org.gradle.api.internal.tasks.DefaultTaskDependency
-import org.gradle.plugins.cpp.CppCompile
-
-class GppCompileSpec implements CompileSpec, StandardCppCompiler, CompileTaskAware, CppCompileSpec {
- Binary binary
-
- private CppCompile task
- List<Closure> settings = []
-
- String outputFileName
- String baseName
- String extension
- private final Compiler<? super GppCompileSpec> compiler
- private final ProjectInternal project
- private final ConfigurableFileCollection libs
- private final ConfigurableFileCollection includes
- private final ConfigurableFileCollection source
-
- GppCompileSpec(Binary binary, Compiler<? super GppCompileSpec> compiler, ProjectInternal project) {
- this.binary = binary
- this.compiler = compiler
- this.project = project
- libs = project.files()
- includes = project.files()
- source = project.files()
- }
-
- void configure(CppCompile task) {
- this.task = task
- task.spec = this
- task.compiler = compiler
-
- task.onlyIf { !task.inputs.files.empty }
- task.outputs.file { getOutputFile() }
-
- // problem: will break if a source set is removed
- binary.sourceSets.withType(CppSourceSet).all { from(it) }
- }
-
- String getName() {
- binary.name
- }
-
- TaskDependency getBuildDependencies() {
- return new DefaultTaskDependency().add(task)
- }
-
- File getWorkDir() {
- project.file "$project.buildDir/compileWork/$name"
- }
-
- Iterable<File> getLibs() {
- return libs
- }
-
- Iterable<File> getIncludeRoots() {
- return includes
- }
-
- Iterable<File> getSource() {
- return source
- }
-
- /**
- * @deprecated No replacement
- */
- @Deprecated
- String getExtension() {
- DeprecationLogger.nagUserOfDiscontinuedMethod("GppCompileSpec.getExtension()")
- return extension
- }
-
- /**
- * @deprecated No replacement
- */
- @Deprecated
- void setExtension(String extension) {
- DeprecationLogger.nagUserOfDiscontinuedMethod("GppCompileSpec.setExtension()")
- this.extension = extension
- }
-
- /**
- * @deprecated No replacement
- */
- @Deprecated
- void setBinary(Binary binary) {
- DeprecationLogger.nagUserOfDiscontinuedMethod("GppCompileSpec.setBinary()")
- this.binary = binary
- }
-
- File getOutputFile() {
- project.file "$project.buildDir/binaries/${getOutputFileName()}"
- }
-
- String getOutputFileName() {
- if (outputFileName) {
- return outputFileName
- } else if (extension) {
- return "${getBaseName()}.${extension}"
- } else {
- return getDefaultOutputFileName()
- }
- }
-
- protected String getDefaultOutputFileName() {
- return OperatingSystem.current().getExecutableName(getBaseName())
- }
-
- String getBaseName() {
- baseName ?: name
- }
-
- void setting(Closure closure) {
- settings << closure
- }
-
- void from(CppSourceSet sourceSet) {
- includes sourceSet.exportedHeaders
- source sourceSet.source
- libs sourceSet.libs
-
- sourceSet.nativeDependencySets.all { deps ->
- includes deps.includeRoots
- source deps.files
- }
- }
-
- void includes(SourceDirectorySet dirs) {
- task.inputs.files dirs
- includes.from({dirs.srcDirs})
- }
-
- // special filecollection version because filecollection may be buildable
- void includes(FileCollection includeRoots) {
- task.inputs.files includeRoots
- includes.from(includeRoots)
- }
-
- void includes(Iterable<File> includeRoots) {
- for (File includeRoot in includeRoots) {
- task.inputs.dir(includeRoot)
- }
- includes.from(includeRoots)
- }
-
- void source(Iterable<File> files) {
- task.inputs.files files
- source.from files
- }
-
- // special filecollection version because filecollection may be buildable
- void source(FileCollection files) {
- task.inputs.source files
- source.from files
- }
-
- void libs(Iterable<Library> libs) {
- task.dependsOn libs
- this.libs.from({ libs*.spec*.outputFile })
- includes(project.files { libs*.headers*.srcDirs })
- }
-
- void args(Object... args) {
- setting {
- it.args args
- }
- }
-
- /**
- * @deprecated No replacement
- */
- @Deprecated
- void sharedLibrary() {
- DeprecationLogger.nagUserOfDiscontinuedMethod("CompileSpec.sharedLibrary()")
- }
-
- /**
- * @deprecated No replacement
- */
- @Deprecated
- void compile() {
- DeprecationLogger.nagUserOfDiscontinuedMethod("CompileSpec.compile()")
- compiler.execute(this)
- }
-}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/gpp/GppCompilerPlugin.groovy b/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/gpp/GppCompilerPlugin.groovy
deleted file mode 100644
index 433c2d4..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/gpp/GppCompilerPlugin.groovy
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp.gpp
-
-import org.gradle.api.Plugin
-import org.gradle.api.Project
-import org.gradle.api.internal.file.FileResolver
-import org.gradle.internal.Factory
-import org.gradle.internal.os.OperatingSystem
-import org.gradle.plugins.binaries.BinariesPlugin
-import org.gradle.plugins.binaries.model.CompilerRegistry
-import org.gradle.plugins.cpp.gpp.internal.GppCompilerAdapter
-import org.gradle.process.internal.DefaultExecAction
-import org.gradle.process.internal.ExecAction
-
-import javax.inject.Inject
-
-/**
- * A {@link Plugin} which makes the <a href="http://gcc.gnu.org/">GNU G++ compiler</a> available for compiling C/C++ code.
- */
-class GppCompilerPlugin implements Plugin<Project> {
- private final FileResolver fileResolver
-
- @Inject
- GppCompilerPlugin(FileResolver fileResolver) {
- this.fileResolver = fileResolver
- }
-
- void apply(Project project) {
- project.plugins.apply(BinariesPlugin)
- project.extensions.getByType(CompilerRegistry).add(new GppCompilerAdapter(
- OperatingSystem.current(),
- new Factory<ExecAction>() {
- ExecAction create() {
- new DefaultExecAction(fileResolver)
- }
- }))
- }
-
-}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/gpp/GppLibraryCompileSpec.groovy b/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/gpp/GppLibraryCompileSpec.groovy
deleted file mode 100755
index e1ea17e..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/gpp/GppLibraryCompileSpec.groovy
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp.gpp
-
-import org.gradle.plugins.binaries.model.LibraryCompileSpec
-import org.gradle.plugins.binaries.model.Binary
-import org.gradle.api.internal.tasks.compile.Compiler
-import org.gradle.internal.os.OperatingSystem
-import org.gradle.api.internal.project.ProjectInternal
-
-class GppLibraryCompileSpec extends GppCompileSpec implements LibraryCompileSpec {
- String installName
-
- GppLibraryCompileSpec(Binary binary, Compiler<? super GppCompileSpec> compiler, ProjectInternal project) {
- super(binary, compiler, project)
- }
-
- @Override
- protected String getDefaultOutputFileName() {
- return OperatingSystem.current().getSharedLibraryName(getBaseName())
- }
-
- String getInstallName() {
- return installName ?: getOutputFileName()
- }
-}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/gpp/internal/GppCompileSpecFactory.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/gpp/internal/GppCompileSpecFactory.java
deleted file mode 100644
index 16a1ac6..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/gpp/internal/GppCompileSpecFactory.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp.gpp.internal;
-
-import org.gradle.api.internal.project.ProjectInternal;
-import org.gradle.api.internal.tasks.compile.Compiler;
-import org.gradle.plugins.binaries.model.Binary;
-import org.gradle.plugins.binaries.model.Library;
-import org.gradle.plugins.binaries.model.internal.BinaryCompileSpec;
-import org.gradle.plugins.binaries.model.internal.BinaryCompileSpecFactory;
-import org.gradle.plugins.cpp.gpp.GppCompileSpec;
-import org.gradle.plugins.cpp.gpp.GppLibraryCompileSpec;
-
-public class GppCompileSpecFactory implements BinaryCompileSpecFactory {
- private ProjectInternal project;
-
- public GppCompileSpecFactory(ProjectInternal project) {
- this.project = project;
- }
-
- public BinaryCompileSpec create(Binary binary, org.gradle.api.internal.tasks.compile.Compiler<?> compiler) {
- Compiler<? super GppCompileSpec> typed = (Compiler<? super GppCompileSpec>) compiler;
- if (binary instanceof Library) {
- return new GppLibraryCompileSpec(binary, typed, project);
- }
- return new GppCompileSpec(binary, typed, project);
- }
-}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/gpp/internal/GppCompileSpecToArguments.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/gpp/internal/GppCompileSpecToArguments.java
deleted file mode 100644
index 1d44fff..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/gpp/internal/GppCompileSpecToArguments.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp.gpp.internal;
-
-import org.gradle.internal.os.OperatingSystem;
-import org.gradle.plugins.binaries.model.LibraryCompileSpec;
-import org.gradle.api.internal.tasks.compile.ArgCollector;
-import org.gradle.api.internal.tasks.compile.CompileSpecToArguments;
-import org.gradle.plugins.cpp.gpp.GppCompileSpec;
-
-import java.io.File;
-
-public class GppCompileSpecToArguments implements CompileSpecToArguments<GppCompileSpec> {
-
- public void collectArguments(GppCompileSpec spec, ArgCollector collector) {
- collector.args("-o", spec.getOutputFile().getAbsolutePath());
- if (spec instanceof LibraryCompileSpec) {
- LibraryCompileSpec librarySpec = (LibraryCompileSpec) spec;
- collector.args("-shared");
- if (!OperatingSystem.current().isWindows()) {
- collector.args("-fPIC");
- if (OperatingSystem.current().isMacOsX()) {
- collector.args("-Wl,-install_name," + librarySpec.getInstallName());
- } else {
- collector.args("-Wl,-soname," + librarySpec.getInstallName());
- }
- }
- }
- for (File file : spec.getIncludeRoots()) {
- collector.args("-I");
- collector.args(file.getAbsolutePath());
- }
- for (File file : spec.getSource()) {
- collector.args(file.getAbsolutePath());
- }
- for (File file : spec.getLibs()) {
- collector.args(file.getAbsolutePath());
- }
- }
-
-}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/gpp/internal/GppCompiler.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/gpp/internal/GppCompiler.java
deleted file mode 100755
index 8b5dbf7..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/gpp/internal/GppCompiler.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp.gpp.internal;
-
-import org.gradle.internal.Factory;
-import org.gradle.api.internal.tasks.compile.ArgWriter;
-import org.gradle.plugins.cpp.compiler.internal.CommandLineCppCompiler;
-import org.gradle.plugins.cpp.compiler.internal.CommandLineCppCompilerArgumentsToOptionFile;
-import org.gradle.plugins.cpp.gpp.GppCompileSpec;
-import org.gradle.process.internal.ExecAction;
-
-import java.io.File;
-
-public class GppCompiler extends CommandLineCppCompiler<GppCompileSpec> {
-
- public GppCompiler(File executable, Factory<ExecAction> execActionFactory, boolean useCommandFile) {
- super(executable, execActionFactory, useCommandFile ? viaCommandFile() : withoutCommandFile());
- }
-
- private static GppCompileSpecToArguments withoutCommandFile() {
- return new GppCompileSpecToArguments();
- }
-
- private static CommandLineCppCompilerArgumentsToOptionFile<GppCompileSpec> viaCommandFile() {
- return new CommandLineCppCompilerArgumentsToOptionFile<GppCompileSpec>(
- ArgWriter.unixStyleFactory(), new GppCompileSpecToArguments()
- );
- }
-
-}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/gpp/internal/GppCompilerAdapter.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/gpp/internal/GppCompilerAdapter.java
deleted file mode 100755
index 4763183..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/gpp/internal/GppCompilerAdapter.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp.gpp.internal;
-
-import org.gradle.api.Transformer;
-import org.gradle.api.internal.tasks.compile.Compiler;
-import org.gradle.internal.Factory;
-import org.gradle.internal.os.OperatingSystem;
-import org.gradle.plugins.binaries.model.Binary;
-import org.gradle.plugins.cpp.compiler.internal.CommandLineCppCompilerAdapter;
-import org.gradle.plugins.cpp.gpp.GppCompileSpec;
-import org.gradle.plugins.cpp.gpp.internal.version.GppVersionDeterminer;
-import org.gradle.process.internal.ExecAction;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.File;
-
-/**
- * Compiler adapter for g++
- */
-public class GppCompilerAdapter extends CommandLineCppCompilerAdapter<GppCompileSpec> {
-
- private static final Logger LOGGER = LoggerFactory.getLogger(GppCompilerAdapter.class);
-
- static final String EXECUTABLE = "g++";
-
- public static final String NAME = "gpp";
-
- private boolean determinedVersion;
- private String version;
-
- private final Transformer<String, File> versionDeterminer;
-
- public GppCompilerAdapter(OperatingSystem operatingSystem, Factory<ExecAction> execActionFactory) {
- this(operatingSystem, execActionFactory, new GppVersionDeterminer());
- }
-
- GppCompilerAdapter(OperatingSystem operatingSystem, Factory<ExecAction> execActionFactory, Transformer<String, File> versionDeterminer) {
- super(EXECUTABLE, operatingSystem, execActionFactory);
- this.versionDeterminer = versionDeterminer;
- }
-
- public String getName() {
- return NAME;
- }
-
- @Override
- public String toString() {
- return String.format("GNU G++ (%s)", getOperatingSystem().getExecutableName(EXECUTABLE));
- }
-
- public boolean isAvailable() {
- String version = getVersion();
- return version != null;
- }
-
- public Compiler<GppCompileSpec> createCompiler(Binary binary) {
- String version = getVersion();
- if (version == null) {
- throw new IllegalStateException("Cannot create gpp compiler when it is not available");
- }
-
- String[] components = version.split("\\.");
-
- int majorVersion;
- try {
- majorVersion = Integer.valueOf(components[0]);
- } catch (NumberFormatException e) {
- throw new IllegalStateException(String.format("Unable to determine major g++ version from version number %s.", version), e);
- }
-
- return new GppCompiler(getExecutable(), getExecActionFactory(), majorVersion >= 4);
- }
-
- private String getVersion() {
- if (!determinedVersion) {
- determinedVersion = true;
- version = determineVersion(getExecutable());
- if (version == null) {
- LOGGER.info("Did not find {} on system", EXECUTABLE);
- } else {
- LOGGER.info("Found {} with version {}", EXECUTABLE, version);
- }
- }
- return version;
- }
-
- private String determineVersion(File executable) {
- return executable == null ? null : versionDeterminer.transform(executable);
- }
-
-}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/gpp/internal/version/GppVersionDeterminer.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/gpp/internal/version/GppVersionDeterminer.java
deleted file mode 100644
index efc9863..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/gpp/internal/version/GppVersionDeterminer.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp.gpp.internal.version;
-
-import org.gradle.api.Transformer;
-import org.gradle.api.internal.file.IdentityFileResolver;
-import org.gradle.internal.Factory;
-import org.gradle.process.ExecResult;
-import org.gradle.process.internal.ExecHandle;
-import org.gradle.process.internal.ExecHandleBuilder;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Given a File pointing to an (existing) g++ binary, extracts the version number by running with -v and scraping the output.
- */
-public class GppVersionDeterminer implements Transformer<String, File> {
-
- private static final Logger LOGGER = LoggerFactory.getLogger(GppVersionDeterminer.class);
-
- private final Transformer<String, String> outputScraper;
- private final Transformer<String, File> outputProducer;
-
- public GppVersionDeterminer() {
- this(new GppVersionOutputProducer(new Factory<ExecHandleBuilder>() {
- public ExecHandleBuilder create() {
- return new ExecHandleBuilder(new IdentityFileResolver());
- }
- }), new GppVersionOutputScraper());
- }
-
- GppVersionDeterminer(Transformer<String, File> outputProducer, Transformer<String, String> outputScraper) {
- this.outputProducer = outputProducer;
- this.outputScraper = outputScraper;
- }
-
- static class GppVersionOutputScraper implements Transformer<String, String> {
- public String transform(String output) {
- Pattern pattern = Pattern.compile(".*gcc version (\\S+).*", Pattern.DOTALL);
- Matcher matcher = pattern.matcher(output);
- if (matcher.matches()) {
- String scrapedVersion = matcher.group(1);
- LOGGER.debug("Extracted version {} from g++ -v output", scrapedVersion);
- return scrapedVersion;
- } else {
- LOGGER.warn("Unable to extract g++ version number from \"{}\" with pattern \"{}\"", output, pattern);
- return null;
- }
- }
- }
-
- static class GppVersionOutputProducer implements Transformer<String, File> {
-
- private final Factory<ExecHandleBuilder> execHandleBuilderFactory;
-
- GppVersionOutputProducer(Factory<ExecHandleBuilder> execHandleBuilderFactory) {
- this.execHandleBuilderFactory = execHandleBuilderFactory;
- }
-
- public String transform(File gppBinary) {
- ExecHandleBuilder exec = execHandleBuilderFactory.create();
- exec.executable(gppBinary.getAbsolutePath());
- exec.setWorkingDir(gppBinary.getParentFile());
- exec.args("-v");
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- exec.setErrorOutput(baos);
- ExecHandle handle = exec.build();
- ExecResult result = handle.start().waitForFinish();
-
- int exitValue = result.getExitValue();
- if (exitValue == 0) {
- String output = new String(baos.toByteArray());
- LOGGER.debug("Output from '{} -v {}", gppBinary.getPath(), output);
- return output;
- } else {
- LOGGER.warn("Executing '{} -v' return exit code {}, cannot use", gppBinary.getPath(), exitValue);
- return null;
- }
- }
- }
-
- public String transform(File gppBinary) {
- String output = outputProducer.transform(gppBinary);
- return output == null ? null : outputScraper.transform(output);
- }
-}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/gpp/package-info.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/gpp/package-info.java
deleted file mode 100644
index 23db2ad..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/gpp/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.
- */
-
-/**
- * Integration with the gpp (gcc frontend) compiler.
- */
-package org.gradle.plugins.cpp.gpp;
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/internal/CppCompileSpec.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/internal/CppCompileSpec.java
deleted file mode 100644
index 1699745..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/internal/CppCompileSpec.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp.internal;
-
-import groovy.lang.Closure;
-import org.gradle.plugins.binaries.model.internal.BinaryCompileSpec;
-import org.gradle.plugins.cpp.compiler.capability.StandardCppCompiler;
-
-import java.io.File;
-import java.util.List;
-
-public interface CppCompileSpec extends StandardCppCompiler, BinaryCompileSpec {
-
- File getWorkDir();
-
- // This needs to go
- List<Closure> getSettings();
-
-}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/internal/DefaultCppSourceSet.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/internal/DefaultCppSourceSet.java
deleted file mode 100644
index d7c1f32..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/internal/DefaultCppSourceSet.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp.internal;
-
-import org.gradle.plugins.cpp.CppSourceSet;
-
-import org.gradle.plugins.binaries.model.Library;
-import org.gradle.plugins.binaries.model.NativeDependencySet;
-import org.gradle.plugins.binaries.model.internal.ConfigurationBasedNativeDependencySet;
-
-import org.gradle.api.DomainObjectSet;
-import org.gradle.api.file.SourceDirectorySet;
-
-import org.gradle.api.internal.DefaultDomainObjectSet;
-import org.gradle.api.internal.project.ProjectInternal;
-import org.gradle.api.internal.file.DefaultSourceDirectorySet;
-import org.gradle.util.ConfigureUtil;
-
-import groovy.lang.Closure;
-import java.util.Map;
-
-public class DefaultCppSourceSet implements CppSourceSet {
-
- private final String name;
-
- private final DefaultSourceDirectorySet exportedHeaders;
- private final DefaultSourceDirectorySet source;
- private final DefaultDomainObjectSet<Library> libs;
- private final DefaultDomainObjectSet<NativeDependencySet> nativeDependencySets;
- private final ConfigurationBasedNativeDependencySet configurationDependencySet;
-
- public DefaultCppSourceSet(String name, ProjectInternal project) {
- this.name = name;
-
- this.exportedHeaders = new DefaultSourceDirectorySet("exported headers", project.getFileResolver());
- this.source = new DefaultSourceDirectorySet("source", project.getFileResolver());
- this.libs = new DefaultDomainObjectSet<Library>(Library.class);
- this.nativeDependencySets = new DefaultDomainObjectSet<NativeDependencySet>(NativeDependencySet.class);
- this.configurationDependencySet = new ConfigurationBasedNativeDependencySet(project, name);
-
- nativeDependencySets.add(configurationDependencySet);
- }
-
- public String getName() {
- return name;
- }
-
- public SourceDirectorySet getExportedHeaders() {
- return exportedHeaders;
- }
-
- public DefaultCppSourceSet exportedHeaders(Closure closure) {
- ConfigureUtil.configure(closure, exportedHeaders);
- return this;
- }
-
- public SourceDirectorySet getSource() {
- return source;
- }
-
- public DefaultCppSourceSet source(Closure closure) {
- ConfigureUtil.configure(closure, source);
- return this;
- }
-
- public DomainObjectSet<Library> getLibs() {
- return libs;
- }
-
- public DomainObjectSet<NativeDependencySet> getNativeDependencySets() {
- return nativeDependencySets;
- }
-
- public void dependency(Map<?, ?> dep) {
- configurationDependencySet.add(dep);
- }
-}
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/msvcpp/MicrosoftVisualCppPlugin.groovy b/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/msvcpp/MicrosoftVisualCppPlugin.groovy
deleted file mode 100755
index a64ea77..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/msvcpp/MicrosoftVisualCppPlugin.groovy
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp.msvcpp
-
-import org.gradle.api.Plugin
-import org.gradle.api.Project
-import org.gradle.api.internal.file.FileResolver
-import org.gradle.internal.Factory
-import org.gradle.plugins.binaries.BinariesPlugin
-import org.gradle.plugins.binaries.model.CompilerRegistry
-import org.gradle.plugins.cpp.msvcpp.internal.VisualCppCompilerAdapter
-import org.gradle.process.internal.ExecAction
-import org.gradle.process.internal.DefaultExecAction
-import org.gradle.internal.os.OperatingSystem
-
-import javax.inject.Inject
-
-/**
- * A {@link Plugin} which makes the Microsoft Visual C++ compiler available to compile C/C++ code.
- */
-class MicrosoftVisualCppPlugin implements Plugin<Project> {
- private final FileResolver fileResolver;
-
- @Inject
- MicrosoftVisualCppPlugin(FileResolver fileResolver) {
- this.fileResolver = fileResolver
- }
-
- void apply(Project project) {
- project.plugins.apply(BinariesPlugin)
-
- if (!OperatingSystem.current().windows) {
- return
- }
-
- project.extensions.getByType(CompilerRegistry).add(new VisualCppCompilerAdapter(
- OperatingSystem.current(),
- new Factory<ExecAction>() {
- ExecAction create() {
- new DefaultExecAction(fileResolver)
- }
- }
- ))
- }
-}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/msvcpp/internal/VisualCppCompileSpecToArguments.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/msvcpp/internal/VisualCppCompileSpecToArguments.java
deleted file mode 100644
index 91ba77f..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/msvcpp/internal/VisualCppCompileSpecToArguments.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp.msvcpp.internal;
-
-import org.gradle.plugins.binaries.model.LibraryCompileSpec;
-import org.gradle.api.internal.tasks.compile.ArgCollector;
-import org.gradle.api.internal.tasks.compile.CompileSpecToArguments;
-import org.gradle.plugins.cpp.gpp.GppCompileSpec;
-
-import java.io.File;
-
-public class VisualCppCompileSpecToArguments implements CompileSpecToArguments<GppCompileSpec> {
-
- public void collectArguments(GppCompileSpec spec, ArgCollector collector) {
- collector.args("/nologo");
- collector.args("/EHsc");
- collector.args("/Fe" + spec.getOutputFile().getAbsolutePath());
- if (spec instanceof LibraryCompileSpec) {
- collector.args("/LD");
- }
- for (File file : spec.getIncludeRoots()) {
- collector.args("/I", file.getAbsolutePath());
- }
- for (File file : spec.getSource()) {
- collector.args(file);
- }
- // Link options need to be on one line in the options file
- for (File file : spec.getLibs()) {
- collector.args("/link", file.getAbsolutePath().replaceFirst("\\.dll$", ".lib"));
- }
-
- }
-}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/msvcpp/internal/VisualCppCompiler.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/msvcpp/internal/VisualCppCompiler.java
deleted file mode 100755
index 25767dc..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/msvcpp/internal/VisualCppCompiler.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp.msvcpp.internal;
-
-import org.gradle.internal.Factory;
-import org.gradle.api.internal.tasks.compile.ArgWriter;
-import org.gradle.plugins.cpp.compiler.internal.CommandLineCppCompiler;
-import org.gradle.plugins.cpp.compiler.internal.CommandLineCppCompilerArgumentsToOptionFile;
-import org.gradle.plugins.cpp.gpp.GppCompileSpec;
-import org.gradle.process.internal.ExecAction;
-
-import java.io.File;
-
-class VisualCppCompiler extends CommandLineCppCompiler<GppCompileSpec> {
-
- VisualCppCompiler(File executable, Factory<ExecAction> execActionFactory) {
- super(executable, execActionFactory, new CommandLineCppCompilerArgumentsToOptionFile<GppCompileSpec>(
- ArgWriter.windowsStyleFactory(), new VisualCppCompileSpecToArguments()
- ));
- }
-
-}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/msvcpp/internal/VisualCppCompilerAdapter.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/msvcpp/internal/VisualCppCompilerAdapter.java
deleted file mode 100755
index 6fb7532..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/msvcpp/internal/VisualCppCompilerAdapter.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp.msvcpp.internal;
-
-import org.gradle.api.internal.tasks.compile.Compiler;
-import org.gradle.internal.Factory;
-import org.gradle.internal.os.OperatingSystem;
-import org.gradle.plugins.binaries.model.Binary;
-import org.gradle.plugins.cpp.compiler.internal.CommandLineCppCompilerAdapter;
-import org.gradle.plugins.cpp.gpp.GppCompileSpec;
-import org.gradle.process.internal.ExecAction;
-
-public class VisualCppCompilerAdapter extends CommandLineCppCompilerAdapter<GppCompileSpec> {
-
- static final String EXECUTABLE = "cl.exe";
-
- public VisualCppCompilerAdapter(OperatingSystem operatingSystem, Factory<ExecAction> execActionFactory) {
- super(EXECUTABLE, operatingSystem, execActionFactory);
- }
-
- public String getName() {
- return "visualCpp";
- }
-
- @Override
- public String toString() {
- return String.format("Visual C++ (%s)", getOperatingSystem().getExecutableName(EXECUTABLE));
- }
-
- public boolean isAvailable() {
- return getOperatingSystem().isWindows() && super.isAvailable();
- }
-
- public Compiler<GppCompileSpec> createCompiler(Binary binary) {
- return new VisualCppCompiler(getExecutable(), getExecActionFactory());
- }
-}
diff --git a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/package-info.java b/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/package-info.java
deleted file mode 100644
index 578bd12..0000000
--- a/subprojects/cpp/src/main/groovy/org/gradle/plugins/cpp/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.
- */
-
-/**
- * A {@link org.gradle.api.Plugin} for building C++ projects with Gradle.
- */
-package org.gradle.plugins.cpp;
diff --git a/subprojects/cpp/src/main/resources/META-INF/gradle-plugins/binaries.properties b/subprojects/cpp/src/main/resources/META-INF/gradle-plugins/binaries.properties
index fe8bfdc..e60e5d5 100644
--- a/subprojects/cpp/src/main/resources/META-INF/gradle-plugins/binaries.properties
+++ b/subprojects/cpp/src/main/resources/META-INF/gradle-plugins/binaries.properties
@@ -1 +1 @@
-implementation-class=org.gradle.plugins.binaries.BinariesPlugin
\ No newline at end of file
+implementation-class=org.gradle.nativecode.base.plugins.NativeBinariesPlugin
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/resources/META-INF/gradle-plugins/cpp-exe.properties b/subprojects/cpp/src/main/resources/META-INF/gradle-plugins/cpp-exe.properties
index 23e9515..19f5f83 100644
--- a/subprojects/cpp/src/main/resources/META-INF/gradle-plugins/cpp-exe.properties
+++ b/subprojects/cpp/src/main/resources/META-INF/gradle-plugins/cpp-exe.properties
@@ -1 +1 @@
-implementation-class=org.gradle.plugins.cpp.CppExeConventionPlugin
\ No newline at end of file
+implementation-class=org.gradle.nativecode.language.cpp.plugins.CppExeConventionPlugin
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/resources/META-INF/gradle-plugins/cpp-lib.properties b/subprojects/cpp/src/main/resources/META-INF/gradle-plugins/cpp-lib.properties
index 7ca7910..36844f0 100644
--- a/subprojects/cpp/src/main/resources/META-INF/gradle-plugins/cpp-lib.properties
+++ b/subprojects/cpp/src/main/resources/META-INF/gradle-plugins/cpp-lib.properties
@@ -1 +1 @@
-implementation-class=org.gradle.plugins.cpp.CppLibConventionPlugin
\ No newline at end of file
+implementation-class=org.gradle.nativecode.language.cpp.plugins.CppLibConventionPlugin
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/resources/META-INF/gradle-plugins/cpp.properties b/subprojects/cpp/src/main/resources/META-INF/gradle-plugins/cpp.properties
index cad2a5f..7289d30 100644
--- a/subprojects/cpp/src/main/resources/META-INF/gradle-plugins/cpp.properties
+++ b/subprojects/cpp/src/main/resources/META-INF/gradle-plugins/cpp.properties
@@ -1 +1 @@
-implementation-class=org.gradle.plugins.cpp.CppPlugin
\ No newline at end of file
+implementation-class=org.gradle.nativecode.language.cpp.plugins.CppPlugin
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/resources/META-INF/gradle-plugins/eclipse-cdt.properties b/subprojects/cpp/src/main/resources/META-INF/gradle-plugins/eclipse-cdt.properties
index 7ec9e10..d7d7cdf 100644
--- a/subprojects/cpp/src/main/resources/META-INF/gradle-plugins/eclipse-cdt.properties
+++ b/subprojects/cpp/src/main/resources/META-INF/gradle-plugins/eclipse-cdt.properties
@@ -1 +1 @@
-implementation-class=org.gradle.plugins.cpp.cdt.CdtIdePlugin
\ No newline at end of file
+implementation-class=org.gradle.nativecode.cdt.CdtIdePlugin
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/resources/META-INF/gradle-plugins/gpp-compiler.properties b/subprojects/cpp/src/main/resources/META-INF/gradle-plugins/gpp-compiler.properties
index a135aac..2189642 100644
--- a/subprojects/cpp/src/main/resources/META-INF/gradle-plugins/gpp-compiler.properties
+++ b/subprojects/cpp/src/main/resources/META-INF/gradle-plugins/gpp-compiler.properties
@@ -1 +1 @@
-implementation-class=org.gradle.plugins.cpp.gpp.GppCompilerPlugin
\ No newline at end of file
+implementation-class=org.gradle.nativecode.toolchain.plugins.GppCompilerPlugin
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/resources/META-INF/gradle-plugins/visual-cpp.properties b/subprojects/cpp/src/main/resources/META-INF/gradle-plugins/visual-cpp.properties
new file mode 100644
index 0000000..507007b
--- /dev/null
+++ b/subprojects/cpp/src/main/resources/META-INF/gradle-plugins/visual-cpp.properties
@@ -0,0 +1 @@
+implementation-class=org.gradle.nativecode.toolchain.plugins.MicrosoftVisualCppPlugin
\ No newline at end of file
diff --git a/subprojects/cpp/src/main/resources/org/gradle/plugins/cpp/cdt/model/defaultCproject-linux.xml b/subprojects/cpp/src/main/resources/org/gradle/nativecode/cdt/model/defaultCproject-linux.xml
similarity index 100%
rename from subprojects/cpp/src/main/resources/org/gradle/plugins/cpp/cdt/model/defaultCproject-linux.xml
rename to subprojects/cpp/src/main/resources/org/gradle/nativecode/cdt/model/defaultCproject-linux.xml
diff --git a/subprojects/cpp/src/main/resources/org/gradle/plugins/cpp/cdt/model/defaultCproject-macos.xml b/subprojects/cpp/src/main/resources/org/gradle/nativecode/cdt/model/defaultCproject-macos.xml
similarity index 100%
rename from subprojects/cpp/src/main/resources/org/gradle/plugins/cpp/cdt/model/defaultCproject-macos.xml
rename to subprojects/cpp/src/main/resources/org/gradle/nativecode/cdt/model/defaultCproject-macos.xml
diff --git a/subprojects/cpp/src/main/resources/org/gradle/plugins/cpp/cdt/model/defaultProject.xml b/subprojects/cpp/src/main/resources/org/gradle/nativecode/cdt/model/defaultProject.xml
similarity index 100%
rename from subprojects/cpp/src/main/resources/org/gradle/plugins/cpp/cdt/model/defaultProject.xml
rename to subprojects/cpp/src/main/resources/org/gradle/nativecode/cdt/model/defaultProject.xml
diff --git a/subprojects/cpp/src/test/groovy/org/gradle/nativecode/base/internal/DefaultExecutableBinaryTest.groovy b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/base/internal/DefaultExecutableBinaryTest.groovy
new file mode 100644
index 0000000..814cfb5
--- /dev/null
+++ b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/base/internal/DefaultExecutableBinaryTest.groovy
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.internal
+import org.gradle.internal.reflect.DirectInstantiator
+import org.gradle.language.base.internal.DefaultBinaryNamingScheme
+import org.gradle.nativecode.base.Executable
+import spock.lang.Specification
+
+class DefaultExecutableBinaryTest extends Specification {
+ def namingScheme = new DefaultBinaryNamingScheme("bigOne")
+ def flavorContainer = new DefaultFlavorContainer(new DirectInstantiator())
+
+ def "has useful string representation"() {
+ given:
+ def executable = Stub(Executable) {
+ getName() >> "bigOne"
+ getFlavors() >> flavorContainer
+ }
+ flavorContainer.add(new DefaultFlavor("flavorOne"))
+
+ when:
+ def binary = new DefaultExecutableBinary(executable, new DefaultFlavor("flavorOne"), Stub(ToolChainInternal), namingScheme)
+
+ then:
+ binary.toString() == "executable 'bigOneExecutable'"
+ }
+}
diff --git a/subprojects/cpp/src/test/groovy/org/gradle/nativecode/base/internal/DefaultExecutableTest.groovy b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/base/internal/DefaultExecutableTest.groovy
new file mode 100644
index 0000000..418b0e5
--- /dev/null
+++ b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/base/internal/DefaultExecutableTest.groovy
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.internal
+import org.gradle.internal.reflect.DirectInstantiator
+import spock.lang.Specification
+
+class DefaultExecutableTest extends Specification {
+ def "has useful string representation"() {
+ def executable = new DefaultExecutable("someExe", new DirectInstantiator())
+
+ expect:
+ executable.toString() == "executable 'someExe'"
+ }
+}
diff --git a/subprojects/cpp/src/test/groovy/org/gradle/nativecode/base/internal/DefaultFlavorContainerTest.groovy b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/base/internal/DefaultFlavorContainerTest.groovy
new file mode 100644
index 0000000..4f091cf
--- /dev/null
+++ b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/base/internal/DefaultFlavorContainerTest.groovy
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.internal
+
+import org.gradle.internal.reflect.DirectInstantiator
+import org.gradle.nativecode.base.Flavor
+import spock.lang.Specification
+
+class DefaultFlavorContainerTest extends Specification {
+ def flavorContainer = new DefaultFlavorContainer(new DirectInstantiator())
+
+ def "has a single default flavor when not configured"() {
+ expect:
+ flavorContainer.size() == 1
+ flavorContainer == [Flavor.DEFAULT] as Set
+ }
+
+ def "configured flavors overwrite default flavor"() {
+ when:
+ flavorContainer.configure {
+ flavor1 {}
+ flavor2 {}
+ }
+
+ then:
+ flavorContainer.size() == 2
+ flavorContainer == [new DefaultFlavor("flavor1"), new DefaultFlavor("flavor2")] as Set
+
+ }
+
+ def "can explicitly add flavor named 'default'"() {
+ when:
+ flavorContainer.configure {
+ flavor1 {}
+ it.'default' {}
+ flavor2 {}
+ }
+
+ then:
+ flavorContainer.size() == 3
+ flavorContainer == [new DefaultFlavor("flavor1"), new DefaultFlavor("flavor2"), Flavor.DEFAULT] as Set
+
+ }
+}
diff --git a/subprojects/cpp/src/test/groovy/org/gradle/nativecode/base/internal/DefaultFlavorTest.groovy b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/base/internal/DefaultFlavorTest.groovy
new file mode 100644
index 0000000..5fdcd4b
--- /dev/null
+++ b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/base/internal/DefaultFlavorTest.groovy
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.internal
+
+import spock.lang.Specification
+
+class DefaultFlavorTest extends Specification {
+ def "has useful string representation"() {
+ def flavor = new DefaultFlavor("someFlavor")
+
+ expect:
+ flavor.toString() == "flavor 'someFlavor'"
+ }
+
+ def "has well behaved equals and hashcode"() {
+ def one = new DefaultFlavor("one")
+ def same = new DefaultFlavor("one")
+ def different = new DefaultFlavor("two")
+
+ expect:
+ one == same
+ one != different
+ }
+}
diff --git a/subprojects/cpp/src/test/groovy/org/gradle/nativecode/base/internal/DefaultLibraryResolverTest.groovy b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/base/internal/DefaultLibraryResolverTest.groovy
new file mode 100644
index 0000000..79260f2
--- /dev/null
+++ b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/base/internal/DefaultLibraryResolverTest.groovy
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.internal
+import org.gradle.api.InvalidUserDataException
+import org.gradle.api.internal.DefaultDomainObjectSet
+import org.gradle.internal.reflect.DirectInstantiator
+import org.gradle.nativecode.base.*
+import spock.lang.Specification
+
+class DefaultLibraryResolverTest extends Specification {
+ final flavor1 = new DefaultFlavor("flavor1")
+ final flavor2 = new DefaultFlavor("flavor2")
+ final flavorContainer = new DefaultFlavorContainer(new DirectInstantiator())
+
+ def library = Mock(Library)
+ def sharedDeps = Mock(NativeDependencySet)
+ def staticDeps = Mock(NativeDependencySet)
+
+ def staticBinary1 = Stub(StaticLibraryBinary) {
+ getFlavor() >> flavor1
+ }
+ def staticBinary2 = Stub(StaticLibraryBinary) {
+ getFlavor() >> flavor2
+ }
+ def sharedBinary1 = Stub(SharedLibraryBinary) {
+ getFlavor() >> flavor1
+ }
+ def sharedBinary2 = Stub(SharedLibraryBinary) {
+ getFlavor() >> flavor2
+ }
+
+ def "setup"() {
+ library.flavors >> flavorContainer
+ }
+
+ def "returns library dependencies for library with single default flavor"() {
+ when:
+ library.getBinaries() >> binaries(staticBinary1, sharedBinary1)
+
+ and:
+ sharedBinary1.resolve() >> sharedDeps
+ staticBinary1.resolve() >> staticDeps
+
+ then:
+ resolver.resolve() == sharedDeps;
+ resolver.withType(SharedLibraryBinary.class).resolve() == sharedDeps
+ resolver.withType(StaticLibraryBinary.class).resolve() == staticDeps
+ }
+
+ def "returns library dependencies for library with single explicit flavor"() {
+ when:
+ flavorContainer.addAll([flavor2])
+ library.getBinaries() >> binaries(staticBinary2, sharedBinary2)
+
+ and:
+ sharedBinary2.resolve() >> sharedDeps
+ staticBinary2.resolve() >> staticDeps
+
+ then:
+ resolver.withFlavor(flavor1).resolve() == sharedDeps;
+ resolver.withFlavor(flavor1).withType(SharedLibraryBinary.class).resolve() == sharedDeps
+ resolver.withFlavor(flavor1).withType(StaticLibraryBinary.class).resolve() == staticDeps
+
+ and:
+ resolver.withFlavor(flavor2).resolve() == sharedDeps;
+ resolver.withFlavor(flavor2).withType(SharedLibraryBinary.class).resolve() == sharedDeps
+ resolver.withFlavor(flavor2).withType(StaticLibraryBinary.class).resolve() == staticDeps
+ }
+
+ def "returns matching library dependencies for library with multiple flavors"() {
+ when:
+ flavorContainer.addAll([flavor1, flavor2])
+ library.getBinaries() >> binaries(staticBinary1, staticBinary2, sharedBinary1, sharedBinary2)
+
+ and:
+ sharedBinary2.resolve() >> sharedDeps
+ staticBinary2.resolve() >> staticDeps
+
+ then:
+ resolver.withFlavor(flavor2).resolve() == sharedDeps;
+ resolver.withFlavor(flavor2).withType(SharedLibraryBinary.class).resolve() == sharedDeps
+ resolver.withFlavor(flavor2).withType(StaticLibraryBinary.class).resolve() == staticDeps
+
+ when:
+ sharedBinary1.resolve() >> sharedDeps
+ staticBinary1.resolve() >> staticDeps
+
+ then:
+ resolver.withFlavor(flavor1).resolve() == sharedDeps;
+ resolver.withFlavor(flavor1).withType(SharedLibraryBinary.class).resolve() == sharedDeps
+ resolver.withFlavor(flavor1).withType(StaticLibraryBinary.class).resolve() == staticDeps
+ }
+
+ def "fails when no library found with defined flavor"() {
+ when:
+ flavorContainer.addAll([flavor1, flavor2])
+ library.getBinaries() >> binaries(sharedBinary1, sharedBinary2)
+
+ and:
+ resolver.withFlavor(new DefaultFlavor("different")).resolve();
+
+ then:
+ def e = thrown InvalidUserDataException
+ e.message == "No shared library binary available for $library with flavor 'different'"
+ }
+
+ def getResolver() {
+ return new DefaultLibraryResolver(library)
+ }
+
+ def binaries(NativeBinary... values) {
+ return new DefaultDomainObjectSet<NativeBinary>(NativeBinary.class, values as List)
+ }
+}
diff --git a/subprojects/cpp/src/test/groovy/org/gradle/nativecode/base/internal/DefaultLibraryTest.groovy b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/base/internal/DefaultLibraryTest.groovy
new file mode 100644
index 0000000..aff2eea
--- /dev/null
+++ b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/base/internal/DefaultLibraryTest.groovy
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.internal
+
+import org.gradle.api.file.FileCollection
+import org.gradle.api.internal.file.FileResolver
+import org.gradle.internal.reflect.DirectInstantiator
+import org.gradle.nativecode.base.NativeDependencySet
+import org.gradle.nativecode.base.SharedLibraryBinary
+import org.gradle.nativecode.base.StaticLibraryBinary
+import spock.lang.Specification
+
+class DefaultLibraryTest extends Specification {
+ def "has useful string representation"() {
+ def library = new DefaultLibrary("someLib", new DirectInstantiator(), Stub(FileResolver))
+
+ expect:
+ library.toString() == "library 'someLib'"
+ }
+
+ def "can use shared and static variants as dependencies"() {
+ def library = new DefaultLibrary("someLib", new DirectInstantiator(), Stub(FileResolver))
+ def sharedLinkFiles = Stub(FileCollection)
+ def staticLinkFiles = Stub(FileCollection)
+ def sharedDependency = Stub(NativeDependencySet)
+ def staticDependency = Stub(NativeDependencySet)
+ def sharedBinary = Stub(SharedLibraryBinary) {
+ getFlavor() >> new DefaultFlavor("default")
+ }
+ def staticBinary = Stub(StaticLibraryBinary) {
+ getFlavor() >> new DefaultFlavor("default")
+ }
+
+ given:
+ library.binaries.add(sharedBinary)
+ library.binaries.add(staticBinary)
+
+ and:
+ sharedDependency.linkFiles >> sharedLinkFiles
+ staticDependency.linkFiles >> staticLinkFiles
+ sharedBinary.resolve() >> sharedDependency
+ staticBinary.resolve() >> staticDependency
+
+ expect:
+ library.shared.resolve().linkFiles == sharedLinkFiles
+ library.static.resolve().linkFiles == staticLinkFiles
+ }
+}
diff --git a/subprojects/cpp/src/test/groovy/org/gradle/nativecode/base/internal/DefaultNativeBinaryTest.groovy b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/base/internal/DefaultNativeBinaryTest.groovy
new file mode 100644
index 0000000..0661b10
--- /dev/null
+++ b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/base/internal/DefaultNativeBinaryTest.groovy
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.internal
+
+import org.gradle.internal.reflect.DirectInstantiator
+import org.gradle.language.base.LanguageSourceSet
+import org.gradle.language.base.internal.DefaultBinaryNamingScheme
+import org.gradle.language.base.internal.DefaultFunctionalSourceSet
+import org.gradle.nativecode.base.*
+import spock.lang.Specification
+
+class DefaultNativeBinaryTest extends Specification {
+ def flavor1 = new DefaultFlavor("flavor1")
+ def component = new DefaultNativeComponent("name", new DirectInstantiator())
+
+ def "binary uses source from its owner component"() {
+ given:
+ def binary = new TestBinary(component)
+ def sourceSet = Stub(LanguageSourceSet)
+
+ when:
+ component.source(sourceSet)
+
+ then:
+ binary.source.contains(sourceSet)
+ }
+
+ def "binary uses all source sets from a functional source set"() {
+ given:
+ def binary = new TestBinary(component)
+ def functionalSourceSet = new DefaultFunctionalSourceSet("func", new DirectInstantiator())
+ def sourceSet1 = Stub(LanguageSourceSet) {
+ getName() >> "ss1"
+ }
+ def sourceSet2 = Stub(LanguageSourceSet) {
+ getName() >> "ss2"
+ }
+
+ when:
+ functionalSourceSet.add(sourceSet1)
+ functionalSourceSet.add(sourceSet2)
+
+ and:
+ binary.source functionalSourceSet
+
+ then:
+ binary.source.contains(sourceSet1)
+ binary.source.contains(sourceSet2)
+ }
+
+ def "can add a resolved library as a dependency of the binary"() {
+ def binary = new TestBinary(component, flavor1)
+ def library = Mock(Library)
+ def resolver = Mock(ConfigurableLibraryResolver)
+ def dependency = Stub(NativeDependencySet)
+
+ given:
+ library.shared >> resolver
+ resolver.withFlavor(flavor1) >> resolver
+ resolver.resolve() >> dependency
+
+ when:
+ binary.lib(library)
+
+ then:
+ binary.libs.size() == 1
+ binary.libs.contains(dependency)
+ }
+
+ def "can add a library binary as a dependency of the binary"() {
+ def binary = new TestBinary(component)
+ def dependency = Stub(NativeDependencySet)
+ def libraryBinary = Mock(LibraryBinary)
+
+ given:
+ libraryBinary.resolve() >> dependency
+
+ when:
+ binary.lib(libraryBinary)
+
+ then:
+ binary.libs.size() == 1
+ binary.libs.contains(dependency)
+ }
+
+ def "can add a native dependency as a dependency of the binary"() {
+ def binary = new TestBinary(component)
+ def dependency = Stub(NativeDependencySet)
+
+ when:
+ binary.lib(dependency)
+
+ then:
+ binary.libs.size() == 1
+ binary.libs.contains(dependency)
+ }
+
+ class TestBinary extends DefaultNativeBinary {
+ TestBinary(NativeComponent owner, Flavor flavor = Flavor.DEFAULT, String type = "type") {
+ super(owner, flavor, null, new DefaultBinaryNamingScheme("baseName"))
+ }
+
+ @Override
+ protected NativeComponent getComponent() {
+ throw new UnsupportedOperationException()
+ }
+
+ @Override
+ String getOutputFileName() {
+ throw new UnsupportedOperationException()
+ }
+ }
+}
diff --git a/subprojects/cpp/src/test/groovy/org/gradle/nativecode/base/internal/DefaultNativeComponentTest.groovy b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/base/internal/DefaultNativeComponentTest.groovy
new file mode 100644
index 0000000..9fcc3fd
--- /dev/null
+++ b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/base/internal/DefaultNativeComponentTest.groovy
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.internal
+
+import org.gradle.api.Action
+import org.gradle.api.internal.AsmBackedClassGenerator
+import org.gradle.api.internal.ClassGeneratorBackedInstantiator
+import org.gradle.internal.reflect.DirectInstantiator
+import org.gradle.language.base.LanguageSourceSet
+import org.gradle.language.base.internal.DefaultFunctionalSourceSet
+import org.gradle.nativecode.base.Flavor
+import org.gradle.nativecode.base.FlavorContainer
+import spock.lang.Specification
+
+class DefaultNativeComponentTest extends Specification {
+ def instantiator = new ClassGeneratorBackedInstantiator(new AsmBackedClassGenerator(), new DirectInstantiator())
+ def component = new DefaultNativeComponent("name", instantiator)
+
+ def "uses all source sets from a functional source set"() {
+ given:
+ def functionalSourceSet = new DefaultFunctionalSourceSet("func", instantiator)
+ def sourceSet1 = Stub(LanguageSourceSet) {
+ getName() >> "ss1"
+ }
+ def sourceSet2 = Stub(LanguageSourceSet) {
+ getName() >> "ss2"
+ }
+
+ when:
+ functionalSourceSet.add(sourceSet1)
+ functionalSourceSet.add(sourceSet2)
+
+ and:
+ component.source functionalSourceSet
+
+ then:
+ component.source.contains(sourceSet1)
+ component.source.contains(sourceSet2)
+ }
+
+ def "automatically has a single flavor named 'default'"() {
+ expect:
+ component.flavors == [Flavor.DEFAULT] as Set
+ }
+
+ def "flavors can be added and will replace default flavor"() {
+ when:
+ component.flavors({
+ it.create("flavor1")
+ it.create("flavor2")
+ } as Action<FlavorContainer>)
+
+ and:
+ component.flavors.create("flavor3")
+
+ then:
+ component.flavors == [flavor("flavor1"), flavor("flavor2"), flavor("flavor3")] as Set
+ }
+
+ def flavor(String name) {
+ new DefaultFlavor(name)
+ }
+}
diff --git a/subprojects/cpp/src/test/groovy/org/gradle/nativecode/base/internal/DefaultSharedLibraryBinaryTest.groovy b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/base/internal/DefaultSharedLibraryBinaryTest.groovy
new file mode 100644
index 0000000..9a58d77
--- /dev/null
+++ b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/base/internal/DefaultSharedLibraryBinaryTest.groovy
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.internal
+import org.gradle.api.Task
+import org.gradle.api.file.SourceDirectorySet
+import org.gradle.language.base.internal.DefaultBinaryNamingScheme
+import org.gradle.nativecode.base.Library
+import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
+import org.junit.Rule
+import spock.lang.Specification
+
+class DefaultSharedLibraryBinaryTest extends Specification {
+ @Rule TestNameTestDirectoryProvider tmpDir
+ def namingScheme = new DefaultBinaryNamingScheme("main")
+ final toolChain = Stub(ToolChainInternal)
+ final library = Stub(Library)
+
+ def "has useful string representation"() {
+ expect:
+ sharedLibrary.toString() == "shared library 'mainSharedLibrary'"
+ }
+
+ def "can convert binary to a native dependency"() {
+ given:
+ def binary = sharedLibrary
+ def binaryFile = tmpDir.createFile("binary.run")
+ def linkFile = tmpDir.createFile("binary.link")
+ def lifecycleTask = Stub(Task)
+ binary.setLifecycleTask(lifecycleTask)
+ binary.dependsOn(Stub(Task))
+ binary.outputFile = binaryFile
+
+ and:
+ def headers = Stub(SourceDirectorySet)
+ library.headers >> headers
+ toolChain.getSharedLibraryLinkFileName(binaryFile.path) >> linkFile.path
+
+ expect:
+ def nativeDependency = binary.resolve()
+ nativeDependency.includeRoots == headers
+
+ and:
+ nativeDependency.linkFiles.files == [linkFile] as Set
+ nativeDependency.linkFiles.buildDependencies.getDependencies(Stub(Task)) == [lifecycleTask] as Set
+ nativeDependency.linkFiles.toString() == "shared library 'mainSharedLibrary'"
+
+ and:
+ nativeDependency.runtimeFiles.files == [binaryFile] as Set
+ nativeDependency.runtimeFiles.buildDependencies.getDependencies(Stub(Task)) == [lifecycleTask] as Set
+ nativeDependency.runtimeFiles.toString() == "shared library 'mainSharedLibrary'"
+ }
+
+ private DefaultSharedLibraryBinary getSharedLibrary() {
+ new DefaultSharedLibraryBinary(library, new DefaultFlavor("flavorOne"), toolChain, namingScheme)
+ }
+}
diff --git a/subprojects/cpp/src/test/groovy/org/gradle/nativecode/base/internal/DefaultStaticLibraryBinaryTest.groovy b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/base/internal/DefaultStaticLibraryBinaryTest.groovy
new file mode 100644
index 0000000..82a9328
--- /dev/null
+++ b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/base/internal/DefaultStaticLibraryBinaryTest.groovy
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.internal
+import org.gradle.api.Task
+import org.gradle.api.file.SourceDirectorySet
+import org.gradle.language.base.internal.DefaultBinaryNamingScheme
+import org.gradle.nativecode.base.Library
+import spock.lang.Specification
+
+class DefaultStaticLibraryBinaryTest extends Specification {
+ def namingScheme = new DefaultBinaryNamingScheme("main")
+ def library = Stub(Library)
+ def toolChain = Stub(ToolChainInternal)
+
+ def "has useful string representation"() {
+ expect:
+ staticLibrary.toString() == "static library 'mainStaticLibrary'"
+ }
+
+ def getStaticLibrary() {
+ new DefaultStaticLibraryBinary(library, new DefaultFlavor("flavorOne"), toolChain, namingScheme)
+ }
+
+ def "can convert binary to a native dependency"() {
+ final binary = staticLibrary
+ given:
+ def headers = Stub(SourceDirectorySet)
+ library.headers >> headers
+ def lifecycleTask = Stub(Task)
+ binary.lifecycleTask = lifecycleTask
+ binary.dependsOn(Stub(Task))
+
+ expect:
+ def nativeDependency = binary.resolve()
+ nativeDependency.includeRoots == headers
+
+ and:
+ nativeDependency.linkFiles.files == [binary.outputFile] as Set
+ nativeDependency.linkFiles.buildDependencies.getDependencies(Stub(Task)) == [lifecycleTask] as Set
+ nativeDependency.linkFiles.toString() == "static library 'mainStaticLibrary'"
+
+ and:
+ nativeDependency.runtimeFiles.files.isEmpty()
+ nativeDependency.runtimeFiles.buildDependencies.getDependencies(Stub(Task)).isEmpty()
+ nativeDependency.runtimeFiles.toString() == "static library 'mainStaticLibrary'"
+ }
+}
diff --git a/subprojects/cpp/src/test/groovy/org/gradle/nativecode/base/internal/DefaultToolChainRegistryTest.groovy b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/base/internal/DefaultToolChainRegistryTest.groovy
new file mode 100644
index 0000000..639a7cc
--- /dev/null
+++ b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/base/internal/DefaultToolChainRegistryTest.groovy
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.internal
+import org.gradle.api.NamedDomainObjectFactory
+import org.gradle.internal.reflect.Instantiator
+import org.gradle.util.TestUtil
+import spock.lang.Specification
+
+class DefaultToolChainRegistryTest extends Specification {
+ def project = TestUtil.createRootProject()
+ def instantiator = project.services.get(Instantiator)
+ def registry = instantiator.newInstance(DefaultToolChainRegistry, instantiator)
+ def NamedDomainObjectFactory<TestToolChain> factory = Mock(NamedDomainObjectFactory)
+
+ def "setup"() {
+ project.extensions.add("toolChains", registry)
+ registry.registerFactory(TestToolChain, factory)
+ }
+
+ def "has first available default tool chain when none configured"() {
+ unavailableToolChain("test1")
+ def defaultToolChain2 = availableToolChain("test2")
+
+ when:
+ registry.registerDefaultToolChain("test1", TestToolChain)
+ registry.registerDefaultToolChain("test2", TestToolChain)
+ registry.registerDefaultToolChain("test3", TestToolChain)
+
+ then:
+ registry.asList() == [defaultToolChain2]
+ registry.availableToolChains == [defaultToolChain2]
+ }
+
+ def "explicitly created toolchain overwrites default toolchain"() {
+ availableToolChain("default")
+ def configuredToolChain = unavailableToolChain("configured")
+
+ when:
+ registry.registerDefaultToolChain("default", TestToolChain)
+
+ and:
+ registry.create("configured", TestToolChain)
+
+ then:
+ registry.asList() == [configuredToolChain]
+ }
+
+ def "explicitly added toolchain overwrites default toolchain"() {
+ availableToolChain("default")
+ def addedToolChain = Stub(TestToolChain) {
+ getName() >> "added"
+ getAvailability() >> new ToolChainAvailability()
+ }
+
+ when:
+ registry.registerDefaultToolChain("default", TestToolChain)
+
+ and:
+ registry.add(addedToolChain)
+
+ then:
+ registry.asList() == [addedToolChain]
+ }
+
+ def "can use DSL to replace and add to default toolchain list"() {
+ availableToolChain("test")
+ def replacementToolChain = unavailableToolChain("test")
+ def anotherToolChain = unavailableToolChain("another")
+
+ when:
+ registry.registerDefaultToolChain("test", TestToolChain)
+
+ and:
+ project.toolChains {
+ test(TestToolChain) {
+ baseDir = "foo"
+ }
+ another(TestToolChain) {
+ baseDir = "bar"
+ }
+ }
+
+ then:
+ 1 * replacementToolChain.setBaseDir("foo")
+ 1 * anotherToolChain.setBaseDir("bar")
+
+ and:
+ registry.asList() == [anotherToolChain, replacementToolChain]
+ }
+
+ def "returns all available toolchains from configured in name order"() {
+ unavailableToolChain("test")
+ def tc2 = availableToolChain("test2")
+ def tcFirst = availableToolChain("first")
+
+ when:
+ registry.create("test", TestToolChain)
+ registry.create("test2", TestToolChain)
+ registry.create("first", TestToolChain)
+
+ then:
+ registry.availableToolChains == [tcFirst, tc2]
+ }
+
+ def "default toolchain is first available in name order"() {
+ unavailableToolChain("test")
+ def tc2 = availableToolChain("test2")
+ unavailableToolChain("test3")
+
+ when:
+ registry.create("test", TestToolChain)
+ registry.create("test2", TestToolChain)
+ registry.create("test3", TestToolChain)
+
+
+ then:
+ registry.defaultToolChain == tc2
+ }
+
+ def "reports unavailability when no tool chain available"() {
+ unavailableToolChain("test", "nope")
+ unavailableToolChain("test2", "not me")
+ unavailableToolChain("test3", "not me either")
+
+ given:
+ registry.create("test", TestToolChain)
+ registry.create("test2", TestToolChain)
+ registry.create("test3", TestToolChain)
+
+ when:
+ def defaultToolChain = registry.defaultToolChain
+ defaultToolChain.createCCompiler()
+
+ then:
+ IllegalStateException e = thrown()
+ e.message == "No tool chain is available: [Could not load 'test': nope, Could not load 'test2': not me, Could not load 'test3': not me either]"
+ }
+
+ def availableToolChain(String name) {
+ TestToolChain testToolChain = Mock(TestToolChain) {
+ _ * getName() >> name
+ _ * getAvailability() >> new ToolChainAvailability()
+ }
+ 1 * factory.create(name) >> testToolChain
+ return testToolChain
+ }
+
+ def unavailableToolChain(String name, String message = "Not available") {
+ TestToolChain testToolChain = Mock(TestToolChain) {
+ _ * getName() >> name
+ _ * getAvailability() >> new ToolChainAvailability().unavailable(message)
+ }
+ 1 * factory.create(name) >> testToolChain
+ return testToolChain
+ }
+
+ interface TestToolChain extends ToolChainInternal
+ {
+ void setBaseDir(String value);
+ }
+
+}
diff --git a/subprojects/cpp/src/test/groovy/org/gradle/nativecode/base/internal/NativeBinaryFactoryTest.groovy b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/base/internal/NativeBinaryFactoryTest.groovy
new file mode 100644
index 0000000..ecf56da
--- /dev/null
+++ b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/base/internal/NativeBinaryFactoryTest.groovy
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.internal
+import org.gradle.api.internal.project.ProjectInternal
+import org.gradle.internal.reflect.DirectInstantiator
+import org.gradle.nativecode.base.Flavor
+import spock.lang.Specification
+
+class NativeBinaryFactoryTest extends Specification {
+ def project = Mock(ProjectInternal)
+
+ def toolChain = Mock(ToolChainInternal)
+
+ def flavor1 = new DefaultFlavor("flavor1")
+ def component = new DefaultExecutable("name", new DirectInstantiator())
+
+ def "does not use flavor in names name when component has only default flavor"() {
+ when:
+ def factory = new NativeBinaryFactory(new DirectInstantiator(), project, [])
+ def binary = factory.createNativeBinary(DefaultExecutableBinary, component, toolChain, Flavor.DEFAULT)
+
+ then:
+ component.flavors == [Flavor.DEFAULT] as Set
+
+ and:
+ binary.namingScheme.lifecycleTaskName == 'nameExecutable'
+ binary.namingScheme.outputDirectoryBase == 'nameExecutable'
+ binary.namingScheme.getTaskName("link") == 'linkNameExecutable'
+ binary.namingScheme.getTaskName("compile", "cpp") == 'compileNameExecutableCpp'
+ }
+
+ def "does not use flavor in names when component has only one configured flavor"() {
+ when:
+ component.flavors.add(flavor1)
+
+ and:
+ def factory = new NativeBinaryFactory(new DirectInstantiator(), project, [])
+ def binary = factory.createNativeBinary(DefaultExecutableBinary, component, toolChain, flavor1)
+
+ then:
+ binary.namingScheme.lifecycleTaskName == 'nameExecutable'
+ binary.namingScheme.outputDirectoryBase == 'nameExecutable'
+ binary.namingScheme.getTaskName("link") == 'linkNameExecutable'
+ binary.namingScheme.getTaskName("compile", "cpp") == 'compileNameExecutableCpp'
+ }
+
+ def "includes flavor in names when component has multiple flavors"() {
+ when:
+ component.flavors.add(Flavor.DEFAULT)
+ component.flavors.add(flavor1)
+
+ and:
+ def factory = new NativeBinaryFactory(new DirectInstantiator(), project, [])
+ def binary = factory.createNativeBinary(DefaultExecutableBinary, component, toolChain, flavor1)
+
+ then:
+ binary.namingScheme.lifecycleTaskName == 'flavor1NameExecutable'
+ binary.namingScheme.outputDirectoryBase == 'nameExecutable/flavor1'
+ binary.namingScheme.getTaskName("link") == 'linkFlavor1NameExecutable'
+ binary.namingScheme.getTaskName("compile", "cpp") == 'compileFlavor1NameExecutableCpp'
+ }
+
+ def "includes tool chain in names when building with multiple tool chains"() {
+ when:
+ component.flavors.add(Flavor.DEFAULT)
+ component.flavors.add(flavor1)
+
+ and:
+ def toolChain2 = Stub(ToolChainInternal) {
+ getName() >> "toolChain2"
+ }
+
+ and:
+ def factory = new NativeBinaryFactory(new DirectInstantiator(), project, [toolChain, toolChain2])
+ def binary = factory.createNativeBinary(DefaultExecutableBinary, component, toolChain2, flavor1)
+
+ then:
+ binary.namingScheme.lifecycleTaskName == 'toolChain2Flavor1NameExecutable'
+ binary.namingScheme.outputDirectoryBase == 'nameExecutable/toolChain2Flavor1'
+ binary.namingScheme.getTaskName("link") == 'linkToolChain2Flavor1NameExecutable'
+ binary.namingScheme.getTaskName("compile", "cpp") == 'compileToolChain2Flavor1NameExecutableCpp'
+ }
+}
diff --git a/subprojects/cpp/src/test/groovy/org/gradle/nativecode/base/internal/SourceSetNotationParserTest.groovy b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/base/internal/SourceSetNotationParserTest.groovy
new file mode 100644
index 0000000..2b44302
--- /dev/null
+++ b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/base/internal/SourceSetNotationParserTest.groovy
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.internal
+import org.gradle.internal.reflect.DirectInstantiator
+import org.gradle.language.base.LanguageSourceSet
+import org.gradle.language.base.internal.DefaultFunctionalSourceSet
+import spock.lang.Specification
+
+class SourceSetNotationParserTest extends Specification {
+ def parser = SourceSetNotationParser.parser()
+ def languageSourceSet1 = languageSourceSet("lss1")
+ def languageSourceSet2 = languageSourceSet("lss2")
+
+ def "translates single LanguageSourceSet"() {
+ expect:
+ parser.parseNotation(languageSourceSet1) == [languageSourceSet1] as Set
+ }
+
+ def "collects all LanguageSourceSets for a FunctionalSourceSet"() {
+ when:
+ def functionalSourceSet = new DefaultFunctionalSourceSet("func", new DirectInstantiator())
+ functionalSourceSet.add(languageSourceSet1)
+ functionalSourceSet.add(languageSourceSet2)
+
+ then:
+ parser.parseNotation(functionalSourceSet) == [languageSourceSet1, languageSourceSet2] as Set
+ }
+
+ def "collects all LanguageSourceSets in a collection"() {
+ expect:
+ parser.parseNotation([languageSourceSet1, languageSourceSet2]) == [languageSourceSet1, languageSourceSet2] as Set
+ }
+
+ private LanguageSourceSet languageSourceSet(def name) {
+ Stub(LanguageSourceSet) {
+ getName() >> name
+ }
+ }
+}
diff --git a/subprojects/cpp/src/test/groovy/org/gradle/nativecode/base/plugins/NativeBinariesPluginTest.groovy b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/base/plugins/NativeBinariesPluginTest.groovy
new file mode 100644
index 0000000..15cb82b
--- /dev/null
+++ b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/base/plugins/NativeBinariesPluginTest.groovy
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.base.plugins
+import org.gradle.api.Task
+import org.gradle.api.plugins.BasePlugin
+import org.gradle.api.tasks.TaskDependency
+import org.gradle.internal.os.OperatingSystem
+import org.gradle.nativecode.base.ExecutableBinary
+import org.gradle.nativecode.toolchain.plugins.GppCompilerPlugin
+import org.gradle.util.TestUtil
+import spock.lang.Specification
+
+class NativeBinariesPluginTest extends Specification {
+ final def project = TestUtil.createRootProject()
+
+ def "creates domain objects and lifecycle task for executable"() {
+ given:
+ dsl {
+ apply plugin: NativeBinariesPlugin
+ apply plugin: GppCompilerPlugin
+
+ executables {
+ test {
+ }
+ }
+ }
+
+ expect:
+ def executable = project.executables.test
+
+ and:
+ ExecutableBinary executableBinary = project.binaries.testExecutable
+ executableBinary.component == executable
+ executableBinary.toolChain
+ executableBinary.outputFile == project.file("build/binaries/testExecutable/${executableBinary.toolChain.getExecutableName('test')}")
+
+ and:
+ executable.binaries.contains executableBinary
+
+ and:
+ with (oneTask(executableBinary.buildDependencies)) {
+ name == executableBinary.name
+ group == BasePlugin.BUILD_GROUP
+ }
+ }
+
+ def "creates domain objects and lifecycle tasks for library"() {
+ when:
+ dsl {
+ apply plugin: NativeBinariesPlugin
+ apply plugin: GppCompilerPlugin
+ libraries {
+ test {
+ }
+ }
+ }
+
+ then:
+ def sharedLibName = OperatingSystem.current().getSharedLibraryName("test")
+ def staticLibName = OperatingSystem.current().getStaticLibraryName("test")
+ def library = project.libraries.test
+
+ and:
+ def sharedLibraryBinary = project.binaries.testSharedLibrary
+ sharedLibraryBinary.toolChain
+ sharedLibraryBinary.outputFile == project.file("build/binaries/testSharedLibrary/$sharedLibName")
+ sharedLibraryBinary.component == project.libraries.test
+
+ and:
+ def staticLibraryBinary = project.binaries.testStaticLibrary
+ staticLibraryBinary.toolChain
+ staticLibraryBinary.outputFile == project.file("build/binaries/testStaticLibrary/$staticLibName")
+ staticLibraryBinary.component == project.libraries.test
+
+ and:
+ library.binaries.contains(sharedLibraryBinary)
+ library.binaries.contains(staticLibraryBinary)
+
+ and:
+ with (oneTask(sharedLibraryBinary.buildDependencies)) {
+ name == sharedLibraryBinary.name
+ group == BasePlugin.BUILD_GROUP
+ }
+ with (oneTask(staticLibraryBinary.buildDependencies)) {
+ name == staticLibraryBinary.name
+ group == BasePlugin.BUILD_GROUP
+ }
+ }
+
+ def dsl(Closure closure) {
+ closure.delegate = project
+ closure()
+ project.evaluate()
+ }
+
+ Task oneTask(TaskDependency dependencies) {
+ def tasks = dependencies.getDependencies(Stub(Task))
+ assert tasks.size() == 1
+ return tasks.asList()[0]
+ }
+}
diff --git a/subprojects/cpp/src/test/groovy/org/gradle/nativecode/cdt/model/CprojectSettingsSpec.groovy b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/cdt/model/CprojectSettingsSpec.groovy
new file mode 100644
index 0000000..7ff496a
--- /dev/null
+++ b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/cdt/model/CprojectSettingsSpec.groovy
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.cdt.model
+
+import spock.lang.*
+
+import org.gradle.api.Project
+import org.gradle.util.TestUtil
+
+// very loose test, but I'm not expecting it to stay around
+ at Ignore
+class CprojectSettingsSpec extends Specification {
+
+ Project project = TestUtil.createRootProject()
+
+ def descriptor = new CprojectDescriptor()
+ def settings = new CprojectSettings()
+
+ def "wire in includes"() {
+ given:
+ project.apply plugin: 'cpp-exe'
+ settings.binary = project.executables.main
+ descriptor.loadDefaults()
+
+ expect:
+ descriptor.getRootCppCompilerTools().each { compiler ->
+ def includePathsOption = descriptor.getOrCreateIncludePathsOption(compiler)
+ assert includePathsOption.listOptionValue.size() == 0
+ }
+
+ when:
+ settings.applyTo(descriptor)
+ def baos = new ByteArrayOutputStream()
+ descriptor.store(baos)
+ descriptor.load(new ByteArrayInputStream(baos.toByteArray()))
+
+ then:
+ descriptor.getRootCppCompilerTools().each { compiler ->
+ def includePathsOption = descriptor.getOrCreateIncludePathsOption(compiler)
+ assert includePathsOption.listOptionValue.size() == 1
+ }
+ }
+
+
+}
\ No newline at end of file
diff --git a/subprojects/cpp/src/test/groovy/org/gradle/nativecode/cdt/model/ProjectDescriptorSpec.groovy b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/cdt/model/ProjectDescriptorSpec.groovy
new file mode 100644
index 0000000..1976e6e
--- /dev/null
+++ b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/cdt/model/ProjectDescriptorSpec.groovy
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.cdt.model
+
+import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
+import org.junit.Rule
+import spock.lang.Specification
+
+class ProjectDescriptorSpec extends Specification {
+
+ @Rule public TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider()
+ ProjectDescriptor descriptor = new ProjectDescriptor()
+
+ def "method"() {
+ given:
+ descriptor.loadDefaults()
+
+ when:
+ new ProjectSettings(name: "test").applyTo(descriptor)
+
+ then:
+ def dict = xml.buildSpec[0].buildCommand[0].arguments[0].dictionary.key.find { it.text() == "org.eclipse.cdt.make.core.buildLocation" }.parent()
+ dict.value[0].text() == "\${workspace_loc:/test/Debug}"
+ }
+
+ def getString() {
+ def baos = new ByteArrayOutputStream()
+ descriptor.store(baos)
+ baos.toString()
+ }
+
+ def getXml() {
+ new XmlParser().parseText(getString())
+ }
+}
\ No newline at end of file
diff --git a/subprojects/cpp/src/test/groovy/org/gradle/nativecode/language/cpp/internal/DefaultCppSourceSetTest.groovy b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/language/cpp/internal/DefaultCppSourceSetTest.groovy
new file mode 100644
index 0000000..b76ae20
--- /dev/null
+++ b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/language/cpp/internal/DefaultCppSourceSetTest.groovy
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp.internal
+import org.gradle.language.base.FunctionalSourceSet
+import org.gradle.nativecode.base.Library
+import org.gradle.nativecode.base.LibraryBinary
+import org.gradle.nativecode.base.NativeDependencySet
+import org.gradle.util.TestUtil
+import spock.lang.Specification
+
+class DefaultCppSourceSetTest extends Specification {
+ def parent = Stub(FunctionalSourceSet) {
+ getName() >> "main"
+ }
+ def sourceSet = new DefaultCppSourceSet("cpp", parent, TestUtil.createRootProject())
+
+ def "has useful string representation"() {
+ expect:
+ sourceSet.toString() == "C++ source 'mainCpp'"
+ }
+
+ def "can add a library as a dependency of the source set"() {
+ def library = Mock(Library)
+
+ when:
+ sourceSet.lib(library)
+
+ then:
+ sourceSet.libs.contains(library)
+ }
+
+ def "can add a library binary as a dependency of the binary"() {
+ def library = Mock(LibraryBinary)
+
+ when:
+ sourceSet.lib(library)
+
+ then:
+ sourceSet.libs.contains(library)
+ }
+
+ def "can add a native dependency as a dependency of the binary"() {
+ def dependency = Stub(NativeDependencySet)
+
+ when:
+ sourceSet.lib(dependency)
+
+ then:
+ sourceSet.libs.contains(dependency)
+ }
+}
diff --git a/subprojects/cpp/src/test/groovy/org/gradle/nativecode/language/cpp/plugins/CppExeConventionPluginTest.groovy b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/language/cpp/plugins/CppExeConventionPluginTest.groovy
new file mode 100644
index 0000000..7a66bd6
--- /dev/null
+++ b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/language/cpp/plugins/CppExeConventionPluginTest.groovy
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp.plugins
+
+import org.gradle.util.TestUtil
+import spock.lang.Specification
+
+class CppExeConventionPluginTest extends Specification {
+ final def project = TestUtil.createRootProject()
+
+ def "adds and configures main executable"() {
+ given:
+ project.plugins.apply(CppExeConventionPlugin)
+
+ expect:
+ def executable = project.executables.main
+ def sourceSet = project.sources.main.cpp
+ executable.baseName == project.name
+ executable.source as List == [sourceSet]
+ }
+}
diff --git a/subprojects/cpp/src/test/groovy/org/gradle/nativecode/language/cpp/plugins/CppLibConventionPluginTest.groovy b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/language/cpp/plugins/CppLibConventionPluginTest.groovy
new file mode 100644
index 0000000..4a93b35
--- /dev/null
+++ b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/language/cpp/plugins/CppLibConventionPluginTest.groovy
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp.plugins
+
+import org.gradle.util.TestUtil
+import spock.lang.Specification
+
+class CppLibConventionPluginTest extends Specification {
+ final def project = TestUtil.createRootProject()
+
+ def "adds and configures main library"() {
+ given:
+ project.plugins.apply(CppLibConventionPlugin)
+
+ expect:
+ def library = project.libraries.main
+ def sourceSet = project.sources.main.cpp
+ library.baseName == project.name
+ library.source as List == [sourceSet]
+ }
+}
diff --git a/subprojects/cpp/src/test/groovy/org/gradle/nativecode/language/cpp/plugins/CppPluginTest.groovy b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/language/cpp/plugins/CppPluginTest.groovy
new file mode 100644
index 0000000..aa7201b
--- /dev/null
+++ b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/language/cpp/plugins/CppPluginTest.groovy
@@ -0,0 +1,235 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.language.cpp.plugins
+import org.gradle.api.NamedDomainObjectContainer
+import org.gradle.language.base.FunctionalSourceSet
+import org.gradle.nativecode.base.SharedLibraryBinary
+import org.gradle.nativecode.base.StaticLibraryBinary
+import org.gradle.nativecode.base.tasks.CreateStaticLibrary
+import org.gradle.nativecode.base.tasks.InstallExecutable
+import org.gradle.nativecode.base.tasks.LinkExecutable
+import org.gradle.nativecode.base.tasks.LinkSharedLibrary
+import org.gradle.nativecode.language.cpp.CppSourceSet
+import org.gradle.nativecode.language.cpp.tasks.CppCompile
+import org.gradle.util.Matchers
+import org.gradle.util.TestUtil
+import spock.lang.Specification
+
+class CppPluginTest extends Specification {
+ final def project = TestUtil.createRootProject()
+
+ def "extensions are available"() {
+ given:
+ dsl {
+ apply plugin: CppPlugin
+ }
+
+ expect:
+ project.executables instanceof NamedDomainObjectContainer
+ project.libraries instanceof NamedDomainObjectContainer
+ }
+
+ def "can create some cpp source sets"() {
+ given:
+ dsl {
+ apply plugin: CppPlugin
+ sources {
+ s1 {}
+ s2 {}
+ }
+ }
+
+ expect:
+ def sourceSets = project.sources
+ sourceSets.size() == 2
+ sourceSets*.name == ["s1", "s2"]
+ sourceSets.s1 instanceof FunctionalSourceSet
+ sourceSets.s1.cpp instanceof CppSourceSet
+ }
+
+ def "configure source sets"() {
+ given:
+ dsl {
+ apply plugin: CppPlugin
+ sources {
+ ss1 {
+ cpp {
+ source {
+ srcDirs "d1", "d2"
+ }
+ exportedHeaders {
+ srcDirs "h1", "h2"
+ }
+ }
+ }
+ ss2 {
+ cpp {
+ source {
+ srcDirs "d3"
+ }
+ exportedHeaders {
+ srcDirs "h3"
+ }
+ }
+ }
+ }
+ }
+
+ expect:
+ def sourceSets = project.sources
+ def ss1 = sourceSets.ss1.cpp
+ def ss2 = sourceSets.ss2.cpp
+
+ // cpp dir automatically added by convention
+ ss1.source.srcDirs*.name == ["cpp", "d1", "d2"]
+ ss2.source.srcDirs*.name == ["cpp", "d3"]
+
+ // headers dir automatically added by convention
+ ss1.exportedHeaders.srcDirs*.name == ["headers", "h1", "h2"]
+ ss2.exportedHeaders.srcDirs*.name == ["headers", "h3"]
+ }
+
+ def "creates tasks for each executable"() {
+ given:
+ dsl {
+ apply plugin: CppPlugin
+ sources {
+ main {}
+ }
+ executables {
+ test {
+ source sources.main.cpp
+
+ binaries.all {
+ define "NDEBUG"
+ compilerArgs "ARG1", "ARG2"
+ linkerArgs "LINK1", "LINK2"
+ }
+ }
+ }
+ }
+
+ expect:
+ def binary = project.binaries.testExecutable
+
+ def compile = project.tasks.compileTestExecutableMainCpp
+ compile instanceof CppCompile
+ compile.toolChain == binary.toolChain
+ compile.macros == ["NDEBUG"]
+ compile.compilerArgs == ["ARG1", "ARG2"]
+
+ and:
+ def link = project.tasks.linkTestExecutable
+ link instanceof LinkExecutable
+ link.toolChain == binary.toolChain
+ link.linkerArgs == ["LINK1", "LINK2"]
+ link.outputFile == project.binaries.testExecutable.outputFile
+ link Matchers.dependsOn("compileTestExecutableMainCpp")
+
+ and:
+ def lifecycle = project.tasks.testExecutable
+ lifecycle Matchers.dependsOn("linkTestExecutable")
+
+ and:
+ def install = project.tasks.installTestExecutable
+ install instanceof InstallExecutable
+ install.destinationDir == project.file('build/install/testExecutable')
+ install.executable == project.binaries.testExecutable.outputFile
+ install.libs.files.empty
+ install Matchers.dependsOn("testExecutable")
+
+ and:
+ project.binaries.testExecutable.buildDependencies.getDependencies(null) == [lifecycle] as Set
+ }
+
+ def "creates tasks for each library"() {
+ given:
+ dsl {
+ apply plugin: CppPlugin
+ sources {
+ main {}
+ }
+ libraries {
+ test {
+ source sources.main.cpp
+
+ binaries.all {
+ define "NDEBUG"
+ compilerArgs "ARG1", "ARG2"
+ }
+ binaries.withType(SharedLibraryBinary) {
+ linkerArgs "LINK1", "LINK2"
+ }
+ binaries.withType(StaticLibraryBinary) {
+ staticLibArgs "LIB1", "LIB2"
+ }
+ }
+ }
+ }
+
+ expect:
+ def sharedLib = project.binaries.testSharedLibrary
+ def staticLib = project.binaries.testStaticLibrary
+
+ def sharedCompile = project.tasks.compileTestSharedLibraryMainCpp
+ sharedCompile instanceof CppCompile
+ sharedCompile.toolChain == sharedLib.toolChain
+ sharedCompile.macros == ["NDEBUG"]
+ sharedCompile.compilerArgs == ["ARG1", "ARG2"]
+
+ and:
+ def link = project.tasks.linkTestSharedLibrary
+ link instanceof LinkSharedLibrary
+ link.toolChain == sharedLib.toolChain
+ link.linkerArgs == ["LINK1", "LINK2"]
+ link.outputFile == sharedLib.outputFile
+ link Matchers.dependsOn("compileTestSharedLibraryMainCpp")
+
+ and:
+ def sharedLibraryTask = project.tasks.testSharedLibrary
+ sharedLibraryTask Matchers.dependsOn("linkTestSharedLibrary")
+
+ and:
+ def staticCompile = project.tasks.compileTestStaticLibraryMainCpp
+ staticCompile instanceof CppCompile
+ staticCompile.toolChain == staticLib.toolChain
+ staticCompile.macros == ["NDEBUG"]
+ staticCompile.compilerArgs == ["ARG1", "ARG2"]
+
+ and:
+ def staticLink = project.tasks.createTestStaticLibrary
+ staticLink instanceof CreateStaticLibrary
+ staticLink.toolChain == staticLib.toolChain
+ staticLink.outputFile == staticLib.outputFile
+ staticLink.staticLibArgs == ["LIB1", "LIB2"]
+ staticLink Matchers.dependsOn("compileTestStaticLibraryMainCpp")
+
+ and:
+ def staticLibraryTask = project.tasks.testStaticLibrary
+ staticLibraryTask Matchers.dependsOn("createTestStaticLibrary")
+
+ and:
+ sharedLib.buildDependencies.getDependencies(null) == [sharedLibraryTask] as Set
+ staticLib.buildDependencies.getDependencies(null) == [staticLibraryTask] as Set
+ }
+
+ def dsl(Closure closure) {
+ closure.delegate = project
+ closure()
+ project.evaluate()
+ }
+}
diff --git a/subprojects/cpp/src/test/groovy/org/gradle/nativecode/toolchain/internal/gpp/GppToolChainTest.groovy b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/toolchain/internal/gpp/GppToolChainTest.groovy
new file mode 100644
index 0000000..600f828
--- /dev/null
+++ b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/toolchain/internal/gpp/GppToolChainTest.groovy
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.toolchain.internal.gpp
+import org.gradle.api.internal.file.FileResolver
+import org.gradle.internal.Factory
+import org.gradle.internal.os.OperatingSystem
+import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
+import org.junit.Rule
+import spock.lang.Specification
+
+class GppToolChainTest extends Specification {
+ @Rule final TestNameTestDirectoryProvider tmpDirProvider = new TestNameTestDirectoryProvider()
+ final FileResolver fileResolver = Mock(FileResolver)
+ final toolChain = new GppToolChain("gcc", OperatingSystem.current(), fileResolver, Stub(Factory))
+
+ def "uses shared library binary at link time"() {
+ expect:
+ toolChain.getSharedLibraryLinkFileName("test") == toolChain.getSharedLibraryName("test")
+ }
+
+ def "has default tool names"() {
+ expect:
+ toolChain.cppCompiler.exe == "g++"
+ toolChain.CCompiler.exe == "gcc"
+ toolChain.assembler.exe == "as"
+ toolChain.linker.exe == "g++"
+ toolChain.staticLibArchiver.exe == "ar"
+ }
+
+ def "can update tool names"() {
+ when:
+ toolChain.assembler.exe = "foo"
+
+ then:
+ toolChain.assembler.exe == "foo"
+ }
+
+ def "resolves path entries"() {
+ def testDir = tmpDirProvider.testDirectory
+
+ when:
+ toolChain.path "The Path"
+ toolChain.path "Path1", "Path2"
+
+ then:
+ fileResolver.resolve("The Path") >> testDir.file("one")
+ fileResolver.resolve("Path1") >> testDir.file("two")
+ fileResolver.resolve("Path2") >> testDir.file("three")
+
+ and:
+ toolChain.paths == [testDir.file("one"), testDir.file("two"), testDir.file("three")]
+ }
+}
diff --git a/subprojects/cpp/src/test/groovy/org/gradle/nativecode/toolchain/internal/gpp/version/GppVersionDeterminerTest.groovy b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/toolchain/internal/gpp/version/GppVersionDeterminerTest.groovy
new file mode 100644
index 0000000..b08fcd5
--- /dev/null
+++ b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/toolchain/internal/gpp/version/GppVersionDeterminerTest.groovy
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.toolchain.internal.gpp.version
+
+import org.gradle.api.Transformer
+import org.gradle.internal.Factory
+import org.gradle.process.internal.ExecHandleBuilder
+import spock.lang.Specification
+import spock.lang.Unroll
+import org.gradle.process.internal.ExecHandle
+import org.gradle.process.ExecResult
+
+class GppVersionDeterminerTest extends Specification {
+
+ @Unroll
+ "can scrape ok output"() {
+ expect:
+ version == output(output)
+
+ where:
+ [version, output] << OUTPUTS.collect { [it.value, it.key] }
+ }
+
+ def "null output (errored execution) ok"() {
+ expect:
+ output(null) == null
+ }
+
+ def "null scraped ok (can't parse output)"() {
+ expect:
+ scraped(null) == null
+ }
+
+ def "g++ -v execution error ok"() {
+ given:
+ def builder = Mock(ExecHandleBuilder)
+ def handle = Mock(ExecHandle)
+ def result = Mock(ExecResult)
+
+ and:
+ def determiner = new GppVersionDeterminer(producer(builder), new GppVersionDeterminer.GppVersionOutputScraper())
+ def binary = new File("g++")
+
+ when:
+ String version = determiner.transform(binary)
+
+ then:
+ 1 * builder.build() >> handle
+ 1 * handle.start() >> handle
+ 1 * handle.waitForFinish() >> result
+ 1 * result.getExitValue() >> 1
+
+ and:
+ version == null
+ }
+
+ def "happy day case"() {
+ given:
+ def builder = Mock(ExecHandleBuilder)
+ def handle = Mock(ExecHandle)
+ def result = Mock(ExecResult)
+ def output = """Reading specs from /opt/gcc/3.4.6/usr/local/bin/../lib/gcc/i686-pc-linux-gnu/3.4.6/specs
+Configured with: /home/ld/Downloads/gcc-3.4.6/configure
+Thread model: posix
+gcc version 3.4.6"""
+
+ and:
+ def determiner = new GppVersionDeterminer(producer(builder), new GppVersionDeterminer.GppVersionOutputScraper())
+ def binary = new File("g++")
+
+ when:
+ String version = determiner.transform(binary)
+
+ then:
+ 1 * builder.build() >> handle
+ 1 * builder.setErrorOutput(_) >> { OutputStream out -> out << output; builder }
+ 1 * handle.start() >> handle
+ 1 * handle.waitForFinish() >> result
+ 1 * result.getExitValue() >> 0
+
+ and:
+ version == "3.4.6"
+ }
+
+ Transformer<String, File> producer(ExecHandleBuilder builder) {
+ new GppVersionDeterminer.GppVersionOutputProducer(new Factory() {
+ def create() {
+ builder
+ }
+ })
+ }
+
+ String output(String output) {
+ new GppVersionDeterminer(transformer(output), new GppVersionDeterminer.GppVersionOutputScraper()).transform(new File("."))
+ }
+
+ String scraped(String scraped) {
+ new GppVersionDeterminer(transformer("doesntmatter"), transformer(scraped)).transform(new File("."))
+ }
+
+ Transformer transformer(constant) {
+ transformer { constant }
+ }
+
+ Transformer transformer(Closure closure) {
+ new Transformer() {
+ String transform(original) {
+ closure.call(original)
+ }
+ }
+ }
+
+ static final OUTPUTS = [
+ """Using built-in specs.
+Target: i686-apple-darwin11
+Configured with: /private/var/tmp/llvmgcc42/llvmgcc42-2336.1~22/src/configure
+Thread model: posix
+gcc version 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.1.00)""": "4.2.1",
+ """Reading specs from /opt/gcc/3.4.6/usr/local/bin/../lib/gcc/i686-pc-linux-gnu/3.4.6/specs
+Configured with: /home/ld/Downloads/gcc-3.4.6/configure
+Thread model: posix
+gcc version 3.4.6""": "3.4.6",
+ """Reading specs from /opt/gcc/3.4.6/usr/local/bin/../lib/gcc/i686-pc-linux-gnu/3.4.6/specs
+Configured with: /home/ld/Downloads/gcc-3.4.6/configure
+Thread model: posix
+gcc version 3.4.6-sometag""": "3.4.6-sometag"
+ ]
+}
diff --git a/subprojects/cpp/src/test/groovy/org/gradle/nativecode/toolchain/internal/msvcpp/VisualCppToolChainTest.groovy b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/toolchain/internal/msvcpp/VisualCppToolChainTest.groovy
new file mode 100644
index 0000000..4cdb6a4
--- /dev/null
+++ b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/toolchain/internal/msvcpp/VisualCppToolChainTest.groovy
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.toolchain.internal.msvcpp
+
+import org.gradle.api.internal.file.FileResolver
+import org.gradle.internal.Factory
+import org.gradle.internal.os.OperatingSystem
+import org.gradle.nativecode.base.internal.ToolChainAvailability
+import org.gradle.test.fixtures.file.TestDirectoryProvider
+import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
+import spock.lang.Specification
+
+class VisualCppToolChainTest extends Specification {
+ TestDirectoryProvider testDirectoryProvider = new TestNameTestDirectoryProvider()
+ final FileResolver fileResolver = Mock(FileResolver)
+ final toolChain = new VisualCppToolChain("visualCpp", new OperatingSystem.Windows(), fileResolver, Stub(Factory))
+
+
+ def "uses .lib file for shared library at link time"() {
+ expect:
+ toolChain.getSharedLibraryLinkFileName("test") == "test.lib"
+ toolChain.getSharedLibraryLinkFileName("test.dll") == "test.lib"
+ }
+
+ def "uses .dll file for shared library at runtime time"() {
+ expect:
+ toolChain.getSharedLibraryName("test") == "test.dll"
+ toolChain.getSharedLibraryName("test.dll") == "test.dll"
+ }
+
+ def "checks availability of required executables"() {
+ final os = Stub(OperatingSystem) {
+ isWindows() >> true
+ getExecutableName(_ as String) >> { String exeName -> exeName }
+ findInPath("cl.exe") >> file('cl.exe')
+ findInPath("link.exe") >> file('link.exe')
+ findInPath("lib.exe") >> file('lib.exe')
+ findInPath("ml.exe") >> file('ml.exe')
+ }
+
+ def cppToolChain = new VisualCppToolChain("test", os, fileResolver, Stub(Factory))
+
+ when:
+ def availability = new ToolChainAvailability()
+ cppToolChain.checkAvailable(availability)
+
+ then:
+ !availability.available
+ availability.unavailableMessage == "C++ compiler cannot be found"
+
+ when:
+ createFile('cl.exe')
+ createFile('link.exe')
+ createFile('ml.exe')
+
+ and:
+ def availability2 = new ToolChainAvailability()
+ cppToolChain.checkAvailable(availability2);
+
+ then:
+ !availability2.available
+ availability2.unavailableMessage == 'Static library archiver cannot be found'
+
+ when:
+ createFile('lib.exe')
+
+ and:
+ def availability3 = new ToolChainAvailability()
+ cppToolChain.checkAvailable(availability3);
+
+ then:
+ availability3.available
+ }
+
+ def "has default tool names"() {
+ expect:
+ toolChain.cppCompiler.exe == "cl.exe"
+ toolChain.CCompiler.exe == "cl.exe"
+ toolChain.assembler.exe == "ml.exe"
+ toolChain.linker.exe == "link.exe"
+ toolChain.staticLibArchiver.exe == "lib.exe"
+ }
+
+ def "can update tool names"() {
+ when:
+ toolChain.assembler.exe = "foo"
+
+ then:
+ toolChain.assembler.exe == "foo"
+ }
+
+ def "resolves path entries"() {
+ when:
+ toolChain.path "The Path"
+ toolChain.path "Path1", "Path2"
+
+ then:
+ fileResolver.resolve("The Path") >> file("one")
+ fileResolver.resolve("Path1") >> file("two")
+ fileResolver.resolve("Path2") >> file("three")
+
+ and:
+ toolChain.paths == [file("one"), file("two"), file("three")]
+ }
+
+ def file(String name) {
+ testDirectoryProvider.testDirectory.file(name)
+ }
+
+ def createFile(String name) {
+ file(name).createFile()
+ }
+}
diff --git a/subprojects/cpp/src/test/groovy/org/gradle/nativecode/toolchain/plugins/MicrosoftVisualCppPluginTest.groovy b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/toolchain/plugins/MicrosoftVisualCppPluginTest.groovy
new file mode 100644
index 0000000..928936b
--- /dev/null
+++ b/subprojects/cpp/src/test/groovy/org/gradle/nativecode/toolchain/plugins/MicrosoftVisualCppPluginTest.groovy
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.nativecode.toolchain.plugins
+import org.gradle.nativecode.toolchain.VisualCpp
+import org.gradle.util.Requires
+import org.gradle.util.TestPrecondition
+import org.gradle.util.TestUtil
+import spock.lang.Specification
+
+class MicrosoftVisualCppPluginTest extends Specification {
+ def project = TestUtil.createRootProject()
+
+ @Requires(TestPrecondition.NOT_WINDOWS)
+ def "no default tool chain when not windows"() {
+ when:
+ project.plugins.apply(MicrosoftVisualCppPlugin)
+
+ then:
+ project.toolChains.findByName("visualCpp") == null
+ }
+
+ @Requires(TestPrecondition.NOT_WINDOWS)
+ def "installs an unavailable tool chain when not windows"() {
+ when:
+ project.plugins.apply(MicrosoftVisualCppPlugin)
+
+ project.toolChains.create("vc", VisualCpp)
+
+ then:
+ def visualCpp = project.toolChains.vc
+ !visualCpp.availability.available
+ visualCpp.availability.unavailableMessage == 'Not available on this operating system.'
+ visualCpp.toString() == "ToolChain 'vc' (Visual C++)"
+ }
+
+ @Requires(TestPrecondition.WINDOWS)
+ def "installs an unavailable tool chain when on windows but Visual C++ not in path"() {
+ when:
+ project.plugins.apply(MicrosoftVisualCppPlugin)
+
+ project.toolChains.create("vc", VisualCpp)
+
+ then:
+ def visualCpp = project.toolChains.vc
+ !visualCpp.availability.available
+ visualCpp.availability.unavailableMessage == 'C++ compiler cannot be found'
+ visualCpp.toString() == "ToolChain 'vc' (Visual C++)"
+ }
+}
diff --git a/subprojects/cpp/src/test/groovy/org/gradle/plugins/binaries/model/internal/DefaultCompilerRegistryTest.groovy b/subprojects/cpp/src/test/groovy/org/gradle/plugins/binaries/model/internal/DefaultCompilerRegistryTest.groovy
deleted file mode 100644
index 16d0a45..0000000
--- a/subprojects/cpp/src/test/groovy/org/gradle/plugins/binaries/model/internal/DefaultCompilerRegistryTest.groovy
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.binaries.model.internal
-
-import org.gradle.internal.reflect.DirectInstantiator
-import org.gradle.api.internal.tasks.compile.Compiler
-import org.gradle.plugins.binaries.model.Binary
-import spock.lang.Specification
-
-class DefaultCompilerRegistryTest extends Specification {
- final BinaryCompileSpecFactory specFactory = Mock()
- final DefaultCompilerRegistry registry = new DefaultCompilerRegistry(new DirectInstantiator())
-
- def setup() {
- registry.specFactory = specFactory
- }
-
- def "search order defaults to the order that adapters are added"() {
- CompilerAdapter<BinaryCompileSpec> compiler1 = compiler("z")
- CompilerAdapter<BinaryCompileSpec> compiler2 = compiler("b")
- CompilerAdapter<BinaryCompileSpec> compiler3 = compiler("a")
-
- expect:
- registry.searchOrder == []
-
- when:
- registry.add(compiler2)
- registry.add(compiler1)
- registry.add(compiler3)
-
- then:
- registry.searchOrder == [compiler2, compiler1, compiler3]
-
- when:
- registry.remove(compiler1)
-
- then:
- registry.searchOrder == [compiler2, compiler3]
- }
-
- def "compilation searches adapters in the order added and uses the first available"() {
- Binary binary = Mock()
- BinaryCompileSpec compileSpec = Mock()
- CompilerAdapter<BinaryCompileSpec> compiler1 = compiler("z")
- CompilerAdapter<BinaryCompileSpec> compiler2 = compiler("b")
- CompilerAdapter<BinaryCompileSpec> compiler3 = compiler("a")
- Compiler<BinaryCompileSpec> compiler = Mock()
- Compiler<BinaryCompileSpec> lazyCompiler
-
- given:
- registry.add(compiler1)
- registry.add(compiler2)
- registry.add(compiler3)
-
- and:
- compiler2.available >> true
-
- when:
- registry.create(binary)
-
- then:
- 1 * specFactory.create(binary, !null) >> { lazyCompiler = it[1]; return compileSpec }
-
- when:
- lazyCompiler.execute(compileSpec)
-
- then:
- 1 * compiler2.createCompiler(binary) >> compiler
- 1 * compiler.execute(compileSpec)
- }
-
- def "compilation fails when no adapter is available"() {
- Binary binary = Mock()
- BinaryCompileSpec compileSpec = Mock()
- CompilerAdapter<BinaryCompileSpec> compiler1 = compiler("z")
- CompilerAdapter<BinaryCompileSpec> compiler2 = compiler("b")
- CompilerAdapter<BinaryCompileSpec> compiler3 = compiler("a")
- Compiler<BinaryCompileSpec> lazyCompiler
-
- given:
- registry.add(compiler1)
- registry.add(compiler2)
- registry.add(compiler3)
-
- when:
- registry.create(binary)
-
- then:
- 1 * specFactory.create(binary, !null) >> { lazyCompiler = it[1]; return compileSpec }
-
- when:
- lazyCompiler.execute(compileSpec)
-
- then:
- IllegalStateException e = thrown()
- e.message == "No compiler is available to compile $binary. Searched for $compiler1, $compiler2, $compiler3."
- }
-
- def "there is no default compiler when no adapters are available"() {
- CompilerAdapter<BinaryCompileSpec> compiler1 = compiler("c1")
- CompilerAdapter<BinaryCompileSpec> compiler2 = compiler("c2")
-
- given:
- registry.add(compiler1)
- registry.add(compiler2)
-
- expect:
- registry.defaultCompiler == null
- }
-
- def compiler(String name) {
- CompilerAdapter<BinaryCompileSpec> compiler = Mock()
- _ * compiler.name >> name
- return compiler
- }
-}
diff --git a/subprojects/cpp/src/test/groovy/org/gradle/plugins/cpp/CppExeConventionPluginTest.groovy b/subprojects/cpp/src/test/groovy/org/gradle/plugins/cpp/CppExeConventionPluginTest.groovy
deleted file mode 100644
index 9aee384..0000000
--- a/subprojects/cpp/src/test/groovy/org/gradle/plugins/cpp/CppExeConventionPluginTest.groovy
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp
-
-import org.gradle.util.HelperUtil
-import spock.lang.Specification
-
-class CppExeConventionPluginTest extends Specification {
- final def project = HelperUtil.createRootProject()
-
- def "adds and configures main executable"() {
- given:
- project.plugins.apply(CppExeConventionPlugin)
-
- expect:
- def executable = project.executables.main
- def sourceSet = project.cpp.sourceSets.main
- executable.spec.baseName == project.name
- executable.sourceSets as List == [sourceSet]
- }
-}
diff --git a/subprojects/cpp/src/test/groovy/org/gradle/plugins/cpp/CppLibConventionPluginTest.groovy b/subprojects/cpp/src/test/groovy/org/gradle/plugins/cpp/CppLibConventionPluginTest.groovy
deleted file mode 100644
index 76105de..0000000
--- a/subprojects/cpp/src/test/groovy/org/gradle/plugins/cpp/CppLibConventionPluginTest.groovy
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp
-
-import org.gradle.util.HelperUtil
-import spock.lang.Specification
-
-class CppLibConventionPluginTest extends Specification {
- final def project = HelperUtil.createRootProject()
-
- def "adds and configures main library"() {
- given:
- project.plugins.apply(CppLibConventionPlugin)
-
- expect:
- def library = project.libraries.main
- def sourceSet = project.cpp.sourceSets.main
- library.spec.baseName == project.name
- library.sourceSets as List == [sourceSet]
- }
-}
diff --git a/subprojects/cpp/src/test/groovy/org/gradle/plugins/cpp/CppPluginTest.groovy b/subprojects/cpp/src/test/groovy/org/gradle/plugins/cpp/CppPluginTest.groovy
deleted file mode 100644
index c2282e7..0000000
--- a/subprojects/cpp/src/test/groovy/org/gradle/plugins/cpp/CppPluginTest.groovy
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp
-
-import spock.lang.Specification
-import org.gradle.util.HelperUtil
-import org.gradle.plugins.cpp.gpp.GppCompileSpec
-import org.gradle.plugins.cpp.gpp.GppLibraryCompileSpec
-import org.gradle.util.Requires
-import org.gradle.util.TestPrecondition
-import org.gradle.api.NamedDomainObjectContainer
-import org.gradle.api.tasks.Sync
-import org.gradle.util.Matchers
-
-class CppPluginTest extends Specification {
- final def project = HelperUtil.createRootProject()
-
- def "extensions are available"() {
- given:
- project.plugins.apply(CppPlugin)
-
- expect:
- project.cpp instanceof CppExtension
- project.executables instanceof NamedDomainObjectContainer
- project.libraries instanceof NamedDomainObjectContainer
- }
-
- @Requires(TestPrecondition.WINDOWS)
- def "gcc and visual cpp adapters are available on windows"() {
- given:
- project.plugins.apply(CppPlugin)
-
- expect:
- project.compilers.collect { it.name } == ['gpp', 'visualCpp']
- project.compilers.searchOrder.collect { it.name } == ['visualCpp', 'gpp']
- }
-
- @Requires(TestPrecondition.UNIX)
- def "gcc adapter is available on unix"() {
- given:
- project.plugins.apply(CppPlugin)
-
- expect:
- project.compilers.collect { it.name } == ['gpp']
- project.compilers.searchOrder.collect { it.name } == ['gpp']
- }
-
- def "can create some cpp source sets"() {
- given:
- project.plugins.apply(CppPlugin)
-
- when:
- project.cpp {
- sourceSets {
- s1 {}
- s2 {}
- }
- }
-
- then:
- def sourceSets = project.cpp.sourceSets
- sourceSets.size() == 2
- sourceSets*.name == ["s1", "s2"]
- sourceSets.s1 instanceof CppSourceSet
- }
-
- def "configure source sets"() {
- given:
- project.plugins.apply(CppPlugin)
-
- when:
- project.cpp {
- sourceSets {
- ss1 {
- source {
- srcDirs "d1", "d2"
- }
- exportedHeaders {
- srcDirs "h1", "h2"
- }
- }
- ss2 {
- source {
- srcDirs "d3"
- }
- exportedHeaders {
- srcDirs "h3"
- }
- }
- }
- }
-
- then:
- def sourceSets = project.cpp.sourceSets
- def ss1 = sourceSets.ss1
- def ss2 = sourceSets.ss2
-
- // cpp dir automatically added by convention
- ss1.source.srcDirs*.name == ["cpp", "d1", "d2"]
- ss2.source.srcDirs*.name == ["cpp", "d3"]
-
- // headers dir automatically added by convention
- ss1.exportedHeaders.srcDirs*.name == ["headers", "h1", "h2"]
- ss2.exportedHeaders.srcDirs*.name == ["headers", "h3"]
- }
-
- @Requires(TestPrecondition.UNIX)
- def "creates domain objects for executable on unix"() {
- given:
- project.plugins.apply(CppPlugin)
-
- when:
- project.executables {
- test
- }
-
- then:
- def executable = project.executables.test
- executable.spec instanceof GppCompileSpec
- executable.spec.outputFile == project.file("build/binaries/test")
- }
-
- @Requires(TestPrecondition.WINDOWS)
- def "creates domain objects for executable on windows"() {
- given:
- project.plugins.apply(CppPlugin)
-
- when:
- project.executables {
- test
- }
-
- then:
- def executable = project.executables.test
- executable.spec instanceof GppCompileSpec
- executable.spec.outputFile == project.file("build/binaries/test.exe")
- }
-
- def "creates tasks for each executable"() {
- given:
- project.plugins.apply(CppPlugin)
-
- when:
- project.executables {
- test
- }
-
- then:
- def compile = project.tasks['compileTest']
- compile instanceof CppCompile
- compile.spec == project.executables.test.spec
-
- def install = project.tasks['installTest']
- install instanceof Sync
- install.destinationDir == project.file('build/install/test')
- install Matchers.dependsOn("compileTest")
- }
-
- @Requires(TestPrecondition.MAC_OS_X)
- def "creates domain objects for library on os x"() {
- given:
- project.plugins.apply(CppPlugin)
-
- when:
- project.libraries {
- test
- }
-
- then:
- def lib = project.libraries.test
- lib.spec instanceof GppLibraryCompileSpec
- lib.spec.outputFile == project.file("build/binaries/libtest.dylib")
- }
-
- @Requires(TestPrecondition.LINUX)
- def "creates domain objects for library on linux"() {
- given:
- project.plugins.apply(CppPlugin)
-
- when:
- project.libraries {
- test
- }
-
- then:
- def lib = project.libraries.test
- lib.spec instanceof GppLibraryCompileSpec
- lib.spec.outputFile == project.file("build/binaries/libtest.so")
- }
-
- @Requires(TestPrecondition.WINDOWS)
- def "creates domain objects for library on windows"() {
- given:
- project.plugins.apply(CppPlugin)
-
- when:
- project.libraries {
- test
- }
-
- then:
- def lib = project.libraries.test
- lib.spec instanceof GppLibraryCompileSpec
- lib.spec.outputFile == project.file("build/binaries/test.dll")
- }
-
- def "creates tasks for each library"() {
- given:
- project.plugins.apply(CppPlugin)
-
- when:
- project.libraries {
- test
- }
-
- then:
- def compile = project.tasks['compileTest']
- compile instanceof CppCompile
- compile.spec == project.libraries.test.spec
- }
-}
diff --git a/subprojects/cpp/src/test/groovy/org/gradle/plugins/cpp/cdt/model/CprojectSettingsSpec.groovy b/subprojects/cpp/src/test/groovy/org/gradle/plugins/cpp/cdt/model/CprojectSettingsSpec.groovy
deleted file mode 100644
index 3811190..0000000
--- a/subprojects/cpp/src/test/groovy/org/gradle/plugins/cpp/cdt/model/CprojectSettingsSpec.groovy
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp.cdt.model
-
-import spock.lang.*
-
-import org.gradle.api.Project
-import org.gradle.util.HelperUtil
-
-// very loose test, but I'm not expecting it to stay around
- at Ignore
-class CprojectSettingsSpec extends Specification {
-
- Project project = HelperUtil.createRootProject()
-
- def descriptor = new CprojectDescriptor()
- def settings = new CprojectSettings()
-
- def "wire in includes"() {
- given:
- project.apply plugin: 'cpp-exe'
- settings.binary = project.executables.main
- descriptor.loadDefaults()
-
- expect:
- descriptor.getRootCppCompilerTools().each { compiler ->
- def includePathsOption = descriptor.getOrCreateIncludePathsOption(compiler)
- assert includePathsOption.listOptionValue.size() == 0
- }
-
- when:
- settings.applyTo(descriptor)
- def baos = new ByteArrayOutputStream()
- descriptor.store(baos)
- descriptor.load(new ByteArrayInputStream(baos.toByteArray()))
-
- then:
- descriptor.getRootCppCompilerTools().each { compiler ->
- def includePathsOption = descriptor.getOrCreateIncludePathsOption(compiler)
- assert includePathsOption.listOptionValue.size() == 1
- }
- }
-
-
-}
\ No newline at end of file
diff --git a/subprojects/cpp/src/test/groovy/org/gradle/plugins/cpp/cdt/model/ProjectDescriptorSpec.groovy b/subprojects/cpp/src/test/groovy/org/gradle/plugins/cpp/cdt/model/ProjectDescriptorSpec.groovy
deleted file mode 100644
index 7341abc..0000000
--- a/subprojects/cpp/src/test/groovy/org/gradle/plugins/cpp/cdt/model/ProjectDescriptorSpec.groovy
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp.cdt.model
-
-import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
-import org.junit.Rule
-import spock.lang.Specification
-
-class ProjectDescriptorSpec extends Specification {
-
- @Rule public TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider()
- ProjectDescriptor descriptor = new ProjectDescriptor()
-
- def "method"() {
- given:
- descriptor.loadDefaults()
-
- when:
- new ProjectSettings(name: "test").applyTo(descriptor)
-
- then:
- def dict = xml.buildSpec[0].buildCommand[0].arguments[0].dictionary.key.find { it.text() == "org.eclipse.cdt.make.core.buildLocation" }.parent()
- dict.value[0].text() == "\${workspace_loc:/test/Debug}"
- }
-
- def getString() {
- def baos = new ByteArrayOutputStream()
- descriptor.store(baos)
- baos.toString()
- }
-
- def getXml() {
- new XmlParser().parseText(getString())
- }
-}
\ No newline at end of file
diff --git a/subprojects/cpp/src/test/groovy/org/gradle/plugins/cpp/gpp/GppCompileSpecTest.groovy b/subprojects/cpp/src/test/groovy/org/gradle/plugins/cpp/gpp/GppCompileSpecTest.groovy
deleted file mode 100644
index 1ed649c..0000000
--- a/subprojects/cpp/src/test/groovy/org/gradle/plugins/cpp/gpp/GppCompileSpecTest.groovy
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp.gpp
-
-import org.gradle.api.internal.project.ProjectInternal
-import org.gradle.api.internal.tasks.compile.Compiler
-import org.gradle.plugins.binaries.model.internal.DefaultBinary
-import org.gradle.util.HelperUtil
-import spock.lang.Specification
-import org.gradle.plugins.binaries.model.internal.CompileSpecFactory
-import org.gradle.plugins.cpp.CppCompile
-
-class GppCompileSpecTest extends Specification {
- final ProjectInternal project = HelperUtil.createRootProject()
-
- def "is built by the compile task"() {
- given:
- def binary = new DefaultBinary("binary", project, Mock(CompileSpecFactory))
- def spec = new GppCompileSpec(binary, Mock(Compiler), project)
- def compileTask = project.tasks.add("compile", CppCompile)
- spec.configure(compileTask)
-
- expect:
- spec.buildDependencies.getDependencies(null) == [compileTask] as Set
- }
-}
diff --git a/subprojects/cpp/src/test/groovy/org/gradle/plugins/cpp/gpp/GppLibraryCompileSpecTest.groovy b/subprojects/cpp/src/test/groovy/org/gradle/plugins/cpp/gpp/GppLibraryCompileSpecTest.groovy
deleted file mode 100644
index 4c31e63..0000000
--- a/subprojects/cpp/src/test/groovy/org/gradle/plugins/cpp/gpp/GppLibraryCompileSpecTest.groovy
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp.gpp
-
-import org.gradle.api.internal.project.ProjectInternal
-import org.gradle.api.internal.tasks.compile.Compiler
-import org.gradle.plugins.binaries.model.internal.CompileSpecFactory
-import org.gradle.plugins.binaries.model.internal.DefaultLibrary
-import org.gradle.util.HelperUtil
-import spock.lang.Specification
-
-class GppLibraryCompileSpecTest extends Specification {
- final ProjectInternal project = HelperUtil.createRootProject()
-
- def "has default installPath"() {
- given:
- def library = new DefaultLibrary("binary", project, Mock(CompileSpecFactory))
- def spec = new GppLibraryCompileSpec(library, Mock(Compiler), project)
-
- expect:
- spec.installName == spec.outputFileName
- }
-}
diff --git a/subprojects/cpp/src/test/groovy/org/gradle/plugins/cpp/gpp/internal/version/GppVersionDeterminerTest.groovy b/subprojects/cpp/src/test/groovy/org/gradle/plugins/cpp/gpp/internal/version/GppVersionDeterminerTest.groovy
deleted file mode 100644
index 028c8b1..0000000
--- a/subprojects/cpp/src/test/groovy/org/gradle/plugins/cpp/gpp/internal/version/GppVersionDeterminerTest.groovy
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.plugins.cpp.gpp.internal.version
-
-import org.gradle.api.Transformer
-import org.gradle.internal.Factory
-import org.gradle.process.internal.ExecHandleBuilder
-import spock.lang.Specification
-import spock.lang.Unroll
-import org.gradle.process.internal.ExecHandle
-import org.gradle.process.ExecResult
-
-class GppVersionDeterminerTest extends Specification {
-
- @Unroll
- "can scrape ok output"() {
- expect:
- version == output(output)
-
- where:
- [version, output] << OUTPUTS.collect { [it.value, it.key] }
- }
-
- def "null output (errored execution) ok"() {
- expect:
- output(null) == null
- }
-
- def "null scraped ok (can't parse output)"() {
- expect:
- scraped(null) == null
- }
-
- def "g++ -v execution error ok"() {
- given:
- def builder = Mock(ExecHandleBuilder)
- def handle = Mock(ExecHandle)
- def result = Mock(ExecResult)
-
- and:
- def determiner = new GppVersionDeterminer(producer(builder), new GppVersionDeterminer.GppVersionOutputScraper())
- def binary = new File("g++")
-
- when:
- String version = determiner.transform(binary)
-
- then:
- 1 * builder.build() >> handle
- 1 * handle.start() >> handle
- 1 * handle.waitForFinish() >> result
- 1 * result.getExitValue() >> 1
-
- and:
- version == null
- }
-
- def "happy day case"() {
- given:
- def builder = Mock(ExecHandleBuilder)
- def handle = Mock(ExecHandle)
- def result = Mock(ExecResult)
- def output = """Reading specs from /opt/gcc/3.4.6/usr/local/bin/../lib/gcc/i686-pc-linux-gnu/3.4.6/specs
-Configured with: /home/ld/Downloads/gcc-3.4.6/configure
-Thread model: posix
-gcc version 3.4.6"""
-
- and:
- def determiner = new GppVersionDeterminer(producer(builder), new GppVersionDeterminer.GppVersionOutputScraper())
- def binary = new File("g++")
-
- when:
- String version = determiner.transform(binary)
-
- then:
- 1 * builder.build() >> handle
- 1 * builder.setErrorOutput(_) >> { OutputStream out -> out << output; builder }
- 1 * handle.start() >> handle
- 1 * handle.waitForFinish() >> result
- 1 * result.getExitValue() >> 0
-
- and:
- version == "3.4.6"
- }
-
- Transformer<String, File> producer(ExecHandleBuilder builder) {
- new GppVersionDeterminer.GppVersionOutputProducer(new Factory() {
- def create() {
- builder
- }
- })
- }
-
- String output(String output) {
- new GppVersionDeterminer(transformer(output), new GppVersionDeterminer.GppVersionOutputScraper()).transform(new File("."))
- }
-
- String scraped(String scraped) {
- new GppVersionDeterminer(transformer("doesntmatter"), transformer(scraped)).transform(new File("."))
- }
-
- Transformer transformer(constant) {
- transformer { constant }
- }
-
- Transformer transformer(Closure closure) {
- new Transformer() {
- String transform(original) {
- closure.call(original)
- }
- }
- }
-
- static final OUTPUTS = [
- """Using built-in specs.
-Target: i686-apple-darwin11
-Configured with: /private/var/tmp/llvmgcc42/llvmgcc42-2336.1~22/src/configure
-Thread model: posix
-gcc version 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.1.00)""": "4.2.1",
- """Reading specs from /opt/gcc/3.4.6/usr/local/bin/../lib/gcc/i686-pc-linux-gnu/3.4.6/specs
-Configured with: /home/ld/Downloads/gcc-3.4.6/configure
-Thread model: posix
-gcc version 3.4.6""": "3.4.6",
- """Reading specs from /opt/gcc/3.4.6/usr/local/bin/../lib/gcc/i686-pc-linux-gnu/3.4.6/specs
-Configured with: /home/ld/Downloads/gcc-3.4.6/configure
-Thread model: posix
-gcc version 3.4.6-sometag""": "3.4.6-sometag"
- ]
-}
diff --git a/subprojects/diagnostics/diagnostics.gradle b/subprojects/diagnostics/diagnostics.gradle
index cbbf7b1..ec07001 100644
--- a/subprojects/diagnostics/diagnostics.gradle
+++ b/subprojects/diagnostics/diagnostics.gradle
@@ -15,7 +15,7 @@
*/
dependencies {
- groovy libraries.groovy
+ compile libraries.groovy
compile project(':core')
compile project(':plugins')
compile project(':coreImpl')
diff --git a/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportTaskIntegrationTest.groovy b/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportTaskIntegrationTest.groovy
index dee91ad..f82ee53 100644
--- a/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportTaskIntegrationTest.groovy
+++ b/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportTaskIntegrationTest.groovy
@@ -17,6 +17,7 @@
package org.gradle.api.tasks.diagnostics
import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+import spock.lang.Ignore
import static org.gradle.util.TextUtil.toPlatformLineSeparators
@@ -259,6 +260,94 @@ org:leaf:2.0 -> 1.0
"""))
}
+ def "shows substituted modules"() {
+ given:
+ mavenRepo.module("org", "new-leaf", 77).publish()
+
+ mavenRepo.module("org", "foo", 1.0).dependsOn('org', 'leaf', '1.0').publish()
+ mavenRepo.module("org", "bar", 1.0).dependsOn('org', 'leaf', '2.0').publish()
+
+ file("build.gradle") << """
+ repositories {
+ maven { url "${mavenRepo.uri}" }
+ }
+ configurations {
+ conf {
+ resolutionStrategy.eachDependency { if (it.requested.name == 'leaf') { it.useTarget('org:new-leaf:77') } }
+ }
+ }
+ dependencies {
+ conf 'org:foo:1.0', 'org:bar:1.0'
+ }
+ task insight(type: DependencyInsightReportTask) {
+ configuration = configurations.conf
+ setDependencySpec { it.requested.name == 'leaf' }
+ }
+ """
+
+ when:
+ run "insight"
+
+ then:
+ output.contains(toPlatformLineSeparators("""
+org:new-leaf:77 (selected by rule)
+
+org:leaf:1.0 -> org:new-leaf:77
+\\--- org:foo:1.0
+ \\--- conf
+
+org:leaf:2.0 -> org:new-leaf:77
+\\--- org:bar:1.0
+ \\--- conf
+"""))
+ }
+
+ def "shows version resolved from dynamic selectors"() {
+ given:
+ mavenRepo.module("org", "leaf", "1.6").publish()
+ mavenRepo.module("org", "top", "1.0")
+ .dependsOn("org", "leaf", "[1.5,1.9]")
+ .dependsOn("org", "leaf", "latest.integration")
+ .dependsOn("org", "leaf", "1.+")
+ .publish()
+
+ file("build.gradle") << """
+ repositories {
+ maven { url "${mavenRepo.uri}" }
+ }
+ configurations {
+ conf
+ }
+ dependencies {
+ conf 'org:top:1.0'
+ }
+ task insight(type: DependencyInsightReportTask) {
+ setDependencySpec { it.requested.name == 'leaf' }
+ configuration = configurations.conf
+ }
+ """
+
+ when:
+ run "insight"
+
+ then:
+ output.contains(toPlatformLineSeparators("""
+org:leaf:1.6
+
+org:leaf:1.+ -> 1.6
+\\--- org:top:1.0
+ \\--- conf
+
+org:leaf:[1.5,1.9] -> 1.6
+\\--- org:top:1.0
+ \\--- conf
+
+org:leaf:latest.integration -> 1.6
+\\--- org:top:1.0
+ \\--- conf
+"""))
+ }
+
def "forced version matches the conflict resolution"() {
given:
mavenRepo.module("org", "leaf", 1.0).publish()
@@ -587,9 +676,55 @@ org:middle:1.0 -> 2.0+ FAILED
"""))
}
+ @Ignore
+ def "shows version resolved from a range where some selectors did not match anything"() {
+ given:
+ mavenRepo.module("org", "leaf", "1.5").publish()
+ mavenRepo.module("org", "top", "1.0")
+ .dependsOn("org", "leaf", "1.0")
+ .dependsOn("org", "leaf", "[1.5,1.9]")
+ .dependsOn("org", "leaf", "0.8+")
+ .publish()
+
+ file("build.gradle") << """
+ repositories {
+ maven { url "${mavenRepo.uri}" }
+ }
+ configurations {
+ conf
+ }
+ dependencies {
+ conf 'org:top:1.0'
+ }
+ task insight(type: DependencyInsightReportTask) {
+ setDependencySpec { it.requested.name == 'leaf' }
+ configuration = configurations.conf
+ }
+ """
+
+ when:
+ run "insight"
+
+ then:
+ output.contains(toPlatformLineSeparators("""
+org:leaf:1.5 (conflict resolution)
+
+org:leaf:1.0 -> 1.5
+\\--- org:top:1.0
+ \\--- conf
+
+org:leaf:0.8+ -> 1.5
+\\--- org:top:1.0
+ \\--- conf
+
+org:leaf:[1.5,1.9] -> 1.5
+\\--- org:top:1.0
+ \\--- conf
+"""))
+ }
+
def "shows multiple failed outgoing dependencies"() {
given:
- mavenRepo.module("org", "leaf", "1.0").publish()
mavenRepo.module("org", "top", "1.0")
.dependsOn("org", "leaf", "1.0")
.dependsOn("org", "leaf", "[1.5,2.0]")
@@ -616,18 +751,15 @@ org:middle:1.0 -> 2.0+ FAILED
run "insight"
then:
- // TODO - need to use a fixed ordering for dynamic requested versions
output.contains(toPlatformLineSeparators("""
-org:leaf:1.0
+org:leaf:1.0 FAILED
\\--- org:top:1.0
\\--- conf
-"""))
- output.contains(toPlatformLineSeparators("""
+
org:leaf:1.6+ FAILED
\\--- org:top:1.0
\\--- conf
-"""))
- output.contains(toPlatformLineSeparators("""
+
org:leaf:[1.5,2.0] FAILED
\\--- org:top:1.0
\\--- conf
diff --git a/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyReportTaskIntegrationTest.groovy b/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyReportTaskIntegrationTest.groovy
index 94ecc8e..39d377e 100644
--- a/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyReportTaskIntegrationTest.groovy
+++ b/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyReportTaskIntegrationTest.groovy
@@ -278,7 +278,7 @@ rootProject.name = 'root'
run ":dependencies"
then:
- output.contains 'compile - Classpath for compiling the main sources.'
+ output.contains "compile - Compile classpath for source set 'main'."
output.contains(toPlatformLineSeparators("""
+--- root:a:1.0
@@ -411,13 +411,13 @@ rootProject.name = 'root'
def "renders ivy tree with custom configurations"() {
given:
def module = ivyRepo.module("org", "child")
- module.configurations['first'] = [extendsFrom: ['second'], transitive: true]
- module.configurations['second'] = [extendsFrom: [], transitive: true]
+ module.configuration('first', extendsFrom: ['second'])
+ module.configuration('second')
module.publish()
module = ivyRepo.module("org", "parent").dependsOn('child')
- module.configurations['first'] = [extendsFrom: ['second'], transitive: true]
- module.configurations['second'] = [extendsFrom: [], transitive: true]
+ module.configuration('first', extendsFrom: ['second'])
+ module.configuration('second')
module.publish()
file("build.gradle") << """
diff --git a/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/ResolutionResultApiIntegrationTest.groovy b/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/ResolutionResultApiIntegrationTest.groovy
deleted file mode 100644
index 1aaf46d..0000000
--- a/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/ResolutionResultApiIntegrationTest.groovy
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.tasks.diagnostics
-
-import org.gradle.integtests.fixtures.AbstractIntegrationSpec
-
-import static org.gradle.util.TextUtil.toPlatformLineSeparators
-
-class ResolutionResultApiIntegrationTest extends AbstractIntegrationSpec {
-
- def setup() {
- executer.requireOwnGradleUserHomeDir()
- }
-
- /*
- The ResolutionResult API is also covered by the dependency report integration tests.
- */
-
- def "selection reasons are described"() {
- given:
- mavenRepo.module("org", "leaf", 1.0).publish()
- mavenRepo.module("org", "leaf", 2.0).publish()
- mavenRepo.module("org", "foo", 0.5).publish()
-
- mavenRepo.module("org", "foo", 1.0).dependsOn('org', 'leaf', '1.0').publish()
- mavenRepo.module("org", "bar", 1.0).dependsOn('org', 'leaf', '2.0').publish()
- mavenRepo.module("org", "baz", 1.0).dependsOn('org', 'foo', '1.0').publish()
-
- file("settings.gradle") << "rootProject.name = 'cool-project'"
-
- file("build.gradle") << """
- version = '5.0'
- repositories {
- maven { url "${mavenRepo.uri}" }
- }
- configurations {
- conf
- }
- configurations.conf.resolutionStrategy.force 'org:leaf:2.0'
- dependencies {
- conf 'org:foo:0.5', 'org:bar:1.0', 'org:baz:1.0'
- }
- task resolutionResult << {
- def result = configurations.conf.incoming.resolutionResult
- result.allModuleVersions {
- println it.id.name + ":" + it.id.version + " " + it.selectionReason.description
- }
- }
- """
-
- when:
- run "resolutionResult"
-
- then:
- output.contains(toPlatformLineSeparators("""
-cool-project:5.0 root
-foo:1.0 conflict resolution
-leaf:2.0 forced
-bar:1.0 requested
-baz:1.0 requested
-"""))
- }
-}
diff --git a/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/TaskReportTaskIntegrationTest.groovy b/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/TaskReportTaskIntegrationTest.groovy
index b262c65..4d5acba 100644
--- a/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/TaskReportTaskIntegrationTest.groovy
+++ b/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/TaskReportTaskIntegrationTest.groovy
@@ -48,7 +48,7 @@ class TaskReportTaskIntegrationTest extends AbstractIntegrationSpec {
def name = it - "autoCreate"
name = name[0].toLowerCase() + name[1..-1]
if (tasks.findByName(name)) {
- project.tasks.add(it)
+ project.tasks.create(it)
}
}
}
diff --git a/subprojects/diagnostics/src/main/groovy/org/gradle/api/plugins/HelpTasksPlugin.groovy b/subprojects/diagnostics/src/main/groovy/org/gradle/api/plugins/HelpTasksPlugin.groovy
index 1ef988e..c7e5587 100644
--- a/subprojects/diagnostics/src/main/groovy/org/gradle/api/plugins/HelpTasksPlugin.groovy
+++ b/subprojects/diagnostics/src/main/groovy/org/gradle/api/plugins/HelpTasksPlugin.groovy
@@ -19,39 +19,40 @@ package org.gradle.api.plugins
import org.gradle.api.Incubating
import org.gradle.api.Plugin
import org.gradle.api.internal.project.ProjectInternal
-import org.gradle.configuration.Help
import org.gradle.api.tasks.diagnostics.*
+import org.gradle.configuration.Help
import static org.gradle.configuration.ImplicitTasksConfigurer.*
-/**
- * by Szczepan Faber, created at: 9/5/12
- */
@Incubating
class HelpTasksPlugin implements Plugin<ProjectInternal> {
void apply(ProjectInternal project) {
- project.implicitTasks.add(name: HELP_TASK, type: Help) {
+ project.implicitTasks.create(name: HELP_TASK, type: Help) {
description = "Displays a help message"
group = HELP_GROUP
}
- project.implicitTasks.add(name: PROJECTS_TASK, type: ProjectReportTask) {
+ project.implicitTasks.create(name: PROJECTS_TASK, type: ProjectReportTask) {
description = "Displays the sub-projects of $project."
group = HELP_GROUP
}
- project.implicitTasks.add(name: TASKS_TASK, type: TaskReportTask) {
- description = "Displays the tasks runnable from $project (some of the displayed tasks may belong to subprojects)."
+ project.implicitTasks.create(name: TASKS_TASK, type: TaskReportTask) {
+ if (project.subprojects.empty) {
+ description = "Displays the tasks runnable from $project."
+ } else {
+ description = "Displays the tasks runnable from $project (some of the displayed tasks may belong to subprojects)."
+ }
group = HELP_GROUP
}
- project.implicitTasks.add(name: PROPERTIES_TASK, type: PropertyReportTask) {
+ project.implicitTasks.create(name: PROPERTIES_TASK, type: PropertyReportTask) {
description = "Displays the properties of $project."
group = HELP_GROUP
}
- project.implicitTasks.add(name: DEPENDENCY_INSIGHT_TASK, type: DependencyInsightReportTask) { task ->
+ project.implicitTasks.create(name: DEPENDENCY_INSIGHT_TASK, type: DependencyInsightReportTask) { task ->
description = "Displays the insight into a specific dependency in $project."
group = HELP_GROUP
project.plugins.withType(JavaPlugin) {
@@ -59,7 +60,7 @@ class HelpTasksPlugin implements Plugin<ProjectInternal> {
}
}
- project.implicitTasks.add(name: DEPENDENCIES_TASK, type: DependencyReportTask) {
+ project.implicitTasks.create(name: DEPENDENCIES_TASK, type: DependencyReportTask) {
description = "Displays all dependencies declared in $project."
group = HELP_GROUP
}
diff --git a/subprojects/diagnostics/src/main/groovy/org/gradle/api/plugins/ProjectReportsPlugin.java b/subprojects/diagnostics/src/main/groovy/org/gradle/api/plugins/ProjectReportsPlugin.java
index 245f237..a6d0a38 100644
--- a/subprojects/diagnostics/src/main/groovy/org/gradle/api/plugins/ProjectReportsPlugin.java
+++ b/subprojects/diagnostics/src/main/groovy/org/gradle/api/plugins/ProjectReportsPlugin.java
@@ -39,7 +39,7 @@ public class ProjectReportsPlugin implements Plugin<Project> {
final ProjectReportsPluginConvention convention = new ProjectReportsPluginConvention(project);
project.getConvention().getPlugins().put("projectReports", convention);
- TaskReportTask taskReportTask = project.getTasks().add(TASK_REPORT, TaskReportTask.class);
+ TaskReportTask taskReportTask = project.getTasks().create(TASK_REPORT, TaskReportTask.class);
taskReportTask.setDescription("Generates a report about your tasks.");
taskReportTask.conventionMapping("outputFile", new Callable<Object>() {
public Object call() throws Exception {
@@ -52,7 +52,7 @@ public class ProjectReportsPlugin implements Plugin<Project> {
}
});
- PropertyReportTask propertyReportTask = project.getTasks().add(PROPERTY_REPORT, PropertyReportTask.class);
+ PropertyReportTask propertyReportTask = project.getTasks().create(PROPERTY_REPORT, PropertyReportTask.class);
propertyReportTask.setDescription("Generates a report about your properties.");
propertyReportTask.conventionMapping("outputFile", new Callable<Object>() {
public Object call() throws Exception {
@@ -65,7 +65,7 @@ public class ProjectReportsPlugin implements Plugin<Project> {
}
});
- DependencyReportTask dependencyReportTask = project.getTasks().add(DEPENDENCY_REPORT,
+ DependencyReportTask dependencyReportTask = project.getTasks().create(DEPENDENCY_REPORT,
DependencyReportTask.class);
dependencyReportTask.setDescription("Generates a report about your library dependencies.");
dependencyReportTask.conventionMapping("outputFile", new Callable<Object>() {
@@ -79,7 +79,7 @@ public class ProjectReportsPlugin implements Plugin<Project> {
}
});
- Task projectReportTask = project.getTasks().add(PROJECT_REPORT);
+ Task projectReportTask = project.getTasks().create(PROJECT_REPORT);
projectReportTask.dependsOn(TASK_REPORT, PROPERTY_REPORT, DEPENDENCY_REPORT);
projectReportTask.setDescription("Generates a report about your project.");
projectReportTask.setGroup("reporting");
diff --git a/subprojects/diagnostics/src/main/groovy/org/gradle/api/plugins/internal/HelpTasksAutoApplyAction.java b/subprojects/diagnostics/src/main/groovy/org/gradle/api/plugins/internal/HelpTasksAutoApplyAction.java
new file mode 100644
index 0000000..8852340
--- /dev/null
+++ b/subprojects/diagnostics/src/main/groovy/org/gradle/api/plugins/internal/HelpTasksAutoApplyAction.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.plugins.internal;
+
+import org.gradle.api.internal.project.ProjectInternal;
+import org.gradle.configuration.project.ProjectConfigureAction;
+
+//This one should go away once we complete the auto-apply plugins
+public class HelpTasksAutoApplyAction implements ProjectConfigureAction {
+ public void execute(ProjectInternal project) {
+ project.getPlugins().apply("help-tasks");
+ }
+}
diff --git a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/AbstractReportTask.java b/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/AbstractReportTask.java
index 82b1751..9f4926b 100644
--- a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/AbstractReportTask.java
+++ b/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/AbstractReportTask.java
@@ -44,7 +44,7 @@ public abstract class AbstractReportTask extends ConventionTask {
protected AbstractReportTask() {
getOutputs().upToDateWhen(new Spec<Task>() {
public boolean isSatisfiedBy(Task element) {
- return getOutputFile() != null;
+ return false;
}
});
projects = new HashSet<Project>();
diff --git a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportTask.groovy b/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportTask.groovy
index 30657fa..bae4e34 100644
--- a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportTask.groovy
+++ b/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportTask.groovy
@@ -27,7 +27,7 @@ import org.gradle.api.artifacts.result.ResolutionResult
import org.gradle.api.internal.tasks.CommandLineOption
import org.gradle.api.specs.Spec
import org.gradle.api.tasks.TaskAction
-import org.gradle.api.tasks.diagnostics.internal.GraphRenderer
+import org.gradle.internal.graph.GraphRenderer
import org.gradle.api.tasks.diagnostics.internal.dsl.DependencyResultSpecNotationParser
import org.gradle.api.tasks.diagnostics.internal.graph.DependencyGraphRenderer
import org.gradle.api.tasks.diagnostics.internal.graph.NodeRenderer
diff --git a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/DependencyReportTask.java b/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/DependencyReportTask.java
index 2a03f4c..30c2807 100644
--- a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/DependencyReportTask.java
+++ b/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/DependencyReportTask.java
@@ -28,8 +28,6 @@ import java.util.*;
/**
* Displays the dependency tree for a project. An instance of this type is used when you
* execute the {@code dependencies} task from the command-line.
- *
- * @author Phil Messenger
*/
public class DependencyReportTask extends AbstractReportTask {
diff --git a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/ProjectReportTask.java b/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/ProjectReportTask.java
index d4a1dbd..52b5784 100644
--- a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/ProjectReportTask.java
+++ b/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/ProjectReportTask.java
@@ -18,7 +18,7 @@ package org.gradle.api.tasks.diagnostics;
import org.apache.commons.lang.StringUtils;
import org.gradle.api.Action;
import org.gradle.api.Project;
-import org.gradle.api.tasks.diagnostics.internal.GraphRenderer;
+import org.gradle.internal.graph.GraphRenderer;
import org.gradle.api.tasks.diagnostics.internal.TextReportRenderer;
import org.gradle.configuration.ImplicitTasksConfigurer;
import org.gradle.initialization.BuildClientMetaData;
diff --git a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/DependencyReportRenderer.java b/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/DependencyReportRenderer.java
index d26be81..9a7e945 100644
--- a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/DependencyReportRenderer.java
+++ b/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/DependencyReportRenderer.java
@@ -21,8 +21,6 @@ import java.io.IOException;
/**
* Renders the model of a project dependency report.
- *
- * @author Phil Messenger
*/
public interface DependencyReportRenderer extends ReportRenderer {
/**
diff --git a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/GraphRenderer.java b/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/GraphRenderer.java
deleted file mode 100644
index 03eef17..0000000
--- a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/GraphRenderer.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.tasks.diagnostics.internal;
-
-import org.gradle.api.Action;
-import org.gradle.logging.StyledTextOutput;
-
-import static org.gradle.logging.StyledTextOutput.Style.Info;
-
-public class GraphRenderer {
- private final StyledTextOutput output;
- private StringBuilder prefix = new StringBuilder();
- private boolean seenRootChildren;
- private boolean lastChild = true;
-
- public GraphRenderer(StyledTextOutput output) {
- this.output = output;
- }
-
- /**
- * Visits a node in the graph.
- */
- public void visit(Action<? super StyledTextOutput> node, boolean lastChild) {
- if (seenRootChildren) {
- output.withStyle(Info).text(prefix + (lastChild ? "\\--- " : "+--- "));
- }
- this.lastChild = lastChild;
- node.execute(output);
- output.println();
- }
-
- /**
- * Starts visiting the children of the most recently visited node.
- */
- public void startChildren() {
- if (seenRootChildren) {
- prefix.append(lastChild ? " " : "| ");
- }
- seenRootChildren = true;
- }
-
- /**
- * Completes visiting the children of the node which most recently started visiting children.
- */
- public void completeChildren() {
- if (prefix.length() == 0) {
- seenRootChildren = false;
- } else {
- prefix.setLength(prefix.length() - 5);
- }
- }
-
- public StyledTextOutput getOutput() {
- return output;
- }
-}
diff --git a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/SingleProjectTaskReportModel.java b/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/SingleProjectTaskReportModel.java
index 5bc8491..24e045c 100644
--- a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/SingleProjectTaskReportModel.java
+++ b/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/SingleProjectTaskReportModel.java
@@ -18,8 +18,8 @@ package org.gradle.api.tasks.diagnostics.internal;
import com.google.common.collect.SetMultimap;
import com.google.common.collect.TreeMultimap;
import org.gradle.api.Task;
-import org.gradle.api.internal.DirectedGraph;
-import org.gradle.api.internal.GraphAggregator;
+import org.gradle.internal.graph.DirectedGraph;
+import org.gradle.internal.graph.GraphAggregator;
import org.gradle.util.GUtil;
import org.gradle.util.Path;
@@ -49,7 +49,7 @@ public class SingleProjectTaskReportModel implements TaskReportModel {
}
}
GraphAggregator<Task> aggregator = new GraphAggregator<Task>(new DirectedGraph<Task, Object>() {
- public void getNodeValues(Task node, Collection<Object> values, Collection<Task> connectedNodes) {
+ public void getNodeValues(Task node, Collection<? super Object> values, Collection<? super Task> connectedNodes) {
for (Task dep : node.getTaskDependencies().getDependencies(node)) {
if (containsTaskWithPath(tasks, dep.getPath())) {
connectedNodes.add(dep);
diff --git a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/TaskReportRenderer.java b/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/TaskReportRenderer.java
index 7d560d1..19257ac 100644
--- a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/TaskReportRenderer.java
+++ b/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/TaskReportRenderer.java
@@ -32,8 +32,6 @@ import static org.gradle.logging.StyledTextOutput.Style.*;
/**
* <p>A {@code TaskReportRenderer} is responsible for rendering the model of a project task report.</p>
- *
- * @author Hans Dockter
*/
public class TaskReportRenderer extends TextReportRenderer {
private boolean currentProjectHasTasks;
diff --git a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/dependencies/AsciiDependencyReportRenderer.java b/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/dependencies/AsciiDependencyReportRenderer.java
index 11a44e9..e18db8e 100644
--- a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/dependencies/AsciiDependencyReportRenderer.java
+++ b/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/dependencies/AsciiDependencyReportRenderer.java
@@ -20,13 +20,13 @@ import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.result.ResolutionResult;
import org.gradle.api.tasks.diagnostics.internal.DependencyReportRenderer;
-import org.gradle.api.tasks.diagnostics.internal.GraphRenderer;
import org.gradle.api.tasks.diagnostics.internal.TextReportRenderer;
import org.gradle.api.tasks.diagnostics.internal.graph.DependencyGraphRenderer;
import org.gradle.api.tasks.diagnostics.internal.graph.NodeRenderer;
import org.gradle.api.tasks.diagnostics.internal.graph.SimpleNodeRenderer;
import org.gradle.api.tasks.diagnostics.internal.graph.nodes.RenderableDependency;
import org.gradle.api.tasks.diagnostics.internal.graph.nodes.RenderableModuleResult;
+import org.gradle.internal.graph.GraphRenderer;
import org.gradle.logging.StyledTextOutput;
import org.gradle.util.GUtil;
@@ -36,8 +36,6 @@ import static org.gradle.logging.StyledTextOutput.Style.*;
/**
* Simple dependency graph renderer that emits an ASCII tree.
- *
- * @author Phil Messenger
*/
public class AsciiDependencyReportRenderer extends TextReportRenderer implements DependencyReportRenderer {
private boolean hasConfigs;
diff --git a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/dsl/DependencyResultSpec.java b/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/dsl/DependencyResultSpec.java
index 5bcdf10..4a380c7 100644
--- a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/dsl/DependencyResultSpec.java
+++ b/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/dsl/DependencyResultSpec.java
@@ -21,9 +21,6 @@ import org.gradle.api.artifacts.result.DependencyResult;
import org.gradle.api.artifacts.result.ResolvedDependencyResult;
import org.gradle.api.specs.Spec;
-/**
-* by Szczepan Faber, created at: 11/6/12
-*/
class DependencyResultSpec implements Spec<DependencyResult> {
private final String stringNotation;
diff --git a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/dsl/DependencyResultSpecNotationParser.java b/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/dsl/DependencyResultSpecNotationParser.java
index 1b8f16b..b4c151c 100644
--- a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/dsl/DependencyResultSpecNotationParser.java
+++ b/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/dsl/DependencyResultSpecNotationParser.java
@@ -26,9 +26,6 @@ import org.gradle.api.specs.Spec;
import java.util.Collection;
-/**
- * by Szczepan Faber, created at: 10/9/12
- */
public class DependencyResultSpecNotationParser implements NotationParser<Spec<DependencyResult>> {
public Spec<DependencyResult> parseNotation(final Object notation) throws UnsupportedNotationException {
diff --git a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/graph/DependencyGraphRenderer.groovy b/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/graph/DependencyGraphRenderer.groovy
index caf2438..33e016e 100644
--- a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/graph/DependencyGraphRenderer.groovy
+++ b/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/graph/DependencyGraphRenderer.groovy
@@ -18,15 +18,12 @@ package org.gradle.api.tasks.diagnostics.internal.graph
import org.gradle.api.Action
import org.gradle.api.artifacts.ModuleVersionIdentifier
-import org.gradle.api.tasks.diagnostics.internal.GraphRenderer
import org.gradle.api.tasks.diagnostics.internal.graph.nodes.RenderableDependency
+import org.gradle.internal.graph.GraphRenderer
import org.gradle.logging.StyledTextOutput
import static org.gradle.logging.StyledTextOutput.Style.Info
-/**
- * by Szczepan Faber, created at: 9/20/12
- */
class DependencyGraphRenderer {
private final GraphRenderer renderer
private final NodeRenderer nodeRenderer
diff --git a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/graph/NodeRenderer.groovy b/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/graph/NodeRenderer.groovy
index eb4ddc1..ed21b83 100644
--- a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/graph/NodeRenderer.groovy
+++ b/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/graph/NodeRenderer.groovy
@@ -19,9 +19,6 @@ package org.gradle.api.tasks.diagnostics.internal.graph
import org.gradle.api.tasks.diagnostics.internal.graph.nodes.RenderableDependency
import org.gradle.logging.StyledTextOutput
-/**
- * by Szczepan Faber, created at: 9/20/12
- */
interface NodeRenderer {
void renderNode(StyledTextOutput output, RenderableDependency node, boolean alreadyRendered);
}
diff --git a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/graph/SimpleNodeRenderer.java b/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/graph/SimpleNodeRenderer.java
index 2e8b5b3..08f1222 100644
--- a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/graph/SimpleNodeRenderer.java
+++ b/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/graph/SimpleNodeRenderer.java
@@ -22,9 +22,6 @@ import org.gradle.logging.StyledTextOutput;
import static org.gradle.logging.StyledTextOutput.Style.Failure;
import static org.gradle.logging.StyledTextOutput.Style.Info;
-/**
- * by Szczepan Faber, created at: 9/21/12
- */
public class SimpleNodeRenderer implements NodeRenderer {
public void renderNode(StyledTextOutput output, RenderableDependency node, boolean alreadyRendered) {
output.text(node.getName());
diff --git a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/graph/nodes/AbstractRenderableModuleResult.java b/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/graph/nodes/AbstractRenderableModuleResult.java
index 95a3606..f037fe4 100644
--- a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/graph/nodes/AbstractRenderableModuleResult.java
+++ b/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/graph/nodes/AbstractRenderableModuleResult.java
@@ -21,9 +21,6 @@ import org.gradle.api.artifacts.result.ResolvedModuleVersionResult;
import java.util.Set;
-/**
- * by Szczepan Faber, created at: 8/10/12
- */
public abstract class AbstractRenderableModuleResult implements RenderableDependency {
protected final ResolvedModuleVersionResult module;
diff --git a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/graph/nodes/InvertedRenderableModuleResult.java b/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/graph/nodes/InvertedRenderableModuleResult.java
index 4f3bc33..06a7789 100644
--- a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/graph/nodes/InvertedRenderableModuleResult.java
+++ b/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/graph/nodes/InvertedRenderableModuleResult.java
@@ -27,8 +27,6 @@ import java.util.Set;
/**
* Children of this renderable dependency node are its dependents.
- *
- * by Szczepan Faber, created at: 8/10/12
*/
public class InvertedRenderableModuleResult extends RenderableModuleResult {
diff --git a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/graph/nodes/RenderableDependency.java b/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/graph/nodes/RenderableDependency.java
index d5695b4..71ec43c 100644
--- a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/graph/nodes/RenderableDependency.java
+++ b/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/graph/nodes/RenderableDependency.java
@@ -20,9 +20,6 @@ import org.gradle.api.artifacts.ModuleVersionIdentifier;
import java.util.Set;
-/**
-* by Szczepan Faber, created at: 7/27/12
-*/
public interface RenderableDependency {
ModuleVersionIdentifier getId();
String getName();
diff --git a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/graph/nodes/RenderableDependencyResult.java b/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/graph/nodes/RenderableDependencyResult.java
index e5f697a..aacc293 100644
--- a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/graph/nodes/RenderableDependencyResult.java
+++ b/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/graph/nodes/RenderableDependencyResult.java
@@ -25,9 +25,6 @@ import org.gradle.api.artifacts.result.UnresolvedDependencyResult;
import java.util.LinkedHashSet;
import java.util.Set;
-/**
- * by Szczepan Faber, created at: 7/27/12
- */
public class RenderableDependencyResult extends AbstractRenderableDependencyResult {
private final ResolvedDependencyResult dependency;
diff --git a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/graph/nodes/RenderableModuleResult.java b/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/graph/nodes/RenderableModuleResult.java
index 20c2a4b..9d30e93 100644
--- a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/graph/nodes/RenderableModuleResult.java
+++ b/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/graph/nodes/RenderableModuleResult.java
@@ -24,9 +24,6 @@ import org.gradle.api.artifacts.result.UnresolvedDependencyResult;
import java.util.LinkedHashSet;
import java.util.Set;
-/**
- * by Szczepan Faber, created at: 8/10/12
- */
public class RenderableModuleResult extends AbstractRenderableModuleResult {
public RenderableModuleResult(ResolvedModuleVersionResult module) {
diff --git a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/insight/DependencyInsightReporter.groovy b/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/insight/DependencyInsightReporter.groovy
index f9258de..0f83eca 100644
--- a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/insight/DependencyInsightReporter.groovy
+++ b/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/insight/DependencyInsightReporter.groovy
@@ -25,8 +25,6 @@ import org.gradle.api.tasks.diagnostics.internal.graph.nodes.*
/**
* Created: 23/08/2012
- *
- * @author Szczepan Faber
*/
public class DependencyInsightReporter {
diff --git a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/insight/DependencyResultSorter.java b/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/insight/DependencyResultSorter.java
index ba99512..7b90e25 100644
--- a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/insight/DependencyResultSorter.java
+++ b/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/insight/DependencyResultSorter.java
@@ -18,15 +18,14 @@ package org.gradle.api.tasks.diagnostics.internal.insight;
import org.gradle.api.artifacts.ModuleVersionIdentifier;
import org.gradle.api.artifacts.ModuleVersionSelector;
-import org.gradle.api.internal.artifacts.version.LatestVersionSemanticComparator;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.ResolverStrategy;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.VersionMatcher;
import org.gradle.api.tasks.diagnostics.internal.graph.nodes.DependencyEdge;
import java.util.*;
/**
* Created: 17/08/2012
- *
- * @author Szczepan Faber
*/
public class DependencyResultSorter {
@@ -43,7 +42,7 @@ public class DependencyResultSorter {
private static class DependencyComparator implements Comparator<DependencyEdge> {
- private final LatestVersionSemanticComparator versionComparator = new LatestVersionSemanticComparator();
+ private final VersionMatcher matcher = ResolverStrategy.INSTANCE.getVersionMatcher();
public int compare(DependencyEdge left, DependencyEdge right) {
ModuleVersionSelector leftRequested = left.getRequested();
@@ -67,7 +66,23 @@ public class DependencyResultSorter {
return 1;
}
- int byVersion = versionComparator.compare(leftRequested.getVersion(), rightRequested.getVersion());
+ //order dynamic selectors after static selectors
+ boolean leftDynamic = matcher.isDynamic(leftRequested.getVersion());
+ boolean rightDynamic = matcher.isDynamic(rightRequested.getVersion());
+ if (leftDynamic && !rightDynamic) {
+ return 1;
+ } else if (!leftDynamic && rightDynamic) {
+ return -1;
+ }
+
+ int byVersion;
+ if (leftDynamic && rightDynamic) {
+ // order dynamic selectors lexicographically
+ byVersion = leftRequested.getVersion().compareTo(rightRequested.getVersion());
+ } else {
+ // order static selectors semantically
+ byVersion = matcher.compare(leftRequested.getVersion(), rightRequested.getVersion());
+ }
if (byVersion != 0) {
return byVersion;
}
@@ -84,7 +99,7 @@ public class DependencyResultSorter {
return byModule;
}
- return versionComparator.compare(leftFrom.getVersion(), rightFrom.getVersion());
+ return matcher.compare(leftFrom.getVersion(), rightFrom.getVersion());
}
}
}
diff --git a/subprojects/diagnostics/src/main/resources/META-INF/services/org.gradle.configuration.project.ProjectConfigureAction b/subprojects/diagnostics/src/main/resources/META-INF/services/org.gradle.configuration.project.ProjectConfigureAction
new file mode 100644
index 0000000..9d15f53
--- /dev/null
+++ b/subprojects/diagnostics/src/main/resources/META-INF/services/org.gradle.configuration.project.ProjectConfigureAction
@@ -0,0 +1 @@
+org.gradle.api.plugins.internal.HelpTasksAutoApplyAction
\ No newline at end of file
diff --git a/subprojects/diagnostics/src/test/groovy/org/gradle/api/plugins/HelpTasksPluginSpec.groovy b/subprojects/diagnostics/src/test/groovy/org/gradle/api/plugins/HelpTasksPluginSpec.groovy
index cdfccf8..203acf4 100644
--- a/subprojects/diagnostics/src/test/groovy/org/gradle/api/plugins/HelpTasksPluginSpec.groovy
+++ b/subprojects/diagnostics/src/test/groovy/org/gradle/api/plugins/HelpTasksPluginSpec.groovy
@@ -16,19 +16,15 @@
package org.gradle.api.plugins
+import org.gradle.api.tasks.diagnostics.*
import org.gradle.configuration.Help
-import org.gradle.testfixtures.ProjectBuilder
+import org.gradle.util.TestUtil
import spock.lang.Specification
-import org.gradle.api.tasks.diagnostics.*
import static org.gradle.configuration.ImplicitTasksConfigurer.*
-/**
- * by Szczepan Faber, created at: 9/5/12
- */
class HelpTasksPluginSpec extends Specification {
-
- def project = new ProjectBuilder().build()
+ final project = TestUtil.createRootProject()
def "adds help tasks"() {
when:
@@ -43,6 +39,19 @@ class HelpTasksPluginSpec extends Specification {
hasHelpTask(PROPERTIES_TASK, PropertyReportTask)
}
+ def "tasks description reflects whether project has sub-projects or not"() {
+ given:
+ def child = TestUtil.createChildProject(project, "child")
+
+ when:
+ project.apply(plugin: 'help-tasks')
+ child.apply(plugin: 'help-tasks')
+
+ then:
+ project.implicitTasks[TASKS_TASK].description == "Displays the tasks runnable from root project 'test' (some of the displayed tasks may belong to subprojects)."
+ child.implicitTasks[TASKS_TASK].description == "Displays the tasks runnable from project ':child'."
+ }
+
def "configures tasks for java plugin"() {
when:
project.apply(plugin: 'help-tasks')
@@ -57,12 +66,13 @@ class HelpTasksPluginSpec extends Specification {
project.implicitTasks[DEPENDENCY_INSIGHT_TASK].configuration == project.configurations.compile
}
- private void hasHelpTask(String name, Class type) {
+ private hasHelpTask(String name, Class type) {
def task = project.implicitTasks.getByName(name)
assert type.isInstance(task)
assert task.group == HELP_GROUP
if (type != Help.class) {
assert task.description.contains(project.name)
}
+ return task
}
}
diff --git a/subprojects/diagnostics/src/test/groovy/org/gradle/api/plugins/ProjectReportsPluginTest.java b/subprojects/diagnostics/src/test/groovy/org/gradle/api/plugins/ProjectReportsPluginTest.java
index c7ad6f0..ca0c3d0 100644
--- a/subprojects/diagnostics/src/test/groovy/org/gradle/api/plugins/ProjectReportsPluginTest.java
+++ b/subprojects/diagnostics/src/test/groovy/org/gradle/api/plugins/ProjectReportsPluginTest.java
@@ -20,7 +20,7 @@ import org.gradle.api.Task;
import org.gradle.api.tasks.diagnostics.DependencyReportTask;
import org.gradle.api.tasks.diagnostics.PropertyReportTask;
import org.gradle.api.tasks.diagnostics.TaskReportTask;
-import org.gradle.util.HelperUtil;
+import org.gradle.util.TestUtil;
import org.gradle.util.WrapUtil;
import org.junit.Test;
@@ -32,7 +32,7 @@ import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
public class ProjectReportsPluginTest {
- private final Project project = HelperUtil.createRootProject();
+ private final Project project = TestUtil.createRootProject();
private final ProjectReportsPlugin plugin = new ProjectReportsPlugin();
@Test
diff --git a/subprojects/diagnostics/src/test/groovy/org/gradle/api/plugins/ReportingBasePluginConventionTest.groovy b/subprojects/diagnostics/src/test/groovy/org/gradle/api/plugins/ReportingBasePluginConventionTest.groovy
deleted file mode 100644
index 5748ae7..0000000
--- a/subprojects/diagnostics/src/test/groovy/org/gradle/api/plugins/ReportingBasePluginConventionTest.groovy
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.plugins
-
-import org.gradle.api.Project
-import org.gradle.api.reporting.ReportingExtension
-import org.gradle.testfixtures.ProjectBuilder
-import spock.lang.Specification
-
-// Note: ReportingBasePluginConvention has been deprecated
-public class ReportingBasePluginConventionTest extends Specification {
-
- Project project = ProjectBuilder.builder().build()
- ReportingExtension extension = new ReportingExtension(project)
- ReportingBasePluginConvention convention = new ReportingBasePluginConvention(project, extension)
-
- def "defaults to reports dir in build dir"() {
- expect:
- convention.reportsDirName == ReportingExtension.DEFAULT_REPORTS_DIR_NAME
- convention.reportsDir == new File(project.buildDir, ReportingExtension.DEFAULT_REPORTS_DIR_NAME)
- }
-
- def "can set reports dir by name, relative to build dir"() {
- when:
- convention.reportsDirName = "something-else"
-
- then:
- convention.reportsDir == new File(project.buildDir, "something-else")
-
- when:
- project.buildDir = new File(project.buildDir, "new-build-dir")
-
- then:
- convention.reportsDir == new File(project.buildDir, "something-else")
- }
-
- def "calculates api doc title from project name and version"() {
- expect:
- project.version == Project.DEFAULT_VERSION
-
- and:
- convention.apiDocTitle == "$project.name API"
-
- when:
- project.version = "1.0"
-
- then:
- convention.apiDocTitle == "$project.name 1.0 API"
- }
-
-}
diff --git a/subprojects/diagnostics/src/test/groovy/org/gradle/api/plugins/ReportingBasePluginTest.groovy b/subprojects/diagnostics/src/test/groovy/org/gradle/api/plugins/ReportingBasePluginTest.groovy
deleted file mode 100644
index 1e3ccde..0000000
--- a/subprojects/diagnostics/src/test/groovy/org/gradle/api/plugins/ReportingBasePluginTest.groovy
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.plugins
-
-import org.gradle.api.Project
-import org.gradle.api.reporting.ReportingExtension
-import org.gradle.util.HelperUtil
-import spock.lang.Specification
-
-public class ReportingBasePluginTest extends Specification {
-
- Project project = HelperUtil.createRootProject();
-
- def setup() {
- project.plugins.apply(ReportingBasePlugin)
- }
-
- def addsTasksAndConventionToProject() {
- expect:
- project.convention.plugins.get("reportingBase") instanceof ReportingBasePluginConvention
- }
-
- def "adds reporting extension"() {
- expect:
- project.reporting instanceof ReportingExtension
-
- project.configure(project) {
- reporting {
- baseDir "somewhere"
- }
- }
- }
-}
diff --git a/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/AbstractReportTaskTest.java b/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/AbstractReportTaskTest.java
index 179fd4d..91f3013 100644
--- a/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/AbstractReportTaskTest.java
+++ b/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/AbstractReportTaskTest.java
@@ -20,7 +20,7 @@ import org.gradle.api.internal.project.DefaultProject;
import org.gradle.api.tasks.diagnostics.internal.ReportRenderer;
import org.gradle.logging.StyledTextOutput;
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider;
-import org.gradle.util.HelperUtil;
+import org.gradle.util.TestUtil;
import org.gradle.util.WrapUtil;
import org.jmock.Expectations;
import org.jmock.Sequence;
@@ -34,8 +34,8 @@ import org.junit.runner.RunWith;
import java.io.File;
import java.io.IOException;
-import static org.gradle.util.HelperUtil.createChildProject;
-import static org.gradle.util.HelperUtil.createRootProject;
+import static org.gradle.util.TestUtil.createChildProject;
+import static org.gradle.util.TestUtil.createRootProject;
import static org.hamcrest.Matchers.notNullValue;
@RunWith(JMock.class)
@@ -52,7 +52,7 @@ public class AbstractReportTaskTest {
public void setUp() throws Exception {
generator = context.mock(Runnable.class);
renderer = context.mock(ReportRenderer.class);
- task = HelperUtil.createTask(TestReportTask.class, project);
+ task = TestUtil.createTask(TestReportTask.class, project);
task.setGenerator(generator);
task.setRenderer(renderer);
task.setProjects(WrapUtil.<Project>toSet(project));
diff --git a/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportTaskSpec.groovy b/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportTaskSpec.groovy
index 86499a9..98bfbe6 100644
--- a/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportTaskSpec.groovy
+++ b/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportTaskSpec.groovy
@@ -18,16 +18,13 @@ package org.gradle.api.tasks.diagnostics
import org.gradle.api.InvalidUserDataException
import org.gradle.api.specs.Spec
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 9/20/12
- */
class DependencyInsightReportTaskSpec extends Specification {
- def project = HelperUtil.createRootProject()
- def task = HelperUtil.createTask(DependencyInsightReportTask, project)
+ def project = TestUtil.createRootProject()
+ def task = TestUtil.createTask(DependencyInsightReportTask, project)
def "fails if configuration missing"() {
when:
@@ -38,7 +35,7 @@ class DependencyInsightReportTaskSpec extends Specification {
}
def "fails if dependency to include missing"() {
- def conf = project.configurations.add("foo")
+ def conf = project.configurations.create("foo")
task.configuration = conf
when:
@@ -58,7 +55,7 @@ class DependencyInsightReportTaskSpec extends Specification {
def "can set spec and configuration directly"() {
when:
- def conf = project.configurations.add("foo")
+ def conf = project.configurations.create("foo")
task.configuration = conf
task.dependencySpec = { true } as Spec
then:
@@ -68,7 +65,7 @@ class DependencyInsightReportTaskSpec extends Specification {
def "can set spec and configuration via methods"() {
when:
- project.configurations.add("foo")
+ project.configurations.create("foo")
task.setConfiguration 'foo'
task.setDependencySpec 'bar'
then:
diff --git a/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/DependencyReportTaskTest.groovy b/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/DependencyReportTaskTest.groovy
index a17431a..20a26cb 100644
--- a/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/DependencyReportTaskTest.groovy
+++ b/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/DependencyReportTaskTest.groovy
@@ -20,23 +20,22 @@ import org.gradle.api.artifacts.Configuration
import org.gradle.api.tasks.diagnostics.internal.DependencyReportRenderer
import org.gradle.api.tasks.diagnostics.internal.dependencies.AsciiDependencyReportRenderer
import org.gradle.testfixtures.ProjectBuilder
-import org.gradle.util.HelperUtil
-
+import org.gradle.util.TestUtil
import spock.lang.Specification
class DependencyReportTaskTest extends Specification {
private Project project = new ProjectBuilder().build()
- private DependencyReportTask task = HelperUtil.createTask(DependencyReportTask.class, project)
+ private DependencyReportTask task = TestUtil.createTask(DependencyReportTask.class, project)
private DependencyReportRenderer renderer = Mock(DependencyReportRenderer)
- private Configuration conf1 = project.configurations.add("conf1")
- private Configuration conf2 = project.configurations.add("conf2")
+ private Configuration conf1 = project.configurations.create("conf1")
+ private Configuration conf2 = project.configurations.create("conf2")
void setup() {
task.renderer = renderer
}
def "task is configured correctly"() {
- task = HelperUtil.createTask(DependencyReportTask.class);
+ task = TestUtil.createTask(DependencyReportTask.class);
expect:
task.renderer instanceof AsciiDependencyReportRenderer
@@ -61,8 +60,8 @@ class DependencyReportTaskTest extends Specification {
def "rendering can be limited to specific configurations"() {
given:
- project.configurations.add("a")
- def bConf = project.configurations.add("b")
+ project.configurations.create("a")
+ def bConf = project.configurations.create("b")
task.configurations = [bConf] as Set
when:
@@ -77,8 +76,8 @@ class DependencyReportTaskTest extends Specification {
def "rendering can be limited to a single configuration, specified by name"() {
given:
- project.configurations.add("a")
- def bConf = project.configurations.add("b")
+ project.configurations.create("a")
+ def bConf = project.configurations.create("b")
when:
task.configuration = "b"
diff --git a/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/ProjectReportTaskTest.groovy b/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/ProjectReportTaskTest.groovy
index bb3d948..4993eb5 100644
--- a/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/ProjectReportTaskTest.groovy
+++ b/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/ProjectReportTaskTest.groovy
@@ -18,12 +18,12 @@ package org.gradle.api.tasks.diagnostics
import org.gradle.api.Project
import org.gradle.api.internal.project.ProjectInternal
import org.gradle.logging.TestStyledTextOutput
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import spock.lang.Specification
class ProjectReportTaskTest extends Specification {
- final ProjectInternal project = HelperUtil.createRootProject()
- final ProjectReportTask task = HelperUtil.createTask(ProjectReportTask, project)
+ final ProjectInternal project = TestUtil.createRootProject()
+ final ProjectReportTask task = TestUtil.createTask(ProjectReportTask, project)
final TestStyledTextOutput output = new TestStyledTextOutput().ignoreStyle()
def setup() {
@@ -32,10 +32,10 @@ class ProjectReportTaskTest extends Specification {
def rendersReportForRootProjectWithChildren() {
project.description = 'this is the root project'
- Project child1 = HelperUtil.createChildProject(project, "child1")
+ Project child1 = TestUtil.createChildProject(project, "child1")
child1.description = 'this is a subproject'
- HelperUtil.createChildProject(child1, "child1")
- HelperUtil.createChildProject(project, "child2")
+ TestUtil.createChildProject(child1, "child1")
+ TestUtil.createChildProject(project, "child2")
when:
task.generate(project)
@@ -67,7 +67,7 @@ For example, try running gradle :tasks
}
def rendersReportForNonRootProjectWithNoChildren() {
- Project child1 = HelperUtil.createChildProject(project, "child1")
+ Project child1 = TestUtil.createChildProject(project, "child1")
when:
task.generate(child1)
diff --git a/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/PropertyReportTaskTest.java b/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/PropertyReportTaskTest.java
index 4e6f89e..58f54ae 100644
--- a/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/PropertyReportTaskTest.java
+++ b/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/PropertyReportTaskTest.java
@@ -18,7 +18,7 @@ package org.gradle.api.tasks.diagnostics;
import org.gradle.api.internal.project.ProjectInternal;
import org.gradle.api.tasks.diagnostics.internal.PropertyReportRenderer;
import org.gradle.util.GUtil;
-import org.gradle.util.HelperUtil;
+import org.gradle.util.TestUtil;
import org.jmock.Expectations;
import org.jmock.Sequence;
import org.jmock.integration.junit4.JMock;
@@ -50,7 +50,7 @@ public class PropertyReportTaskTest {
will(returnValue(null));
}});
- task = HelperUtil.createTask(PropertyReportTask.class);
+ task = TestUtil.createTask(PropertyReportTask.class);
task.setRenderer(renderer);
}
diff --git a/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/TaskReportTaskTest.java b/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/TaskReportTaskTest.java
index d208996..b3168ef 100644
--- a/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/TaskReportTaskTest.java
+++ b/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/TaskReportTaskTest.java
@@ -23,7 +23,7 @@ import org.gradle.api.internal.tasks.TaskContainerInternal;
import org.gradle.api.tasks.TaskDependency;
import org.gradle.api.tasks.diagnostics.internal.TaskDetails;
import org.gradle.api.tasks.diagnostics.internal.TaskReportRenderer;
-import org.gradle.util.HelperUtil;
+import org.gradle.util.TestUtil;
import org.gradle.util.JUnit4GroovyMockery;
import org.gradle.util.Path;
import org.hamcrest.BaseMatcher;
@@ -71,7 +71,7 @@ public class TaskReportTaskTest {
will(returnValue(toSet()));
}});
- task = HelperUtil.createTask(TaskReportTask.class);
+ task = TestUtil.createTask(TaskReportTask.class);
task.setRenderer(renderer);
}
diff --git a/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/internal/TaskReportRendererTest.groovy b/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/internal/TaskReportRendererTest.groovy
index 7817b99..5c90751 100644
--- a/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/internal/TaskReportRendererTest.groovy
+++ b/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/internal/TaskReportRendererTest.groovy
@@ -19,9 +19,6 @@ package org.gradle.api.tasks.diagnostics.internal
import org.gradle.api.Rule
import org.gradle.logging.TestStyledTextOutput
-/**
- * @author Hans Dockter
- */
class TaskReportRendererTest extends AbstractTaskModelSpec {
private final TestStyledTextOutput writer = new TestStyledTextOutput().ignoreStyle()
private final TaskReportRenderer renderer = new TaskReportRenderer()
diff --git a/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/internal/dependencies/AsciiDependencyReportRendererTest.groovy b/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/internal/dependencies/AsciiDependencyReportRendererTest.groovy
index 8fbda25..b2b15b9 100644
--- a/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/internal/dependencies/AsciiDependencyReportRendererTest.groovy
+++ b/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/internal/dependencies/AsciiDependencyReportRendererTest.groovy
@@ -20,13 +20,13 @@ import org.gradle.api.artifacts.Configuration
import org.gradle.api.tasks.diagnostics.internal.graph.DependencyGraphRenderer
import org.gradle.api.tasks.diagnostics.internal.graph.nodes.SimpleDependency
import org.gradle.logging.TestStyledTextOutput
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import spock.lang.Specification
class AsciiDependencyReportRendererTest extends Specification {
private final TestStyledTextOutput textOutput = new TestStyledTextOutput().ignoreStyle()
private final AsciiDependencyReportRenderer renderer = new AsciiDependencyReportRenderer()
- private final Project project = HelperUtil.createRootProject()
+ private final Project project = TestUtil.createRootProject()
def setup() {
renderer.output = textOutput
diff --git a/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/internal/dsl/DependencyResultSpecNotationParserSpec.groovy b/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/internal/dsl/DependencyResultSpecNotationParserSpec.groovy
index 9ba513a..4f85c13 100644
--- a/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/internal/dsl/DependencyResultSpecNotationParserSpec.groovy
+++ b/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/internal/dsl/DependencyResultSpecNotationParserSpec.groovy
@@ -16,16 +16,13 @@
package org.gradle.api.tasks.diagnostics.internal.dsl
+import org.gradle.api.InvalidUserDataException
import org.gradle.api.artifacts.result.DependencyResult
import org.gradle.api.internal.artifacts.result.ResolutionResultDataBuilder
import org.gradle.api.internal.notations.api.NotationParser
import org.gradle.api.specs.Spec
import spock.lang.Specification
-import org.gradle.api.InvalidUserDataException
-/**
- * by Szczepan Faber, created at: 10/9/12
- */
class DependencyResultSpecNotationParserSpec extends Specification {
NotationParser<Spec<DependencyResult>> parser = DependencyResultSpecNotationParser.create()
diff --git a/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/internal/dsl/DependencyResultSpecTest.groovy b/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/internal/dsl/DependencyResultSpecTest.groovy
index ea241fc..be295b5 100644
--- a/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/internal/dsl/DependencyResultSpecTest.groovy
+++ b/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/internal/dsl/DependencyResultSpecTest.groovy
@@ -19,12 +19,8 @@ package org.gradle.api.tasks.diagnostics.internal.dsl
import spock.lang.Specification
import static org.gradle.api.internal.artifacts.result.ResolutionResultDataBuilder.newDependency
-
import static org.gradle.api.internal.artifacts.result.ResolutionResultDataBuilder.newUnresolvedDependency
-/**
- * by Szczepan Faber, created at: 11/6/12
- */
class DependencyResultSpecTest extends Specification {
def "knows matching dependencies"() {
diff --git a/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/internal/graph/DependencyGraphRendererSpec.groovy b/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/internal/graph/DependencyGraphRendererSpec.groovy
index 9820b2b..de3211b 100644
--- a/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/internal/graph/DependencyGraphRendererSpec.groovy
+++ b/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/internal/graph/DependencyGraphRendererSpec.groovy
@@ -16,14 +16,11 @@
package org.gradle.api.tasks.diagnostics.internal.graph
-import org.gradle.api.tasks.diagnostics.internal.GraphRenderer
import org.gradle.api.tasks.diagnostics.internal.graph.nodes.SimpleDependency
+import org.gradle.internal.graph.GraphRenderer
import org.gradle.logging.TestStyledTextOutput
import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 9/21/12
- */
class DependencyGraphRendererSpec extends Specification {
private textOutput = new TestStyledTextOutput().ignoreStyle()
diff --git a/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/internal/graph/nodes/AbstractRenderableDependencyResultSpec.groovy b/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/internal/graph/nodes/AbstractRenderableDependencyResultSpec.groovy
index 82222e1..4b4859b 100644
--- a/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/internal/graph/nodes/AbstractRenderableDependencyResultSpec.groovy
+++ b/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/internal/graph/nodes/AbstractRenderableDependencyResultSpec.groovy
@@ -23,9 +23,6 @@ import spock.lang.Specification
import static org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier.newId
import static org.gradle.api.internal.artifacts.DefaultModuleVersionSelector.newSelector
-/**
- * by Szczepan Faber, created at: 10/9/12
- */
class AbstractRenderableDependencyResultSpec extends Specification {
def "renders name cleanly"() {
diff --git a/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/internal/graph/nodes/RenderableDependencyResultTest.groovy b/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/internal/graph/nodes/RenderableDependencyResultTest.groovy
index d085884..a9d0478 100644
--- a/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/internal/graph/nodes/RenderableDependencyResultTest.groovy
+++ b/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/internal/graph/nodes/RenderableDependencyResultTest.groovy
@@ -23,9 +23,6 @@ import spock.lang.Specification
import static org.gradle.api.internal.artifacts.DefaultModuleVersionSelector.newSelector
import static org.gradle.api.internal.artifacts.result.ResolutionResultDataBuilder.newModule
-/**
- * by Szczepan Faber, created at: 10/9/12
- */
class RenderableDependencyResultTest extends Specification {
def "renders name"() {
diff --git a/subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/graph/nodes/SimpleDependency.java b/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/internal/graph/nodes/SimpleDependency.java
similarity index 100%
rename from subprojects/diagnostics/src/main/groovy/org/gradle/api/tasks/diagnostics/internal/graph/nodes/SimpleDependency.java
rename to subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/internal/graph/nodes/SimpleDependency.java
diff --git a/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/internal/insight/DependencyInsightReporterSpec.groovy b/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/internal/insight/DependencyInsightReporterSpec.groovy
index 9a37f3a..9589814 100644
--- a/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/internal/insight/DependencyInsightReporterSpec.groovy
+++ b/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/internal/insight/DependencyInsightReporterSpec.groovy
@@ -27,10 +27,6 @@ import static org.gradle.api.internal.artifacts.DefaultModuleVersionSelector.new
import static org.gradle.api.internal.artifacts.ivyservice.resolveengine.result.VersionSelectionReasons.CONFLICT_RESOLUTION
import static org.gradle.api.internal.artifacts.ivyservice.resolveengine.result.VersionSelectionReasons.FORCED
-/**
- * Created: 23/08/2012
- * @author Szczepan Faber
- */
class DependencyInsightReporterSpec extends Specification {
def "sorts dependencies"() {
@@ -103,6 +99,6 @@ class DependencyInsightReporterSpec extends Specification {
def selectedModule = new DefaultResolvedModuleVersionResult(newId(group, name, selected), selectionReason)
new DefaultResolvedDependencyResult(newSelector(group, name, requested),
selectedModule,
- new DefaultResolvedModuleVersionResult(newId("a", "root", "1")))
+ new DefaultResolvedModuleVersionResult(newId("a", "root", "1"), VersionSelectionReasons.REQUESTED))
}
}
diff --git a/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/internal/insight/DependencyResultSorterSpec.groovy b/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/internal/insight/DependencyResultSorterSpec.groovy
index 4d49297..dc06f00 100644
--- a/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/internal/insight/DependencyResultSorterSpec.groovy
+++ b/subprojects/diagnostics/src/test/groovy/org/gradle/api/tasks/diagnostics/internal/insight/DependencyResultSorterSpec.groovy
@@ -24,14 +24,11 @@ import spock.lang.Specification
import static org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier.newId
import static org.gradle.api.internal.artifacts.DefaultModuleVersionSelector.newSelector
-/**
- * by Szczepan Faber, created at: 8/22/12
- */
class DependencyResultSorterSpec extends Specification {
- def "sorts by requested version and prefers exact matching selected version over inexact"() {
+ def "sorts by requested version"() {
def d1 = newDependency(newSelector("org.aha", "aha", "1.0"), newId("org.gradle", "zzzz", "3.0"))
- def d2 = newDependency(newSelector("org.gradle", "core", "2.0"), newId("org.gradle", "core", "2.0"))
+ def d2 = newDependency(newSelector("org.gradle", "core", "0.8"), newId("org.gradle", "core", "2.0"))
def d3 = newDependency(newSelector("org.gradle", "core", "1.0"), newId("org.gradle", "core", "2.0"))
def d4 = newDependency(newSelector("org.gradle", "core", "1.5"), newId("org.gradle", "core", "2.0"))
@@ -47,15 +44,53 @@ class DependencyResultSorterSpec extends Specification {
sorted == [d1, d2, d3, d4, d5, d6, d7]
}
+ def "for a given module prefers dependency where selected exactly matches requested"() {
+ def d1 = newDependency(newSelector("org.gradle", "core", "2.0"), newId("org.gradle", "core", "2.0"))
+ def d2 = newDependency(newSelector("org.gradle", "core", "2.2"), newId("org.gradle", "core", "2.2"))
+ def d3 = newDependency(newSelector("org.gradle", "core", "1.0"), newId("org.gradle", "core", "2.0"))
+ def d4 = newDependency(newSelector("org.gradle", "core", "1.5"), newId("org.gradle", "core", "2.0"))
+ def d5 = newDependency(newSelector("org.gradle", "core", "3.0"), newId("org.gradle", "core", "2.2"))
+
+ when:
+ def sorted = DependencyResultSorter.sort([d3, d1, d5, d2, d4])
+
+ then:
+ sorted == [d1, d2, d3, d4, d5]
+ }
+
def "semantically compares versions"() {
- def d1 = newDependency(newSelector("org.gradle", "core", "1.0"), newId("org.gradle", "core", "2.0"))
+ def d1 = newDependency(newSelector("org.gradle", "core", "0.8"), newId("org.gradle", "core", "2.0"))
def d2 = newDependency(newSelector("org.gradle", "core", "1.0-alpha"), newId("org.gradle", "core", "2.0"))
+ def d3 = newDependency(newSelector("org.gradle", "core", "1.0"), newId("org.gradle", "core", "2.0"))
+ def d4 = newDependency(newSelector("org.gradle", "core", "1.2"), newId("org.gradle", "core", "2.0"))
+ def d5 = newDependency(newSelector("org.gradle", "core", "1.11"), newId("org.gradle", "core", "2.0"))
+ def d6 = newDependency(newSelector("org.gradle", "core", "1.11.2"), newId("org.gradle", "core", "2.0"))
+ def d7 = newDependency(newSelector("org.gradle", "core", "1.11.11"), newId("org.gradle", "core", "2.0"))
+ def d8 = newDependency(newSelector("org.gradle", "core", "2"), newId("org.gradle", "core", "2.0"))
+
+ when:
+ def sorted = DependencyResultSorter.sort([d4, d7, d1, d6, d8, d5, d3, d2])
+
+ then:
+ sorted == [d1, d2, d3, d4, d5, d6, d7, d8]
+ }
+
+ def "orders a mix of dynamic and static versions"() {
+ def d1 = newDependency(newSelector("org.gradle", "core", "2.0"), newId("org.gradle", "core", "2.0"))
+ def d2 = newDependency(newSelector("org.gradle", "core", "not-a-dynamic-selector"), newId("org.gradle", "core", "2.0"))
+ def d3 = newDependency(newSelector("org.gradle", "core", "0.8"), newId("org.gradle", "core", "2.0"))
+ def d4 = newDependency(newSelector("org.gradle", "core", "1.0"), newId("org.gradle", "core", "2.0"))
+ def d5 = newDependency(newSelector("org.gradle", "core", "(,2.0]"), newId("org.gradle", "core", "2.0"))
+ def d6 = newDependency(newSelector("org.gradle", "core", "1.2+"), newId("org.gradle", "core", "2.0"))
+ def d7 = newDependency(newSelector("org.gradle", "core", "[1.2,)"), newId("org.gradle", "core", "2.0"))
+ def d8 = newDependency(newSelector("org.gradle", "core", "latest.integration"), newId("org.gradle", "core", "2.0"))
+ def d9 = newDependency(newSelector("org.gradle", "core", "latest.zzz"), newId("org.gradle", "core", "2.0"))
when:
- def sorted = DependencyResultSorter.sort([d1, d2])
+ def sorted = DependencyResultSorter.sort([d4, d7, d1, d6, d8, d5, d3, d9, d2])
then:
- sorted == [d2, d1]
+ sorted == [d1, d2, d3, d4, d5, d6, d7, d8, d9]
}
def "sorts by from when requested version is the same"() {
@@ -78,6 +113,7 @@ class DependencyResultSorterSpec extends Specification {
private newDependency(ModuleVersionSelector requested, ModuleVersionIdentifier selected, ModuleVersionIdentifier from = newId("org", "a", "1.0")) {
return Stub(DependencyEdge) {
+ toString() >> "$requested -> $selected"
getRequested() >> requested
getActual() >> selected
getFrom() >> from
diff --git a/subprojects/distributions/distributions.gradle b/subprojects/distributions/distributions.gradle
index 00ccf8f..80d0f35 100644
--- a/subprojects/distributions/distributions.gradle
+++ b/subprojects/distributions/distributions.gradle
@@ -30,21 +30,13 @@ tasks.withType(AbstractArchiveTask) {
}
dependencies {
- groovy libraries.groovy
+ testCompile libraries.groovy
}
configurations {
dists
}
-integTestTasks.all {
- if (project.hasProperty("noDistTests")) {
- gradle.startParameter.excludedTaskNames << it.path
- } else {
- inputs.files buildDists
- }
-}
-
daemonIntegTest.enabled = false
evaluationDependsOn ":docs"
@@ -133,3 +125,7 @@ task outputsZip(type: Zip) {
artifacts {
dists allZip, binZip, srcZip
}
+
+integTest {
+ inputs.files allZip, binZip, srcZip
+}
\ No newline at end of file
diff --git a/subprojects/distributions/src/integTest/groovy/org/gradle/AllDistributionIntegrationSpec.groovy b/subprojects/distributions/src/integTest/groovy/org/gradle/AllDistributionIntegrationSpec.groovy
index b954efc..225063d 100644
--- a/subprojects/distributions/src/integTest/groovy/org/gradle/AllDistributionIntegrationSpec.groovy
+++ b/subprojects/distributions/src/integTest/groovy/org/gradle/AllDistributionIntegrationSpec.groovy
@@ -37,7 +37,7 @@ class AllDistributionIntegrationSpec extends DistributionIntegrationSpec {
// Source
contentsDir.file('src/org/gradle/api/Project.java').assertIsFile()
- contentsDir.file('src/org/gradle/initialization/defaultBuildSourceScript.txt').assertIsFile()
+ contentsDir.file('src/org/gradle/initialization/buildsrc/defaultBuildSourceScript.txt').assertIsFile()
contentsDir.file('src/org/gradle/gradleplugin/userinterface/swing/standalone/BlockingApplication.java').assertIsFile()
contentsDir.file('src/org/gradle/wrapper/WrapperExecutor.java').assertIsFile()
diff --git a/subprojects/distributions/src/integTest/groovy/org/gradle/DistributionIntegrationSpec.groovy b/subprojects/distributions/src/integTest/groovy/org/gradle/DistributionIntegrationSpec.groovy
index 4233b87..1037dc6 100644
--- a/subprojects/distributions/src/integTest/groovy/org/gradle/DistributionIntegrationSpec.groovy
+++ b/subprojects/distributions/src/integTest/groovy/org/gradle/DistributionIntegrationSpec.groovy
@@ -45,7 +45,7 @@ abstract class DistributionIntegrationSpec extends AbstractIntegrationSpec {
when:
def entries = zipFile.entries().toList()
def entriesByPath = entries.groupBy { ZipEntry zipEntry -> zipEntry.name }
- def dupes = entriesByPath.findAll() { it.value.size() > 1 }
+ def dupes = entriesByPath.findAll { it.value.size() > 1 && !it.key.contains('/META-INF/services/') }
def dupesWithCount = dupes.collectEntries { [it.key, it.value.size()]}
then:
@@ -76,11 +76,8 @@ abstract class DistributionIntegrationSpec extends AbstractIntegrationSpec {
// Core libs
def coreLibs = contentsDir.file("lib").listFiles().findAll { it.name.startsWith("gradle-") }
- assert coreLibs.size() == 11
+ assert coreLibs.size() == 13
coreLibs.each { assertIsGradleJar(it) }
- def wrapperJar = contentsDir.file("lib/gradle-wrapper-${version}.jar")
- wrapperJar.assertIsFile()
- assert wrapperJar.length() < 20 * 1024; // wrapper needs to be small. Let's check it's smaller than some arbitrary 'small' limit
def toolingApiJar = contentsDir.file("lib/gradle-tooling-api-${version}.jar")
toolingApiJar.assertIsFile()
diff --git a/subprojects/docs/docs.gradle b/subprojects/docs/docs.gradle
index be98e7a..a1909c3 100755
--- a/subprojects/docs/docs.gradle
+++ b/subprojects/docs/docs.gradle
@@ -18,6 +18,7 @@ import org.gradle.build.docs.UserGuideTransformTask
import org.gradle.build.docs.ExtractSnippetsTask
import org.gradle.build.docs.AssembleSamplesDocTask
import org.gradle.build.docs.Docbook2Xhtml
+import org.gradle.build.docs.dsl.source.GenerateDefaultImportsTask
import org.gradle.build.docs.dsl.docbook.AssembleDslDocTask
import org.gradle.build.docs.dsl.source.ExtractDslMetaDataTask
import org.gradle.build.docs.releasenotes.*
@@ -40,12 +41,16 @@ repositories {
ivy '[organisation]/v[revision]/ivy(.[ext])'
}
}
+
+ maven { url 'http://repo.gradle.org/gradle/gradle-build-internal' }
}
configurations {
+ groovydocGroovy {}
userGuideStyleSheets
userGuideTask
jquery
+ jqueryTipTip
fonts
}
@@ -58,6 +63,7 @@ dependencies {
userGuideStyleSheets 'docbook:docbook-xsl:1.75.2 at zip'
jquery "jquery:jquery.min:1.8.0 at js"
+ jqueryTipTip "com.drewwilson.code:jquery.tipTip:1.3:minified at js"
fonts \
"lato:regular:6:v0SdcGFAl2aezM9Vq_aFTQ at ttf",
@@ -69,7 +75,9 @@ dependencies {
"ubuntumono:bold:3:ceqTZGKHipo8pJj4molytp_TkvowlIOtbR7ePgFOpF4 at ttf",
"ubuntumono:bold-italic:3:n_d8tv_JOIiYyMXR4eaV9WsGzsqhEorxQDpu60nfWEc at ttf"
- groovy libraries.groovy
+ groovydocGroovy libraries.groovy
+
+ testCompile libraries.groovy
testCompile "org.pegdown:pegdown:1.1.0"
testCompile libraries.jsoup
testCompile "org.gebish:geb-spock:0.9.0-RC-1"
@@ -214,6 +222,24 @@ task dslStandaloneDocbook(type: UserGuideTransformTask, dependsOn: [dslDocbook])
dsldocUrl = '.'
}
+task defaultImports(type: GenerateDefaultImportsTask, dependsOn: dslMetaData) {
+ metaDataFile = dslMetaData.destFile
+ destFile = new File(generatedResourcesDir, "default-imports.txt")
+ // These are part of the API, but not the DSL
+ excludePackage 'org.gradle.tooling.**'
+ excludePackage 'org.gradle.testfixtures.**'
+
+ // Tweak the imports due to some inconsistencies introduced before we automated the default-imports generation
+ excludePackage 'org.gradle.plugins.ide.eclipse.model'
+ excludePackage 'org.gradle.plugins.ide.idea.model'
+ excludePackage 'org.gradle.api.tasks.testing.logging'
+ extraPackage 'org.gradle.util'
+
+ // TODO - rename some incubating types to remove collisions and then remove these exclusions
+ excludePackage 'org.gradle.plugins.binaries.model'
+ excludePackage 'org.gradle.nativecode.cdt.model'
+}
+
task dslHtml(type: Docbook2Xhtml) {
source dslStandaloneDocbook
destDir = new File(docsDir, 'dsl')
@@ -224,12 +250,12 @@ task dslHtml(type: Docbook2Xhtml) {
}
// This is used in the distribution and for the online version
-task userguideDocbook(type: UserGuideTransformTask, dependsOn: [samples, samplesDocbook]) {
+task userguideDocbook(type: UserGuideTransformTask, dependsOn: [samples, samplesDocbook, defaultImports]) {
destFile = new File(docbookSrc, 'userguide.xml')
}
// This is used for the PDF, where we need absolute links to the javadoc etc.
-task pdfUserguideDocbook(type: UserGuideTransformTask, dependsOn: [samples, samplesDocbook]) {
+task pdfUserguideDocbook(type: UserGuideTransformTask, dependsOn: [samples, samplesDocbook, defaultImports]) {
destFile = new File(docbookSrc, 'remoteUserguide.xml')
}
@@ -293,10 +319,14 @@ task javadocAll(type: Javadoc) {
include 'org/gradle/api/**'
include 'org/gradle/*'
include 'org/gradle/external/javadoc/**'
+ include 'org/gradle/language/**'
+ include 'org/gradle/nativecode/**'
include 'org/gradle/process/**'
include 'org/gradle/plugins/**'
include 'org/gradle/testfixtures/**'
include 'org/gradle/tooling/**'
+ include 'org/gradle/testing/jacoco/**'
+ include 'org/gradle/buildsetup/**'
exclude '**/internal/**'
options.links(javaApiUrl, groovyApiUrl, "http://maven.apache.org/ref/2.2.1/maven-core/apidocs",
"http://maven.apache.org/ref/2.2.1/maven-model/apidocs")
@@ -329,7 +359,7 @@ task groovydocAll(type: Groovydoc, dependsOn: configureGroovydocAll) {
windowTitle = "Gradle API $version"
docTitle = windowTitle
}
- groovyClasspath = project(':core').configurations.groovy
+ groovyClasspath = configurations.groovydocGroovy
doLast {
def index = new File(destinationDir, "index.html")
index.text = index.text.replace("{todo.title}", windowTitle) // workaround groovydoc bug
@@ -343,7 +373,7 @@ task checkstyleApi(type: Checkstyle) {
reports.xml.destination = file("$checkstyle.reportsDir/checkstyle-api.xml")
}
-task userguideFragmentSrc(type: UserGuideTransformTask, dependsOn: [userguideStyleSheets, samples]) {
+task userguideFragmentSrc(type: UserGuideTransformTask, dependsOn: [userguideStyleSheets]) {
tags << 'standalone'
sourceFile = new File(userguideSrcDir, 'installation.xml')
destFile = new File(docbookSrc, 'installation.xml')
@@ -392,6 +422,8 @@ task viewReleaseNotes(dependsOn: releaseNotes) {
}
}
+sourceSets.main.output.dir generatedResourcesDir, builtBy: defaultImports
+
test {
dependsOn releaseNotes
systemProperty "org.gradle.docs.releasenotes.source", releaseNotesMarkdown.source.singleFile
@@ -399,10 +431,6 @@ test {
}
-if (project.hasProperty('noDocsTests')) {
- gradle.startParameter.excludedTaskNames << test.path
-}
-
task docs {
dependsOn javadocAll, groovydocAll, userguide, distDocs, samplesDocs, dslHtml, releaseNotes
description = 'Generates all documentation'
diff --git a/subprojects/docs/src/docs/css/release-notes.css b/subprojects/docs/src/docs/css/release-notes.css
index 476dd9b..1c41eaa 100644
--- a/subprojects/docs/src/docs/css/release-notes.css
+++ b/subprojects/docs/src/docs/css/release-notes.css
@@ -42,30 +42,25 @@ button.display-toggle {
cursor: pointer;
}
-h3.incubating {
- display: inline-block;
-}
-
a.incubating-marker {
- display: inline-block;
- clear: right;
+ display: inline;
color: white;
font-style: italic;
- font-size: 1.0em;
- text-shadow: 0 0 1px rgba(0, 0, 0, 0.4);
+ font-size: 0.6em;
+ text-shadow: none;
margin-left: 0.6em;
- cursor: help;
border-radius: 6px;
background-color: rgb(160, 160, 160);
- padding: 0 5px;
- box-shadow: 1px 1px 3px 0 black;
- vertical-align: text-bottom;
+ border: 1px solid rgb(150, 150, 150);
+ padding: 1px 5px;
+ box-shadow: none;
+ cursor: pointer;
+ vertical-align: 1px;
}
-
a.incubating-marker:hover {
text-decoration: none;
- border-bottom: none
+ border: 1px solid rgb(150, 150, 150);
}
section.footer {
@@ -124,12 +119,12 @@ section.footer {
#tiptip_content {
font-size: 13px;
- color: #8B8B8B;
+ color: #717171;
padding: 6px 10px;
- border: 2px solid #8B8B8B;
+ border: 1px solid #8B8B8B;
background-color: #FFF;
border-radius: 8px;
- box-shadow: 0 0 4px #acacac;
+ box-shadow: 2px 2px 4px #acacac;
text-align: center;
}
diff --git a/subprojects/docs/src/docs/dsl/dsl.xml b/subprojects/docs/src/docs/dsl/dsl.xml
index d045910..1b9c01d 100644
--- a/subprojects/docs/src/docs/dsl/dsl.xml
+++ b/subprojects/docs/src/docs/dsl/dsl.xml
@@ -149,6 +149,9 @@
<td>org.gradle.api.tasks.SourceSetOutput</td>
</tr>
<tr>
+ <td>org.gradle.api.tasks.incremental.IncrementalTaskInputs</td>
+ </tr>
+ <tr>
<td>org.gradle.api.artifacts.Configuration</td>
</tr>
<tr>
@@ -167,6 +170,18 @@
<td>org.gradle.api.publish.PublishingExtension</td>
</tr>
<tr>
+ <td>org.gradle.api.reporting.Report</td>
+ </tr>
+ <tr>
+ <td>org.gradle.api.reporting.Reporting</td>
+ </tr>
+ <tr>
+ <td>org.gradle.api.reporting.ReportContainer</td>
+ </tr>
+ <tr>
+ <td>org.gradle.api.reporting.ReportingExtension</td>
+ </tr>
+ <tr>
<td>org.gradle.api.publish.ivy.IvyPublication</td>
</tr>
<tr>
@@ -256,9 +271,6 @@
<td>org.gradle.api.plugins.buildcomparison.gradle.CompareGradleBuilds</td>
</tr>
<tr>
- <td>org.gradle.api.tasks.compile.Compile</td>
- </tr>
- <tr>
<td>org.gradle.api.tasks.Copy</td>
</tr>
<tr>
@@ -298,6 +310,12 @@
<td>org.gradle.api.tasks.javadoc.Groovydoc</td>
</tr>
<tr>
+ <td>org.gradle.testing.jacoco.tasks.JacocoReport</td>
+ </tr>
+ <tr>
+ <td>org.gradle.testing.jacoco.tasks.JacocoMerge</td>
+ </tr>
+ <tr>
<td>org.gradle.api.tasks.bundling.Jar</td>
</tr>
<tr>
@@ -337,6 +355,9 @@
<td>org.gradle.api.tasks.scala.ScalaDoc</td>
</tr>
<tr>
+ <td>org.gradle.buildsetup.tasks.SetupBuild</td>
+ </tr>
+ <tr>
<td>org.gradle.plugins.signing.Sign</td>
</tr>
<tr>
@@ -448,4 +469,66 @@
</table>
</section>
+ <section>
+ <title>Native component core types</title>
+ <para>Used to configure components developed with native code.</para>
+ <table>
+ <title>Native component core types</title>
+ <tr>
+ <td>org.gradle.nativecode.base.NativeComponent</td>
+ </tr>
+ <tr>
+ <td>org.gradle.nativecode.base.Executable</td>
+ </tr>
+ <tr>
+ <td>org.gradle.nativecode.base.Library</td>
+ </tr>
+ <tr>
+ <td>org.gradle.nativecode.base.NativeBinary</td>
+ </tr>
+ <tr>
+ <td>org.gradle.nativecode.base.ExecutableBinary</td>
+ </tr>
+ <tr>
+ <td>org.gradle.nativecode.base.SharedLibraryBinary</td>
+ </tr>
+ <tr>
+ <td>org.gradle.nativecode.base.StaticLibraryBinary</td>
+ </tr>
+ <tr>
+ <td>org.gradle.nativecode.base.ToolChain</td>
+ </tr>
+ <tr>
+ <td>org.gradle.nativecode.base.ToolChainRegistry</td>
+ </tr>
+ </table>
+ </section>
+ <section>
+ <title>Native component task and plugin types</title>
+ <para>Tasks and plugins used to build native code components.</para>
+ <table>
+ <title>Native component task and plugin types</title>
+ <tr>
+ <td>org.gradle.nativecode.language.cpp.tasks.CppCompile</td>
+ </tr>
+ <tr>
+ <td>org.gradle.nativecode.language.c.tasks.CCompile</td>
+ </tr>
+ <tr>
+ <td>org.gradle.nativecode.language.asm.tasks.Assemble</td>
+ </tr>
+ <tr>
+ <td>org.gradle.nativecode.base.tasks.LinkExecutable</td>
+ </tr>
+ <tr>
+ <td>org.gradle.nativecode.base.tasks.LinkSharedLibrary</td>
+ </tr>
+ <tr>
+ <td>org.gradle.nativecode.base.tasks.CreateStaticLibrary</td>
+ </tr>
+ <tr>
+ <td>org.gradle.nativecode.base.tasks.InstallExecutable</td>
+ </tr>
+ </table>
+ </section>
</book>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.api.Task.xml b/subprojects/docs/src/docs/dsl/org.gradle.api.Task.xml
index 82369a8..7388dcc 100644
--- a/subprojects/docs/src/docs/dsl/org.gradle.api.Task.xml
+++ b/subprojects/docs/src/docs/dsl/org.gradle.api.Task.xml
@@ -44,6 +44,12 @@
<td>dependsOn</td>
</tr>
<tr>
+ <td>mustRunAfter</td>
+ </tr>
+ <tr>
+ <td>finalizedBy</td>
+ </tr>
+ <tr>
<td>state</td>
</tr>
<tr>
@@ -75,6 +81,12 @@
<td>dependsOn</td>
</tr>
<tr>
+ <td>mustRunAfter</td>
+ </tr>
+ <tr>
+ <td>finalizedBy</td>
+ </tr>
+ <tr>
<td>onlyIf</td>
</tr>
<tr>
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.api.artifacts.dsl.DependencyHandler.xml b/subprojects/docs/src/docs/dsl/org.gradle.api.artifacts.dsl.DependencyHandler.xml
index 635cd25..1acf8f3 100644
--- a/subprojects/docs/src/docs/dsl/org.gradle.api.artifacts.dsl.DependencyHandler.xml
+++ b/subprojects/docs/src/docs/dsl/org.gradle.api.artifacts.dsl.DependencyHandler.xml
@@ -7,6 +7,9 @@
<td>Name</td>
</tr>
</thead>
+ <tr>
+ <td>components</td>
+ </tr>
</table>
</section>
<section>
@@ -35,6 +38,9 @@
<tr>
<td>localGroovy</td>
</tr>
+ <tr>
+ <td>components</td>
+ </tr>
</table>
</section>
</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.api.artifacts.dsl.RepositoryHandler.xml b/subprojects/docs/src/docs/dsl/org.gradle.api.artifacts.dsl.RepositoryHandler.xml
index 27fabf5..74a90e7 100644
--- a/subprojects/docs/src/docs/dsl/org.gradle.api.artifacts.dsl.RepositoryHandler.xml
+++ b/subprojects/docs/src/docs/dsl/org.gradle.api.artifacts.dsl.RepositoryHandler.xml
@@ -46,6 +46,9 @@
<td>mavenCentral</td>
</tr>
<tr>
+ <td>jcenter</td>
+ </tr>
+ <tr>
<td>mavenLocal</td>
</tr>
<tr>
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.api.plugins.ApplicationPluginConvention.xml b/subprojects/docs/src/docs/dsl/org.gradle.api.plugins.ApplicationPluginConvention.xml
index 98ddc78..d9912bb 100644
--- a/subprojects/docs/src/docs/dsl/org.gradle.api.plugins.ApplicationPluginConvention.xml
+++ b/subprojects/docs/src/docs/dsl/org.gradle.api.plugins.ApplicationPluginConvention.xml
@@ -16,6 +16,10 @@
<td><literal>null</literal></td>
</tr>
<tr>
+ <td>applicationDefaultJvmArgs</td>
+ <td><literal>[]</literal></td>
+ </tr>
+ <tr>
<td>applicationDistribution</td>
<td>A copy spec that; includes all of the contents of <literal>src/dist</literal>, copies the start scripts into <literal>bin</literal>, and copies the built jar and all dependencies into <literal>lib</literal></td>
</tr>
@@ -29,4 +33,4 @@
</thead>
</table>
</section>
-</section>
\ No newline at end of file
+</section>
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.api.plugins.jetty.AbstractJettyRunTask.xml b/subprojects/docs/src/docs/dsl/org.gradle.api.plugins.jetty.AbstractJettyRunTask.xml
index 91bf7f4..96aef57 100644
--- a/subprojects/docs/src/docs/dsl/org.gradle.api.plugins.jetty.AbstractJettyRunTask.xml
+++ b/subprojects/docs/src/docs/dsl/org.gradle.api.plugins.jetty.AbstractJettyRunTask.xml
@@ -33,6 +33,14 @@
<td><literal>project.httpPort</literal></td>
</tr>
<tr>
+ <td>reload</td>
+ <td><literal>"automatic"</literal></td>
+ </tr>
+ <tr>
+ <td>scanIntervalSeconds</td>
+ <td><literal>0</literal></td>
+ </tr>
+ <tr>
<td>additionalRuntimeJars</td>
<td><literal>[]</literal></td>
</tr>
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.api.plugins.jetty.JettyRunWar.xml b/subprojects/docs/src/docs/dsl/org.gradle.api.plugins.jetty.JettyRunWar.xml
index 2f70fd1..5fea4a2 100644
--- a/subprojects/docs/src/docs/dsl/org.gradle.api.plugins.jetty.JettyRunWar.xml
+++ b/subprojects/docs/src/docs/dsl/org.gradle.api.plugins.jetty.JettyRunWar.xml
@@ -12,6 +12,14 @@
<td>webApp</td>
<td><literal>project.war.archivePath</literal></td>
</tr>
+ <tr>
+ <td>reload</td>
+ <td><literal>"automatic"</literal></td>
+ </tr>
+ <tr>
+ <td>scanIntervalSeconds</td>
+ <td><literal>0</literal></td>
+ </tr>
</table>
</section>
<section>
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.api.plugins.quality.CodeNarc.xml b/subprojects/docs/src/docs/dsl/org.gradle.api.plugins.quality.CodeNarc.xml
index 94773f1..b0babdf 100644
--- a/subprojects/docs/src/docs/dsl/org.gradle.api.plugins.quality.CodeNarc.xml
+++ b/subprojects/docs/src/docs/dsl/org.gradle.api.plugins.quality.CodeNarc.xml
@@ -13,6 +13,18 @@
<td><literal>project.codenarc.configFile</literal></td>
</tr>
<tr>
+ <td>maxPriority1Violations</td>
+ <td><literal>0</literal></td>
+ </tr>
+ <tr>
+ <td>maxPriority2Violations</td>
+ <td><literal>0</literal></td>
+ </tr>
+ <tr>
+ <td>maxPriority3Violations</td>
+ <td><literal>0</literal></td>
+ </tr>
+ <tr>
<td>ignoreFailures</td>
<td><literal>project.codenarc.ignoreFailures</literal></td>
</tr>
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.api.plugins.quality.CodeNarcExtension.xml b/subprojects/docs/src/docs/dsl/org.gradle.api.plugins.quality.CodeNarcExtension.xml
index 3fdba2c..9c22989 100644
--- a/subprojects/docs/src/docs/dsl/org.gradle.api.plugins.quality.CodeNarcExtension.xml
+++ b/subprojects/docs/src/docs/dsl/org.gradle.api.plugins.quality.CodeNarcExtension.xml
@@ -25,6 +25,21 @@
<td><literal>project.codeNarcConfigFile</literal></td>
</tr>
<tr>
+ <td>maxPriority1Violations</td>
+ <td><literal>0</literal></td>
+ <td><literal>0</literal></td>
+ </tr>
+ <tr>
+ <td>maxPriority2Violations</td>
+ <td><literal>0</literal></td>
+ <td><literal>0</literal></td>
+ </tr>
+ <tr>
+ <td>maxPriority3Violations</td>
+ <td><literal>0</literal></td>
+ <td><literal>0</literal></td>
+ </tr>
+ <tr>
<td>reportFormat</td>
<td><literal>html</literal></td>
<td><literal>project.codeNarcReportsFormat</literal></td>
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.api.publish.PublicationContainer.xml b/subprojects/docs/src/docs/dsl/org.gradle.api.publish.PublicationContainer.xml
index 5bf3ebb..f46d04e 100644
--- a/subprojects/docs/src/docs/dsl/org.gradle.api.publish.PublicationContainer.xml
+++ b/subprojects/docs/src/docs/dsl/org.gradle.api.publish.PublicationContainer.xml
@@ -17,9 +17,6 @@
<td>Name</td>
</tr>
</thead>
- <tr>
- <td>add</td>
- </tr>
</table>
</section>
</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.api.publish.ivy.IvyPublication.xml b/subprojects/docs/src/docs/dsl/org.gradle.api.publish.ivy.IvyPublication.xml
index 7eedb8e..8963f72 100644
--- a/subprojects/docs/src/docs/dsl/org.gradle.api.publish.ivy.IvyPublication.xml
+++ b/subprojects/docs/src/docs/dsl/org.gradle.api.publish.ivy.IvyPublication.xml
@@ -10,6 +10,21 @@
<tr>
<td>descriptor</td>
</tr>
+ <tr>
+ <td>artifacts</td>
+ </tr>
+ <tr>
+ <td>configurations</td>
+ </tr>
+ <tr>
+ <td>organisation</td>
+ </tr>
+ <tr>
+ <td>module</td>
+ </tr>
+ <tr>
+ <td>revision</td>
+ </tr>
</table>
</section>
<section>
@@ -21,8 +36,17 @@
</tr>
</thead>
<tr>
+ <td>from</td>
+ </tr>
+ <tr>
<td>descriptor</td>
</tr>
+ <tr>
+ <td>artifact</td>
+ </tr>
+ <tr>
+ <td>configurations</td>
+ </tr>
</table>
</section>
</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.api.publish.maven.MavenPublication.xml b/subprojects/docs/src/docs/dsl/org.gradle.api.publish.maven.MavenPublication.xml
index c3412b4..70ff391 100644
--- a/subprojects/docs/src/docs/dsl/org.gradle.api.publish.maven.MavenPublication.xml
+++ b/subprojects/docs/src/docs/dsl/org.gradle.api.publish.maven.MavenPublication.xml
@@ -13,6 +13,15 @@
<tr>
<td>artifacts</td>
</tr>
+ <tr>
+ <td>groupId</td>
+ </tr>
+ <tr>
+ <td>artifactId</td>
+ </tr>
+ <tr>
+ <td>version</td>
+ </tr>
</table>
</section>
<section>
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.api.reporting.GenerateBuildDashboard.xml b/subprojects/docs/src/docs/dsl/org.gradle.api.reporting.GenerateBuildDashboard.xml
index ad43461..6d74ac4 100644
--- a/subprojects/docs/src/docs/dsl/org.gradle.api.reporting.GenerateBuildDashboard.xml
+++ b/subprojects/docs/src/docs/dsl/org.gradle.api.reporting.GenerateBuildDashboard.xml
@@ -24,9 +24,6 @@
</tr>
</thead>
<tr>
- <td>inputReportsFiles</td>
- </tr>
- <tr>
<td>reports</td>
</tr>
</table>
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.api.reporting.Report.xml b/subprojects/docs/src/docs/dsl/org.gradle.api.reporting.Report.xml
new file mode 100644
index 0000000..2bfd69f
--- /dev/null
+++ b/subprojects/docs/src/docs/dsl/org.gradle.api.reporting.Report.xml
@@ -0,0 +1,37 @@
+<section>
+ <section>
+ <title>Properties</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>destination</td>
+ </tr>
+ <tr>
+ <td>displayName</td>
+ </tr>
+ <tr>
+ <td>name</td>
+ </tr>
+ <tr>
+ <td>outputType</td>
+ </tr>
+ <tr>
+ <td>enabled</td>
+ </tr>
+ </table>
+ </section>
+ <section>
+ <title>Methods</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.api.reporting.ReportContainer.xml b/subprojects/docs/src/docs/dsl/org.gradle.api.reporting.ReportContainer.xml
new file mode 100644
index 0000000..933a075
--- /dev/null
+++ b/subprojects/docs/src/docs/dsl/org.gradle.api.reporting.ReportContainer.xml
@@ -0,0 +1,25 @@
+<section>
+ <section>
+ <title>Properties</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>enabled</td>
+ </tr>
+ </table>
+ </section>
+ <section>
+ <title>Methods</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.api.reporting.Reporting.xml b/subprojects/docs/src/docs/dsl/org.gradle.api.reporting.Reporting.xml
new file mode 100644
index 0000000..a154f34
--- /dev/null
+++ b/subprojects/docs/src/docs/dsl/org.gradle.api.reporting.Reporting.xml
@@ -0,0 +1,28 @@
+<section>
+ <section>
+ <title>Properties</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>reports</td>
+ </tr>
+ </table>
+ </section>
+ <section>
+ <title>Methods</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>reports</td>
+ </tr>
+ </table>
+ </section>
+</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.api.reporting.ReportingExtension.xml b/subprojects/docs/src/docs/dsl/org.gradle.api.reporting.ReportingExtension.xml
new file mode 100644
index 0000000..def7c35
--- /dev/null
+++ b/subprojects/docs/src/docs/dsl/org.gradle.api.reporting.ReportingExtension.xml
@@ -0,0 +1,28 @@
+<section>
+ <section>
+ <title>Properties</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>baseDir</td>
+ </tr>
+ </table>
+ </section>
+ <section>
+ <title>Methods</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>file</td>
+ </tr>
+ </table>
+ </section>
+</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.AbstractCopyTask.xml b/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.AbstractCopyTask.xml
index 9245214..05f9422 100644
--- a/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.AbstractCopyTask.xml
+++ b/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.AbstractCopyTask.xml
@@ -36,6 +36,10 @@
<td>includeEmptyDirs</td>
<td><literal>true</literal></td>
</tr>
+ <tr>
+ <td>duplicatesStrategy</td>
+ <td><literal>null</literal></td>
+ </tr>
</table>
</section>
<section>
@@ -73,6 +77,12 @@
<tr>
<td>eachFile</td>
</tr>
+ <tr>
+ <td>filesMatching</td>
+ </tr>
+ <tr>
+ <td>filesNotMatching</td>
+ </tr>
</table>
</section>
</section>
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.Copy.xml b/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.Copy.xml
index d01de1a..28973e0 100644
--- a/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.Copy.xml
+++ b/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.Copy.xml
@@ -24,4 +24,4 @@
</thead>
</table>
</section>
-</section>
\ No newline at end of file
+</section>
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.GroovyRuntime.xml b/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.GroovyRuntime.xml
new file mode 100644
index 0000000..85f9881
--- /dev/null
+++ b/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.GroovyRuntime.xml
@@ -0,0 +1,25 @@
+<section>
+ <section>
+ <title>Properties</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+ <section>
+ <title>Methods</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>inferGroovyClasspath</td>
+ </tr>
+ </table>
+ </section>
+</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.ScalaRuntime.xml b/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.ScalaRuntime.xml
new file mode 100644
index 0000000..4d62cda
--- /dev/null
+++ b/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.ScalaRuntime.xml
@@ -0,0 +1,31 @@
+<section>
+ <section>
+ <title>Properties</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+ <section>
+ <title>Methods</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>inferScalaClasspath</td>
+ </tr>
+ <tr>
+ <td>findScalaJar</td>
+ </tr>
+ <tr>
+ <td>getScalaVersion</td>
+ </tr>
+ </table>
+ </section>
+</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.application.CreateStartScripts.xml b/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.application.CreateStartScripts.xml
index 84602cb..7773624 100644
--- a/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.application.CreateStartScripts.xml
+++ b/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.application.CreateStartScripts.xml
@@ -8,6 +8,7 @@
<tr><td>applicationName</td></tr>
<tr><td>mainClassName</td></tr>
<tr><td>classpath</td></tr>
+ <tr><td>defaultJvmOpts</td></tr>
<tr><td>outputDir</td></tr>
<tr><td>optsEnvironmentVar</td></tr>
</table>
@@ -20,4 +21,4 @@
</thead>
</table>
</section>
-</section>
\ No newline at end of file
+</section>
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.compile.GroovyCompile.xml b/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.compile.GroovyCompile.xml
index 98c4272..33dca71 100644
--- a/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.compile.GroovyCompile.xml
+++ b/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.compile.GroovyCompile.xml
@@ -22,7 +22,7 @@
</tr>
<tr>
<td>groovyClasspath</td>
- <td><literal>project.configurations.groovy</literal></td>
+ <td>Groovy library found on <literal>classpath</literal></td>
</tr>
</table>
</section>
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.incremental.IncrementalTaskInputs.xml b/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.incremental.IncrementalTaskInputs.xml
new file mode 100644
index 0000000..0ca5d88
--- /dev/null
+++ b/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.incremental.IncrementalTaskInputs.xml
@@ -0,0 +1,25 @@
+<section>
+ <section>
+ <title>Properties</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ <tr><td>incremental</td></tr>
+ </table>
+ </section>
+ <section>
+ <title>Methods</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ <tr><td>outOfDate</td></tr>
+ <tr><td>removed</td></tr>
+ </table>
+ </section>
+</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.incremental.InputFile.xml b/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.incremental.InputFile.xml
new file mode 100644
index 0000000..c0c0a9f
--- /dev/null
+++ b/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.incremental.InputFile.xml
@@ -0,0 +1,26 @@
+<section>
+ <section>
+ <title>Properties</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ <tr><td>file</td></tr>
+ <tr><td>added</td></tr>
+ <tr><td>modified</td></tr>
+ <tr><td>removed</td></tr>
+ </table>
+ </section>
+ <section>
+ <title>Methods</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.scala.ScalaCompile.xml b/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.scala.ScalaCompile.xml
index 2f47edc..09714bb 100644
--- a/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.scala.ScalaCompile.xml
+++ b/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.scala.ScalaCompile.xml
@@ -10,7 +10,7 @@
</thead>
<tr>
<td>scalaClasspath</td>
- <td><literal>project.configurations.scalaTools</literal></td>
+ <td><literal>scala-compiler</literal> dependency matching the <literal>scala-library</literal> version found on <literal>classpath</literal></td>
</tr>
<tr>
<td>options</td>
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.scala.ScalaDoc.xml b/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.scala.ScalaDoc.xml
index 313f7c1..a5d9622 100644
--- a/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.scala.ScalaDoc.xml
+++ b/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.scala.ScalaDoc.xml
@@ -18,7 +18,7 @@
</tr>
<tr>
<td>scalaClasspath</td>
- <td><literal>project.configurations.scalaTools</literal></td>
+ <td><literal>scala-compiler</literal> dependency matching the <literal>scala-library</literal> version found on <literal>classpath</literal></td>
</tr>
<tr>
<td>scalaDocOptions</td>
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.testing.Test.xml b/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.testing.Test.xml
index 923e8af..29151e1 100644
--- a/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.testing.Test.xml
+++ b/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.testing.Test.xml
@@ -25,6 +25,10 @@
<td><literal>project.testReportDir</literal></td>
</tr>
<tr>
+ <td>reports</td>
+ <td><literal>project.testReportDir</literal></td>
+ </tr>
+ <tr>
<td>classpath</td>
<td><literal>project.sourceSets.test.runtimeClasspath</literal></td>
</tr>
@@ -69,6 +73,10 @@
<td><literal>null</literal></td>
</tr>
<tr>
+ <td>minHeapSize</td>
+ <td><literal>null</literal></td>
+ </tr>
+ <tr>
<td>jvmArgs</td>
<td><literal>[]</literal></td>
</tr>
@@ -182,6 +190,9 @@
<td>testLogging</td>
</tr>
<tr>
+ <td>reports</td>
+ </tr>
+ <tr>
<td>options</td>
</tr>
</table>
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.wrapper.Wrapper.xml b/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.wrapper.Wrapper.xml
index bf35017..df692d2 100644
--- a/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.wrapper.Wrapper.xml
+++ b/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.wrapper.Wrapper.xml
@@ -38,9 +38,9 @@
</tr>
<tr>
<td>distributionUrl</td>
- <td><literal>'http\://services.gradle.org/distributions/gradle-${gradleVersion}-bin.zip'</literal>
+ <td><literal>"http\://services.gradle.org/distributions/gradle-${gradleVersion}-bin.zip"</literal>
(or
- <literal>'http\://services.gradle.org/distributions-snapshots/gradle-${gradleVersion}-bin.zip'</literal>
+ <literal>"http\://services.gradle.org/distributions-snapshots/gradle-${gradleVersion}-bin.zip"</literal>
for snapshot versions).
</td>
</tr>
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.buildsetup.tasks.SetupBuild.xml b/subprojects/docs/src/docs/dsl/org.gradle.buildsetup.tasks.SetupBuild.xml
new file mode 100644
index 0000000..b4cea87
--- /dev/null
+++ b/subprojects/docs/src/docs/dsl/org.gradle.buildsetup.tasks.SetupBuild.xml
@@ -0,0 +1,43 @@
+<!--
+ ~ Copyright 2013 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ 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.
+ -->
+
+<section>
+ <section>
+ <title>Properties</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ <td>Default</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>type</td>
+ <td><literal><replaceable>empty</replaceable> (or <replaceable>pom</replaceable> if a pom.xml file exists in the project directory)</literal></td>
+ </tr>
+ </table>
+ </section>
+ <section>
+ <title>Methods</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.language.base.BinaryContainer.xml b/subprojects/docs/src/docs/dsl/org.gradle.language.base.BinaryContainer.xml
new file mode 100644
index 0000000..659d719
--- /dev/null
+++ b/subprojects/docs/src/docs/dsl/org.gradle.language.base.BinaryContainer.xml
@@ -0,0 +1,38 @@
+<!--
+ ~ Copyright 2013 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ 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.
+ -->
+
+<section>
+ <section>
+ <title>Properties</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+ <section>
+ <title>Methods</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.Executable.xml b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.Executable.xml
new file mode 100644
index 0000000..659d719
--- /dev/null
+++ b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.Executable.xml
@@ -0,0 +1,38 @@
+<!--
+ ~ Copyright 2013 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ 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.
+ -->
+
+<section>
+ <section>
+ <title>Properties</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+ <section>
+ <title>Methods</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.ExecutableBinary.xml b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.ExecutableBinary.xml
new file mode 100644
index 0000000..659d719
--- /dev/null
+++ b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.ExecutableBinary.xml
@@ -0,0 +1,38 @@
+<!--
+ ~ Copyright 2013 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ 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.
+ -->
+
+<section>
+ <section>
+ <title>Properties</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+ <section>
+ <title>Methods</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.ExecutableContainer.xml b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.ExecutableContainer.xml
new file mode 100644
index 0000000..659d719
--- /dev/null
+++ b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.ExecutableContainer.xml
@@ -0,0 +1,38 @@
+<!--
+ ~ Copyright 2013 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ 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.
+ -->
+
+<section>
+ <section>
+ <title>Properties</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+ <section>
+ <title>Methods</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.Library.xml b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.Library.xml
new file mode 100644
index 0000000..ee8f6d6
--- /dev/null
+++ b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.Library.xml
@@ -0,0 +1,47 @@
+<!--
+ ~ Copyright 2013 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ 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.
+ -->
+
+<section>
+ <section>
+ <title>Properties</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>headers</td>
+ </tr>
+ <tr>
+ <td>shared</td>
+ </tr>
+ <tr>
+ <td>static</td>
+ </tr>
+ </table>
+ </section>
+ <section>
+ <title>Methods</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.LibraryBinary.xml b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.LibraryBinary.xml
new file mode 100644
index 0000000..7cf0d93
--- /dev/null
+++ b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.LibraryBinary.xml
@@ -0,0 +1,41 @@
+<!--
+ ~ Copyright 2013 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ 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.
+ -->
+
+<section>
+ <section>
+ <title>Properties</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>component</td>
+ </tr>
+ </table>
+ </section>
+ <section>
+ <title>Methods</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.LibraryContainer.xml b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.LibraryContainer.xml
new file mode 100644
index 0000000..659d719
--- /dev/null
+++ b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.LibraryContainer.xml
@@ -0,0 +1,38 @@
+<!--
+ ~ Copyright 2013 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ 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.
+ -->
+
+<section>
+ <section>
+ <title>Properties</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+ <section>
+ <title>Methods</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.NativeBinary.xml b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.NativeBinary.xml
new file mode 100644
index 0000000..6b350bf
--- /dev/null
+++ b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.NativeBinary.xml
@@ -0,0 +1,77 @@
+<!--
+ ~ Copyright 2013 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ 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.
+ -->
+
+<section>
+ <section>
+ <title>Properties</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>toolChain</td>
+ </tr>
+ <tr>
+ <td>outputFile</td>
+ </tr>
+ <tr>
+ <td>source</td>
+ </tr>
+ <tr>
+ <td>libs</td>
+ </tr>
+ <tr>
+ <td>macros</td>
+ </tr>
+ <tr>
+ <td>compilerArgs</td>
+ </tr>
+ <tr>
+ <td>linkerArgs</td>
+ </tr>
+ <tr>
+ <td>flavor</td>
+ </tr>
+ </table>
+ </section>
+ <section>
+ <title>Methods</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>source</td>
+ </tr>
+ <tr>
+ <td>lib</td>
+ </tr>
+ <tr>
+ <td>define</td>
+ </tr>
+ <tr>
+ <td>compilerArgs</td>
+ </tr>
+ <tr>
+ <td>linkerArgs</td>
+ </tr>
+ </table>
+ </section>
+</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.NativeComponent.xml b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.NativeComponent.xml
new file mode 100644
index 0000000..3250462
--- /dev/null
+++ b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.NativeComponent.xml
@@ -0,0 +1,56 @@
+<!--
+ ~ Copyright 2013 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ 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.
+ -->
+
+<section>
+ <section>
+ <title>Properties</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>baseName</td>
+ </tr>
+ <tr>
+ <td>source</td>
+ </tr>
+ <tr>
+ <td>binaries</td>
+ </tr>
+ <tr>
+ <td>flavors</td>
+ </tr>
+ </table>
+ </section>
+ <section>
+ <title>Methods</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>source</td>
+ </tr>
+ <tr>
+ <td>flavors</td>
+ </tr>
+ </table>
+ </section>
+</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.SharedLibraryBinary.xml b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.SharedLibraryBinary.xml
new file mode 100644
index 0000000..659d719
--- /dev/null
+++ b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.SharedLibraryBinary.xml
@@ -0,0 +1,38 @@
+<!--
+ ~ Copyright 2013 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ 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.
+ -->
+
+<section>
+ <section>
+ <title>Properties</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+ <section>
+ <title>Methods</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.StaticLibraryBinary.xml b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.StaticLibraryBinary.xml
new file mode 100644
index 0000000..659d719
--- /dev/null
+++ b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.StaticLibraryBinary.xml
@@ -0,0 +1,38 @@
+<!--
+ ~ Copyright 2013 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ 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.
+ -->
+
+<section>
+ <section>
+ <title>Properties</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+ <section>
+ <title>Methods</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.ToolChain.xml b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.ToolChain.xml
new file mode 100644
index 0000000..659d719
--- /dev/null
+++ b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.ToolChain.xml
@@ -0,0 +1,38 @@
+<!--
+ ~ Copyright 2013 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ 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.
+ -->
+
+<section>
+ <section>
+ <title>Properties</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+ <section>
+ <title>Methods</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.ToolChainRegistry.xml b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.ToolChainRegistry.xml
new file mode 100644
index 0000000..e3fa5de
--- /dev/null
+++ b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.ToolChainRegistry.xml
@@ -0,0 +1,44 @@
+<!--
+ ~ Copyright 2013 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ 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.
+ -->
+
+<section>
+ <section>
+ <title>Properties</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>availableToolChains</td>
+ </tr>
+ <tr>
+ <td>defaultToolChain</td>
+ </tr>
+ </table>
+ </section>
+ <section>
+ <title>Methods</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.tasks.AbstractLinkTask.xml b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.tasks.AbstractLinkTask.xml
new file mode 100644
index 0000000..b895322
--- /dev/null
+++ b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.tasks.AbstractLinkTask.xml
@@ -0,0 +1,59 @@
+<!--
+ ~ Copyright 2013 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ 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.
+ -->
+
+<section>
+ <section>
+ <title>Properties</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>source</td>
+ </tr>
+ <tr>
+ <td>libs</td>
+ </tr>
+ <tr>
+ <td>linkerArgs</td>
+ </tr>
+ <tr>
+ <td>outputFile</td>
+ </tr>
+ <tr>
+ <td>toolChain</td>
+ </tr>
+ </table>
+ </section>
+ <section>
+ <title>Methods</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>source</td>
+ </tr>
+ <tr>
+ <td>lib</td>
+ </tr>
+ </table>
+ </section>
+</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.tasks.CreateStaticLibrary.xml b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.tasks.CreateStaticLibrary.xml
new file mode 100644
index 0000000..0573d32
--- /dev/null
+++ b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.tasks.CreateStaticLibrary.xml
@@ -0,0 +1,50 @@
+<!--
+ ~ Copyright 2013 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ 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.
+ -->
+
+<section>
+ <section>
+ <title>Properties</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>source</td>
+ </tr>
+ <tr>
+ <td>outputFile</td>
+ </tr>
+ <tr>
+ <td>toolChain</td>
+ </tr>
+ </table>
+ </section>
+ <section>
+ <title>Methods</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>source</td>
+ </tr>
+ </table>
+ </section>
+</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.tasks.InstallExecutable.xml b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.tasks.InstallExecutable.xml
new file mode 100644
index 0000000..386ba3d
--- /dev/null
+++ b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.tasks.InstallExecutable.xml
@@ -0,0 +1,50 @@
+<!--
+ ~ Copyright 2013 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ 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.
+ -->
+
+<section>
+ <section>
+ <title>Properties</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>destinationDir</td>
+ </tr>
+ <tr>
+ <td>executable</td>
+ </tr>
+ <tr>
+ <td>libs</td>
+ </tr>
+ </table>
+ </section>
+ <section>
+ <title>Methods</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>lib</td>
+ </tr>
+ </table>
+ </section>
+</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.tasks.LinkExecutable.xml b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.tasks.LinkExecutable.xml
new file mode 100644
index 0000000..659d719
--- /dev/null
+++ b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.tasks.LinkExecutable.xml
@@ -0,0 +1,38 @@
+<!--
+ ~ Copyright 2013 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ 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.
+ -->
+
+<section>
+ <section>
+ <title>Properties</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+ <section>
+ <title>Methods</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.tasks.LinkSharedLibrary.xml b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.tasks.LinkSharedLibrary.xml
new file mode 100644
index 0000000..659d719
--- /dev/null
+++ b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.base.tasks.LinkSharedLibrary.xml
@@ -0,0 +1,38 @@
+<!--
+ ~ Copyright 2013 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ 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.
+ -->
+
+<section>
+ <section>
+ <title>Properties</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+ <section>
+ <title>Methods</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.nativecode.language.asm.tasks.Assemble.xml b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.language.asm.tasks.Assemble.xml
new file mode 100644
index 0000000..f14571a
--- /dev/null
+++ b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.language.asm.tasks.Assemble.xml
@@ -0,0 +1,47 @@
+<!--
+ ~ Copyright 2013 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ 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.
+ -->
+
+<section>
+ <section>
+ <title>Properties</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>objectFileDir</td>
+ </tr>
+ <tr>
+ <td>assemblerArgs</td>
+ </tr>
+ </table>
+ </section>
+ <section>
+ <title>Methods</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>source</td>
+ </tr>
+ </table>
+ </section>
+</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.nativecode.language.base.tasks.AbstractNativeCompileTask.xml b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.language.base.tasks.AbstractNativeCompileTask.xml
new file mode 100644
index 0000000..2da0bf5
--- /dev/null
+++ b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.language.base.tasks.AbstractNativeCompileTask.xml
@@ -0,0 +1,56 @@
+<!--
+ ~ Copyright 2013 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ 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.
+ -->
+
+<section>
+ <section>
+ <title>Properties</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>positionIndependentCode</td>
+ </tr>
+ <tr>
+ <td>objectFileDir</td>
+ </tr>
+ <tr>
+ <td>macros</td>
+ </tr>
+ <tr>
+ <td>compilerArgs</td>
+ </tr>
+ </table>
+ </section>
+ <section>
+ <title>Methods</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>includes</td>
+ </tr>
+ <tr>
+ <td>source</td>
+ </tr>
+ </table>
+ </section>
+</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.nativecode.language.c.tasks.CCompile.xml b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.language.c.tasks.CCompile.xml
new file mode 100644
index 0000000..659d719
--- /dev/null
+++ b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.language.c.tasks.CCompile.xml
@@ -0,0 +1,38 @@
+<!--
+ ~ Copyright 2013 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ 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.
+ -->
+
+<section>
+ <section>
+ <title>Properties</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+ <section>
+ <title>Methods</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.nativecode.language.cpp.plugins.CppExeConventionPlugin.xml b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.language.cpp.plugins.CppExeConventionPlugin.xml
new file mode 100644
index 0000000..659d719
--- /dev/null
+++ b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.language.cpp.plugins.CppExeConventionPlugin.xml
@@ -0,0 +1,38 @@
+<!--
+ ~ Copyright 2013 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ 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.
+ -->
+
+<section>
+ <section>
+ <title>Properties</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+ <section>
+ <title>Methods</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.nativecode.language.cpp.plugins.CppExtension.xml b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.language.cpp.plugins.CppExtension.xml
new file mode 100644
index 0000000..31e6e33
--- /dev/null
+++ b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.language.cpp.plugins.CppExtension.xml
@@ -0,0 +1,41 @@
+<!--
+ ~ Copyright 2013 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ 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.
+ -->
+
+<section>
+ <section>
+ <title>Properties</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>sourceSets</td>
+ </tr>
+ </table>
+ </section>
+ <section>
+ <title>Methods</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.nativecode.language.cpp.plugins.CppLibConventionPlugin.xml b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.language.cpp.plugins.CppLibConventionPlugin.xml
new file mode 100644
index 0000000..659d719
--- /dev/null
+++ b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.language.cpp.plugins.CppLibConventionPlugin.xml
@@ -0,0 +1,38 @@
+<!--
+ ~ Copyright 2013 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ 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.
+ -->
+
+<section>
+ <section>
+ <title>Properties</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+ <section>
+ <title>Methods</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.nativecode.language.cpp.plugins.CppPlugin.xml b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.language.cpp.plugins.CppPlugin.xml
new file mode 100644
index 0000000..659d719
--- /dev/null
+++ b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.language.cpp.plugins.CppPlugin.xml
@@ -0,0 +1,38 @@
+<!--
+ ~ Copyright 2013 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ 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.
+ -->
+
+<section>
+ <section>
+ <title>Properties</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+ <section>
+ <title>Methods</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.nativecode.language.cpp.tasks.CppCompile.xml b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.language.cpp.tasks.CppCompile.xml
new file mode 100644
index 0000000..659d719
--- /dev/null
+++ b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.language.cpp.tasks.CppCompile.xml
@@ -0,0 +1,38 @@
+<!--
+ ~ Copyright 2013 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ 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.
+ -->
+
+<section>
+ <section>
+ <title>Properties</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+ <section>
+ <title>Methods</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.nativecode.toolchain.plugins.GppCompilerPlugin.xml b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.toolchain.plugins.GppCompilerPlugin.xml
new file mode 100644
index 0000000..659d719
--- /dev/null
+++ b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.toolchain.plugins.GppCompilerPlugin.xml
@@ -0,0 +1,38 @@
+<!--
+ ~ Copyright 2013 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ 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.
+ -->
+
+<section>
+ <section>
+ <title>Properties</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+ <section>
+ <title>Methods</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.nativecode.toolchain.plugins.MicrosoftVisualCppPlugin.xml b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.toolchain.plugins.MicrosoftVisualCppPlugin.xml
new file mode 100644
index 0000000..659d719
--- /dev/null
+++ b/subprojects/docs/src/docs/dsl/org.gradle.nativecode.toolchain.plugins.MicrosoftVisualCppPlugin.xml
@@ -0,0 +1,38 @@
+<!--
+ ~ Copyright 2013 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ 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.
+ -->
+
+<section>
+ <section>
+ <title>Properties</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+ <section>
+ <title>Methods</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.plugins.ide.idea.model.IdeaProject.xml b/subprojects/docs/src/docs/dsl/org.gradle.plugins.ide.idea.model.IdeaProject.xml
index a5dde5f..fc85d08 100644
--- a/subprojects/docs/src/docs/dsl/org.gradle.plugins.ide.idea.model.IdeaProject.xml
+++ b/subprojects/docs/src/docs/dsl/org.gradle.plugins.ide.idea.model.IdeaProject.xml
@@ -11,7 +11,7 @@
</thead>
<tr>
<td>modules</td>
- <td><literal>project.allprojects*idea.module</literal></td>
+ <td><literal>project.allprojects.idea.module</literal></td>
<td/>
</tr>
<tr>
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.testing.jacoco.plugins.JacocoPluginExtension.xml b/subprojects/docs/src/docs/dsl/org.gradle.testing.jacoco.plugins.JacocoPluginExtension.xml
new file mode 100644
index 0000000..b846737
--- /dev/null
+++ b/subprojects/docs/src/docs/dsl/org.gradle.testing.jacoco.plugins.JacocoPluginExtension.xml
@@ -0,0 +1,50 @@
+<!--
+ ~ Copyright 2013 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ 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.
+ -->
+
+<section>
+ <section>
+ <title>Properties</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ <td>Default</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>toolVersion</td>
+ <td><literal>0.6.2.201302030002</literal></td>
+ </tr>
+ <tr>
+ <td>reportsDir</td>
+ <td><literal><replaceable>${project.reporting.baseDir}</replaceable>/jacoco</literal></td>
+ </tr>
+ </table>
+ </section>
+ <section>
+ <title>Methods</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>applyTo</td>
+ </tr>
+ </table>
+ </section>
+</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.testing.jacoco.plugins.JacocoTaskExtension.xml b/subprojects/docs/src/docs/dsl/org.gradle.testing.jacoco.plugins.JacocoTaskExtension.xml
new file mode 100644
index 0000000..e292057
--- /dev/null
+++ b/subprojects/docs/src/docs/dsl/org.gradle.testing.jacoco.plugins.JacocoTaskExtension.xml
@@ -0,0 +1,77 @@
+<!--
+ ~ Copyright 2013 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ 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.
+ -->
+
+<section>
+ <section>
+ <title>Properties</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>destinationFile</td>
+ </tr>
+ <tr>
+ <td>append</td>
+ </tr>
+ <tr>
+ <td>includes</td>
+ </tr>
+ <tr>
+ <td>excludes</td>
+ </tr>
+ <tr>
+ <td>excludeClassLoaders</td>
+ </tr>
+ <tr>
+ <td>sessionId</td>
+ </tr>
+ <tr>
+ <td>dumpOnExit</td>
+ </tr>
+ <tr>
+ <td>output</td>
+ </tr>
+ <tr>
+ <td>address</td>
+ </tr>
+ <tr>
+ <td>port</td>
+ </tr>
+ <tr>
+ <td>classDumpFile</td>
+ </tr>
+ <tr>
+ <td>jmx</td>
+ </tr>
+ </table>
+ </section>
+ <section>
+ <title>Methods</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>getAsJvmArg</td>
+ </tr>
+ </table>
+ </section>
+</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.testing.jacoco.tasks.JacocoBase.xml b/subprojects/docs/src/docs/dsl/org.gradle.testing.jacoco.tasks.JacocoBase.xml
new file mode 100644
index 0000000..5374067
--- /dev/null
+++ b/subprojects/docs/src/docs/dsl/org.gradle.testing.jacoco.tasks.JacocoBase.xml
@@ -0,0 +1,45 @@
+<!--
+ ~ Copyright 2013 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ 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.
+ -->
+
+<section>
+ <section>
+ <title>Properties</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ <td>Default with <literal>jacoco</literal> plugin</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>jacocoClasspath</td>
+ <td>
+ <literal>project.configurations.jacocoAnt</literal>
+ </td>
+ </tr>
+ </table>
+ </section>
+ <section>
+ <title>Methods</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ </table>
+ </section>
+</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.testing.jacoco.tasks.JacocoMerge.xml b/subprojects/docs/src/docs/dsl/org.gradle.testing.jacoco.tasks.JacocoMerge.xml
new file mode 100644
index 0000000..ac2d736
--- /dev/null
+++ b/subprojects/docs/src/docs/dsl/org.gradle.testing.jacoco.tasks.JacocoMerge.xml
@@ -0,0 +1,50 @@
+<!--
+ ~ Copyright 2013 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ 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.
+ -->
+
+<section>
+ <section>
+ <title>Properties</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ <td>Default with <literal>jacoco</literal> plugin</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>executionData</td>
+ <td/>
+ </tr>
+ <tr>
+ <td>destinationFile</td>
+ <td><filename><replaceable>buildDir</replaceable>/jacoco/<replaceable>task.name</replaceable>.exec</filename></td>
+ </tr>
+ </table>
+ </section>
+ <section>
+ <title>Methods</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>executionData</td>
+ </tr>
+ </table>
+ </section>
+</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/org.gradle.testing.jacoco.tasks.JacocoReport.xml b/subprojects/docs/src/docs/dsl/org.gradle.testing.jacoco.tasks.JacocoReport.xml
new file mode 100644
index 0000000..82e4548
--- /dev/null
+++ b/subprojects/docs/src/docs/dsl/org.gradle.testing.jacoco.tasks.JacocoReport.xml
@@ -0,0 +1,69 @@
+<!--
+ ~ Copyright 2013 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ 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.
+ -->
+
+<section>
+ <section>
+ <title>Properties</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ <td>Default with
+ <literal>jacoco</literal>
+ plugin
+ </td>
+ </tr>
+ </thead>
+ <tr>
+ <td>executionData</td>
+ <td/>
+ </tr>
+ <tr>
+ <td>sourceDirectories</td>
+ <td/>
+ </tr>
+ <tr>
+ <td>classDirectories</td>
+ <td/>
+ </tr>
+ <tr>
+ <td>additionalClassDirs</td>
+ <td/>
+ </tr>
+ <tr>
+ <td>additionalSourceDirs</td>
+ <td/>
+ </tr>
+ <tr>
+ <td>reports</td>
+ <td/>
+ </tr>
+ </table>
+ </section>
+ <section>
+ <title>Methods</title>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>executionData</td>
+ </tr>
+ </table>
+ </section>
+</section>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/dsl/plugins.xml b/subprojects/docs/src/docs/dsl/plugins.xml
index 8920812..680f878 100755
--- a/subprojects/docs/src/docs/dsl/plugins.xml
+++ b/subprojects/docs/src/docs/dsl/plugins.xml
@@ -73,4 +73,14 @@
<plugin id="jdepend" description="JDepend Plugin">
<extends targetClass="org.gradle.api.Project" id="jdepend" extensionClass="org.gradle.api.plugins.quality.JDependExtension"/>
</plugin>
+ <plugin id="jacoco" description="JaCoCo Plugin">
+ <extends targetClass="org.gradle.api.Project" id="jacoco" extensionClass="org.gradle.testing.jacoco.plugins.JacocoPluginExtension"/>
+ <extends targetClass="org.gradle.api.tasks.testing.Test" id="jacoco" extensionClass="org.gradle.testing.jacoco.plugins.JacocoTaskExtension"/>
+ </plugin>
+ <plugin id="cpp" description="C++ Plugin">
+ <extends targetClass="org.gradle.api.Project" id="toolChains" extensionClass="org.gradle.nativecode.base.ToolChainRegistry"/>
+ <extends targetClass="org.gradle.api.Project" id="executables" extensionClass="org.gradle.nativecode.base.ExecutableContainer"/>
+ <extends targetClass="org.gradle.api.Project" id="libraries" extensionClass="org.gradle.nativecode.base.LibraryContainer"/>
+ <extends targetClass="org.gradle.api.Project" id="binaries" extensionClass="org.gradle.language.base.BinaryContainer"/>
+ </plugin>
</plugins>
diff --git a/subprojects/docs/src/docs/release/content/script.js b/subprojects/docs/src/docs/release/content/script.js
index 0d6d9d3..9978212 100644
--- a/subprojects/docs/src/docs/release/content/script.js
+++ b/subprojects/docs/src/docs/release/content/script.js
@@ -1,25 +1,3 @@
-/*
- * TipTip
- * Copyright 2010 Drew Wilson
- * www.drewwilson.com
- * code.drewwilson.com/entry/tiptip-jquery-plugin
- *
- * Version 1.3 - Updated: Mar. 23, 2010
- *
- * This Plug-In will create a custom tooltip to replace the default
- * browser tooltip. It is extremely lightweight and very smart in
- * that it detects the edges of the browser window and will make sure
- * the tooltip stays within the current window size. As a result the
- * tooltip will adjust itself to be displayed above, below, to the left
- * or to the right depending on what is necessary to stay within the
- * browser window. It is completely customizable as well via CSS.
- *
- * This TipTip jQuery plug-in is dual licensed under the MIT and GPL licenses:
- * http://www.opensource.org/licenses/mit-license.php
- * http://www.gnu.org/licenses/gpl.html
- */
-(function($){$.fn.tipTip=function(options){var defaults={activation:"hover",keepAlive:false,maxWidth:"200px",edgeOffset:3,defaultPosition:"bottom",delay:400,fadeIn:200,fadeOut:200,attribute:"title",content:false,enter:function(){},exit:function(){}};var opts=$.extend(defaults,options);if($("#tiptip_holder").length<=0){var tiptip_holder=$('<div id="tiptip_holder" style="max-width:'+opts.maxWidth+';"></div>');var tiptip_content=$('<div id="tiptip_content"></div>');var tiptip_arrow=$('<div [...]
-
$(function() {
function elementInViewport(el) {
var rect = el.getBoundingClientRect();
@@ -121,11 +99,11 @@ $(function() {
"Retrieving the known issue information for @versionBase@",
function(i) {
if (i > 0) {
- return i + " issues have been fixed in Gradle @versionBase at .";
+ return i + " issues are known to affect Gradle @versionBase at .";
} else {
return "There are no known issues of Gradle @versionBase@ at this time.";
}
- }
+ }
);
$("section.major-detail").each(function() {
diff --git a/subprojects/docs/src/docs/release/notes-template.md b/subprojects/docs/src/docs/release/notes-template.md
index 18a21d5..438cd29 100644
--- a/subprojects/docs/src/docs/release/notes-template.md
+++ b/subprojects/docs/src/docs/release/notes-template.md
@@ -19,18 +19,6 @@ The following are the features that have been promoted in this Gradle release.
## Fixed issues
-## Incubating features
-
-Incubating features are intended to be used, but not yet guaranteed to be backwards compatible.
-By giving early access to new features, real world feedback can be incorporated into their design.
-See the User guide section on the “[Feature Lifecycle](userguide/feature_lifecycle.html)” for more information.
-
-The following are the new incubating features or changes to existing incubating features in this Gradle release.
-
-<!--
-### Example incubating feature
--->
-
## Deprecations
Features that have become superseded or irrelevant due to the natural evolution of Gradle become *deprecated*, and scheduled to be removed
@@ -53,7 +41,7 @@ The following are the newly deprecated items in this Gradle release. If you have
We would like to thank the following community members for making contributions to this release of Gradle.
<!--
-* Some Person - fixed some issue (GRADLE-1234)
+* [Some person](https://github.com/some-person) - fixed some issue (GRADLE-1234)
-->
We love getting contributions from the Gradle community. For information on contributing, please see [gradle.org/contribute](http://gradle.org/contribute).
diff --git a/subprojects/docs/src/docs/release/notes.md b/subprojects/docs/src/docs/release/notes.md
index a4aaf63..2399c32 100644
--- a/subprojects/docs/src/docs/release/notes.md
+++ b/subprojects/docs/src/docs/release/notes.md
@@ -1,390 +1,347 @@
-Continuing on with the performance improvements delivered in recent Gradle versions, 1.5 brings wide reaching optimizations to dependency resolution as well as important
-improvements to two recent features; configure-on-demand and parallel execution.
-Gradle continues to embrace the challenges of large scale build automation. Along with the performance improvements comes the usual mix of new features, bug fixes, usability improvements and refinements.
-
-The dependency resolve rule feature introduced in 1.4 gains new capabilities in 1.5. Trouble dependencies can now be completely substituted at resolution time which enables solving
-some very tricky issues with complex dependency graphs. On the publication side, the new (incubating) Maven and Ivy publishing plugins gain new capabilities making them able
-to solve more publishing use cases with elegance.
-
-A very exciting trend is the increase in code and documentation contributions from the community, both large and small. Some very useful new features such as the "build dashboard"
-and "distributions" plugins added in this release, to name a few, came by way of contribution. If you'd like to get involved and contribute to Gradle, a great place to
-start is [gradle.org/contribute](http://www.gradle.org/contribute).
-
-The Gradle team is also excited to announce the first ever [“Gradle Summit”](http://gradlesummit.com/) (Sponsored by [Gradleware](http://gradleware.com/)),
-held June 13th - 14th in Santa Clara, California. The summit will be two fully packed days of technical sessions given by Gradle core developers ranging from introductory
-to deep dive as well as informational sessions by several large organizations on how they get the most out of Gradle. In between sessions there'll be plenty of opportunity
-for talking to other Gradle users and the Gradle development team. This is an event not to miss.
-Registration is [now open](http://gradlesummit.com/conference/santa_clara/2013/06/gradle/event_register).
-
-Read on for more details on why you should upgrade to Gradle 1.5. As always, please share your feedback and experiences with Gradle 1.5 via the Gradle Forums.
-## New and noteworthy
-
-Here are the new features introduced in this Gradle release.
-
-### Performance improvements
-
-This release brings performance improvements for JUnit and TestNG test execution as well as dependency resolution improvements for all builds that use dependency resolution.
+Gradle 1.8 continues the focus on performance in recent Gradle releases. In this release, dependency resolution is more efficient in its use of memory. This means
+faster builds, in particular for really large builds. Also, the tooling API adds new features that allows integrations such as IDE import to work much more quickly -
+expect to see performance improvements in Android Studio soon.
-#### Test execution performance
+This release of Gradle adds support for more native languages, with support for C and Assembler joining C++. Support for native languages in general is an area
+under heavy development and there are many more improvements planned in upcoming releases.
-Test execution has been further optimized in this release, continuing on the work in Gradle 1.4. The test report is now generated more efficiently, so that it take less
-time and heap space to generate the HTML report. In addition, for those projects that use the TestNG framework, the test JVM now starts more quickly, meaning that test
-execution starts earlier than it did in previous Gradle releases.
+Dependency management is now more flexible with the introduction of component meta-data rules. These rules allow you to fine-tune dependency meta-data in your
+build or plugins.
-#### Dependency resolution performance
+Gradle 1.8 contains many contributions from developers outside the core development team. Thank you to all who contributed to Gradle 1.8.
-Gradle's [dependency cache](userguide/dependency_management.html#sec:dependency_cache) is multi process safe, which requires the use of locking mechanisms.
-Improvements to the way the locks are utilised in this release have increased the dependency resolution speed by up to 30%
-for builds that use local repositories or maven local.
-Builds that don't use local repositories should also exhibit slightly faster dependency resolution.
-Every build that resolves dependencies benefits from this improvement.
+For more information on what's new in Gradle 1.8, please read on. As always, please share your feedback and experiences with Gradle 1.8 via the
+[Gradle Forums](http://forums.gradle.org).
-### Substituting dependencies via dependency resolve rules (i)
-
-Gradle 1.4 [introduced the ability](http://www.gradle.org/docs/1.4/release-notes#dependency-resolve-rules) to dynamically change the version of a dependency to be resolved via dependency resolve rules.
-It is now possible to change the group, name and/or version of a requested dependency, allowing a dependency to be substituted with a completely
-different dependency during resolution.
-
- configurations.all {
- resolutionStrategy.eachDependency { DependencyResolveDetails details ->
- if (details.requested.name == 'groovy-all') {
- details.useTarget group: details.requested.group, name: 'groovy', version: details.requested.version
- }
- }
- }
-
-Dependency resolve rules can now be used to solve some interesting dependency resolution problems:
-
-- Substituting an alternative implementation for some module. For example, replace all usages of `log4j` with a compatible version of `log4j-over-slf4j`.
-- Dealing with conflicting implementations of some module. For example, replace all usages of the various `slf4j` bindings with `slf4j-simple`.
-- Dealing with conflicting packaging of some module. For example, replace all usages of `groovy-all` with `groovy`.
-- Dealing with modules that have changed their (group, module) identifier. For example, replace `ant:ant:*` with `org.apache.ant:ant:1.7.0` and let conflict resolution take care of the rest.
-- Substituting different implementations at different stages. For example, substitute all servlet API dependencies with `'javax.servlet:servlet-api:2.4'` at compile time and the jetty implementation at test runtime.
+## New and noteworthy
-For more information, including more code samples, please refer to [the user guide](userguide/dependency_management.html#sec:dependency_resolve_rules).
+Here are the new features introduced in this Gradle release.
-### New Sonar Runner plugin (i)
+### Improved performance and memory consumption
-Gradle 1.5 ships with a new `sonar-runner` plugin that is set to replace the existing Sonar plugin. As its name indicates,
-the new plugin is based on the [Sonar Runner](http://docs.codehaus.org/display/SONAR/Analyzing+with+Sonar+Runner),
-the new and official way to integrate with Sonar. Unlike the old Sonar plugin, the new Sonar Runner plugin
-is compatible with the latest Sonar versions (3.4 and above). To learn more, check out the [Sonar Runner Plugin](userguide/sonar_runner_plugin.html)
-chapter in the Gradle user guide, and the `sonarRunner` samples in the full Gradle distribution.
+Gradle 1.8 uses less heap than previous versions. The less heap Gradle uses, the less expensive garbage collection is, and the faster your builds are.
-### IDEA plugin is now Scala aware
+Some builds, particularly very large builds, should see some significant improvements in performance with Gradle 1.8.
-When the IDEA plugin encounters a Scala project, it will now add additional configuration to make the
-project compile in IntelliJ IDEA out of the box. In particular, the plugin adds a Scala facet and
-a Scala compiler library that matches the Scala version used on the project's class path.
+#### Serialization of the resolution results.
-### Configure-on-demand improvements (i)
+The heart of this performance improvement is not creating the full dependency resolution results unless they are required.
+These results consume a lot of memory in large builds.
+Instead, the information is streamed to disk during the resolution process and the results assembled in heap only when requested.
+As this information is usually not needed, typical builds will get faster and all builds will use less heap.
-Gradle 1.4 introduced a [new operational mode called “configure-on-demand”](http://www.gradle.org/docs/1.4/release-notes#improved-scalability-via-configuration-on-demand) designed
-to improve Gradle performance on large projects. This release brings the following improvements to this new feature:
+Note that the results API has not changed and is fully backwards compatible with previous Gradle versions.
-* [Tooling API](userguide/embedding.html) compatibility.
-* [buildSrc](userguide/organizing_build_logic.html#sec:build_sources) is now fully supported.
-* Task dependencies declared via task path are now supported.
+### Component metadata rules
-Enabling this new mode is now more convenient. It can be enabled at invocation time via the new `--configure-on-demand` flag, or via the `org.gradle.configureondemand` project property.
-The project property can be set permanently for a project, or permanently for a user just like other [build settings](userguide/build_environment.html#sec:gradle_configuration_properties).
+In Gradle, a dependency is resolved to a component (often also called a _module_).
+Each component has metadata associated with it, such as 'group', 'name', 'version', and a set of dependencies.
+Typically, this metadata is specified in a module descriptor (Ivy file or Maven POM).
+Component metadata rules allow you to manipulate this metadata from within the build script or a plugin.
-For example, by adding a `gradle.properties` file to root of the project with the following content Gradle will always use configure-on-demand mode for the project.
+Component metadata rules are another instrument for customizing dependency resolution (building on _dependency resolve rules_ introduced in Gradle 1.4).
+These rules are evaluated during dependency resolution, immediately after component metadata has be retrieved from a repository.
+Using a rule, you are able to change the raw component metadata, overriding or tweaking the values to suit your build.
- #gradle.properties file
- org.gradle.configureondemand=true
+As of Gradle 1.8, only two pieces of metadata can be manipulated for a component: the *status scheme*, and the *status*.
+The former describes the increasing levels of maturity that a component may transition through over a series of versions.
+The latter describes the component's current maturity, and needs to correspond to one of the values listed in the component's status scheme.
-For more information on configure-on-demand please consult [the user guide](userguide/multi_project_builds.html#sec:configuration_on_demand).
+A component's status scheme defaults to `integration`, `milestone`, `release` (in that order). The status defaults to `integration` for Ivy modules
+(if not specified in the Ivy file) and Maven snapshot modules, and to `release` for Maven modules other than snapshots.
-### Parallel execution improvements (i)
+What can a status (scheme) be used for? Most notably, a dependency can request the highest version with at least the stated status:
-Gradle 1.2 introduced a [parallel execution](userguide/multi_project_builds.html#sec:parallel_execution) mode for multi-project builds.
-This release brings significantly improved utilisation of the parallel workers.
+ dependencies {
+ // the highest version with status milestone or release
+ compile "org.foo:bar:latest.milestone
+ }
-Previously, workers where statically assigned to projects and often waited for the upstream dependencies to be built.
-This caused workers to stay idle when there was work they could be doing. The distribution of work is now more dynamic which has resulted in highly parallelizable builds building up to 30% faster.
+Ivy users will be familiar with this feature. 'Latest' version resolution also works together with custom status schemes:
-It is also now possible to enable parallel building via a [build setting](userguide/build_environment.html#sec:gradle_configuration_properties).
-For example, by adding a `gradle.properties` file to root of the project with the following content Gradle will always build the project in parallel.
+ dependencies {
+ // the highest version with status silver, gold, or platinum
+ compile "org.foo:bar:latest.silver"
+ components {
+ eachComponent { ComponentMetadataDetails details ->
+ if (details.id.group == "org.foo") {
+ // declare a custom status scheme
+ details.statusScheme = ["bronze", "silver", "gold", "platinum"]
+ }
+ }
+ }
+ }
- //gradle.properties file
- org.gradle.parallel=true
+For API details, see [`ComponentMetadataHandler`](javadoc/org/gradle/api/artifacts/dsl/ComponentMetadataHandler.html).
+Future Gradle versions will likely allow more pieces of component metadata to be manipulated.
-### New distribution plugin (i)
+### Create native libraries and executables from C and Assembler sources (i)
-Thanks to a contribution from [Sébastien Cogneau](https://github.com/scogneau), a new `distribution` plugin has been added. This plugin adds general-purpose for support bundling and installing distributions.
+With Gradle 1.8, it is now possible to include 'C' and 'Assembler' source files to create a native library or executable. The C sources are compiled
+with relevant compiler settings, and Assembler sources are translated directly to object files by the assembler.
-This plugin adds a `main` distribution, and you can add additional distributions. For each distribution, tasks are added to create a ZIP or TAR file for the distribution and
-to install the distribution.
+Including C and Assembler sources in your project is straightforward. Whereas C++ sources are contained in a 'cpp' source directory,
+C source files should be located in a 'c' directory and Assembler source files in a 'asm' directory. These directory locations are by convention, and
+can be updated in your build script.
-You can define multiple distributions:
+Here's an example of how you can customize which source files and directories to include:
- distributions {
- enterprise
- community
+ sources {
+ main {
+ c {
+ source {
+ srcDirs "sourcefiles"
+ include "**/*.c"
+ }
+ exportedHeaders {
+ srcDirs "includes"
+ }
+ }
+ asm {
+ source {
+ srcDirs "sourcefiles", "assemblerfiles"
+ include "**/*.s"
+ }
+ }
+ }
}
-To build the additional distributions you can run the generated `Zip` tasks `enterpriseDistZip` and `communityDistZip`. For more information, please consult the
-[user guide](userguide/distribution_plugin.html).
-
-### Improved Java library distribution plugin (i)
+Note that support for building native binaries is under active development, and this functionality is very likely to be changed and improved in upcoming
+releases.
-The Java library distribution plugin now extends the newly introduced distribution plugin. Thanks to this, you can now create tar files and install Java library distributions.
+### New duplicate file handling strategies
-For more information, please consult the [user guide](userguide/javaLibraryDistribution_plugin.html).
+Gradle 1.7 introduced some strategies for dealing with duplicates when copying files and building archives such as ZIPs and JARs. The Gradle 1.8 release adds two
+more:
-### Improved usability of project dependencies
+* `warn`, which includes the duplicates in the result but logs a warning.
+* `fail`, which fails when attempting to include duplicate files in the result.
-Project dependencies at configuration time are now fully supported.
-Prior to this change, any resolution of a project dependency at configuration time may have led to confusing behavior as the target project may not have been configured yet.
-Now the resolution of the project dependency implies configuration of the target project.
-This means that the order in which projects are configured may now be different (i.e. it will be correct).
-This change should not cause any trouble in existing builds and it fixes up the confusing behavior with project dependencies.
+Thanks to [Kyle Mahan](https://github.com/kylewm) for this contribution.
-### Improvements to the new '`maven-publish`' and '`ivy-publish`' plugins (i)
+### Tooling API
-The '`maven-publish`' and '`ivy-publish`' plugins gain new features and capabilities in this Gradle release.
+This release includes a number of improvements to the tooling API. The tooling API is used by tools such as IDEs, CI servers and other
+applications to execute and query Gradle builds. You can also use the tooling API to embed Gradle in your own applications.
-#### Easy publication of software components
+* Information about the build script for a project is now available via the `GradleProject` tooling model.
+* A new `GradleBuild` model provides basic information about a Gradle build without requiring the entire build to be configured,
+ making it a more efficient alternative to the `GradleProject` model.
+* Batch operations can be performed in a single request using the new `BuildAction` interface. This means much faster tooling integrations.
-Gradle 1.5 introduces the concept of a “Software Component”, which defines something that can be produced by a Gradle project such as a Java library or a web application.
-Both the '`ivy-publish`' and '`maven-publish`' plugins are component-aware, simplifying the process of publishing a module. The component defines the set of artifacts and dependencies for publishing.
+### Early preparations for Gradle 2.0
-Presently, the set of components available for publishing is limited to '`java`' and '`web`', added by the '`java`' and '`war`' plugins respectively. In the future it will be possible to
-create new components and new component types.
+This release sees the start of initial preparations for a Gradle 2.0 release next year. At this stage, this means some cleanup of API and
+deprecating some old features, for removal in Gradle 2.0. You'll find more details below.
-Publishing the '`web`' component will result in the war file being published with no runtime dependencies (dependencies are bundled in the war):
+Removing unwanted features allows the implementation of Gradle to be simplified. In the long term this means fewer bugs, more features and faster builds for you.
- apply plugin: 'war'
- apply plugin: 'maven-publish'
+Please note that we'll continue to follow our usual feature lifecycle for removing features.
+No supported feature or syntax will be removed without a significant period of prior deprecation.
- group = 'group'
- version = '1.0'
+Almost every deprecated feature has a non-deprecated replacement and this is documented in the deprecation descriptions below.
+However, some deprecated features do not have a replacement. If you find a feature that you use has been deprecated,
+and there doesn't seem to be a replacement for it that you can use , please let us know as soon as possible via the
+[forums](http://forums.gradle.org).
- // … declare dependencies and other config on how to build
-
- publishing {
- repositories {
- maven { url 'http://mycompany.org/mavenRepo' }
- ivy { url 'http://mycompany.org/ivyRepo' }
- }
- publications {
- mavenWeb(MavenPublication) {
- from components.web
- }
- ivyWeb(IvyPublication) {
- from components.java // Include the standard java artifacts
- }
- }
- }
-
-#### Publishing custom artifacts
-
-This release introduces the ability to customize the set of artifacts to publish to a Maven repository or an Ivy repository.
-This gives complete control over which artifacts are published, and the classifier/extension used to publish them.
-
-Due to differences in the capabilities of Ivy vs Maven repositories, the DSL is slightly different for each repository format.
+## Fixed issues
- apply plugin: 'java'
- apply plugin: 'maven-publish'
- apply plugin: 'ivy-publish'
+## Deprecations
- group = 'group'
- version = '1.0'
+Features that have become superseded or irrelevant due to the natural evolution of Gradle become *deprecated*, and scheduled to be removed
+in the next major Gradle version (Gradle 2.0). See the User guide section on the “[Feature Lifecycle](userguide/feature_lifecycle.html)” for more information.
- // … declare dependencies and other config on how to build
+The following are the newly deprecated items in this Gradle release. If you have concerns about a deprecation, please raise it via the [Gradle Forums](http://forums.gradle.org).
- task sourceJar(type: Jar) {
- from sourceSets.main.allJava
- classifier "source"
+### Support for using Ivy `DependencyResolver` implementations
+
+For several years (since Gradle 1.0-milestone-3), there have been two ways that you can define an Ivy repository for Gradle to use. The first, and preferred, way is to
+use Gradle's native `repositories.ivy { }` DSL. The second way was to register an Ivy `DependencyResolver` implementation using the `repositories.add()` method.
+There have been a lot of improvements to dependency resolution in Gradle over the years, but this native support for Ivy classes makes it
+difficult to continue this evolution.
+
+Because of this, support for using Ivy `DependencyResolver` instances will be discontinued in Gradle 2.0.
+*Please note that Gradle will continue to support Ivy repositories through its native DSL.*
+
+The following methods have been deprecated and will be removed in Gradle 2.0:
+
+* The `RepositoryHandler.mavenRepo()` method has been deprecated. You should use the `maven()` method instead:
+* The `ArtifactRepositoryContainer.add(DependencyResolver)` method. You should use one of the other repository methods instead.
+* The `ArtifactRepositoryContainer.addFirst(Object)` method. You should use the `addFirst(ArtifactRepository)` instead.
+* The `ArtifactRepositoryContainer.addBefore()` and `addAfter()` methods. There is no replacement for these methods.
+
+<table>
+ <tr><th>Gradle 1.7</th><th>Gradle 1.8</th></tr>
+ <tr>
+ <td>
+ <pre>repositories {
+ mavenRepo url: 'http://my.server/'
+ add(new org.apache.ivy.plugins.resolver.FileSystemResolver()) {
+ addArtifactPattern('/some/dir/[organisation]/[module]-[revision].[ext]')
+}</pre>
+ </td>
+ <td>
+ <pre>repositories {
+ maven {
+ url 'http://my.server/'
}
-
- publishing {
- repositories {
- maven { url 'http://mycompany.org/mavenRepo' }
- ivy { url 'http://mycompany.org/ivyRepo' }
- }
- publications {
- mavenCustom(MavenPublication) {
- from components.java // Include the standard java artifacts
- artifact sourceJar {
- classifier "source"
- }
- artifact("project-docs.htm") {
- classifier "docs"
- extension "html"
- builtBy myDocsTask
- }
- }
- ivyCustom(IvyPublication) {
- from components.java // Include the standard java artifacts
- artifact(sourceJar) {
- type "source"
- conf "runtime"
- classifier "source"
- }
- artifact("project-docs.htm") {
- classifier "docs"
- extension "html"
- builtBy myDocsTask
- }
- }
- }
+ ivy {
+ artifactPattern '/some/dir/[organisation]/[module]-[revision].[ext]'
}
+}</pre>
+ </td>
+ </tr>
+</table>
-Be sure to check out the DSL reference for [MavenPublication](dsl/org.gradle.api.publish.maven.MavenPublication.html) and [IvyPublication](dsl/org.gradle.api.publish.ivy.IvyPublication.html)
-for complete details on how the set of artifacts can be customized.
-
-For more information about using the new '`maven-publish`' and '`ivy-publish`' plugins in general, please consult the user guide ([maven](userguide/publishing_maven.html)) ([ivy](userguide/publishing_ivy.html)).
-
-#### Generate POM file without publishing
-
-POM file generation has been moved into a separate task, so that it is now possible to generate the POM file without actually publishing your project. All details of
-the publishing model are still considered in POM generation, including `components`, custom `artifacts`, and any modifications made via `pom.withXml`.
+### Using `GradleLauncher` to run Gradle builds
-The task for generating the POM file is of type [`GenerateMavenPom`](dsl/org.gradle.api.publish.maven.tasks.GenerateMavenPom.html), and is given a name based on the name
-of the publication: `generatePomFileFor<publication-name>Publication`. So in the above example where the publication is named '`mavenCustom`',
-the task will be named `generatePomFileForMavenCustomPublication`.
+There are currently 3 ways you can programmatically run a build. The first, and recommended, way is to use the Gradle tooling API. You can also use
+the `GradleBuild` task type. The third way is to use the `GradleLauncher` API. The `GradleLauncher` API is now deprecated and will be removed in Gradle
+2.0.
-#### Full support for Unicode in publication identifiers
+* The `GradleLauncher` class has been deprecated and will be removed in Gradle 2.0.
+* The `GradleLauncher.newInstance()` and `createStartParameter()` methods have been deprecated and will be removed in Gradle 2.0.
-Where supported by the underlying metadata format, Gradle will now handle any valid Unicode character in module group, name and version as well as artifact name, extension and classifier.
+### Unused constants on `ArtifactRepositoryContainer`
-The only values that are explicitly prohibited are '\\', '/' and any ISO control character. Supplied values are validated early in publication.
+A number of constants on `ArtifactRepositoryContainer` are no longer used. These have been deprecated and will be removed in Gradle 2.0.
-A couple of caveats to the Unicode support:
+### Unused classes
-- Maven restricts '`groupId`' and '`artifactId`' to a limited character set (`[A-Za-z0-9_\\-.]+`) and Gradle enforces this restriction.
-- Certain repositories will not be able to handle all supported characters. For example, the '`:`' character cannot be used
- as an identifier when publishing to a filesystem-backed repository on Windows.
+The following classes will be removed in Gradle 2.0. They are no longer used:
-### Support for Ivy dynamic resolve mode (i)
+* `IllegalOperationAtExecutionTimeException`
+* `AntJavadoc`
-It is now possible to enable the equivalent of Ivy's _dynamic resolve_ mode when resolving dependencies. This is only supported for Ivy repositories.
+### Open API classes
-See the [user guide](userguide/dependency_management.html#ivy_dynamic_resolve_mode) for examples and further details.
+The Open API has been deprecated for over two years (since Gradle 1.0-milestone-4) and is due to be removed in Gradle 2.0. The entry points to the
+Open API were marked deprecated at that time.
-### New build dashboard Plugin (i)
+To make the deprecation of the Open API clearer, all of the Open API classes are now marked as deprecated, in addition to the entry points. All of the
+Open API classes will be removed in Gradle 2.0.
-Thanks to a contribution from [Marcin Erdmann](https://github.com/erdi), a new `build-dashboard` plugin has been added. This plugin adds a task to projects to generate a build dashboard HTML report which contains
-references to all reports that were generated during the build. In the following example, the `build-dashboard` plugin is added to a project which has also the `groovy` and
-the `codenarc` plugin applied:
+<!--
+### Example deprecation
+-->
- apply plugin: 'groovy'
- apply plugin: 'build-dashboard'
- apply plugin: 'codenarc'
+## Potential breaking changes
-By running the `buildDashboard` task after other tasks that generate reports (e.g. by running `gradle check buildDashboard`), the generated build dashboard contains links to the
-`codenarc` reports. This version of the build dashboard does not include links to test reports. This plugin is in the early stages of development and will be significantly improved in future Gradle releases.
+### Upgraded to Ant 1.9.2
-More information on the `build-dashboard` plugin can be found in the [user guide](userguide/buildDashboard_plugin.html).
-
-## Fixed issues
+The version of Ant used by Gradle has been upgraded to Ant 1.9.2. This should be backwards compatible.
-## Deprecations
+### Changes in task arguments evaluation
-Features that have become superseded or irrelevant due to the natural evolution of Gradle become *deprecated*, and scheduled to be removed
-in the next major Gradle version (Gradle 2.0). See the User guide section on the “[Feature Lifecycle](userguide/feature_lifecycle.html)” for more information.
+All arguments passed for task creation are evaluated to be valid. In earlier Gradle versions, a typo in the arguments was silently ignored.
+The following snippet will now fail with an error message, giving a hint that 'Type' is not a valid argument.
-The following are the newly deprecated items in this Gradle release. If you have concerns about a deprecation, please raise it via the [Gradle Forums](http://forums.gradle.org).
+<pre>
+ task myCopy(Type: copy) {
+ from "..."
+ into "..."
+ }
+}</pre>
-### `ArtifactRepositoryContainer.getResolvers()`
-This method exposes internal implementation details that will be subject to change in the future. Its use should be avoided.
+### Changes to incubating C++ support
-## Potential breaking changes
+* Renamed task class `AssembleStaticLibrary` to `CreateStaticLibrary`, with the default task instance also being renamed from `assemble${StaticLibraryName}` to
+ `create${StaticLibraryName}`
+* Renamed plugin class `BinariesPlugin` to `NativeBinariesPlugin`.
+* Without any defined tool chains, only a single default tool chain is added to the `toolChains` list. When relying on a default tool chain,
+binary configuration should be applied based on the tool chain type instead of comparing with a particular tool chain:
-### Changes to incubating Maven publishing support
+<pre>
+ binaries.all {
+ if (toolChain in VisualCpp) {
+ // Visual C++ configuration
+ }
+ if (toolChain in Gcc) {
+ // GCC configuration
+ }
+ }
+</pre>
+
+* The DSL for defining C++ source sets has changed, with the `cpp` extension being removed. This change makes the C++ plugin DSL consistent with
+the new Gradle DSL for multiple source sets.
+
+<table>
+ <tr><th>Gradle 1.7</th><th>Gradle 1.8</th></tr>
+ <tr>
+ <td>`cpp.sourceSets.main`</td>
+ <td>`sources.main.cpp`</td>
+ </tr>
+ <tr>
+ <td><pre>cpp {
+ sourceSets {
+ main {
+ source {
+ srcDirs "..."
+ exportedHeaders "..."
+ }
+ }
+ }
+}</pre>
+ </td>
+ <td>
+<pre>sources {
+ main {
+ cpp {
+ source {
+ srcDirs "..."
+ exportedHeaders "..."
+ }
+ }
+ }
+}</pre>
+ </td>
+ </tr>
+</table>
-Breaking changes have been made to the incubating '`maven-publish`' plugin, which provides an alternative means to publish to Maven repositories.
+### The order of resolved files and artifacts has changed
-- A MavenPublication must be explicitly added to the `publications` container; no publication is added implicitly by the `maven-publish` plugin.
- - If no `MavenPublication` is configured then nothing will be published.
-- A `MavenPublication` does not include any artifacts or dependencies by default; these must be added directly or via a `SoftwareComponent`.
- - If no artifacts are configured, a Maven POM file will be published with no artifacts or dependencies declared.
-- The `groupId`, `artifactId` and `version` in the published pom cannot be changed via `MavenPom.withXml()`:
- it was previously possible change these values, but any interproject dependency would not pick up these changes.
- - In the future Gradle will provide a robust mechanism for modifying publication identity prior to publication.
-- Identifiers used in Maven publications (`groupId`, `artifactId`, `version`, `ext`, `classifier`) have new character restrictions:
- these identifiers may not contain '`/`', '`\`' or any ISO Control Characters. Using these values generally made it impossible to resolve these modules, so this is now prevented
- at the time of publication.
- - `groupId` and `artifactId` are further restricted to "`[A-Za-z0-9_\-.]+`": this is a Maven restriction, so it is enforced at the time of publication.
-- The `GenerateMavenPom` task for a publication is not created until the publishing extension is first accessed. Any attempt to configure a `GenerateMavenPom` task
- should be enclosed within a `publishing` block.
-- Once the publishing extension is accessed as a property, it is no longer possible to further configure the extension using a `publishing` block.
+The order of resolved artifacts and resolved files has changed. This change is transparent to the vast majority of builds.
-Be sure to check out the [Maven Publishing User Guide Chapter](userguide/publishing_maven.html) and the [MavenPublication DSL reference](dsl/org.gradle.api.publish.maven.MavenPublication.html)
-for complete description and examples of the new Maven Publishing support.
+This change was necessary to implement important performance improvements mentioned above, and may impact the order of files of a
+resolved configuration, consequently, it may impact some classpaths.
-### Changes to incubating Ivy publishing support
+### Changes to handling of Ivy `DependencyResolver` implementations
-Breaking changes have been made to the incubating '`ivy-publish`' plugin, which provides an alternative means to publish to Ivy repositories.
+In order to improve performance and heap usage during dependency resolution, this release includes some internal changes to the way meta-data is
+parsed. If you use an Ivy `DependencyResolver` implementation to define repositories, meta-data parsing is now delegated to Ivy instead of
+using Gradle's parser implementations. This means that these resolvers will no longer take advantage of performance improvements in Gradle's
+meta-data parsing and handling. However, the changes should generally be backwards compatible.
-- An `IvyPublication` must be explicitly added to the `publications` container; no publication is added implicitly by the `ivy-publish` plugin.
- - If no `IvyPublication` is configured then nothing will be published.
-- An `IvyPublication` does not include any artifacts or dependencies by default; these must be added directly or via a `SoftwareComponent`.
- - If no artifacts are configured, an `ivy.xml` file will be published with no artifacts or dependencies declared.
-- The `organisation`, `name` and `revision` cannot be changed via `IvyDescriptor.withXml()`:
- it was previously possible to do this, although it did not change the actual identity of the published module.
- - In the future Gradle will provide a robust mechanism for modifying publication identity prior to publication.
-- Identifiers in ivy modules (`organisation`, `module`, `revision`) and artifacts (`name`, `ext`, `type`, `classifier`) have new character restrictions:
- these identifiers may not contain '`/`', '`\`' or any ISO Control Characters. Using these values generally made it impossible to resolve these modules, so this is now prevented
- at the time of publication.
-- Removed `GenerateIvyDescriptor.xmlAction` property. The `ivy.descriptor.withXml()` method provides a way to customise the generated module descriptor.
-- The `GenerateIvyDescriptor` task for a publication is not created until the publishing extension is first accessed. Any attempt to configure a `GenerateIvyDescriptor`
- should be enclosed within a `publishing` block.
-- Once the publishing extension is accessed as a property, it is no longer possible to further configure the extension using a `publishing` block.
+Note that using Ivy `DependencyResolver` implementations is deprecated, and we recommend that you use Gradle's repository implementations instead.
-Be sure to check out the [Ivy Publishing User Guide Chapter](userguide/publishing_ivy.html) and the [IvyPublication DSL reference](dsl/org.gradle.api.publish.ivy.IvyPublication.html)
-for complete description and examples of the new Ivy Publishing support.
+### Ivy `DependencyResolver` implementations returned by Gradle APIs no longer support `latestStrategy` methods
-### Project configuration order
+A select few Gradle APIs methods return an Ivy `DependencyResolver` implementation (e.g. `repositories.mavenRepo`).
+These returned `DependencyResolver` instances no longer support the following methods:
+`getLatestStrategy()`, `setLatestStrategy()`, `getLatest()`, `setLatest()`. Calling one of these methods will now throw an `UnsupportedOperationException`.
-Improving the usability of project dependencies (see the section above) might change the order in which projects are configured.
-This is not expected to cause problems in existing builds, but is mentioned for completeness.
+Note that all Gradle API methods that return an Ivy `DependencyResolver` implementation are deprecated, and we recommend that you use Gradle's repository implementations instead.
-### Optimized order of task execution in parallel execution mode
+## External contributions
-Parallel builds are now much faster due to better utilisation of parallel workers. However, this means that tasks may be executed in different order in parallel builds.
-This will not cause problems in a correctly [decoupled build](userguide/multi_project_builds.html#sec:decoupled_projects) but may bring problems to light in builds that are not properly decoupled.
+We would like to thank the following community members for making contributions to this release of Gradle.
-### Changes to the incubating Java library distribution plugin
+## Contributors
-The `distribution` extension that is added by the `java-library-distribution` plugin was removed. The `main` distribution is now accessible using the `distributions` extension:
+On behalf of the Gradle community, the Gradle development team would like to thank the following people who contributed to this version of Gradle:
- distributions {
- main {
- ...
- }
- }
+* [Kyle Mahan](https://github.com/kylewm) - some Javadoc fixes & duplicate file handling improvements
+* [Stephane Gallés](https://github.com/sgalles) - Documentation improvements
+* [Bobby Warner](https://github.com/bobbywarner) - Documentation improvements
+* [René Scheibe](https://github.com/darxriggs) - Documentation improvements
+* [Harald Schmitt](https://github.com/surfing) - Fixed unit test case that was broken for German locales
+* [Jeremy Maness](https://github.com/jmaness) - Support for Ivy 2.3 content in ivy.xml (GRADLE-2743)
-## External contributions
+Contributions are an important part of the continuous improvement of Gradle.
-We would like to thank the following community members for making excellent contributions to this release of Gradle.
-
-* [Joe Sortelli](https://github.com/sortelli) - Fixed incorrect handling of `ivy.xml` where dependency configuration contained wildcard values (GRADLE-2352)
-* [David M. Carr](https://github.com/davidmc24)
- * When JUnit tests have assumption failures, treat them as "skipped" (GRADLE-2454)
- * Documentation cleanups.
-* [Sébastien Cogneau](https://github.com/scogneau) - Introduce the distribution plugin
-* [Kenny Stridh](https://github.com/kensi)
- * Allow specifying `targetJdk` for PMD code analysis (GRADLE-2106)
- * Added support for PMD version 5.0.+
-* [Marcin Erdmann](https://github.com/erdi)
- * Add`build-dashboard` plugin
- * Make notify-send notifications transient in Gnome Shell
-* [Michael R. Maletich](https://github.com/HawaiianSpork)
- * Add `maxHeapSize` property to `FindBugs` task to allow setting the max heap size for spawned FindBugs java process
- * Add `contentsCompression` property to the `Zip` task type to specify the compression level of the archive
-* [Barry Pitman](https://github.com/barrypitman) - Fixed Maven conversion problem (GRADLE-2645)
-* [Kallin Nagelberg](https://github.com/Kallin) - Fixed grammar in the `SourceSetOutput` documentation
-* [Klaus Illusioni](https://github.com/illusioni) - Fixed Eclipse wtp component generation issue (GRADLE-2653)
-* [Alex Birmingham](https://github.com/abirmingham) - Fixed PMD Javadoc
-* [Matthieu Leclercq](https://github.com/mleclercq) - Fixed the nested configuration resolution issue (GRADLE-2477)
-* [Dan Stine](https://github.com/dstine) - Userguide cleanups.
-
-We love getting contributions from the Gradle community. For information on contributing, please see [gradle.org/contribute](http://gradle.org/contribute).
+If you would like to contribute to Gradle, please see [gradle.org/contribute](http://gradle.org/contribute) for how to start.
## Known issues
diff --git a/subprojects/docs/src/docs/stylesheets/dslHtml.xsl b/subprojects/docs/src/docs/stylesheets/dslHtml.xsl
index b232faa..c0ac085 100644
--- a/subprojects/docs/src/docs/stylesheets/dslHtml.xsl
+++ b/subprojects/docs/src/docs/stylesheets/dslHtml.xsl
@@ -34,14 +34,14 @@
<xsl:template name="formal.object.heading"></xsl:template>
- <!-- customise the stylesheets to add to the <head> element -->
+ <!-- customize the stylesheets to add to the <head> element -->
<xsl:template name="output.html.stylesheets">
<link href="base.css" rel="stylesheet" type="text/css"/>
<link href="docs.css" rel="stylesheet" type="text/css"/>
<link href="dsl.css" rel="stylesheet" type="text/css"/>
</xsl:template>
- <!-- Customise the page titles -->
+ <!-- customize the page titles -->
<xsl:template match="book" mode="object.title.markup.textonly">
<xsl:value-of select="bookinfo/titleabbrev"/>
<xsl:text> Version </xsl:text>
@@ -54,7 +54,7 @@
<xsl:apply-templates select="/book" mode="object.title.markup.textonly"/>
</xsl:template>
- <!-- customise the layout of the html page -->
+ <!-- customize the layout of the html page -->
<xsl:template name="chunk-element-content">
<xsl:param name="prev"/>
<xsl:param name="next"/>
@@ -149,7 +149,7 @@
</xsl:template>
<!--
- - Customised header for property and method detail sections
+ - Customized header for property and method detail sections
-->
<xsl:template match="section[@role='detail']/title" mode="titlepage.mode">
@@ -170,7 +170,7 @@
</xsl:template>
<!--
- - Customised <segmentedlist> formats
+ - Customized <segmentedlist> formats
-->
<xsl:template match="segmentedlist">
<div>
diff --git a/subprojects/docs/src/docs/stylesheets/userGuideHtmlCommon.xsl b/subprojects/docs/src/docs/stylesheets/userGuideHtmlCommon.xsl
index e8ea7e8..098e053 100644
--- a/subprojects/docs/src/docs/stylesheets/userGuideHtmlCommon.xsl
+++ b/subprojects/docs/src/docs/stylesheets/userGuideHtmlCommon.xsl
@@ -88,7 +88,7 @@
<!-- BOOK TITLEPAGE -->
- <!-- Customise the contents of the book titlepage -->
+ <!-- Customize the contents of the book titlepage -->
<xsl:template name="book.titlepage">
<div class="titlepage">
<div class="title">
diff --git a/subprojects/docs/src/docs/userguide/artifactMngmt.xml b/subprojects/docs/src/docs/userguide/artifactMngmt.xml
index 604efb2..226c93a 100644
--- a/subprojects/docs/src/docs/userguide/artifactMngmt.xml
+++ b/subprojects/docs/src/docs/userguide/artifactMngmt.xml
@@ -18,7 +18,7 @@
<note>
<para>
This chapter describes the <emphasis>original</emphasis> publishing mechanism available in Gradle 1.0: in Gradle 1.3 a new mechanism for publishing was introduced.
- While this new mechanism is <emphasis>incubating</emphasis> and not yet complete, it introduces some new concepts and features that do (and will) make Gradle publishing even more powerful.
+ While this new mechanism is <link linkend="feature_lifecycle">incubating</link> and not yet complete, it introduces some new concepts and features that do (and will) make Gradle publishing even more powerful.
</para>
<para>
You can read about the new publishing plugins in <xref linkend="publishing_ivy"/> and <xref linkend="publishing_maven"/>. Please try them out and give us feedback.
@@ -69,7 +69,7 @@
</sample>
<para>Gradle will figure out the properties of the artifact based on the name of the file. You can customize these properties:</para>
<sample id="fileArtifact" dir="userguide/artifacts/uploading" title="Customizing an artifact">
- <sourcefile file="build.gradle" snippet="customised-file-artifact"/>
+ <sourcefile file="build.gradle" snippet="customized-file-artifact"/>
</sample>
<para>There is a map-based syntax for defining an artifact using a file. The map must include a <literal>file</literal> entry that
defines the file. The map may include other artifact properties:
diff --git a/subprojects/docs/src/docs/userguide/bootstrapPlugin.xml b/subprojects/docs/src/docs/userguide/bootstrapPlugin.xml
deleted file mode 100644
index 837e740..0000000
--- a/subprojects/docs/src/docs/userguide/bootstrapPlugin.xml
+++ /dev/null
@@ -1,88 +0,0 @@
-<!--
- ~ Copyright 2012 the original author or authors.
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ 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.
- -->
-<chapter id='bootstrap_plugin'>
- <title>Bootstrap Plugin</title>
- <para>The Gradle bootstrap plugin prepares the current project for Gradle.
- Typically it will create the relevant build.gradle, settings.gradle files.
- At the moment only conversion from maven3 is supported.</para>
- <para>
- The plugin is currently *incubating* which means it is already useful
- but not everything might work perfectly.
- The api, plugin and task names may change before the final release.
- Please let us know your feedback or report any issues.</para>
- <para>
- The plugin works by obtaining the effective POM of the current project
- by executing external 'mvn' command. Then it reads the dependencies
- and other information to generate build.gradle scripts.</para>
- <para>
- The plugin is inspired by the <ulink url="https://github.com/jbaruch/maven2gradle">maven2gradle tool</ulink>
- founded and maintained by recognized leaders of Gradle community;
- created by Baruch Sadogursky with contributions from Antony Stubbs, Matthew McCullough and others.
- </para>
-
- <section>
- <title>Maven conversion - features</title>
- <itemizedlist>
- <listitem>Uses effective POM and effective settings
- (support for POM inheritance, dependency management, properties)</listitem>
- <listitem>Supports both single module and multimodule projects.
- Generates settings.gradle for multimodule projects (*).</listitem>
- <listitem>Supports custom module names (that differ from directory names)</listitem>
- <listitem>Generates general metadata - id, description and version</listitem>
- <listitem>Applies maven, java and war plugins (as needed)</listitem>
- <listitem>Supports packaging war projects as jars if needed</listitem>
- <listitem>Generates dependencies (both external and inter-module)</listitem>
- <listitem>Generates download repositories (inc. local Maven repository)</listitem>
- <listitem>Adjusts java compiler settings</listitem>
- <listitem>Supports packaging of sources and tests</listitem>
- <listitem>Supports testng runner</listitem>
- <listitem>Generates global exclusions from Maven enforcer plugin settings</listitem>
- </itemizedlist>
-
- <para>
- (*) - Note: Your project will be considered multi-module
- only if your reactor is also a parent of at least one of your modules.
- Why so? Reactor project is built last, when Parent project is built first.
- The reactor has to be built first, because effective-pom Mojo generates needed output
- only if it finds modules in first project it encounters.
- Making reactor also a parent achieves this.
- </para>
- </section>
-
- <section>
- <title>Usage</title>
- <para>To convert a Maven project follow the steps:</para>
- <itemizedlist>
- <listitem>Make sure your Maven project builds and uses maven3.</listitem>
- <listitem>Make sure <code>mvn</code> command can be executed and it runs maven3.</listitem>
- <listitem>Create <filename>build.gradle</filename> file in the root folder of your Maven project.</listitem>
- <listitem>Specify <code>apply plugin: 'maven2Gradle'</code> and nothing else
- in the <filename>build.gradle</filename> file.</listitem>
- <listitem>Make sure you are using the Gradle version that contains the plugin.
- If necessary download the required Gradle version.
- Until Gradle 1.2 is released you should use the
- <ulink url="website:nightly">nightly build</ulink>.
- You only need this version for conversion of the Maven project.
- When converting is complete feel free to use the desired Gradle version, for example 1.1.
- </listitem>
- <listitem>Run <code>gradle tasks</code>. You should see <code>maven2Gradle</code> task available.</listitem>
- <listitem>Run <code>gradle maven2Gradle</code>.</listitem>
- <listitem>Advanced users: you can configure following boolean properties on the <code>maven2Gradle</code> task:
- <code>verbose</code> (shows more output, including the effective POM)
- and <code>keepFile</code> (keeps the obtained effective POM file).</listitem>
- </itemizedlist>
- </section>
-</chapter>
diff --git a/subprojects/docs/src/docs/userguide/buildAnnouncementsPlugin.xml b/subprojects/docs/src/docs/userguide/buildAnnouncementsPlugin.xml
index fb9d064..6e46ac3 100644
--- a/subprojects/docs/src/docs/userguide/buildAnnouncementsPlugin.xml
+++ b/subprojects/docs/src/docs/userguide/buildAnnouncementsPlugin.xml
@@ -2,7 +2,7 @@
<title>The Build Announcements Plugin</title>
<note>
<para>
- The build announcements is incubating (see <xref linkend="sec:incubating_state"/>).
+ The build announcements plugin is currently <link linkend="feature_lifecycle">incubating</link>. Please be aware that the DSL and other configuration may change in later Gradle versions.
</para>
</note>
<para>The build announcements plugin uses the <link linkend="announce_plugin">announce</link> plugin to send local announcements on important events in the build.</para>
diff --git a/subprojects/docs/src/docs/userguide/buildDashboardPlugin.xml b/subprojects/docs/src/docs/userguide/buildDashboardPlugin.xml
index 47a64a6..ddf8f17 100644
--- a/subprojects/docs/src/docs/userguide/buildDashboardPlugin.xml
+++ b/subprojects/docs/src/docs/userguide/buildDashboardPlugin.xml
@@ -18,10 +18,13 @@
<title>The Build Dashboard Plugin</title>
<note>
<para>
- The Build Dashboard plugin is incubating (see <xref linkend="sec:incubating_state"/>).
+ The build dashboard plugin is currently <link linkend="feature_lifecycle">incubating</link>. Please be aware that the DSL and other configuration may change in later Gradle versions.
</para>
</note>
- <para>The Build Dashboard plugin adds a task to projects which generates build dashboard report.
+
+ <para>
+ The Build Dashboard plugin can be used to generate a single HTML dashboard that provides a single point of
+ access to all of the reports generated by a build.
</para>
<section>
@@ -30,8 +33,17 @@
<sample id="useBuildDashboardPlugin" dir="buildDashboard" title="Using the Build Dashboard plugin">
<sourcefile file="build.gradle" snippet="use-build-dashboard-plugin"/>
</sample>
- <para>You can then generate the report by running the <userinput>buildDashboard</userinput> task after running any tasks that
- generate reports, for example: <userinput>gradle check buildDashboard</userinput>.</para>
+ <para>
+ Applying the plugin adds the <literal>buildDashboard</literal> task to your project.
+ The task aggregates the reports for all tasks that implement the <apilink class="org.gradle.api.reporting.Reporting" />
+ interface from <emphasis>all projects</emphasis> in the build.
+ It is typically only applied to the root project.
+ </para>
+ <para>
+ The <literal>buildDashboard</literal> task does not depend on any other tasks. It will only aggregate the reporting tasks that are independently
+ being executed as part of the build run. To generate the build dashboard, simply include the <literal>buildDashboard</literal> task in the list of tasks to execute.
+ For example, <userinput>gradle buildDashboard build</userinput> will generate a dashboard for all of the reporting tasks that are dependents of the <literal>build</literal> task.
+ </para>
</section>
<section>
diff --git a/subprojects/docs/src/docs/userguide/buildLifecycle.xml b/subprojects/docs/src/docs/userguide/buildLifecycle.xml
index 32cbd88..f6feaed 100644
--- a/subprojects/docs/src/docs/userguide/buildLifecycle.xml
+++ b/subprojects/docs/src/docs/userguide/buildLifecycle.xml
@@ -45,7 +45,7 @@
<listitem>
<para>During this phase the project objects are configured.
The build scripts of <emphasis>all</emphasis> projects which are part of the build are
- executed. Gradle 1.4 introduces an incubating opt-in feature called 'configuration on demand'.
+ executed. Gradle 1.4 introduces an <link linkend="feature_lifecycle">incubating</link> opt-in feature called <firstterm>configuration on demand</firstterm>.
In this mode, Gradle configures only relevant projects (see <xref linkend="sec:configuration_on_demand"/>).
</para>
</listitem>
@@ -66,7 +66,7 @@
<title>Settings file</title>
<para>Beside the build script files, Gradle defines a settings file. The settings file is determined by Gradle
via a naming convention. The default name for this file is <filename>settings.gradle</filename>. Later in
- this chapter we explain, how Gradle looks for a settings file.
+ this chapter we explain how Gradle looks for a settings file.
</para>
<para>The settings file gets executed during the initialization phase. A multiproject build must have a
<filename>settings.gradle</filename>
@@ -130,7 +130,7 @@
<sourcefile file="settings.gradle" snippet="flat-layout"/>
</sample>
<para>The <literal>includeFlat</literal> method takes directory names as an argument. Those directories
- need to exist at the same level as the root project directory. The location of those directories
+ need to exist as siblings of the root project directory. The location of those directories
are considered as child projects of the root project in the multi-project tree.
</para>
</section>
diff --git a/subprojects/docs/src/docs/userguide/buildSetupPlugin.xml b/subprojects/docs/src/docs/userguide/buildSetupPlugin.xml
new file mode 100644
index 0000000..f30055a
--- /dev/null
+++ b/subprojects/docs/src/docs/userguide/buildSetupPlugin.xml
@@ -0,0 +1,177 @@
+<!--
+ ~ Copyright 2012 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ 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.
+ -->
+<chapter id='build_setup_plugin'>
+ <title>Build Setup Plugin</title>
+ <note>
+ <para>
+ The Build Setup plugin is currently <link linkend="feature_lifecycle">incubating</link>. Please be aware that the DSL and other configuration may change in later Gradle versions.
+ </para>
+ </note>
+ <para>
+ The Gradle Build Setup plugin can be used to bootstrap the process of creating a new Gradle build. It supports creating brand new projects of different types
+ as well as converting existing builds (e.g. An Apache Maven build) to be Gradle builds.
+ </para>
+ <para>
+ Gradle plugins typically need to be
+ <firstterm>applied</firstterm>
+ to a project before they can be used (see <xref linkend="sec:using_plugins"/>).
+ The Build Setup plugin is an automatically applied plugin, which means you do not need to apply it explicitly.
+ To use the plugin, simply execute the task named
+ <literal>setupBuild</literal>
+ where you would like to create the Gradle build.
+ There is no need to create a “stub”
+ <literal>build.gradle</literal>
+ file in order to apply the plugin.
+ </para>
+ <para>
+ It also leverages the
+ <literal>wrapper</literal>
+ task from the Wrapper plugin (see <xref linkend='wrapper_plugin'/>),
+ which means that the Gradle Wrapper will also be installed into the project.
+ </para>
+ <section>
+ <title>Tasks</title>
+ <para>The plugin adds the following tasks to the project:</para>
+ <table>
+ <title>Build Setup plugin - tasks</title>
+ <thead>
+ <tr>
+ <td>Task name</td>
+ <td>Depends on</td>
+ <td>Type</td>
+ <td>Description</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>
+ <literal>setupBuild</literal>
+ </td>
+ <td>
+ <literal>wrapper</literal>
+ </td>
+ <td>
+ <apilink class="org.gradle.buildsetup.tasks.SetupBuild"/>
+ </td>
+ <td>Generates a Gradle project.</td>
+ </tr>
+ <tr>
+ <td>
+ <literal>wrapper</literal>
+ </td>
+ <td>-</td>
+ <td>
+ <apilink class="org.gradle.api.tasks.wrapper.Wrapper"/>
+ </td>
+ <td>Generates Gradle wrapper files.
+ </td>
+ </tr>
+ </table>
+ </section>
+ <section>
+ <title>What to set up</title>
+ <para>The
+ <literal>setupBuild</literal>
+ supports different build setup <firstterm>types</firstterm>. The type is specified by supplying a
+ <literal>--type</literal>
+ argument value. For example, to create a Java library project simply execute:
+ <literal>gradle setupBuild --type java-library</literal>.
+ </para>
+ <para>
+ If a
+ <literal>--type</literal>
+ parameter is not supplied, Gradle will attempt to infer the type from the environment. For example, it will
+ infer a type value of "<literal>pom</literal>" if it finds a
+ <literal>pom.xml</literal>
+ to convert to a Gradle build.
+ </para>
+ <para>
+ If the type could not be inferred, the type "<literal>basic</literal>" will be used.
+ </para>
+ <para>All build setup types include the setup of the Gradle Wrapper.</para>
+ </section>
+ <section>
+ <title>Build setup types</title>
+ <note>
+ As this plugin is currently <link linkend="feature_lifecycle">incubating</link>, only 3 build setup types are currently supported.
+ More types will be added in future Gradle releases.
+ </note>
+ <section>
+ <title>"<literal>java-library</literal>"
+ </title>
+ <para>
+ The "<literal>java-library</literal>" build setup type is not inferable. It must be explicitly specified.
+ </para>
+ <para>
+ It has the following features:
+ </para>
+ <itemizedlist>
+ <listitem>Uses the "<literal>java</literal>" plugin
+ </listitem>
+ <listitem>Uses the "
+ <literal>mavenCentral()</literal>
+ dependency repository
+ </listitem>
+ <listitem>Uses JUnit for testing</listitem>
+ <listitem>Has directories in the conventional locations for source code</listitem>
+ <listitem>Contains a sample class and unit test, if there are no existing source or test files</listitem>
+ </itemizedlist>
+ </section>
+ <section>
+ <title>"<literal>pom</literal>" (Maven conversion)
+ </title>
+ <para>
+ The "<literal>pom</literal>" type can be used to convert an Apache Maven build to a Gradle build.
+ This works by converting the POM to one or more Gradle files.
+ It is only able to be used if there is a valid "<literal>pom.xml</literal>"
+ file in the directory that the
+ <literal>setupBuild</literal>
+ task is invoked in. This type will be automatically inferred if such a file exists.
+ </para>
+ <para>
+ The Maven conversion implementation was inspired by the
+ <ulink url="https://github.com/jbaruch/maven2gradle">maven2gradle tool</ulink>
+ that was originally developed by Gradle community members.
+ </para>
+ <para>
+ The conversion process has the following features:
+ </para>
+ <itemizedlist>
+ <listitem>Uses effective POM and effective settings (support for POM inheritance, dependency management, properties)</listitem>
+ <listitem>Supports both single module and multimodule projects</listitem>
+ <listitem>Supports custom module names (that differ from directory names)</listitem>
+ <listitem>Generates general metadata - id, description and version</listitem>
+ <listitem>Applies maven, java and war plugins (as needed)</listitem>
+ <listitem>Supports packaging war projects as jars if needed</listitem>
+ <listitem>Generates dependencies (both external and inter-module)</listitem>
+ <listitem>Generates download repositories (inc. local Maven repository)</listitem>
+ <listitem>Adjusts java compiler settings</listitem>
+ <listitem>Supports packaging of sources and tests</listitem>
+ <listitem>Supports TestNG runner</listitem>
+ <listitem>Generates global exclusions from Maven enforcer plugin settings</listitem>
+ </itemizedlist>
+ </section>
+ <section>
+ <title>"basic"</title>
+ <para>
+ The "<literal>basic</literal>" build setup type is useful for creating a fresh new Gradle project.
+ It creates a sample
+ <literal>build.gradle</literal>
+ file, with comments and links to help get started.
+ </para>
+ <para>This type is used when no type was explicitly specified, and no type could be inferred.</para>
+ </section>
+ </section>
+</chapter>
diff --git a/subprojects/docs/src/docs/userguide/comparingBuilds.xml b/subprojects/docs/src/docs/userguide/comparingBuilds.xml
index 8d99896..d0a8bd3 100644
--- a/subprojects/docs/src/docs/userguide/comparingBuilds.xml
+++ b/subprojects/docs/src/docs/userguide/comparingBuilds.xml
@@ -18,7 +18,7 @@
<title>Comparing Builds</title>
<note>
<para>
- Build comparison support is an <firstterm>incubating</firstterm> feature. This means that it is incomplete and not yet at regular Gradle production quality.
+ Build comparison support is an <link linkend="feature_lifecycle">incubating</link> feature. This means that it is incomplete and not yet at regular Gradle production quality.
This also means that this Gradle User Guide chapter is a work in progress.
</para>
</note>
@@ -127,7 +127,7 @@
<section>
<title>Current Capabilities</title>
<para>
- As this is an <firstterm>incubating</firstterm> feature, a limited set of the eventual functionality has been implemented at this time.
+ As this is an <link linkend="feature_lifecycle">incubating</link> feature, a limited set of the eventual functionality has been implemented at this time.
</para>
<section>
<title>Supported builds</title>
diff --git a/subprojects/docs/src/docs/userguide/cpp.xml b/subprojects/docs/src/docs/userguide/cpp.xml
index bee4ccc..b16b165 100755
--- a/subprojects/docs/src/docs/userguide/cpp.xml
+++ b/subprojects/docs/src/docs/userguide/cpp.xml
@@ -19,33 +19,37 @@
<note>
<para>
- The Gradle C++ support is in very early stages of development. Please be aware that the DSL and other configuration may change in later Gradle versions.
+ The Gradle C++ support is currently <link linkend="feature_lifecycle">incubating</link>. Please be aware that the DSL and other configuration may change in later Gradle versions.
</para>
</note>
<para>
The C++ plugins add support for building software comprised of C++ source code, and managing the process of building “native” software in general.
- While many excellent build tools exist for this space of software development, Gradle brings the dependency management practices more traditionally
- found in the JVM development space to C++ developers.
+ While many excellent build tools exist for this space of software development, Gradle offers C++ developers it's trademark power and flexibility
+ together with the dependency management practices more traditionally found in the JVM development space.
</para>
<para>
- The following platforms are supported:
+ Gradle offers the ability to execute the same build using different tool chains. At present, you control which tool chain will be used to build
+ by changing the operating system PATH to include the desired tool chain compiler. The following tool chains are supported:
</para>
<table>
<thread>
- <tr><td>Operating System</td><td>Compiler</td><td>Notes</td></tr>
+ <tr><td>Operating System</td><td>Tool Chain</td><td>Notes</td></tr>
</thread>
<tr>
- <td>Linux</td><td><ulink url="http://gcc.gnu.org/">GCC</ulink></td><td>Tested with GCC 4.6.1 on Ubuntu 11.10</td>
+ <td>Linux</td><td><ulink url="http://gcc.gnu.org/">GCC</ulink></td><td></td>
</tr>
<tr>
- <td>Mac OS X</td><td><ulink url="http://gcc.gnu.org/">GCC</ulink></td><td>Tested with XCode 4.2.1 on OS X 10.7</td>
+ <td>Mac OS X</td><td><ulink url="http://gcc.gnu.org/">GCC</ulink></td><td>Using GCC distributed with XCode.</td>
</tr>
<tr>
- <td>Windows</td><td><ulink url="http://www.microsoft.com/visualstudio/en-us">Visual C++</ulink></td><td>Tested with Windows 7 and Visual C++ 2010</td>
+ <td>Windows</td><td><ulink url="http://gcc.gnu.org/">GCC</ulink></td><td>Windows XP and later, using GCC distributed with Cygwin.</td>
</tr>
<tr>
- <td>Windows</td><td><ulink url="http://www.mingw.org/">MinGW</ulink></td><td>Tested with Windows 7 and MinGW 4.6.2. Note: G++ support is currently broken under cygwin</td>
+ <td>Windows</td><td><ulink url="http://www.microsoft.com/visualstudio/en-us">Visual C++</ulink></td><td>Windows XP and later, Visual C++ 2010 and later.</td>
+ </tr>
+ <tr>
+ <td>Windows</td><td><ulink url="http://www.mingw.org/">MinGW</ulink></td><td>Windows XP and later.</td>
</tr>
</table>
<para>
@@ -56,43 +60,116 @@
</para>
<section>
- <title>Usage</title>
+ <title>Source code locations</title>
+ <para>
+ A C++ project may define a number of source sets, each of which may contain source files and header files.
+ By default, a named <apilink class="org.gradle.nativecode.language.cpp.CppSourceSet"/> contains
+ <filename>.cpp</filename> and <filename>.c</filename> source files in <filename>src/${name}/cpp</filename>,
+ and header files in <filename>src/${name}/headers</filename>.
+ </para>
+ <sample id="cppSourceSets" dir="cpp/cpp" title="Defining 'cpp' source sets">
+ <sourcefile file="build.gradle" snippet="sourceSets"/>
+ </sample>
+ <para>
+ For a library named 'main', files in <filename>src/main/headers</filename> are considered the “public” or “exported” headers.
+ Header files that should not be exported (but are used internally) should be placed inside the <filename>src/main/cpp</filename> directory (though be aware that
+ such header files should always be referenced in a manner relative to the file including them).
+ </para>
+ <para>
+ While the <literal>cpp</literal> plugin defines these default locations for each <apilink class="org.gradle.nativecode.language.cpp.CppSourceSet"/>,
+ it is possible to extend or override these defaults to allow for a different project layout.
+ </para>
+ </section>
+
+ <section>
+ <title>Component model</title>
<para>
- The build scripts DSLs, model elements and tasks used to manage C++ projects are added by the <literal>cpp</literal> plugin. However, it is typically
- more convenient to use either the <literal>cpp-lib</literal> or <literal>cpp-exe</literal> plugins that sit on top of the <literal>cpp</literal>
- plugin to preconfigure the project to build either a shared library or executable binary respectively.
+ A C++ project defines a set of <apilink class="org.gradle.nativecode.base.Executable"/> and <apilink class="org.gradle.nativecode.base.Library"/> components,
+ each of which Gradle maps to a number of <apilink class="org.gradle.nativecode.base.NativeBinary"/> outputs.
+ Each <literal>executable</literal> or <literal>library</literal> is associated with a particular <literal>CppSourceSet</literal>, which contains C++ source files as well as header files.
</para>
- <sample id="useCppExePlugin" dir="cpp/dependencies" title="Using the 'cpp-exe' plugin">
- <sourcefile file="build.gradle" snippet="use-plugin-exe"/>
+ <para>
+ To build either a static or shared native library binary,
+ a <apilink class="org.gradle.nativecode.base.Library"/> component is added to the <literal>libraries</literal>
+ container and associated with a <literal>CppSourceSet</literal>.
+ Each <literal>library</literal> component can produce at least one <apilink class="org.gradle.nativecode.base.SharedLibraryBinary"/> and
+ at least one <apilink class="org.gradle.nativecode.base.StaticLibraryBinary"/>.
+ </para>
+ <sample id="cppLibraries" dir="cpp/cpp" title="Defining a library component">
+ <sourcefile file="build.gradle" snippet="libraries"/>
</sample>
- <sample id="useCppLibPlugin" dir="cpp/dependencies" title="Using the 'cpp-lib' plugin">
- <sourcefile file="build.gradle" snippet="use-plugin-lib"/>
+ <para>
+ To build an executable binary,
+ an <apilink class="org.gradle.nativecode.base.Executable"/> component is added to the <literal>executables</literal> container
+ and associated with a <literal>CppSourceSet</literal>.
+ </para>
+ <para>
+ Each <literal>executable</literal> component added can produce at least one <apilink class="org.gradle.nativecode.base.ExecutableBinary"/>.
+ If the executable requires a library for compiling and/or linking, then that library can be provided directly to a <literal>binary</literal>.
+ </para> <sample id="cppExecutables" dir="cpp/cpp" title="Defining executable components">
+ <sourcefile file="build.gradle" snippet="executables"/>
</sample>
<para>
- The <literal>cpp-exe</literal> plugin configures the project to build a single executable (at <filename><replaceable>$buildDir</replaceable>/binaries/<replaceable>$project.name</replaceable></filename>) and
- the <literal>cpp-lib</literal> plugin configures the project to build a single shared library (at <filename><replaceable>$buildDir</replaceable>/binaries/lib<replaceable>$project.name</replaceable>.so</filename>).
+ Alternatively, the library dependency can be specified at the level of the the <literal>CppSourceSet</literal> associated with an <literal>executable</literal> component:
</para>
+ <sample id="cppSourceLibrary" dir="cpp/cpp" title="Specifying a source-level library">
+ <sourcefile file="build.gradle" snippet="source-library"/>
+ </sample>
</section>
<section>
- <title>Source code locations</title>
+ <title>Plugins</title>
<para>
- Both plugins configure the project to look for <filename>.cpp</filename> and <filename>.c</filename> source files in <filename>src/main/cpp</filename> and use the <filename>src/main/headers</filename>
- directory as a header include root. For a library, the header files in <filename>src/main/headers</filename> are considered the “public” or “exported” headers.
- Header files that should not be exported (but are used internally) should be placed inside the <filename>src/main/cpp</filename> directory (though be aware that
- such header files should always be referenced in a manner relative to the file including them).
+ All build scripts DSLs, model elements and tasks used to manage C++ projects are added by the <literal>cpp</literal> plugin.
+ </para>
+ <sample id="cppLibraries" dir="cpp/cpp" title="Applying the 'cpp' plugin">
+ <sourcefile file="build.gradle" snippet="apply-plugin"/>
+ </sample>
+ <para>
+ The <literal>cpp</literal> plugin allows you to configure any number of <literal>libraries</literal> and <literal>executables</literal> for your project.
+ However, at times it is more convenient to use either the <literal>cpp-lib</literal> or <literal>cpp-exe</literal> plugins that sit on top of the <literal>cpp</literal>
+ plugin and pre-configure the project to build a single native library or executable respectively.
+ </para>
+ <sample id="useCppExePlugin" dir="cpp/cpp-exe" title="Using the 'cpp-exe' plugin">
+ <sourcefile file="build.gradle" snippet="use-plugin"/>
+ </sample>
+ <sample id="useCppLibPlugin" dir="cpp/cpp-lib" title="Using the 'cpp-lib' plugin">
+ <sourcefile file="build.gradle" snippet="use-plugin"/>
+ </sample>
+ <para>
+ The <literal>cpp-exe</literal> plugin configures the project to build a single executable named <literal>main</literal>,
+ and the <literal>cpp-lib</literal> plugin configures the project to build a shared and static version of a single library named <literal>main</literal>.
</para>
<para>
- The <literal>cpp</literal> plugin is also very flexible in where it looks for source and header files, aand you can configure the above conventions to look however you
- like.
+ In both cases, a single source set (<literal>src/main</literal>) containing C++ sources is assumed to exist.
</para>
</section>
<section>
- <title>Compiling</title>
+ <title>Tasks</title>
<para>
- For both the <literal>cpp-lib</literal> and <literal>cpp-exe</literal> plugins, you can run <userinput>gradle compileMain</userinput> to compile and link the binary.
+ For each <apilink class="org.gradle.nativecode.base.NativeBinary"/> that can be produced by a build, the <literal>cpp</literal> plugin
+ creates a single <literal>lifecycle task</literal> that can be used to create that binary, together with a set of sub-tasks that do the actual
+ work of compiling, linking or assembling the binary.
</para>
+ <table>
+ <thread>
+ <tr><td>Component Type</td><td>Native Binary Type</td><td>Lifecycle task</td><td>Location of created binary</td></tr>
+ </thread>
+ <tr>
+ <td><apilink class="org.gradle.nativecode.base.Executable"/></td><td><apilink class="org.gradle.nativecode.base.ExecutableBinary"/></td><td><literal>mainExecutable</literal></td><td><filename><replaceable>$buildDir</replaceable>/binaries/<replaceable>$project.name</replaceable></filename></td>
+ </tr>
+ <tr>
+ <td><apilink class="org.gradle.nativecode.base.Library"/></td><td><apilink class="org.gradle.nativecode.base.SharedLibraryBinary"/></td><td><literal>mainSharedLibrary</literal></td><td><filename><replaceable>$buildDir</replaceable>/binaries/lib<replaceable>$project.name</replaceable>.so</filename></td>
+ </tr>
+ <tr>
+ <td><apilink class="org.gradle.nativecode.base.Library"/></td><td><apilink class="org.gradle.nativecode.base.StaticLibraryBinary"/></td><td><literal>mainStaticLibrary</literal></td><td><filename><replaceable>$buildDir</replaceable>/binaries/<replaceable>$project.name</replaceable>.a</filename></td>
+ </tr>
+ </table>
+ </section>
+
+ <section>
+ <title>Building</title>
<section>
<title>Compiling on UNIX</title>
<para>
@@ -110,21 +187,48 @@
</section>
<section>
- <title>Configuring the compiler</title>
- <para>Arbitrary arguments can be provided to the compiler by using the following syntax:</para>
- <sample id="gppArgs" dir="cpp/exe" title="Supplying arbitrary args to the compiler">
+ <title>Configuring the compiler and linker</title>
+ <para>
+ Each binary to be produced is associated with a set of compiler and linker settings, which include command-line arguments as well as macro definitions.
+ These settings can be applied to all binaries, an individual binary, or selectively to a group of binaries based on some criteria.
+ </para>
+ <sample id="allBinarySettings" dir="cpp/cpp" title="Settings that apply to all binaries">
+ <sourcefile file="build.gradle" snippet="all-binaries"/>
+ </sample>
+ <para>
+ Each binary is associated with a particular <apilink class="org.gradle.nativecode.base.ToolChain"/>, allowing settings to be targeted based on
+ this value.
+ </para>
+ <para>
+ It is easy to apply settings to all binaries of a particular type:
+ </para>
+ <sample id="allSharedLibraryBinarySettings" dir="cpp/cpp" title="Settings that apply to all shared libraries">
+ <sourcefile file="build.gradle" snippet="all-shared-libraries"/>
+ </sample>
+ <para>
+ Furthermore, it is possible to specify settings that apply to all binaries produces for a particular <literal>executable</literal>
+ or <literal>library</literal> component:
+ </para>
+ <sample id="componentBinarySettings" dir="cpp/cpp-exe" title="Settings that apply to all binaries produced for the 'main' executable component">
<sourcefile file="build.gradle" snippet="args"/>
</sample>
<para>
- The above example applies to the <literal>cpp-exe</literal> plugin, to supply arguments for the <literal>cpp-lib</literal> plugin replace
- “<literal>executables</literal>” with “<literal>libraries</literal>”.
+ The above example will apply the supplied configuration to all <literal>executable</literal> binaries built.
+ </para>
+ <para>
+ Similarly, settings can be specified to target binaries for a component that are of a particular type:
+ eg all <literal>shared libraries</literal> for the <literal>main library</literal> component.
</para>
+ <sample id="sharedLibraryArgs" dir="cpp/cpp-lib" title="Settings that apply only to shared libraries produced for the 'main' library component">
+ <sourcefile file="build.gradle" snippet="args"/>
+ </sample>
</section>
<section>
<title>Working with shared libraries</title>
<para>
- The C++ plugin provides an <literal>installMain</literal> task, which creates a development install of the executable, along with the shared libraries it requires.
+ For each executable binary produced, the <literal>cpp</literal> plugin provides an <literal>install${binary.name}</literal> task,
+ which creates a development install of the executable, along with the shared libraries it requires.
This allows you to run the executable without needing to install the shared libraries in their final locations.
</para>
</section>
@@ -158,7 +262,7 @@
<para>
The notation for project dependencies is slightly different.
</para>
- <sample id="cppProjectDependencies" dir="cpp/exewithlib" title="Declaring project dependencies">
+ <sample id="cppProjectDependencies" dir="cpp/multi-project" title="Declaring project dependencies">
<sourcefile file="build.gradle" snippet="project-dependencies"/>
</sample>
</section>
diff --git a/subprojects/docs/src/docs/userguide/customTasks.xml b/subprojects/docs/src/docs/userguide/customTasks.xml
index c8578ae..94afb48 100644
--- a/subprojects/docs/src/docs/userguide/customTasks.xml
+++ b/subprojects/docs/src/docs/userguide/customTasks.xml
@@ -158,4 +158,146 @@
</sample>
</section>
</section>
+ <section id='incremental_tasks'>
+ <title>Incremental tasks</title>
+ <note>
+ <para>
+ Incremental tasks are an <link linkend="feature_lifecycle">incubating</link> feature.
+ </para>
+ <para>
+ Since the introduction of the implementation described above (early in the Gradle 1.6 release cycle), discussions within the Gradle community have produced
+ superior ideas for exposing the information about changes to task implementors to what is described below. As such, the API for this feature will almost certainly
+ change in upcoming releases. However, please do experiment with the current implementation and share your experiences with the Gradle community.
+ </para>
+ <para>
+ The feature incubation process, which is part of the Gradle feature lifecycle (see <xref linkend="feature_lifecycle"/>), exists for this purpose of ensuring high quality
+ final implementation through incorporation of early user feedback.
+ </para>
+ </note>
+ <para>
+ With Gradle, it's very simple to implement a task that gets skipped when all of it's inputs and outputs are up to date (see <xref linkend="sec:up_to_date_checks"/>).
+ However, there are times when only a few input files have changed since the last execution, and you'd like to avoid reprocessing all of the unchanged inputs.
+ This can be particularly useful for a transformer task, that converts input files to output files on a 1:1 basis.
+ </para>
+ <para>
+ If you'd like to optimise your build so that only out-of-date inputs are processed, you can do so with an <firstterm>incremental task</firstterm>.
+ </para>
+ <section>
+ <title>Implementing an incremental task</title>
+ <para>
+ For a task to process inputs incrementally, that task must contain an <firstterm>incremental task action</firstterm>. This is a task action method that contains a
+ single <apilink class="org.gradle.api.tasks.incremental.IncrementalTaskInputs"/> parameter, which indicates to Gradle that the action will process the changed inputs only.
+ </para>
+ <para>
+ The incremental task action may supply an <apilink class="org.gradle.api.tasks.incremental.IncrementalTaskInputs" method="outOfDate"/> action for processing any input file that is out-of-date,
+ and a <apilink class="org.gradle.api.tasks.incremental.IncrementalTaskInputs" method="removed"/> action that executes for any input file that has been removed since the previous execution.
+ </para>
+ <sample id="taskDefinition" dir="userguide/tasks/incrementalTask" title="Defining an incremental task action" includeLocation="true">
+ <sourcefile file="build.gradle" snippet="incremental-task" />
+ </sample>
+ <para>
+ For a simple transformer task like this, the task action simply needs to generate output files for any out-of-date inputs,
+ and delete output files for any removed inputs.
+ </para>
+ <para>
+ A task may only contain a single incremental task action.
+ </para>
+ </section>
+ <section>
+ <title>Which inputs are considered out of date?</title>
+ <para>
+ When Gradle has history of a previous task execution, and the only changes to the task execution context since that execution are to input files,
+ then Gradle is able to determine which input files need to be reprocessed by the task.
+ In this case, the <apilink class="org.gradle.api.tasks.incremental.IncrementalTaskInputs" method="outOfDate"/> action will be executed for any input file that was <emphasis>added</emphasis> or <emphasis>modified</emphasis>,
+ and the <apilink class="org.gradle.api.tasks.incremental.IncrementalTaskInputs" method="removed"/> action will be executed for any <emphasis>removed</emphasis> input file.
+ </para>
+ <para>
+ However, there are many cases where Gradle is unable to determine which input files need to be reprocessed. Examples include:
+ </para>
+ <itemizedlist>
+ <listitem>There is no history available from a previous execution.</listitem>
+ <listitem>You are building with a different version of Gradle. Currently, Gradle does not use task history from a different version.</listitem>
+ <listitem>An <literal>upToDateWhen</literal> criteria added to the task returns <literal>false</literal>.</listitem>
+ <listitem>An input property has changed since the previous execution.</listitem>
+ <listitem>One or more output files have changed since the previous execution.</listitem>
+ </itemizedlist>
+ <para>
+ In any of these cases, Gradle will consider all of the input files to be <literal>outOfDate</literal>.
+ The <apilink class="org.gradle.api.tasks.incremental.IncrementalTaskInputs" method="outOfDate"/> action will be executed for every input file, and the
+ <apilink class="org.gradle.api.tasks.incremental.IncrementalTaskInputs" method="removed"/> action will not be executed at all.
+ </para>
+ <para>
+ You can check if Gradle was able to determine the incremental changes to input files with <apilink class="org.gradle.api.tasks.incremental.IncrementalTaskInputs" method="isIncremental"/>.
+ </para>
+ </section>
+ <section>
+ <title>An incremental task in action</title>
+ <para>
+ Given the incremental task implementation <link linkend="taskDefinition">above</link>, we can explore the various change scenarios by example.
+ Note that the various mutation tasks ('updateInputs', 'removeInput', etc) are only present for demonstration purposes: these would not normally be part of your build script.
+ </para>
+ <para>
+ First, consider the <literal>IncrementalReverseTask</literal> executed against a set of inputs for the first time.
+ In this case, all inputs will be considered "out of date":
+ </para>
+ <sample id="incrementalTaskFirstRun" dir="userguide/tasks/incrementalTask" title="Running the incremental task for the first time">
+ <sourcefile file="build.gradle" snippet="reverse"/>
+ <layout after="originalInputs">
+ build.gradle
+ inputs/
+ inputs/1.txt
+ inputs/2.txt
+ inputs/3.txt
+ </layout>
+ <output args="-q incrementalReverse" ignoreLineOrder="true"/>
+ </sample>
+ <para>
+ Naturally when the task is executed again with no changes, then task itself is up to date and no files are reported to the task action:
+ </para>
+ <sample id="incrementalTaskNoChange" dir="userguide/tasks/incrementalTask" title="Running the incremental task with unchanged inputs">
+ <test args="-q originalInputs incrementalReverse"/>
+ <output args="-q incrementalReverse"/>
+ </sample>
+
+ <para>
+ When an input file is modified in some way or a new input file is added, then re-executing the task results in those files being reported to <apilink class="org.gradle.api.tasks.incremental.IncrementalTaskInputs" method="outOfDate"/>:
+ </para>
+ <sample id="incrementalTaskUpdatedInputs" dir="userguide/tasks/incrementalTask" title="Running the incremental task with updated input files">
+ <sourcefile file="build.gradle" snippet="updated-inputs" />
+ <test args="-q originalInputs incrementalReverse"/>
+ <output args="-q updateInputs incrementalReverse" ignoreLineOrder="true"/>
+ </sample>
+
+ <para>
+ When an existing input file is removed, then re-executing the task results that file being reported to <apilink class="org.gradle.api.tasks.incremental.IncrementalTaskInputs" method="removed"/>:
+ </para>
+ <sample id="incrementalTaskRemovedInput" dir="userguide/tasks/incrementalTask" title="Running the incremental task with an input file removed">
+ <sourcefile file="build.gradle" snippet="removed-input" />
+ <test args="-q originalInputs incrementalReverse"/>
+ <output args="-q removeInput incrementalReverse" ignoreLineOrder="true"/>
+ </sample>
+
+ <para>
+ When an output file is deleted (or modified), then Gradle is unable to determine which input files are out of date.
+ In this case, <emphasis>all</emphasis> input files are reported to the <apilink class="org.gradle.api.tasks.incremental.IncrementalTaskInputs" method="outOfDate"/> action,
+ and no input files are reported to the <apilink class="org.gradle.api.tasks.incremental.IncrementalTaskInputs" method="removed"/> action:
+ </para>
+ <sample id="incrementalTaskRemovedOutput" dir="userguide/tasks/incrementalTask" title="Running the incremental task with an output file removed">
+ <sourcefile file="build.gradle" snippet="removed-output" />
+ <test args="-q originalInputs incrementalReverse"/>
+ <output args="-q removeOutput incrementalReverse" ignoreLineOrder="true"/>
+ </sample>
+
+ <para>
+ When a task input property modified, Gradle is not able to determine how this property impacted the task outputs, so all input files are assumed to be out of date.
+ So similar to the changed output file example, <emphasis>all</emphasis> input files are reported to
+ the <apilink class="org.gradle.api.tasks.incremental.IncrementalTaskInputs" method="outOfDate"/> action,
+ and no input files are reported to the <apilink class="org.gradle.api.tasks.incremental.IncrementalTaskInputs" method="removed"/> action:
+ </para>
+ <sample id="incrementalTaskChangedProperty" dir="userguide/tasks/incrementalTask" title="Running the incremental task with an input property changed">
+ <test args="-q originalInputs incrementalReverse"/>
+ <output args="-q -PtaskInputProperty=changed incrementalReverse" ignoreLineOrder="true"/>
+ </sample>
+ </section>
+ </section>
</chapter>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/userguide/depMngmt.xml b/subprojects/docs/src/docs/userguide/depMngmt.xml
index df42f66..f1f1a88 100644
--- a/subprojects/docs/src/docs/userguide/depMngmt.xml
+++ b/subprojects/docs/src/docs/userguide/depMngmt.xml
@@ -19,7 +19,7 @@
<title>Introduction</title>
<para>Dependency management is a critical feature of every build, and Gradle has placed an emphasis on offering first-class dependency management that is both easy-to-understand and
compatible with a wide variety of approaches. If you are familiar with the approach used by either Maven or Ivy you will be delighted to learn that Gradle is fully compatible with both
- approaches in addition to being flexible enough to support fully-customised approaches.
+ approaches in addition to being flexible enough to support fully-customized approaches.
</para>
<para>Here are the major highlights of Gradle's support for dependency management:</para>
@@ -38,7 +38,7 @@
</para>
</listitem>
<listitem>
- <para><emphasis>A fully customisable approach to Dependency Resolution</emphasis>: Gradle provides you with the ability to customize resolution rules making dependency substitution
+ <para><emphasis>A fully customizable approach to Dependency Resolution</emphasis>: Gradle provides you with the ability to customize resolution rules making dependency substitution
easy.
</para>
</listitem>
@@ -87,7 +87,7 @@
<para>Both tools rely on descriptor XML files, which contain information about the dependencies of a particular jar. Both also use repositories where the actual jars are placed together
with their descriptor files, and both offer resolution for conflicting jar versions in one form or the other. Both have emerged as standards for solving dependency conflicts, and while
Gradle originally used Ivy under the hood for its dependency management. Gradle has replaced this direct dependency on Ivy with a native Gradle dependency resolution engine which
- supports a range of approached to dependency resolution including both POM and Ivy descriptor files.
+ supports a range of approaches to dependency resolution including both POM and Ivy descriptor files.
</para>
</section>
</section>
@@ -153,27 +153,26 @@
and the often accidental order of the classpath will determine what version of a dependency will win. On a large project with many developers changing dependencies, successful builds
will be few and far between as the order of dependencies may directly affect whether a build succeeds or fails (or whether a bug appears or disappears in production).
</para>
- <para>If you haven't had to deal with the curse of conflicting versions of jars on a classpath, here's a small example of the fun that awaits you. Consider a large project with 30
- submodules, adding a dependency with a particular version to a subproject changes the order of a classpath, swapping an old version of Spring 2.4 for a newer version Spring 2.5. While
- the build may continue to work, developers are starting to notice all sorts of surprising (and surprisingly awful) bugs in production. Worse yet, this unintentional downgrade of Spring
- introduced several security vulnerabilities into the system which now require a full security audit throughout the organization.
+ <para>If you haven't had to deal with the curse of conflicting versions of jars on a classpath, here is a small anecdote of the fun that awaits you. In a large project with 30
+ submodules, adding a dependency to a subproject changed the order of a classpath, swapping Spring 2.5 for an older 2.4 version. While
+ the build continued to work, developers were starting to notice all sorts of surprising (and surprisingly awful) bugs in production. Worse yet, this unintentional downgrade of Spring
+ introduced several security vulnerabilities into the system, which now required a full security audit throughout the organization.
</para>
- <para>In short, version conflicts are bad, manage your transitive dependencies to avoid them. You might also want to learn where conflicting versions are used and consolidate on a
- particular version of a dependency across your organization. With a good conflict reporting tool like Gradle that information can be used to communicate with the entire organization
- and standardise on a single version.
+ <para>In short, version conflicts are bad, and you should manage your transitive dependencies to avoid them. You might also want to learn where conflicting versions are used and consolidate on a
+ particular version of a dependency across your organization. With a good conflict reporting tool like Gradle, that information can be used to communicate with the entire organization
+ and standardize on a single version.
<emphasis>If you think version conflicts don't happen to you, think again.</emphasis>
It is very common for different first-level dependencies to rely on a range of different overlapping versions for other dependencies, and the JVM doesn't yet offer an easy way to have
different versions of the same jar in the classpath (see <xref linkend='sub:dependency_management_and_java'/>).
</para>
- <para>Gradle offers following conflict resolution strategies:</para>
+ <para>Gradle offers the following conflict resolution strategies:</para>
<itemizedlist>
<listitem>
- <emphasis>Newest</emphasis> - used by default by Gradle - the newest version of the dependency is used. This has been Gradle's approach since the beginning of the project, and
- while it isn't appropriate in every situation, this is why Gradle provides you with various options for resolving conflicts.
+ <emphasis>Newest</emphasis>: The newest version of the dependency is used. This is Gradle's default strategy, and is often an appropriate choice as long as versions are backwards-compatible.
</listitem>
<listitem>
- <emphasis>Fail</emphasis> - fail eagerly on version conflict. Useful if you need extra control over dependencies and if you need to manage version conflicts manually. See
- <apilink class='org.gradle.api.artifacts.ResolutionStrategy'/> for reference on managing the conflict resolution strategies.
+ <emphasis>Fail</emphasis>: A version conflict results in a build failure. This strategy enforces that all version conflicts are resolved explicitly in the build script. See
+ <apilink class='org.gradle.api.artifacts.ResolutionStrategy'/> for details on how to explicitly choose a particular version.
</listitem>
</itemizedlist>
<para>While the strategies introduced above are usually enough to solve most conflicts, Gradle provides more fine-grained mechanisms to resolve version conflicts:</para>
@@ -188,7 +187,7 @@
See examples in <apilink class='org.gradle.api.artifacts.ResolutionStrategy'/>
</listitem>
<listitem>
- Dependency resolve rules are an incubating feature introduced in Gradle 1.4 which give you fine-grained control over the version selected for a particular dependency.
+ Dependency resolve rules are an <link linkend="feature_lifecycle">incubating</link> feature introduced in Gradle 1.4 which give you fine-grained control over the version selected for a particular dependency.
</listitem>
</itemizedlist>
<para>To deal with problems due to version conflicts, reports with dependency graphs are also very helpful. Such reports are another feature of dependency management.</para>
@@ -220,7 +219,7 @@
Many Gradle plugin add pre-defined configurations to your project. The Java plugin, for example,
adds some configurations to represent the various classpaths it needs. see
<xref linkend='sec:java_plugin_and_dependency_management'/>
- for details. Of course you can add your add custom configurations on top of that. There are many use cases
+ for details. Of course you can add custom configurations on top of that. There are many use cases
for custom configurations. This is very handy for example for adding dependencies not needed for
building or testing your software (e.g. additional JDBC drivers to be shipped with your distribution).
</para>
@@ -306,47 +305,43 @@
<sample id="moduleDependencies" dir="userguide/artifacts/externalDependencies" title="Module dependencies">
<sourcefile file="build.gradle" snippet="module-dependencies"/>
</sample>
- <para>Please see the
- <apilink class='org.gradle.api.artifacts.dsl.DependencyHandler'/>
- for more examples and complete reference. Please read on to get thorough understanding of the Gradle's dependency management.
+ <para>See <apilink class='org.gradle.api.artifacts.dsl.DependencyHandler'/>
+ for more examples and a complete reference.
</para>
<para>Gradle provides different notations for module dependencies. There is a string notation and
a map notation. A module dependency has an API which allows for further configuration. Have a look at
<apilink class='org.gradle.api.artifacts.ExternalModuleDependency'/>
to learn all about the API.
This API provides properties and configuration methods. Via the string notation you can define a subset
- the properties. With the map notation you can define all properties. To have access to the complete API,
+ of the properties. With the map notation you can define all properties. To have access to the complete API,
either with the map or with the string notation, you can assign a single dependency to a configuration
together with a closure.
</para>
<para>If you declare a module dependency, Gradle looks for a corresponding module descriptor file (<filename>pom.xml</filename> or
<filename>ivy.xml</filename>) in the repositories. If such a module descriptor file exists, it is parsed and the artifacts of
- this module (e.g.<filename>hibernate-3.0.5.jar</filename>) as well as its dependencies (e.g. cglib) are downloaded. If no such
+ this module (e.g. <filename>hibernate-3.0.5.jar</filename>) as well as its dependencies (e.g. cglib) are downloaded. If no such
module descriptor file exists, Gradle looks for a file called <filename>hibernate-3.0.5.jar</filename>
- to retrieve. In Maven a module can only have one and only one artifact. In Gradle and Ivy a module can have multiple artifacts.
+ to retrieve. In Maven, a module can have one and only one artifact. In Gradle and Ivy, a module can have multiple artifacts.
Each artifact can have a different set of dependencies.
</para>
<section id='ssub:multi_artifact_dependencies'>
<title>Depending on modules with multiple artifacts</title>
- As mentioned earlier, a Maven module has only one artifact. So, when your project depends on a Maven module it's obvious what artifact is the actual dependency.
- With Gradle or Ivy the case is different. Ivy model of dependencies (<filename>ivy.xml</filename>) can declare multiple artifacts.
- For more information, see Ivy reference for<filename>ivy.xml</filename>.
- In Gradle, when you declare a dependency on an ivy module you actually declare dependency on the '<literal>default</literal>' configuration of that module.
- So the actual list of artifacts (typically jars) your project depends on, are all artifacts that are attached to the
- <literal>default</literal> configuration of that module.
- This is very important in following exemplary use cases:
+ As mentioned earlier, a Maven module has only one artifact. Hence, when your project depends on a Maven module, it's obvious what its artifact is.
+ With Gradle or Ivy, the case is different. Ivy's dependency descriptor (<filename>ivy.xml</filename>) can declare multiple artifacts.
+ For more information, see the Ivy reference for<filename>ivy.xml</filename>.
+ In Gradle, when you declare a dependency on an Ivy module, you actually declare a dependency on the <literal>default</literal> configuration of that module.
+ So the actual set of artifacts (typically jars) you depend on is the set of artifacts that are associated with the
+ <literal>default</literal> configuration of that module. Here are some situations where this matters:
<itemizedlist>
- <listitem>The <literal>default</literal> configuration of some module contains some artifacts
- you don't want on the classpath. You might need to configure a dependency on specific artifact(s) of given module,
- rather than pulling all artifacts of the <literal>default</literal> dependency
+ <listitem>The <literal>default</literal> configuration of a module contains undesired artifacts. Rather than depending on the
+ whole configuration, a dependency on just the desired artifacts is declared.
</listitem>
- <listitem>The artifact you need on the classpath has been published in a different configuration
- than the <literal>default</literal> one. This means this artifact will not be pulled in by Gradle.
- Unless you explicitly declare what configuration of the module you depend on.
+ <listitem>The desired artifact belongs to a configuration other than <literal>default</literal>. That configuration is explicitly named
+ as part of the dependency declaration.
</listitem>
</itemizedlist>
- There are other situations where it is necessary to fine-tune the dependency declaration.
- Please see the <apilink class='org.gradle.api.artifacts.dsl.DependencyHandler'/> for examples and complete reference on declaring dependencies.
+ There are other situations where it is necessary to fine-tune dependency declarations.
+ Please see <apilink class='org.gradle.api.artifacts.dsl.DependencyHandler'/> for examples and a complete reference for declaring dependencies.
</section>
<section id='ssub:artifact_dependencies'>
<title>Artifact only notation</title>
@@ -377,11 +372,11 @@
<sample id="classifier" dir="userguide/artifacts/excludesAndClassifiers" title="Dependency with classifier">
<sourcefile file="build.gradle" snippet="classifier"/>
</sample>
- <para>As you can see in the example, classifiers can be used together with setting an explicit extension (artifact only notation).
+ <para>As can be seen in the first line above, classifiers can be used together with artifact only notation.
</para>
</section>
- <para>To use the external dependencies of a configuration:</para>
- <sample id="externalDependencies" dir="userguide/artifacts/externalDependencies" title="Usage of external dependency of a configuration">
+ <para>It is easy to iterate over the dependency artifacts of a configuration:</para>
+ <sample id="externalDependencies" dir="userguide/artifacts/externalDependencies" title="Iterating over a configuration">
<sourcefile file="build.gradle" snippet="use-configuration"/>
<output args="-q listJars"/>
</sample>
@@ -389,13 +384,13 @@
<section id='sub:client_module_dependencies'>
<title>Client module dependencies</title>
- <para>Client module dependencies enable you to declare <emphasis>transitive</emphasis> dependencies directly in your build script. They are a replacement for a module descriptor
- XML file in an external repository.
+ <para>Client module dependencies allow to declare <emphasis>transitive</emphasis> dependencies directly in the build script. They are a replacement for a module descriptor
+ in an external repository.
</para>
<sample id="client-modules" dir="userguide/artifacts/externalDependencies" title="Client module dependencies - transitive dependencies">
<sourcefile file="build.gradle" snippet="client-modules"/>
</sample>
- <para>This declares a dependency of your project on Groovy. Groovy itself has dependencies. But Gradle does
+ <para>This declares a dependency on Groovy. Groovy itself has dependencies. But Gradle does
not look for an XML descriptor to figure them out but gets the information from the build file. The
dependencies of a client module can be normal module dependencies or artifact dependencies or another
client module. Have also a look at the API documentation:
@@ -554,7 +549,7 @@
</para>
<para>
Since Gradle 1.2 there is also a new programmatic API to access the resolved dependency information.
- The dependency reports (see the previous paragraph) are using this API behind the hood.
+ The dependency reports (see the previous paragraph) are using this API under the covers.
The API lets you to walk the resolved dependency graph and provides information about the dependencies.
With the coming releases the API will grow to provide more information about the resolution result.
For more information about the API please refer to the javadocs on
@@ -658,6 +653,12 @@
</tr>
<tr>
<td>
+ <link linkend="sub:maven_jcenter">Maven JCenter repository</link>
+ </td>
+ <td>A pre-configured repository that looks for dependencies in Bintray's JCenter.</td>
+ </tr>
+ <tr>
+ <td>
<link linkend="sub:maven_local">Maven local repository</link>
</td>
<td>A pre-configured repository that looks for dependencies in the local Maven repository.</td>
@@ -693,6 +694,19 @@
</para>
</section>
+ <section id='sub:maven_jcenter'>
+ <title>Maven JCenter repository</title>
+ <para><ulink url='http://bintray.com'>Bintray</ulink>'s JCenter is an up-to-date collection of all popular Maven OSS artifacts, including artifacts published directly to Bintray.
+ </para>
+ <para>To add the JCenter Maven repository (<ulink url='http://jcenter.bintray.com'/>) simply add this to your build script:
+ </para>
+ <sample id="mavenJcenter" dir="userguide/artifacts/defineRepository" title="Adding Bintray's JCenter Maven repository">
+ <sourcefile file="build.gradle" snippet="maven-jcenter"/>
+ </sample>
+ <para>Now Gradle will look for your dependencies in the JCenter repository.
+ </para>
+ </section>
+
<section id='sub:maven_local'>
<title>Local Maven repository</title>
<para>To use the local Maven cache as a repository you can do:</para>
@@ -918,7 +932,7 @@ someroot/[artifact]-[revision].[ext]
<section id='sec:dependency_resolve_rules'>
<title>Using dependency resolve rules</title>
<para>A dependency resolve rule is executed for each resolved dependency, and offers a powerful api for manipulating a requested dependency prior to that dependency being resolved.
- This feature is incubating, but currently offers the ability to change the group, name and/or version of a requested dependency,
+ This feature is <link linkend="feature_lifecycle">incubating</link>, but currently offers the ability to change the group, name and/or version of a requested dependency,
allowing a dependency to be substituted with a completely different module during resolution.
</para>
<para>
@@ -1007,6 +1021,38 @@ someroot/[artifact]-[revision].[ext]
<sourcefile file="build.gradle" snippet="ivy-repo-dynamic-mode"/>
</sample>
</section>
+ <section id="component_metadata_rules">
+ <title>Component metadata rules</title>
+ <para>Each module (also called <emphasis>component</emphasis>) has metadata associated with it, such as its group, name, version, dependencies, and so on.
+ This metadata typically originates in the module's descriptor. Metadata rules allow certain parts of a module's metadata to be manipulated
+ from within the build script. They take effect after a module's descriptor has been downloaded, but before it has been selected among all candidate versions.
+ This makes metadata rules another instrument for customizing dependency resolution.
+ </para>
+ <para>
+ One piece of module metadata that Gradle understands is a module's <emphasis>status scheme</emphasis>. This concept, also known from Ivy, models the different
+ levels of maturity that a module transitions through over time. The default status scheme, ordered from least to most mature status, is <literal>integration</literal>,
+ <literal>milestone</literal>, <literal>release</literal>. Apart from a status scheme, a module also has a (current) <emphasis>status</emphasis>, which must be one of
+ the values in its status scheme. If not specified in the (Ivy) descriptor, the status defaults to <literal>integration</literal> for Ivy modules and Maven snapshot modules,
+ and <literal>release</literal> for Maven modules that aren't snapshots.
+ </para>
+ <para>
+ A module's status and status scheme are taken into consideration when a <literal>latest</literal> version selector is resolved. Specifically, <literal>latest.someStatus</literal>
+ will resolve to the highest module version that has status <literal>someStatus</literal> or a more mature status. For example, with the default status scheme in place,
+ <literal>latest.integration</literal> will select the highest module version regardless of its status (because <literal>integration</literal> is the least mature status),
+ whereas <literal>latest.release</literal> will select the highest module version with status <literal>release</literal>. Here is what this looks like in code:
+ </para>
+ <sample id="latestSelector" dir="userguide/artifacts/componentMetadata" title="'Latest' version selector">
+ <sourcefile file="build.gradle" snippet="latest-selector"/>
+ <output args="-q listFish"/>
+ </sample>
+ <para>
+ The next example demonstrates <literal>latest</literal> selectors based on a custom status scheme declared in a module metadata rule:
+ </para>
+ <sample id="customStatusScheme" dir="userguide/artifacts/componentMetadata" title="Custom status scheme">
+ <sourcefile file="build.gradle" snippet="custom-status-scheme"/>
+ <output args="-q listBirds"/>
+ </sample>
+ </section>
</section>
<section id='sec:dependency_cache'>
<title>The dependency cache</title>
@@ -1112,7 +1158,7 @@ someroot/[artifact]-[revision].[ext]
</para>
<para>The <literal>--refresh-dependencies</literal> option tells Gradle to ignore all cached entries for resolved modules and artifacts.
A fresh resolve will be performed against all configured repositories, with dynamic versions recalculated, modules refreshed, and artifacts downloaded.
- However, where possible Gradle will attempt to if the previously downloaded artifacts are valid before downloading again.
+ However, where possible Gradle will check if the previously downloaded artifacts are valid before downloading again.
This is done by comparing published SHA1 values in the repository with the SHA1 values for existing downloaded artifacts.
</para>
</section>
@@ -1186,6 +1232,10 @@ someroot/[artifact]-[revision].[ext]
libraries and you need a backup. It is another layer of indirection. Another source of information
you have to lookup. All this is not really a big deal but in its sum it has an impact. Repository Manager like
Artifactory or Nexus make this easier. But for example open source projects don't usually have a host for those products.
+ This is changing with new services like <ulink url='http://bintray.com'>Bintray</ulink> that let developers host and
+ distribute their release binaries using a self-service repository platform. Bintray also supports sharing approved artifacts
+ though the <ulink url='http://jcenter.bintray.com'>JCenter</ulink> public repository to provide a single resolution address for
+ all popular OSS java artifacts (see <xref linkend="sub:maven_jcenter"/>).
</para>
<para>This is a reason why some projects prefer to store their libraries in their version control system. This
approach is fully supported by Gradle. The libraries can be stored in a flat directory without any XML module
diff --git a/subprojects/docs/src/docs/userguide/distributionPlugin.xml b/subprojects/docs/src/docs/userguide/distributionPlugin.xml
index 5d453b9..058466c 100644
--- a/subprojects/docs/src/docs/userguide/distributionPlugin.xml
+++ b/subprojects/docs/src/docs/userguide/distributionPlugin.xml
@@ -18,11 +18,13 @@
<title>The Distribution Plugin</title>
<note>
<para>
- The distribution plugin is incubating (see <xref linkend="sec:incubating_state"/>).
+ The distribution plugin is currently <link linkend="feature_lifecycle">incubating</link>. Please be aware that the DSL and other configuration may change in later Gradle versions.
</para>
</note>
- <para>The distribution plugin extends the language plugins with common distribution related tasks.
- It allows bundling a project including binaries, sources and documentation.
+
+ <para>
+ The distribution plugin facilitates building archives that serve as distributions of the project.
+ Distribution archives typically contain then executable application and other supporting files, such as documentation.
</para>
<section>
@@ -31,18 +33,24 @@
<sample id="useDistributionPlugin" dir="userguide/distribution" title="Using the distribution plugin">
<sourcefile file="build.gradle" snippet="use-plugin"/>
</sample>
- <para>To define the name for the distribution you have to set the <literal>baseName</literal> property as shown below</para>
- <sample id="configureDistributionName" dir="userguide/distribution" title="Configure the distribution name">
- <sourcefile file="build.gradle" snippet="name-conf"/>
- </sample>
- <para>The plugin build a distribution for your project. You can run <userinput>gradle distZip</userinput> to create a
- ZIP containing the distribution. Given that the project name is myproject and version is 1.2, then running gradle customDistZip will produce a ZIP file called myproject-1.2.zip
+ <para>
+ The plugin adds an extension named "<literal>distributions</literal>" of type <apilink class="org.gradle.api.distribution.DistributionContainer" /> to the project.
+ It also creates a single distribution in the distributions container extension named "<literal>main</literal>".
+ If your build only produces one distribution you only need to configure this distribution (or use the defaults).
+ </para>
+ <para>
+ You can run "<userinput>gradle distZip</userinput>" to package the main distribution as a ZIP, or "<userinput>gradle distTar</userinput>" to create
+ a GZip compressed TAR file.
+ The files will be created at "<literal><replaceable>$buildDir</replaceable>/distributions/<replaceable>$project.name</replaceable>-<replaceable>$project.version</replaceable>.<replaceable>«ext»</replaceable></literal>".
+ </para>
+ <para>
+ You can run "<userinput>gradle installDist</userinput>" to assembles the distribution content, uncompressed, into "<literal><replaceable>$buildDir</replaceable>/install/<replaceable>main</replaceable></literal>".
</para>
</section>
<section>
<title>Tasks</title>
- <para>The Distribution plugin adds the following tasks to the project.</para>
+ <para>The Distribution plugin adds the following tasks to the project:</para>
<table>
<title>Distribution plugin - tasks</title>
<thead>
@@ -53,71 +61,137 @@
<td>Description</td>
</tr>
</thead>
- <tr>
- <td>
- <literal>distZip</literal>
- </td>
- <td>
- <literal>-</literal>
- </td>
- <td>
- <apilink class="org.gradle.api.tasks.bundling.Zip"/>
- </td>
- <td>Creates a full distribution ZIP archive.</td>
+ <tr>
+ <td>
+ <literal>distZip</literal>
+ </td>
+ <td>
+ <literal>-</literal>
+ </td>
+ <td>
+ <apilink class="org.gradle.api.tasks.bundling.Zip"/>
+ </td>
+ <td>
+ Creates a ZIP archive of the distribution contents
+ </td>
</tr>
- <tr>
- <td>
- <literal>distTar</literal>
- </td>
- <td>
- <literal>-</literal>
- </td>
- <td>
- <apilink class="org.gradle.api.tasks.bundling.Tar"/>
- </td>
- <td>Creates a full distribution TAR archive.</td>
+ <tr>
+ <td>
+ <literal>distTar</literal>
+ </td>
+ <td>
+ <literal>-</literal>
+ </td>
+ <td>
+ <apilink class="org.gradle.api.tasks.bundling.Tar"/>
+ </td>
+ <td>
+ Creates a ZIP archive of the distribution contents
+ </td>
</tr>
- <tr>
- <td>
- <literal>installDist</literal>
- </td>
- <td>
- <literal>-</literal>
- </td>
- <td>
- <apilink class="org.gradle.api.tasks.Sync"/>
- </td>
- <td>Install distribution contents.</td>
+ <tr>
+ <td>
+ <literal>installDist</literal>
+ </td>
+ <td>
+ <literal>-</literal>
+ </td>
+ <td>
+ <apilink class="org.gradle.api.tasks.Sync"/>
+ </td>
+ <td>
+ Assembles the distribution content and installs it on the current machine
+ </td>
</tr>
-
</table>
- </section>
-
- <section>
- <title>Configure distributions</title>
- <para>The distribution plugin allow to configure distributions to include custom files and to change distribution baseName.
- </para>
- <sample id="customDistribution" dir="userguide/distribution" title="Declare multiple distributions">
+ <para>For each extra distribution set you add to the project, the distribution plugin adds the following tasks:</para>
+ <table>
+ <title>Multiple distributions - tasks</title>
+ <thead>
+ <tr>
+ <td>Task name</td>
+ <td>Depends on</td>
+ <td>Type</td>
+ <td>Description</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>
+ <literal><replaceable>${distribution.name}</replaceable>DistZip</literal>
+ </td>
+ <td>
+ <literal>-</literal>
+ </td>
+ <td>
+ <apilink class="org.gradle.api.tasks.bundling.Zip"/>
+ </td>
+ <td>
+ Creates a ZIP archive of the distribution contents
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <literal><replaceable>${distribution.name}</replaceable>DistTar</literal>
+ </td>
+ <td>
+ <literal>-</literal>
+ </td>
+ <td>
+ <apilink class="org.gradle.api.tasks.bundling.Tar"/>
+ </td>
+ <td>
+ Creates a TAR archive of the distribution contents
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <literal>install<replaceable>${distribution.name.capitalize()}</replaceable>Dist</literal>
+ </td>
+ <td>
+ <literal>-</literal>
+ </td>
+ <td>
+ <apilink class="org.gradle.api.tasks.Sync"/>
+ </td>
+ <td>
+ Assembles the distribution content and installs it on the current machine
+ </td>
+ </tr>
+ </table>
+ <sample id="multipleDistribution" dir="userguide/distribution" title="Adding extra distributions">
<sourcefile file="build.gradle" snippet="custom-distribution"/>
</sample>
+ <para>
+ This will add following tasks to the project:
+ <itemizedlist>
+ <listitem>customDistZip</listitem>
+ <listitem>customDistTar</listitem>
+ <listitem>installCustomDist</listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ Given that the project name is "<literal>myproject</literal>" and version "<literal>1.2</literal>", running "<userinput>gradle customDistZip</userinput>" will produce a
+ ZIP file named "<literal>myproject-custom-1.2.zip</literal>".
+ </para>
+ <para>
+ Running "<userinput>gradle installCustomDist</userinput>" will install the distribution contents into "<literal><replaceable>$buildDir</replaceable>/install/custom</literal>".
+ </para>
</section>
-
<section>
- <title>Multiple distributions</title>
- <para>The distribution plugin allow to generate multiple distributions.
-
+ <title>Distribution contents</title>
+ <para>
+ All of the files in the "<literal>src/<replaceable>$distribution.name</replaceable>/dist</literal>" directory will automatically be included in the distribution.
+ You can add additional files by configuring the <apilink class="org.gradle.api.distribution.Distribution" /> object that is part of the container.
</para>
- <sample id="multipleDistribution" dir="userguide/distribution" title="Declare multiple distributions">
- <sourcefile file="build.gradle" snippet="declare-distribution"/>
+ <sample id="configureDistribution" dir="userguide/distribution" title="Configuring the main distribution">
+ <sourcefile file="build.gradle" snippet="configure-distribution"/>
</sample>
- <para>This will following tasks to the project : customDistZip, customDistTar, installcustomDist. Given that the project name is myproject, then running gradle customDistZip will produce a ZIP file called myproject-custom-1.2.zip
- and running customDistTar will produce myproject-custom-1.2.tar. Running installcustomDist will install distribution contents into buildDir/install/custom.</para>
- </section>
-
- <section>
- <title>Extension properties</title>
- <para>The distribution plugin add an extension to the project, which you can use to configure its behaviour. See <apilink class="org.gradle.api.Project"/>.
- </para>
+ <para>
+ In the above example, the content of the "<literal>src/readme</literal>" directory will be included in the distribution
+ (along with the files in the "<literal>src/dist/main</literal>" directory which are added by default).
+ </para>
+ <para>
+ The "<literal>baseName</literal>" property has also been changed. This will cause the distribution archives to be created with a different name.
+ </para>
</section>
-
</chapter>
diff --git a/subprojects/docs/src/docs/userguide/eclipsePlugin.xml b/subprojects/docs/src/docs/userguide/eclipsePlugin.xml
index 3354d6f..e0e9c59 100644
--- a/subprojects/docs/src/docs/userguide/eclipsePlugin.xml
+++ b/subprojects/docs/src/docs/userguide/eclipsePlugin.xml
@@ -271,7 +271,7 @@
<section>
<title>Customizing the generated files</title>
<para>
- The Eclipse plugin allows you to customise the generated metadata files. The plugin provides a DSL for configuring model objects
+ The Eclipse plugin allows you to customize the generated metadata files. The plugin provides a DSL for configuring model objects
that model the Eclipse view of the project. These model objects are then merged with the existing Eclipse XML metadata to ultimately
generate new metadata. The model objects provide lower level hooks for working with domain objects representing the file content
before and after merging with the model configuration. They also provide a very low level hook for working directly with the raw
@@ -301,7 +301,7 @@
<listitem>The <code>beforeMerged</code> hook is executed with a domain object representing the existing file</listitem>
<listitem>The existing content is merged with the configuration inferred from the Gradle build or defined explicitly in the eclipse DSL</listitem>
<listitem>The <code>whenMerged</code> hook is executed with a domain object representing contents of the file to be persisted</listitem>
- <listitem>The <code>withXml</code> hook is executed with a raw representation of the xml that will be persisted</listitem>
+ <listitem>The <code>withXml</code> hook is executed with a raw representation of the XML that will be persisted</listitem>
<listitem>The final XML is persisted</listitem>
</orderedlist>
The following table lists the domain object used for each of the Eclipse model types:
diff --git a/subprojects/docs/src/docs/userguide/gradleDaemon.xml b/subprojects/docs/src/docs/userguide/gradleDaemon.xml
index 696c2a7..bd945f5 100644
--- a/subprojects/docs/src/docs/userguide/gradleDaemon.xml
+++ b/subprojects/docs/src/docs/userguide/gradleDaemon.xml
@@ -50,8 +50,8 @@
<para>
The Tooling API (see <xref linkend="embedding"/>)
uses the daemon all the time, e.g. you cannot officially use the Tooling API without the daemon.
- This means that if you use the STS Gradle plugin for Eclipse or new Intellij IDEA plugin (IDEA>10)
- the daemon acts behind the hood.
+ This means that whenever you are using the STS Gradle plugin for Eclipse or the Gradle support in Intellij IDEA,
+ you're already using the Gradle Daemon.
</para>
<para>In future the daemon will offer more features:
<itemizedlist>
diff --git a/subprojects/docs/src/docs/userguide/gradleWrapper.xml b/subprojects/docs/src/docs/userguide/gradleWrapper.xml
index 0f73982..3c1b519 100644
--- a/subprojects/docs/src/docs/userguide/gradleWrapper.xml
+++ b/subprojects/docs/src/docs/userguide/gradleWrapper.xml
@@ -57,33 +57,24 @@
</para>
<section id='sec:configuration'>
<title>Configuration</title>
- <para>If you run Gradle with <command>gradlew</command>, Gradle checks if a Gradle distribution for the wrapper
+ <para>If you run Gradle with <command>gradlew</command>, the wrapper checks if a Gradle distribution for the wrapper
is available. If not it tries to download it, otherwise it delegates to the <command>gradle</command>
command of this distribution with all the arguments passed originally to the <command>gradlew</command>
command.
</para>
- <para>You can specify where the wrapper files should be stored (within your project directory):</para>
- <sample id="wrapperCustomized" dir="userguide/wrapper/customized" title="Configuration of wrapper task">
- <sourcefile file="build.gradle"/>
- <layout after="wrapper">
- gradlew
- gradlew.bat
- wrapper/wrapper.jar
- wrapper/wrapper.properties
- </layout>
- </sample>
<para>
- You can specify the download URL of the wrapper distribution. You can also specify where the wrapper distribution
- should be stored and unpacked (either within the project or within the Gradle user home dir). If the wrapper
- is run and there is local archive of the wrapper distribution Gradle tries to download it and stores it at
- the specified place. If there is no unpacked wrapper distribution Gradle unpacks the local archive of the
- wrapper distribution at the specified place. All the configuration options have defaults except the version of the wrapper distribution.</para>
+ When you configure the <literal>Wrapper</literal> task, you can specify the Gradle version you wish to use. The <command>gradlew</command>
+ command will download the appropriate distribution from the Gradle repository.
+ Alternatively, you can specify the download URL of the Gradle distribution. The <command>gradlew</command> command will use this URL to download
+ the distribution.
+ If you specify neither a Gradle version or download URL, the <command>gradlew</command> command will by default download whichever version
+ of Gradle was used to generate the wrapper files.
+ </para>
<para>For the details on how to configure the wrapper, see <apilink class="org.gradle.api.tasks.wrapper.Wrapper"/>
</para>
- <para>If you don't
- want any download to happen when your project is build via <command>gradlew</command>, simply add the Gradle
+ <para>If you don't want any download to happen when your project is build via <command>gradlew</command>, simply add the Gradle
distribution zip to your version control at the location specified by your wrapper configuration.
- Relative url is supported - you can specify a distribution file relative to the location of <literal>gradle-wrapper.properties</literal> file.
+ A relative URL is supported - you can specify a distribution file relative to the location of <literal>gradle-wrapper.properties</literal> file.
</para>
<para>If you build via the wrapper, any existing Gradle distribution installed on the machine is ignored.
</para>
@@ -95,39 +86,4 @@
What should always work is to execute <literal>sh gradlew</literal>.
</para>
</section>
- <section id='sec:environment_variable'>
- <title>Environment variable</title>
- <para>Some rather exotic use cases might occur when working with the Gradle Wrapper. For example the continuous
- integration server goes down during unzipping the Gradle distribution. As the distribution directory exists
- <command>gradlew</command>
- delegates to it but the distribution is corrupt. Or the zip-distribution was not properly downloaded. When
- you have no admin right on the continuous integration server to remove the corrupt files, Gradle offers a
- solution via environment variables.
- </para>
- <table>
- <title>Gradle wrapper environment variables</title>
- <thead>
- <tr>
- <td>Variable Name</td>
- <td>Meaning</td>
- </tr>
- </thead>
- <tr>
- <td>GRADLE_WRAPPER_ALWAYS_UNPACK</td>
- <td>If set to <literal>true</literal>, the distribution directory gets always deleted when
- <command>gradlew</command>
- is run and the distribution zip is freshly unpacked. If the zip is not there, Gradle tries to
- download it.
- </td>
- </tr>
- <tr>
- <td>GRADLE_WRAPPER_ALWAYS_DOWNLOAD</td>
- <td>If set to <literal>true</literal>, the distribution directory and the distribution zip gets always
- deleted when <command>gradlew</command>
- is run and the distribution zip is freshly downloaded.
- </td>
- </tr>
-
- </table>
- </section>
</chapter>
diff --git a/subprojects/docs/src/docs/userguide/groovyPlugin.xml b/subprojects/docs/src/docs/userguide/groovyPlugin.xml
index b33bb14..8754dab 100644
--- a/subprojects/docs/src/docs/userguide/groovyPlugin.xml
+++ b/subprojects/docs/src/docs/userguide/groovyPlugin.xml
@@ -153,21 +153,13 @@
<section>
<title>Dependency management</title>
- <para>Because Gradle itself is partly implemented in Groovy, and its build language is also based on Groovy, Gradle already ships
- with a Groovy library (1.8.6 as of Gradle 1.3). Nevertheless, Groovy projects need to explicitly add a Groovy dependency to
- the appropriate configuration(s). This dependency, which can be the same or a different Groovy version than the one used internally by Gradle,
- will then be used as a compile and runtime dependency for the project's Groovy code. It will also be used to execute the Groovy
- compiler and Groovydoc tool, respectively.
- <footnote>
- More precisely, if a <literal>GroovyCompile</literal> or <literal>Groovydoc</literal> task's <literal>groovyClasspath</literal>
- is empty, the plugin searches the task's <literal>classpath</literal> for a
- <literal>groovy-all(-indy)</literal> or <literal>groovy(-indy)</literal> artifact. If it finds the former, it adds the same artifact
- to <literal>groovyClasspath</literal>. If it finds the latter, and the project has at least one repository declared, the plugin adds
- a corresponding repository dependency to <literal>groovyClasspath</literal>.
- </footnote>
+ <para>Because Gradle's build language is based on Groovy, and parts of Gradle are implemented in Groovy, Gradle already ships
+ with a Groovy library (1.8.6 as of Gradle 1.6). Nevertheless, Groovy projects need to explicitly declare a Groovy dependency.
+ This dependency will then be used on compile and runtime class paths. It will also be used to get hold of the Groovy compiler
+ and Groovydoc tool, respectively.
</para>
<para>
- If Groovy is used both for production code, the Groovy dependency should be added to the <literal>compile</literal>
+ If Groovy is used for production code, the Groovy dependency should be added to the <literal>compile</literal>
configuration:
</para>
<sample id="quickstartGroovyDependency" dir="groovy/quickstart" title="Configuration of Groovy dependency">
@@ -175,26 +167,19 @@
</sample>
<para>
If Groovy is only used for test code, the Groovy dependency should be added to the <literal>testCompile</literal>
- (but not the <literal>compile</literal>) configuration:
+ configuration:
</para>
<sample id="groovyTestDependency" dir="userguide/groovy/groovyDependency" title="Configuration of Groovy test dependency">
<sourcefile file="build.gradle" snippet="groovy-test-dependency"/>
</sample>
<para>
- To use the same Groovy library that ships with Gradle, declare a <literal>localGroovy()</literal> dependency. Note that
+ To use the Groovy library that ships with Gradle, declare a <literal>localGroovy()</literal> dependency. Note that
different Gradle versions ship with different Groovy versions; as such, using <literal>localGroovy()</literal> is less
- safe then explicitly choosing a Groovy version.
+ safe then declaring a regular Groovy dependency.
</para>
<sample id="bundledGroovyDependency" dir="userguide/groovy/groovyDependency" title="Configuration of bundled Groovy dependency">
<sourcefile file="build.gradle" snippet="bundled-groovy-dependency"/>
</sample>
- <para>
- In earlier Gradle versions, the Groovy dependency was instead added to the <literal>groovy</literal> configuration.
- This is no longer the preferred approach, but is still supported for backwards compatibility.
- </para>
- <sample id="groovyConfiguration" dir="userguide/groovy/groovyDependency" title="Configuration of Groovy configuration">
- <sourcefile file="build.gradle" snippet="groovy-configuration"/>
- </sample>
<para>The Groovy library doesn't necessarily have to come from a remote repository. It could also come from a local
<literal>lib</literal> directory, perhaps checked in to source control:</para>
<sample id="groovyFileDependency" dir="userguide/tutorial/groovyWithFlatDir" title="Configuration of Groovy file dependency">
@@ -204,29 +189,32 @@
</section>
<section>
- <title>Adding custom GroovyCompile and Groovydoc tasks</title>
- <para>
- When adding custom <literal>GroovyCompile</literal> and <literal>Groovydoc</literal> tasks, it's important to understand
- that these tasks consume Groovy in two ways: on their <literal>classpath</literal>, and on their <literal>groovyClasspath</literal>.
- The former is the regular class path required by these tools to locate referenced classes, and will typically contain more than
- just the Groovy library. The latter is used to load the Groovy compiler and Groovydoc tool, respectively, and shouldn't contain anything
- other than the Groovy library and its dependencies.
- </para>
+ <title>Automatic configuration of groovyClasspath</title>
<para>
- Unless <literal>groovyClasspath</literal> is explicitly configured for a task, the Groovy (base) plugin will try to infer
- the Groovy library to be used from the task's<literal>classpath</literal>. For example, if <literal>classpath</literal> contains
- <literal>groovy-all-2.0.5.jar</literal>, the plugin will add the same dependency to <literal>groovyClasspath</literal>. If the project
- has at least one repository defined, an external dependency will be added (e.g. <literal>"org.codehaus.groovy:groovy-all:2.0.5"</literal>);
- otherwise, a file dependency will be added.
+ <literal>GroovyCompile</literal> and <literal>Groovydoc</literal> tasks consume Groovy in two ways: on their <literal>classpath</literal>,
+ and on their <literal>groovyClasspath</literal>. The former is used to locate classes referenced by the source code, and will typically
+ contain the Groovy library along with other libraries. The latter is used to load and execute the Groovy compiler and Groovydoc tool,
+ respectively, and should only contain the Groovy library and its dependencies.
</para>
<para>
- Note: When using the <literal>groovy</literal> rather than the <literal>groovy-all</literal> artifact, automatic configuration of
- <literal>groovyClasspath</literal> will only work correctly if the project declares a repository that contains the <literal>groovy</literal>
- artifact along with a descriptor (<filename>pom.xml</filename> or <filename>ivy.xml</filename>) listing its dependencies. Otherwise, only the
- artifact itself will be added to <literal>groovyClasspath</literal>, which will likely result in a <literal>NoClassDefFoundError</literal>
- during compilation.
+ Unless a task's <literal>groovyClasspath</literal> is configured explicitly, the Groovy (base) plugin will try to infer it
+ from the task's <literal>classpath</literal>. This is done as follows:
+ <itemizedlist>
+ <listitem>
+ If a <literal>groovy-all(-indy)</literal> Jar is found on <literal>classpath</literal>, the same Jar will be added to
+ <literal>groovyClasspath</literal>.
+ </listitem>
+ <listitem>
+ If a <literal>groovy(-indy)</literal> Jar is found on <literal>classpath</literal>, and the project has at least one repository declared,
+ a corresponding <literal>groovy(-indy)</literal> repository dependency will be added to <literal>groovyClasspath</literal>.
+ </listitem>
+ <listitem>
+ Otherwise, execution of the task will fail with a message saying that <literal>groovyClasspath</literal> could not be inferred.
+ </listitem>
+ </itemizedlist>
</para>
</section>
+
<section>
<title>Convention properties</title>
<para>The Groovy plugin does not add any convention properties to the project.</para>
diff --git a/subprojects/docs/src/docs/userguide/groovyTutorial.xml b/subprojects/docs/src/docs/userguide/groovyTutorial.xml
index e1349c7..2178d56 100644
--- a/subprojects/docs/src/docs/userguide/groovyTutorial.xml
+++ b/subprojects/docs/src/docs/userguide/groovyTutorial.xml
@@ -38,9 +38,9 @@
<para>To use the groovy compilation tasks, you must also declare the Groovy version to use and where to find the
Groovy libraries. You do this by adding a dependency to the <literal>groovy</literal> configuration.
The <literal>compile</literal> configuration inherits this dependency, so the groovy libraries will
- be included in classpath when compiling Groovy and Java source. For our sample, we will use Groovy 1.7.10
+ be included in classpath when compiling Groovy and Java source. For our sample, we will use Groovy 2.0.5
from the public Maven repository:</para>
- <sample id="groovyQuickstart" dir="groovy/quickstart" title="Dependency on Groovy 1.7.10">
+ <sample id="groovyQuickstart" dir="groovy/quickstart" title="Dependency on Groovy 2.0.5">
<sourcefile file="build.gradle" snippet="groovy-dependency"/>
</sample>
<para>Here is our complete build file:</para>
diff --git a/subprojects/docs/src/docs/userguide/ideSupport.xml b/subprojects/docs/src/docs/userguide/ideSupport.xml
index b1710a3..9e83f4d 100644
--- a/subprojects/docs/src/docs/userguide/ideSupport.xml
+++ b/subprojects/docs/src/docs/userguide/ideSupport.xml
@@ -52,7 +52,7 @@
</para>
<figure>
<title>gradle-imports</title>
- <programlisting><xi:include href='../../../../../subprojects/core/src/main/resources/org/gradle/configuration/default-imports.txt' parse='text'/></programlisting>
+ <programlisting><xi:include href='../../../build/generated-resources/main/default-imports.txt' parse='text'/></programlisting>
</figure>
</section>
</appendix>
diff --git a/subprojects/docs/src/docs/userguide/ideaPlugin.xml b/subprojects/docs/src/docs/userguide/ideaPlugin.xml
index bd4326a..9948f06 100644
--- a/subprojects/docs/src/docs/userguide/ideaPlugin.xml
+++ b/subprojects/docs/src/docs/userguide/ideaPlugin.xml
@@ -192,7 +192,7 @@
<apilink class="org.gradle.plugins.ide.idea.model.IdeaWorkspace"/>
</td>
<td><literal>idea.workspace</literal></td>
- <td>Allows configuring the workspace xml</td>
+ <td>Allows configuring the workspace XML</td>
</tr>
</table>
</section>
@@ -226,7 +226,7 @@
<listitem>The <code>beforeMerged</code> hook is executed with a domain object representing the existing file</listitem>
<listitem>The existing content is merged with the configuration inferred from the Gradle build or defined explicitly in the eclipse DSL</listitem>
<listitem>The <code>whenMerged</code> hook is executed with a domain object representing contents of the file to be persisted</listitem>
- <listitem>The <code>withXml</code> hook is executed with a raw representation of the xml that will be persisted</listitem>
+ <listitem>The <code>withXml</code> hook is executed with a raw representation of the XML that will be persisted</listitem>
<listitem>The final XML is persisted</listitem>
</orderedlist>
The following table lists the domain object used for each of the model types:
diff --git a/subprojects/docs/src/docs/userguide/img/jacocoHtmlReport.png b/subprojects/docs/src/docs/userguide/img/jacocoHtmlReport.png
new file mode 100644
index 0000000..15fe295
Binary files /dev/null and b/subprojects/docs/src/docs/userguide/img/jacocoHtmlReport.png differ
diff --git a/subprojects/docs/src/docs/userguide/initscripts.xml b/subprojects/docs/src/docs/userguide/initscripts.xml
index f50a124..2b8c208 100644
--- a/subprojects/docs/src/docs/userguide/initscripts.xml
+++ b/subprojects/docs/src/docs/userguide/initscripts.xml
@@ -46,7 +46,7 @@
</para>
</listitem>
<listitem>
- <para>Register build loggers. You might wish to customise how Gradle logs the events that it generates.
+ <para>Register build loggers. You might wish to customize how Gradle logs the events that it generates.
</para>
</listitem>
</itemizedlist>
@@ -127,4 +127,21 @@
<output args="--init-script init.gradle -q doNothing"/>
</sample>
</section>
+ <section>
+ <title>Init script plugins</title>
+ <para>Similar to a Gradle build script or a Gradle settings file, plugins can be applied on init scripts.
+ </para>
+ <sample id="usePluginsInInitScripts" dir="userguide/initScripts/plugins" title="Using plugins in init scripts">
+ <sourcefile file="init.gradle" snippet="init-script-plugin"/>
+ <sourcefile file="build.gradle" snippet="show-repos-task"/>
+ <output args="-q -I init.gradle showRepositories"/>
+ </sample>
+ <para>The plugin in the sample init scripts ensures, that only a specified repository is used when running the build.
+ </para>
+ <para>When applying plugins within the init script, Gradle instantiates the plugin and calls the plugin
+ instance's <apilink class="org.gradle.api.Plugin" method="apply"/> method. The <literal>gradle</literal> object is passed as a parameter,
+ which can be used to configure all aspects of a build.
+ Of course, the applied plugin can be resolved as external dependency as described in <xref linkend='sec:custom_classpath'/>
+ </para>
+ </section>
</chapter>
diff --git a/subprojects/docs/src/docs/userguide/jacocoPlugin.xml b/subprojects/docs/src/docs/userguide/jacocoPlugin.xml
new file mode 100644
index 0000000..26e49ac
--- /dev/null
+++ b/subprojects/docs/src/docs/userguide/jacocoPlugin.xml
@@ -0,0 +1,248 @@
+<!--
+ ~ Copyright 2013 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ 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.
+ -->
+
+<chapter id="jacoco_plugin">
+ <title>The JaCoCo Plugin</title>
+ <note>
+ <para>
+ The JaCoCo plugin is currently <link linkend="feature_lifecycle">incubating</link>. Please be aware that the DSL and other configuration may change in later Gradle versions.
+ </para>
+ </note>
+
+ <para>The JaCoCo plugin provides code coverage metrics for Java code via integration with <ulink url="http://www.eclemma.org/jacoco/">JaCoCo</ulink>.
+ </para>
+ <section>
+ <title>Getting Started</title>
+ <para>To get started, apply the JaCoCo plugin to the project you want to calculate code coverage for.</para>
+ <sample id="applyJacoco" dir="testing/jacoco/quickstart" title="Applying the JaCoCo plugin">
+ <sourcefile file="build.gradle" snippet="apply-plugin"/>
+ </sample>
+ <para>
+ If the Java plugin is also applied to your project, a new task named
+ <literal>jacocoTestReport</literal>
+ is created that depends on the
+ <literal>test</literal>
+ task.
+ The report is available at
+ <filename><replaceable>$buildDir</replaceable>/reports/jacoco/test</filename>. By default, a HTML report is generated.
+ </para>
+ </section>
+
+ <section>
+ <title>Configuring the JaCoCo Plugin</title>
+ <para>
+ The JaCoCo plugin adds a project extension named <literal>jacoco</literal> of type <apilink class="org.gradle.testing.jacoco.plugins.JacocoPluginExtension"/>,
+ which allows configuring defaults for JaCoCo usage in your build.
+ </para>
+ <sample id="configJacoco" dir="testing/jacoco/quickstart" title="Configuring JaCoCo plugin settings">
+ <sourcefile file="build.gradle" snippet="jacoco-configuration"/>
+ </sample>
+ <table>
+ <title>Gradle defaults for JaCoCo properties</title>
+ <thead>
+ <tr>
+ <td>Property</td>
+ <td>Gradle default</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>reportsDir</td>
+ <td>"<replaceable>$buildDir</replaceable>/reports/jacoco"
+ </td>
+ </tr>
+ </table>
+ </section>
+ <section>
+ <title>JaCoCo Report configuration</title>
+ <para>The
+ <apilink class="org.gradle.testing.jacoco.tasks.JacocoReport"/>
+ task can be used to generate code coverage reports in different formats.
+ It implements the standard Gradle type <apilink class="org.gradle.api.reporting.Reporting"/> and exposes a report container of
+ type <apilink class="org.gradle.testing.jacoco.tasks.JacocoReportsContainer" />.
+ </para>
+ <sample id="configJacocoReport" dir="testing/jacoco/quickstart" title="Configuring test task">
+ <sourcefile file="build.gradle" snippet="report-configuration"/>
+ </sample>
+ <imageobject>
+ <imagedata fileref="img/jacocoHtmlReport.png" width="903px" depth="277px"/>
+ </imageobject>
+ </section>
+
+ <section>
+ <title>JaCoCo specific task configuration</title>
+ <para>The JaCoCo plugin adds a
+ <apilink class="org.gradle.testing.jacoco.plugins.JacocoTaskExtension"/>
+ extension to all tasks of type
+ <apilink class="org.gradle.api.tasks.testing.Test"/>.
+ This extension allows the configuration of the JaCoCo specific properties of the test task.
+ </para>
+ <sample id="jacocotesttast" dir="testing/jacoco/quickstart" title="Configuring test task">
+ <sourcefile file="build.gradle" snippet="testtask-configuration"/>
+ </sample>
+ <table>
+ <title>Default values of the JaCoCo Task extension</title>
+ <thead>
+ <tr>
+ <td>Property</td>
+ <td>Gradle default</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>enabled</td>
+ <td>true</td>
+ </tr>
+ <tr>
+ <td>destPath</td>
+ <td><replaceable>$buildDir</replaceable>/jacoco
+ </td>
+ </tr>
+ <tr>
+ <td>append</td>
+ <td>true</td>
+ </tr>
+ <tr>
+ <td>includes</td>
+ <td>[]</td>
+ </tr>
+ <tr>
+ <td>excludes</td>
+ <td>[]</td>
+ </tr>
+ <tr>
+ <td>excludeClassLoaders</td>
+ <td>[]</td>
+ </tr>
+ <tr>
+ <td>sessionId</td>
+ <td>
+ <literal>auto-generated</literal>
+ </td>
+ </tr>
+ <tr>
+ <td>dumpOnExit</td>
+ <td>
+ <literal>true</literal>
+ </td>
+ </tr>
+ <tr>
+ <td>output</td>
+ <td>
+ <literal>Output.FILE</literal>
+ </td>
+ </tr>
+ <tr>
+ <td>address</td>
+ <td>
+ <literal>-</literal>
+ </td>
+ </tr>
+ <tr>
+ <td>port</td>
+ <td>
+ <literal>-</literal>
+ </td>
+ </tr>
+ <tr>
+ <td>classDumpPath</td>
+ <td>
+ <literal>-</literal>
+ </td>
+ </tr>
+ <tr>
+ <td>jmx</td>
+ <td>
+ <literal>false</literal>
+ </td>
+ </tr>
+ </table>
+ <para>While all tasks of type
+ <apilink class="org.gradle.api.tasks.testing.Test"/>
+ are automatically enhanced to provide coverage information when the <literal>java</literal> plugin has been applied,
+ any task that implements <apilink class="org.gradle.process.JavaForkOptions"/> can be enhanced by the JaCoCo plugin.
+ That is, any task that forks Java processes can be used to generate coverage information.
+ </para>
+ <para>
+ For example you can configure your build to generate code coverage using the <literal>application</literal> plugin.
+ </para>
+ <sample id="jacoco-application-setup" dir="testing/jacoco/application" includeLocation="true" title="Using application plugin to generate code coverage data">
+ <sourcefile file="build.gradle" snippet="application-configuration"/>
+ </sample>
+ <sample id="jacoco-application-output" dir="testing/jacoco/application" title="Coverage reports generated by applicationCodeCoverageReport">
+ <layout after='run applicationCodeCoverageReport'>
+ build/jacoco/run.exec
+ build/reports/jacoco/applicationCodeCoverageReport/html/index.html
+ </layout>
+ </sample>
+ </section>
+
+ <section>
+ <title>Tasks</title>
+ <para>For projects that also apply the Java Plugin, The JaCoCo plugin automatically adds the following tasks:</para>
+ <table>
+ <title>JaCoCo plugin - tasks</title>
+ <thead>
+ <tr>
+ <td>Task name</td>
+ <td>Depends on</td>
+ <td>Type</td>
+ <td>Description</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>
+ <literal>jacocoTestReport</literal>
+ </td>
+ <td>-</td>
+ <td>
+ <apilink class="org.gradle.testing.jacoco.tasks.JacocoReport"/>
+ </td>
+ <td>Generates code coverage report for the test task.</td>
+ </tr>
+ </table>
+ </section>
+
+ <section>
+ <title>Dependency management</title>
+ <para>The JaCoCo plugin adds the following dependency configurations:</para>
+ <table>
+ <title>JaCoCo plugin - dependency configurations</title>
+ <thead>
+ <tr>
+ <td>Name</td>
+ <td>Meaning</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>
+ <filename>jacocoAnt</filename>
+ </td>
+ <td>The JaCoCo Ant library used for running the
+ <literal>JacocoReport</literal>
+ and
+ <literal>JacocoMerge</literal>
+ tasks.
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <filename>jacocoAgent</filename>
+ </td>
+ <td>The JaCoCo agent library used for instrumenting the code under test.</td>
+ </tr>
+ </table>
+ </section>
+
+</chapter>
\ No newline at end of file
diff --git a/subprojects/docs/src/docs/userguide/javaLibraryDistributionPlugin.xml b/subprojects/docs/src/docs/userguide/javaLibraryDistributionPlugin.xml
index c695b8a..28806f3 100644
--- a/subprojects/docs/src/docs/userguide/javaLibraryDistributionPlugin.xml
+++ b/subprojects/docs/src/docs/userguide/javaLibraryDistributionPlugin.xml
@@ -2,9 +2,10 @@
<title>The Java Library Distribution Plugin</title>
<note>
<para>
- The Java library distribution plugin is incubating (see <xref linkend="sec:incubating_state"/>).
+ The Java library distribution plugin is currently <link linkend="feature_lifecycle">incubating</link>. Please be aware that the DSL and other configuration may change in later Gradle versions.
</para>
</note>
+
<para>The Java library distribution plugin adds support for building a distribution ZIP for a Java library. The distribution contains the
JAR file for the library and its dependencies.
</para>
diff --git a/subprojects/docs/src/docs/userguide/javaPlugin.xml b/subprojects/docs/src/docs/userguide/javaPlugin.xml
index 9b177d0..efc7b13 100644
--- a/subprojects/docs/src/docs/userguide/javaPlugin.xml
+++ b/subprojects/docs/src/docs/userguide/javaPlugin.xml
@@ -1228,7 +1228,30 @@
and the for exclude it is <literal>"**/Abstract*.class"</literal>.
</para>
</section>
-
+ <section id="test_grouping">
+ <title>Test grouping</title>
+ <para>JUnit and TestNG allows sophisticated groupings of test methods. </para>
+ <para>For grouping JUnit test classes and methods JUnit 4.8 introduces the concept of categories.
+ <footnote>
+ <para>The JUnit wiki contains a detailed description on how to work with JUnit categories:
+ <ulink url='https://github.com/junit-team/junit/wiki/Categories'/>.
+ </para>
+ </footnote>
+ The <literal>test</literal> task allows the specification of the JUnit categories you want to include and exclude.
+ </para>
+ <sample id="junitcategories" dir="testing/junit/categories" title="JUnit Categories">
+ <sourcefile file="build.gradle" snippet="test-categories"/>
+ </sample>
+ <para>The TestNG framework has a quite similar concept. In TestNG you can specify different test groups.
+ <footnote>
+ <para>The TestNG documentation contains more details about test groups:
+ <ulink url='http://testng.org/doc/documentation-main.html#test-groups'/>.
+ </para>
+ </footnote> The test groups that should be included or excluded from the test execution can be configured in the test task. </para>
+ <sample id="testnggrouping" dir="testing/testng/groups" title="Grouping TestNG tests">
+ <sourcefile file="build.gradle" snippet="test-config"/>
+ </sample>
+ </section>
<section id="test_reporting">
<title>Test reporting</title>
@@ -1258,6 +1281,19 @@
multiple test tasks, then the test report will include only one execution of that class and discard the other executions of that
class. This will be addressed in a future Gradle version.
</para>
+ <section id="testNgParameterizedReporting">
+ <title>TestNG parameterized methods and reporting</title>
+ <para>
+ TestNG supports <ulink url="http://testng.org/doc/documentation-main.html#parameters">parameterizing test methods</ulink>,
+ allowing a particular test method to be executed multiple times with different inputs. Gradle includes the parameter values
+ in its reporting of the test method execution.
+ </para>
+ <para>
+ Given a parameterized test method named <literal>aParameterizedTestMethod</literal> that takes two parameters, it will be reported with the name:
+ <literal>aParameterizedTestMethod(toStringValueOfParam1, toStringValueOfParam2)</literal>. This makes identifying the parameter values for a
+ particular iteration easy.
+ </para>
+ </section>
</section>
<section>
diff --git a/subprojects/docs/src/docs/userguide/javaTutorial.xml b/subprojects/docs/src/docs/userguide/javaTutorial.xml
index edef18d..d1e7c98 100644
--- a/subprojects/docs/src/docs/userguide/javaTutorial.xml
+++ b/subprojects/docs/src/docs/userguide/javaTutorial.xml
@@ -130,27 +130,27 @@
</section>
<section>
- <title>Customising the project</title>
+ <title>customizing the project</title>
<para>The Java plugin adds a number of properties to your project. These properties have default values
which are usually sufficient to get started. It's easy to change these values if they don't suit. Let's
look at this for our sample. Here we will specify the version number for our Java project, along
with the Java version our source is written in. We also add some attributes to the JAR manifest.
</para>
<sample id="javaQuickstart" dir="java/quickstart" title="Customization of MANIFEST.MF">
- <sourcefile file="build.gradle" snippet="customisation"/>
+ <sourcefile file="build.gradle" snippet="customization"/>
</sample>
<tip>
<title>What properties are available?</title>
<para>You can use <userinput>gradle properties</userinput> to list the properties of a project. This will allow
you to see the properties added by the Java plugin, and their default values.</para></tip>
<para>The tasks which the Java plugin adds are regular tasks, exactly the same as if they were declared in
- the build file. This means you can use any of the mechanisms shown in earlier chapters to customise
+ the build file. This means you can use any of the mechanisms shown in earlier chapters to customize
these tasks. For example, you can set the properties of a task, add behaviour to a task, change the
dependencies of a task, or replace a task entirely. In our sample, we will configure the
<literal>test</literal> task, which is of type <apilink class="org.gradle.api.tasks.testing.Test"/>, to
add a system property when the tests are executed: </para>
<sample id="javaQuickstart" dir="java/quickstart" title="Adding a test system property">
- <sourcefile file="build.gradle" snippet="task-customisation"/>
+ <sourcefile file="build.gradle" snippet="task-customization"/>
</sample>
</section>
diff --git a/subprojects/docs/src/docs/userguide/mavenPlugin.xml b/subprojects/docs/src/docs/userguide/mavenPlugin.xml
index 7148821..4848515 100644
--- a/subprojects/docs/src/docs/userguide/mavenPlugin.xml
+++ b/subprojects/docs/src/docs/userguide/mavenPlugin.xml
@@ -156,7 +156,7 @@
</sample>
<para>That is all. Calling the
<literal>uploadArchives</literal>
- task will generate the POM and deploys the artifact and the pom to the specified repository.
+ task will generate the POM and deploys the artifact and the POM to the specified repository.
</para>
<para>There is some more work to do if you need support for other protocols than <literal>file</literal>. In
this case the native Maven code we delegate to needs additional libraries. Which libraries depend on the
diff --git a/subprojects/docs/src/docs/userguide/multiproject.xml b/subprojects/docs/src/docs/userguide/multiproject.xml
index 7ce1e20..061b6fa 100644
--- a/subprojects/docs/src/docs/userguide/multiproject.xml
+++ b/subprojects/docs/src/docs/userguide/multiproject.xml
@@ -13,7 +13,7 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<chapter id='multi_project_builds' xmlns:xi="http://www.w3.org/2001/XInclude">
+<chapter id='multi_project_builds'>
<title>Multi-project Builds</title>
<para>The powerful support for multi-project builds is one of Gradle's unique selling points. This topic is also the
most intellectually challenging.
@@ -465,7 +465,7 @@
distribution out of them.
<footnote>
<para>The real use case we had, was using <ulink url='http://lucene.apache.org/solr'/>, where you
- need a separate war for each index your are accessing. That was one reason why we have created a
+ need a separate war for each index you are accessing. That was one reason why we have created a
distribution of webapps. The Resin servlet container allows us, to let such a distribution point
to a base installation of the servlet container.
</para>
diff --git a/subprojects/docs/src/docs/userguide/organizeBuildLogic.xml b/subprojects/docs/src/docs/userguide/organizeBuildLogic.xml
index ae993c9..4681cd8 100644
--- a/subprojects/docs/src/docs/userguide/organizeBuildLogic.xml
+++ b/subprojects/docs/src/docs/userguide/organizeBuildLogic.xml
@@ -118,7 +118,7 @@
<para>Listed below is the default build script that Gradle applies to the <filename>buildSrc</filename> project:</para>
<figure>
<title>Default buildSrc build script</title>
- <programlisting><xi:include href='../../../../../subprojects/core/src/main/resources/org/gradle/initialization/defaultBuildSourceScript.txt' parse='text'/></programlisting>
+ <programlisting><xi:include href='../../../../../subprojects/core/src/main/resources/org/gradle/initialization/buildsrc/defaultBuildSourceScript.txt' parse='text'/></programlisting>
</figure>
<para>
This means that you can just put you build source code in this directory and stick to the layout convention for a
diff --git a/subprojects/docs/src/docs/userguide/publishingIvy.xml b/subprojects/docs/src/docs/userguide/publishingIvy.xml
index a00837d..fb1fd67 100644
--- a/subprojects/docs/src/docs/userguide/publishingIvy.xml
+++ b/subprojects/docs/src/docs/userguide/publishingIvy.xml
@@ -18,11 +18,11 @@
<title>Ivy Publishing (new)</title>
<note>
<para>
- This chapter describes the new <emphasis>incubating</emphasis> Ivy publishing support provided by the “<literal>ivy-publish</literal>”
+ This chapter describes the new <link linkend="feature_lifecycle">incubating</link> Ivy publishing support provided by the “<literal>ivy-publish</literal>”
plugin. Eventually this new publishing support will replace publishing via the <literal>Upload</literal> task.
</para>
<para>
- If you are looking for documentation on 'traditional' Ivy publishing using the <literal>Upload</literal> task please see
+ If you are looking for documentation on the original Ivy publishing support using the <literal>Upload</literal> task please see
<xref linkend="artifact_management"/>.
</para>
</note>
@@ -82,7 +82,7 @@
<para>
For the “<literal>ivy-publish</literal>” plugin to have any effect, a <apilink class="org.gradle.api.publish.ivy.IvyPublication" /> must be added to the set of publications.
This publication determines which artifacts are actually published as well as the details included in the associated Ivy module descriptor file.
- A publication can be configured by adding components, customising artifacts, and by modifying the generated module descriptor file directly.
+ A publication can be configured by adding components, customizing artifacts, and by modifying the generated module descriptor file directly.
</para>
<section>
<title>Publishing a Software Component</title>
@@ -137,13 +137,13 @@
<sourcefile file="build.gradle" snippet="publish-custom-artifact" />
</sample>
<para>
- See <apilink class="org.gradle.api.publish.ivy.IvyPublication" /> for more detailed documentation on how artifacts can be customised.
+ See <apilink class="org.gradle.api.publish.ivy.IvyPublication" /> for more detailed documentation on how artifacts can be customized.
</para>
</section>
<section>
<title>Identity values for the published project</title>
<para>
- The generated Ivy module descriptor file contains an<literal><info></literal> tag that identifies the module.
+ The generated Ivy module descriptor file contains an <literal><info></literal> tag that identifies the module.
The default identity values are derived from the following project properties:
</para>
<itemizedlist>
@@ -152,14 +152,19 @@
<listitem><literal>revision</literal> - <apilink class="org.gradle.api.Project" method="getVersion()" /></listitem>
<listitem><literal>status</literal> - <apilink class="org.gradle.api.Project" method="getStatus()" /></listitem>
</itemizedlist>
+
+ <para>
+ Overriding the default identity values is easy: simply specify the <literal>organisation</literal>, <literal>module</literal>
+ or <literal>revision</literal> attributes when configuring the <literal>IvyPublication</literal>.
+ </para>
+ <sample dir="ivy-publish/multiple-publications" id="publishing_ivy:publish-customize-identity" title="customizing the publication identity">
+ <sourcefile file="build.gradle" snippet="customize-identity" />
+ </sample>
<tip>
Certain repositories are not able to handle all supported characters.
For example, the ':' character cannot be used as an identifier when publishing to a filesystem-backed repository on Windows.
</tip>
<para>
- Note that you can set the value of these project properties in your build script, with the exception of <literal>name</literal>.
- </para>
- <para>
Gradle will handle any valid Unicode character for organisation, module and revision (as well as artifact name, extension and classifier).
The only values that are explicitly prohibited are '<literal>\</literal>', '<literal>/</literal>' and any ISO control character. The supplied values are validated early in publication.
</para>
@@ -189,6 +194,20 @@
The identifier (organisation, module, revision) of the published module is an exception; these values cannot be modified in the descriptor using the `withXML` hook.
</para>
</section>
+ <section>
+ <title>Publishing multiple modules</title>
+ <para>
+ Sometimes it's useful to publish multiple modules from your Gradle build, without creating a separate Gradle subproject.
+ An example is publishing a separate API and implementation jar for your library. With Gradle this is simple:
+ </para>
+ <sample dir="ivy-publish/multiple-publications" id="publishing_ivy:publish-multiple-publications" title="Publishing multiple modules from a single project">
+ <sourcefile file="build.gradle" snippet="multiple-publications" />
+ </sample>
+ <para>
+ If a project defines multiple publications then Gradle will publish each of these to the defined repositories. Each publication
+ must be given a unique identity as described above.
+ </para>
+ </section>
</section>
<section id="publishing_ivy:repositories">
<title>Repositories</title>
@@ -244,8 +263,8 @@
<para>
The “<literal>ivy-publish</literal>” plugin automatically wires in one <apilink class="org.gradle.api.publish.ivy.tasks.GenerateIvyDescriptor" /> task
for each registered <apilink class="org.gradle.api.publish.ivy.IvyPublication" />.
- This task is given a name based on the name of the publication: "<literal>generate«<emphasis>NAME OF PUBLICATION</emphasis>»IvyModuleDescriptor</literal>".
- So in the above example where the publication is named "<literal>ivyJava</literal>", the task will be named "<literal>generateIvyJavaIvyModuleDescriptor</literal>".
+ This task is given a name based on the name of the publication: "<literal>generateDescriptorFileFor«<emphasis>NAME OF PUBLICATION</emphasis>»Publication</literal>".
+ So in the above example where the publication is named "<literal>ivyJava</literal>", the task will be named "<literal>generateDescriptorFileForIvyJavaPublication</literal>".
</para>
<para>
You can specify where the generated Ivy file will be located by setting the <literal>destination</literal> property on the generate task.
@@ -253,7 +272,7 @@
</para>
<sample dir="ivy-publish/descriptor-customization" id="publishingIvyGenerateDescriptor" title="Generating the Ivy module descriptor file">
<sourcefile file="build.gradle" snippet="generate" />
- <output args="generateIvyCustomIvyModuleDescriptor"/>
+ <output args="generateDescriptorFileForIvyCustomPublication"/>
</sample>
<note>
<para>
@@ -298,12 +317,12 @@
<section id="publishing_ivy:future">
<title>Future features</title>
<para>
- The “<literal>ivy-publish</literal>” plugin functionality as described above is incomplete, as the feature is still <firstterm>incubating</firstterm>.
+ The “<literal>ivy-publish</literal>” plugin functionality as described above is incomplete, as the feature is still <link linkend="feature_lifecycle">incubating</link>.
Over the coming Gradle releases, the functionality will be expanded to include (but not limited to):
</para>
<itemizedlist>
- <listitem>Convenient customisation of module attributes (<literal>module</literal>, <literal>organisation</literal> etc.)</listitem>
- <listitem>Convenient customisation of dependencies reported in <literal>module descriptor</literal>.</listitem>
+ <listitem>Convenient customization of module attributes (<literal>module</literal>, <literal>organisation</literal> etc.)</listitem>
+ <listitem>Convenient customization of dependencies reported in <literal>module descriptor</literal>.</listitem>
<listitem>Multiple discreet publications per project</listitem>
</itemizedlist>
</section>
diff --git a/subprojects/docs/src/docs/userguide/publishingMaven.xml b/subprojects/docs/src/docs/userguide/publishingMaven.xml
index a1a9f07..1846942 100644
--- a/subprojects/docs/src/docs/userguide/publishingMaven.xml
+++ b/subprojects/docs/src/docs/userguide/publishingMaven.xml
@@ -18,11 +18,11 @@
<title>Maven Publishing (new)</title>
<note>
<para>
- This chapter describes the new <emphasis>incubating</emphasis> Maven publishing support provided by the “<literal>maven-publish</literal>”
+ This chapter describes the new <link linkend="feature_lifecycle">incubating</link> Maven publishing support provided by the “<literal>maven-publish</literal>”
plugin. Eventually this new publishing support will replace publishing via the <literal>Upload</literal> task.
</para>
<para>
- If you are looking for documentation on 'traditional' Maven publishing using the <literal>Upload</literal> task please see
+ If you are looking for documentation on the original Maven publishing support using the <literal>Upload</literal> task please see
<xref linkend="artifact_management"/>.
</para>
</note>
@@ -81,7 +81,7 @@
<para>
For the “<literal>maven-publish</literal>” plugin to have any effect, a <apilink class="org.gradle.api.publish.maven.MavenPublication" /> must be added to the set of publications.
This publication determines which artifacts are actually published as well as the details included in the associated POM file.
- A publication can be configured by adding components, customising artifacts, and by modifying the generated POM file directly.
+ A publication can be configured by adding components, customizing artifacts, and by modifying the generated POM file directly.
</para>
<section>
<title>Publishing a Software Component</title>
@@ -136,7 +136,7 @@
<sourcefile file="build.gradle" snippet="publish-custom-artifact" />
</sample>
<para>
- See <apilink class="org.gradle.api.publish.maven.MavenPublication" /> for more detailed documentation on how artifacts can be customised.
+ See <apilink class="org.gradle.api.publish.maven.MavenPublication" /> for more detailed documentation on how artifacts can be customized.
</para>
</section>
@@ -150,14 +150,19 @@
<listitem><literal>artifactId</literal> - <apilink class="org.gradle.api.Project" method="getName()" /></listitem>
<listitem><literal>version</literal> - <apilink class="org.gradle.api.Project" method="getVersion()" /></listitem>
</itemizedlist>
+
+ <para>
+ Overriding the default identity values is easy: simply specify the <literal>groupId</literal>, <literal>artifactId</literal>
+ or <literal>version</literal> attributes when configuring the <literal>MavenPublication</literal>.
+ </para>
+ <sample dir="maven-publish/multiple-publications" id="publishing_maven:publish-customize-identity" title="customizing the publication identity">
+ <sourcefile file="build.gradle" snippet="customize-identity" />
+ </sample>
<tip>
Certain repositories will not be able to handle all supported characters.
For example, the ':' character cannot be used as an identifier when publishing to a filesystem-backed repository on Windows.
</tip>
<para>
- Note that you can set the value of these project properties in your build script, with the exception of <literal>name</literal>.
- </para>
- <para>
Maven restricts 'groupId' and 'artifactId' to a limited character set (<literal>[A-Za-z0-9_\\-.]+</literal>) and Gradle enforces this restriction.
For 'version' (as well as artifact 'extension' and 'classifier'), Gradle will handle any valid Unicode character.
</para>
@@ -191,6 +196,20 @@
The identifier (groupId, artifactId, version) of the published module is an exception; these values cannot be modified in the POM using the `withXML` hook.
</para>
</section>
+ <section>
+ <title>Publishing multiple modules</title>
+ <para>
+ Sometimes it's useful to publish multiple modules from your Gradle build, without creating a separate Gradle subproject.
+ An example is publishing a separate API and implementation jar for your library. With Gradle this is simple:
+ </para>
+ <sample dir="maven-publish/multiple-publications" id="publishing_maven:publish-multiple-publications" title="Publishing multiple modules from a single project">
+ <sourcefile file="build.gradle" snippet="multiple-publications" />
+ </sample>
+ <para>
+ If a project defines multiple publications then Gradle will publish each of these to the defined repositories. Each publication
+ must be given a unique identity as described above.
+ </para>
+ </section>
</section>
<section id="publishing_maven:repositories">
diff --git a/subprojects/docs/src/docs/userguide/scalaPlugin.xml b/subprojects/docs/src/docs/userguide/scalaPlugin.xml
index 6f84347..f44f371 100644
--- a/subprojects/docs/src/docs/userguide/scalaPlugin.xml
+++ b/subprojects/docs/src/docs/userguide/scalaPlugin.xml
@@ -160,14 +160,10 @@
<section>
<title>Dependency management</title>
<para>
- Scala projects need to add a <literal>scala-library</literal> dependency to the appropriate configuration(s). This dependency will then
- be used as a compile and runtime dependency for the project's Scala code. It will also be used to infer a <literal>scala-compiler</literal>
- dependency for executing the Scala compiler and Scaladoc tool.
+ Scala projects need to declare a <literal>scala-library</literal> dependency. This dependency will then be used on compile and
+ runtime class paths. It will also be used to get hold of the Scala compiler and Scaladoc tool, respectively.
<footnote>
- More precisely, if a <literal>ScalaCompile</literal> or <literal>ScalaDoc</literal> task's <literal>scalaClasspath</literal> is empty,
- and the project has at least one repository declared, the plugin searches the task's <literal>classpath</literal> for a
- <literal>scala-library</literal> artifact, and adds a corresponding <literal>scala-compiler</literal> repository dependency to the
- task's <literal>scalaClasspath</literal>.
+ <para>See <xref linkend="sec:configure_scala_classpath"/>.</para>
</footnote>
</para>
<para>
@@ -179,16 +175,33 @@
</sample>
<para>
If Scala is only used for test code, the <literal>scala-library</literal> dependency should be added to the <literal>testCompile</literal>
- (but not the <literal>compile</literal>)
configuration:
</para>
<sample id="declareScalaTestDependency" dir="userguide/scala/scalaDependency" title="Declaring a Scala dependency for test code">
<sourcefile file="build.gradle" snippet="scala-test-dependency"/>
</sample>
+ </section>
+
+ <section id="sec:configure_scala_classpath">
+ <title>Automatic configuration of scalaClasspath</title>
+ <para>
+ <literal>ScalaCompile</literal> and <literal>ScalaDoc</literal> tasks consume Scala in two ways: on their <literal>classpath</literal>,
+ and on their <literal>scalaClasspath</literal>. The former is used to locate classes referenced by the source code, and will typically
+ contain <literal>scala-library</literal> along with other libraries. The latter is used to load and execute the Scala compiler
+ and Scaladoc tool, respectively, and should only contain the <literal>scala-compiler</literal> library and its dependencies.
+ </para>
<para>
- In earlier Gradle versions, it was necessary to add a <literal>scala-compiler</literal> dependency to the <literal>scalaTools</literal>
- configuration. Although typically no longer necessary (because the compiler dependency is inferred), this is still supported for
- backwards compatibility.
+ Unless a task's <literal>scalaClasspath</literal> is configured explicitly, the Scala (base) plugin will try to infer it
+ from the task's <literal>classpath</literal>. This is done as follows:
+ <itemizedlist>
+ <listitem>
+ If a <literal>scala-library</literal> Jar is found on <literal>classpath</literal>, and the project has at least one repository declared,
+ a corresponding <literal>scala-compiler</literal> repository dependency will be added to <literal>scalaClasspath</literal>.
+ </listitem>
+ <listitem>
+ Otherwise, execution of the task will fail with a message saying that <literal>scalaClasspath</literal> could not be inferred.
+ </listitem>
+ </itemizedlist>
</para>
</section>
diff --git a/subprojects/docs/src/docs/userguide/sonarPlugin.xml b/subprojects/docs/src/docs/userguide/sonarPlugin.xml
index 755e62e..3e2ce40 100644
--- a/subprojects/docs/src/docs/userguide/sonarPlugin.xml
+++ b/subprojects/docs/src/docs/userguide/sonarPlugin.xml
@@ -165,35 +165,35 @@
The following properties can alternatively be set from the command line, as task parameters of the <literal>sonarAnalyze</literal> task.
A task parameter will override any corresponding value set in the build script.
</para>
- <ul>
- <li>
+ <itemizedlist>
+ <listitem>
<literal>server.url</literal>
- </li>
- <li>
+ </listitem>
+ <listitem>
<literal>database.url</literal>
- </li>
- <li>
+ </listitem>
+ <listitem>
<literal>database.driverClassName</literal>
- </li>
- <li>
+ </listitem>
+ <listitem>
<literal>database.username</literal>
- </li>
- <li>
+ </listitem>
+ <listitem>
<literal>database.password</literal>
- </li>
- <li>
+ </listitem>
+ <listitem>
<literal>showSql</literal>
- </li>
- <li>
+ </listitem>
+ <listitem>
<literal>showSqlResults</literal>
- </li>
- <li>
+ </listitem>
+ <listitem>
<literal>verbose</literal>
- </li>
- <li>
+ </listitem>
+ <listitem>
<literal>forceAnalysis</literal>
- </li>
- </ul>
+ </listitem>
+ </itemizedlist>
<para>
Here is a complete example:
</para>
diff --git a/subprojects/docs/src/docs/userguide/sonarRunnerPlugin.xml b/subprojects/docs/src/docs/userguide/sonarRunnerPlugin.xml
index b2a9100..917598d 100644
--- a/subprojects/docs/src/docs/userguide/sonarRunnerPlugin.xml
+++ b/subprojects/docs/src/docs/userguide/sonarRunnerPlugin.xml
@@ -17,7 +17,7 @@
<title>The Sonar Runner Plugin</title>
<note>
<para>
- The Sonar Runner plugin is <link linkend="sec:incubating_state">incubating</link>.
+ The Sonar runner plugin is currently <link linkend="feature_lifecycle">incubating</link>. Please be aware that the DSL and other configuration may change in later Gradle versions.
</para>
</note>
<para>The Sonar Runner plugin provides integration with <ulink url="http://www.sonarsource.org">Sonar</ulink>,
@@ -86,7 +86,7 @@
<sourcefile file="build.gradle" snippet="connection-settings"/>
</sample>
<para>
- For a complete list of standard Sonar properties, consult the<ulink url="http://docs.codehaus.org/display/SONAR/Analysis+Parameters">Sonar documentation</ulink>.
+ For a complete list of standard Sonar properties, consult the <ulink url="http://docs.codehaus.org/display/SONAR/Analysis+Parameters">Sonar documentation</ulink>.
If you happen to use additional Sonar plugins, consult their documentation.
</para>
<para>
diff --git a/subprojects/docs/src/docs/userguide/standardPlugins.xml b/subprojects/docs/src/docs/userguide/standardPlugins.xml
index 53ac590..fa4f5f9 100644
--- a/subprojects/docs/src/docs/userguide/standardPlugins.xml
+++ b/subprojects/docs/src/docs/userguide/standardPlugins.xml
@@ -1,25 +1,10 @@
-<!--
- ~ Copyright 2010 the original author or authors.
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ 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.
- -->
<chapter id="standard_plugins">
<title>Standard Gradle plugins</title>
<para>There are a number of plugins included in the Gradle distribution. These are listed below.
</para>
<section>
<title>Language plugins</title>
- <para>These plugins add support for various languages which can be compiled and executed in the JVM.</para>
+ <para>These plugins add support for various languages which can be compiled for and executed in the JVM.</para>
<table>
<title>Language plugins</title>
<thead>
@@ -149,7 +134,7 @@
</section>
<section>
<title>Integration plugins</title>
- <para>These plugins provide some integration with various build and runtime technologies.</para>
+ <para>These plugins provide some integration with various runtime technologies.</para>
<table>
<title>Integration plugins</title>
<thead>
@@ -162,18 +147,6 @@
</thead>
<tr>
<td>
- <link linkend='announce_plugin'>
- <literal>announce</literal>
- </link>
- </td>
- <td>-</td>
- <td>-</td>
- <td>
- <para>Publish messages to your favourite platforms, such as Twitter or Growl.</para>
- </td>
- </tr>
- <tr>
- <td>
<link linkend='application_plugin'>
<literal>application</literal>
</link>
@@ -189,18 +162,6 @@
</tr>
<tr>
<td>
- <link linkend='build_announcements_plugin'>
- <literal>build-announcements</literal>
- </link>
- </td>
- <td>announce</td>
- <td>-</td>
- <td>
- <para>Sends local announcements to your desktop about interesting events in the build lifecycle.</para>
- </td>
- </tr>
- <tr>
- <td>
<link linkend='ear_plugin'>
<literal>ear</literal>
</link>
@@ -277,7 +238,7 @@
</section>
<section>
<title>Incubating integration plugins</title>
- <para>These plugins provide some integration with various build and runtime technologies.</para>
+ <para>These plugins provide some integration with various runtime technologies.</para>
<table>
<title>Incubating integration plugins</title>
<thead>
@@ -290,14 +251,27 @@
</thead>
<tr>
<td>
+ <link linkend="distribution_plugin">
+ <literal>distribution</literal>
+ </link>
+ </td>
+ <td>-</td>
+ <td>-</td>
+ <td>
+ <para>Adds support for building ZIP and TAR distributions.
+ </para>
+ </td>
+ </tr>
+ <tr>
+ <td>
<link linkend="javaLibraryDistribution_plugin">
<literal>java-library-distribution</literal>
</link>
</td>
- <td><literal>java</literal></td>
+ <td><literal>java</literal>, <literal>distribution</literal></td>
<td>-</td>
<td>
- <para>Adds support for building a ZIP distribution for a Java library.
+ <para>Adds support for building ZIP and TAR distributions for a Java library.
</para>
</td>
</tr>
@@ -308,7 +282,7 @@
</link>
</td>
<td>-</td>
- <td>-</td>
+ <td><literal>java</literal>, <literal>war</literal></td>
<td>
<para>This plugin provides a new DSL to support publishing artifacts to Ivy repositories, which improves on the existing DSL.
</para>
@@ -327,47 +301,45 @@
</para>
</td>
</tr>
+ </table>
+ </section>
+ <section>
+ <title>Software development plugins</title>
+ <para>These plugins provide help with your software development process.</para>
+ <table>
+ <title>Software development plugins</title>
+ <thead>
+ <tr>
+ <td>Plugin Id</td>
+ <td>Automatically applies</td>
+ <td>Works with</td>
+ <td>Description</td>
+ </tr>
+ </thead>
<tr>
<td>
- <link linkend="bootstrap_plugin">
- <literal>maven2Gradle</literal>
+ <link linkend='announce_plugin'>
+ <literal>announce</literal>
</link>
</td>
<td>-</td>
<td>-</td>
<td>
- <para>Adds support for converting an existing Maven build into a Gradle project.
- </para>
+ <para>Publish messages to your favourite platforms, such as Twitter or Growl.</para>
</td>
</tr>
<tr>
<td>
- <link linkend="buildDashboard_plugin">
- <literal>build-dashboard</literal>
+ <link linkend='build_announcements_plugin'>
+ <literal>build-announcements</literal>
</link>
</td>
- <td>reporting-base</td>
+ <td>announce</td>
<td>-</td>
<td>
- <para>Generates build dashboard report.
- </para>
+ <para>Sends local announcements to your desktop about interesting events in the build lifecycle.</para>
</td>
</tr>
- </table>
- </section>
- <section>
- <title>Software development plugins</title>
- <para>These plugins provide help with your software development process.</para>
- <table>
- <title>Software development plugins</title>
- <thead>
- <tr>
- <td>Plugin Id</td>
- <td>Automatically applies</td>
- <td>Works with</td>
- <td>Description</td>
- </tr>
- </thead>
<tr>
<td>
<link linkend='checkstyle_plugin'>
@@ -537,7 +509,7 @@
</link>
</td>
<td>-</td>
- <td>-</td>
+ <td>java-base, java, jacoco</td>
<td>
<para>Provides integration with the
<ulink url="http://www.sonarsource.org">Sonar</ulink>
@@ -562,12 +534,53 @@
</thead>
<tr>
<td>
+ <link linkend="buildDashboard_plugin">
+ <literal>build-dashboard</literal>
+ </link>
+ </td>
+ <td>reporting-base</td>
+ <td>-</td>
+ <td>
+ <para>Generates build dashboard report.
+ </para>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <link linkend="build_setup_plugin">
+ <literal>build-setup</literal>
+ </link>
+ </td>
+ <td>wrapper</td>
+ <td>-</td>
+ <td>
+ <para>Adds support for initializing a new Gradle build. Handles converting a Maven build to a Gradle build.
+ </para>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <link linkend='jacoco_plugin'>
+ <literal>jacoco</literal>
+ </link>
+ </td>
+ <td>reporting-base</td>
+ <td>java</td>
+ <td>
+ <para>Provides integration with the
+ <ulink url="http://www.eclemma.org/jacoco/">JaCoCo</ulink>
+ code coverage library for Java.
+ </para>
+ </td>
+ </tr>
+ <tr>
+ <td>
<link linkend='sonar_runner_plugin'>
<literal>sonar-runner</literal>
</link>
</td>
<td>-</td>
- <td>-</td>
+ <td>java-base, java, jacoco</td>
<td>
<para>Provides integration with the
<ulink url="http://www.sonarsource.org">Sonar</ulink>
@@ -575,6 +588,19 @@
</para>
</td>
</tr>
+ <tr>
+ <td>
+ <link linkend="wrapper_plugin">
+ <literal>wrapper</literal>
+ </link>
+ </td>
+ <td>-</td>
+ <td>-</td>
+ <td>
+ <para>Adds a <apilink class="org.gradle.api.tasks.wrapper.Wrapper"/> task for generating Gradle wrapper files.
+ </para>
+ </td>
+ </tr>
</table>
</section>
<section>
@@ -655,4 +681,4 @@
<ulink url="http://wiki.gradle.org/display/GRADLE/Plugins">wiki</ulink>.
</para>
</section>
-</chapter>
\ No newline at end of file
+</chapter>
diff --git a/subprojects/docs/src/docs/userguide/tasks.xml b/subprojects/docs/src/docs/userguide/tasks.xml
index b98232a..0a2b13e 100644
--- a/subprojects/docs/src/docs/userguide/tasks.xml
+++ b/subprojects/docs/src/docs/userguide/tasks.xml
@@ -40,7 +40,7 @@
<sourcefile file="build.gradle"/>
</sample>
<para>Here we add tasks to the <literal>tasks</literal> collection. Have a look at
- <apilink class="org.gradle.api.tasks.TaskContainer"/> for more variations of the <literal>add()</literal>
+ <apilink class="org.gradle.api.tasks.TaskContainer"/> for more variations of the <literal>create()</literal>
method.</para>
</section>
<section>
@@ -151,6 +151,58 @@
</sample>
<para>For more information about task dependencies, see the <apilink class="org.gradle.api.Task"/> API.</para>
</section>
+ <section id="sec:ordering_tasks">
+ <title>Ordering tasks</title>
+ <note>
+ <para>
+ Task ordering is an <link linkend="feature_lifecycle">incubating</link> feature. Please be aware that this feature may change in later Gradle versions.
+ </para>
+ </note>
+ <para>
+ In some cases it is useful to control the <emphasis>order</emphasis> in which 2 tasks will execute, without introducing an explicit dependency between those tasks.
+ The primary difference between a task <emphasis>ordering</emphasis> and a task <emphasis>dependency</emphasis> is that an ordering rule does not influence which tasks
+ will be executed, only the order in which they will be executed.
+ </para>
+ <para>
+ Task ordering can be useful in a number of scenarios:
+ </para>
+ <itemizedlist>
+ <listitem>Enforce sequential ordering of tasks: eg. 'build' never runs before 'clean'.</listitem>
+ <listitem>Run build validations early in the build: eg. validate I have the correct credentials before starting the work for a release build.</listitem>
+ <listitem>Get feedback faster by running quick verification tasks before long verification tasks: eg. unit tests should run before integration tests.</listitem>
+ <listitem>A task that aggregates the results of all tasks of a particular type: eg. test report task combines the outputs of all executed test tasks.</listitem>
+ </itemizedlist>
+ <para>
+ Presently, the only task ordering rule available is "<emphasis>must run after</emphasis>", which allows you to specify that <literal>taskB</literal> must always run after <literal>taskA</literal>,
+ whenever both <literal>taskA</literal> and <literal>taskB</literal> are scheduled for execution. This is expressed as <literal>taskB.mustRunAfter(taskA)</literal>.
+ With this rule present it is still possible to execute <literal>taskA</literal> without <literal>taskB</literal> and vice-versa.
+ </para>
+ <note>
+ <para>
+ While 'must-run-after' is useful in many cases, there are times when your ordering requirements are slightly different.
+ An example is an ordering preference for faster feedback, where the ordering is helpful but not strictly required.
+ We plan to add different types of task ordering in the future, to better support the full gamut of ordering use cases.
+ </para>
+ </note>
+ <sample id="mustRunAfter" dir="userguide/tasks/mustRunAfter" title="Adding a 'must run after' task ordering">
+ <sourcefile file="build.gradle"/>
+ <output args="-q taskY taskX"/>
+ </sample>
+ <para>In the example, it is still possible to execute <literal>taskY</literal> without causing <literal>taskX</literal> to run:</para>
+ <sample id="mustRunAfterSingleTask" dir="userguide/tasks/mustRunAfter" title="Task ordering does not imply task execution">
+ <output args="-q taskY"/>
+ </sample>
+ <para>To specify a "must run after" ordering between 2 tasks, you use the <apilink class="org.gradle.api.Task" method="mustRunAfter"/> method.
+ This method accepts a task instance, a task name or any other input accepted by <apilink class="org.gradle.api.Task" method="dependsOn"/>.
+ </para>
+ <para>
+ Note that "<literal>B.mustRunAfter(A)</literal>" does not imply any execution dependency between the tasks:
+ </para>
+ <itemizedlist>
+ <listitem>It is possible to execute tasks <literal>A</literal> and <literal>B</literal> independently. The ordering rule only has an effect when both tasks are scheduled for execution.</listitem>
+ <listitem>When run with <literal>--continue</literal>, it is possible for <literal>B</literal> to execute in the event that <literal>A</literal> fails.</listitem>
+ </itemizedlist>
+ </section>
<section>
<title>Adding a description to a task</title>
<para>You can add a description to your task. This description is for example displayed when executing
@@ -228,7 +280,7 @@
</section>
</section>
- <section>
+ <section id="sec:up_to_date_checks">
<title>Skipping tasks that are up-to-date</title>
<para>If you are using one of the tasks that come with Gradle, such as a task added by the Java plugin,
you might have noticed that Gradle will skip tasks that are up-to-date. This behaviour is also available
@@ -305,6 +357,34 @@
<output args="-q groupPing"/>
</sample>
</section>
+
+ <section>
+ <title>Finalizer tasks</title>
+ <note>
+ <para>
+ Finalizers tasks are an <firstterm>incubating</firstterm> feature (see <xref linkend="sec:incubating_state"/>).
+ </para>
+ </note>
+ <para>Finalizer tasks are automatically added to the task graph when the finalized task is scheduled to run.</para>
+ <sample id="taskFinalizers" dir="userguide/tasks/finalizers" title="Adding a task finalizer">
+ <sourcefile file="build.gradle"/>
+ <output args="-q taskX"/>
+ </sample>
+ <para>Finalizer task will be executed even if the finalized task fails.</para>
+ <sample id="taskFinalizersWithFailure" dir="userguide/tasks/finalizersWithFailure" title="Task finalizer for a failing task">
+ <sourcefile file="build.gradle"/>
+ <output args="-q taskX"/>
+ </sample>
+ <para>On the other hand, finalizer tasks are not executed if the finalized task didn't do any work, for example due to failed
+ task dependency or if it's considered up to date.</para>
+ <para>Finalizer tasks are useful in situations where build creates a resource that has to be cleaned up regardless
+ of the build failing or succeeding. An example of such resource is a web container started before an integration test task
+ and which should be always shut down, even if some of the tests fail.</para>
+ <para>To specify a finalizer task you use the <apilink class="org.gradle.api.Task" method="finalizedBy"/> method.
+ This method accepts a task instance, a task name or any other input accepted by <apilink class="org.gradle.api.Task" method="dependsOn"/>.
+ </para>
+ </section>
+
<section id='sec:the_idea_behind_gradle_tasks'>
<title>Summary</title>
<para>If you are coming from Ant, such an enhanced Gradle task as <emphasis>Copy</emphasis> looks like a mixture
diff --git a/subprojects/docs/src/docs/userguide/thisAndThat.xml b/subprojects/docs/src/docs/userguide/thisAndThat.xml
index e15074d..e3406c6 100644
--- a/subprojects/docs/src/docs/userguide/thisAndThat.xml
+++ b/subprojects/docs/src/docs/userguide/thisAndThat.xml
@@ -59,8 +59,7 @@
</footnote>
If the environment property follows the pattern
<literal>ORG_GRADLE_PROJECT_<replaceable>propertyName</replaceable>=somevalue</literal>,
- <literal>propertyName</literal> is added to your project object. If in the future CI servers support Gradle
- directly, they might start Gradle via its main method. Therefore we already support the same mechanism for
+ <literal>propertyName</literal> is added to your project object. We also support the same mechanism for
system properties. The only difference is the pattern, which is
<literal>org.gradle.project.<replaceable>propertyName</replaceable></literal>.
</para>
diff --git a/subprojects/docs/src/docs/userguide/userguide.xml b/subprojects/docs/src/docs/userguide/userguide.xml
index 46a99e3..50fc85e 100755
--- a/subprojects/docs/src/docs/userguide/userguide.xml
+++ b/subprojects/docs/src/docs/userguide/userguide.xml
@@ -60,6 +60,7 @@
<xi:include href='findBugsPlugin.xml'/>
<xi:include href='jdependPlugin.xml'/>
<xi:include href='pmdPlugin.xml'/>
+ <xi:include href='jacocoPlugin.xml'/>
<xi:include href='sonarPlugin.xml'/>
<xi:include href='sonarRunnerPlugin.xml'/>
<xi:include href='osgi.xml'/>
@@ -72,9 +73,10 @@
<xi:include href='distributionPlugin.xml'/>
<xi:include href='applicationPlugin.xml'/>
<xi:include href='javaLibraryDistributionPlugin.xml'/>
- <xi:include href='bootstrapPlugin.xml'/>
+ <xi:include href='buildSetupPlugin.xml'/>
+ <xi:include href='wrapperPlugin.xml'/>
<xi:include href='buildDashboardPlugin.xml'/>
- <xi:include href='depMngmt.xml'/>
+ <xi:include href='depMngmt.xml'/>
<xi:include href='artifactMngmt.xml'/>
<xi:include href='mavenPlugin.xml'/>
<xi:include href='signingPlugin.xml'/>
diff --git a/subprojects/docs/src/docs/userguide/warPlugin.xml b/subprojects/docs/src/docs/userguide/warPlugin.xml
index 15a0be8..d8a9029 100644
--- a/subprojects/docs/src/docs/userguide/warPlugin.xml
+++ b/subprojects/docs/src/docs/userguide/warPlugin.xml
@@ -175,7 +175,7 @@
<title>Customizing</title>
<para>Here is an example with the most important customization options:
</para>
- <sample id="webproject" dir="webApplication/customised" title="Customization of war plugin">
+ <sample id="webproject" dir="webApplication/customized" title="Customization of war plugin">
<sourcefile file="build.gradle" snippet="customization"/>
</sample>
<para>Of course one can configure the different file-sets with a closure to define excludes and includes.
diff --git a/subprojects/docs/src/docs/userguide/workingWithFiles.xml b/subprojects/docs/src/docs/userguide/workingWithFiles.xml
index 6e7ef94..1866072 100644
--- a/subprojects/docs/src/docs/userguide/workingWithFiles.xml
+++ b/subprojects/docs/src/docs/userguide/workingWithFiles.xml
@@ -168,7 +168,7 @@
<para>Many objects in Gradle have properties which accept a set of input files. For example, the
<apilink class="org.gradle.api.tasks.compile.JavaCompile"/> task has a <literal>source</literal> property,
which defines the source files to compile. You can set the value of this property using any of the types
- supported by the <link linkend="sec:file_collections">files()</link> method, which we have seen in above.
+ supported by the <link linkend="sec:file_collections">files()</link> method, which was shown above.
This means you can set the property using, for example, a <classname>File</classname>, <classname>String</classname>,
collection, <classname>FileCollection</classname> or even a closure.
Here are some examples:
@@ -188,14 +188,14 @@
<section id="sec:copying_files">
<title>Copying files</title>
<para>You can use the <apilink class="org.gradle.api.tasks.Copy"/> task to copy files. The copy task is very flexible, and allows
- you to, for example, filter the contents of the files as they are copied, and to map the files names.
+ you to, for example, filter the contents of the files as they are copied, and map to the file names.
</para>
<para>To use the <literal>Copy</literal> task, you must provide a set of source files to copy, and a destination directory to copy
the files to. You may also specify how to transform the files as they are copied. You do all this using a
<firstterm>copy spec</firstterm>. A copy spec is represented by the <apilink class="org.gradle.api.file.CopySpec"/> interface. The
<literal>Copy</literal> task implements this interface.
You specify the source files using the <apilink class="org.gradle.api.file.CopySpec" method="from(java.lang.Object...)"/>
- method. To specify the destination directory, you use the <apilink class="org.gradle.api.file.CopySpec" method="into(java.lang.Object)"/>
+ method. To specify the destination directory, use the <apilink class="org.gradle.api.file.CopySpec" method="into(java.lang.Object)"/>
method.
</para>
<sample id="copy" dir="userguide/files/copy" title="Copying files using the copy task">
@@ -206,7 +206,9 @@
<link linkend="sec:file_collections">files()</link> method does. When an argument resolves to a directory,
everything under that directory (but not the directory itself) is recursively copied into the destination
directory. When an argument resolves to a file, that file is copied into the destination directory.
- When an argument resolves to a non-existing file, that argument is ignored.
+ When an argument resolves to a non-existing file, that argument is ignored. If the argument is
+ a task, the output files (i.e. the files the task creates) of the task are copied and the task is automatically
+ added as a dependency of the <literal>Copy</literal> task.
The <literal>into()</literal> accepts
any of the arguments that the <link linkend="sec:locating_files">file()</link> method does. Here is another
example:
@@ -219,10 +221,26 @@
<sourcefile file="build.gradle" snippet="copy-task-with-patterns"/>
</sample>
<para>You can also use the <apilink class="org.gradle.api.Project" method="copy"/> method to copy files. It works the
- same way as the task.</para>
- <sample id="copy" dir="userguide/files/copy" title="Copying files using the copy() method">
+ same way as the task with some major limitations though. First, the <literal>copy()</literal> is not incremental
+ (see <xref linkend="sec:up_to_date_checks" />).
+ </para>
+ <sample id="copy" dir="userguide/files/copy" title="Copying files using the copy() method without up-to-date check">
<sourcefile file="build.gradle" snippet="copy-method"/>
</sample>
+ <para>Secondly, the <literal>copy()</literal> method can not honor task dependencies when a task is used as a copy source
+ (i.e. as an argument to <literal>from()</literal>) because it's a method and not a task.
+ As such, if you are using the <literal>copy()</literal> method as part of a task action, you must explicitly
+ declare all inputs and outputs in order to get the correct behavior.
+ </para>
+ <sample id="copy" dir="userguide/files/copy" title="Copying files using the copy() method with up-to-date check">
+ <sourcefile file="build.gradle" snippet="copy-method-with-dependency"/>
+ </sample>
+ <para>
+ It is preferable to use the <literal>Copy</literal> task wherever possible, as it support incremental building and task dependency inference
+ without any extra effort on your part. The <literal>copy()</literal> method can be used to copy files as <emphasis>part</emphasis> of a task's
+ implementation. That is, the copy method is intended to be used by custom tasks (see <xref linkend="custom_tasks" />) that need to copy files
+ as part of their function. In such a scenario, the custom task should sufficiently declare the inputs/outputs relevant to the copy action.
+ </para>
<section>
<title>Renaming files</title>
<sample id="renameOnCopy" dir="userguide/files/copy" title="Renaming files as they are copied">
@@ -238,7 +256,7 @@
<section>
<title>Using the <classname>CopySpec</classname> class</title>
<para>Copy specs form a hierarchy. A copy spec inherits its destination path, include patterns, exclude patterns, copy actions,
- name mappings, filters.</para>
+ name mappings and filters.</para>
<sample id="nestedCopySpecs" dir="userguide/files/copy" title="Nested copy specs">
<sourcefile file="build.gradle" snippet="nested-specs"/>
</sample>
@@ -267,8 +285,9 @@
Archives are created using the various archive tasks:
<apilink class="org.gradle.api.tasks.bundling.Zip"/>,
<apilink class="org.gradle.api.tasks.bundling.Tar"/>,
- <apilink class="org.gradle.api.tasks.bundling.Jar"/>, and
- <apilink class="org.gradle.api.tasks.bundling.War"/>.
+ <apilink class="org.gradle.api.tasks.bundling.Jar"/>,
+ <apilink class="org.gradle.api.tasks.bundling.War"/>, and
+ <apilink class="org.gradle.plugins.ear.Ear"/>.
They all work the same way, so let's look at how you create a ZIP file.
</para>
<sample id="createZip" dir="userguide/files/archives" title="Creating a ZIP archive">
@@ -389,7 +408,7 @@
<section>
<title>Sharing content between multiple archives</title>
- <para>Using the <apilink class="org.gradle.api.Project" method="copySpec"/> method to share content between archives.</para>
+ <para>You can use the <apilink class="org.gradle.api.Project" method="copySpec"/> method to share content between archives.</para>
</section>
<para>Often you will want to publish an archive, so that it is usable from another project. This process is
@@ -398,4 +417,4 @@
</section>
-</chapter>
\ No newline at end of file
+</chapter>
diff --git a/subprojects/docs/src/docs/userguide/wrapperPlugin.xml b/subprojects/docs/src/docs/userguide/wrapperPlugin.xml
new file mode 100644
index 0000000..9ad70bc
--- /dev/null
+++ b/subprojects/docs/src/docs/userguide/wrapperPlugin.xml
@@ -0,0 +1,59 @@
+<!--
+ ~ Copyright 2013 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ 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.
+ -->
+<chapter id='wrapper_plugin'>
+ <title>Wrapper Plugin</title>
+
+ <note>
+ <para>
+ The wrapper plugin is currently <link linkend="feature_lifecycle">incubating</link>. Please be aware that the DSL and other configuration may change in later Gradle versions.
+ </para>
+ </note>
+
+ <para>The Gradle wrapper plugin allows the generation of Gradle wrapper files by adding a <apilink class="org.gradle.api.tasks.wrapper.Wrapper"/>
+ task, that generates all files needed to run the build using the Gradle Wrapper.
+ Details about the Gradle Wrapper can be found in the according chapter <xref linkend='gradle_wrapper'/>
+ </para>
+ <section>
+ <title>Usage</title>
+ <para>
+ Without modifying the <literal>build.gradle</literal> file, the wrapper plugin can be auto-applied to the rootproject of the current build by running
+ <literal>gradle wrapper</literal> from the commandline. This applies the plugin if no task named <literal>wrapper</literal> is already defined in the build.
+ </para>
+ </section>
+ <section>
+ <title>Tasks</title>
+ <para>The wrapper plugin adds the following tasks to the project:</para>
+ <table>
+ <title>Wrapper plugin - tasks</title>
+ <thead>
+ <tr>
+ <td>Task name</td>
+ <td>Depends on</td>
+ <td>Type</td>
+ <td>Description</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>
+ <literal>wrapper</literal>
+ </td>
+ <td>-</td>
+ <td><apilink class="org.gradle.api.tasks.wrapper.Wrapper"/></td>
+ <td>Generates Gradle wrapper files.</td>
+ </tr>
+ </table>
+ </section>
+</chapter>
diff --git a/subprojects/docs/src/docs/userguide/writingBuildScripts.xml b/subprojects/docs/src/docs/userguide/writingBuildScripts.xml
index 8bdeff3..4ed644b 100644
--- a/subprojects/docs/src/docs/userguide/writingBuildScripts.xml
+++ b/subprojects/docs/src/docs/userguide/writingBuildScripts.xml
@@ -179,7 +179,7 @@
<title>Some Groovy basics</title>
<para>Groovy provides plenty of features for creating DSLs, and the Gradle build language takes advantage of these.
Understanding how the build language works will help you when you write your build script, and in particular,
- when you start to write customs plugins and tasks.
+ when you start to write custom plugins and tasks.
</para>
<section>
<title>Groovy JDK</title>
diff --git a/subprojects/docs/src/samples/buildDashboard/build.gradle b/subprojects/docs/src/samples/buildDashboard/build.gradle
index f57e409..486877d 100755
--- a/subprojects/docs/src/samples/buildDashboard/build.gradle
+++ b/subprojects/docs/src/samples/buildDashboard/build.gradle
@@ -25,6 +25,6 @@ repositories {
}
dependencies {
- groovy localGroovy()
+ compile localGroovy()
testCompile 'junit:junit:4.11'
}
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/buildDashboard/src/main/java/org/gradle/sample/Person.java b/subprojects/docs/src/samples/buildDashboard/src/main/java/org/gradle/sample/Person.java
new file mode 100755
index 0000000..5ff1d1a
--- /dev/null
+++ b/subprojects/docs/src/samples/buildDashboard/src/main/java/org/gradle/sample/Person.java
@@ -0,0 +1,15 @@
+package org.gradle.sample;
+
+import java.lang.String;
+
+class Person {
+ private String name;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/codeQuality/build.gradle b/subprojects/docs/src/samples/codeQuality/build.gradle
index 63d401d..f8a58f3 100755
--- a/subprojects/docs/src/samples/codeQuality/build.gradle
+++ b/subprojects/docs/src/samples/codeQuality/build.gradle
@@ -21,6 +21,6 @@ repositories {
}
dependencies {
- groovy localGroovy()
+ compile localGroovy()
testCompile 'junit:junit:4.11'
}
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/cpp/c-with-assembler/build.gradle b/subprojects/docs/src/samples/cpp/c-with-assembler/build.gradle
new file mode 100644
index 0000000..70404eb
--- /dev/null
+++ b/subprojects/docs/src/samples/cpp/c-with-assembler/build.gradle
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+apply plugin: 'cpp'
+
+def os = org.gradle.internal.os.OperatingSystem.current()
+def visualCpp = toolChains.defaultToolChain.name == "visualCpp"
+def platform = os.macOsX ? "i386_osx"
+ : os.linux ? "x64_gcc"
+ : visualCpp ? "i386_masm"
+ : "i386_gcc"
+
+sources {
+ main {
+ asm {
+ source.srcDir "src/main/asm_${platform}"
+ }
+ }
+}
+executables {
+ main {
+ source sources.main
+ }
+}
+
+if (os.macOsX) {
+ binaries.all {
+ compilerArgs "-m32"
+ assemblerArgs "-arch", "i386"
+ linkerArgs "-no_pie", "-arch", "i386"
+ }
+}
+
diff --git a/subprojects/docs/src/samples/cpp/c-with-assembler/src/main/asm_i386_gcc/sum.s b/subprojects/docs/src/samples/cpp/c-with-assembler/src/main/asm_i386_gcc/sum.s
new file mode 100644
index 0000000..bfd9155
--- /dev/null
+++ b/subprojects/docs/src/samples/cpp/c-with-assembler/src/main/asm_i386_gcc/sum.s
@@ -0,0 +1,6 @@
+ .text
+ .globl _sum
+_sum:
+ movl 8(%esp), %eax
+ addl 4(%esp), %eax
+ ret
diff --git a/subprojects/docs/src/samples/cpp/c-with-assembler/src/main/asm_i386_masm/sum.s b/subprojects/docs/src/samples/cpp/c-with-assembler/src/main/asm_i386_masm/sum.s
new file mode 100644
index 0000000..b1a1fe1
--- /dev/null
+++ b/subprojects/docs/src/samples/cpp/c-with-assembler/src/main/asm_i386_masm/sum.s
@@ -0,0 +1,12 @@
+ .386
+ .model flat
+
+PUBLIC _sum
+_TEXT SEGMENT
+_sum PROC
+ mov eax, DWORD PTR 4[esp]
+ add eax, DWORD PTR 8[esp]
+ ret 0
+_sum ENDP
+_TEXT ENDS
+END
diff --git a/subprojects/docs/src/samples/cpp/c-with-assembler/src/main/asm_i386_osx/sum.s b/subprojects/docs/src/samples/cpp/c-with-assembler/src/main/asm_i386_osx/sum.s
new file mode 100644
index 0000000..709f483
--- /dev/null
+++ b/subprojects/docs/src/samples/cpp/c-with-assembler/src/main/asm_i386_osx/sum.s
@@ -0,0 +1,10 @@
+ .section __TEXT,__text,regular,pure_instructions
+ .globl _sum
+ .align 4
+_sum:
+ movl 8(%esp), %eax
+ addl 4(%esp), %eax
+ ret
+
+
+.subsections_via_symbols
diff --git a/subprojects/docs/src/samples/cpp/c-with-assembler/src/main/asm_x64_gcc/sum.s b/subprojects/docs/src/samples/cpp/c-with-assembler/src/main/asm_x64_gcc/sum.s
new file mode 100644
index 0000000..8931cec
--- /dev/null
+++ b/subprojects/docs/src/samples/cpp/c-with-assembler/src/main/asm_x64_gcc/sum.s
@@ -0,0 +1,7 @@
+ .text
+ .p2align 4,,15
+.globl sum
+ .type sum, @function
+sum:
+ leal (%rsi,%rdi), %eax
+ ret
diff --git a/subprojects/docs/src/samples/cpp/c-with-assembler/src/main/c/main.c b/subprojects/docs/src/samples/cpp/c-with-assembler/src/main/c/main.c
new file mode 100644
index 0000000..eb4dda0
--- /dev/null
+++ b/subprojects/docs/src/samples/cpp/c-with-assembler/src/main/c/main.c
@@ -0,0 +1,8 @@
+#include <stdio.h>
+#include "sum.h"
+
+int main () {
+ int x = sum(5, 7);
+ printf("5 + 7 = %d\n", x);
+ return 0;
+}
diff --git a/subprojects/docs/src/samples/cpp/c-with-assembler/src/main/headers/sum.h b/subprojects/docs/src/samples/cpp/c-with-assembler/src/main/headers/sum.h
new file mode 100755
index 0000000..2410ec7
--- /dev/null
+++ b/subprojects/docs/src/samples/cpp/c-with-assembler/src/main/headers/sum.h
@@ -0,0 +1 @@
+int sum(int a, int b);
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/cpp/c/build.gradle b/subprojects/docs/src/samples/cpp/c/build.gradle
new file mode 100644
index 0000000..fc0756f
--- /dev/null
+++ b/subprojects/docs/src/samples/cpp/c/build.gradle
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+// START SNIPPET apply-plugin
+apply plugin: 'cpp'
+// END SNIPPET apply-plugin
+
+// START SNIPPET sourceSets
+sources {
+ exe {}
+ lib {}
+}
+// END SNIPPET sourceSets
+
+// START SNIPPET libraries
+libraries {
+ hello {
+ source sources.lib
+ }
+}
+// END SNIPPET libraries
+
+// START SNIPPET executables
+executables {
+ main {
+ source sources.exe
+ binaries.all {
+ // Each executable binary produced uses the 'hello' shared library binary
+ lib libraries.hello.shared
+ }
+ }
+}
+// END SNIPPET executables
+
+/*
+// START SNIPPET source-library
+sources.exe.cpp.lib libraries.hello
+// END SNIPPET source-library
+*/
+
+// START SNIPPET all-binaries
+binaries.all {
+ // Define a preprocessor macro for every binary
+ define "NDEBUG"
+
+ // Define toolchain-specific compiler and linker options
+ if (toolChain in Gcc) {
+ compilerArgs "-O2"
+ linkerArgs "-S"
+ }
+ if (toolChain in VisualCpp) {
+ compilerArgs "/Z7"
+ linkerArgs "/DEBUG"
+ }
+}
+// END SNIPPET all-binaries
+
+// START SNIPPET all-shared-libraries
+// For any shared library binaries built with Visual C++, define the DLL_EXPORT macro
+binaries.withType(SharedLibraryBinary) {
+ if (toolChain in VisualCpp) {
+ define "DLL_EXPORT"
+ }
+}
+// END SNIPPET all-shared-libraries
+
+
diff --git a/subprojects/docs/src/samples/cpp/exewithlib/exe/src/main/cpp/main.cpp b/subprojects/docs/src/samples/cpp/c/src/exe/c/main.c
similarity index 100%
copy from subprojects/docs/src/samples/cpp/exewithlib/exe/src/main/cpp/main.cpp
copy to subprojects/docs/src/samples/cpp/c/src/exe/c/main.c
diff --git a/subprojects/docs/src/samples/cpp/c/src/lib/c/hello.c b/subprojects/docs/src/samples/cpp/c/src/lib/c/hello.c
new file mode 100755
index 0000000..1d8c48f
--- /dev/null
+++ b/subprojects/docs/src/samples/cpp/c/src/lib/c/hello.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+#include "hello.h"
+
+void LIB_FUNC hello () {
+ printf("Hello world!");
+}
diff --git a/subprojects/docs/src/samples/cpp/c/src/lib/headers/hello.h b/subprojects/docs/src/samples/cpp/c/src/lib/headers/hello.h
new file mode 100755
index 0000000..b4a1ec2
--- /dev/null
+++ b/subprojects/docs/src/samples/cpp/c/src/lib/headers/hello.h
@@ -0,0 +1,8 @@
+#ifdef DLL_EXPORT
+#define LIB_FUNC __declspec(dllexport)
+#else
+#define LIB_FUNC
+#endif
+
+void LIB_FUNC hello();
+
diff --git a/subprojects/docs/src/samples/cpp/cpp-exe/build.gradle b/subprojects/docs/src/samples/cpp/cpp-exe/build.gradle
new file mode 100644
index 0000000..2e36b6d
--- /dev/null
+++ b/subprojects/docs/src/samples/cpp/cpp-exe/build.gradle
@@ -0,0 +1,33 @@
+// START SNIPPET use-plugin
+apply plugin: "cpp-exe"
+// END SNIPPET use-plugin
+
+// START SNIPPET args
+executables {
+ main {
+ binaries.all {
+ // Define a preprocessor macro
+ define "NDEBUG"
+ // Add some additional compiler arguments
+ if (toolChain in Gcc) {
+ compilerArgs "-fno-access-control", "-fconserve-space"
+ }
+ }
+ }
+}
+// END SNIPPET args
+
+// START SNIPPET strip
+binaries.withType(ExecutableBinary) { binary ->
+ def linkTask = tasks["link${binary.name.capitalize()}"]
+ def stripTask = task("strip${binary.name.capitalize()}") {
+ dependsOn linkTask
+ doFirst {
+ if (binary.toolChain in Gcc) {
+ ["strip", linkTask.outputFile].execute()
+ }
+ }
+ }
+ binary.dependsOn stripTask
+}
+// END SNIPPET strip
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/cpp/cpp-exe/settings.gradle b/subprojects/docs/src/samples/cpp/cpp-exe/settings.gradle
new file mode 100644
index 0000000..7bd15c8
--- /dev/null
+++ b/subprojects/docs/src/samples/cpp/cpp-exe/settings.gradle
@@ -0,0 +1 @@
+rootProject.name = "sampleExe"
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/cpp/exe/src/main/cpp/hello.cpp b/subprojects/docs/src/samples/cpp/cpp-exe/src/main/cpp/hello.cpp
similarity index 100%
rename from subprojects/docs/src/samples/cpp/exe/src/main/cpp/hello.cpp
rename to subprojects/docs/src/samples/cpp/cpp-exe/src/main/cpp/hello.cpp
diff --git a/subprojects/docs/src/samples/cpp/cpp-lib/build.gradle b/subprojects/docs/src/samples/cpp/cpp-lib/build.gradle
new file mode 100644
index 0000000..56f374e
--- /dev/null
+++ b/subprojects/docs/src/samples/cpp/cpp-lib/build.gradle
@@ -0,0 +1,14 @@
+// START SNIPPET use-plugin
+apply plugin: "cpp-lib"
+// END SNIPPET use-plugin
+
+// START SNIPPET args
+libraries {
+ main {
+ binaries.withType(SharedLibraryBinary) {
+ // Define a preprocessor macro that only applies to shared libraries
+ define "DLL_EXPORT"
+ }
+ }
+}
+// END SNIPPET args
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/cpp/cpp-lib/settings.gradle b/subprojects/docs/src/samples/cpp/cpp-lib/settings.gradle
new file mode 100644
index 0000000..cd1f30d
--- /dev/null
+++ b/subprojects/docs/src/samples/cpp/cpp-lib/settings.gradle
@@ -0,0 +1 @@
+rootProject.name = "sampleLib"
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/cpp/cpp-lib/src/main/cpp/hello.cpp b/subprojects/docs/src/samples/cpp/cpp-lib/src/main/cpp/hello.cpp
new file mode 100644
index 0000000..b849636
--- /dev/null
+++ b/subprojects/docs/src/samples/cpp/cpp-lib/src/main/cpp/hello.cpp
@@ -0,0 +1,14 @@
+#include <iostream>
+#ifdef _WIN32
+#ifdef DLL_EXPORT
+#define LIB_FUNC __declspec(dllexport)
+#endif
+#endif
+#ifndef LIB_FUNC
+#define LIB_FUNC
+#endif
+
+
+void LIB_FUNC hello () {
+ std::cout << "Hello, World!\n";
+}
diff --git a/subprojects/docs/src/samples/cpp/exewithlib/lib/src/main/headers/hello.h b/subprojects/docs/src/samples/cpp/cpp-lib/src/main/headers/hello.h
similarity index 100%
copy from subprojects/docs/src/samples/cpp/exewithlib/lib/src/main/headers/hello.h
copy to subprojects/docs/src/samples/cpp/cpp-lib/src/main/headers/hello.h
diff --git a/subprojects/docs/src/samples/cpp/cpp/build.gradle b/subprojects/docs/src/samples/cpp/cpp/build.gradle
new file mode 100644
index 0000000..c6ed4c8
--- /dev/null
+++ b/subprojects/docs/src/samples/cpp/cpp/build.gradle
@@ -0,0 +1,64 @@
+// START SNIPPET apply-plugin
+apply plugin: 'cpp'
+// END SNIPPET apply-plugin
+
+// START SNIPPET sourceSets
+sources {
+ exe {}
+ lib {}
+}
+// END SNIPPET sourceSets
+
+// START SNIPPET libraries
+libraries {
+ hello {
+ source sources.lib
+ }
+}
+// END SNIPPET libraries
+
+// START SNIPPET executables
+executables {
+ main {
+ source sources.exe
+ binaries.all {
+ // Each executable binary produced uses the 'hello' shared library binary
+ lib libraries.hello.shared
+ }
+ }
+}
+// END SNIPPET executables
+
+/*
+// START SNIPPET source-library
+sources.exe.cpp.lib libraries.hello
+// END SNIPPET source-library
+*/
+
+// START SNIPPET all-binaries
+binaries.all {
+ // Define a preprocessor macro for every binary
+ define "NDEBUG"
+
+ // Define toolchain-specific compiler and linker options
+ if (toolChain in Gcc) {
+ compilerArgs "-O2", "-fno-access-control"
+ linkerArgs "-S"
+ }
+ if (toolChain in VisualCpp) {
+ compilerArgs "/Z7"
+ linkerArgs "/DEBUG"
+ }
+}
+// END SNIPPET all-binaries
+
+// START SNIPPET all-shared-libraries
+// For any shared library binaries built with Visual C++, define the DLL_EXPORT macro
+binaries.withType(SharedLibraryBinary) {
+ if (toolChain in VisualCpp) {
+ define "DLL_EXPORT"
+ }
+}
+// END SNIPPET all-shared-libraries
+
+
diff --git a/subprojects/docs/src/samples/cpp/exewithlib/exe/src/main/cpp/main.cpp b/subprojects/docs/src/samples/cpp/cpp/src/exe/cpp/main.cpp
similarity index 100%
copy from subprojects/docs/src/samples/cpp/exewithlib/exe/src/main/cpp/main.cpp
copy to subprojects/docs/src/samples/cpp/cpp/src/exe/cpp/main.cpp
diff --git a/subprojects/docs/src/samples/cpp/cpp/src/lib/cpp/hello.cpp b/subprojects/docs/src/samples/cpp/cpp/src/lib/cpp/hello.cpp
new file mode 100755
index 0000000..dc7b045
--- /dev/null
+++ b/subprojects/docs/src/samples/cpp/cpp/src/lib/cpp/hello.cpp
@@ -0,0 +1,6 @@
+#include <iostream>
+#include "hello.h"
+
+void LIB_FUNC hello () {
+ std::cout << "Hello world!" << std::endl;
+}
diff --git a/subprojects/docs/src/samples/cpp/cpp/src/lib/headers/hello.h b/subprojects/docs/src/samples/cpp/cpp/src/lib/headers/hello.h
new file mode 100755
index 0000000..51b48fd
--- /dev/null
+++ b/subprojects/docs/src/samples/cpp/cpp/src/lib/headers/hello.h
@@ -0,0 +1,7 @@
+#ifdef DLL_EXPORT
+#define LIB_FUNC __declspec(dllexport)
+#else
+#define LIB_FUNC
+#endif
+
+void LIB_FUNC hello();
diff --git a/subprojects/docs/src/samples/cpp/dependencies/build.gradle b/subprojects/docs/src/samples/cpp/dependencies/build.gradle
index b96b63f..a207bac 100644
--- a/subprojects/docs/src/samples/cpp/dependencies/build.gradle
+++ b/subprojects/docs/src/samples/cpp/dependencies/build.gradle
@@ -3,9 +3,7 @@ apply plugin: "base"
project(":lib") {
archivesBaseName = "some-lib"
- // START SNIPPET use-plugin-lib
apply plugin: "cpp-lib"
- // END SNIPPET use-plugin-lib
apply plugin: "eclipse-cdt"
apply plugin: 'maven'
@@ -27,9 +25,7 @@ uploadArchives {
}
project(":exe") {
- // START SNIPPET use-plugin-exe
apply plugin: "cpp-exe"
- // END SNIPPET use-plugin-exe
apply plugin: "eclipse-cdt"
apply plugin: "maven"
@@ -42,9 +38,9 @@ project(":exe") {
}
// START SNIPPET declaring-dependencies
-cpp {
- sourceSets {
- main {
+sources {
+ main {
+ cpp {
dependency group: "some-org", name: "some-lib", version: "1.0"
}
}
@@ -60,4 +56,4 @@ cpp {
}
}
-task build(dependsOn: project(":exe").compileMain)
\ No newline at end of file
+task build(dependsOn: ":exe:mainExecutable")
diff --git a/subprojects/docs/src/samples/cpp/exe/build.gradle b/subprojects/docs/src/samples/cpp/exe/build.gradle
deleted file mode 100644
index bcbc79e..0000000
--- a/subprojects/docs/src/samples/cpp/exe/build.gradle
+++ /dev/null
@@ -1,11 +0,0 @@
-apply plugin: "cpp-exe"
-
-// START SNIPPET args
-executables {
- main {
- spec {
- args "-fno-access-control", "-fconserve-space"
- }
- }
-}
-// END SNIPPET args
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/cpp/exewithlib/build.gradle b/subprojects/docs/src/samples/cpp/exewithlib/build.gradle
deleted file mode 100644
index 1bce29e..0000000
--- a/subprojects/docs/src/samples/cpp/exewithlib/build.gradle
+++ /dev/null
@@ -1,18 +0,0 @@
-// START SNIPPET project-dependencies
-project(":lib") {
- apply plugin: "cpp-lib"
-}
-
-project(":exe") {
- apply plugin: "cpp-exe"
- cpp {
- sourceSets {
- main {
- libs << project(":lib").libraries.main
- }
- }
- }
-}
-// END SNIPPET project-dependencies
-
-task build(dependsOn: project(":exe").compileMain)
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/cpp/multi-project/build.gradle b/subprojects/docs/src/samples/cpp/multi-project/build.gradle
new file mode 100644
index 0000000..4938b6d
--- /dev/null
+++ b/subprojects/docs/src/samples/cpp/multi-project/build.gradle
@@ -0,0 +1,18 @@
+// START SNIPPET project-dependencies
+project(":lib") {
+ apply plugin: "cpp-lib"
+}
+
+project(":exe") {
+ apply plugin: "cpp-exe"
+ evaluationDependsOn(":lib")
+
+ sources {
+ main {
+ cpp {
+ lib project(":lib").libraries.main
+ }
+ }
+ }
+}
+// END SNIPPET project-dependencies
diff --git a/subprojects/docs/src/samples/cpp/exewithlib/exe/src/main/cpp/main.cpp b/subprojects/docs/src/samples/cpp/multi-project/exe/src/main/cpp/main.cpp
similarity index 100%
copy from subprojects/docs/src/samples/cpp/exewithlib/exe/src/main/cpp/main.cpp
copy to subprojects/docs/src/samples/cpp/multi-project/exe/src/main/cpp/main.cpp
diff --git a/subprojects/docs/src/samples/cpp/exewithlib/lib/src/main/cpp/hello.cpp b/subprojects/docs/src/samples/cpp/multi-project/lib/src/main/cpp/hello.cpp
similarity index 100%
rename from subprojects/docs/src/samples/cpp/exewithlib/lib/src/main/cpp/hello.cpp
rename to subprojects/docs/src/samples/cpp/multi-project/lib/src/main/cpp/hello.cpp
diff --git a/subprojects/docs/src/samples/cpp/exewithlib/lib/src/main/headers/hello.h b/subprojects/docs/src/samples/cpp/multi-project/lib/src/main/headers/hello.h
similarity index 100%
rename from subprojects/docs/src/samples/cpp/exewithlib/lib/src/main/headers/hello.h
rename to subprojects/docs/src/samples/cpp/multi-project/lib/src/main/headers/hello.h
diff --git a/subprojects/docs/src/samples/cpp/exewithlib/settings.gradle b/subprojects/docs/src/samples/cpp/multi-project/settings.gradle
similarity index 100%
rename from subprojects/docs/src/samples/cpp/exewithlib/settings.gradle
rename to subprojects/docs/src/samples/cpp/multi-project/settings.gradle
diff --git a/subprojects/docs/src/samples/cpp/variants/build.gradle b/subprojects/docs/src/samples/cpp/variants/build.gradle
new file mode 100644
index 0000000..aa3f06f
--- /dev/null
+++ b/subprojects/docs/src/samples/cpp/variants/build.gradle
@@ -0,0 +1,39 @@
+apply plugin: 'cpp'
+
+sources {
+ exe {}
+ lib {}
+}
+libraries {
+ // Define some common settings for all shared library binaries
+ all {
+ binaries.withType(SharedLibraryBinary) {
+ define "DLL_EXPORT"
+ }
+ }
+ hello {
+ source sources.lib
+ flavors {
+ english {}
+ french {}
+ }
+ binaries.all {
+ if (flavor == flavors.french) {
+ define "FRENCH"
+ }
+ }
+ }
+}
+
+executables {
+ main {
+ source sources.exe
+ flavors {
+ english {}
+ french {}
+ }
+ binaries.all {
+ lib libraries.hello
+ }
+ }
+}
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/cpp/exewithlib/exe/src/main/cpp/main.cpp b/subprojects/docs/src/samples/cpp/variants/src/exe/cpp/main.cpp
similarity index 100%
copy from subprojects/docs/src/samples/cpp/exewithlib/exe/src/main/cpp/main.cpp
copy to subprojects/docs/src/samples/cpp/variants/src/exe/cpp/main.cpp
diff --git a/subprojects/docs/src/samples/cpp/variants/src/lib/cpp/hello.cpp b/subprojects/docs/src/samples/cpp/variants/src/lib/cpp/hello.cpp
new file mode 100755
index 0000000..733d15a
--- /dev/null
+++ b/subprojects/docs/src/samples/cpp/variants/src/lib/cpp/hello.cpp
@@ -0,0 +1,10 @@
+#include <iostream>
+#include "hello.h"
+
+void LIB_FUNC hello () {
+ #ifdef FRENCH
+ std::cout << "Bonjour monde!" << std::endl;
+ #else
+ std::cout << "Hello world!" << std::endl;
+ #endif
+}
diff --git a/subprojects/docs/src/samples/cpp/variants/src/lib/headers/hello.h b/subprojects/docs/src/samples/cpp/variants/src/lib/headers/hello.h
new file mode 100755
index 0000000..79b608b
--- /dev/null
+++ b/subprojects/docs/src/samples/cpp/variants/src/lib/headers/hello.h
@@ -0,0 +1,10 @@
+#ifdef _WIN32
+#ifdef DLL_EXPORT
+#define LIB_FUNC __declspec(dllexport)
+#endif
+#endif
+#ifndef LIB_FUNC
+#define LIB_FUNC
+#endif
+
+void LIB_FUNC hello();
diff --git a/subprojects/docs/src/samples/customBuildLanguage/buildSrc/src/main/groovy/org/gradle/samples/ProductPlugin.groovy b/subprojects/docs/src/samples/customBuildLanguage/buildSrc/src/main/groovy/org/gradle/samples/ProductPlugin.groovy
index d47ed71..693a875 100644
--- a/subprojects/docs/src/samples/customBuildLanguage/buildSrc/src/main/groovy/org/gradle/samples/ProductPlugin.groovy
+++ b/subprojects/docs/src/samples/customBuildLanguage/buildSrc/src/main/groovy/org/gradle/samples/ProductPlugin.groovy
@@ -37,7 +37,7 @@ class ProductPlugin implements Plugin<Project> {
configurations {
runtime
}
- tasks.add(name: 'dist', type: Zip)
+ tasks.create(name: 'dist', type: Zip)
artifacts {
archives dist
}
diff --git a/subprojects/docs/src/samples/customDistribution/plugin/build.gradle b/subprojects/docs/src/samples/customDistribution/plugin/build.gradle
index f046720..e20c41f 100644
--- a/subprojects/docs/src/samples/customDistribution/plugin/build.gradle
+++ b/subprojects/docs/src/samples/customDistribution/plugin/build.gradle
@@ -12,7 +12,7 @@ configurations {
dependencies {
gradleApi gradleApi()
- groovy localGroovy()
+ compile localGroovy()
compile 'com.google.guava:guava:11.0.2'
}
diff --git a/subprojects/docs/src/samples/customPlugin/plugin/build.gradle b/subprojects/docs/src/samples/customPlugin/plugin/build.gradle
index 5eb4b90..028f3f7 100644
--- a/subprojects/docs/src/samples/customPlugin/plugin/build.gradle
+++ b/subprojects/docs/src/samples/customPlugin/plugin/build.gradle
@@ -8,7 +8,7 @@ dependencies {
compile gradleApi()
// END SNIPPET gradle-api-dependencies
// START SNIPPET local-groovy-dependencies
- groovy localGroovy()
+ compile localGroovy()
// START SNIPPET gradle-api-dependencies
}
// END SNIPPET gradle-api-dependencies
diff --git a/subprojects/docs/src/samples/groovy/multiproject/testproject/src/main/groovy/org/gradle/GroovyJavaPerson.java b/subprojects/docs/src/samples/groovy/multiproject/testproject/src/main/groovy/org/gradle/GroovyJavaPerson.java
index 1200e2c..df1e06d 100644
--- a/subprojects/docs/src/samples/groovy/multiproject/testproject/src/main/groovy/org/gradle/GroovyJavaPerson.java
+++ b/subprojects/docs/src/samples/groovy/multiproject/testproject/src/main/groovy/org/gradle/GroovyJavaPerson.java
@@ -3,9 +3,6 @@ package org.gradle;
import java.util.Properties;
import java.io.IOException;
-/**
- * @author Hans Dockter
- */
public class GroovyJavaPerson {
public String readProperty() throws IOException {
Properties properties = new Properties();
diff --git a/subprojects/docs/src/samples/groovy/multiproject/testproject/src/main/groovy/org/gradle/GroovyPerson.groovy b/subprojects/docs/src/samples/groovy/multiproject/testproject/src/main/groovy/org/gradle/GroovyPerson.groovy
index 28e1759..01197ab 100644
--- a/subprojects/docs/src/samples/groovy/multiproject/testproject/src/main/groovy/org/gradle/GroovyPerson.groovy
+++ b/subprojects/docs/src/samples/groovy/multiproject/testproject/src/main/groovy/org/gradle/GroovyPerson.groovy
@@ -1,8 +1,5 @@
package org.gradle
-/**
- * @author Hans Dockter
- */
class GroovyPerson {
String readProperty() throws IOException {
Properties properties = new Properties()
diff --git a/subprojects/docs/src/samples/groovy/multiproject/testproject/src/main/java/org/gradle/JavaPerson.java b/subprojects/docs/src/samples/groovy/multiproject/testproject/src/main/java/org/gradle/JavaPerson.java
index df8099f..aa47c45 100644
--- a/subprojects/docs/src/samples/groovy/multiproject/testproject/src/main/java/org/gradle/JavaPerson.java
+++ b/subprojects/docs/src/samples/groovy/multiproject/testproject/src/main/java/org/gradle/JavaPerson.java
@@ -3,9 +3,6 @@ package org.gradle;
import java.util.Properties;
import java.io.IOException;
-/**
- * @author Hans Dockter
- */
public class JavaPerson {
public String readProperty() throws IOException {
Properties properties = new Properties();
diff --git a/subprojects/docs/src/samples/ivy-publish/descriptor-customization/build.gradle b/subprojects/docs/src/samples/ivy-publish/descriptor-customization/build.gradle
index ef79270..c47e2da 100644
--- a/subprojects/docs/src/samples/ivy-publish/descriptor-customization/build.gradle
+++ b/subprojects/docs/src/samples/ivy-publish/descriptor-customization/build.gradle
@@ -15,13 +15,13 @@ publishing {
// END SNIPPET customize-descriptor
repositories {
ivy {
- url "file://$buildDir/repo" // change to point to your repo, e.g. http://my.org/repo
+ url "$buildDir/repo" // change to point to your repo, e.g. http://my.org/repo
}
}
}
// START SNIPPET generate
publishing {
- generateIvyCustomIvyModuleDescriptor {
+ generateDescriptorFileForIvyCustomPublication {
destination = file("$buildDir/generated-ivy.xml")
}
}
diff --git a/subprojects/docs/src/samples/ivy-publish/java-multi-project/build.gradle b/subprojects/docs/src/samples/ivy-publish/java-multi-project/build.gradle
index 0d833d9..0d7cfdf 100644
--- a/subprojects/docs/src/samples/ivy-publish/java-multi-project/build.gradle
+++ b/subprojects/docs/src/samples/ivy-publish/java-multi-project/build.gradle
@@ -38,7 +38,7 @@ subprojects {
// END SNIPPET publish-custom-artifact
repositories {
ivy {
- url "file://${rootProject.buildDir}/repo" // change to point to your repo, e.g. http://my.org/repo
+ url "${rootProject.buildDir}/repo" // change to point to your repo, e.g. http://my.org/repo
}
}
// START SNIPPET publish-custom-artifact
diff --git a/subprojects/docs/src/samples/ivy-publish/multiple-publications/build.gradle b/subprojects/docs/src/samples/ivy-publish/multiple-publications/build.gradle
new file mode 100644
index 0000000..31aae76
--- /dev/null
+++ b/subprojects/docs/src/samples/ivy-publish/multiple-publications/build.gradle
@@ -0,0 +1,83 @@
+subprojects {
+ apply plugin: 'java'
+ apply plugin: 'ivy-publish'
+
+ repositories {
+ mavenCentral()
+ }
+
+ publishing {
+ repositories {
+ ivy {
+ url "${rootProject.buildDir}/repo" // change to point to your repo, e.g. http://my.org/repo
+ }
+ }
+ }
+}
+
+project(":project1") {
+ dependencies {
+ compile 'junit:junit:4.11'
+ }
+
+
+ // START SNIPPET customize-identity
+ publishing {
+ publications {
+ ivy(IvyPublication) {
+ organisation 'org.gradle.sample'
+ module 'project1-sample'
+ revision '1.1'
+ descriptor.status = 'milestone'
+
+ from components.java
+ }
+ }
+ }
+ // END SNIPPET customize-identity
+}
+
+project(":project2") {
+ // START SNIPPET multiple-publications
+ task apiJar(type: Jar) {
+ baseName "publishing-api"
+ from sourceSets.main.output
+ exclude '**/impl/**'
+ }
+ // END SNIPPET multiple-publications
+
+ dependencies {
+ compile 'commons-collections:commons-collections:3.1', project(':project1')
+ }
+
+ // START SNIPPET multiple-publications
+ publishing {
+ publications {
+ impl(IvyPublication) {
+ organisation 'org.gradle.sample.impl'
+ module 'project2-impl'
+ revision '2.3'
+
+ from components.java
+ }
+ api(IvyPublication) {
+ // END SNIPPET multiple-publications
+ configurations {
+ it.default {
+ extend "runtime"
+ }
+ runtime {}
+ }
+ artifact(apiJar) {
+ conf "runtime"
+ }
+
+ // START SNIPPET multiple-publications
+ organisation 'org.gradle.sample'
+ module 'project2-api'
+ revision '2'
+ }
+ }
+ }
+ // END SNIPPET multiple-publications
+}
diff --git a/subprojects/docs/src/samples/ivy-publish/multiple-publications/output/project1.ivy.xml b/subprojects/docs/src/samples/ivy-publish/multiple-publications/output/project1.ivy.xml
new file mode 100644
index 0000000..f74cff2
--- /dev/null
+++ b/subprojects/docs/src/samples/ivy-publish/multiple-publications/output/project1.ivy.xml
@@ -0,0 +1,15 @@
+<!-- This file is an example of the Ivy module descriptor that this build will produce -->
+<?xml version="1.0" encoding="UTF-8"?>
+<ivy-module version="2.0">
+ <info organisation="org.gradle.sample" module="project1-sample" revision="1.1" status="milestone" publication="«PUBLICATION-TIME-STAMP»"/>
+ <configurations>
+ <conf name="default" visibility="public" extends="runtime"/>
+ <conf name="runtime" visibility="public"/>
+ </configurations>
+ <publications>
+ <artifact name="project1-sample" type="jar" ext="jar" conf="runtime"/>
+ </publications>
+ <dependencies>
+ <dependency org="junit" name="junit" rev="4.11" conf="runtime->default"/>
+ </dependencies>
+</ivy-module>
diff --git a/subprojects/docs/src/samples/ivy-publish/multiple-publications/output/project2-api.ivy.xml b/subprojects/docs/src/samples/ivy-publish/multiple-publications/output/project2-api.ivy.xml
new file mode 100644
index 0000000..b695d6a
--- /dev/null
+++ b/subprojects/docs/src/samples/ivy-publish/multiple-publications/output/project2-api.ivy.xml
@@ -0,0 +1,13 @@
+<!-- This file is an example of the Ivy module descriptor that this build will produce -->
+<?xml version="1.0" encoding="UTF-8"?>
+<ivy-module version="2.0">
+ <info organisation="org.gradle.sample" module="project2-api" revision="2" status="integration" publication="«PUBLICATION-TIME-STAMP»"/>
+ <configurations>
+ <conf name="default" visibility="public" extends="runtime"/>
+ <conf name="runtime" visibility="public"/>
+ </configurations>
+ <publications>
+ <artifact name="project2-api" type="jar" ext="jar" conf="runtime"/>
+ </publications>
+ <dependencies/>
+</ivy-module>
diff --git a/subprojects/docs/src/samples/ivy-publish/multiple-publications/output/project2-impl.ivy.xml b/subprojects/docs/src/samples/ivy-publish/multiple-publications/output/project2-impl.ivy.xml
new file mode 100644
index 0000000..30e4e54
--- /dev/null
+++ b/subprojects/docs/src/samples/ivy-publish/multiple-publications/output/project2-impl.ivy.xml
@@ -0,0 +1,16 @@
+<!-- This file is an example of the Ivy module descriptor that this build will produce -->
+<?xml version="1.0" encoding="UTF-8"?>
+<ivy-module version="2.0">
+ <info organisation="org.gradle.sample.impl" module="project2-impl" revision="2.3" status="integration" publication="«PUBLICATION-TIME-STAMP»"/>
+ <configurations>
+ <conf name="default" visibility="public" extends="runtime"/>
+ <conf name="runtime" visibility="public"/>
+ </configurations>
+ <publications>
+ <artifact name="project2-impl" type="jar" ext="jar" conf="runtime"/>
+ </publications>
+ <dependencies>
+ <dependency org="commons-collections" name="commons-collections" rev="3.1" conf="runtime->default"/>
+ <dependency org="org.gradle.sample" name="project1-sample" rev="1.1" conf="runtime->default"/>
+ </dependencies>
+</ivy-module>
diff --git a/subprojects/docs/src/samples/ivy-publish/multiple-publications/settings.gradle b/subprojects/docs/src/samples/ivy-publish/multiple-publications/settings.gradle
new file mode 100644
index 0000000..611129e
--- /dev/null
+++ b/subprojects/docs/src/samples/ivy-publish/multiple-publications/settings.gradle
@@ -0,0 +1,2 @@
+rootProject.name = 'ivy-publish-multiple'
+include 'project1', 'project2'
diff --git a/subprojects/docs/src/samples/ivy-publish/quickstart/build.gradle b/subprojects/docs/src/samples/ivy-publish/quickstart/build.gradle
index 0d62680..e596ec3 100644
--- a/subprojects/docs/src/samples/ivy-publish/quickstart/build.gradle
+++ b/subprojects/docs/src/samples/ivy-publish/quickstart/build.gradle
@@ -17,7 +17,7 @@ publishing {
// START SNIPPET repositories
repositories {
ivy {
- url "file://$buildDir/repo" // change to point to your repo, e.g. http://my.org/repo
+ url "$buildDir/repo" // change to point to your repo, e.g. http://my.org/repo
}
}
// END SNIPPET repositories
diff --git a/subprojects/docs/src/samples/java/multiproject/services/webservice/src/test/java/org/gradle/webservice/TestTestTest.java b/subprojects/docs/src/samples/java/multiproject/services/webservice/src/test/java/org/gradle/webservice/TestTestTest.java
index 320d999..e09236c 100644
--- a/subprojects/docs/src/samples/java/multiproject/services/webservice/src/test/java/org/gradle/webservice/TestTestTest.java
+++ b/subprojects/docs/src/samples/java/multiproject/services/webservice/src/test/java/org/gradle/webservice/TestTestTest.java
@@ -2,9 +2,6 @@ package org.gradle.webservice;
import junit.framework.TestCase;
-/**
- * @author Hans Dockter
- */
public class TestTestTest extends TestCase {
public void testClasspath() {
new TestTest().method();
diff --git a/subprojects/docs/src/samples/java/quickstart/build.gradle b/subprojects/docs/src/samples/java/quickstart/build.gradle
index f1b1d1d..8b5fa71 100644
--- a/subprojects/docs/src/samples/java/quickstart/build.gradle
+++ b/subprojects/docs/src/samples/java/quickstart/build.gradle
@@ -5,7 +5,7 @@ apply plugin: 'java'
apply plugin: 'eclipse'
// END SNIPPET use-eclipse-plugin
-// START SNIPPET customisation
+// START SNIPPET customization
sourceCompatibility = 1.5
version = '1.0'
jar {
@@ -13,7 +13,7 @@ jar {
attributes 'Implementation-Title': 'Gradle Quickstart', 'Implementation-Version': version
}
}
-// END SNIPPET customisation
+// END SNIPPET customization
// START SNIPPET repo
repositories {
@@ -28,11 +28,11 @@ dependencies {
}
// END SNIPPET dependencies
-// START SNIPPET task-customisation
+// START SNIPPET task-customization
test {
systemProperties 'property': 'value'
}
-// END SNIPPET task-customisation
+// END SNIPPET task-customization
// START SNIPPET upload
uploadArchives {
diff --git a/subprojects/docs/src/samples/maven-publish/javaProject/build.gradle b/subprojects/docs/src/samples/maven-publish/javaProject/build.gradle
index d4bc19b..b615a76 100644
--- a/subprojects/docs/src/samples/maven-publish/javaProject/build.gradle
+++ b/subprojects/docs/src/samples/maven-publish/javaProject/build.gradle
@@ -30,7 +30,7 @@ publishing {
// END SNIPPET publish-custom-artifact
repositories {
maven {
- url "file://$buildDir/repo" // change to point to your repo, e.g. http://my.org/repo
+ url "$buildDir/repo" // change to point to your repo, e.g. http://my.org/repo
}
}
// START SNIPPET publish-custom-artifact
diff --git a/subprojects/docs/src/samples/maven-publish/multiple-publications/build.gradle b/subprojects/docs/src/samples/maven-publish/multiple-publications/build.gradle
new file mode 100644
index 0000000..8d9c491
--- /dev/null
+++ b/subprojects/docs/src/samples/maven-publish/multiple-publications/build.gradle
@@ -0,0 +1,69 @@
+subprojects {
+ apply plugin: 'java'
+ apply plugin: 'maven-publish'
+
+ repositories {
+ mavenCentral()
+ }
+
+ publishing {
+ repositories {
+ maven {
+ url "${rootProject.buildDir}/repo" // change to point to your repo, e.g. http://my.org/repo
+ }
+ }
+ }
+}
+
+project(":project1") {
+ dependencies {
+ compile 'org.slf4j:slf4j-api:1.7.5'
+ }
+
+ // START SNIPPET customize-identity
+ publishing {
+ publications {
+ maven(MavenPublication) {
+ groupId 'org.gradle.sample'
+ artifactId 'project1-sample'
+ version '1.1'
+
+ from components.java
+ }
+ }
+ }
+ // END SNIPPET customize-identity
+}
+
+project(":project2") {
+ dependencies {
+ compile 'commons-collections:commons-collections:3.1', project(':project1')
+ }
+
+ // START SNIPPET multiple-publications
+ task apiJar(type: Jar) {
+ baseName "publishing-api"
+ from sourceSets.main.output
+ exclude '**/impl/**'
+ }
+
+ publishing {
+ publications {
+ impl(MavenPublication) {
+ groupId 'org.gradle.sample.impl'
+ artifactId 'project2-impl'
+ version '2.3'
+
+ from components.java
+ }
+ api(MavenPublication) {
+ groupId 'org.gradle.sample'
+ artifactId 'project2-api'
+ version '2'
+
+ artifact apiJar
+ }
+ }
+ }
+ // END SNIPPET multiple-publications
+}
diff --git a/subprojects/docs/src/samples/maven-publish/multiple-publications/output/project1.pom.xml b/subprojects/docs/src/samples/maven-publish/multiple-publications/output/project1.pom.xml
new file mode 100644
index 0000000..d5e2f42
--- /dev/null
+++ b/subprojects/docs/src/samples/maven-publish/multiple-publications/output/project1.pom.xml
@@ -0,0 +1,17 @@
+<!-- Example of the Maven POM this build will produce -->
+<?xml version="1.0" encoding="UTF-8"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.gradle.sample</groupId>
+ <artifactId>project1-sample</artifactId>
+ <version>1.1</version>
+ <dependencies>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>1.7.5</version>
+ <scope>runtime</scope>
+ </dependency>
+ </dependencies>
+</project>
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/maven-publish/multiple-publications/output/project2-api.pom.xml b/subprojects/docs/src/samples/maven-publish/multiple-publications/output/project2-api.pom.xml
new file mode 100644
index 0000000..0c39c1b
--- /dev/null
+++ b/subprojects/docs/src/samples/maven-publish/multiple-publications/output/project2-api.pom.xml
@@ -0,0 +1,9 @@
+<!-- This file is an example of the Ivy module descriptor that this build will produce -->
+<?xml version="1.0" encoding="UTF-8"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.gradle.sample</groupId>
+ <artifactId>project2-api</artifactId>
+ <version>2</version>
+</project>
diff --git a/subprojects/docs/src/samples/maven-publish/multiple-publications/output/project2-impl.pom.xml b/subprojects/docs/src/samples/maven-publish/multiple-publications/output/project2-impl.pom.xml
new file mode 100644
index 0000000..07d71c8
--- /dev/null
+++ b/subprojects/docs/src/samples/maven-publish/multiple-publications/output/project2-impl.pom.xml
@@ -0,0 +1,23 @@
+<!-- This file is an example of the Ivy module descriptor that this build will produce -->
+<?xml version="1.0" encoding="UTF-8"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.gradle.sample.impl</groupId>
+ <artifactId>project2-impl</artifactId>
+ <version>2.3</version>
+ <dependencies>
+ <dependency>
+ <groupId>commons-collections</groupId>
+ <artifactId>commons-collections</artifactId>
+ <version>3.1</version>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.gradle.sample</groupId>
+ <artifactId>project1-sample</artifactId>
+ <version>1.1</version>
+ <scope>runtime</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/subprojects/docs/src/samples/maven-publish/multiple-publications/settings.gradle b/subprojects/docs/src/samples/maven-publish/multiple-publications/settings.gradle
new file mode 100644
index 0000000..efcca68
--- /dev/null
+++ b/subprojects/docs/src/samples/maven-publish/multiple-publications/settings.gradle
@@ -0,0 +1,2 @@
+rootProject.name = 'maven-publish-multiple'
+include 'project1', 'project2'
diff --git a/subprojects/docs/src/samples/maven-publish/pomCustomization/build.gradle b/subprojects/docs/src/samples/maven-publish/pomCustomization/build.gradle
index b0fc28b..05a0e0b 100644
--- a/subprojects/docs/src/samples/maven-publish/pomCustomization/build.gradle
+++ b/subprojects/docs/src/samples/maven-publish/pomCustomization/build.gradle
@@ -8,14 +8,14 @@ publishing {
publications {
mavenCustom(MavenPublication) {
pom.withXml {
- asNode().appendNode('description', 'A demonstration of maven pom customisation')
+ asNode().appendNode('description', 'A demonstration of maven POM customization')
}
}
}
// END SNIPPET pom-modification
repositories {
maven {
- url "file://$buildDir/repo" // change to point to your repo, e.g. http://my.org/repo
+ url "$buildDir/repo" // change to point to your repo, e.g. http://my.org/repo
}
}
}
diff --git a/subprojects/docs/src/samples/maven-publish/quickstart/build.gradle b/subprojects/docs/src/samples/maven-publish/quickstart/build.gradle
index 853a142..770938e 100644
--- a/subprojects/docs/src/samples/maven-publish/quickstart/build.gradle
+++ b/subprojects/docs/src/samples/maven-publish/quickstart/build.gradle
@@ -17,7 +17,7 @@ publishing {
// START SNIPPET repositories
repositories {
maven {
- url "file://$buildDir/repo" // change to point to your repo, e.g. http://my.org/repo
+ url "$buildDir/repo" // change to point to your repo, e.g. http://my.org/repo
}
}
// END SNIPPET repositories
diff --git a/subprojects/docs/src/samples/multiProjectBuildSrc/buildSrc/build.gradle b/subprojects/docs/src/samples/multiProjectBuildSrc/buildSrc/build.gradle
index c2bafa7..1222b30 100644
--- a/subprojects/docs/src/samples/multiProjectBuildSrc/buildSrc/build.gradle
+++ b/subprojects/docs/src/samples/multiProjectBuildSrc/buildSrc/build.gradle
@@ -2,7 +2,7 @@ subprojects {
apply plugin: "groovy"
dependencies {
- groovy localGroovy()
+ compile localGroovy()
compile gradleApi()
}
diff --git a/subprojects/docs/src/samples/osgi/build.gradle b/subprojects/docs/src/samples/osgi/build.gradle
index dba106b..d661386 100644
--- a/subprojects/docs/src/samples/osgi/build.gradle
+++ b/subprojects/docs/src/samples/osgi/build.gradle
@@ -14,8 +14,8 @@ repositories {
}
dependencies {
- groovy group: 'org.codehaus.groovy', name: 'groovy-all', version: '1.7.10'
- compile group: 'org.eclipse', name: 'osgi', version: '3.5.0.v20090520'
+ compile 'org.codehaus.groovy:groovy-all:2.0.5'
+ compile 'org.eclipse:osgi:3.5.0.v20090520'
}
jar {
diff --git a/subprojects/docs/src/samples/osgi/src/main/groovy/org/gradle/GradleActivator.groovy b/subprojects/docs/src/samples/osgi/src/main/groovy/org/gradle/GradleActivator.groovy
index a5116ff..15f0e0d 100644
--- a/subprojects/docs/src/samples/osgi/src/main/groovy/org/gradle/GradleActivator.groovy
+++ b/subprojects/docs/src/samples/osgi/src/main/groovy/org/gradle/GradleActivator.groovy
@@ -3,11 +3,6 @@ package org.gradle
import org.osgi.framework.BundleActivator
import org.osgi.framework.BundleContext
-/**
-* A sample OSGi Activator written in Groovy.
-*
-* @author Hamlet D'Arcy
-*/
public class GradleActivator implements BundleActivator {
public void start(BundleContext context) {
diff --git a/subprojects/docs/src/samples/sonarRunner/multiProject/build.gradle b/subprojects/docs/src/samples/sonarRunner/multiProject/build.gradle
index f79cf7c..1d43c6c 100644
--- a/subprojects/docs/src/samples/sonarRunner/multiProject/build.gradle
+++ b/subprojects/docs/src/samples/sonarRunner/multiProject/build.gradle
@@ -6,8 +6,8 @@ sonarRunner {
property "sonar.host.url", "http://my.server.com"
property "sonar.jdbc.url", "jdbc:mysql://my.server.com/sonar"
property "sonar.jdbc.driverClassName", "com.mysql.jdbc.Driver"
- property "sonar.username", "Fred Flintstone"
- property "sonar.password", "very clever"
+ property "sonar.jdbc.username", "Fred Flintstone"
+ property "sonar.jdbc.password", "very clever"
}
}
// END SNIPPET global-configuration-settings
diff --git a/subprojects/docs/src/samples/sonarRunner/quickstart/build.gradle b/subprojects/docs/src/samples/sonarRunner/quickstart/build.gradle
index c52cf83..10e7a73 100644
--- a/subprojects/docs/src/samples/sonarRunner/quickstart/build.gradle
+++ b/subprojects/docs/src/samples/sonarRunner/quickstart/build.gradle
@@ -10,8 +10,8 @@ sonarRunner {
property "sonar.host.url", "http://my.server.com"
property "sonar.jdbc.url", "jdbc:mysql://my.server.com/sonar"
property "sonar.jdbc.driverClassName", "com.mysql.jdbc.Driver"
- property "sonar.username", "Fred Flintstone"
- property "sonar.password", "very clever"
+ property "sonar.jdbc.username", "Fred Flintstone"
+ property "sonar.jdbc.password", "very clever"
}
}
// END SNIPPET connection-settings
diff --git a/subprojects/docs/src/samples/cpp/exewithlib/exe/src/main/cpp/main.cpp b/subprojects/docs/src/samples/src/main/cpp/library/cpp/main.cpp
similarity index 100%
rename from subprojects/docs/src/samples/cpp/exewithlib/exe/src/main/cpp/main.cpp
rename to subprojects/docs/src/samples/src/main/cpp/library/cpp/main.cpp
diff --git a/subprojects/docs/src/samples/testing/jacoco/application/build.gradle b/subprojects/docs/src/samples/testing/jacoco/application/build.gradle
new file mode 100644
index 0000000..943de86
--- /dev/null
+++ b/subprojects/docs/src/samples/testing/jacoco/application/build.gradle
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+// START SNIPPET application-configuration
+apply plugin: "application"
+apply plugin: "jacoco"
+
+mainClassName = "org.gradle.MyMain"
+
+jacoco {
+ applyTo run
+}
+
+task applicationCodeCoverageReport(type:JacocoReport){
+ executionData run
+ sourceSets sourceSets.main
+}
+// END SNIPPET application-configuration
+
+repositories {
+ mavenCentral()
+}
diff --git a/subprojects/docs/src/samples/testing/jacoco/application/src/main/java/org/gradle/MyMain.java b/subprojects/docs/src/samples/testing/jacoco/application/src/main/java/org/gradle/MyMain.java
new file mode 100644
index 0000000..8b2b531
--- /dev/null
+++ b/subprojects/docs/src/samples/testing/jacoco/application/src/main/java/org/gradle/MyMain.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle;
+
+import java.lang.String;
+
+public class MyMain{
+
+ public static void main(String... args){
+ new MyMain().someMethod();
+ }
+
+ private void someMethod(){
+ System.out.println("Some output from 'MyMain'");
+ }
+}
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/testing/jacoco/quickstart/build.gradle b/subprojects/docs/src/samples/testing/jacoco/quickstart/build.gradle
new file mode 100644
index 0000000..0c41485
--- /dev/null
+++ b/subprojects/docs/src/samples/testing/jacoco/quickstart/build.gradle
@@ -0,0 +1,58 @@
+
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+apply plugin: "java"
+
+// START SNIPPET apply-plugin
+apply plugin: "jacoco"
+// END SNIPPET apply-plugin
+
+// START SNIPPET jacoco-configuration
+jacoco {
+ toolVersion = "0.6.2.201302030002"
+ reportsDir = file("$buildDir/customJacocoReportDir")
+}
+// END SNIPPET jacoco-configuration
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ testCompile "junit:junit:4.+"
+}
+
+// START SNIPPET testtask-configuration
+test {
+ jacoco {
+ append = false
+ destinationFile = file("$buildDir/jacoco/jacocoTest.exec")
+ classDumpFile = file("$buildDir/jacoco/classpathdumps")
+ }
+}
+// END SNIPPET testtask-configuration
+
+
+// START SNIPPET report-configuration
+jacocoTestReport {
+ reports {
+ xml.enabled false
+ csv.enabled false
+ html.destination "${buildDir}/jacocoHtml"
+ }
+}
+// END SNIPPET report-configuration
diff --git a/subprojects/docs/src/samples/testing/jacoco/quickstart/src/main/java/org/gradle/Person.java b/subprojects/docs/src/samples/testing/jacoco/quickstart/src/main/java/org/gradle/Person.java
new file mode 100644
index 0000000..9c40af9
--- /dev/null
+++ b/subprojects/docs/src/samples/testing/jacoco/quickstart/src/main/java/org/gradle/Person.java
@@ -0,0 +1,24 @@
+package org.gradle;
+
+import java.lang.String;
+
+public class Person{
+ String surname;
+ int age;
+
+ public String getSurname() {
+ return surname;
+ }
+
+ public void setSurname(String surname) {
+ this.surname = surname;
+ }
+
+ public int getAge() {
+ return age;
+ }
+
+ public void setAge(int age) {
+ this.age = age;
+ }
+}
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/testing/jacoco/quickstart/src/test/java/org/gradle/PersonTest.java b/subprojects/docs/src/samples/testing/jacoco/quickstart/src/test/java/org/gradle/PersonTest.java
new file mode 100644
index 0000000..7864bd8
--- /dev/null
+++ b/subprojects/docs/src/samples/testing/jacoco/quickstart/src/test/java/org/gradle/PersonTest.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle;
+
+import org.junit.Test;
+import org.junit.Before;
+
+import static org.junit.Assert.assertEquals;
+
+public class PersonTest{
+
+ Person person;
+ @Before public void setup(){
+ person = new Person();
+ }
+
+ @Test public void testAge() {
+ person.setAge(30);
+ assertEquals(30, person.getAge());
+ }
+
+
+ @Test public void testSurname() {
+ person.setSurname("Duke");
+ assertEquals("Duke", person.getSurname());
+ }
+}
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/testing/junit/categories/build.gradle b/subprojects/docs/src/samples/testing/junit/categories/build.gradle
new file mode 100644
index 0000000..457a88b
--- /dev/null
+++ b/subprojects/docs/src/samples/testing/junit/categories/build.gradle
@@ -0,0 +1,18 @@
+apply plugin: 'java'
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ testCompile 'junit:junit:4.11'
+}
+
+// START SNIPPET test-categories
+test {
+ useJUnit {
+ includeCategories 'org.gradle.junit.CategoryA'
+ excludeCategories 'org.gradle.junit.CategoryB'
+ }
+}
+// END SNIPPET test-categories
diff --git a/subprojects/docs/src/samples/testing/junit/categories/src/test/java/org/gradle/junit/CategorizedJUnitTest.java b/subprojects/docs/src/samples/testing/junit/categories/src/test/java/org/gradle/junit/CategorizedJUnitTest.java
new file mode 100644
index 0000000..f30aa5f
--- /dev/null
+++ b/subprojects/docs/src/samples/testing/junit/categories/src/test/java/org/gradle/junit/CategorizedJUnitTest.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.junit;
+
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+public class CategorizedJUnitTest {
+
+ @Category(CategoryA.class)
+ @Test
+ public void a() {
+ System.out.println("hello from CategorizedTest a.");
+ }
+
+ @Category(CategoryB.class)
+ @Test
+ public void b() {
+ System.out.println("hello from CategorizedTest b.");
+ }
+}
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/testing/junit/categories/src/test/java/org/gradle/junit/CategoryA.java b/subprojects/docs/src/samples/testing/junit/categories/src/test/java/org/gradle/junit/CategoryA.java
new file mode 100644
index 0000000..d80ba09
--- /dev/null
+++ b/subprojects/docs/src/samples/testing/junit/categories/src/test/java/org/gradle/junit/CategoryA.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.junit;
+
+public interface CategoryA{
+
+}
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/testing/junit/categories/src/test/java/org/gradle/junit/CategoryB.java b/subprojects/docs/src/samples/testing/junit/categories/src/test/java/org/gradle/junit/CategoryB.java
new file mode 100644
index 0000000..e10eba9
--- /dev/null
+++ b/subprojects/docs/src/samples/testing/junit/categories/src/test/java/org/gradle/junit/CategoryB.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.junit;
+
+public interface CategoryB{
+
+}
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/testing/junit/categories/src/test/java/org/gradle/junit/SimpleJUnitTest.java b/subprojects/docs/src/samples/testing/junit/categories/src/test/java/org/gradle/junit/SimpleJUnitTest.java
new file mode 100644
index 0000000..03588b4
--- /dev/null
+++ b/subprojects/docs/src/samples/testing/junit/categories/src/test/java/org/gradle/junit/SimpleJUnitTest.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.junit;
+
+import org.junit.Test;
+import java.lang.System;
+
+public class SimpleJUnitTest {
+ @Test
+ public void ok() {
+ System.out.println("hello from SimpleJUnitTest.");
+ }
+}
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/testing/testReport/build.gradle b/subprojects/docs/src/samples/testing/testReport/build.gradle
index c9cdcf3..fb83a7d 100644
--- a/subprojects/docs/src/samples/testing/testReport/build.gradle
+++ b/subprojects/docs/src/samples/testing/testReport/build.gradle
@@ -14,7 +14,7 @@ subprojects {
// START SNIPPET test-report
// Disable the test report for the individual test task
test {
- testReport = false
+ reports.html.enabled = false
}
}
diff --git a/subprojects/docs/src/samples/testing/testng/groups/build.gradle b/subprojects/docs/src/samples/testing/testng/groups/build.gradle
new file mode 100644
index 0000000..d9bc57a
--- /dev/null
+++ b/subprojects/docs/src/samples/testing/testng/groups/build.gradle
@@ -0,0 +1,18 @@
+apply plugin: 'java'
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ testCompile 'org.testng:testng:6.3.1'
+}
+
+// START SNIPPET test-config
+test {
+ useTestNG {
+ excludeGroups 'integrationTests'
+ includeGroups 'unitTests'
+ }
+}
+// END SNIPPET test-config
diff --git a/subprojects/docs/src/samples/testing/testng/groups/src/test/java/org/gradle/testng/SimpleIntegrationTest.java b/subprojects/docs/src/samples/testing/testng/groups/src/test/java/org/gradle/testng/SimpleIntegrationTest.java
new file mode 100644
index 0000000..0fab222
--- /dev/null
+++ b/subprojects/docs/src/samples/testing/testng/groups/src/test/java/org/gradle/testng/SimpleIntegrationTest.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.testng;
+
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.testng.annotations.AfterMethod;
+import static org.testng.Assert.*;
+
+public class SimpleIntegrationTest{
+ @Test(groups = { "integrationTests" })
+ public void simpleIntegrationTest(){
+ assertEquals(true, true);
+ }
+}
diff --git a/subprojects/docs/src/samples/testing/testng/groups/src/test/java/org/gradle/testng/SimpleUnitTest.java b/subprojects/docs/src/samples/testing/testng/groups/src/test/java/org/gradle/testng/SimpleUnitTest.java
new file mode 100644
index 0000000..8311ca9
--- /dev/null
+++ b/subprojects/docs/src/samples/testing/testng/groups/src/test/java/org/gradle/testng/SimpleUnitTest.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.testng;
+
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.testng.annotations.AfterMethod;
+import static org.testng.Assert.*;
+
+public class SimpleUnitTest{
+ @Test(groups = { "unitTests" })
+ public void simpleUnitTest(){
+ assertEquals(true, true);
+ }
+}
diff --git a/subprojects/docs/src/samples/testing/testng/suitexmlbuilder/src/main/java/org/gradle/testng/User.java b/subprojects/docs/src/samples/testing/testng/suitexmlbuilder/src/main/java/org/gradle/testng/User.java
index 06503c7..27641b2 100644
--- a/subprojects/docs/src/samples/testing/testng/suitexmlbuilder/src/main/java/org/gradle/testng/User.java
+++ b/subprojects/docs/src/samples/testing/testng/suitexmlbuilder/src/main/java/org/gradle/testng/User.java
@@ -1,8 +1,5 @@
package org.gradle.testng;
-/**
- * @author Tom Eyckmans
- */
public interface User
{
String getFirstName();
diff --git a/subprojects/docs/src/samples/testing/testng/suitexmlbuilder/src/main/java/org/gradle/testng/UserImpl.java b/subprojects/docs/src/samples/testing/testng/suitexmlbuilder/src/main/java/org/gradle/testng/UserImpl.java
index eb7bd74..96df209 100644
--- a/subprojects/docs/src/samples/testing/testng/suitexmlbuilder/src/main/java/org/gradle/testng/UserImpl.java
+++ b/subprojects/docs/src/samples/testing/testng/suitexmlbuilder/src/main/java/org/gradle/testng/UserImpl.java
@@ -1,8 +1,5 @@
package org.gradle.testng;
-/**
- * @author Tom Eyckmans
- */
public class UserImpl implements User
{
private final String firstName;
diff --git a/subprojects/docs/src/samples/testing/testng/suitexmlbuilder/src/test/java/org/gradle/testng/UserImplTest.java b/subprojects/docs/src/samples/testing/testng/suitexmlbuilder/src/test/java/org/gradle/testng/UserImplTest.java
index 99deeb8..2127fbb 100644
--- a/subprojects/docs/src/samples/testing/testng/suitexmlbuilder/src/test/java/org/gradle/testng/UserImplTest.java
+++ b/subprojects/docs/src/samples/testing/testng/suitexmlbuilder/src/test/java/org/gradle/testng/UserImplTest.java
@@ -5,9 +5,6 @@ import org.testng.annotations.Test;
import org.testng.annotations.AfterMethod;
import static org.testng.Assert.*;
-/**
- * @author Tom Eyckmans
- */
public class UserImplTest
{
private UserImpl user;
diff --git a/subprojects/docs/src/samples/toolingApi/customModel/plugin/build.gradle b/subprojects/docs/src/samples/toolingApi/customModel/plugin/build.gradle
new file mode 100644
index 0000000..36078ff
--- /dev/null
+++ b/subprojects/docs/src/samples/toolingApi/customModel/plugin/build.gradle
@@ -0,0 +1,20 @@
+apply plugin: 'java'
+apply plugin: 'ivy-publish'
+
+group 'org.gradle.sample'
+version '1.0'
+
+dependencies {
+ compile gradleApi()
+}
+
+publishing {
+ repositories {
+ ivy { url 'build/repo' }
+ }
+ publications {
+ ivy(IvyPublication) {
+ from components.java
+ }
+ }
+}
diff --git a/subprojects/docs/src/samples/toolingApi/customModel/plugin/src/main/java/org/gradle/sample/plugin/CustomModel.java b/subprojects/docs/src/samples/toolingApi/customModel/plugin/src/main/java/org/gradle/sample/plugin/CustomModel.java
new file mode 100644
index 0000000..efa736a
--- /dev/null
+++ b/subprojects/docs/src/samples/toolingApi/customModel/plugin/src/main/java/org/gradle/sample/plugin/CustomModel.java
@@ -0,0 +1,14 @@
+package org.gradle.sample.plugin;
+
+import java.util.List;
+import org.gradle.tooling.model.Model;
+import org.gradle.tooling.model.DomainObjectSet;
+
+/**
+ * This is a custom tooling model. It must be assignable to {@link Model} and it must be an interface.
+ */
+public interface CustomModel extends Model {
+ String getName();
+
+ DomainObjectSet<String> getTasks();
+}
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/toolingApi/customModel/plugin/src/main/java/org/gradle/sample/plugin/CustomPlugin.java b/subprojects/docs/src/samples/toolingApi/customModel/plugin/src/main/java/org/gradle/sample/plugin/CustomPlugin.java
new file mode 100644
index 0000000..dfcc0f5
--- /dev/null
+++ b/subprojects/docs/src/samples/toolingApi/customModel/plugin/src/main/java/org/gradle/sample/plugin/CustomPlugin.java
@@ -0,0 +1,39 @@
+package org.gradle.sample.plugin;
+
+import javax.inject.Inject;
+import org.gradle.api.Plugin;
+import org.gradle.api.Project;
+import org.gradle.tooling.provider.model.ToolingModelBuilder;
+import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry;
+
+/**
+ * A plugin that exposes a custom tooling model.
+ */
+public class CustomPlugin implements Plugin<Project> {
+ private final ToolingModelBuilderRegistry registry;
+
+ /**
+ * Need to use a {@link ToolingModelBuilderRegistry} to register the custom tooling model, so inject this into
+ * the constructor.
+ */
+ @Inject
+ public CustomPlugin(ToolingModelBuilderRegistry registry) {
+ this.registry = registry;
+ }
+
+ public void apply(Project project) {
+ // Register a builder for the custom tooling model
+ registry.register(new CustomToolingModelBuilder());
+ }
+
+ private static class CustomToolingModelBuilder extends ToolingModelBuilder {
+ public boolean canBuild(String modelName) {
+ // The default name for a model is the name of the Java interface
+ return modelName.equals(CustomModel.class.getName());
+ }
+
+ public Object buildAll(String modelName, Project project) {
+ return new DefaultModel();
+ }
+ }
+}
diff --git a/subprojects/docs/src/samples/toolingApi/customModel/plugin/src/main/java/org/gradle/sample/plugin/DefaultModel.java b/subprojects/docs/src/samples/toolingApi/customModel/plugin/src/main/java/org/gradle/sample/plugin/DefaultModel.java
new file mode 100644
index 0000000..99d533b
--- /dev/null
+++ b/subprojects/docs/src/samples/toolingApi/customModel/plugin/src/main/java/org/gradle/sample/plugin/DefaultModel.java
@@ -0,0 +1,20 @@
+package org.gradle.sample.plugin;
+
+import java.io.Serializable;
+import java.lang.String;
+import java.util.List;
+import java.util.Arrays;
+
+/**
+ * This is the implementation of the custom tooling model. It must be serializable and must have methods and properties that
+ * are compatible with the custom tooling model interface. It may or may not implement the custom tooling model interface.
+ */
+public class DefaultModel implements Serializable {
+ public String getName() {
+ return "name";
+ }
+
+ public List<String> getTasks() {
+ return Arrays.asList(":a", ":b", ":c");
+ }
+}
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/toolingApi/customModel/plugin/src/main/resources/META-INF/gradle-plugins/custom-plugin.properties b/subprojects/docs/src/samples/toolingApi/customModel/plugin/src/main/resources/META-INF/gradle-plugins/custom-plugin.properties
new file mode 100644
index 0000000..451e4ed
--- /dev/null
+++ b/subprojects/docs/src/samples/toolingApi/customModel/plugin/src/main/resources/META-INF/gradle-plugins/custom-plugin.properties
@@ -0,0 +1 @@
+implementation-class: org.gradle.sample.plugin.CustomPlugin
diff --git a/subprojects/docs/src/samples/toolingApi/customModel/readme.xml b/subprojects/docs/src/samples/toolingApi/customModel/readme.xml
new file mode 100644
index 0000000..664199f
--- /dev/null
+++ b/subprojects/docs/src/samples/toolingApi/customModel/readme.xml
@@ -0,0 +1,3 @@
+<sample>
+ <para>A sample of how a plugin can expose its own custom tooling model to tooling API clients.</para>
+</sample>
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/toolingApi/customModel/sampleBuild/build.gradle b/subprojects/docs/src/samples/toolingApi/customModel/sampleBuild/build.gradle
new file mode 100644
index 0000000..273de5c
--- /dev/null
+++ b/subprojects/docs/src/samples/toolingApi/customModel/sampleBuild/build.gradle
@@ -0,0 +1,10 @@
+buildscript {
+ repositories {
+ ivy { url '../plugin/build/repo' }
+ }
+ dependencies {
+ classpath 'org.gradle.sample:plugin:1.0'
+ }
+}
+
+apply plugin: 'custom-plugin'
diff --git a/subprojects/docs/src/samples/toolingApi/customModel/sampleBuild/settings.gradle b/subprojects/docs/src/samples/toolingApi/customModel/sampleBuild/settings.gradle
new file mode 100644
index 0000000..0f1d7f3
--- /dev/null
+++ b/subprojects/docs/src/samples/toolingApi/customModel/sampleBuild/settings.gradle
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
diff --git a/subprojects/docs/src/samples/toolingApi/customModel/tooling/build.gradle b/subprojects/docs/src/samples/toolingApi/customModel/tooling/build.gradle
new file mode 100644
index 0000000..600e074
--- /dev/null
+++ b/subprojects/docs/src/samples/toolingApi/customModel/tooling/build.gradle
@@ -0,0 +1,22 @@
+apply plugin: 'application'
+
+def toolingApiVersion = gradle.gradleVersion
+
+repositories {
+ ivy {
+ url '../plugin/build/repo'
+ }
+ maven {
+ url 'http://repo.gradle.org/gradle/libs-releases-local'
+ }
+ mavenCentral()
+}
+
+dependencies {
+ compile 'org.gradle.sample:plugin:1.0'
+ compile "org.gradle:gradle-tooling-api:${toolingApiVersion}"
+ // Need an SLF4J implementation at runtime
+ runtime 'org.slf4j:slf4j-simple:1.7.2'
+}
+
+mainClassName = 'org.gradle.sample.Main'
diff --git a/subprojects/docs/src/samples/toolingApi/customModel/tooling/src/main/java/org/gradle/sample/Main.java b/subprojects/docs/src/samples/toolingApi/customModel/tooling/src/main/java/org/gradle/sample/Main.java
new file mode 100644
index 0000000..2550f2b
--- /dev/null
+++ b/subprojects/docs/src/samples/toolingApi/customModel/tooling/src/main/java/org/gradle/sample/Main.java
@@ -0,0 +1,39 @@
+package org.gradle.sample;
+
+import org.gradle.tooling.*;
+import org.gradle.sample.plugin.CustomModel;
+
+import java.io.File;
+import java.lang.Object;
+import java.lang.String;
+import java.lang.System;
+
+public class Main {
+ public static void main(String[] args) {
+ // Configure the connector and create the connection
+ GradleConnector connector = GradleConnector.newConnector();
+
+ if (args.length > 0) {
+ connector.useInstallation(new File(args[0]));
+ if (args.length > 1) {
+ connector.useGradleUserHomeDir(new File(args[1]));
+ }
+ }
+
+ connector.forProjectDirectory(new File("../sampleBuild"));
+
+ ProjectConnection connection = connector.connect();
+ try {
+ // Load the custom model for the project
+ CustomModel model = connection.getModel(CustomModel.class);
+ System.out.println("Project: " + model.getName());
+ System.out.println("Tasks: ");
+ for (String task : model.getTasks()) {
+ System.out.println(" " + task);
+ }
+ } finally {
+ // Clean up
+ connection.close();
+ }
+ }
+}
diff --git a/subprojects/docs/src/samples/toolingApi/eclipse/src/main/java/org/gradle/sample/Main.java b/subprojects/docs/src/samples/toolingApi/eclipse/src/main/java/org/gradle/sample/Main.java
index 40e8d48..7458d67 100644
--- a/subprojects/docs/src/samples/toolingApi/eclipse/src/main/java/org/gradle/sample/Main.java
+++ b/subprojects/docs/src/samples/toolingApi/eclipse/src/main/java/org/gradle/sample/Main.java
@@ -12,7 +12,6 @@ public class Main {
public static void main(String[] args) {
// Configure the connector and create the connection
GradleConnector connector = GradleConnector.newConnector();
- connector.forProjectDirectory(new File("."));
if (args.length > 0) {
connector.useInstallation(new File(args[0]));
@@ -21,9 +20,7 @@ public class Main {
}
}
- if (args.length > 0) {
- connector.useInstallation(new File(args[0]));
- }
+ connector.forProjectDirectory(new File("."));
ProjectConnection connection = connector.connect();
try {
diff --git a/subprojects/docs/src/samples/toolingApi/idea/src/main/java/org/gradle/sample/Main.java b/subprojects/docs/src/samples/toolingApi/idea/src/main/java/org/gradle/sample/Main.java
index f78bce2..65915b0 100644
--- a/subprojects/docs/src/samples/toolingApi/idea/src/main/java/org/gradle/sample/Main.java
+++ b/subprojects/docs/src/samples/toolingApi/idea/src/main/java/org/gradle/sample/Main.java
@@ -10,7 +10,6 @@ public class Main {
public static void main(String[] args) {
// Configure the connector and create the connection
GradleConnector connector = GradleConnector.newConnector();
- connector.forProjectDirectory(new File("."));
if (args.length > 0) {
connector.useInstallation(new File(args[0]));
@@ -19,6 +18,8 @@ public class Main {
}
}
+ connector.forProjectDirectory(new File("."));
+
ProjectConnection connection = connector.connect();
try {
IdeaProject project = connection.getModel(IdeaProject.class);
diff --git a/subprojects/docs/src/samples/toolingApi/model/src/main/java/org/gradle/sample/Main.java b/subprojects/docs/src/samples/toolingApi/model/src/main/java/org/gradle/sample/Main.java
index 4791e4f..32ad551 100644
--- a/subprojects/docs/src/samples/toolingApi/model/src/main/java/org/gradle/sample/Main.java
+++ b/subprojects/docs/src/samples/toolingApi/model/src/main/java/org/gradle/sample/Main.java
@@ -11,7 +11,6 @@ public class Main {
public static void main(String[] args) {
// Configure the connector and create the connection
GradleConnector connector = GradleConnector.newConnector();
- connector.forProjectDirectory(new File("."));
if (args.length > 0) {
connector.useInstallation(new File(args[0]));
@@ -20,9 +19,7 @@ public class Main {
}
}
- if (args.length > 0) {
- connector.useInstallation(new File(args[0]));
- }
+ connector.forProjectDirectory(new File("."));
ProjectConnection connection = connector.connect();
try {
diff --git a/subprojects/docs/src/samples/toolingApi/runBuild/src/main/java/org/gradle/sample/Main.java b/subprojects/docs/src/samples/toolingApi/runBuild/src/main/java/org/gradle/sample/Main.java
index dab318f..406c04d 100644
--- a/subprojects/docs/src/samples/toolingApi/runBuild/src/main/java/org/gradle/sample/Main.java
+++ b/subprojects/docs/src/samples/toolingApi/runBuild/src/main/java/org/gradle/sample/Main.java
@@ -20,9 +20,6 @@ public class Main {
}
connector.forProjectDirectory(new File("."));
- if (args.length > 0) {
- connector.useInstallation(new File(args[0]));
- }
ProjectConnection connection = connector.connect();
try {
diff --git a/subprojects/docs/src/samples/userguide/artifacts/componentMetadata/build.gradle b/subprojects/docs/src/samples/userguide/artifacts/componentMetadata/build.gradle
new file mode 100644
index 0000000..adb0830
--- /dev/null
+++ b/subprojects/docs/src/samples/userguide/artifacts/componentMetadata/build.gradle
@@ -0,0 +1,41 @@
+repositories {
+ ivy {
+ url "$projectDir/repo"
+ }
+
+ configurations {
+ config1
+ config2
+ config3
+ }
+
+ // START SNIPPET latest-selector
+ dependencies {
+ config1 "sea.fish:tuna:latest.integration"
+ config2 "sea.fish:tuna:latest.release"
+ }
+ // END SNIPPET latest-selector
+
+ // START SNIPPET custom-status-scheme
+ dependencies {
+ config3 "air.birds:albatros:latest.silver"
+ components {
+ eachComponent { ComponentMetadataDetails details ->
+ if (details.id.group == "air.birds") {
+ details.statusScheme = ["bronze", "silver", "gold", "platinum"]
+ }
+ }
+ }
+ }
+ // END SNIPPET custom-status-scheme
+
+ task listFish << {
+ configurations.config1.each { println it.name }
+ println()
+ configurations.config2.each { println it.name}
+ }
+
+ task listBirds << {
+ configurations.config3.each { println it.name }
+ }
+}
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/userguide/artifacts/componentMetadata/repo/air.birds/albatros/1.9/ivy-1.9.xml b/subprojects/docs/src/samples/userguide/artifacts/componentMetadata/repo/air.birds/albatros/1.9/ivy-1.9.xml
new file mode 100644
index 0000000..5899994
--- /dev/null
+++ b/subprojects/docs/src/samples/userguide/artifacts/componentMetadata/repo/air.birds/albatros/1.9/ivy-1.9.xml
@@ -0,0 +1,9 @@
+<ivy-module version="2.0">
+ <info organisation="air.birds"
+ module="albatros"
+ revision="1.9"
+ status="silver"/>
+ <publications>
+ <artifact />
+ </publications>
+</ivy-module>
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/userguide/artifacts/componentMetadata/repo/air.birds/albatros/2.0/ivy-2.0.xml b/subprojects/docs/src/samples/userguide/artifacts/componentMetadata/repo/air.birds/albatros/2.0/ivy-2.0.xml
new file mode 100644
index 0000000..d8accfe
--- /dev/null
+++ b/subprojects/docs/src/samples/userguide/artifacts/componentMetadata/repo/air.birds/albatros/2.0/ivy-2.0.xml
@@ -0,0 +1,9 @@
+<ivy-module version="2.0">
+ <info organisation="air.birds"
+ module="albatros"
+ revision="2.0"
+ status="gold"/>
+ <publications>
+ <artifact />
+ </publications>
+</ivy-module>
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/userguide/artifacts/componentMetadata/repo/sea.fish/tuna/1.3/ivy-1.3.xml b/subprojects/docs/src/samples/userguide/artifacts/componentMetadata/repo/sea.fish/tuna/1.3/ivy-1.3.xml
new file mode 100644
index 0000000..fc54db0
--- /dev/null
+++ b/subprojects/docs/src/samples/userguide/artifacts/componentMetadata/repo/sea.fish/tuna/1.3/ivy-1.3.xml
@@ -0,0 +1,9 @@
+<ivy-module version="2.0">
+ <info organisation="sea.fish"
+ module="tuna"
+ revision="1.3"
+ status="milestone" />
+ <publications>
+ <artifact />
+ </publications>
+</ivy-module>
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/userguide/artifacts/componentMetadata/repo/sea.fish/tuna/1.4/ivy-1.4.xml b/subprojects/docs/src/samples/userguide/artifacts/componentMetadata/repo/sea.fish/tuna/1.4/ivy-1.4.xml
new file mode 100644
index 0000000..3c13bbe
--- /dev/null
+++ b/subprojects/docs/src/samples/userguide/artifacts/componentMetadata/repo/sea.fish/tuna/1.4/ivy-1.4.xml
@@ -0,0 +1,9 @@
+<ivy-module version="2.0">
+ <info organisation="sea.fish"
+ module="tuna"
+ revision="1.4"
+ status="release" />
+ <publications>
+ <artifact />
+ </publications>
+</ivy-module>
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/userguide/artifacts/componentMetadata/repo/sea.fish/tuna/1.5/ivy-1.5.xml b/subprojects/docs/src/samples/userguide/artifacts/componentMetadata/repo/sea.fish/tuna/1.5/ivy-1.5.xml
new file mode 100644
index 0000000..fa235ac
--- /dev/null
+++ b/subprojects/docs/src/samples/userguide/artifacts/componentMetadata/repo/sea.fish/tuna/1.5/ivy-1.5.xml
@@ -0,0 +1,9 @@
+<ivy-module version="2.0">
+ <info organisation="sea.fish"
+ module="tuna"
+ revision="1.5"
+ status="integration" />
+ <publications>
+ <artifact />
+ </publications>
+</ivy-module>
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/userguide/artifacts/defineRepository/build.gradle b/subprojects/docs/src/samples/userguide/artifacts/defineRepository/build.gradle
index a52abdc..0fdcd60 100644
--- a/subprojects/docs/src/samples/userguide/artifacts/defineRepository/build.gradle
+++ b/subprojects/docs/src/samples/userguide/artifacts/defineRepository/build.gradle
@@ -6,6 +6,12 @@ repositories {
}
//END SNIPPET maven-central
+//START SNIPPET maven-jcenter
+repositories {
+ jcenter()
+}
+//END SNIPPET maven-jcenter
+
//START SNIPPET maven-central-jar-repo
repositories {
mavenCentral name: 'single-jar-repo', artifactUrls: ["http://repo.mycompany.com/jars"]
diff --git a/subprojects/docs/src/samples/userguide/artifacts/uploading/build.gradle b/subprojects/docs/src/samples/userguide/artifacts/uploading/build.gradle
index 55b4b94..2d4129e 100644
--- a/subprojects/docs/src/samples/userguide/artifacts/uploading/build.gradle
+++ b/subprojects/docs/src/samples/userguide/artifacts/uploading/build.gradle
@@ -16,7 +16,7 @@ artifacts {
}
//END SNIPPET file-artifact
-//START SNIPPET customised-file-artifact
+//START SNIPPET customized-file-artifact
task myTask(type: MyTaskType) {
destFile = file('build/somefile.txt')
}
@@ -28,7 +28,7 @@ artifacts {
builtBy myTask
}
}
-//END SNIPPET customised-file-artifact
+//END SNIPPET customized-file-artifact
//START SNIPPET map-file-artifact
task generate(type: MyTaskType) {
diff --git a/subprojects/docs/src/samples/userguide/distribution/build.gradle b/subprojects/docs/src/samples/userguide/distribution/build.gradle
index 18ab403..e5f30ee 100755
--- a/subprojects/docs/src/samples/userguide/distribution/build.gradle
+++ b/subprojects/docs/src/samples/userguide/distribution/build.gradle
@@ -4,48 +4,24 @@ apply plugin: 'distribution'
version = '1.0.0'
-// START SNIPPET name-conf
-distributions {
- main {
- baseName = 'my-name'
- }
-}
-// END SNIPPET name-conf
-
-// START SNIPPET custom-distZip
-apply plugin: 'distribution'
-
-distributions {
- custom
-}
-
-customDistZip {
- from "custom/custom.txt"
-}
-// END SNIPPET custom-distZip
-
-// START SNIPPET custom-distribution
+// START SNIPPET configure-distribution
apply plugin: 'distribution'
distributions {
main {
baseName = 'someName'
contents {
- from { 'src/dist' }
+ from { 'src/readme' }
}
}
}
-// END SNIPPET custom-distribution
+// END SNIPPET configure-distribution
-// START SNIPPET declare-distribution
+// START SNIPPET custom-distribution
apply plugin: 'distribution'
version = '1.2'
distributions {
- custom {
- contents {
- from { 'src/dist' }
- }
- }
+ custom {}
}
-// END SNIPPET declare-distribution
+// END SNIPPET custom-distribution
diff --git a/subprojects/docs/src/samples/userguide/files/copy/build.gradle b/subprojects/docs/src/samples/userguide/files/copy/build.gradle
index 22078a3..c1fb029 100644
--- a/subprojects/docs/src/samples/userguide/files/copy/build.gradle
+++ b/subprojects/docs/src/samples/userguide/files/copy/build.gradle
@@ -47,6 +47,20 @@ task copyMethod << {
}
// END SNIPPET copy-method
+// START SNIPPET copy-method-with-dependency
+task copyMethodWithExplicitDependencies{
+ inputs.file copyTask // up-to-date check for inputs, plus add copyTask as dependency
+ outputs.dir 'some-dir' // up-to-date check for outputs
+ doLast{
+ copy {
+ // Copy the output of copyTask
+ from copyTask
+ into 'some-dir'
+ }
+ }
+}
+// END SNIPPET copy-method-with-dependency
+
configurations { runtime }
// START SNIPPET nested-specs
@@ -99,4 +113,5 @@ task filter(type: Copy) {
task test {
dependsOn tasks.withType(Copy)
dependsOn copyMethod
+ dependsOn copyMethodWithExplicitDependencies
}
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/userguide/groovy/groovyDependency/build.gradle b/subprojects/docs/src/samples/userguide/groovy/groovyDependency/build.gradle
index ab87fe3..a4418d5 100644
--- a/subprojects/docs/src/samples/userguide/groovy/groovyDependency/build.gradle
+++ b/subprojects/docs/src/samples/userguide/groovy/groovyDependency/build.gradle
@@ -10,12 +10,6 @@ dependencies {
}
// END SNIPPET groovy-test-dependency
-// START SNIPPET groovy-configuration
-dependencies {
- groovy "org.codehaus.groovy:groovy-all:2.0.5"
-}
-// END SNIPPET groovy-configuration
-
// START SNIPPET bundled-groovy-dependency
dependencies {
compile localGroovy()
diff --git a/subprojects/docs/src/samples/userguide/initScripts/plugins/build.gradle b/subprojects/docs/src/samples/userguide/initScripts/plugins/build.gradle
new file mode 100644
index 0000000..e4fa489
--- /dev/null
+++ b/subprojects/docs/src/samples/userguide/initScripts/plugins/build.gradle
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+// START SNIPPET show-repos-task
+repositories{
+ mavenCentral()
+}
+
+ task showRepositories << {
+ repositories.each{
+ println "repository: ${it.name} ('${it.url}')"
+ }
+}
+// END SNIPPET show-repos-task
diff --git a/subprojects/docs/src/samples/userguide/initScripts/plugins/init.gradle b/subprojects/docs/src/samples/userguide/initScripts/plugins/init.gradle
new file mode 100644
index 0000000..b9f8f68
--- /dev/null
+++ b/subprojects/docs/src/samples/userguide/initScripts/plugins/init.gradle
@@ -0,0 +1,34 @@
+import org.gradle.api.artifacts.repositories.ArtifactRepository
+import org.gradle.api.artifacts.repositories.MavenArtifactRepository
+
+// START SNIPPET init-script-plugin
+
+apply plugin:EnterpriseRepositoryPlugin
+
+class EnterpriseRepositoryPlugin implements Plugin<Gradle> {
+
+ private static String ENTERPRISE_REPOSITORY_URL = "http://repo.gradle.org/gradle/repo"
+
+ void apply(Gradle gradle) {
+ // ONLY USE ENTERPRISE REPO FOR DEPENDENCIES
+ gradle.allprojects{ project ->
+ project.repositories {
+
+ //remove all repositories not pointing to the enterprise repository url
+ all { ArtifactRepository repo ->
+ if (!(repo instanceof MavenArtifactRepository) || repo.url.toString() != ENTERPRISE_REPOSITORY_URL) {
+ project.logger.lifecycle "Repository ${repo.url} removed. Only $ENTERPRISE_REPOSITORY_URL is allowed"
+ remove repo
+ }
+ }
+
+ // add the enterprise repository
+ maven {
+ name "STANDARD_ENTERPRISE_REPO"
+ url ENTERPRISE_REPOSITORY_URL
+ }
+ }
+ }
+ }
+}
+// END SNIPPET init-script-plugin
diff --git a/subprojects/docs/src/samples/userguide/multiproject/dependencies/firstMessages/messages/build.gradle b/subprojects/docs/src/samples/userguide/multiproject/dependencies/firstMessages/messages/build.gradle
new file mode 100644
index 0000000..36e2695
--- /dev/null
+++ b/subprojects/docs/src/samples/userguide/multiproject/dependencies/firstMessages/messages/build.gradle
@@ -0,0 +1 @@
+ext.producerMessage = null
diff --git a/subprojects/docs/src/samples/userguide/multiproject/dependencies/firstMessages/messages/consumer/build.gradle b/subprojects/docs/src/samples/userguide/multiproject/dependencies/firstMessages/messages/consumer/build.gradle
index b552cba..a7e89a7 100644
--- a/subprojects/docs/src/samples/userguide/multiproject/dependencies/firstMessages/messages/consumer/build.gradle
+++ b/subprojects/docs/src/samples/userguide/multiproject/dependencies/firstMessages/messages/consumer/build.gradle
@@ -1,4 +1,3 @@
task action << {
- println("Consuming message: " +
- (rootProject.hasProperty('producerMessage') ? rootProject.producerMessage : 'null'))
+ println("Consuming message: ${rootProject.producerMessage}")
}
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/userguide/multiproject/dependencies/messagesConfigDependencies/messages/build.gradle b/subprojects/docs/src/samples/userguide/multiproject/dependencies/messagesConfigDependencies/messages/build.gradle
new file mode 100644
index 0000000..36e2695
--- /dev/null
+++ b/subprojects/docs/src/samples/userguide/multiproject/dependencies/messagesConfigDependencies/messages/build.gradle
@@ -0,0 +1 @@
+ext.producerMessage = null
diff --git a/subprojects/docs/src/samples/userguide/multiproject/dependencies/messagesConfigDependencies/messages/consumer/build.gradle b/subprojects/docs/src/samples/userguide/multiproject/dependencies/messagesConfigDependencies/messages/consumer/build.gradle
index 9ca9261..8cf6c17 100644
--- a/subprojects/docs/src/samples/userguide/multiproject/dependencies/messagesConfigDependencies/messages/consumer/build.gradle
+++ b/subprojects/docs/src/samples/userguide/multiproject/dependencies/messagesConfigDependencies/messages/consumer/build.gradle
@@ -1,6 +1,6 @@
evaluationDependsOn(':producer')
-message = rootProject.hasProperty('producerMessage') ? rootProject.producerMessage : 'null'
+message = rootProject.producerMessage
task consume << {
println("Consuming message: " + message)
diff --git a/subprojects/docs/src/samples/userguide/multiproject/dependencies/messagesConfigDependenciesAltSolution/messages/build.gradle b/subprojects/docs/src/samples/userguide/multiproject/dependencies/messagesConfigDependenciesAltSolution/messages/build.gradle
new file mode 100644
index 0000000..36e2695
--- /dev/null
+++ b/subprojects/docs/src/samples/userguide/multiproject/dependencies/messagesConfigDependenciesAltSolution/messages/build.gradle
@@ -0,0 +1 @@
+ext.producerMessage = null
diff --git a/subprojects/docs/src/samples/userguide/multiproject/dependencies/messagesConfigDependenciesAltSolution/messages/consumer/build.gradle b/subprojects/docs/src/samples/userguide/multiproject/dependencies/messagesConfigDependenciesAltSolution/messages/consumer/build.gradle
index d36e857..7d89691 100644
--- a/subprojects/docs/src/samples/userguide/multiproject/dependencies/messagesConfigDependenciesAltSolution/messages/consumer/build.gradle
+++ b/subprojects/docs/src/samples/userguide/multiproject/dependencies/messagesConfigDependenciesAltSolution/messages/consumer/build.gradle
@@ -1,4 +1,3 @@
task consume << {
- println("Consuming message: " +
- (rootProject.hasProperty('producerMessage') ? rootProject.producerMessage : 'null'))
+ println("Consuming message: ${rootProject.producerMessage}")
}
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/userguide/multiproject/dependencies/messagesConfigDependenciesBroken/messages/build.gradle b/subprojects/docs/src/samples/userguide/multiproject/dependencies/messagesConfigDependenciesBroken/messages/build.gradle
new file mode 100644
index 0000000..36e2695
--- /dev/null
+++ b/subprojects/docs/src/samples/userguide/multiproject/dependencies/messagesConfigDependenciesBroken/messages/build.gradle
@@ -0,0 +1 @@
+ext.producerMessage = null
diff --git a/subprojects/docs/src/samples/userguide/multiproject/dependencies/messagesConfigDependenciesBroken/messages/consumer/build.gradle b/subprojects/docs/src/samples/userguide/multiproject/dependencies/messagesConfigDependenciesBroken/messages/consumer/build.gradle
index d1ba74e..c4cef37 100644
--- a/subprojects/docs/src/samples/userguide/multiproject/dependencies/messagesConfigDependenciesBroken/messages/consumer/build.gradle
+++ b/subprojects/docs/src/samples/userguide/multiproject/dependencies/messagesConfigDependenciesBroken/messages/consumer/build.gradle
@@ -1,4 +1,4 @@
-message = rootProject.hasProperty('producerMessage') ? rootProject.producerMessage : 'null'
+message = rootProject.producerMessage
task consume << {
println("Consuming message: " + message)
diff --git a/subprojects/docs/src/samples/userguide/multiproject/dependencies/messagesHack/messages/build.gradle b/subprojects/docs/src/samples/userguide/multiproject/dependencies/messagesHack/messages/build.gradle
new file mode 100644
index 0000000..36e2695
--- /dev/null
+++ b/subprojects/docs/src/samples/userguide/multiproject/dependencies/messagesHack/messages/build.gradle
@@ -0,0 +1 @@
+ext.producerMessage = null
diff --git a/subprojects/docs/src/samples/userguide/multiproject/dependencies/messagesHack/messages/consumer/build.gradle b/subprojects/docs/src/samples/userguide/multiproject/dependencies/messagesHack/messages/consumer/build.gradle
index b552cba..a7e89a7 100644
--- a/subprojects/docs/src/samples/userguide/multiproject/dependencies/messagesHack/messages/consumer/build.gradle
+++ b/subprojects/docs/src/samples/userguide/multiproject/dependencies/messagesHack/messages/consumer/build.gradle
@@ -1,4 +1,3 @@
task action << {
- println("Consuming message: " +
- (rootProject.hasProperty('producerMessage') ? rootProject.producerMessage : 'null'))
+ println("Consuming message: ${rootProject.producerMessage}")
}
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/userguide/multiproject/dependencies/messagesTaskDependencies/messages/build.gradle b/subprojects/docs/src/samples/userguide/multiproject/dependencies/messagesTaskDependencies/messages/build.gradle
new file mode 100644
index 0000000..36e2695
--- /dev/null
+++ b/subprojects/docs/src/samples/userguide/multiproject/dependencies/messagesTaskDependencies/messages/build.gradle
@@ -0,0 +1 @@
+ext.producerMessage = null
diff --git a/subprojects/docs/src/samples/userguide/multiproject/dependencies/messagesTaskDependencies/messages/consumer/build.gradle b/subprojects/docs/src/samples/userguide/multiproject/dependencies/messagesTaskDependencies/messages/consumer/build.gradle
index 8abffac..89bf7d4 100644
--- a/subprojects/docs/src/samples/userguide/multiproject/dependencies/messagesTaskDependencies/messages/consumer/build.gradle
+++ b/subprojects/docs/src/samples/userguide/multiproject/dependencies/messagesTaskDependencies/messages/consumer/build.gradle
@@ -1,4 +1,3 @@
task consume(dependsOn: ':producer:produce') << {
- println("Consuming message: " +
- (rootProject.hasProperty('producerMessage') ? rootProject.producerMessage : 'null'))
+ println("Consuming message: ${rootProject.producerMessage}")
}
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/userguide/multiproject/dependencies/messagesWithDependencies/messages/build.gradle b/subprojects/docs/src/samples/userguide/multiproject/dependencies/messagesWithDependencies/messages/build.gradle
new file mode 100644
index 0000000..36e2695
--- /dev/null
+++ b/subprojects/docs/src/samples/userguide/multiproject/dependencies/messagesWithDependencies/messages/build.gradle
@@ -0,0 +1 @@
+ext.producerMessage = null
diff --git a/subprojects/docs/src/samples/userguide/multiproject/dependencies/messagesWithDependencies/messages/consumer/build.gradle b/subprojects/docs/src/samples/userguide/multiproject/dependencies/messagesWithDependencies/messages/consumer/build.gradle
index 2e70b12..4bb5354 100644
--- a/subprojects/docs/src/samples/userguide/multiproject/dependencies/messagesWithDependencies/messages/consumer/build.gradle
+++ b/subprojects/docs/src/samples/userguide/multiproject/dependencies/messagesWithDependencies/messages/consumer/build.gradle
@@ -1,4 +1,3 @@
task action(dependsOn: ":producer:action") << {
- println("Consuming message: " +
- (rootProject.hasProperty('producerMessage') ? rootProject.producerMessage : 'null'))
+ println("Consuming message: ${rootProject.producerMessage}")
}
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/userguide/multiproject/standardLayouts/settings.gradle b/subprojects/docs/src/samples/userguide/multiproject/standardLayouts/settings.gradle
index e898abc..959a186 100644
--- a/subprojects/docs/src/samples/userguide/multiproject/standardLayouts/settings.gradle
+++ b/subprojects/docs/src/samples/userguide/multiproject/standardLayouts/settings.gradle
@@ -1,5 +1,5 @@
//START SNIPPET hierarchical-layout
-include 'project1', 'project2', 'project2:child1'
+include 'project1', 'project2:child', 'project3:child1'
//END SNIPPET hierarchical-layout
//START SNIPPET flat-layout
diff --git a/subprojects/docs/src/samples/userguide/tasks/addToTaskContainer/build.gradle b/subprojects/docs/src/samples/userguide/tasks/addToTaskContainer/build.gradle
index e8e6a5e..153c1a7 100644
--- a/subprojects/docs/src/samples/userguide/tasks/addToTaskContainer/build.gradle
+++ b/subprojects/docs/src/samples/userguide/tasks/addToTaskContainer/build.gradle
@@ -1,8 +1,8 @@
-tasks.add(name: 'hello') << {
+tasks.create(name: 'hello') << {
println "hello"
}
-tasks.add(name: 'copy', type: Copy) {
+tasks.create(name: 'copy', type: Copy) {
from(file('srcDir'))
into(buildDir)
}
diff --git a/subprojects/docs/src/samples/userguide/tasks/customTaskWithProperty/build.gradle b/subprojects/docs/src/samples/userguide/tasks/customTaskWithProperty/build.gradle
index 70ae299..b5854db 100644
--- a/subprojects/docs/src/samples/userguide/tasks/customTaskWithProperty/build.gradle
+++ b/subprojects/docs/src/samples/userguide/tasks/customTaskWithProperty/build.gradle
@@ -8,7 +8,7 @@ task greeting(type: GreetingTask) {
}
class GreetingTask extends DefaultTask {
- def String greeting = 'hello from GreetingTask'
+ String greeting = 'hello from GreetingTask'
@TaskAction
def greet() {
diff --git a/subprojects/docs/src/samples/userguide/tasks/finalizers/build.gradle b/subprojects/docs/src/samples/userguide/tasks/finalizers/build.gradle
new file mode 100644
index 0000000..d0ffc52
--- /dev/null
+++ b/subprojects/docs/src/samples/userguide/tasks/finalizers/build.gradle
@@ -0,0 +1,8 @@
+task taskX << {
+ println 'taskX'
+}
+task taskY << {
+ println 'taskY'
+}
+
+taskX.finalizedBy taskY
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/userguide/tasks/finalizersWithFailure/build.gradle b/subprojects/docs/src/samples/userguide/tasks/finalizersWithFailure/build.gradle
new file mode 100644
index 0000000..72a43f4
--- /dev/null
+++ b/subprojects/docs/src/samples/userguide/tasks/finalizersWithFailure/build.gradle
@@ -0,0 +1,9 @@
+task taskX << {
+ println 'taskX'
+ throw new RuntimeException()
+}
+task taskY << {
+ println 'taskY'
+}
+
+taskX.finalizedBy taskY
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/userguide/tasks/incrementalTask/build.gradle b/subprojects/docs/src/samples/userguide/tasks/incrementalTask/build.gradle
new file mode 100644
index 0000000..bb4b1d1
--- /dev/null
+++ b/subprojects/docs/src/samples/userguide/tasks/incrementalTask/build.gradle
@@ -0,0 +1,66 @@
+task originalInputs() << {
+ file('inputs').mkdir()
+ file('inputs/1.txt').text = "Content for file 1."
+ file('inputs/2.txt').text = "Content for file 2."
+ file('inputs/3.txt').text = "Content for file 3."
+}
+
+// START SNIPPET updated-inputs
+task updateInputs() << {
+ file('inputs/1.txt').text = "Changed content for existing file 1."
+ file('inputs/4.txt').text = "Content for new file 4."
+}
+// END SNIPPET updated-inputs
+
+// START SNIPPET removed-input
+task removeInput() << {
+ file('inputs/3.txt').delete()
+}
+// END SNIPPET removed-input
+
+// START SNIPPET removed-output
+task removeOutput() << {
+ file("$buildDir/outputs/1.txt").delete()
+}
+// END SNIPPET removed-output
+
+// START SNIPPET reverse
+task incrementalReverse(type: IncrementalReverseTask) {
+ inputDir = file('inputs')
+ outputDir = file("$buildDir/outputs")
+ inputProperty = project.properties['taskInputProperty'] ?: "original"
+}
+// END SNIPPET reverse
+
+// START SNIPPET incremental-task
+class IncrementalReverseTask extends DefaultTask {
+ @InputDirectory
+ def File inputDir
+
+ @OutputDirectory
+ def File outputDir
+
+ @Input
+ def inputProperty
+
+ @TaskAction
+ void execute(IncrementalTaskInputs inputs) {
+ println inputs.incremental ? "CHANGED inputs considered out of date" : "ALL inputs considered out of date"
+ // START SNIPPET out-of-date-inputs
+ inputs.outOfDate { change ->
+ println "out of date: ${change.file.name}"
+ def targetFile = new File(outputDir, change.file.name)
+ targetFile.text = change.file.text.reverse()
+ }
+ // END SNIPPET out-of-date-inputs
+
+ // START SNIPPET removed-inputs
+ inputs.removed { change ->
+ println "removed: ${change.file.name}"
+ def targetFile = new File(outputDir, change.file.name)
+ targetFile.delete()
+ }
+ // END SNIPPET removed-inputs
+ }
+}
+// END SNIPPET incremental-task
diff --git a/subprojects/docs/src/samples/userguide/tasks/mustRunAfter/build.gradle b/subprojects/docs/src/samples/userguide/tasks/mustRunAfter/build.gradle
new file mode 100644
index 0000000..744b150
--- /dev/null
+++ b/subprojects/docs/src/samples/userguide/tasks/mustRunAfter/build.gradle
@@ -0,0 +1,7 @@
+task taskX << {
+ println 'taskX'
+}
+task taskY << {
+ println 'taskY'
+}
+taskY.mustRunAfter taskX
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/userguide/tutorial/groovyWithFlatDir/build.gradle b/subprojects/docs/src/samples/userguide/tutorial/groovyWithFlatDir/build.gradle
index 63fccdf..b169b45 100644
--- a/subprojects/docs/src/samples/userguide/tutorial/groovyWithFlatDir/build.gradle
+++ b/subprojects/docs/src/samples/userguide/tutorial/groovyWithFlatDir/build.gradle
@@ -1,17 +1,21 @@
apply plugin: 'groovy'
+repositories {
+ mavenCentral()
+}
+
// START SNIPPET groovy-dependency
repositories {
flatDir { dirs 'lib' }
}
dependencies {
- groovy module(':groovy:1.6.0') {
+ compile module('org.codehaus.groovy:groovy:1.6.0') {
dependency('asm:asm-all:2.2.3')
dependency('antlr:antlr:2.7.7')
dependency('commons-cli:commons-cli:1.2')
- module(':ant:1.7.0') {
- dependencies(':ant-junit:1.7.0:jar', ':ant-launcher:1.7.0')
+ module('org.apache.ant:ant:1.7.0') {
+ dependencies('org.apache.ant:ant-junit:1.7.0 at jar', 'org.apache.ant:ant-launcher:1.7.0')
}
}
}
diff --git a/subprojects/docs/src/samples/userguide/wrapper/customized/build.gradle b/subprojects/docs/src/samples/userguide/wrapper/customized/build.gradle
deleted file mode 100644
index eed403b..0000000
--- a/subprojects/docs/src/samples/userguide/wrapper/customized/build.gradle
+++ /dev/null
@@ -1,4 +0,0 @@
-task wrapper(type: Wrapper) {
- gradleVersion = '0.9'
- jarFile = 'wrapper/wrapper.jar'
-}
diff --git a/subprojects/docs/src/samples/userguide/wrapper/simple/build.gradle b/subprojects/docs/src/samples/userguide/wrapper/simple/build.gradle
index ad082e6..e9e26b3 100644
--- a/subprojects/docs/src/samples/userguide/wrapper/simple/build.gradle
+++ b/subprojects/docs/src/samples/userguide/wrapper/simple/build.gradle
@@ -1,3 +1,3 @@
task wrapper(type: Wrapper) {
- gradleVersion = '0.9'
+ gradleVersion = '1.4'
}
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/userguideOutput/configurationHandlingAllFiles.out b/subprojects/docs/src/samples/userguideOutput/configurationHandlingAllFiles.out
index 45cee23..520ccb1 100644
--- a/subprojects/docs/src/samples/userguideOutput/configurationHandlingAllFiles.out
+++ b/subprojects/docs/src/samples/userguideOutput/configurationHandlingAllFiles.out
@@ -1,5 +1,5 @@
orca-1.0.jar
shark-1.0.jar
tuna-1.0.jar
-seal-2.0.jar
-herring-1.0.jar
\ No newline at end of file
+herring-1.0.jar
+seal-2.0.jar
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/userguideOutput/customStatusScheme.out b/subprojects/docs/src/samples/userguideOutput/customStatusScheme.out
new file mode 100644
index 0000000..79e65a6
--- /dev/null
+++ b/subprojects/docs/src/samples/userguideOutput/customStatusScheme.out
@@ -0,0 +1 @@
+albatros-2.0.jar
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/userguideOutput/externalDependencies.out b/subprojects/docs/src/samples/userguideOutput/externalDependencies.out
index 65061e7..bd07146 100644
--- a/subprojects/docs/src/samples/userguideOutput/externalDependencies.out
+++ b/subprojects/docs/src/samples/userguideOutput/externalDependencies.out
@@ -2,7 +2,7 @@ hibernate-core-3.6.7.Final.jar
antlr-2.7.6.jar
commons-collections-3.1.jar
dom4j-1.6.1.jar
-slf4j-api-1.6.1.jar
hibernate-commons-annotations-3.2.0.Final.jar
hibernate-jpa-2.0-api-1.0.1.Final.jar
-jta-1.1.jar
\ No newline at end of file
+jta-1.1.jar
+slf4j-api-1.6.1.jar
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/userguideOutput/incrementalTaskChangedProperty.out b/subprojects/docs/src/samples/userguideOutput/incrementalTaskChangedProperty.out
new file mode 100644
index 0000000..9e20258
--- /dev/null
+++ b/subprojects/docs/src/samples/userguideOutput/incrementalTaskChangedProperty.out
@@ -0,0 +1,4 @@
+ALL inputs considered out of date
+out of date: 1.txt
+out of date: 2.txt
+out of date: 3.txt
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/userguideOutput/incrementalTaskFirstRun.out b/subprojects/docs/src/samples/userguideOutput/incrementalTaskFirstRun.out
new file mode 100644
index 0000000..9e20258
--- /dev/null
+++ b/subprojects/docs/src/samples/userguideOutput/incrementalTaskFirstRun.out
@@ -0,0 +1,4 @@
+ALL inputs considered out of date
+out of date: 1.txt
+out of date: 2.txt
+out of date: 3.txt
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/webApplication/customised/src/additionalWebInf/additional.xml b/subprojects/docs/src/samples/userguideOutput/incrementalTaskNoChange.out
similarity index 100%
copy from subprojects/docs/src/samples/webApplication/customised/src/additionalWebInf/additional.xml
copy to subprojects/docs/src/samples/userguideOutput/incrementalTaskNoChange.out
diff --git a/subprojects/docs/src/samples/userguideOutput/incrementalTaskRemovedInput.out b/subprojects/docs/src/samples/userguideOutput/incrementalTaskRemovedInput.out
new file mode 100644
index 0000000..73aaed0
--- /dev/null
+++ b/subprojects/docs/src/samples/userguideOutput/incrementalTaskRemovedInput.out
@@ -0,0 +1,2 @@
+CHANGED inputs considered out of date
+removed: 3.txt
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/userguideOutput/incrementalTaskRemovedOutput.out b/subprojects/docs/src/samples/userguideOutput/incrementalTaskRemovedOutput.out
new file mode 100644
index 0000000..9e20258
--- /dev/null
+++ b/subprojects/docs/src/samples/userguideOutput/incrementalTaskRemovedOutput.out
@@ -0,0 +1,4 @@
+ALL inputs considered out of date
+out of date: 1.txt
+out of date: 2.txt
+out of date: 3.txt
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/userguideOutput/incrementalTaskUpdatedInputs.out b/subprojects/docs/src/samples/userguideOutput/incrementalTaskUpdatedInputs.out
new file mode 100644
index 0000000..ad2dc90
--- /dev/null
+++ b/subprojects/docs/src/samples/userguideOutput/incrementalTaskUpdatedInputs.out
@@ -0,0 +1,3 @@
+CHANGED inputs considered out of date
+out of date: 1.txt
+out of date: 4.txt
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/userguideOutput/latestSelector.out b/subprojects/docs/src/samples/userguideOutput/latestSelector.out
new file mode 100644
index 0000000..979e2ef
--- /dev/null
+++ b/subprojects/docs/src/samples/userguideOutput/latestSelector.out
@@ -0,0 +1,3 @@
+tuna-1.5.jar
+
+tuna-1.4.jar
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/userguideOutput/mustRunAfter.out b/subprojects/docs/src/samples/userguideOutput/mustRunAfter.out
new file mode 100644
index 0000000..6c41820
--- /dev/null
+++ b/subprojects/docs/src/samples/userguideOutput/mustRunAfter.out
@@ -0,0 +1,2 @@
+taskX
+taskY
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/userguideOutput/mustRunAfterSingleTask.out b/subprojects/docs/src/samples/userguideOutput/mustRunAfterSingleTask.out
new file mode 100644
index 0000000..0c11d0d
--- /dev/null
+++ b/subprojects/docs/src/samples/userguideOutput/mustRunAfterSingleTask.out
@@ -0,0 +1 @@
+taskY
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/userguideOutput/publishingIvyGenerateDescriptor.out b/subprojects/docs/src/samples/userguideOutput/publishingIvyGenerateDescriptor.out
index a7c07c3..10031f7 100644
--- a/subprojects/docs/src/samples/userguideOutput/publishingIvyGenerateDescriptor.out
+++ b/subprojects/docs/src/samples/userguideOutput/publishingIvyGenerateDescriptor.out
@@ -1,4 +1,4 @@
-:generateIvyCustomIvyModuleDescriptor
+:generateDescriptorFileForIvyCustomPublication
BUILD SUCCESSFUL
diff --git a/subprojects/docs/src/samples/userguideOutput/publishingIvyPublishLifecycle.out b/subprojects/docs/src/samples/userguideOutput/publishingIvyPublishLifecycle.out
index 9bd41b5..c9ae2f4 100644
--- a/subprojects/docs/src/samples/userguideOutput/publishingIvyPublishLifecycle.out
+++ b/subprojects/docs/src/samples/userguideOutput/publishingIvyPublishLifecycle.out
@@ -1,4 +1,4 @@
-:generateIvyJavaIvyModuleDescriptor
+:generateDescriptorFileForIvyJavaPublication
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
diff --git a/subprojects/docs/src/samples/userguideOutput/publishingIvyPublishSingle.out b/subprojects/docs/src/samples/userguideOutput/publishingIvyPublishSingle.out
index 74218e8..b48f4fe 100644
--- a/subprojects/docs/src/samples/userguideOutput/publishingIvyPublishSingle.out
+++ b/subprojects/docs/src/samples/userguideOutput/publishingIvyPublishSingle.out
@@ -1,4 +1,4 @@
-:generateIvyJavaIvyModuleDescriptor
+:generateDescriptorFileForIvyJavaPublication
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
diff --git a/subprojects/docs/src/samples/userguideOutput/taskFinalizers.out b/subprojects/docs/src/samples/userguideOutput/taskFinalizers.out
new file mode 100644
index 0000000..6c41820
--- /dev/null
+++ b/subprojects/docs/src/samples/userguideOutput/taskFinalizers.out
@@ -0,0 +1,2 @@
+taskX
+taskY
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/userguideOutput/taskFinalizersWithFailure.out b/subprojects/docs/src/samples/userguideOutput/taskFinalizersWithFailure.out
new file mode 100644
index 0000000..6c41820
--- /dev/null
+++ b/subprojects/docs/src/samples/userguideOutput/taskFinalizersWithFailure.out
@@ -0,0 +1,2 @@
+taskX
+taskY
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/userguideOutput/taskListAllReport.out b/subprojects/docs/src/samples/userguideOutput/taskListAllReport.out
index 9b537c0..54a78b8 100644
--- a/subprojects/docs/src/samples/userguideOutput/taskListAllReport.out
+++ b/subprojects/docs/src/samples/userguideOutput/taskListAllReport.out
@@ -17,6 +17,11 @@ api:libs - Builds the JAR
webapp:libs - Builds the JAR [api:libs]
webapp:compile - Compiles the source files
+Build Setup tasks
+-----------------
+setupBuild - Initializes a new Gradle build. [incubating]
+wrapper - Generates Gradle wrapper files. [incubating]
+
Help tasks
----------
dependencies - Displays all dependencies declared in root project 'projectReports'.
diff --git a/subprojects/docs/src/samples/userguideOutput/taskListReport.out b/subprojects/docs/src/samples/userguideOutput/taskListReport.out
index 16ff74c..82fadb4 100644
--- a/subprojects/docs/src/samples/userguideOutput/taskListReport.out
+++ b/subprojects/docs/src/samples/userguideOutput/taskListReport.out
@@ -11,6 +11,11 @@ clean - Deletes the build directory (build)
dists - Builds the distribution
libs - Builds the JAR
+Build Setup tasks
+-----------------
+setupBuild - Initializes a new Gradle build. [incubating]
+wrapper - Generates Gradle wrapper files. [incubating]
+
Help tasks
----------
dependencies - Displays all dependencies declared in root project 'projectReports'.
diff --git a/subprojects/docs/src/samples/userguideOutput/usePluginsInInitScripts.out b/subprojects/docs/src/samples/userguideOutput/usePluginsInInitScripts.out
new file mode 100644
index 0000000..f58eafb
--- /dev/null
+++ b/subprojects/docs/src/samples/userguideOutput/usePluginsInInitScripts.out
@@ -0,0 +1 @@
+repository: STANDARD_ENTERPRISE_REPO ('http://repo.gradle.org/gradle/repo')
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/webApplication/customised/readme.xml b/subprojects/docs/src/samples/webApplication/customised/readme.xml
deleted file mode 100755
index ad69e48..0000000
--- a/subprojects/docs/src/samples/webApplication/customised/readme.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-<sample>
- <para>Web application with customized WAR contents.</para>
-</sample>
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/webApplication/customised/build.gradle b/subprojects/docs/src/samples/webApplication/customized/build.gradle
similarity index 100%
rename from subprojects/docs/src/samples/webApplication/customised/build.gradle
rename to subprojects/docs/src/samples/webApplication/customized/build.gradle
diff --git a/subprojects/docs/src/samples/webApplication/customized/readme.xml b/subprojects/docs/src/samples/webApplication/customized/readme.xml
new file mode 100755
index 0000000..bd523a5
--- /dev/null
+++ b/subprojects/docs/src/samples/webApplication/customized/readme.xml
@@ -0,0 +1,3 @@
+<sample>
+ <para>Web application with customized WAR contents.</para>
+</sample>
\ No newline at end of file
diff --git a/subprojects/docs/src/samples/webApplication/customised/src/additionalWebInf/additional.xml b/subprojects/docs/src/samples/webApplication/customized/src/additionalWebInf/additional.xml
similarity index 100%
rename from subprojects/docs/src/samples/webApplication/customised/src/additionalWebInf/additional.xml
rename to subprojects/docs/src/samples/webApplication/customized/src/additionalWebInf/additional.xml
diff --git a/subprojects/docs/src/samples/webApplication/customised/src/main/java/org/gradle/HelloServlet.java b/subprojects/docs/src/samples/webApplication/customized/src/main/java/org/gradle/HelloServlet.java
similarity index 100%
rename from subprojects/docs/src/samples/webApplication/customised/src/main/java/org/gradle/HelloServlet.java
rename to subprojects/docs/src/samples/webApplication/customized/src/main/java/org/gradle/HelloServlet.java
diff --git a/subprojects/docs/src/samples/webApplication/customised/src/main/java/org/gradle/MyClass.java b/subprojects/docs/src/samples/webApplication/customized/src/main/java/org/gradle/MyClass.java
similarity index 100%
rename from subprojects/docs/src/samples/webApplication/customised/src/main/java/org/gradle/MyClass.java
rename to subprojects/docs/src/samples/webApplication/customized/src/main/java/org/gradle/MyClass.java
diff --git a/subprojects/docs/src/samples/webApplication/customised/src/main/webapp/WEB-INF/webapp.xml b/subprojects/docs/src/samples/webApplication/customized/src/main/webapp/WEB-INF/webapp.xml
similarity index 100%
rename from subprojects/docs/src/samples/webApplication/customised/src/main/webapp/WEB-INF/webapp.xml
rename to subprojects/docs/src/samples/webApplication/customized/src/main/webapp/WEB-INF/webapp.xml
diff --git a/subprojects/docs/src/samples/webApplication/customised/src/main/webapp/webapp.html b/subprojects/docs/src/samples/webApplication/customized/src/main/webapp/webapp.html
similarity index 100%
rename from subprojects/docs/src/samples/webApplication/customised/src/main/webapp/webapp.html
rename to subprojects/docs/src/samples/webApplication/customized/src/main/webapp/webapp.html
diff --git a/subprojects/docs/src/samples/webApplication/customised/src/rootContent/root.txt b/subprojects/docs/src/samples/webApplication/customized/src/rootContent/root.txt
similarity index 100%
rename from subprojects/docs/src/samples/webApplication/customised/src/rootContent/root.txt
rename to subprojects/docs/src/samples/webApplication/customized/src/rootContent/root.txt
diff --git a/subprojects/docs/src/samples/webApplication/customised/src/someWeb.xml b/subprojects/docs/src/samples/webApplication/customized/src/someWeb.xml
similarity index 100%
rename from subprojects/docs/src/samples/webApplication/customised/src/someWeb.xml
rename to subprojects/docs/src/samples/webApplication/customized/src/someWeb.xml
diff --git a/subprojects/docs/src/samples/webApplication/customised/src/test/java/org/gradle/MyClassTest.java b/subprojects/docs/src/samples/webApplication/customized/src/test/java/org/gradle/MyClassTest.java
similarity index 100%
rename from subprojects/docs/src/samples/webApplication/customised/src/test/java/org/gradle/MyClassTest.java
rename to subprojects/docs/src/samples/webApplication/customized/src/test/java/org/gradle/MyClassTest.java
diff --git a/subprojects/docs/src/test/groovy/org/gradle/docs/releasenotes/FunctionalReleaseNotesTest.groovy b/subprojects/docs/src/test/groovy/org/gradle/docs/releasenotes/FunctionalReleaseNotesTest.groovy
index eae6162..c7608c9 100644
--- a/subprojects/docs/src/test/groovy/org/gradle/docs/releasenotes/FunctionalReleaseNotesTest.groovy
+++ b/subprojects/docs/src/test/groovy/org/gradle/docs/releasenotes/FunctionalReleaseNotesTest.groovy
@@ -31,10 +31,10 @@ import spock.lang.Shared
@IgnoreIf({ !canReachServices() })
class FunctionalReleaseNotesTest extends GebReportingSpec {
- static private final String FIXED_ISSUES_URL = "http://services.gradle.org/fixed-issues/${GradleVersion.current().versionBase}"
- static private final String KNOWN_ISSUES_URL = "http://services.gradle.org/known-issues/${GradleVersion.current().versionBase}"
+ static private final String FIXED_ISSUES_URL = "http://services.gradle.org/fixed-issues/${GradleVersion.current().baseVersion.version}"
+ static private final String KNOWN_ISSUES_URL = "http://services.gradle.org/known-issues/${GradleVersion.current().baseVersion.version}"
- private String version = GradleVersion.current().versionBase
+ private String version = GradleVersion.current().baseVersion.version
static boolean canReachServices() {
try {
diff --git a/subprojects/docs/src/transforms/release-notes.gradle b/subprojects/docs/src/transforms/release-notes.gradle
index 3a23dda..ddeb589 100644
--- a/subprojects/docs/src/transforms/release-notes.gradle
+++ b/subprojects/docs/src/transforms/release-notes.gradle
@@ -10,16 +10,16 @@ buildscript {
}
import org.jsoup.nodes.Element
+import org.jsoup.nodes.TextNode
import org.jsoup.select.Elements
import com.uwyn.jhighlight.renderer.XhtmlRendererFactory
-ext {
- baseStyleFile = project.file("$project.cssFiles.dir/base.css")
- releaseNotesStyleFile = project.file("$project.cssFiles.dir/release-notes.css")
- scriptFile = project.file("src/docs/release/content/script.js")
-}
+def baseStyleFile = project.file("$project.cssFiles.dir/base.css")
+def releaseNotesStyleFile = project.file("$project.cssFiles.dir/release-notes.css")
+def scriptFile = project.file("src/docs/release/content/script.js")
+def incubatingMarker = " (i)"
-inputs.files([project.cssFiles, baseStyleFile, releaseNotesStyleFile, project.configurations.jquery, scriptFile])
+inputs.files([project.cssFiles, baseStyleFile, releaseNotesStyleFile, project.configurations.jquery, project.configurations.jqueryTipTip, scriptFile])
transformDocument {
outputSettings().indentAmount(2).prettyPrint(true)
@@ -32,8 +32,9 @@ transformDocument {
head().append("<style>p{}</style>").children().last().childNode(0).attr("data", baseStyleFile.text + releaseNotesStyleFile.text)
- head().append("<script type='text/javascript'>1;</script>").children().last().childNode(0).attr("data", project.configurations.jquery.singleFile.text)
- head().append("<script type='text/javascript'>1;</script>").children().last().childNode(0).attr("data", scriptFile.text)
+ [project.configurations.jquery.singleFile, project.configurations.jqueryTipTip.singleFile, scriptFile].each {
+ head().append("<script type='text/javascript'>1;</script>").children().last().childNode(0).attr("data", it.text)
+ }
}
// wrap each h2 section in section.topic
@@ -62,12 +63,13 @@ transformDocument {
}
}
+// replace the incubating marker in h3 with class
transformDocument {
- def incubatingMarker = " (i)"
for (heading in body().select(".topic").select("h3")) {
- if (heading.text().endsWith(incubatingMarker)) {
- heading.text(heading.text() - incubatingMarker).addClass("incubating")
- heading.after("<a class='incubating-marker' href='userguide/feature_lifecycle.html' title='“incubating” features are not yet guaranteed to be backwards compatible<br />(click for more information)'>incubating feature</a>")
+ def textNode = heading.childNodes().last()
+ if (textNode instanceof TextNode && textNode.text().endsWith(incubatingMarker)) {
+ textNode.text(textNode.text() - incubatingMarker)
+ heading.addClass("incubating")
}
}
}
@@ -147,12 +149,18 @@ transformDocument {
if (subs) {
def sublist = toc.children().last().append("<ul class='toc-sub'/>").children().last()
subs.each {
- def subName = it.text()
+ def subName = it.html()
def subAnchorName = it.attr("id")
- sublist.append("<li><a/></li>").children().last().select("a").first().text(subName).attr("href", "#$subAnchorName")
+ sublist.append("<li><a/></li>").children().last().select("a").first().html(subName).attr("href", "#$subAnchorName")
}
}
+ }
+}
+// add a tooltip to all h3 marked incubating
+transformDocument {
+ for (heading in body().select(".incubating").select("h3")) {
+ heading.append(" <a class='incubating-marker' href='userguide/feature_lifecycle.html' title='“incubating” features are not yet guaranteed to be backwards compatible<br />(click for more information)'>incubating feature</a>")
}
}
diff --git a/subprojects/ear/ear.gradle b/subprojects/ear/ear.gradle
index 145c352..d44049d 100644
--- a/subprojects/ear/ear.gradle
+++ b/subprojects/ear/ear.gradle
@@ -15,7 +15,6 @@
*/
dependencies {
- groovy libraries.groovy
compile project(':core')
compile project(":plugins")
compile libraries.inject
diff --git a/subprojects/ear/src/integTest/groovy/org/gradle/plugins/ear/EarPluginIntegrationTest.groovy b/subprojects/ear/src/integTest/groovy/org/gradle/plugins/ear/EarPluginIntegrationTest.groovy
index dd74fe3..0784b31 100644
--- a/subprojects/ear/src/integTest/groovy/org/gradle/plugins/ear/EarPluginIntegrationTest.groovy
+++ b/subprojects/ear/src/integTest/groovy/org/gradle/plugins/ear/EarPluginIntegrationTest.groovy
@@ -18,11 +18,12 @@ package org.gradle.plugins.ear
import org.gradle.integtests.fixtures.AbstractIntegrationTest
import org.junit.Before
+import org.junit.Ignore
import org.junit.Test
-/**
- * @author: Szczepan Faber, created at: 6/3/11
- */
+import static org.testng.Assert.assertEquals
+import static org.testng.Assert.assertFalse
+
class EarPluginIntegrationTest extends AbstractIntegrationTest {
@Before
@@ -82,6 +83,31 @@ ear {
assert file("unzipped/META-INF/application.xml").text.contains('cool ear')
}
+
+ @Test
+ void "includes modules in deployment descriptor"() {
+ file('moduleA.jar').createFile()
+ file('moduleB.war').createFile()
+
+ file("build.gradle").write("""
+apply plugin: 'ear'
+
+dependencies {
+ deploy files('moduleA.jar', 'moduleB.war')
+}
+""")
+ //when
+ executer.withTasks('assemble').run()
+ file("build/libs/root.ear").unzipTo(file("unzipped"))
+
+ //then
+ def appXml = new XmlSlurper().parse(
+ file('unzipped/META-INF/application.xml'))
+ def modules = appXml.module
+ assertEquals(modules[0].ejb.text(), 'moduleA.jar')
+ assertEquals(modules[1].web.'web-uri'.text(), 'moduleB.war')
+ }
+
@Test
void "uses content found in specified app folder"() {
def applicationXml = """<?xml version="1.0"?>
@@ -140,4 +166,56 @@ ear {
assert file("unzipped/META-INF/stuff/yetAnotherFile.txt").assertExists()
assert file("unzipped/META-INF/application.xml").text == applicationXml
}
+
+ @Test @Ignore
+ void "exclude duplicates: deploymentDescriptor has priority over metaInf"() {
+ file('bad-meta-inf/application.xml').createFile().write('bad descriptor')
+ file('build.gradle').write('''
+apply plugin: 'ear'
+ear {
+ duplicatesStrategy = 'exclude'
+ metaInf {
+ from 'bad-meta-inf'
+ }
+ deploymentDescriptor {
+ applicationName = 'good'
+ }
+}''')
+
+ // when
+ executer.withTasks('assemble').run();
+ file('build/libs/root.ear').unzipTo(file('unzipped'))
+
+ // then
+ assertFalse(
+ file('unzipped/META-INF/application.xml').text.contains('bad descriptor'))
+
+ }
+
+ @Test
+ void "exclude duplicates: lib has priority over other files"() {
+ file('bad-lib/file.txt').createFile().write('bad')
+ file('good-lib/file.txt').createFile().write('good')
+
+ file('build.gradle').write('''
+apply plugin: 'ear'
+ear {
+ duplicatesStrategy = 'exclude'
+ into('lib') {
+ from 'bad-lib'
+ }
+ lib {
+ from 'good-lib'
+ }
+}''')
+
+ // when
+ executer.withTasks('assemble').run();
+ file('build/libs/root.ear').unzipTo(file('unzipped'))
+
+ // then
+ assertEquals('good', file('unzipped/lib/file.txt').text)
+
+ }
+
}
diff --git a/subprojects/ear/src/main/groovy/org/gradle/plugins/ear/Ear.groovy b/subprojects/ear/src/main/groovy/org/gradle/plugins/ear/Ear.groovy
index a5bac93..4fd7227 100644
--- a/subprojects/ear/src/main/groovy/org/gradle/plugins/ear/Ear.groovy
+++ b/subprojects/ear/src/main/groovy/org/gradle/plugins/ear/Ear.groovy
@@ -16,23 +16,20 @@
package org.gradle.plugins.ear
-import org.gradle.plugins.ear.descriptor.DeploymentDescriptor
-import org.gradle.plugins.ear.descriptor.internal.DefaultDeploymentDescriptor
-import org.gradle.plugins.ear.descriptor.EarModule
-import org.gradle.plugins.ear.descriptor.internal.DefaultEarModule
-import org.gradle.plugins.ear.descriptor.internal.DefaultEarWebModule
-
-import org.gradle.api.tasks.bundling.Jar
import org.gradle.api.file.CopySpec
import org.gradle.api.file.FileCopyDetails
import org.gradle.api.internal.file.collections.FileTreeAdapter
import org.gradle.api.internal.file.collections.MapFileTree
+import org.gradle.api.tasks.bundling.Jar
+import org.gradle.plugins.ear.descriptor.DeploymentDescriptor
+import org.gradle.plugins.ear.descriptor.EarModule
+import org.gradle.plugins.ear.descriptor.internal.DefaultDeploymentDescriptor
+import org.gradle.plugins.ear.descriptor.internal.DefaultEarModule
+import org.gradle.plugins.ear.descriptor.internal.DefaultEarWebModule
import org.gradle.util.ConfigureUtil
/**
* Assembles an EAR archive.
- *
- * @author David Gileadi
*/
class Ear extends Jar {
public static final String EAR_EXTENSION = 'ear'
@@ -51,30 +48,30 @@ class Ear extends Jar {
Ear() {
extension = EAR_EXTENSION
- lib = copyAction.rootSpec.addChild().into {
+ lib = rootSpec.addFirst().into {
getLibDirName()
}
- copyAction.mainSpec.eachFile { FileCopyDetails details ->
- if (deploymentDescriptor && details.path.equalsIgnoreCase('META-INF/' + deploymentDescriptor.fileName)) {
+ mainSpec.eachFile { FileCopyDetails details ->
+ if (this.deploymentDescriptor && details.path.equalsIgnoreCase('META-INF/' + this.deploymentDescriptor.fileName)) {
// the deployment descriptor already exists; no need to generate it
- deploymentDescriptor = null
+ this.deploymentDescriptor = null
}
// since we might generate the deployment descriptor, record each top-level module
- if (deploymentDescriptor && details.path.lastIndexOf('/') <= 0) {
+ if (this.deploymentDescriptor && details.path.lastIndexOf('/') <= 0) {
EarModule module
if (details.path.toLowerCase().endsWith(".war")) {
module = new DefaultEarWebModule(details.path, details.path.substring(0, details.path.lastIndexOf('.')))
} else {
module = new DefaultEarModule(details.path)
}
- if (!deploymentDescriptor.modules.contains(module)) {
- deploymentDescriptor.modules.add module
+ if (!this.deploymentDescriptor.modules.contains(module)) {
+ this.deploymentDescriptor.modules.add module
}
}
}
// create our own metaInf which runs after mainSpec's files
// this allows us to generate the deployment descriptor after recording all modules it contains
- def metaInf = copyAction.mainSpec.addChild().into('META-INF')
+ def metaInf = mainSpec.addChild().into('META-INF')
metaInf.addChild().from {
MapFileTree descriptorSource = new MapFileTree(temporaryDirFactory)
final DeploymentDescriptor descriptor = deploymentDescriptor
diff --git a/subprojects/ear/src/main/groovy/org/gradle/plugins/ear/EarPlugin.java b/subprojects/ear/src/main/groovy/org/gradle/plugins/ear/EarPlugin.java
index 126d317..87caba6 100644
--- a/subprojects/ear/src/main/groovy/org/gradle/plugins/ear/EarPlugin.java
+++ b/subprojects/ear/src/main/groovy/org/gradle/plugins/ear/EarPlugin.java
@@ -41,8 +41,6 @@ import java.util.concurrent.Callable;
* <p>
* A {@link Plugin} with tasks which assemble a web application into a EAR file.
* </p>
- *
- * @author David Gileadi, Hans Dockter
*/
public class EarPlugin implements Plugin<Project> {
@@ -125,7 +123,7 @@ public class EarPlugin implements Plugin<Project> {
}
private void setupEarTask(final Project project, EarPluginConvention convention) {
- Ear ear = project.getTasks().add(EAR_TASK_NAME, Ear.class);
+ Ear ear = project.getTasks().create(EAR_TASK_NAME, Ear.class);
ear.setDescription("Generates a ear archive with all the modules, the application descriptor and the libraries.");
DeploymentDescriptor deploymentDescriptor = convention.getDeploymentDescriptor();
if (deploymentDescriptor != null) {
@@ -172,9 +170,9 @@ public class EarPlugin implements Plugin<Project> {
private void configureConfigurations(final Project project) {
ConfigurationContainer configurations = project.getConfigurations();
- Configuration moduleConfiguration = configurations.add(DEPLOY_CONFIGURATION_NAME).setVisible(false)
+ Configuration moduleConfiguration = configurations.create(DEPLOY_CONFIGURATION_NAME).setVisible(false)
.setTransitive(false).setDescription("Classpath for deployable modules, not transitive.");
- Configuration earlibConfiguration = configurations.add(EARLIB_CONFIGURATION_NAME).setVisible(false)
+ Configuration earlibConfiguration = configurations.create(EARLIB_CONFIGURATION_NAME).setVisible(false)
.setDescription("Classpath for module dependencies.");
configurations.getByName(Dependency.DEFAULT_CONFIGURATION)
diff --git a/subprojects/ear/src/main/groovy/org/gradle/plugins/ear/descriptor/DeploymentDescriptor.java b/subprojects/ear/src/main/groovy/org/gradle/plugins/ear/descriptor/DeploymentDescriptor.java
index adbff5d..3883a87 100644
--- a/subprojects/ear/src/main/groovy/org/gradle/plugins/ear/descriptor/DeploymentDescriptor.java
+++ b/subprojects/ear/src/main/groovy/org/gradle/plugins/ear/descriptor/DeploymentDescriptor.java
@@ -26,8 +26,6 @@ import java.util.Set;
/**
* A deployment descriptor such as application.xml.
- *
- * @author David Gileadi
*/
public interface DeploymentDescriptor {
diff --git a/subprojects/ear/src/main/groovy/org/gradle/plugins/ear/descriptor/EarModule.java b/subprojects/ear/src/main/groovy/org/gradle/plugins/ear/descriptor/EarModule.java
index 42a22fc..1d243d4 100644
--- a/subprojects/ear/src/main/groovy/org/gradle/plugins/ear/descriptor/EarModule.java
+++ b/subprojects/ear/src/main/groovy/org/gradle/plugins/ear/descriptor/EarModule.java
@@ -19,8 +19,6 @@ import groovy.util.Node;
/**
* A module element in a deployment descriptor like application.xml.
- *
- * @author David Gileadi
*/
public interface EarModule {
diff --git a/subprojects/ear/src/main/groovy/org/gradle/plugins/ear/descriptor/EarSecurityRole.java b/subprojects/ear/src/main/groovy/org/gradle/plugins/ear/descriptor/EarSecurityRole.java
index 1ec1873..84c9103 100644
--- a/subprojects/ear/src/main/groovy/org/gradle/plugins/ear/descriptor/EarSecurityRole.java
+++ b/subprojects/ear/src/main/groovy/org/gradle/plugins/ear/descriptor/EarSecurityRole.java
@@ -17,8 +17,6 @@ package org.gradle.plugins.ear.descriptor;
/**
* A security-role element in a deployment descriptor like application.xml.
- *
- * @author David Gileadi
*/
public interface EarSecurityRole {
diff --git a/subprojects/ear/src/main/groovy/org/gradle/plugins/ear/descriptor/EarWebModule.java b/subprojects/ear/src/main/groovy/org/gradle/plugins/ear/descriptor/EarWebModule.java
index f34425d..be32226 100644
--- a/subprojects/ear/src/main/groovy/org/gradle/plugins/ear/descriptor/EarWebModule.java
+++ b/subprojects/ear/src/main/groovy/org/gradle/plugins/ear/descriptor/EarWebModule.java
@@ -17,8 +17,6 @@ package org.gradle.plugins.ear.descriptor;
/**
* A module element in a deployment descriptor like application.xml that has a web child element.
- *
- * @author David Gileadi
*/
public interface EarWebModule extends EarModule {
diff --git a/subprojects/ear/src/main/groovy/org/gradle/plugins/ear/descriptor/internal/DefaultDeploymentDescriptor.groovy b/subprojects/ear/src/main/groovy/org/gradle/plugins/ear/descriptor/internal/DefaultDeploymentDescriptor.groovy
index 7c17ee1..2a35435 100644
--- a/subprojects/ear/src/main/groovy/org/gradle/plugins/ear/descriptor/internal/DefaultDeploymentDescriptor.groovy
+++ b/subprojects/ear/src/main/groovy/org/gradle/plugins/ear/descriptor/internal/DefaultDeploymentDescriptor.groovy
@@ -27,9 +27,6 @@ import org.gradle.plugins.ear.descriptor.EarModule
import org.gradle.plugins.ear.descriptor.EarSecurityRole
import org.gradle.plugins.ear.descriptor.EarWebModule
-/**
- * @author David Gileadi
- */
class DefaultDeploymentDescriptor implements DeploymentDescriptor {
private String fileName = "application.xml"
diff --git a/subprojects/ear/src/main/groovy/org/gradle/plugins/ear/descriptor/internal/DefaultEarModule.groovy b/subprojects/ear/src/main/groovy/org/gradle/plugins/ear/descriptor/internal/DefaultEarModule.groovy
index 14e1a19..9b94742 100644
--- a/subprojects/ear/src/main/groovy/org/gradle/plugins/ear/descriptor/internal/DefaultEarModule.groovy
+++ b/subprojects/ear/src/main/groovy/org/gradle/plugins/ear/descriptor/internal/DefaultEarModule.groovy
@@ -18,9 +18,6 @@ package org.gradle.plugins.ear.descriptor.internal
import groovy.xml.QName
import org.gradle.plugins.ear.descriptor.EarModule
-/**
- * @author David Gileadi
- */
class DefaultEarModule implements EarModule {
String path;
diff --git a/subprojects/ear/src/main/groovy/org/gradle/plugins/ear/descriptor/internal/DefaultEarSecurityRole.groovy b/subprojects/ear/src/main/groovy/org/gradle/plugins/ear/descriptor/internal/DefaultEarSecurityRole.groovy
index 0bc4965..f1168ca 100644
--- a/subprojects/ear/src/main/groovy/org/gradle/plugins/ear/descriptor/internal/DefaultEarSecurityRole.groovy
+++ b/subprojects/ear/src/main/groovy/org/gradle/plugins/ear/descriptor/internal/DefaultEarSecurityRole.groovy
@@ -17,9 +17,6 @@ package org.gradle.plugins.ear.descriptor.internal
import org.gradle.plugins.ear.descriptor.EarSecurityRole
-/**
- * @author David Gileadi
- */
class DefaultEarSecurityRole implements EarSecurityRole {
String description
diff --git a/subprojects/ear/src/main/groovy/org/gradle/plugins/ear/descriptor/internal/DefaultEarWebModule.groovy b/subprojects/ear/src/main/groovy/org/gradle/plugins/ear/descriptor/internal/DefaultEarWebModule.groovy
index 76640c7..0c77f87 100644
--- a/subprojects/ear/src/main/groovy/org/gradle/plugins/ear/descriptor/internal/DefaultEarWebModule.groovy
+++ b/subprojects/ear/src/main/groovy/org/gradle/plugins/ear/descriptor/internal/DefaultEarWebModule.groovy
@@ -17,9 +17,6 @@ package org.gradle.plugins.ear.descriptor.internal
import org.gradle.plugins.ear.descriptor.EarWebModule;
-/**
- * @author David Gileadi
- */
class DefaultEarWebModule extends DefaultEarModule implements EarWebModule {
String contextRoot
diff --git a/subprojects/ear/src/test/groovy/org/gradle/plugins/ear/EarPluginTest.groovy b/subprojects/ear/src/test/groovy/org/gradle/plugins/ear/EarPluginTest.groovy
index 399878d..c8563e5 100644
--- a/subprojects/ear/src/test/groovy/org/gradle/plugins/ear/EarPluginTest.groovy
+++ b/subprojects/ear/src/test/groovy/org/gradle/plugins/ear/EarPluginTest.groovy
@@ -23,20 +23,18 @@ import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.Dependency
import org.gradle.api.internal.project.ProjectInternal
import org.gradle.api.plugins.BasePlugin
+import org.gradle.api.plugins.JavaBasePlugin
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.plugins.WarPlugin
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import org.junit.Before
import org.junit.Test
+
import static org.gradle.util.Matchers.dependsOn
import static org.gradle.util.TextUtil.toPlatformLineSeparators
import static org.hamcrest.Matchers.*
import static org.junit.Assert.*
-import org.gradle.api.plugins.JavaBasePlugin
-/**
- * @author David Gileadi
- */
class EarPluginTest {
private ProjectInternal project
private static final String TEST_APP_XML = toPlatformLineSeparators('<?xml version="1.0" encoding="UTF-8"?>\n' +
@@ -56,7 +54,7 @@ class EarPluginTest {
@Before
public void setUp() {
- project = HelperUtil.createRootProject()
+ project = TestUtil.createRootProject()
}
@Test public void appliesBasePluginAndAddsConvention() {
@@ -105,7 +103,7 @@ class EarPluginTest {
@Test public void dependsOnEarlibConfig() {
project.plugins.apply(EarPlugin)
- Project childProject = HelperUtil.createChildProject(project, 'child')
+ Project childProject = TestUtil.createChildProject(project, 'child')
JavaPlugin javaPlugin = new JavaPlugin()
javaPlugin.apply(childProject)
@@ -195,14 +193,12 @@ class EarPluginTest {
}
@Test public void supportsRenamingLibDir() {
- Project childProject = HelperUtil.createChildProject(project, 'child')
+ Project childProject = TestUtil.createChildProject(project, 'child')
childProject.file("src/main/resources").mkdirs()
childProject.file("src/main/resources/test.txt").createNewFile()
JavaPlugin javaPlugin = new JavaPlugin()
javaPlugin.apply(childProject)
- execute childProject.tasks[BasePlugin.ASSEMBLE_TASK_NAME]
-
project.plugins.apply(EarPlugin)
project.convention.plugins.ear.libDirName = "APP-INF/lib"
project.dependencies {
diff --git a/subprojects/ear/src/test/groovy/org/gradle/plugins/ear/EarTest.groovy b/subprojects/ear/src/test/groovy/org/gradle/plugins/ear/EarTest.groovy
index 1a4746f..edb6be7 100644
--- a/subprojects/ear/src/test/groovy/org/gradle/plugins/ear/EarTest.groovy
+++ b/subprojects/ear/src/test/groovy/org/gradle/plugins/ear/EarTest.groovy
@@ -16,16 +16,14 @@
package org.gradle.plugins.ear
-import org.gradle.plugins.ear.descriptor.internal.DefaultDeploymentDescriptor
-import org.gradle.api.tasks.bundling.AbstractArchiveTaskTest
import org.gradle.api.tasks.bundling.AbstractArchiveTask
+import org.gradle.api.tasks.bundling.AbstractArchiveTaskTest
+import org.gradle.plugins.ear.descriptor.internal.DefaultDeploymentDescriptor
import org.junit.Before
import org.junit.Test
+
import static org.junit.Assert.assertEquals
-/**
- * @author David Gileadi
- */
class EarTest extends AbstractArchiveTaskTest {
Ear ear
diff --git a/subprojects/ear/src/test/groovy/org/gradle/plugins/ear/descriptor/internal/DefaultDeploymentDescriptorTest.groovy b/subprojects/ear/src/test/groovy/org/gradle/plugins/ear/descriptor/internal/DefaultDeploymentDescriptorTest.groovy
index 66c024a..30757fd 100644
--- a/subprojects/ear/src/test/groovy/org/gradle/plugins/ear/descriptor/internal/DefaultDeploymentDescriptorTest.groovy
+++ b/subprojects/ear/src/test/groovy/org/gradle/plugins/ear/descriptor/internal/DefaultDeploymentDescriptorTest.groovy
@@ -25,9 +25,6 @@ import javax.xml.parsers.DocumentBuilderFactory
import static org.gradle.util.TextUtil.toPlatformLineSeparators
-/**
- * @author: Szczepan Faber, created at: 6/3/11
- */
class DefaultDeploymentDescriptorTest extends Specification {
def descriptor = new DefaultDeploymentDescriptor({ it } as FileResolver)
@Rule TestNameTestDirectoryProvider tmpDir
diff --git a/subprojects/ide/ide.gradle b/subprojects/ide/ide.gradle
index 1e4eab0..453ecf1 100644
--- a/subprojects/ide/ide.gradle
+++ b/subprojects/ide/ide.gradle
@@ -14,7 +14,7 @@
* limitations under the License.
*/
dependencies {
- groovy libraries.groovy
+ compile libraries.groovy
compile project(':scala')
compile project(':core')
diff --git a/subprojects/ide/src/integTest/groovy/org/gradle/plugins/ide/AutoTestedSamplesIntegrationTest.groovy b/subprojects/ide/src/integTest/groovy/org/gradle/plugins/ide/AutoTestedSamplesIntegrationTest.groovy
index 80da222..2cc4497 100644
--- a/subprojects/ide/src/integTest/groovy/org/gradle/plugins/ide/AutoTestedSamplesIntegrationTest.groovy
+++ b/subprojects/ide/src/integTest/groovy/org/gradle/plugins/ide/AutoTestedSamplesIntegrationTest.groovy
@@ -19,9 +19,6 @@ package org.gradle.plugins.ide
import org.gradle.integtests.fixtures.AbstractAutoTestedSamplesTest
import org.junit.Test
-/**
- * @author Szczepan Faber, created at: 3/27/11
- */
class AutoTestedSamplesIntegrationTest extends AbstractAutoTestedSamplesTest {
@Test
diff --git a/subprojects/ide/src/integTest/groovy/org/gradle/plugins/ide/eclipse/EclipseClasspathIntegrationTest.groovy b/subprojects/ide/src/integTest/groovy/org/gradle/plugins/ide/eclipse/EclipseClasspathIntegrationTest.groovy
index a4f758c..b427c79 100644
--- a/subprojects/ide/src/integTest/groovy/org/gradle/plugins/ide/eclipse/EclipseClasspathIntegrationTest.groovy
+++ b/subprojects/ide/src/integTest/groovy/org/gradle/plugins/ide/eclipse/EclipseClasspathIntegrationTest.groovy
@@ -20,9 +20,6 @@ import org.junit.Rule
import org.junit.Test
import spock.lang.Issue
-/**
- * @author Szczepan Faber
- */
class EclipseClasspathIntegrationTest extends AbstractEclipseIntegrationTest {
@Rule
diff --git a/subprojects/ide/src/integTest/groovy/org/gradle/plugins/ide/eclipse/EclipseEarIntegrationTest.groovy b/subprojects/ide/src/integTest/groovy/org/gradle/plugins/ide/eclipse/EclipseEarIntegrationTest.groovy
index 5e44ba1..f0d6343 100644
--- a/subprojects/ide/src/integTest/groovy/org/gradle/plugins/ide/eclipse/EclipseEarIntegrationTest.groovy
+++ b/subprojects/ide/src/integTest/groovy/org/gradle/plugins/ide/eclipse/EclipseEarIntegrationTest.groovy
@@ -17,9 +17,6 @@ package org.gradle.plugins.ide.eclipse
import org.junit.Test
-/**
- * @author Szczepan Faber
- */
class EclipseEarIntegrationTest extends AbstractEclipseIntegrationTest {
@Test
diff --git a/subprojects/ide/src/integTest/groovy/org/gradle/plugins/ide/eclipse/EclipseMultiModuleIntegrationTest.groovy b/subprojects/ide/src/integTest/groovy/org/gradle/plugins/ide/eclipse/EclipseMultiModuleIntegrationTest.groovy
index 00d4240..3c10693 100644
--- a/subprojects/ide/src/integTest/groovy/org/gradle/plugins/ide/eclipse/EclipseMultiModuleIntegrationTest.groovy
+++ b/subprojects/ide/src/integTest/groovy/org/gradle/plugins/ide/eclipse/EclipseMultiModuleIntegrationTest.groovy
@@ -20,9 +20,6 @@ import org.gradle.plugins.ide.AbstractIdeIntegrationTest
import org.junit.Rule
import org.junit.Test
-/**
- * @author Szczepan Faber, @date 01.03.11
- */
class EclipseMultiModuleIntegrationTest extends AbstractIdeIntegrationTest {
@Rule
public final TestResources testResources = new TestResources(testDirectoryProvider)
diff --git a/subprojects/ide/src/integTest/groovy/org/gradle/plugins/ide/eclipse/EclipseProjectIntegrationTest.groovy b/subprojects/ide/src/integTest/groovy/org/gradle/plugins/ide/eclipse/EclipseProjectIntegrationTest.groovy
index 970eaff..6531d59 100644
--- a/subprojects/ide/src/integTest/groovy/org/gradle/plugins/ide/eclipse/EclipseProjectIntegrationTest.groovy
+++ b/subprojects/ide/src/integTest/groovy/org/gradle/plugins/ide/eclipse/EclipseProjectIntegrationTest.groovy
@@ -19,9 +19,6 @@ import org.gradle.integtests.fixtures.TestResources
import org.junit.Rule
import org.junit.Test
-/**
- * @author Szczepan Faber
- */
class EclipseProjectIntegrationTest extends AbstractEclipseIntegrationTest {
@Rule
diff --git a/subprojects/ide/src/integTest/groovy/org/gradle/plugins/ide/eclipse/EclipseWtpModelIntegrationTest.groovy b/subprojects/ide/src/integTest/groovy/org/gradle/plugins/ide/eclipse/EclipseWtpModelIntegrationTest.groovy
index d031ac9..e0cb1d2 100644
--- a/subprojects/ide/src/integTest/groovy/org/gradle/plugins/ide/eclipse/EclipseWtpModelIntegrationTest.groovy
+++ b/subprojects/ide/src/integTest/groovy/org/gradle/plugins/ide/eclipse/EclipseWtpModelIntegrationTest.groovy
@@ -22,9 +22,6 @@ import org.junit.Rule
import org.junit.Test
import spock.lang.Issue
-/**
- * @author Szczepan Faber, created at: 4/19/11
- */
class EclipseWtpModelIntegrationTest extends AbstractEclipseIntegrationTest {
@Rule
diff --git a/subprojects/ide/src/integTest/groovy/org/gradle/plugins/ide/idea/IdeaIntegrationTest.groovy b/subprojects/ide/src/integTest/groovy/org/gradle/plugins/ide/idea/IdeaIntegrationTest.groovy
index d53c9da..31c8938 100644
--- a/subprojects/ide/src/integTest/groovy/org/gradle/plugins/ide/idea/IdeaIntegrationTest.groovy
+++ b/subprojects/ide/src/integTest/groovy/org/gradle/plugins/ide/idea/IdeaIntegrationTest.groovy
@@ -22,7 +22,6 @@ import org.gradle.integtests.fixtures.TestResources
import org.gradle.internal.os.OperatingSystem
import org.gradle.plugins.ide.AbstractIdeIntegrationTest
import org.gradle.test.fixtures.file.TestFile
-import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
@@ -95,15 +94,15 @@ apply plugin: 'idea'
assertHasExpectedContents('root.iml')
}
- @Ignore
@Test
void addsScalaFacetAndCompilerLibraries() {
executer.withTasks('idea').run()
- assertHasExpectedContents('root.ipr')
- assertHasExpectedContents('project1/project1.iml')
- assertHasExpectedContents('project2/project2.iml')
- assertHasExpectedContents('project3/project3.iml')
+ hasProjectLibrary('root.ipr', 'scala-compiler-2.9.2', ['scala-compiler-2.9.2.jar', 'scala-library-2.9.2.jar'], [], [])
+ hasProjectLibrary('root.ipr', 'scala-compiler-2.10.0', ['scala-compiler-2.10.0.jar', 'scala-library-2.10.0.jar', 'scala-reflect-2.10.0.jar'], [], [])
+ hasScalaFacet('project1/project1.iml', 'scala-compiler-2.9.2')
+ hasScalaFacet('project2/project2.iml', 'scala-compiler-2.10.0')
+ hasScalaFacet('project3/project3.iml', 'scala-compiler-2.9.2')
}
@Test
@@ -346,6 +345,24 @@ apply plugin: "idea"
failure.output.contains("Perhaps this file was tinkered with?")
}
+ @Test
+ void canAddProjectLibraries() {
+ runTask("idea", """
+apply plugin: 'idea'
+
+idea.project {
+ def lib = new org.gradle.plugins.ide.idea.model.ProjectLibrary()
+ lib.name = "someLib"
+ lib.classes << file("someClasses.jar")
+ lib.javadoc << file("someJavadoc.jar")
+ lib.sources << file("someSources.jar")
+ projectLibraries << lib
+}
+""")
+
+ hasProjectLibrary("root.ipr", "someLib", ["someClasses.jar"], ["someJavadoc.jar"], ["someSources.jar"])
+ }
+
private void assertHasExpectedContents(String path) {
TestFile file = testDirectory.file(path).assertIsFile()
TestFile expectedFile = testDirectory.file("expectedFiles/${path}.xml").assertIsFile()
@@ -370,6 +387,51 @@ apply plugin: "idea"
}
}
+ private void hasProjectLibrary(String iprFileName, String libraryName, List<String> classesLibs, List<String> javadocLibs, List<String> sourcesLibs) {
+ def project = new XmlSlurper().parse(file(iprFileName))
+ def libraryTable = project.component.find { it. at name == "libraryTable" }
+ assert libraryTable
+
+ def library = libraryTable.library.find { it. at name == libraryName }
+ assert library
+
+ def classesRoots = library.CLASSES.root
+ assert classesRoots.size() == classesLibs.size()
+ classesLibs.each {
+ assert classesRoots. at url.text().contains(it)
+ }
+
+ def javadocRoots = library.JAVADOC.root
+ assert javadocRoots.size() == javadocLibs.size()
+ javadocLibs.each {
+ assert javadocRoots. at url.text().contains(it)
+ }
+
+ def sourcesRoots = library.SOURCES.root
+ assert sourcesRoots.size() == sourcesLibs.size()
+ sourcesLibs.each {
+ assert sourcesRoots. at url.text().contains(it)
+ }
+ }
+
+ private void hasScalaFacet(String imlFileName, String libraryName) {
+ def module = new XmlSlurper().parse(file(imlFileName))
+ def facetManager = module.component.find { it. at name == "FacetManager" }
+ assert facetManager
+
+ def facet = facetManager.facet.find { it. at name == "Scala" }
+ assert facet
+ assert facet. at type == "scala"
+
+ def compilerLibraryLevel = facet.configuration.option.find { it. at name == "compilerLibraryLevel" }
+ assert compilerLibraryLevel
+ assert compilerLibraryLevel. at value == "Project"
+
+ def compilerLibraryName = facet.configuration.option.find { it. at name == "compilerLibraryName" }
+ assert compilerLibraryName
+ assert compilerLibraryName. at value == libraryName
+ }
+
private containsDir(path, urls) {
urls.any { it.endsWith(path) }
}
diff --git a/subprojects/ide/src/integTest/groovy/org/gradle/plugins/ide/idea/IdeaMultiModuleIntegrationTest.groovy b/subprojects/ide/src/integTest/groovy/org/gradle/plugins/ide/idea/IdeaMultiModuleIntegrationTest.groovy
index 773e9c6..603d2d3 100644
--- a/subprojects/ide/src/integTest/groovy/org/gradle/plugins/ide/idea/IdeaMultiModuleIntegrationTest.groovy
+++ b/subprojects/ide/src/integTest/groovy/org/gradle/plugins/ide/idea/IdeaMultiModuleIntegrationTest.groovy
@@ -20,9 +20,6 @@ import org.gradle.plugins.ide.AbstractIdeIntegrationTest
import org.junit.Rule
import org.junit.Test
-/**
- * @author Szczepan Faber, @date 03.03.11
- */
class IdeaMultiModuleIntegrationTest extends AbstractIdeIntegrationTest {
@Rule
public final TestResources testResources = new TestResources(testDirectoryProvider)
diff --git a/subprojects/ide/src/integTest/groovy/org/gradle/plugins/ide/idea/IdeaWorkspaceIntegrationTest.groovy b/subprojects/ide/src/integTest/groovy/org/gradle/plugins/ide/idea/IdeaWorkspaceIntegrationTest.groovy
index 5fb85ba..5716992 100644
--- a/subprojects/ide/src/integTest/groovy/org/gradle/plugins/ide/idea/IdeaWorkspaceIntegrationTest.groovy
+++ b/subprojects/ide/src/integTest/groovy/org/gradle/plugins/ide/idea/IdeaWorkspaceIntegrationTest.groovy
@@ -19,9 +19,6 @@ package org.gradle.plugins.ide.idea
import org.gradle.plugins.ide.AbstractIdeIntegrationTest
import org.junit.Test
-/**
- * @author: Szczepan Faber, created at: 6/9/11
- */
class IdeaWorkspaceIntegrationTest extends AbstractIdeIntegrationTest {
@Test
diff --git a/subprojects/ide/src/integTest/resources/org/gradle/plugins/ide/idea/IdeaIntegrationTest/addsScalaFacetAndCompilerLibraries/expectedFiles/project1/project1.iml.xml b/subprojects/ide/src/integTest/resources/org/gradle/plugins/ide/idea/IdeaIntegrationTest/addsScalaFacetAndCompilerLibraries/expectedFiles/project1/project1.iml.xml
deleted file mode 100644
index e430939..0000000
--- a/subprojects/ide/src/integTest/resources/org/gradle/plugins/ide/idea/IdeaIntegrationTest/addsScalaFacetAndCompilerLibraries/expectedFiles/project1/project1.iml.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<module relativePaths="true" type="JAVA_MODULE" version="4">
- <component name="NewModuleRootManager" inherit-compiler-output="true">
- <exclude-output/>
- <orderEntry type="inheritedJdk"/>
- <content url="file://$MODULE_DIR$/">
- <excludeFolder url="file://$MODULE_DIR$/build"/>
- <excludeFolder url="file://$MODULE_DIR$/.gradle"/>
- </content>
- <orderEntry type="sourceFolder" forTests="false"/>
- <orderEntry type="module-library" exported="">
- <library>
- <CLASSES>
- <root url="jar://@CACHE_DIR@/org.scala-lang/scala-library/2.9.2/jar/@SHA1@/scala-library-2.9.2.jar!/"/>
- </CLASSES>
- <JAVADOC/>
- <SOURCES>
- <root url="jar://@CACHE_DIR@/org.scala-lang/scala-library/2.9.2/source/@SHA1@/scala-library-2.9.2-sources.jar!/"/>
- </SOURCES>
- </library>
- </orderEntry>
- </component>
- <component name="ModuleRootManager"/>
- <component name="FacetManager">
- <facet type="scala" name="Scala">
- <configuration>
- <option name="compilerLibraryLevel" value="Project"/>
- <option name="compilerLibraryName" value="scala-compiler-2.9.2"/>
- </configuration>
- </facet>
- </component>
-</module>
diff --git a/subprojects/ide/src/integTest/resources/org/gradle/plugins/ide/idea/IdeaIntegrationTest/addsScalaFacetAndCompilerLibraries/expectedFiles/project2/project2.iml.xml b/subprojects/ide/src/integTest/resources/org/gradle/plugins/ide/idea/IdeaIntegrationTest/addsScalaFacetAndCompilerLibraries/expectedFiles/project2/project2.iml.xml
deleted file mode 100644
index d9f8fb8..0000000
--- a/subprojects/ide/src/integTest/resources/org/gradle/plugins/ide/idea/IdeaIntegrationTest/addsScalaFacetAndCompilerLibraries/expectedFiles/project2/project2.iml.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<module relativePaths="true" type="JAVA_MODULE" version="4">
- <component name="NewModuleRootManager" inherit-compiler-output="true">
- <exclude-output/>
- <orderEntry type="inheritedJdk"/>
- <content url="file://$MODULE_DIR$/">
- <excludeFolder url="file://$MODULE_DIR$/.gradle"/>
- <excludeFolder url="file://$MODULE_DIR$/build"/>
- </content>
- <orderEntry type="sourceFolder" forTests="false"/>
- <orderEntry type="module-library" exported="">
- <library>
- <CLASSES>
- <root url="jar://@CACHE_DIR@/org.scala-lang/scala-library/2.10.0/jar/@SHA1@/scala-library-2.10.0.jar!/"/>
- </CLASSES>
- <JAVADOC/>
- <SOURCES>
- <root url="jar://@CACHE_DIR@/org.scala-lang/scala-library/2.10.0/source/@SHA1@/scala-library-2.10.0-sources.jar!/"/>
- </SOURCES>
- </library>
- </orderEntry>
- </component>
- <component name="ModuleRootManager"/>
- <component name="FacetManager">
- <facet type="scala" name="Scala">
- <configuration>
- <option name="compilerLibraryLevel" value="Project"/>
- <option name="compilerLibraryName" value="scala-compiler-2.10.0"/>
- </configuration>
- </facet>
- </component>
-</module>
diff --git a/subprojects/ide/src/integTest/resources/org/gradle/plugins/ide/idea/IdeaIntegrationTest/addsScalaFacetAndCompilerLibraries/expectedFiles/project3/project3.iml.xml b/subprojects/ide/src/integTest/resources/org/gradle/plugins/ide/idea/IdeaIntegrationTest/addsScalaFacetAndCompilerLibraries/expectedFiles/project3/project3.iml.xml
deleted file mode 100644
index e430939..0000000
--- a/subprojects/ide/src/integTest/resources/org/gradle/plugins/ide/idea/IdeaIntegrationTest/addsScalaFacetAndCompilerLibraries/expectedFiles/project3/project3.iml.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<module relativePaths="true" type="JAVA_MODULE" version="4">
- <component name="NewModuleRootManager" inherit-compiler-output="true">
- <exclude-output/>
- <orderEntry type="inheritedJdk"/>
- <content url="file://$MODULE_DIR$/">
- <excludeFolder url="file://$MODULE_DIR$/build"/>
- <excludeFolder url="file://$MODULE_DIR$/.gradle"/>
- </content>
- <orderEntry type="sourceFolder" forTests="false"/>
- <orderEntry type="module-library" exported="">
- <library>
- <CLASSES>
- <root url="jar://@CACHE_DIR@/org.scala-lang/scala-library/2.9.2/jar/@SHA1@/scala-library-2.9.2.jar!/"/>
- </CLASSES>
- <JAVADOC/>
- <SOURCES>
- <root url="jar://@CACHE_DIR@/org.scala-lang/scala-library/2.9.2/source/@SHA1@/scala-library-2.9.2-sources.jar!/"/>
- </SOURCES>
- </library>
- </orderEntry>
- </component>
- <component name="ModuleRootManager"/>
- <component name="FacetManager">
- <facet type="scala" name="Scala">
- <configuration>
- <option name="compilerLibraryLevel" value="Project"/>
- <option name="compilerLibraryName" value="scala-compiler-2.9.2"/>
- </configuration>
- </facet>
- </component>
-</module>
diff --git a/subprojects/ide/src/integTest/resources/org/gradle/plugins/ide/idea/IdeaIntegrationTest/addsScalaFacetAndCompilerLibraries/expectedFiles/root.ipr.xml b/subprojects/ide/src/integTest/resources/org/gradle/plugins/ide/idea/IdeaIntegrationTest/addsScalaFacetAndCompilerLibraries/expectedFiles/root.ipr.xml
deleted file mode 100644
index e8f66e8..0000000
--- a/subprojects/ide/src/integTest/resources/org/gradle/plugins/ide/idea/IdeaIntegrationTest/addsScalaFacetAndCompilerLibraries/expectedFiles/root.ipr.xml
+++ /dev/null
@@ -1,123 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
- <component name="CompilerConfiguration">
- <option name="DEFAULT_COMPILER" value="Javac"/>
- <resourceExtensions>
- <entry name=".+\.(properties|xml|html|dtd|tld)"/>
- <entry name=".+\.(gif|png|jpeg|jpg)"/>
- </resourceExtensions>
- <wildcardResourcePatterns>
- <entry name="!?*.groovy"/>
- <entry name="!?*.java"/>
- </wildcardResourcePatterns>
- <annotationProcessing enabled="false" useClasspath="true"/>
- </component>
- <component name="CopyrightManager" default="">
- <module2copyright/>
- </component>
- <component name="DependencyValidationManager">
- <option name="SKIP_IMPORT_STATEMENTS" value="false"/>
- </component>
- <component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false"/>
- <component name="GradleUISettings">
- <setting name="root"/>
- </component>
- <component name="GradleUISettings2">
- <setting name="root"/>
- </component>
- <component name="IdProvider" IDEtalkID="11DA1DB66DD62DDA1ED602B7079FE97C"/>
- <component name="JavadocGenerationManager">
- <option name="OUTPUT_DIRECTORY"/>
- <option name="OPTION_SCOPE" value="protected"/>
- <option name="OPTION_HIERARCHY" value="true"/>
- <option name="OPTION_NAVIGATOR" value="true"/>
- <option name="OPTION_INDEX" value="true"/>
- <option name="OPTION_SEPARATE_INDEX" value="true"/>
- <option name="OPTION_DOCUMENT_TAG_USE" value="false"/>
- <option name="OPTION_DOCUMENT_TAG_AUTHOR" value="false"/>
- <option name="OPTION_DOCUMENT_TAG_VERSION" value="false"/>
- <option name="OPTION_DOCUMENT_TAG_DEPRECATED" value="true"/>
- <option name="OPTION_DEPRECATED_LIST" value="true"/>
- <option name="OTHER_OPTIONS" value=""/>
- <option name="HEAP_SIZE"/>
- <option name="LOCALE"/>
- <option name="OPEN_IN_BROWSER" value="true"/>
- </component>
- <component name="ProjectModuleManager">
- <modules>
- <module fileurl="file://$PROJECT_DIR$/root.iml" filepath="$PROJECT_DIR$/root.iml"/>
- <module fileurl="file://$PROJECT_DIR$/project3/project3.iml" filepath="$PROJECT_DIR$/project3/project3.iml"/>
- <module fileurl="file://$PROJECT_DIR$/project2/project2.iml" filepath="$PROJECT_DIR$/project2/project2.iml"/>
- <module fileurl="file://$PROJECT_DIR$/project1/project1.iml" filepath="$PROJECT_DIR$/project1/project1.iml"/>
- </modules>
- </component>
- <component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-type="JavaSDK" assert-jdk-15="true" project-jdk-name="1.7">
- <output url="file://$PROJECT_DIR$/out"/>
- </component>
- <component name="SvnBranchConfigurationManager">
- <option name="mySupportsUserInfoFilter" value="true"/>
- </component>
- <component name="VcsDirectoryMappings">
- <mapping directory="" vcs=""/>
- </component>
- <component name="masterDetails">
- <states>
- <state key="ArtifactsStructureConfigurable.UI">
- <UIState>
- <splitter-proportions>
- <SplitterProportionsDataImpl/>
- </splitter-proportions>
- <settings/>
- </UIState>
- </state>
- <state key="Copyright.UI">
- <UIState>
- <splitter-proportions>
- <SplitterProportionsDataImpl/>
- </splitter-proportions>
- </UIState>
- </state>
- <state key="ProjectJDKs.UI">
- <UIState>
- <splitter-proportions>
- <SplitterProportionsDataImpl>
- <option name="proportions">
- <list>
- <option value="0.2"/>
- </list>
- </option>
- </SplitterProportionsDataImpl>
- </splitter-proportions>
- <last-edited>1.6</last-edited>
- </UIState>
- </state>
- <state key="ScopeChooserConfigurable.UI">
- <UIState>
- <splitter-proportions>
- <SplitterProportionsDataImpl/>
- </splitter-proportions>
- <settings/>
- </UIState>
- </state>
- </states>
- </component>
- <component name="libraryTable">
- <library name="scala-compiler-2.9.2">
- <CLASSES>
- <root url="jar://@CACHE_DIR@/org.scala-lang/scala-compiler/2.9.2/jar/@SHA1@/scala-compiler-2.9.2.jar!/"/>
- <root url="jar://@CACHE_DIR@/org.scala-lang/scala-library/2.9.2/jar/@SHA1@/scala-library-2.9.2.jar!/"/>
- </CLASSES>
- <JAVADOC/>
- <SOURCES/>
- </library>
- <library name="scala-compiler-2.10.0">
- <CLASSES>
- <root url="jar://@CACHE_DIR@/org.scala-lang/scala-compiler/2.10.0/jar/@SHA1@/scala-compiler-2.10.0.jar!/"/>
- <root url="jar://@CACHE_DIR@/org.scala-lang/scala-library/2.10.0/jar/@SHA1@/scala-library-2.10.0.jar!/"/>
- <root url="jar://@CACHE_DIR@/org.scala-lang/scala-reflect/2.10.0/jar/@SHA1@/scala-reflect-2.10.0.jar!/"/>
- </CLASSES>
- <JAVADOC/>
- <SOURCES/>
- </library>
- </component>
-</project>
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/api/FileContentMerger.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/api/FileContentMerger.groovy
index 17e063a..18432c7 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/api/FileContentMerger.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/api/FileContentMerger.groovy
@@ -23,8 +23,6 @@ import org.gradle.listener.ActionBroadcast
* Models the generation/parsing/merging capabilities.
* <p>
* For examples see docs for {@link org.gradle.plugins.ide.eclipse.model.EclipseProject} or {@link org.gradle.plugins.ide.idea.model.IdeaProject} and others.
- *
- * @author: Szczepan Faber, created at: 4/21/11
*/
class FileContentMerger {
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/api/XmlFileContentMerger.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/api/XmlFileContentMerger.groovy
index fe58c62..ad9f0ac 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/api/XmlFileContentMerger.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/api/XmlFileContentMerger.groovy
@@ -19,11 +19,9 @@ package org.gradle.plugins.ide.api
import org.gradle.api.internal.xml.XmlTransformer
/**
- * Models the generation/parsing/merging capabilities. Adds xml-related hooks.
+ * Models the generation/parsing/merging capabilities. Adds XML-related hooks.
* <p>
* For examples see docs for {@link org.gradle.plugins.ide.eclipse.model.EclipseProject} or {@link org.gradle.plugins.ide.idea.model.IdeaProject} and others.
- *
- * @author: Szczepan Faber, created at: 4/21/11
*/
class XmlFileContentMerger extends FileContentMerger {
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/EclipsePlugin.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/EclipsePlugin.groovy
index 7d41b65..3a14788 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/EclipsePlugin.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/EclipsePlugin.groovy
@@ -17,11 +17,11 @@ package org.gradle.plugins.ide.eclipse
import org.gradle.api.Project
import org.gradle.api.artifacts.Dependency
-import org.gradle.internal.reflect.Instantiator
import org.gradle.api.plugins.GroovyBasePlugin
import org.gradle.api.plugins.JavaBasePlugin
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.plugins.scala.ScalaBasePlugin
+import org.gradle.internal.reflect.Instantiator
import org.gradle.plugins.ear.EarPlugin
import org.gradle.plugins.ide.api.XmlFileContentMerger
import org.gradle.plugins.ide.eclipse.internal.EclipseNameDeduper
@@ -35,8 +35,6 @@ import javax.inject.Inject
/**
* <p>A plugin which generates Eclipse files.</p>
- *
- * @author Hans Dockter
*/
class EclipsePlugin extends IdePlugin {
static final String ECLIPSE_TASK_NAME = "eclipse"
@@ -178,7 +176,7 @@ class EclipsePlugin extends IdePlugin {
private void maybeAddTask(Project project, IdePlugin plugin, String taskName, Class taskType, Closure action) {
if (project.tasks.findByName(taskName)) { return }
- def task = project.tasks.add(taskName, taskType)
+ def task = project.tasks.create(taskName, taskType)
project.configure(task, action)
plugin.addWorker(task)
}
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/EclipseWtpPlugin.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/EclipseWtpPlugin.groovy
index 373d7e4..a05c003 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/EclipseWtpPlugin.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/EclipseWtpPlugin.groovy
@@ -19,19 +19,16 @@ package org.gradle.plugins.ide.eclipse
import org.gradle.api.JavaVersion
import org.gradle.api.Project
import org.gradle.api.artifacts.ProjectDependency
-import org.gradle.internal.reflect.Instantiator
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.plugins.WarPlugin
+import org.gradle.internal.reflect.Instantiator
import org.gradle.plugins.ear.EarPlugin
+import org.gradle.plugins.ide.eclipse.model.*
import org.gradle.plugins.ide.eclipse.model.Facet.FacetType
import org.gradle.plugins.ide.internal.IdePlugin
-import org.gradle.plugins.ide.eclipse.model.*
import javax.inject.Inject
-/**
- * @author: Szczepan Faber, created at: 6/28/11
- */
class EclipseWtpPlugin extends IdePlugin {
static final String ECLIPSE_WTP_COMPONENT_TASK_NAME = "eclipseWtpComponent"
@@ -213,7 +210,7 @@ class EclipseWtpPlugin extends IdePlugin {
private void maybeAddTask(Project project, IdePlugin plugin, String taskName, Class taskType, Closure action) {
if (project.tasks.findByName(taskName)) { return }
- def task = project.tasks.add(taskName, taskType)
+ def task = project.tasks.create(taskName, taskType)
project.configure(task, action)
plugin.addWorker(task)
}
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/GenerateEclipseClasspath.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/GenerateEclipseClasspath.groovy
index 020c7b2..ba77fd3 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/GenerateEclipseClasspath.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/GenerateEclipseClasspath.groovy
@@ -26,8 +26,6 @@ import org.gradle.util.DeprecationLogger
* Generates an Eclipse <code>.classpath</code> file. If you want to fine tune the eclipse configuration
* <p>
* At this moment nearly all configuration is done via {@link EclipseClasspath}.
- *
- * @author Hans Dockter
*/
class GenerateEclipseClasspath extends XmlGeneratorTask<Classpath> {
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/GenerateEclipseProject.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/GenerateEclipseProject.groovy
index 784f13b..cc1992f 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/GenerateEclipseProject.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/GenerateEclipseProject.groovy
@@ -25,8 +25,6 @@ import org.gradle.plugins.ide.eclipse.model.Project
* Generates an Eclipse <code>.project</code> file. If you want to fine tune the eclipse configuration
* <p>
* At this moment nearly all configuration is done via {@link EclipseProject}.
- *
- * @author Hans Dockter
*/
class GenerateEclipseProject extends XmlGeneratorTask<Project> {
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/GenerateEclipseWtpComponent.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/GenerateEclipseWtpComponent.groovy
index 4afadc0..5632f4c 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/GenerateEclipseWtpComponent.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/GenerateEclipseWtpComponent.groovy
@@ -30,8 +30,6 @@ import org.gradle.util.DeprecationLogger
* If you want to fine tune the eclipse configuration
* <p>
* At this moment nearly all configuration is done via {@link EclipseWtpComponent}.
- *
- * @author Hans Dockter
*/
class GenerateEclipseWtpComponent extends XmlGeneratorTask<WtpComponent> {
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/GenerateEclipseWtpFacet.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/GenerateEclipseWtpFacet.groovy
index e45956e..8adf9ef 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/GenerateEclipseWtpFacet.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/GenerateEclipseWtpFacet.groovy
@@ -26,8 +26,6 @@ import org.gradle.plugins.ide.eclipse.model.WtpFacet
* If you want to fine tune the eclipse configuration
* <p>
* At this moment nearly all configuration is done via {@link EclipseWtpFacet}.
- *
- * @author Hans Dockter
*/
class GenerateEclipseWtpFacet extends XmlGeneratorTask<WtpFacet> {
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/internal/EclipseNameDeduper.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/internal/EclipseNameDeduper.groovy
index 6907897..424339a 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/internal/EclipseNameDeduper.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/internal/EclipseNameDeduper.groovy
@@ -20,9 +20,6 @@ import org.gradle.plugins.ide.eclipse.EclipsePlugin
import org.gradle.plugins.ide.internal.configurer.DeduplicationTarget
import org.gradle.plugins.ide.internal.configurer.ProjectDeduper
-/**
- * @author Szczepan Faber, @date 11.03.11
- */
class EclipseNameDeduper {
void configureRoot(Project rootProject) {
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/internal/LinkedResourcesCreator.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/internal/LinkedResourcesCreator.groovy
index 017c677..55fc3b7 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/internal/LinkedResourcesCreator.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/internal/LinkedResourcesCreator.groovy
@@ -16,13 +16,10 @@
package org.gradle.plugins.ide.eclipse.internal
+import org.gradle.api.Project
import org.gradle.plugins.ide.eclipse.model.Link
import org.gradle.plugins.ide.eclipse.model.internal.SourceFoldersCreator
-import org.gradle.api.Project
-/**
- * @author: Szczepan Faber, created at: 4/22/11
- */
class LinkedResourcesCreator {
Set<Link> links(Project project) {
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/AbstractClasspathEntry.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/AbstractClasspathEntry.groovy
index 1c12689..be6b334 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/AbstractClasspathEntry.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/AbstractClasspathEntry.groovy
@@ -17,9 +17,6 @@ package org.gradle.plugins.ide.eclipse.model
import org.gradle.plugins.ide.eclipse.model.internal.PathUtil
-/**
- * @author Hans Dockter
- */
// TODO: consider entryAttributes in equals, hashCode, and toString
abstract class AbstractClasspathEntry implements ClasspathEntry {
private static final String NATIVE_LIBRARY_ATTRIBUTE = 'org.eclipse.jdt.launching.CLASSPATH_ATTR_LIBRARY_PATH_ENTRY'
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/AbstractLibrary.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/AbstractLibrary.groovy
index 2bb9703..f19fad5 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/AbstractLibrary.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/AbstractLibrary.groovy
@@ -19,9 +19,6 @@ import org.gradle.api.Nullable
import org.gradle.api.artifacts.ModuleVersionIdentifier
import org.gradle.plugins.ide.eclipse.model.internal.FileReferenceFactory
-/**
- * @author Hans Dockter
- */
abstract class AbstractLibrary extends AbstractClasspathEntry {
FileReference sourcePath
FileReference javadocPath
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/AccessRule.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/AccessRule.groovy
index 39068cb..edaa202 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/AccessRule.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/AccessRule.groovy
@@ -15,9 +15,6 @@
*/
package org.gradle.plugins.ide.eclipse.model
-/**
- * @author Hans Dockter
- */
class AccessRule {
String kind
String pattern
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/BuildCommand.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/BuildCommand.groovy
index f84cde8..5ac290a 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/BuildCommand.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/BuildCommand.groovy
@@ -15,9 +15,6 @@
*/
package org.gradle.plugins.ide.eclipse.model
-/**
- * @author Hans Dockter
- */
class BuildCommand implements Serializable {
String name
Map arguments
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/Classpath.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/Classpath.groovy
index eac13e8..40f5993 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/Classpath.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/Classpath.groovy
@@ -16,13 +16,11 @@
package org.gradle.plugins.ide.eclipse.model
import org.gradle.api.internal.xml.XmlTransformer
-import org.gradle.plugins.ide.internal.generator.XmlPersistableConfigurationObject
import org.gradle.plugins.ide.eclipse.model.internal.FileReferenceFactory
+import org.gradle.plugins.ide.internal.generator.XmlPersistableConfigurationObject
/**
* Represents the customizable elements of an eclipse classpath file. (via XML hooks everything is customizable).
- *
- * @author Hans Dockter
*/
class Classpath extends XmlPersistableConfigurationObject {
private final FileReferenceFactory fileReferenceFactory
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/ClasspathEntry.java b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/ClasspathEntry.java
index e4349b2..f569847 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/ClasspathEntry.java
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/ClasspathEntry.java
@@ -19,8 +19,6 @@ import groovy.util.Node;
/**
* Represents an entry in the Eclipse classpath.
- *
- * @author Hans Dockter
*/
public interface ClasspathEntry {
String getKind();
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/Container.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/Container.groovy
index 2bd8c7e..c8a4f2b 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/Container.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/Container.groovy
@@ -15,9 +15,6 @@
*/
package org.gradle.plugins.ide.eclipse.model
-/**
- * @author Hans Dockter
- */
class Container extends AbstractClasspathEntry {
Container(Node node) {
super(node)
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/EclipseClasspath.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/EclipseClasspath.groovy
index d8abbe3..4e92eb3 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/EclipseClasspath.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/EclipseClasspath.groovy
@@ -82,7 +82,7 @@ import org.gradle.util.ConfigureUtil
* eclipse {
* classpath {
* file {
- * //if you want to mess with the resulting xml in whatever way you fancy
+ * //if you want to mess with the resulting XML in whatever way you fancy
* withXml {
* def node = it.asNode()
* node.appendNode('xml', 'is what I love')
@@ -103,8 +103,6 @@ import org.gradle.util.ConfigureUtil
* }
* }
* </pre>
- *
- * @author Szczepan Faber, created at: 4/16/11
*/
class EclipseClasspath {
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/EclipseDomainModel.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/EclipseDomainModel.groovy
index 0e2ecce..8390c05 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/EclipseDomainModel.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/EclipseDomainModel.groovy
@@ -18,8 +18,6 @@ package org.gradle.plugins.ide.eclipse.model
/**
* For now, we only need the Project. However this class will contain more domain objects soon.
- *
- * @author Szczepan Faber, @date: 17.03.11
*/
class EclipseDomainModel {
Project project
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/EclipseJdt.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/EclipseJdt.groovy
index b6f81f1..df89f78 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/EclipseJdt.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/EclipseJdt.groovy
@@ -53,8 +53,6 @@ import org.gradle.util.ConfigureUtil
* }
* }
* </pre>
- *
- * @author: Szczepan Faber, created at: 4/20/11
*/
class EclipseJdt {
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/EclipseModel.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/EclipseModel.groovy
index 5dd379b..618e54f 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/EclipseModel.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/EclipseModel.groovy
@@ -44,8 +44,6 @@ import org.gradle.util.ConfigureUtil
* </pre>
*
* More examples in docs for {@link EclipseProject}, {@link EclipseClasspath}, {@link EclipseWtp}
- *
- * @author: Szczepan Faber, created at: 4/13/11
*/
class EclipseModel {
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/EclipseProject.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/EclipseProject.groovy
index 7e5d2f3..1ead6ab 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/EclipseProject.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/EclipseProject.groovy
@@ -61,7 +61,7 @@ import org.gradle.util.ConfigureUtil
* }
* </pre>
*
- * For tackling edge cases users can perform advanced configuration on resulting xml file.
+ * For tackling edge cases users can perform advanced configuration on resulting XML file.
* It is also possible to affect the way eclipse plugin merges the existing configuration
* via beforeMerged and whenMerged closures.
* <p>
@@ -77,7 +77,7 @@ import org.gradle.util.ConfigureUtil
* project {
*
* file {
- * //if you want to mess with the resulting xml in whatever way you fancy
+ * //if you want to mess with the resulting XML in whatever way you fancy
* withXml {
* def node = it.asNode()
* node.appendNode('xml', 'is what I love')
@@ -99,8 +99,6 @@ import org.gradle.util.ConfigureUtil
* }
* }
* </pre>
- *
- * @author Szczepan Faber, created at: 4/13/11
*/
class EclipseProject {
@@ -235,7 +233,7 @@ class EclipseProject {
}
/**
- * Enables advanced configuration like tinkering with the output xml
+ * Enables advanced configuration like tinkering with the output XML
* or affecting the way existing .project content is merged with gradle build information
* <p>
* The object passed to whenMerged{} and beforeMerged{} closures is of type {@link Project}
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/EclipseWtp.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/EclipseWtp.groovy
index 8d65c5c..66a16b7 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/EclipseWtp.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/EclipseWtp.groovy
@@ -45,8 +45,6 @@ import org.gradle.util.ConfigureUtil
* }
*
* </pre>
- *
- * @author: Szczepan Faber, created at: 4/19/11
*/
class EclipseWtp {
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/EclipseWtpComponent.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/EclipseWtpComponent.groovy
index 6879b25..89c7680 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/EclipseWtpComponent.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/EclipseWtpComponent.groovy
@@ -73,7 +73,7 @@ import org.gradle.util.ConfigureUtil
* }
* </pre>
*
- * For tackling edge cases users can perform advanced configuration on resulting xml file.
+ * For tackling edge cases users can perform advanced configuration on resulting XML file.
* It is also possible to affect the way eclipse plugin merges the existing configuration
* via beforeMerged and whenMerged closures.
* <p>
@@ -91,7 +91,7 @@ import org.gradle.util.ConfigureUtil
* wtp {
* component {
* file {
- * //if you want to mess with the resulting xml in whatever way you fancy
+ * //if you want to mess with the resulting XML in whatever way you fancy
* withXml {
* def node = it.asNode()
* node.appendNode('xml', 'is what I love')
@@ -113,8 +113,6 @@ import org.gradle.util.ConfigureUtil
* }
* }
* </pre>
- *
- * @author: Szczepan Faber, created at: 4/20/11
*/
class EclipseWtpComponent {
@@ -229,7 +227,7 @@ class EclipseWtpComponent {
String libDeployPath = "/WEB-INF/lib"
/**
- * Enables advanced configuration like tinkering with the output xml
+ * Enables advanced configuration like tinkering with the output XML
* or affecting the way existing wtp component file content is merged with gradle build information
* <p>
* The object passed to whenMerged{} and beforeMerged{} closures is of type {@link WtpComponent}
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/EclipseWtpFacet.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/EclipseWtpFacet.groovy
index 3f9f327..2b51ce4 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/EclipseWtpFacet.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/EclipseWtpFacet.groovy
@@ -36,7 +36,7 @@ import org.gradle.util.ConfigureUtil
* facet name: 'someCoolFacet', version: '1.3'
*
* file {
- * //if you want to mess with the resulting xml in whatever way you fancy
+ * //if you want to mess with the resulting XML in whatever way you fancy
* withXml {
* def node = it.asNode()
* node.appendNode('xml', 'is what I love')
@@ -62,8 +62,6 @@ import org.gradle.util.ConfigureUtil
* }
*
* </pre>
- *
- * @author: Szczepan Faber, created at: 4/20/11
*/
class EclipseWtpFacet {
@@ -87,7 +85,7 @@ class EclipseWtpFacet {
}
/**
- * Enables advanced configuration like tinkering with the output xml
+ * Enables advanced configuration like tinkering with the output XML
* or affecting the way existing wtp facet file content is merged with gradle build information
* <p>
* The object passed to whenMerged{} and beforeMerged{} closures is of type {@link WtpFacet}
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/Facet.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/Facet.groovy
index facfc09..f028835 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/Facet.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/Facet.groovy
@@ -15,9 +15,6 @@
*/
package org.gradle.plugins.ide.eclipse.model
-/**
- * @author Hans Dockter
- */
class Facet {
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/Library.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/Library.groovy
index 55791f7..1e7b7d1 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/Library.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/Library.groovy
@@ -17,9 +17,6 @@ package org.gradle.plugins.ide.eclipse.model
import org.gradle.plugins.ide.eclipse.model.internal.FileReferenceFactory
-/**
- * @author Hans Dockter
- */
class Library extends AbstractLibrary {
Library(Node node, FileReferenceFactory fileReferenceFactory) {
super(node, fileReferenceFactory)
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/Link.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/Link.groovy
index a8e60b2..7b9fe1f 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/Link.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/Link.groovy
@@ -17,9 +17,6 @@ package org.gradle.plugins.ide.eclipse.model
import org.gradle.plugins.ide.eclipse.model.internal.PathUtil
-/**
- * @author Hans Dockter
- */
class Link {
String name
String type
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/Output.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/Output.groovy
index 5a1b22c..e738008 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/Output.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/Output.groovy
@@ -17,9 +17,6 @@ package org.gradle.plugins.ide.eclipse.model
import org.gradle.plugins.ide.eclipse.model.internal.PathUtil
-/**
- * @author Hans Dockter
- */
class Output implements ClasspathEntry {
String path
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/Project.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/Project.groovy
index 5247ab8..e43f0aa 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/Project.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/Project.groovy
@@ -20,8 +20,6 @@ import org.gradle.plugins.ide.internal.generator.XmlPersistableConfigurationObje
/**
* Represents the customizable elements of an eclipse project file. (via XML hooks everything is customizable).
- *
- * @author Hans Dockter
*/
class Project extends XmlPersistableConfigurationObject {
public static final String PROJECT_FILE_NAME = ".project";
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/ProjectDependency.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/ProjectDependency.groovy
index 8837062..a00df7c 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/ProjectDependency.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/ProjectDependency.groovy
@@ -15,9 +15,6 @@
*/
package org.gradle.plugins.ide.eclipse.model
-/**
- * @author Hans Dockter
- */
class ProjectDependency extends AbstractClasspathEntry {
String gradlePath
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/SourceFolder.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/SourceFolder.groovy
index 02cafa7..7beef2d 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/SourceFolder.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/SourceFolder.groovy
@@ -17,8 +17,6 @@ package org.gradle.plugins.ide.eclipse.model
/**
* SourceFolder.path contains only project relative path.
- *
- * @author Hans Dockter
*/
class SourceFolder extends AbstractClasspathEntry {
String output
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/Variable.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/Variable.groovy
index f2d2965..b1498a0 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/Variable.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/Variable.groovy
@@ -17,9 +17,6 @@ package org.gradle.plugins.ide.eclipse.model
import org.gradle.plugins.ide.eclipse.model.internal.FileReferenceFactory
-/**
- * @author Hans Dockter
- */
class Variable extends AbstractLibrary {
Variable(Node node, FileReferenceFactory fileReferenceFactory) {
super(node, fileReferenceFactory)
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/WbDependentModule.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/WbDependentModule.groovy
index 48077b6..01e21fd 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/WbDependentModule.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/WbDependentModule.groovy
@@ -17,9 +17,6 @@ package org.gradle.plugins.ide.eclipse.model
import org.gradle.plugins.ide.eclipse.model.internal.PathUtil
-/**
- * @author Hans Dockter
- */
class WbDependentModule {
String deployPath
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/WbProperty.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/WbProperty.groovy
index 8a44f01..680d3e9 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/WbProperty.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/WbProperty.groovy
@@ -15,9 +15,6 @@
*/
package org.gradle.plugins.ide.eclipse.model
-/**
- * @author Hans Dockter
- */
class WbProperty {
String name
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/WbResource.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/WbResource.groovy
index baa3ced..d117594 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/WbResource.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/WbResource.groovy
@@ -17,9 +17,6 @@ package org.gradle.plugins.ide.eclipse.model
import org.gradle.plugins.ide.eclipse.model.internal.PathUtil
-/**
- * @author Hans Dockter
- */
class WbResource {
String deployPath
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/WtpComponent.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/WtpComponent.groovy
index a4fd1e8..eb61741 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/WtpComponent.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/WtpComponent.groovy
@@ -20,8 +20,6 @@ import org.gradle.plugins.ide.internal.generator.XmlPersistableConfigurationObje
/**
* Creates the .settings/org.eclipse.wst.common.component file for WTP projects.
- *
- * @author Hans Dockter
*/
class WtpComponent extends XmlPersistableConfigurationObject {
String deployName
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/WtpFacet.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/WtpFacet.groovy
index ca5e285..0d4355d 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/WtpFacet.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/WtpFacet.groovy
@@ -20,8 +20,6 @@ import org.gradle.plugins.ide.internal.generator.XmlPersistableConfigurationObje
/**
* Creates the .settings/org.eclipse.wst.common.project.facet.core.xml file for WTP projects.
- *
- * @author Hans Dockter
*/
class WtpFacet extends XmlPersistableConfigurationObject {
List facets = [] // TODO: turn into Set?
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/internal/ClassFoldersCreator.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/internal/ClassFoldersCreator.groovy
index 6df3a5b..99c6ff4 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/internal/ClassFoldersCreator.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/internal/ClassFoldersCreator.groovy
@@ -21,8 +21,6 @@ import org.gradle.plugins.ide.eclipse.model.Library
/**
* Eclipse calls them 'class folders' on java build path->libraries tab
- *
- * @author: Szczepan Faber, created at: 5/6/11
*/
class ClassFoldersCreator {
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/internal/ClasspathFactory.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/internal/ClasspathFactory.groovy
index 8b53c6c..3dcf6b4 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/internal/ClasspathFactory.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/internal/ClasspathFactory.groovy
@@ -16,15 +16,12 @@
package org.gradle.plugins.ide.eclipse.model.internal
import org.gradle.api.artifacts.ModuleVersionIdentifier
+import org.gradle.plugins.ide.eclipse.model.*
import org.gradle.plugins.ide.internal.IdeDependenciesExtractor
import org.gradle.plugins.ide.internal.IdeDependenciesExtractor.IdeLocalFileDependency
import org.gradle.plugins.ide.internal.IdeDependenciesExtractor.IdeProjectDependency
import org.gradle.plugins.ide.internal.IdeDependenciesExtractor.IdeRepoFileDependency
-import org.gradle.plugins.ide.eclipse.model.*
-/**
- * @author Hans Dockter
- */
class ClasspathFactory {
private final ClasspathEntryBuilder outputCreator = new ClasspathEntryBuilder() {
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/internal/ExportedEntriesUpdater.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/internal/ExportedEntriesUpdater.groovy
index c626e02..465200d 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/internal/ExportedEntriesUpdater.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/internal/ExportedEntriesUpdater.groovy
@@ -20,9 +20,6 @@ import org.gradle.plugins.ide.eclipse.model.AbstractLibrary
import org.gradle.plugins.ide.eclipse.model.ClasspathEntry
import org.gradle.plugins.ide.eclipse.model.ProjectDependency
-/**
- * @author: Szczepan Faber, created at: 7/4/11
- */
class ExportedEntriesUpdater {
void updateExported(List<ClasspathEntry> classpathEntries, List<String> noExportConfigNames) {
classpathEntries.each {
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/internal/PathUtil.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/internal/PathUtil.groovy
index edccbb3..c18a65f 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/internal/PathUtil.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/internal/PathUtil.groovy
@@ -17,9 +17,6 @@ package org.gradle.plugins.ide.eclipse.model.internal
import org.apache.commons.io.FilenameUtils
-/**
- * @author Hans Dockter
- */
class PathUtil {
static String normalizePath(String path) {
FilenameUtils.separatorsToUnix(path)
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/internal/ProjectDependencyBuilder.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/internal/ProjectDependencyBuilder.groovy
index b242a39..cb66486 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/internal/ProjectDependencyBuilder.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/internal/ProjectDependencyBuilder.groovy
@@ -19,9 +19,6 @@ import org.gradle.api.Project
import org.gradle.plugins.ide.eclipse.EclipsePlugin
import org.gradle.plugins.ide.eclipse.model.ProjectDependency
-/**
- * @author Szczepan Faber, @date: 11.03.11
- */
class ProjectDependencyBuilder {
ProjectDependency build(Project project, String declaredConfigurationName) {
def name
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/internal/SourceFoldersCreator.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/internal/SourceFoldersCreator.groovy
index 83d5f28..114036f 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/internal/SourceFoldersCreator.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/internal/SourceFoldersCreator.groovy
@@ -22,9 +22,6 @@ import org.gradle.plugins.ide.eclipse.model.ClasspathEntry
import org.gradle.plugins.ide.eclipse.model.EclipseClasspath
import org.gradle.plugins.ide.eclipse.model.SourceFolder
-/**
- * @author: Szczepan Faber, created at: 4/22/11
- */
class SourceFoldersCreator {
void populateForClasspath(List<ClasspathEntry> entries, EclipseClasspath classpath) {
def provideRelativePath = { classpath.project.relativePath(it) }
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/internal/WtpComponentFactory.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/internal/WtpComponentFactory.groovy
index 6e061fd..933a57a 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/internal/WtpComponentFactory.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/eclipse/model/internal/WtpComponentFactory.groovy
@@ -23,9 +23,6 @@ import org.gradle.plugins.ide.eclipse.model.WbResource
import org.gradle.plugins.ide.eclipse.model.WtpComponent
import org.gradle.plugins.ide.internal.IdeDependenciesExtractor
-/**
- * @author Hans Dockter
- */
class WtpComponentFactory {
void configure(EclipseWtpComponent wtp, WtpComponent component) {
def entries = getEntriesFromSourceDirs(wtp)
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/GenerateIdeaModule.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/GenerateIdeaModule.groovy
index e6e8efa..6205f28 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/GenerateIdeaModule.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/GenerateIdeaModule.groovy
@@ -25,8 +25,6 @@ import org.gradle.plugins.ide.idea.model.Module
* Please refer to interesting examples on idea configuration in {@link IdeaModule}.
* <p>
* At this moment nearly all configuration is done via {@link IdeaModule}.
- *
- * @author Hans Dockter
*/
public class GenerateIdeaModule extends XmlGeneratorTask<Module> {
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/GenerateIdeaProject.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/GenerateIdeaProject.groovy
index 754e039..c10348a 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/GenerateIdeaProject.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/GenerateIdeaProject.groovy
@@ -23,8 +23,6 @@ import org.gradle.plugins.ide.idea.model.Project
* Generates an IDEA project file for root project *only*. If you want to fine tune the idea configuration
* <p>
* At this moment nearly all configuration is done via {@link IdeaProject}.
- *
- * @author Hans Dockter
*/
public class GenerateIdeaProject extends XmlGeneratorTask<Project> {
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/GenerateIdeaWorkspace.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/GenerateIdeaWorkspace.groovy
index 0a146ec..f9c5de5 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/GenerateIdeaWorkspace.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/GenerateIdeaWorkspace.groovy
@@ -22,8 +22,6 @@ import org.gradle.plugins.ide.idea.model.Workspace
/**
* Generates an IDEA workspace file *only* for root project.
* There's little you can configure about workspace generation at the moment.
- *
- * @author Hans Dockter
*/
public class GenerateIdeaWorkspace extends XmlGeneratorTask<Workspace> {
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/IdeaPlugin.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/IdeaPlugin.groovy
index 46ed86a..179cc83 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/IdeaPlugin.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/IdeaPlugin.groovy
@@ -18,20 +18,19 @@ package org.gradle.plugins.ide.idea
import org.gradle.api.JavaVersion
import org.gradle.api.Project
import org.gradle.api.plugins.JavaPlugin
+import org.gradle.api.plugins.scala.ScalaBasePlugin
import org.gradle.internal.reflect.Instantiator
import org.gradle.plugins.ide.api.XmlFileContentMerger
import org.gradle.plugins.ide.idea.internal.IdeaNameDeduper
import org.gradle.plugins.ide.idea.internal.IdeaScalaConfigurer
-import org.gradle.plugins.ide.internal.IdePlugin
import org.gradle.plugins.ide.idea.model.*
+import org.gradle.plugins.ide.internal.IdePlugin
import javax.inject.Inject
/**
* Adds a GenerateIdeaModule task. When applied to a root project, also adds a GenerateIdeaProject task.
* For projects that have the Java plugin applied, the tasks receive additional Java-specific configuration.
- *
- * @author Hans Dockter
*/
class IdeaPlugin extends IdePlugin {
private final Instantiator instantiator
@@ -173,6 +172,10 @@ class IdeaPlugin extends IdePlugin {
}
private void configureForScalaPlugin() {
+ project.plugins.withType(ScalaBasePlugin) {
+ //see IdeaScalaConfigurer
+ project.tasks.ideaModule.dependsOn(project.rootProject.tasks.ideaProject)
+ }
if (isRoot(project)) {
new IdeaScalaConfigurer(project).configure()
}
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/internal/IdeaNameDeduper.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/internal/IdeaNameDeduper.groovy
index c7d3a1b..f28f0b7 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/internal/IdeaNameDeduper.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/internal/IdeaNameDeduper.groovy
@@ -20,9 +20,6 @@ import org.gradle.plugins.ide.idea.IdeaPlugin
import org.gradle.plugins.ide.internal.configurer.DeduplicationTarget
import org.gradle.plugins.ide.internal.configurer.ProjectDeduper
-/**
- * @author Szczepan Faber, @date 03.03.11
- */
class IdeaNameDeduper {
void configureRoot(Project rootProject) {
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/internal/IdeaScalaConfigurer.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/internal/IdeaScalaConfigurer.groovy
index 84f77bf..a155c55 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/internal/IdeaScalaConfigurer.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/internal/IdeaScalaConfigurer.groovy
@@ -34,11 +34,10 @@ class IdeaScalaConfigurer {
void configure() {
rootProject.gradle.projectsEvaluated {
def scalaProjects = findProjectsApplyingIdeaAndScalaPlugins()
- scalaProjects.tasks.ideaModule*.dependsOn(rootProject.tasks.ideaProject)
Map<String, ProjectLibrary> scalaCompilerLibraries = [:]
rootProject.ideaProject.doFirst {
- scalaCompilerLibraries = resolveScalaCompilerLibraries(project, scalaProjects)
+ scalaCompilerLibraries = resolveScalaCompilerLibraries(scalaProjects)
declareUniqueProjectLibraries(scalaCompilerLibraries.values() as Set)
}
@@ -50,11 +49,10 @@ class IdeaScalaConfigurer {
}
}
- private Map<String, ProjectLibrary> resolveScalaCompilerLibraries(Project rootProject, Collection<Project> scalaProjects) {
+ private Map<String, ProjectLibrary> resolveScalaCompilerLibraries(Collection<Project> scalaProjects) {
def scalaCompilerLibraries = [:]
for (scalaProject in scalaProjects) {
- def scalaPlugin = scalaProject.plugins.getPlugin(ScalaBasePlugin)
IdeaModule ideaModule = scalaProject.idea.module
// could make resolveDependencies() cache its result for later use by GenerateIdeaModule
@@ -63,9 +61,10 @@ class IdeaScalaConfigurer {
def filePaths = moduleLibraries.collectMany { it.classes.findAll { it instanceof FilePath } }
def files = filePaths.collect { it.file }
- def scalaClasspath = scalaPlugin.inferScalaCompilerClasspath(files)
- def compilerJar = scalaPlugin.findScalaJar(scalaClasspath, "compiler")
- def version = compilerJar == null ? "?" : scalaPlugin.getScalaVersion(compilerJar)
+ def runtime = scalaProject.scalaRuntime
+ def scalaClasspath = runtime.inferScalaClasspath(files)
+ def compilerJar = runtime.findScalaJar(scalaClasspath, "compiler")
+ def version = compilerJar == null ? "?" : runtime.getScalaVersion(compilerJar)
def library = createProjectLibrary("scala-compiler-$version", scalaClasspath)
def duplicate = scalaCompilerLibraries.values().find { it.classes == library.classes }
scalaCompilerLibraries[scalaProject.path] = duplicate ?: library
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/Dependency.java b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/Dependency.java
index 87442ba..a3cbf58 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/Dependency.java
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/Dependency.java
@@ -19,8 +19,6 @@ import groovy.util.Node;
/**
* Represents a dependency of an IDEA module.
- *
- * @author Hans Dockter
*/
public interface Dependency {
void addToNode(Node parentNode);
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/IdeaLanguageLevel.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/IdeaLanguageLevel.groovy
index 9cb1b9f..3d8b7a2 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/IdeaLanguageLevel.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/IdeaLanguageLevel.groovy
@@ -20,8 +20,6 @@ import org.gradle.api.JavaVersion
/**
* Java language level used by IDEA projects.
- *
- * @author: Szczepan Faber, created at: 7/14/11
*/
class IdeaLanguageLevel {
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/IdeaModel.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/IdeaModel.groovy
index 87eb0dc..16cd629 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/IdeaModel.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/IdeaModel.groovy
@@ -24,7 +24,6 @@ import org.gradle.util.ConfigureUtil
* <p>
* See the examples in docs for {@link IdeaModule} or {@link IdeaProject}.
* <p>
- * @author Szczepan Faber, created at: 3/31/11
*/
class IdeaModel {
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/IdeaModule.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/IdeaModule.groovy
index 5170bc6..063abb5 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/IdeaModule.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/IdeaModule.groovy
@@ -82,7 +82,7 @@ import org.gradle.util.ConfigureUtil
* }
* </pre>
*
- * For tackling edge cases users can perform advanced configuration on resulting xml file.
+ * For tackling edge cases users can perform advanced configuration on resulting XML file.
* It is also possible to affect the way the IDEA plugin merges the existing configuration
* via beforeMerged and whenMerged closures.
* <p>
@@ -100,7 +100,7 @@ import org.gradle.util.ConfigureUtil
* //if you like to keep *.iml in a secret folder
* generateTo = file('secret-modules-folder')
*
- * //if you want to mess with the resulting xml in whatever way you fancy
+ * //if you want to mess with the resulting XML in whatever way you fancy
* withXml {
* def node = it.asNode()
* node.appendNode('iLoveGradle', 'true')
@@ -124,8 +124,6 @@ import org.gradle.util.ConfigureUtil
* }
*
* </pre>
- *
- * @author Szczepan Faber, created at: 3/31/11
*/
class IdeaModule {
@@ -268,7 +266,7 @@ class IdeaModule {
final IdeaModuleIml iml
/**
- * Enables advanced configuration like tinkering with the output xml
+ * Enables advanced configuration like tinkering with the output XML
* or affecting the way existing *.iml content is merged with gradle build information.
* <p>
* For example see docs for {@link IdeaModule}.
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/IdeaModuleIml.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/IdeaModuleIml.groovy
index b74914d..8da5886 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/IdeaModuleIml.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/IdeaModuleIml.groovy
@@ -23,8 +23,6 @@ import org.gradle.plugins.ide.api.XmlFileContentMerger
* Models the generation/parsing/merging capabilities of an IDEA module.
* <p>
* For examples, see docs for {@link IdeaModule}.
- *
- * @author: Szczepan Faber, created at: 4/5/11
*/
class IdeaModuleIml extends XmlFileContentMerger {
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/IdeaProject.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/IdeaProject.groovy
index b4bf3fb..39d456f 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/IdeaProject.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/IdeaProject.groovy
@@ -53,7 +53,7 @@ import org.gradle.util.ConfigureUtil
* }
* </pre>
*
- * For tackling edge cases users can perform advanced configuration on resulting xml file.
+ * For tackling edge cases users can perform advanced configuration on resulting XML file.
* It is also possible to affect the way IDEA plugin merges the existing configuration
* via beforeMerged and whenMerged closures.
* <p>
@@ -89,8 +89,6 @@ import org.gradle.util.ConfigureUtil
* }
* }
* </pre>
- *
- * @author Szczepan Faber, created at: 4/4/11
*/
class IdeaProject {
@@ -149,7 +147,7 @@ class IdeaProject {
}
/**
- * Enables advanced configuration like tinkering with the output xml
+ * Enables advanced configuration like tinkering with the output XML
* or affecting the way existing *.ipr content is merged with Gradle build information.
* <p>
* See the examples in the docs for {@link IdeaProject}
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/IdeaWorkspace.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/IdeaWorkspace.groovy
index 98541e8..d9c9588 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/IdeaWorkspace.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/IdeaWorkspace.groovy
@@ -32,13 +32,11 @@ import org.gradle.util.ConfigureUtil
* provider.asNode().appendNode('gradleRocks', 'true')
* }
* </pre>
- *
- * @author Szczepan Faber, created at: 06/09/11
*/
class IdeaWorkspace {
/**
- * Enables advanced manipulation of the output xml.
+ * Enables advanced manipulation of the output XML.
* <p>
* For example see docs for {@link IdeaWorkspace}
*
@@ -49,7 +47,7 @@ class IdeaWorkspace {
}
/**
- * Enables advanced manipulation of the output xml.
+ * Enables advanced manipulation of the output XML.
* <p>
* For example see docs for {@link IdeaWorkspace}
*/
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/JarDirectory.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/JarDirectory.groovy
index 4719078..69f62b3 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/JarDirectory.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/JarDirectory.groovy
@@ -17,8 +17,6 @@ package org.gradle.plugins.ide.idea.model
/**
* Represents a jar directory element of an idea module library.
- *
- * @author Hans Dockter
*/
class JarDirectory {
/**
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/Jdk.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/Jdk.groovy
index b681913..3c11c20 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/Jdk.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/Jdk.groovy
@@ -18,8 +18,6 @@ package org.gradle.plugins.ide.idea.model
/**
* Represents information for the project Java SDK. This translates to attributes of the ProjectRootManager
* element in the ipr.
- *
- * @author Hans Dockter
*/
class Jdk {
boolean assertKeyword
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/Module.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/Module.groovy
index 19a0288..078a54b 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/Module.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/Module.groovy
@@ -21,8 +21,6 @@ import org.gradle.util.DeprecationLogger
/**
* Represents the customizable elements of an iml (via XML hooks everything of the iml is customizable).
- *
- * @author Hans Dockter
*/
class Module extends XmlPersistableConfigurationObject {
static final String INHERITED = "inherited"
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/ModuleDependency.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/ModuleDependency.groovy
index 7c56c10..6ce9fe0 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/ModuleDependency.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/ModuleDependency.groovy
@@ -16,9 +16,7 @@
package org.gradle.plugins.ide.idea.model
/**
- * Represents an orderEntry of type module in the iml xml.
- *
- * @author Hans Dockter
+ * Represents an orderEntry of type module in the iml XML.
*/
class ModuleDependency implements Dependency {
/**
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/ModuleLibrary.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/ModuleLibrary.groovy
index bf5d0f6..f6724cd 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/ModuleLibrary.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/ModuleLibrary.groovy
@@ -16,9 +16,7 @@
package org.gradle.plugins.ide.idea.model
/**
- * Represents an orderEntry of type module-library in the iml xml.
- *
- * @author Hans Dockter
+ * Represents an orderEntry of type module-library in the iml XML.
*/
class ModuleLibrary implements Dependency {
/**
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/Path.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/Path.groovy
index 25a03ae..3152312 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/Path.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/Path.groovy
@@ -17,8 +17,6 @@ package org.gradle.plugins.ide.idea.model
/**
* Represents a path in a format as used often in ipr and iml files.
- *
- * @author Hans Dockter
*/
class Path {
/**
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/Project.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/Project.groovy
index a4ce258..94eb950 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/Project.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/Project.groovy
@@ -21,8 +21,6 @@ import org.gradle.plugins.ide.internal.generator.XmlPersistableConfigurationObje
/**
* Represents the customizable elements of an ipr (via XML hooks everything of the ipr is customizable).
- *
- * @author Hans Dockter
*/
class Project extends XmlPersistableConfigurationObject {
/**
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/Workspace.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/Workspace.groovy
index a47f59c..db14efb 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/Workspace.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/Workspace.groovy
@@ -20,8 +20,6 @@ import org.gradle.plugins.ide.internal.generator.XmlPersistableConfigurationObje
/**
* Represents the customizable elements of an ipr (via XML hooks everything of the ipr is customizable).
- *
- * @author Hans Dockter
*/
class Workspace extends XmlPersistableConfigurationObject {
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/internal/IdeaDependenciesProvider.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/internal/IdeaDependenciesProvider.groovy
index 2044150..88ac1fd 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/internal/IdeaDependenciesProvider.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/internal/IdeaDependenciesProvider.groovy
@@ -21,9 +21,6 @@ import org.gradle.plugins.ide.idea.model.IdeaModule
import org.gradle.plugins.ide.idea.model.SingleEntryModuleLibrary
import org.gradle.plugins.ide.internal.IdeDependenciesExtractor
-/**
- * @author Szczepan Faber, created at: 4/1/11
- */
class IdeaDependenciesProvider {
private final IdeDependenciesExtractor dependenciesExtractor = new IdeDependenciesExtractor()
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/internal/ModuleDependencyBuilder.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/internal/ModuleDependencyBuilder.groovy
index 4930688..b7a6abf 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/internal/ModuleDependencyBuilder.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/idea/model/internal/ModuleDependencyBuilder.groovy
@@ -20,9 +20,6 @@ import org.gradle.api.Project
import org.gradle.plugins.ide.idea.IdeaPlugin
import org.gradle.plugins.ide.idea.model.ModuleDependency
-/**
- * @author Szczepan Faber, @date: 19.03.11
- */
class ModuleDependencyBuilder {
ModuleDependency create(Project project, String scope) {
if (project.plugins.hasPlugin(IdeaPlugin)) {
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/IdeDependenciesExtractor.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/IdeDependenciesExtractor.groovy
index beb65d7..ccb69e5 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/IdeDependenciesExtractor.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/IdeDependenciesExtractor.groovy
@@ -17,12 +17,9 @@
package org.gradle.plugins.ide.internal
import org.gradle.api.Project
-import org.gradle.api.specs.Spec
import org.gradle.api.artifacts.*
+import org.gradle.api.specs.Spec
-/**
- * @author: Szczepan Faber, created at: 7/1/11
- */
class IdeDependenciesExtractor {
static class IdeDependency {
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/IdePlugin.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/IdePlugin.groovy
index 12e0228..1d381ae 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/IdePlugin.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/IdePlugin.groovy
@@ -55,7 +55,7 @@ public abstract class IdePlugin implements Plugin<Project> {
protected void addWorker(Task worker, boolean includeInClean = true) {
lifecycleTask.dependsOn(worker)
- Delete cleanWorker = project.getTasks().add(cleanName(worker.getName()), Delete.class)
+ Delete cleanWorker = project.tasks.create(cleanName(worker.name), Delete.class)
cleanWorker.delete(worker.getOutputs().getFiles())
if (includeInClean) {
cleanTask.dependsOn(cleanWorker)
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/JavadocAndSourcesDownloader.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/JavadocAndSourcesDownloader.groovy
index e0e6d35..819a55c 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/JavadocAndSourcesDownloader.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/JavadocAndSourcesDownloader.groovy
@@ -16,18 +16,11 @@
package org.gradle.plugins.ide.internal
-import org.gradle.api.artifacts.Configuration
-import org.gradle.api.artifacts.Dependency
-import org.gradle.api.artifacts.ResolvedDependency
-import org.gradle.api.artifacts.ExternalDependency
-import org.gradle.api.specs.Spec
+import org.gradle.api.artifacts.*
import org.gradle.api.internal.artifacts.dependencies.DefaultExternalModuleDependency
+import org.gradle.api.specs.Spec
import org.gradle.api.specs.Specs
-import org.gradle.api.artifacts.ConfigurationContainer
-/**
- * by Szczepan Faber, created at: 1/25/13
- */
class JavadocAndSourcesDownloader {
private Map<String, File> sourceFiles
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/configurer/DeduplicationTarget.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/configurer/DeduplicationTarget.groovy
index 31fbe7a..504a381 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/configurer/DeduplicationTarget.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/configurer/DeduplicationTarget.groovy
@@ -18,9 +18,6 @@ package org.gradle.plugins.ide.internal.configurer
import org.gradle.api.Project
-/**
- * @author Szczepan Faber, @date: 14.03.11
- */
class DeduplicationTarget {
def String moduleName
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/configurer/ModuleNameDeduper.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/configurer/ModuleNameDeduper.groovy
index eba77bf..b0ead6b 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/configurer/ModuleNameDeduper.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/configurer/ModuleNameDeduper.groovy
@@ -18,7 +18,6 @@ package org.gradle.plugins.ide.internal.configurer
/**
* Able to deduplicate names. Useful for IDE plugins to make sure module names (IDEA) or project names (Eclipse) are unique.
* <p>
- * @author Szczepan Faber, @date 11.03.11
*/
class ModuleNameDeduper {
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/configurer/ProjectDeduper.groovy b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/configurer/ProjectDeduper.groovy
index fceb77f..68f6b01 100644
--- a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/configurer/ProjectDeduper.groovy
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/configurer/ProjectDeduper.groovy
@@ -18,9 +18,6 @@ package org.gradle.plugins.ide.internal.configurer
import org.gradle.api.Project
-/**
- * @author Szczepan Faber, @date: 14.03.11
- */
class ProjectDeduper {
def moduleNameDeduper = new ModuleNameDeduper()
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/BasicIdeaModelBuilder.java b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/BasicIdeaModelBuilder.java
new file mode 100644
index 0000000..14b3bdf
--- /dev/null
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/BasicIdeaModelBuilder.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.plugins.ide.internal.tooling;
+
+import org.gradle.api.Project;
+import org.gradle.plugins.ide.internal.tooling.idea.DefaultIdeaProject;
+import org.gradle.tooling.provider.model.ToolingModelBuilder;
+
+public class BasicIdeaModelBuilder implements ToolingModelBuilder {
+ public boolean canBuild(String modelName) {
+ return modelName.equals("org.gradle.tooling.model.idea.BasicIdeaProject");
+ }
+
+ public DefaultIdeaProject buildAll(String modelName, Project project) {
+ return new IdeaModelBuilder()
+ .setOfflineDependencyResolution(true)
+ .buildAll(modelName, project);
+ }
+}
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/EclipseModelBuilder.java b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/EclipseModelBuilder.java
new file mode 100644
index 0000000..5b0038e
--- /dev/null
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/EclipseModelBuilder.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.plugins.ide.internal.tooling;
+
+import org.apache.commons.lang.StringUtils;
+import org.gradle.api.Project;
+import org.gradle.api.Task;
+import org.gradle.plugins.ide.eclipse.EclipsePlugin;
+import org.gradle.plugins.ide.eclipse.model.*;
+import org.gradle.plugins.ide.internal.tooling.eclipse.*;
+import org.gradle.tooling.internal.gradle.DefaultGradleProject;
+import org.gradle.tooling.internal.protocol.ExternalDependencyVersion1;
+import org.gradle.tooling.internal.protocol.eclipse.EclipseProjectDependencyVersion2;
+import org.gradle.tooling.internal.protocol.eclipse.EclipseSourceDirectoryVersion1;
+import org.gradle.tooling.internal.protocol.eclipse.EclipseTaskVersion1;
+import org.gradle.tooling.provider.model.ToolingModelBuilder;
+import org.gradle.util.GUtil;
+
+import java.io.File;
+import java.util.*;
+
+public class EclipseModelBuilder implements ToolingModelBuilder {
+ private boolean projectDependenciesOnly;
+ private DefaultEclipseProject result;
+ private final Map<String, DefaultEclipseProject> projectMapping = new HashMap<String, DefaultEclipseProject>();
+ private TasksFactory tasksFactory;
+ private GradleProjectBuilder gradleProjectBuilder = new GradleProjectBuilder();
+ private DefaultGradleProject rootGradleProject;
+ private Project currentProject;
+
+ public boolean canBuild(String modelName) {
+ return modelName.equals("org.gradle.tooling.model.eclipse.EclipseProject")
+ || modelName.equals("org.gradle.tooling.model.eclipse.HierarchicalEclipseProject");
+ }
+
+ public DefaultEclipseProject buildAll(String modelName, Project project) {
+ boolean includeTasks = modelName.equals("org.gradle.tooling.model.eclipse.EclipseProject");
+ tasksFactory = new TasksFactory(includeTasks);
+ projectDependenciesOnly = modelName.equals("org.gradle.tooling.model.eclipse.HierarchicalEclipseProject");
+ currentProject = project;
+ Project root = project.getRootProject();
+ rootGradleProject = gradleProjectBuilder.buildAll(project);
+ tasksFactory.collectTasks(root);
+ applyEclipsePlugin(root);
+ buildHierarchy(root);
+ populate(root);
+ return result;
+ }
+
+ private void applyEclipsePlugin(Project root) {
+ Set<Project> allProjects = root.getAllprojects();
+ for (Project p : allProjects) {
+ p.getPlugins().apply(EclipsePlugin.class);
+ }
+ root.getPlugins().getPlugin(EclipsePlugin.class).makeSureProjectNamesAreUnique();
+ }
+
+ private void addProject(Project project, DefaultEclipseProject eclipseProject) {
+ if (project == currentProject) {
+ result = eclipseProject;
+ }
+ projectMapping.put(project.getPath(), eclipseProject);
+ }
+
+ private void populate(Project project) {
+ EclipseModel eclipseModel = project.getPlugins().getPlugin(EclipsePlugin.class).getModel();
+ EclipseClasspath classpath = eclipseModel.getClasspath();
+
+ classpath.setProjectDependenciesOnly(projectDependenciesOnly);
+ List<ClasspathEntry> entries = classpath.resolveDependencies();
+
+ final List<ExternalDependencyVersion1> externalDependencies = new LinkedList<ExternalDependencyVersion1>();
+ final List<EclipseProjectDependencyVersion2> projectDependencies = new LinkedList<EclipseProjectDependencyVersion2>();
+ final List<EclipseSourceDirectoryVersion1> sourceDirectories = new LinkedList<EclipseSourceDirectoryVersion1>();
+
+ for (ClasspathEntry entry : entries) {
+ //we don't handle Variables at the moment because users didn't request it yet
+ //and it would probably push us to add support in the tooling api to retrieve the variable mappings.
+ if (entry instanceof Library) {
+ AbstractLibrary library = (AbstractLibrary) entry;
+ final File file = library.getLibrary().getFile();
+ final File source = library.getSourcePath() == null ? null : library.getSourcePath().getFile();
+ final File javadoc = library.getJavadocPath() == null ? null : library.getJavadocPath().getFile();
+ externalDependencies.add(new DefaultEclipseExternalDependency(file, javadoc, source, library.getModuleVersion()));
+ } else if (entry instanceof ProjectDependency) {
+ final ProjectDependency projectDependency = (ProjectDependency) entry;
+ final String path = StringUtils.removeStart(projectDependency.getPath(), "/");
+ projectDependencies.add(new DefaultEclipseProjectDependency(path, projectMapping.get(projectDependency.getGradlePath())));
+ } else if (entry instanceof SourceFolder) {
+ String path = ((SourceFolder) entry).getPath();
+ sourceDirectories.add(new DefaultEclipseSourceDirectory(path, project.file(path)));
+ }
+ }
+
+ DefaultEclipseProject eclipseProject = projectMapping.get(project.getPath());
+ eclipseProject.setClasspath(externalDependencies);
+ eclipseProject.setProjectDependencies(projectDependencies);
+ eclipseProject.setSourceDirectories(sourceDirectories);
+
+ List<DefaultEclipseLinkedResource> linkedResources = new LinkedList<DefaultEclipseLinkedResource>();
+ for(Link r: eclipseModel.getProject().getLinkedResources()) {
+ linkedResources.add(new DefaultEclipseLinkedResource(r.getName(), r.getType(), r.getLocation(), r.getLocationUri()));
+ }
+ eclipseProject.setLinkedResources(linkedResources);
+
+ List<EclipseTaskVersion1> tasks = new ArrayList<EclipseTaskVersion1>();
+ for (final Task t : tasksFactory.getTasks(project)) {
+ tasks.add(new DefaultEclipseTask(eclipseProject, t.getPath(), t.getName(), t.getDescription()));
+ }
+ eclipseProject.setTasks(tasks);
+
+ for (Project childProject : project.getChildProjects().values()) {
+ populate(childProject);
+ }
+ }
+
+ private DefaultEclipseProject buildHierarchy(Project project) {
+ List<DefaultEclipseProject> children = new ArrayList<DefaultEclipseProject>();
+ for (Project child : project.getChildProjects().values()) {
+ children.add(buildHierarchy(child));
+ }
+
+ EclipseModel eclipseModel = project.getPlugins().getPlugin(EclipsePlugin.class).getModel();
+ org.gradle.plugins.ide.eclipse.model.EclipseProject internalProject = eclipseModel.getProject();
+ String name = internalProject.getName();
+ String description = GUtil.elvis(internalProject.getComment(), null);
+ DefaultEclipseProject eclipseProject =
+ new DefaultEclipseProject(name, project.getPath(), description, project.getProjectDir(), children)
+ .setGradleProject(rootGradleProject.findByPath(project.getPath()));
+
+ for (DefaultEclipseProject child : children) {
+ child.setParent(eclipseProject);
+ }
+ addProject(project, eclipseProject);
+ return eclipseProject;
+ }
+}
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/GradleBuildBuilder.java b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/GradleBuildBuilder.java
new file mode 100644
index 0000000..bc9a10d
--- /dev/null
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/GradleBuildBuilder.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.plugins.ide.internal.tooling;
+
+import org.gradle.api.Project;
+import org.gradle.tooling.internal.gradle.BasicGradleProject;
+import org.gradle.tooling.internal.gradle.DefaultGradleBuild;
+import org.gradle.tooling.provider.model.ToolingModelBuilder;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+public class GradleBuildBuilder implements ToolingModelBuilder {
+ public boolean canBuild(String modelName) {
+ return modelName.equals("org.gradle.tooling.model.gradle.GradleBuild");
+ }
+
+ public DefaultGradleBuild buildAll(String modelName, Project target) {
+ Map<Project, BasicGradleProject> convertedProjects = new LinkedHashMap<Project, BasicGradleProject>();
+ BasicGradleProject rootProject = convert(target.getRootProject(), convertedProjects);
+ DefaultGradleBuild model = new DefaultGradleBuild().setRootProject(rootProject);
+ for (Project project : target.getRootProject().getAllprojects()) {
+ model.addProject(convertedProjects.get(project));
+ }
+ return model;
+ }
+
+ private BasicGradleProject convert(Project project, Map<Project, BasicGradleProject> convertedProjects) {
+ BasicGradleProject converted = new BasicGradleProject().setName(project.getName()).setPath(project.getPath());
+ converted.setProjectDirectory(project.getProjectDir());
+ if (project.getParent() != null) {
+ converted.setParent(convertedProjects.get(project.getParent()));
+ }
+ convertedProjects.put(project, converted);
+ for (Project child : project.getChildProjects().values()) {
+ converted.addChild(convert(child, convertedProjects));
+ }
+ return converted;
+ }
+}
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/GradleProjectBuilder.java b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/GradleProjectBuilder.java
new file mode 100644
index 0000000..08b16a4
--- /dev/null
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/GradleProjectBuilder.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.plugins.ide.internal.tooling;
+
+import org.gradle.api.Project;
+import org.gradle.api.Task;
+import org.gradle.api.tasks.TaskContainer;
+import org.gradle.tooling.internal.gradle.DefaultGradleProject;
+import org.gradle.tooling.internal.gradle.DefaultGradleTask;
+import org.gradle.tooling.model.GradleTask;
+import org.gradle.tooling.provider.model.ToolingModelBuilder;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Builds the GradleProject that contains the project hierarchy and task information
+ */
+public class GradleProjectBuilder implements ToolingModelBuilder {
+ public boolean canBuild(String modelName) {
+ return modelName.equals("org.gradle.tooling.model.GradleProject");
+ }
+
+ public Object buildAll(String modelName, Project project) {
+ return buildHierarchy(project.getRootProject());
+ }
+
+ public DefaultGradleProject buildAll(Project project) {
+ return buildHierarchy(project.getRootProject());
+ }
+
+ private DefaultGradleProject buildHierarchy(Project project) {
+ List<DefaultGradleProject> children = new ArrayList<DefaultGradleProject>();
+ for (Project child : project.getChildProjects().values()) {
+ children.add(buildHierarchy(child));
+ }
+
+ DefaultGradleProject gradleProject = new DefaultGradleProject()
+ .setPath(project.getPath())
+ .setName(project.getName())
+ .setDescription(project.getDescription())
+ .setChildren(children);
+
+ gradleProject.getBuildScript().setSourceFile(project.getBuildFile());
+ gradleProject.setTasks(tasks(gradleProject, project.getTasks()));
+
+ for (DefaultGradleProject child : children) {
+ child.setParent(gradleProject);
+ }
+
+ return gradleProject;
+ }
+
+ private List<GradleTask> tasks(DefaultGradleProject owner, TaskContainer tasks) {
+ List<GradleTask> out = new LinkedList<GradleTask>();
+
+ for (Task t : tasks) {
+ out.add(new DefaultGradleTask()
+ .setPath(t.getPath())
+ .setName(t.getName())
+ .setDescription(t.getDescription())
+ .setProject(owner));
+ }
+
+ return out;
+ }
+}
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/IdeaModelBuilder.java b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/IdeaModelBuilder.java
new file mode 100644
index 0000000..8c52cd6
--- /dev/null
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/IdeaModelBuilder.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.plugins.ide.internal.tooling;
+
+import org.gradle.api.Project;
+import org.gradle.plugins.ide.idea.IdeaPlugin;
+import org.gradle.plugins.ide.idea.model.*;
+import org.gradle.plugins.ide.internal.tooling.idea.*;
+import org.gradle.tooling.internal.gradle.DefaultGradleModuleVersion;
+import org.gradle.tooling.model.GradleProject;
+import org.gradle.tooling.model.idea.IdeaSourceDirectory;
+import org.gradle.tooling.provider.model.ToolingModelBuilder;
+
+import java.io.File;
+import java.util.*;
+
+public class IdeaModelBuilder implements ToolingModelBuilder {
+ private final GradleProjectBuilder gradleProjectBuilder = new GradleProjectBuilder();
+ private boolean offlineDependencyResolution;
+
+ public boolean canBuild(String modelName) {
+ return modelName.equals("org.gradle.tooling.model.idea.IdeaProject");
+ }
+
+ public DefaultIdeaProject buildAll(String modelName, Project project) {
+ Project root = project.getRootProject();
+ applyIdeaPlugin(root);
+ GradleProject rootGradleProject = gradleProjectBuilder.buildAll(project);
+ return build(root, rootGradleProject);
+ }
+
+ private void applyIdeaPlugin(Project root) {
+ Set<Project> allProjects = root.getAllprojects();
+ for (Project p : allProjects) {
+ p.getPlugins().apply(IdeaPlugin.class);
+ }
+ root.getPlugins().getPlugin(IdeaPlugin.class).makeSureModuleNamesAreUnique();
+ }
+
+ private DefaultIdeaProject build(Project project, GradleProject rootGradleProject) {
+ IdeaModel ideaModel = project.getPlugins().getPlugin(IdeaPlugin.class).getModel();
+ IdeaProject projectModel = ideaModel.getProject();
+
+ DefaultIdeaProject out = new DefaultIdeaProject()
+ .setName(projectModel.getName())
+ .setJdkName(projectModel.getJdkName())
+ .setLanguageLevel(new DefaultIdeaLanguageLevel(projectModel.getLanguageLevel().getLevel()));
+
+ Map<String, DefaultIdeaModule> modules = new HashMap<String, DefaultIdeaModule>();
+ for (IdeaModule module : projectModel.getModules()) {
+ appendModule(modules, module, out, rootGradleProject);
+ }
+ for (IdeaModule module : projectModel.getModules()) {
+ buildDependencies(modules, module);
+ }
+ out.setChildren(new LinkedList<DefaultIdeaModule>(modules.values()));
+
+ return out;
+ }
+
+ private void buildDependencies(Map<String, DefaultIdeaModule> modules, IdeaModule ideaModule) {
+ ideaModule.setOffline(offlineDependencyResolution);
+ Set<Dependency> resolved = ideaModule.resolveDependencies();
+ List<DefaultIdeaDependency> dependencies = new LinkedList<DefaultIdeaDependency>();
+ for (Dependency dependency : resolved) {
+ if (dependency instanceof SingleEntryModuleLibrary) {
+ SingleEntryModuleLibrary d = (SingleEntryModuleLibrary) dependency;
+ DefaultIdeaSingleEntryLibraryDependency defaultDependency = new org.gradle.tooling.internal.idea.DefaultIdeaSingleEntryLibraryDependency()
+ .setFile(d.getLibraryFile())
+ .setSource(d.getSourceFile())
+ .setJavadoc(d.getJavadocFile())
+ .setScope(new DefaultIdeaDependencyScope(d.getScope()))
+ .setExported(d.getExported());
+
+ if (d.getModuleVersion() != null) {
+ defaultDependency.setGradleModuleVersion(new DefaultGradleModuleVersion(d.getModuleVersion()));
+ }
+ dependencies.add(defaultDependency);
+ } else if (dependency instanceof ModuleDependency) {
+ ModuleDependency d = (ModuleDependency) dependency;
+ DefaultIdeaModuleDependency defaultDependency = new org.gradle.tooling.internal.idea.DefaultIdeaModuleDependency()
+ .setExported(d.getExported())
+ .setScope(new DefaultIdeaDependencyScope(d.getScope()))
+ .setDependencyModule(modules.get(d.getName()));
+ dependencies.add(defaultDependency);
+ }
+ }
+ modules.get(ideaModule.getName()).setDependencies(dependencies);
+ }
+
+ private void appendModule(Map<String, DefaultIdeaModule> modules, IdeaModule ideaModule, DefaultIdeaProject ideaProject, GradleProject rootGradleProject) {
+ DefaultIdeaContentRoot contentRoot = new DefaultIdeaContentRoot()
+ .setRootDirectory(ideaModule.getContentRoot())
+ .setSourceDirectories(srcDirs(ideaModule.getSourceDirs()))
+ .setTestDirectories(srcDirs(ideaModule.getTestSourceDirs()))
+ .setExcludeDirectories(ideaModule.getExcludeDirs());
+
+ DefaultIdeaModule defaultIdeaModule = new DefaultIdeaModule()
+ .setName(ideaModule.getName())
+ .setParent(ideaProject)
+ .setGradleProject(rootGradleProject.findByPath(ideaModule.getProject().getPath()))
+ .setContentRoots(Collections.singletonList(contentRoot))
+ .setCompilerOutput(new DefaultIdeaCompilerOutput()
+ .setInheritOutputDirs(ideaModule.getInheritOutputDirs() != null ? ideaModule.getInheritOutputDirs() : false)
+ .setOutputDir(ideaModule.getOutputDir())
+ .setTestOutputDir(ideaModule.getTestOutputDir())
+ );
+
+ modules.put(ideaModule.getName(), defaultIdeaModule);
+ }
+
+ private Set<IdeaSourceDirectory> srcDirs(Set<File> sourceDirs) {
+ Set<IdeaSourceDirectory> out = new LinkedHashSet<IdeaSourceDirectory>();
+ for (File s : sourceDirs) {
+ out.add(new DefaultIdeaSourceDirectory().setDirectory(s));
+ }
+ return out;
+ }
+
+ public IdeaModelBuilder setOfflineDependencyResolution(boolean offlineDependencyResolution) {
+ this.offlineDependencyResolution = offlineDependencyResolution;
+ return this;
+ }
+}
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/TasksFactory.java b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/TasksFactory.java
new file mode 100644
index 0000000..d606d0b
--- /dev/null
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/TasksFactory.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.plugins.ide.internal.tooling;
+
+import org.gradle.api.Project;
+import org.gradle.api.Task;
+
+import java.util.Map;
+import java.util.Set;
+
+import static java.util.Collections.emptySet;
+
+public class TasksFactory {
+ Map<Project, Set<Task>> allTasks;
+ private final boolean includeTasks;
+
+ public TasksFactory(boolean includeTasks) {
+ this.includeTasks = includeTasks;
+ }
+
+ public void collectTasks(Project root) {
+ allTasks = root.getAllTasks(true);
+ }
+
+ public Set<Task> getTasks(Project project) {
+ if (includeTasks) {
+ return allTasks.get(project);
+ } else {
+ return emptySet();
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/ToolingRegistrationAction.java b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/ToolingRegistrationAction.java
new file mode 100644
index 0000000..55d4e7d
--- /dev/null
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/ToolingRegistrationAction.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.plugins.ide.internal.tooling;
+
+import org.gradle.api.internal.project.ProjectInternal;
+import org.gradle.configuration.project.ProjectConfigureAction;
+import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry;
+
+public class ToolingRegistrationAction implements ProjectConfigureAction {
+ public void execute(ProjectInternal project) {
+ ToolingModelBuilderRegistry modelBuilderRegistry = project.getServices().get(ToolingModelBuilderRegistry.class);
+ modelBuilderRegistry.register(new EclipseModelBuilder());
+ modelBuilderRegistry.register(new IdeaModelBuilder());
+ modelBuilderRegistry.register(new GradleProjectBuilder());
+ modelBuilderRegistry.register(new GradleBuildBuilder());
+ modelBuilderRegistry.register(new BasicIdeaModelBuilder());
+ }
+}
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/eclipse/DefaultEclipseExternalDependency.java b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/eclipse/DefaultEclipseExternalDependency.java
new file mode 100644
index 0000000..d12c39c
--- /dev/null
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/eclipse/DefaultEclipseExternalDependency.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.plugins.ide.internal.tooling.eclipse;
+
+import org.gradle.api.artifacts.ModuleVersionIdentifier;
+import org.gradle.tooling.internal.gradle.DefaultGradleModuleVersion;
+import org.gradle.tooling.internal.protocol.ExternalDependencyVersion1;
+import org.gradle.tooling.model.GradleModuleVersion;
+
+import java.io.File;
+import java.io.Serializable;
+
+public class DefaultEclipseExternalDependency implements ExternalDependencyVersion1, Serializable {
+ private final File file;
+ private final File javadoc;
+ private final File source;
+ private final GradleModuleVersion moduleVersion;
+
+ public DefaultEclipseExternalDependency(File file, File javadoc, File source, ModuleVersionIdentifier identifier) {
+ this.file = file;
+ this.javadoc = javadoc;
+ this.source = source;
+ moduleVersion = (identifier == null)? null : new DefaultGradleModuleVersion(identifier);
+ }
+
+ public File getFile() {
+ return file;
+ }
+
+ public File getJavadoc() {
+ return javadoc;
+ }
+
+ public File getSource() {
+ return source;
+ }
+
+ public GradleModuleVersion getGradleModuleVersion() {
+ return moduleVersion;
+ }
+}
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/eclipse/DefaultEclipseLinkedResource.java b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/eclipse/DefaultEclipseLinkedResource.java
new file mode 100644
index 0000000..0ff1f7b
--- /dev/null
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/eclipse/DefaultEclipseLinkedResource.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.plugins.ide.internal.tooling.eclipse;
+
+import org.gradle.tooling.internal.protocol.eclipse.EclipseLinkedResourceVersion1;
+
+import java.io.Serializable;
+
+public class DefaultEclipseLinkedResource implements Serializable, EclipseLinkedResourceVersion1 {
+
+ private String name;
+ private String type;
+ private String location;
+ private String locationUri;
+
+ public DefaultEclipseLinkedResource(String name, String type, String location, String locationUri) {
+ this.name = name;
+ this.type = type;
+ this.location = location;
+ this.locationUri = locationUri;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public String getLocation() {
+ return location;
+ }
+
+ public String getLocationUri() {
+ return locationUri;
+ }
+}
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/eclipse/DefaultEclipseProject.java b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/eclipse/DefaultEclipseProject.java
new file mode 100644
index 0000000..ae006cb
--- /dev/null
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/eclipse/DefaultEclipseProject.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.plugins.ide.internal.tooling.eclipse;
+
+import com.google.common.collect.Lists;
+import org.gradle.tooling.internal.gradle.GradleProjectIdentity;
+import org.gradle.tooling.internal.protocol.ExternalDependencyVersion1;
+import org.gradle.tooling.internal.protocol.eclipse.*;
+import org.gradle.tooling.model.GradleProject;
+
+import java.io.File;
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.List;
+
+public class DefaultEclipseProject implements EclipseProjectVersion3, Serializable, GradleProjectIdentity {
+ private final String name;
+ private final String path;
+ private EclipseProjectVersion3 parent;
+ private List<ExternalDependencyVersion1> classpath;
+ private final List<EclipseProjectVersion3> children;
+ private List<EclipseSourceDirectoryVersion1> sourceDirectories;
+ private List<EclipseProjectDependencyVersion2> projectDependencies;
+ private final String description;
+ private final File projectDirectory;
+ private Iterable<? extends EclipseTaskVersion1> tasks;
+ private Iterable<? extends EclipseLinkedResourceVersion1> linkedResources;
+ private GradleProject gradleProject;
+
+ public DefaultEclipseProject(String name, String path, String description, File projectDirectory, Iterable<? extends EclipseProjectVersion3> children) {
+ this.name = name;
+ this.path = path;
+ this.description = description;
+ this.projectDirectory = projectDirectory;
+ this.tasks = Collections.emptyList();
+ this.children = Lists.newArrayList(children);
+ this.classpath = Collections.emptyList();
+ this.sourceDirectories = Collections.emptyList();
+ this.projectDependencies = Collections.emptyList();
+ }
+
+ @Override
+ public String toString() {
+ return String.format("project '%s'", path);
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public EclipseProjectVersion3 getParent() {
+ return parent;
+ }
+
+ public File getProjectDirectory() {
+ return projectDirectory;
+ }
+
+ public void setParent(EclipseProjectVersion3 parent) {
+ this.parent = parent;
+ }
+
+ public List<EclipseProjectVersion3> getChildren() {
+ return children;
+ }
+
+ public Iterable<? extends EclipseSourceDirectoryVersion1> getSourceDirectories() {
+ return sourceDirectories;
+ }
+
+ public void setSourceDirectories(List<EclipseSourceDirectoryVersion1> sourceDirectories) {
+ this.sourceDirectories = sourceDirectories;
+ }
+
+ public Iterable<? extends EclipseProjectDependencyVersion2> getProjectDependencies() {
+ return projectDependencies;
+ }
+
+ public void setProjectDependencies(List<EclipseProjectDependencyVersion2> projectDependencies) {
+ this.projectDependencies = projectDependencies;
+ }
+
+ public List<ExternalDependencyVersion1> getClasspath() {
+ return classpath;
+ }
+ public void setClasspath(List<ExternalDependencyVersion1> classpath) {
+ this.classpath = classpath;
+ }
+
+ public Iterable<? extends EclipseTaskVersion1> getTasks() {
+ return tasks;
+ }
+
+ public void setTasks(Iterable<? extends EclipseTaskVersion1> tasks) {
+ this.tasks = tasks;
+ }
+
+ public Iterable<? extends EclipseLinkedResourceVersion1> getLinkedResources() {
+ return linkedResources;
+ }
+
+ public void setLinkedResources(Iterable<? extends EclipseLinkedResourceVersion1> linkedResources) {
+ this.linkedResources = linkedResources;
+ }
+
+ public GradleProject getGradleProject() {
+ return gradleProject;
+ }
+
+ public DefaultEclipseProject setGradleProject(GradleProject gradleProject) {
+ this.gradleProject = gradleProject;
+ return this;
+ }
+}
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/eclipse/DefaultEclipseProjectDependency.java b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/eclipse/DefaultEclipseProjectDependency.java
new file mode 100644
index 0000000..f042081
--- /dev/null
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/eclipse/DefaultEclipseProjectDependency.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.plugins.ide.internal.tooling.eclipse;
+
+import org.gradle.tooling.internal.protocol.eclipse.EclipseProjectDependencyVersion2;
+import org.gradle.tooling.internal.protocol.eclipse.HierarchicalEclipseProjectVersion1;
+
+import java.io.Serializable;
+
+public class DefaultEclipseProjectDependency implements EclipseProjectDependencyVersion2, Serializable {
+ private final String path;
+ private final HierarchicalEclipseProjectVersion1 target;
+
+ public DefaultEclipseProjectDependency(String path, HierarchicalEclipseProjectVersion1 target) {
+ this.target = target;
+ this.path = path;
+ }
+
+ public HierarchicalEclipseProjectVersion1 getTargetProject() {
+ return target;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("project dependency %s (%s)", path, target);
+ }
+}
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/eclipse/DefaultEclipseSourceDirectory.java b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/eclipse/DefaultEclipseSourceDirectory.java
new file mode 100644
index 0000000..f6ba5b2
--- /dev/null
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/eclipse/DefaultEclipseSourceDirectory.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.plugins.ide.internal.tooling.eclipse;
+
+import org.gradle.tooling.internal.protocol.eclipse.EclipseSourceDirectoryVersion1;
+
+import java.io.File;
+import java.io.Serializable;
+
+public class DefaultEclipseSourceDirectory implements EclipseSourceDirectoryVersion1, Serializable {
+ private final String path;
+ private final File directory;
+
+ public DefaultEclipseSourceDirectory(String path, File directory) {
+ this.path = path;
+ this.directory = directory;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("source directory '%s'", path);
+ }
+
+ public File getDirectory() {
+ return directory;
+ }
+
+ public String getPath() {
+ return path;
+ }
+}
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/eclipse/DefaultEclipseTask.java b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/eclipse/DefaultEclipseTask.java
new file mode 100644
index 0000000..cebd4bb
--- /dev/null
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/eclipse/DefaultEclipseTask.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.plugins.ide.internal.tooling.eclipse;
+
+import org.gradle.tooling.internal.protocol.eclipse.EclipseProjectVersion3;
+import org.gradle.tooling.internal.protocol.eclipse.EclipseTaskVersion1;
+
+import java.io.Serializable;
+
+public class DefaultEclipseTask implements EclipseTaskVersion1, Serializable {
+ private final EclipseProjectVersion3 project;
+ private final String path;
+ private final String name;
+ private final String description;
+
+ public DefaultEclipseTask(EclipseProjectVersion3 project, String path, String name, String description) {
+ this.project = project;
+ this.path = path;
+ this.name = name;
+ this.description = description;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("task '%s'", path);
+ }
+
+ public EclipseProjectVersion3 getProject() {
+ return project;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+}
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/idea/DefaultIdeaCompilerOutput.java b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/idea/DefaultIdeaCompilerOutput.java
new file mode 100644
index 0000000..1fe7763
--- /dev/null
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/idea/DefaultIdeaCompilerOutput.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.plugins.ide.internal.tooling.idea;
+
+import org.gradle.tooling.model.idea.IdeaCompilerOutput;
+
+import java.io.File;
+import java.io.Serializable;
+
+public class DefaultIdeaCompilerOutput implements IdeaCompilerOutput, Serializable {
+
+ private boolean inheritOutputDirs;
+ private File outputDir;
+ private File testOutputDir;
+
+ public boolean getInheritOutputDirs() {
+ return inheritOutputDirs;
+ }
+
+ public DefaultIdeaCompilerOutput setInheritOutputDirs(boolean inheritOutputDirs) {
+ this.inheritOutputDirs = inheritOutputDirs;
+ return this;
+ }
+
+ public File getOutputDir() {
+ return outputDir;
+ }
+
+ public DefaultIdeaCompilerOutput setOutputDir(File outputDir) {
+ this.outputDir = outputDir;
+ return this;
+ }
+
+ public File getTestOutputDir() {
+ return testOutputDir;
+ }
+
+ public DefaultIdeaCompilerOutput setTestOutputDir(File testOutputDir) {
+ this.testOutputDir = testOutputDir;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return "IdeaCompilerOutput{"
+ + "inheritOutputDirs=" + inheritOutputDirs
+ + ", outputDir=" + outputDir
+ + ", testOutputDir=" + testOutputDir
+ + '}';
+ }
+}
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/idea/DefaultIdeaContentRoot.java b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/idea/DefaultIdeaContentRoot.java
new file mode 100644
index 0000000..b463182
--- /dev/null
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/idea/DefaultIdeaContentRoot.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.plugins.ide.internal.tooling.idea;
+
+import org.gradle.tooling.model.DomainObjectSet;
+import org.gradle.tooling.model.idea.IdeaContentRoot;
+import org.gradle.tooling.model.idea.IdeaSourceDirectory;
+import org.gradle.tooling.model.internal.ImmutableDomainObjectSet;
+
+import java.io.File;
+import java.io.Serializable;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+public class DefaultIdeaContentRoot implements IdeaContentRoot, Serializable {
+
+ File rootDirectory;
+ Set<IdeaSourceDirectory> sourceDirectories = new LinkedHashSet<IdeaSourceDirectory>();
+ Set<IdeaSourceDirectory> testDirectories = new LinkedHashSet<IdeaSourceDirectory>();
+ Set<File> excludeDirectories = new LinkedHashSet<File>();
+
+ public File getRootDirectory() {
+ return rootDirectory;
+ }
+
+ public DefaultIdeaContentRoot setRootDirectory(File rootDirectory) {
+ this.rootDirectory = rootDirectory;
+ return this;
+ }
+
+ public DomainObjectSet<IdeaSourceDirectory> getSourceDirectories() {
+ return new ImmutableDomainObjectSet<IdeaSourceDirectory>(sourceDirectories);
+ }
+
+ public DefaultIdeaContentRoot setSourceDirectories(Set<IdeaSourceDirectory> sourceDirectories) {
+ this.sourceDirectories = sourceDirectories;
+ return this;
+ }
+
+ public DomainObjectSet<IdeaSourceDirectory> getTestDirectories() {
+ return new ImmutableDomainObjectSet<IdeaSourceDirectory>(testDirectories);
+ }
+
+ public DefaultIdeaContentRoot setTestDirectories(Set<IdeaSourceDirectory> testDirectories) {
+ this.testDirectories = testDirectories;
+ return this;
+ }
+
+ public Set<File> getExcludeDirectories() {
+ return excludeDirectories;
+ }
+
+ public DefaultIdeaContentRoot setExcludeDirectories(Set<File> excludeDirectories) {
+ this.excludeDirectories = excludeDirectories;
+ return this;
+ }
+
+ public String toString() {
+ return "IdeaContentRoot{"
+ + "rootDirectory=" + rootDirectory
+ + ", sourceDirectories count=" + sourceDirectories.size()
+ + ", testDirectories count=" + testDirectories.size()
+ + ", excludeDirectories count=" + excludeDirectories.size()
+ + '}';
+ }
+}
\ No newline at end of file
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/idea/DefaultIdeaDependency.java b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/idea/DefaultIdeaDependency.java
new file mode 100644
index 0000000..38d0416
--- /dev/null
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/idea/DefaultIdeaDependency.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.plugins.ide.internal.tooling.idea;
+
+import java.io.Serializable;
+
+public class DefaultIdeaDependency implements Serializable {
+}
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/idea/DefaultIdeaDependencyScope.java b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/idea/DefaultIdeaDependencyScope.java
new file mode 100644
index 0000000..205d09a
--- /dev/null
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/idea/DefaultIdeaDependencyScope.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.plugins.ide.internal.tooling.idea;
+
+import org.gradle.tooling.model.idea.IdeaDependencyScope;
+
+import java.io.Serializable;
+
+public class DefaultIdeaDependencyScope implements IdeaDependencyScope, Serializable {
+
+ String scope;
+
+ public DefaultIdeaDependencyScope(String scope) {
+ this.scope = scope;
+ }
+
+ public String getScope() {
+ return scope;
+ }
+
+ @Override
+ public String toString() {
+ return "IdeaDependencyScope{"
+ + "scope='" + scope + '\''
+ + '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof DefaultIdeaDependencyScope)) {
+ return false;
+ }
+
+ DefaultIdeaDependencyScope that = (DefaultIdeaDependencyScope) o;
+
+ if (scope != null ? !scope.equals(that.scope) : that.scope != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return scope != null ? scope.hashCode() : 0;
+ }
+}
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/idea/DefaultIdeaLanguageLevel.java b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/idea/DefaultIdeaLanguageLevel.java
new file mode 100644
index 0000000..5057431
--- /dev/null
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/idea/DefaultIdeaLanguageLevel.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.plugins.ide.internal.tooling.idea;
+
+import org.gradle.tooling.model.idea.IdeaLanguageLevel;
+
+import java.io.Serializable;
+
+public class DefaultIdeaLanguageLevel implements IdeaLanguageLevel, Serializable {
+
+ private final String level;
+
+ public DefaultIdeaLanguageLevel(String level) {
+ this.level = level;
+ }
+
+ public boolean isJDK_1_4() {
+ return "JDK_1_4".equals(level);
+ }
+
+ public boolean isJDK_1_5() {
+ return "JDK_1_5".equals(level);
+ }
+
+ public boolean isJDK_1_6() {
+ return "JDK_1_6".equals(level);
+ }
+
+ public boolean isJDK_1_7() {
+ return "JDK_1_7".equals(level);
+ }
+
+ public boolean isJDK_1_8() {
+ return "JDK_1_8".equals(level);
+ }
+
+ public String getLevel() {
+ return level;
+ }
+
+ @Override
+ public String toString() {
+ return "IdeaLanguageLevel{level='" + level + "'}";
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof DefaultIdeaLanguageLevel)) {
+ return false;
+ }
+
+ DefaultIdeaLanguageLevel that = (DefaultIdeaLanguageLevel) o;
+
+ if (level != null ? !level.equals(that.level) : that.level != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return level != null ? level.hashCode() : 0;
+ }
+}
\ No newline at end of file
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/idea/DefaultIdeaModule.java b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/idea/DefaultIdeaModule.java
new file mode 100644
index 0000000..c6a2e37
--- /dev/null
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/idea/DefaultIdeaModule.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.plugins.ide.internal.tooling.idea;
+
+import org.gradle.tooling.internal.gradle.GradleProjectIdentity;
+import org.gradle.tooling.model.GradleProject;
+import org.gradle.tooling.model.idea.IdeaCompilerOutput;
+import org.gradle.tooling.model.idea.IdeaContentRoot;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+public class DefaultIdeaModule implements Serializable, GradleProjectIdentity {
+ private String name;
+ private List<? extends IdeaContentRoot> contentRoots = new LinkedList<IdeaContentRoot>();
+ private DefaultIdeaProject parent;
+
+ private List<DefaultIdeaDependency> dependencies = new LinkedList<DefaultIdeaDependency>();
+ private GradleProject gradleProject;
+
+ private IdeaCompilerOutput compilerOutput;
+
+ public String getName() {
+ return name;
+ }
+
+ public DefaultIdeaModule setName(String name) {
+ this.name = name;
+ return this;
+ }
+
+ public Collection<? extends IdeaContentRoot> getContentRoots() {
+ return contentRoots;
+ }
+
+ public DefaultIdeaModule setContentRoots(List<? extends IdeaContentRoot> contentRoots) {
+ this.contentRoots = contentRoots;
+ return this;
+ }
+
+ public DefaultIdeaProject getParent() {
+ return parent;
+ }
+
+ public DefaultIdeaProject getProject() {
+ return parent;
+ }
+
+ public DefaultIdeaModule setParent(DefaultIdeaProject parent) {
+ this.parent = parent;
+ return this;
+ }
+
+ public Collection<DefaultIdeaDependency> getDependencies() {
+ return dependencies;
+ }
+
+ public DefaultIdeaModule setDependencies(List<DefaultIdeaDependency> dependencies) {
+ this.dependencies = dependencies;
+ return this;
+ }
+
+ public Collection<Object> getChildren() {
+ return Collections.emptySet();
+ }
+
+ public String getDescription() {
+ return null;
+ }
+
+ public GradleProject getGradleProject() {
+ return gradleProject;
+ }
+
+ public DefaultIdeaModule setGradleProject(GradleProject gradleProject) {
+ this.gradleProject = gradleProject;
+ return this;
+ }
+
+ public String getPath() {
+ return gradleProject.getPath();
+ }
+
+ public IdeaCompilerOutput getCompilerOutput() {
+ return compilerOutput;
+ }
+
+ public DefaultIdeaModule setCompilerOutput(IdeaCompilerOutput compilerOutput) {
+ this.compilerOutput = compilerOutput;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return "IdeaModule{"
+ + "name='" + name + '\''
+ + ", gradleProject='" + gradleProject + '\''
+ + ", contentRoots=" + contentRoots
+ + ", compilerOutput=" + compilerOutput
+ + ", dependencies count=" + dependencies.size()
+ + '}';
+ }
+}
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/idea/DefaultIdeaModuleDependency.java b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/idea/DefaultIdeaModuleDependency.java
new file mode 100644
index 0000000..0ae71ec
--- /dev/null
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/idea/DefaultIdeaModuleDependency.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.plugins.ide.internal.tooling.idea;
+
+import org.gradle.tooling.model.idea.IdeaDependencyScope;
+
+public class DefaultIdeaModuleDependency extends DefaultIdeaDependency {
+ private IdeaDependencyScope scope;
+ private DefaultIdeaModule dependencyModule;
+ private boolean exported;
+
+ public IdeaDependencyScope getScope() {
+ return scope;
+ }
+
+ public DefaultIdeaModuleDependency setScope(IdeaDependencyScope scope) {
+ this.scope = scope;
+ return this;
+ }
+
+ public DefaultIdeaModule getDependencyModule() {
+ return dependencyModule;
+ }
+
+ public DefaultIdeaModuleDependency setDependencyModule(DefaultIdeaModule dependencyModule) {
+ this.dependencyModule = dependencyModule;
+ return this;
+ }
+
+ public boolean getExported() {
+ return exported;
+ }
+
+ public DefaultIdeaModuleDependency setExported(boolean exported) {
+ this.exported = exported;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return "DefaultIdeaModuleDependency{"
+ + "scope='" + scope + '\''
+ + ", dependencyModule name='" + dependencyModule.getName() + '\''
+ + ", exported=" + exported
+ + '}';
+ }
+}
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/idea/DefaultIdeaProject.java b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/idea/DefaultIdeaProject.java
new file mode 100644
index 0000000..aaf0234
--- /dev/null
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/idea/DefaultIdeaProject.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.plugins.ide.internal.tooling.idea;
+
+import org.gradle.tooling.internal.protocol.InternalIdeaProject;
+import org.gradle.tooling.model.HierarchicalElement;
+import org.gradle.tooling.model.idea.IdeaLanguageLevel;
+
+import java.io.File;
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.LinkedList;
+
+public class DefaultIdeaProject implements InternalIdeaProject, Serializable {
+ private String name;
+ private String description;
+ private Collection<DefaultIdeaModule> children = new LinkedList<DefaultIdeaModule>();
+ private IdeaLanguageLevel languageLevel;
+ private String jdkName;
+
+ public IdeaLanguageLevel getLanguageLevel() {
+ return languageLevel;
+ }
+
+ public DefaultIdeaProject setLanguageLevel(IdeaLanguageLevel languageLevel) {
+ this.languageLevel = languageLevel;
+ return this;
+ }
+
+ public String getJdkName() {
+ return jdkName;
+ }
+
+ public DefaultIdeaProject setJdkName(String jdkName) {
+ this.jdkName = jdkName;
+ return this;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public DefaultIdeaProject setName(String name) {
+ this.name = name;
+ return this;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public DefaultIdeaProject setDescription(String description) {
+ this.description = description;
+ return this;
+ }
+
+ public HierarchicalElement getParent() {
+ return null;
+ }
+
+ public File getProjectDirectory() {
+ throw new UnsupportedOperationException("This method should not be used.");
+ }
+
+ public String getPath() {
+ throw new UnsupportedOperationException("This method should not be used.");
+ }
+
+ public DefaultIdeaProject setChildren(Collection<? extends DefaultIdeaModule> children) {
+ this.children.clear();
+ this.children.addAll(children);
+ return this;
+ }
+
+ public Collection<DefaultIdeaModule> getChildren() {
+ return children;
+ }
+
+ public Collection<DefaultIdeaModule> getModules() {
+ return children;
+ }
+
+ @Override
+ public String toString() {
+ return "DefaultIdeaProject{"
+ + " name='" + name + '\''
+ + ", description='" + description + '\''
+ + ", children count=" + children.size()
+ + ", languageLevel='" + languageLevel + '\''
+ + ", jdkName='" + jdkName + '\''
+ + '}';
+ }
+}
\ No newline at end of file
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/idea/DefaultIdeaSingleEntryLibraryDependency.java b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/idea/DefaultIdeaSingleEntryLibraryDependency.java
new file mode 100644
index 0000000..b51bdd0
--- /dev/null
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/idea/DefaultIdeaSingleEntryLibraryDependency.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.plugins.ide.internal.tooling.idea;
+
+import org.gradle.tooling.model.GradleModuleVersion;
+import org.gradle.tooling.model.idea.IdeaDependencyScope;
+
+import java.io.File;
+
+public class DefaultIdeaSingleEntryLibraryDependency extends DefaultIdeaDependency {
+ private File file;
+ private File source;
+ private File javadoc;
+ private Boolean exported;
+ private IdeaDependencyScope scope;
+ private GradleModuleVersion moduleVersion;
+
+ public File getFile() {
+ return file;
+ }
+
+ public DefaultIdeaSingleEntryLibraryDependency setFile(File file) {
+ this.file = file;
+ return this;
+ }
+
+ public File getSource() {
+ return source;
+ }
+
+ public DefaultIdeaSingleEntryLibraryDependency setSource(File source) {
+ this.source = source;
+ return this;
+ }
+
+ public File getJavadoc() {
+ return javadoc;
+ }
+
+ public GradleModuleVersion getGradleModuleVersion() {
+ return moduleVersion;
+ }
+
+ public DefaultIdeaSingleEntryLibraryDependency setJavadoc(File javadoc) {
+ this.javadoc = javadoc;
+ return this;
+ }
+
+ public boolean getExported() {
+ return exported;
+ }
+
+ public DefaultIdeaSingleEntryLibraryDependency setExported(Boolean exported) {
+ this.exported = exported;
+ return this;
+ }
+
+ public IdeaDependencyScope getScope() {
+ return scope;
+ }
+
+ public DefaultIdeaSingleEntryLibraryDependency setScope(IdeaDependencyScope scope) {
+ this.scope = scope;
+ return this;
+ }
+
+ public DefaultIdeaSingleEntryLibraryDependency setGradleModuleVersion(GradleModuleVersion moduleVersion) {
+ this.moduleVersion = moduleVersion;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return "IdeaLibraryDependency{"
+ + "file=" + file
+ + ", source=" + source
+ + ", javadoc=" + javadoc
+ + ", exported=" + exported
+ + ", scope='" + scope + '\''
+ + ", id='" + moduleVersion + '\''
+ + '}';
+ }
+}
diff --git a/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/idea/DefaultIdeaSourceDirectory.java b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/idea/DefaultIdeaSourceDirectory.java
new file mode 100644
index 0000000..d6685cd
--- /dev/null
+++ b/subprojects/ide/src/main/groovy/org/gradle/plugins/ide/internal/tooling/idea/DefaultIdeaSourceDirectory.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.plugins.ide.internal.tooling.idea;
+
+import org.gradle.tooling.model.idea.IdeaSourceDirectory;
+
+import java.io.File;
+import java.io.Serializable;
+
+public class DefaultIdeaSourceDirectory implements IdeaSourceDirectory, Serializable {
+
+ private File directory;
+
+ public File getDirectory() {
+ return directory;
+ }
+
+ public DefaultIdeaSourceDirectory setDirectory(File directory) {
+ this.directory = directory;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return "DefaultIdeaSourceDirectory{"
+ + "directory=" + directory
+ + '}';
+ }
+}
diff --git a/subprojects/ide/src/main/groovy/org/gradle/tooling/internal/idea/DefaultIdeaModuleDependency.java b/subprojects/ide/src/main/groovy/org/gradle/tooling/internal/idea/DefaultIdeaModuleDependency.java
new file mode 100644
index 0000000..ca6fd46
--- /dev/null
+++ b/subprojects/ide/src/main/groovy/org/gradle/tooling/internal/idea/DefaultIdeaModuleDependency.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.idea;
+
+import org.gradle.tooling.provider.model.internal.LegacyConsumerInterface;
+
+/**
+ * This is here because consumers <= 1.0-milestone-5 expected the implementation class to have a particular name.
+ */
+ at Deprecated
+ at LegacyConsumerInterface("org.gradle.tooling.model.idea.IdeaModuleDependency")
+public class DefaultIdeaModuleDependency extends org.gradle.plugins.ide.internal.tooling.idea.DefaultIdeaModuleDependency {
+}
diff --git a/subprojects/ide/src/main/groovy/org/gradle/tooling/internal/idea/DefaultIdeaSingleEntryLibraryDependency.java b/subprojects/ide/src/main/groovy/org/gradle/tooling/internal/idea/DefaultIdeaSingleEntryLibraryDependency.java
new file mode 100644
index 0000000..dbc50d0
--- /dev/null
+++ b/subprojects/ide/src/main/groovy/org/gradle/tooling/internal/idea/DefaultIdeaSingleEntryLibraryDependency.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.idea;
+
+import org.gradle.tooling.provider.model.internal.LegacyConsumerInterface;
+
+/**
+ * This is here because consumers <= 1.0-milestone-5 expected the implementation class to have a particular name.
+ */
+ at LegacyConsumerInterface("org.gradle.tooling.model.idea.IdeaSingleEntryLibraryDependency")
+ at Deprecated
+public class DefaultIdeaSingleEntryLibraryDependency extends org.gradle.plugins.ide.internal.tooling.idea.DefaultIdeaSingleEntryLibraryDependency {
+}
diff --git a/subprojects/ide/src/main/groovy/org/gradle/tooling/internal/provider/BasicIdeaModelBuilder.java b/subprojects/ide/src/main/groovy/org/gradle/tooling/internal/provider/BasicIdeaModelBuilder.java
deleted file mode 100644
index 7f251c2..0000000
--- a/subprojects/ide/src/main/groovy/org/gradle/tooling/internal/provider/BasicIdeaModelBuilder.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.provider;
-
-import org.gradle.api.internal.GradleInternal;
-import org.gradle.tooling.internal.protocol.InternalBasicIdeaProject;
-import org.gradle.tooling.internal.protocol.ProjectVersion3;
-
-/**
- * @author: Szczepan Faber, created at: 7/23/11
- */
-public class BasicIdeaModelBuilder implements BuildsModel {
- public boolean canBuild(Class<?> type) {
- return type == InternalBasicIdeaProject.class;
- }
-
- public ProjectVersion3 buildAll(GradleInternal gradle) {
- return new IdeaModelBuilder()
- .setOfflineDependencyResolution(true)
- .buildAll(gradle);
- }
-}
diff --git a/subprojects/ide/src/main/groovy/org/gradle/tooling/internal/provider/BuildModelAction.java b/subprojects/ide/src/main/groovy/org/gradle/tooling/internal/provider/BuildModelAction.java
deleted file mode 100644
index 5e0fc4b..0000000
--- a/subprojects/ide/src/main/groovy/org/gradle/tooling/internal/provider/BuildModelAction.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.provider;
-
-import org.gradle.BuildResult;
-import org.gradle.GradleLauncher;
-import org.gradle.api.Action;
-import org.gradle.api.internal.GradleInternal;
-import org.gradle.api.internal.project.ProjectInternal;
-import org.gradle.initialization.GradleLauncherAction;
-import org.gradle.initialization.ModelConfigurationListener;
-import org.gradle.initialization.TasksCompletionListener;
-import org.gradle.tooling.internal.protocol.ProjectVersion3;
-
-import java.util.List;
-
-import static java.util.Arrays.asList;
-
-public class BuildModelAction implements GradleLauncherAction<ProjectVersion3> {
- private final BuildsModel builder;
- private final boolean runTasks;
- private ProjectVersion3 model;
-
- public BuildModelAction(Class<?> type, boolean runTasks) {
- this.runTasks = runTasks;
- List<? extends BuildsModel> modelBuilders = asList(
- new NullResultBuilder(),
- new EclipseModelBuilder(),
- new IdeaModelBuilder(),
- new GradleProjectBuilder(),
- new BasicIdeaModelBuilder(),
- new ProjectOutcomesModelBuilder());
-
- for (BuildsModel builder : modelBuilders) {
- if (builder.canBuild(type)) {
- this.builder = builder;
- return;
- }
- }
-
- throw new UnsupportedOperationException(String.format("I don't know how to build a model of type '%s'.", type.getSimpleName()));
- }
-
- public BuildResult run(GradleLauncher launcher) {
-
- if (runTasks) {
- launcher.addListener(new TasksCompletionListener() {
- public void onTasksFinished(GradleInternal gradle) {
- model = builder.buildAll(gradle);
- }
- });
- return launcher.run();
- } else {
- launcher.addListener(new ModelConfigurationListener() {
- public void onConfigure(GradleInternal gradle) {
- ensureAllProjectsEvaluated(gradle);
- model = builder.buildAll(gradle);
- }
- });
- return launcher.getBuildAnalysis();
- }
- }
-
- private void ensureAllProjectsEvaluated(GradleInternal gradle) {
- gradle.getRootProject().allprojects((Action) new Action<ProjectInternal>() {
- public void execute(ProjectInternal projectInternal) {
- projectInternal.evaluate();
- }
- });
- }
-
- public ProjectVersion3 getResult() {
- return model;
- }
-}
diff --git a/subprojects/ide/src/main/groovy/org/gradle/tooling/internal/provider/BuildsModel.java b/subprojects/ide/src/main/groovy/org/gradle/tooling/internal/provider/BuildsModel.java
deleted file mode 100644
index 9bdc3b0..0000000
--- a/subprojects/ide/src/main/groovy/org/gradle/tooling/internal/provider/BuildsModel.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.provider;
-
-import org.gradle.api.internal.GradleInternal;
-import org.gradle.tooling.internal.protocol.ProjectVersion3;
-
-/**
-* @author: Szczepan Faber, created at: 7/23/11
-*/
-public interface BuildsModel {
- boolean canBuild(Class<?> type);
- ProjectVersion3 buildAll(GradleInternal gradle);
-}
diff --git a/subprojects/ide/src/main/groovy/org/gradle/tooling/internal/provider/EclipseModelBuilder.java b/subprojects/ide/src/main/groovy/org/gradle/tooling/internal/provider/EclipseModelBuilder.java
deleted file mode 100644
index 9947d1f..0000000
--- a/subprojects/ide/src/main/groovy/org/gradle/tooling/internal/provider/EclipseModelBuilder.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.provider;
-
-import org.apache.commons.lang.StringUtils;
-import org.gradle.api.Project;
-import org.gradle.api.Task;
-import org.gradle.api.internal.GradleInternal;
-import org.gradle.plugins.ide.eclipse.EclipsePlugin;
-import org.gradle.plugins.ide.eclipse.model.*;
-import org.gradle.tooling.internal.eclipse.*;
-import org.gradle.tooling.internal.protocol.BuildableProjectVersion1;
-import org.gradle.tooling.internal.protocol.ExternalDependencyVersion1;
-import org.gradle.tooling.internal.protocol.eclipse.EclipseProjectDependencyVersion2;
-import org.gradle.tooling.internal.protocol.eclipse.EclipseProjectVersion3;
-import org.gradle.tooling.internal.protocol.eclipse.EclipseSourceDirectoryVersion1;
-import org.gradle.tooling.internal.protocol.eclipse.EclipseTaskVersion1;
-import org.gradle.tooling.model.GradleProject;
-import org.gradle.util.GUtil;
-import org.gradle.util.ReflectionUtil;
-
-import java.io.File;
-import java.util.*;
-
-/**
-* @author Adam Murdoch, Szczepan Faber, @date: 17.03.11
-*/
-public class EclipseModelBuilder implements BuildsModel {
- private boolean projectDependenciesOnly;
- private EclipseProjectVersion3 currentProject;
- private final Map<String, EclipseProjectVersion3> projectMapping = new HashMap<String, EclipseProjectVersion3>();
- private GradleInternal gradle;
- private TasksFactory tasksFactory;
- private GradleProjectBuilder gradleProjectBuilder = new GradleProjectBuilder();
- private GradleProject rootGradleProject;
-
- public boolean canBuild(Class<?> type) {
- if (type.isAssignableFrom(EclipseProjectVersion3.class)) {
- //I don't like preparing the state in this method but for now lets leave it :/
- boolean includeTasks = BuildableProjectVersion1.class.isAssignableFrom(type);
- this.tasksFactory = new TasksFactory(includeTasks);
- this.projectDependenciesOnly = !EclipseProjectVersion3.class.isAssignableFrom(type);
- return true;
- }
- return false;
- }
-
- public EclipseProjectVersion3 buildAll(GradleInternal gradle) {
- this.gradle = gradle;
- rootGradleProject = gradleProjectBuilder.buildAll(gradle);
- Project root = gradle.getRootProject();
- tasksFactory.collectTasks(root);
- applyEclipsePlugin(root);
- buildHierarchy(root);
- populate(root);
- return currentProject;
- }
-
- private void applyEclipsePlugin(Project root) {
- Set<Project> allprojects = root.getAllprojects();
- for (Project p : allprojects) {
- p.getPlugins().apply(EclipsePlugin.class);
- }
- root.getPlugins().getPlugin(EclipsePlugin.class).makeSureProjectNamesAreUnique();
- }
-
- private void addProject(Project project, EclipseProjectVersion3 eclipseProject) {
- if (project == gradle.getDefaultProject()) {
- currentProject = eclipseProject;
- }
- projectMapping.put(project.getPath(), eclipseProject);
- }
-
- private void populate(Project project) {
- EclipseModel eclipseModel = project.getPlugins().getPlugin(EclipsePlugin.class).getModel();
- EclipseClasspath classpath = eclipseModel.getClasspath();
-
- classpath.setProjectDependenciesOnly(projectDependenciesOnly);
- List<ClasspathEntry> entries = classpath.resolveDependencies();
-
- final List<ExternalDependencyVersion1> externalDependencies = new LinkedList<ExternalDependencyVersion1>();
- final List<EclipseProjectDependencyVersion2> projectDependencies = new LinkedList<EclipseProjectDependencyVersion2>();
- final List<EclipseSourceDirectoryVersion1> sourceDirectories = new LinkedList<EclipseSourceDirectoryVersion1>();
-
- for (ClasspathEntry entry : entries) {
- //we don't handle Variables at the moment because users didn't request it yet
- //and it would probably push us to add support in the tooling api to retrieve the variable mappings.
- if (entry instanceof Library) {
- AbstractLibrary library = (AbstractLibrary) entry;
- final File file = library.getLibrary().getFile();
- final File source = library.getSourcePath() == null ? null : library.getSourcePath().getFile();
- final File javadoc = library.getJavadocPath() == null ? null : library.getJavadocPath().getFile();
- externalDependencies.add(new DefaultEclipseExternalDependency(file, javadoc, source, library.getModuleVersion()));
- } else if (entry instanceof ProjectDependency) {
- final ProjectDependency projectDependency = (ProjectDependency) entry;
- final String path = StringUtils.removeStart(projectDependency.getPath(), "/");
- projectDependencies.add(new DefaultEclipseProjectDependency(path, projectMapping.get(projectDependency.getGradlePath())));
- } else if (entry instanceof SourceFolder) {
- String path = ((SourceFolder) entry).getPath();
- sourceDirectories.add(new DefaultEclipseSourceDirectory(path, project.file(path)));
- }
- }
-
- final EclipseProjectVersion3 eclipseProject = projectMapping.get(project.getPath());
- ReflectionUtil.setProperty(eclipseProject, "classpath", externalDependencies);
- ReflectionUtil.setProperty(eclipseProject, "projectDependencies", projectDependencies);
- ReflectionUtil.setProperty(eclipseProject, "sourceDirectories", sourceDirectories);
-
- if (ReflectionUtil.hasProperty(eclipseProject, "linkedResources")) {
- List<DefaultEclipseLinkedResource> linkedResources = new LinkedList<DefaultEclipseLinkedResource>();
- for(Link r: eclipseModel.getProject().getLinkedResources()) {
- linkedResources.add(new DefaultEclipseLinkedResource(r.getName(), r.getType(), r.getLocation(), r.getLocationUri()));
- }
- ReflectionUtil.setProperty(eclipseProject, "linkedResources", linkedResources);
- }
-
- List<EclipseTaskVersion1> out = new ArrayList<EclipseTaskVersion1>();
- for (final Task t : tasksFactory.getTasks(project)) {
- out.add(new DefaultEclipseTask(eclipseProject, t.getPath(), t.getName(), t.getDescription()));
- }
- ReflectionUtil.setProperty(eclipseProject, "tasks", out);
-
- for (Project childProject : project.getChildProjects().values()) {
- populate(childProject);
- }
- }
-
- private EclipseProjectVersion3 buildHierarchy(Project project) {
- List<EclipseProjectVersion3> children = new ArrayList<EclipseProjectVersion3>();
- for (Project child : project.getChildProjects().values()) {
- children.add(buildHierarchy(child));
- }
-
- EclipseModel eclipseModel = project.getPlugins().getPlugin(EclipsePlugin.class).getModel();
- org.gradle.plugins.ide.eclipse.model.EclipseProject internalProject = eclipseModel.getProject();
- String name = internalProject.getName();
- String description = GUtil.elvis(internalProject.getComment(), null);
- EclipseProjectVersion3 eclipseProject =
- new DefaultEclipseProject(name, project.getPath(), description, project.getProjectDir(), children)
- .setGradleProject(rootGradleProject.findByPath(project.getPath()));
-
- for (Object child : children) {
- ReflectionUtil.setProperty(child, "parent", eclipseProject);
- }
- addProject(project, eclipseProject);
- return eclipseProject;
- }
-}
diff --git a/subprojects/ide/src/main/groovy/org/gradle/tooling/internal/provider/FileOutcomeIdentifier.java b/subprojects/ide/src/main/groovy/org/gradle/tooling/internal/provider/FileOutcomeIdentifier.java
deleted file mode 100644
index 24b7e3c..0000000
--- a/subprojects/ide/src/main/groovy/org/gradle/tooling/internal/provider/FileOutcomeIdentifier.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.provider;
-
-/**
- * This should not be used as a type in the model. It's just a container for known
- * {@link org.gradle.tooling.model.internal.outcomes.GradleFileBuildOutcome#getTypeIdentifier()} values.
- */
-public enum FileOutcomeIdentifier {
- ZIP_ARTIFACT("artifact.zip"),
- JAR_ARTIFACT("artifact.jar"),
- WAR_ARTIFACT("artifact.war"),
- EAR_ARTIFACT("artifact.ear"),
- TAR_ARTIFACT("artifact.tar"),
- ARCHIVE_ARTIFACT("artifact.archive"), // We know it's an archive, but not what kind of archive
- UNKNOWN_ARTIFACT("artifact.unknown"); // We know it's an artifact, but that's all we know for sure
-
- private String typeIdentifier;
-
- FileOutcomeIdentifier(String typeIdentifier) {
- this.typeIdentifier = typeIdentifier;
- }
-
- public String getTypeIdentifier() {
- return typeIdentifier;
- }
-}
diff --git a/subprojects/ide/src/main/groovy/org/gradle/tooling/internal/provider/GradleProjectBuilder.java b/subprojects/ide/src/main/groovy/org/gradle/tooling/internal/provider/GradleProjectBuilder.java
deleted file mode 100644
index fd8ddaa..0000000
--- a/subprojects/ide/src/main/groovy/org/gradle/tooling/internal/provider/GradleProjectBuilder.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.provider;
-
-import org.gradle.api.Project;
-import org.gradle.api.Task;
-import org.gradle.api.internal.GradleInternal;
-import org.gradle.api.tasks.TaskContainer;
-import org.gradle.tooling.internal.gradle.DefaultGradleProject;
-import org.gradle.tooling.internal.gradle.DefaultGradleTask;
-import org.gradle.tooling.internal.protocol.InternalGradleProject;
-import org.gradle.tooling.model.GradleTask;
-
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * Builds the GradleProject that contains the project hierarchy and task information
- *
- * @author: Szczepan Faber, created at: 7/27/11
- */
-public class GradleProjectBuilder implements BuildsModel {
- public boolean canBuild(Class<?> type) {
- return type == InternalGradleProject.class;
- }
-
- public DefaultGradleProject buildAll(GradleInternal gradle) {
- return buildHierarchy(gradle.getRootProject());
- }
-
- private DefaultGradleProject buildHierarchy(Project project) {
- List<DefaultGradleProject> children = new ArrayList<DefaultGradleProject>();
- for (Project child : project.getChildProjects().values()) {
- children.add(buildHierarchy(child));
- }
-
- DefaultGradleProject gradleProject = new DefaultGradleProject()
- .setPath(project.getPath())
- .setName(project.getName())
- .setDescription(project.getDescription())
- .setChildren(children);
-
- gradleProject.setTasks(tasks(gradleProject, project.getTasks()));
-
- for (DefaultGradleProject child : children) {
- child.setParent(gradleProject);
- }
-
- return gradleProject;
- }
-
- private List<GradleTask> tasks(DefaultGradleProject owner, TaskContainer tasks) {
- List<GradleTask> out = new LinkedList<GradleTask>();
-
- for (Task t : tasks) {
- out.add(new DefaultGradleTask()
- .setPath(t.getPath())
- .setName(t.getName())
- .setDescription(t.getDescription())
- .setProject(owner));
- }
-
- return out;
- }
-}
diff --git a/subprojects/ide/src/main/groovy/org/gradle/tooling/internal/provider/IdeaModelBuilder.java b/subprojects/ide/src/main/groovy/org/gradle/tooling/internal/provider/IdeaModelBuilder.java
deleted file mode 100644
index 02eb24a..0000000
--- a/subprojects/ide/src/main/groovy/org/gradle/tooling/internal/provider/IdeaModelBuilder.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.provider;
-
-import org.gradle.api.Project;
-import org.gradle.api.internal.GradleInternal;
-import org.gradle.plugins.ide.idea.IdeaPlugin;
-import org.gradle.plugins.ide.idea.model.*;
-import org.gradle.tooling.internal.gradle.DefaultGradleModuleVersion;
-import org.gradle.tooling.internal.idea.*;
-import org.gradle.tooling.internal.protocol.InternalIdeaProject;
-import org.gradle.tooling.internal.protocol.ProjectVersion3;
-import org.gradle.tooling.model.GradleProject;
-import org.gradle.tooling.model.idea.IdeaDependency;
-import org.gradle.tooling.model.idea.IdeaSourceDirectory;
-
-import java.io.File;
-import java.util.*;
-
-/**
- * @author: Szczepan Faber, created at: 7/23/11
- */
-public class IdeaModelBuilder implements BuildsModel {
- public boolean canBuild(Class<?> type) {
- return type == InternalIdeaProject.class;
- }
-
- private final GradleProjectBuilder gradleProjectBuilder = new GradleProjectBuilder();
- private boolean offlineDependencyResolution;
-
- public ProjectVersion3 buildAll(GradleInternal gradle) {
- Project root = gradle.getRootProject();
- applyIdeaPlugin(root);
- GradleProject rootGradleProject = gradleProjectBuilder.buildAll(gradle);
- return build(root, rootGradleProject);
- }
-
- private void applyIdeaPlugin(Project root) {
- Set<Project> allprojects = root.getAllprojects();
- for (Project p : allprojects) {
- p.getPlugins().apply(IdeaPlugin.class);
- }
- root.getPlugins().getPlugin(IdeaPlugin.class).makeSureModuleNamesAreUnique();
- }
-
- private ProjectVersion3 build(Project project, GradleProject rootGradleProject) {
- IdeaModel ideaModel = project.getPlugins().getPlugin(IdeaPlugin.class).getModel();
- IdeaProject projectModel = ideaModel.getProject();
-
- DefaultIdeaProject out = new DefaultIdeaProject()
- .setName(projectModel.getName())
- .setJdkName(projectModel.getJdkName())
- .setLanguageLevel(new DefaultIdeaLanguageLevel(projectModel.getLanguageLevel().getLevel()));
-
- Map<String, DefaultIdeaModule> modules = new HashMap<String, DefaultIdeaModule>();
- for (IdeaModule module : projectModel.getModules()) {
- appendModule(modules, module, out, rootGradleProject);
- }
- for (IdeaModule module : projectModel.getModules()) {
- buildDependencies(modules, module);
- }
- out.setChildren(new LinkedList<DefaultIdeaModule>(modules.values()));
-
- return out;
- }
-
- private void buildDependencies(Map<String, DefaultIdeaModule> modules, IdeaModule ideaModule) {
- ideaModule.setOffline(offlineDependencyResolution);
- Set<Dependency> resolved = ideaModule.resolveDependencies();
- List<IdeaDependency> dependencies = new LinkedList<IdeaDependency>();
- for (Dependency dependency : resolved) {
- if (dependency instanceof SingleEntryModuleLibrary) {
- SingleEntryModuleLibrary d = (SingleEntryModuleLibrary) dependency;
- DefaultIdeaSingleEntryLibraryDependency defaultDependency = new DefaultIdeaSingleEntryLibraryDependency()
- .setFile(d.getLibraryFile())
- .setSource(d.getSourceFile())
- .setJavadoc(d.getJavadocFile())
- .setScope(new DefaultIdeaDependencyScope(d.getScope()))
- .setExported(d.getExported());
-
- if (d.getModuleVersion() != null) {
- defaultDependency.setGradleModuleVersion(new DefaultGradleModuleVersion(d.getModuleVersion()));
- }
- dependencies.add(defaultDependency);
- } else if (dependency instanceof ModuleDependency) {
- ModuleDependency d = (ModuleDependency) dependency;
- IdeaDependency defaultDependency = new DefaultIdeaModuleDependency()
- .setExported(d.getExported())
- .setScope(new DefaultIdeaDependencyScope(d.getScope()))
- .setDependencyModule(modules.get(d.getName()));
- dependencies.add(defaultDependency);
- }
- }
- modules.get(ideaModule.getName()).setDependencies(dependencies);
- }
-
- private void appendModule(Map<String, DefaultIdeaModule> modules, IdeaModule ideaModule, DefaultIdeaProject ideaProject, GradleProject rootGradleProject) {
- DefaultIdeaContentRoot contentRoot = new DefaultIdeaContentRoot()
- .setRootDirectory(ideaModule.getContentRoot())
- .setSourceDirectories(srcDirs(ideaModule.getSourceDirs()))
- .setTestDirectories(srcDirs(ideaModule.getTestSourceDirs()))
- .setExcludeDirectories(ideaModule.getExcludeDirs());
-
- DefaultIdeaModule defaultIdeaModule = new DefaultIdeaModule()
- .setName(ideaModule.getName())
- .setParent(ideaProject)
- .setGradleProject(rootGradleProject.findByPath(ideaModule.getProject().getPath()))
- .setContentRoots(Collections.singletonList(contentRoot))
- .setCompilerOutput(new DefaultIdeaCompilerOutput()
- .setInheritOutputDirs(ideaModule.getInheritOutputDirs() != null ? ideaModule.getInheritOutputDirs() : false)
- .setOutputDir(ideaModule.getOutputDir())
- .setTestOutputDir(ideaModule.getTestOutputDir())
- );
-
- modules.put(ideaModule.getName(), defaultIdeaModule);
- }
-
- private Set<IdeaSourceDirectory> srcDirs(Set<File> sourceDirs) {
- Set<IdeaSourceDirectory> out = new LinkedHashSet<IdeaSourceDirectory>();
- for (File s : sourceDirs) {
- out.add(new DefaultIdeaSourceDirectory().setDirectory(s));
- }
- return out;
- }
-
- public IdeaModelBuilder setOfflineDependencyResolution(boolean offlineDependencyResolution) {
- this.offlineDependencyResolution = offlineDependencyResolution;
- return this;
- }
-}
diff --git a/subprojects/ide/src/main/groovy/org/gradle/tooling/internal/provider/NullResultBuilder.java b/subprojects/ide/src/main/groovy/org/gradle/tooling/internal/provider/NullResultBuilder.java
deleted file mode 100644
index 752770d..0000000
--- a/subprojects/ide/src/main/groovy/org/gradle/tooling/internal/provider/NullResultBuilder.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.provider;
-
-import org.gradle.api.internal.GradleInternal;
-import org.gradle.tooling.internal.protocol.ProjectVersion3;
-
-public class NullResultBuilder implements BuildsModel {
- public boolean canBuild(Class<?> type) {
- return type.equals(Void.class);
- }
-
- public ProjectVersion3 buildAll(GradleInternal gradle) {
- return null;
- }
-}
diff --git a/subprojects/ide/src/main/groovy/org/gradle/tooling/internal/provider/ProjectOutcomesModelBuilder.java b/subprojects/ide/src/main/groovy/org/gradle/tooling/internal/provider/ProjectOutcomesModelBuilder.java
deleted file mode 100644
index eaeaf58..0000000
--- a/subprojects/ide/src/main/groovy/org/gradle/tooling/internal/provider/ProjectOutcomesModelBuilder.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.provider;
-
-import com.google.common.collect.Lists;
-import org.gradle.api.Project;
-import org.gradle.api.artifacts.Configuration;
-import org.gradle.api.artifacts.PublishArtifact;
-import org.gradle.api.internal.GradleInternal;
-import org.gradle.tooling.internal.outcomes.DefaultProjectOutcomes;
-import org.gradle.tooling.internal.protocol.InternalProjectOutcomes;
-import org.gradle.tooling.internal.protocol.ProjectVersion3;
-import org.gradle.tooling.model.DomainObjectSet;
-import org.gradle.tooling.model.internal.ImmutableDomainObjectSet;
-import org.gradle.tooling.model.internal.outcomes.GradleFileBuildOutcome;
-import org.gradle.tooling.model.internal.outcomes.ProjectOutcomes;
-
-import java.util.List;
-
-public class ProjectOutcomesModelBuilder implements BuildsModel {
-
- private final PublishArtifactToFileBuildOutcomeTransformer artifactTransformer = new PublishArtifactToFileBuildOutcomeTransformer();
-
- public boolean canBuild(Class<?> type) {
- return type == InternalProjectOutcomes.class;
- }
-
- public ProjectVersion3 buildAll(GradleInternal gradle) {
- return buildProjectOutput(gradle.getRootProject(), null);
- }
-
- private DefaultProjectOutcomes buildProjectOutput(Project project, ProjectOutcomes parent) {
- DefaultProjectOutcomes projectOutput = new DefaultProjectOutcomes(project.getName(), project.getPath(),
- project.getDescription(), project.getProjectDir(), getFileOutcomes(project), parent);
- for (Project child : project.getChildProjects().values()) {
- projectOutput.addChild(buildProjectOutput(child, projectOutput));
- }
- return projectOutput;
- }
-
- private DomainObjectSet<GradleFileBuildOutcome> getFileOutcomes(Project project) {
- List<GradleFileBuildOutcome> fileBuildOutcomes = Lists.newArrayList();
- addArtifacts(project, fileBuildOutcomes);
- return new ImmutableDomainObjectSet<GradleFileBuildOutcome>(fileBuildOutcomes);
- }
-
- private void addArtifacts(Project project, List<GradleFileBuildOutcome> outcomes) {
- Configuration configuration = project.getConfigurations().findByName("archives");
- if (configuration != null) {
- for (PublishArtifact artifact : configuration.getArtifacts()) {
- GradleFileBuildOutcome outcome = artifactTransformer.transform(artifact, project);
- outcomes.add(outcome);
- }
- }
- }
-
-}
diff --git a/subprojects/ide/src/main/groovy/org/gradle/tooling/internal/provider/PublishArtifactToFileBuildOutcomeTransformer.java b/subprojects/ide/src/main/groovy/org/gradle/tooling/internal/provider/PublishArtifactToFileBuildOutcomeTransformer.java
deleted file mode 100644
index 4c7c445..0000000
--- a/subprojects/ide/src/main/groovy/org/gradle/tooling/internal/provider/PublishArtifactToFileBuildOutcomeTransformer.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.provider;
-
-import org.gradle.api.Project;
-import org.gradle.api.Task;
-import org.gradle.api.artifacts.PublishArtifact;
-import org.gradle.api.internal.artifacts.publish.ArchivePublishArtifact;
-import org.gradle.api.tasks.bundling.*;
-import org.gradle.plugins.ear.Ear;
-import org.gradle.tooling.internal.outcomes.DefaultGradleFileBuildOutcome;
-import org.gradle.tooling.model.internal.outcomes.GradleFileBuildOutcome;
-
-import java.net.URI;
-import java.util.Set;
-
-import static org.gradle.tooling.internal.provider.FileOutcomeIdentifier.*;
-
-public class PublishArtifactToFileBuildOutcomeTransformer {
-
- public GradleFileBuildOutcome transform(PublishArtifact artifact, Project project) {
- String id = getId(artifact, project);
- String taskPath = getTaskPath(artifact);
- String description = getDescription(artifact);
- String typeIdentifier = getTypeIdentifier(artifact);
-
- return new DefaultGradleFileBuildOutcome(id, description, taskPath, artifact.getFile(), typeIdentifier);
- }
-
- private String getId(PublishArtifact artifact, Project project) {
- // Assume that each artifact points to a unique file, and use the relative path from the project as the id
- URI artifactUri = artifact.getFile().toURI();
- URI projectDirUri = project.getProjectDir().toURI();
- URI relativeUri = projectDirUri.relativize(artifactUri);
- return relativeUri.getPath();
- }
-
- private String getDescription(PublishArtifact artifact) {
- return String.format("Publish artifact '%s'", artifact.toString());
- }
-
- private String getTypeIdentifier(PublishArtifact artifact) {
- if (artifact instanceof ArchivePublishArtifact) {
- ArchivePublishArtifact publishArtifact = (ArchivePublishArtifact) artifact;
- AbstractArchiveTask task = publishArtifact.getArchiveTask();
-
- // There is an inheritance hierarchy in play here, so the order
- // of the clauses is very important.
-
- if (task instanceof War) {
- return WAR_ARTIFACT.getTypeIdentifier();
- } else if (task instanceof Ear) {
- return EAR_ARTIFACT.getTypeIdentifier();
- } else if (task instanceof Jar) {
- return JAR_ARTIFACT.getTypeIdentifier();
- } else if (task instanceof Zip) {
- return ZIP_ARTIFACT.getTypeIdentifier();
- } else if (task instanceof Tar) {
- return TAR_ARTIFACT.getTypeIdentifier();
- } else {
- // we don't know about this kind of archive task
- return ARCHIVE_ARTIFACT.getTypeIdentifier();
- }
- } else {
- // This could very well be a zip (or something else we understand), but we can't know for sure.
- // The client may try to infer from the file extension.
- return UNKNOWN_ARTIFACT.getTypeIdentifier();
- }
- }
-
- private String getTaskPath(PublishArtifact artifact) {
- if (artifact instanceof ArchivePublishArtifact) {
- return ((ArchivePublishArtifact) artifact).getArchiveTask().getPath();
- } else {
- String taskPath = null;
- Set<? extends Task> tasks = artifact.getBuildDependencies().getDependencies(null);
- if (!tasks.isEmpty()) {
- taskPath = tasks.iterator().next().getPath();
- }
- return taskPath;
- }
- }
-
-}
diff --git a/subprojects/ide/src/main/groovy/org/gradle/tooling/internal/provider/TasksFactory.java b/subprojects/ide/src/main/groovy/org/gradle/tooling/internal/provider/TasksFactory.java
deleted file mode 100644
index a1215a7..0000000
--- a/subprojects/ide/src/main/groovy/org/gradle/tooling/internal/provider/TasksFactory.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.provider;
-
-import org.gradle.api.Project;
-import org.gradle.api.Task;
-
-import java.util.Map;
-import java.util.Set;
-
-import static java.util.Collections.emptySet;
-
-public class TasksFactory {
- Map<Project, Set<Task>> allTasks;
- private final boolean includeTasks;
-
- public TasksFactory(boolean includeTasks) {
- this.includeTasks = includeTasks;
- }
-
- public void collectTasks(Project root) {
- allTasks = root.getAllTasks(true);
- }
-
- public Set<Task> getTasks(Project project) {
- if (includeTasks) {
- return allTasks.get(project);
- } else {
- return emptySet();
- }
- }
-
-}
\ No newline at end of file
diff --git a/subprojects/ide/src/main/resources/META-INF/services/org.gradle.configuration.project.ProjectConfigureAction b/subprojects/ide/src/main/resources/META-INF/services/org.gradle.configuration.project.ProjectConfigureAction
new file mode 100644
index 0000000..5d07db7
--- /dev/null
+++ b/subprojects/ide/src/main/resources/META-INF/services/org.gradle.configuration.project.ProjectConfigureAction
@@ -0,0 +1 @@
+org.gradle.plugins.ide.internal.tooling.ToolingRegistrationAction
\ No newline at end of file
diff --git a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/EclipsePluginTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/EclipsePluginTest.groovy
index 572fc28..5d51212 100644
--- a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/EclipsePluginTest.groovy
+++ b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/EclipsePluginTest.groovy
@@ -23,14 +23,11 @@ import org.gradle.api.internal.project.DefaultProject
import org.gradle.api.tasks.Delete
import org.gradle.internal.reflect.Instantiator
import org.gradle.plugins.ide.eclipse.model.BuildCommand
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import spock.lang.Specification
-/**
- * @author Hans Dockter
- */
class EclipsePluginTest extends Specification {
- private final DefaultProject project = HelperUtil.createRootProject()
+ private final DefaultProject project = TestUtil.createRootProject()
private final EclipsePlugin eclipsePlugin = new EclipsePlugin(project.services.get(Instantiator))
def applyToBaseProject_shouldOnlyHaveEclipseProjectTask() {
diff --git a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/EclipseWtpPluginTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/EclipseWtpPluginTest.groovy
index 5864bf4..1214ce0 100644
--- a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/EclipseWtpPluginTest.groovy
+++ b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/EclipseWtpPluginTest.groovy
@@ -21,16 +21,13 @@ import org.gradle.internal.reflect.Instantiator
import org.gradle.plugins.ide.eclipse.model.Facet
import org.gradle.plugins.ide.eclipse.model.Facet.FacetType
import org.gradle.plugins.ide.eclipse.model.WbResource
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import spock.lang.Issue
import spock.lang.Specification
-/**
- * @author: Szczepan Faber, created at: 6/28/11
- */
class EclipseWtpPluginTest extends Specification {
- private final DefaultProject project = HelperUtil.createRootProject()
+ private final DefaultProject project = TestUtil.createRootProject()
private final EclipseWtpPlugin wtpPlugin = new EclipseWtpPlugin(project.services.get(Instantiator))
def "has description"() {
diff --git a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/GenerateEclipseClasspathTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/GenerateEclipseClasspathTest.groovy
index b71a31e..cdad8c7 100644
--- a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/GenerateEclipseClasspathTest.groovy
+++ b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/GenerateEclipseClasspathTest.groovy
@@ -20,9 +20,6 @@ import org.gradle.api.internal.ConventionTask
import org.gradle.api.tasks.AbstractSpockTaskTest
import org.gradle.plugins.ide.eclipse.model.EclipseClasspath
-/**
- * @author Hans Dockter
- */
public class GenerateEclipseClasspathTest extends AbstractSpockTaskTest {
private GenerateEclipseClasspath eclipseClasspath;
diff --git a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/GenerateEclipseWtpComponentTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/GenerateEclipseWtpComponentTest.groovy
index b4a6a59..7022ecb 100644
--- a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/GenerateEclipseWtpComponentTest.groovy
+++ b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/GenerateEclipseWtpComponentTest.groovy
@@ -21,9 +21,6 @@ import org.gradle.plugins.ide.eclipse.model.EclipseWtpComponent
import org.gradle.plugins.ide.eclipse.model.WbProperty
import org.gradle.plugins.ide.eclipse.model.WbResource
-/**
- * @author Hans Dockter
- */
public class GenerateEclipseWtpComponentTest extends AbstractSpockTaskTest {
private eclipseComponent = createTask(GenerateEclipseWtpComponent)
diff --git a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/GenerateEclipseWtpFacetTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/GenerateEclipseWtpFacetTest.groovy
index daec953..11d1384 100644
--- a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/GenerateEclipseWtpFacetTest.groovy
+++ b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/GenerateEclipseWtpFacetTest.groovy
@@ -18,9 +18,6 @@ package org.gradle.plugins.ide.eclipse
import org.gradle.api.tasks.AbstractSpockTaskTest
import org.gradle.plugins.ide.eclipse.model.EclipseWtpFacet
-/**
- * @author Hans Dockter
- */
public class GenerateEclipseWtpFacetTest extends AbstractSpockTaskTest {
private eclipseFacet = createTask(GenerateEclipseWtpFacet)
diff --git a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/ClasspathTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/ClasspathTest.groovy
index d560d8c..197ef1b 100644
--- a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/ClasspathTest.groovy
+++ b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/ClasspathTest.groovy
@@ -21,9 +21,6 @@ import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
import org.junit.Rule
import spock.lang.Specification
-/**
- * @author Hans Dockter
- */
public class ClasspathTest extends Specification {
final fileReferenceFactory = new FileReferenceFactory()
final customEntries = [
diff --git a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/ContainerTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/ContainerTest.groovy
index c09942c..49cce22 100644
--- a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/ContainerTest.groovy
+++ b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/ContainerTest.groovy
@@ -17,9 +17,6 @@ package org.gradle.plugins.ide.eclipse.model
import spock.lang.Specification
-/**
- * @author Hans Dockter
- */
class ContainerTest extends Specification {
final static String XML_TEXT = '''
diff --git a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/EclipseModelTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/EclipseModelTest.groovy
index 6de0370..475d865 100644
--- a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/EclipseModelTest.groovy
+++ b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/EclipseModelTest.groovy
@@ -18,9 +18,6 @@ package org.gradle.plugins.ide.eclipse.model
import spock.lang.Specification
-/**
- * @author Szczepan Faber, created at: 4/19/11
- */
class EclipseModelTest extends Specification {
EclipseModel model = new EclipseModel(classpath: new EclipseClasspath(null))
diff --git a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/EclipseProjectTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/EclipseProjectTest.groovy
index d8c4106..ce0afb5 100644
--- a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/EclipseProjectTest.groovy
+++ b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/EclipseProjectTest.groovy
@@ -19,9 +19,6 @@ package org.gradle.plugins.ide.eclipse.model
import org.gradle.api.InvalidUserDataException
import spock.lang.Specification
-/**
- * @author Szczepan Faber, created at: 4/17/11
- */
class EclipseProjectTest extends Specification {
def eclipseProject = new EclipseProject()
diff --git a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/FacetTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/FacetTest.groovy
index 89298dd..7ae7036 100644
--- a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/FacetTest.groovy
+++ b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/FacetTest.groovy
@@ -15,14 +15,9 @@
*/
package org.gradle.plugins.ide.eclipse.model
-import org.gradle.plugins.ide.eclipse.model.Facet.FacetType;
-
+import org.gradle.plugins.ide.eclipse.model.Facet.FacetType
import spock.lang.Specification
-/**
- * @author Hans Dockter
- */
-
class FacetTest extends Specification {
final static String XML_TEXT = '<installed facet="jst.web" version="2.4"/>'
final static String FIXED_XML_TEXT = '<fixed facet="jst.web"/>'
diff --git a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/LibraryTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/LibraryTest.groovy
index ea5c99c..958995e 100644
--- a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/LibraryTest.groovy
+++ b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/LibraryTest.groovy
@@ -19,9 +19,6 @@ import org.gradle.plugins.ide.eclipse.model.internal.FileReferenceFactory
import org.gradle.util.Matchers
import spock.lang.Specification
-/**
- * @author Hans Dockter
- */
class LibraryTest extends Specification {
final static String XML_TEXT_TEMPLATE = '''
diff --git a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/OutputTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/OutputTest.groovy
index 6d5c7c6..fc7aa76 100644
--- a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/OutputTest.groovy
+++ b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/OutputTest.groovy
@@ -17,9 +17,6 @@ package org.gradle.plugins.ide.eclipse.model
import spock.lang.Specification
-/**
- * @author Hans Dockter
- */
class OutputTest extends Specification {
final static String XML_TEXT = '<classpathentry kind="output" path="somePath"/>'
diff --git a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/ProjectDependencyTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/ProjectDependencyTest.groovy
index bc9c15c..3d82775 100644
--- a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/ProjectDependencyTest.groovy
+++ b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/ProjectDependencyTest.groovy
@@ -17,9 +17,6 @@ package org.gradle.plugins.ide.eclipse.model
import spock.lang.Specification
-/**
- * @author Hans Dockter
- */
class ProjectDependencyTest extends Specification {
final static String XML_TEXT = '''
diff --git a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/ProjectTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/ProjectTest.groovy
index 39f0a07..74130f7 100644
--- a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/ProjectTest.groovy
+++ b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/ProjectTest.groovy
@@ -21,9 +21,6 @@ import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
import org.junit.Rule
import spock.lang.Specification
-/**
- * @author Hans Dockter
- */
public class ProjectTest extends Specification {
def static final CUSTOM_REFERENCED_PROJECTS = ['refProject'] as LinkedHashSet
def static final CUSTOM_BUILD_COMMANDS = [new BuildCommand('org.eclipse.jdt.core.scalabuilder', [climate: 'cold'])]
diff --git a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/SourceFolderTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/SourceFolderTest.groovy
index ba9e92c..45bea65 100644
--- a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/SourceFolderTest.groovy
+++ b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/SourceFolderTest.groovy
@@ -17,9 +17,6 @@ package org.gradle.plugins.ide.eclipse.model
import spock.lang.Specification
-/**
- * @author Hans Dockter
- */
class SourceFolderTest extends Specification {
final static String XML_TEXT = '''
<classpathentry including="**/Test1*|**/Test2*" excluding="**/Test3*|**/Test4*" kind="src" output="bin2" path="src">
diff --git a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/VariableTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/VariableTest.groovy
index 3a4e2a9..4a8f9a6 100644
--- a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/VariableTest.groovy
+++ b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/VariableTest.groovy
@@ -19,9 +19,6 @@ import org.gradle.plugins.ide.eclipse.model.internal.FileReferenceFactory
import org.gradle.util.Matchers
import spock.lang.Specification
-/**
- * @author Hans Dockter
- */
class VariableTest extends Specification {
final static String XML_TEXT_TEMPLATE = '''
diff --git a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/WbDependentModuleTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/WbDependentModuleTest.groovy
index 82ea561..cb6f1c4 100644
--- a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/WbDependentModuleTest.groovy
+++ b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/WbDependentModuleTest.groovy
@@ -17,9 +17,6 @@ package org.gradle.plugins.ide.eclipse.model
import spock.lang.Specification
-/**
- * @author Hans Dockter
- */
class WbDependentModuleTest extends Specification {
final static String XML_TEXT = '''
diff --git a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/WbPropertyTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/WbPropertyTest.groovy
index cbdd953..30467b3 100644
--- a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/WbPropertyTest.groovy
+++ b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/WbPropertyTest.groovy
@@ -17,9 +17,6 @@ package org.gradle.plugins.ide.eclipse.model
import spock.lang.Specification
-/**
- * @author Hans Dockter
- */
class WbPropertyTest extends Specification {
final static String XML_TEXT = '<property name="java-output-path" value="/build/classes"/>'
diff --git a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/WbResourceTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/WbResourceTest.groovy
index 12dec70..afaa718 100644
--- a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/WbResourceTest.groovy
+++ b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/WbResourceTest.groovy
@@ -17,9 +17,6 @@ package org.gradle.plugins.ide.eclipse.model
import spock.lang.Specification
-/**
- * @author Hans Dockter
- */
class WbResourceTest extends Specification {
final static String XML_TEXT = '<wb-resource deploy-path="/" source-path="src/main/webapp"/>'
diff --git a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/WtpComponentTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/WtpComponentTest.groovy
index ea49d02..7232eb8 100644
--- a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/WtpComponentTest.groovy
+++ b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/WtpComponentTest.groovy
@@ -21,9 +21,6 @@ import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
import org.junit.Rule
import spock.lang.Specification
-/**
- * @author Hans Dockter
- */
public class WtpComponentTest extends Specification {
private static final List CUSTOM_WB_MODULE_ENTRIES = [
new WbDependentModule('/WEB-INF/lib', "module:/classpath/myapp-1.0.0.jar"),
diff --git a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/WtpFacetTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/WtpFacetTest.groovy
index 97affe7..86c3bd1 100644
--- a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/WtpFacetTest.groovy
+++ b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/WtpFacetTest.groovy
@@ -22,9 +22,6 @@ import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
import org.junit.Rule
import spock.lang.Specification
-/**
- * @author Hans Dockter
- */
public class WtpFacetTest extends Specification {
private static final List CUSTOM_FACETS = [new Facet(FacetType.fixed, 'jst.java', null), new Facet(FacetType.fixed, 'jst.web', null), new Facet(FacetType.installed, 'jst.web', '2.4'), new Facet(FacetType.installed, 'jst.java', '1.4')]
diff --git a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/internal/ProjectDependencyBuilderTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/internal/ProjectDependencyBuilderTest.groovy
index ef31bd0..5abe135 100644
--- a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/internal/ProjectDependencyBuilderTest.groovy
+++ b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/internal/ProjectDependencyBuilderTest.groovy
@@ -16,15 +16,12 @@
package org.gradle.plugins.ide.eclipse.model.internal
import org.gradle.api.Project
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import spock.lang.Specification
-/**
- * @author Szczepan Faber, @date: 11.03.11
- */
class ProjectDependencyBuilderTest extends Specification {
- def Project project = HelperUtil.createRootProject()
+ def Project project = TestUtil.createRootProject()
def ProjectDependencyBuilder builder = new ProjectDependencyBuilder()
def "should create dependency using project name"() {
diff --git a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/idea/ GenerateIdeaModuleTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/idea/ GenerateIdeaModuleTest.groovy
index 8046c28..65e804b 100644
--- a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/idea/ GenerateIdeaModuleTest.groovy
+++ b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/idea/ GenerateIdeaModuleTest.groovy
@@ -17,17 +17,14 @@ package org.gradle.plugins.ide.idea
import org.gradle.api.Project
import org.gradle.api.internal.project.DefaultProject
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import spock.lang.Specification
-/**
- * @author Szczepan Faber, @date 03.03.11
- */
class GenerateIdeaModuleTest extends Specification {
- DefaultProject project = HelperUtil.createRootProject()
- Project childProject = HelperUtil.createChildProject(project, "child", new File("."))
- Project grandChildProject = HelperUtil.createChildProject(childProject, "grandChild", new File("."))
+ DefaultProject project = TestUtil.createRootProject()
+ Project childProject = TestUtil.createChildProject(project, "child", new File("."))
+ Project grandChildProject = TestUtil.createChildProject(childProject, "grandChild", new File("."))
def "moduleName controls outputFile"() {
given:
diff --git a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/idea/IdeaPluginTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/idea/IdeaPluginTest.groovy
index 2935806..3ca7407 100644
--- a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/idea/IdeaPluginTest.groovy
+++ b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/idea/IdeaPluginTest.groovy
@@ -19,17 +19,15 @@ import org.gradle.api.JavaVersion
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.internal.project.DefaultProject
+import org.gradle.api.plugins.scala.ScalaPlugin
import org.gradle.api.tasks.Delete
import org.gradle.plugins.ide.idea.model.IdeaLanguageLevel
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import spock.lang.Specification
-/**
- * @author Hans Dockter
- */
class IdeaPluginTest extends Specification {
- private final DefaultProject project = HelperUtil.createRootProject()
- private final Project childProject = HelperUtil.createChildProject(project, "child", new File("."))
+ private final DefaultProject project = TestUtil.createRootProject()
+ private final Project childProject = TestUtil.createChildProject(project, "child", new File("."))
def "adds 'ideaProject' task to root project"() {
when:
@@ -136,6 +134,21 @@ class IdeaPluginTest extends Specification {
test.any { it.name.contains('test-resources') }
}
+ def "makes scala modules depend on root's project"() {
+ applyPluginToProjects()
+
+ when:
+ childProject.plugins.apply(ScalaPlugin)
+
+ then:
+ def parentIdeaProject = project.tasks.ideaProject
+ def parentIdeaModule = project.tasks.ideaModule
+ def childIdeaModule = childProject.tasks.ideaModule
+
+ childIdeaModule.taskDependencies.getDependencies(childIdeaModule).contains(parentIdeaProject)
+ !parentIdeaModule.taskDependencies.getDependencies(parentIdeaModule).contains(parentIdeaProject)
+ }
+
private void assertThatIdeaModuleIsProperlyConfigured(Project project) {
GenerateIdeaModule ideaModuleTask = project.ideaModule
assert ideaModuleTask instanceof GenerateIdeaModule
diff --git a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/idea/model/IdeaLanguageLevelTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/idea/model/IdeaLanguageLevelTest.groovy
index cd3eb87..6c02a47 100644
--- a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/idea/model/IdeaLanguageLevelTest.groovy
+++ b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/idea/model/IdeaLanguageLevelTest.groovy
@@ -18,9 +18,6 @@ package org.gradle.plugins.ide.idea.model
import org.gradle.api.JavaVersion
import spock.lang.Specification
-/**
- * @author: Szczepan Faber, created at: 7/14/11
- */
class IdeaLanguageLevelTest extends Specification {
def "formats language level in IDEA fancy format"() {
diff --git a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/idea/model/ModuleDependencyTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/idea/model/ModuleDependencyTest.groovy
index da03e65..27ba3d0 100644
--- a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/idea/model/ModuleDependencyTest.groovy
+++ b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/idea/model/ModuleDependencyTest.groovy
@@ -17,9 +17,6 @@ package org.gradle.plugins.ide.idea.model
import spock.lang.Specification
-/**
- * @author Hans Dockter
- */
class ModuleDependencyTest extends Specification {
def equality() {
expect:
diff --git a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/idea/model/ModuleLibraryTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/idea/model/ModuleLibraryTest.groovy
index 4019a41..3503b5e 100644
--- a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/idea/model/ModuleLibraryTest.groovy
+++ b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/idea/model/ModuleLibraryTest.groovy
@@ -17,9 +17,6 @@ package org.gradle.plugins.ide.idea.model
import spock.lang.Specification
-/**
- * @author Hans Dockter
- */
class ModuleLibraryTest extends Specification {
def equality() {
expect:
diff --git a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/idea/model/ModuleTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/idea/model/ModuleTest.groovy
index 24454af..0470bcd 100644
--- a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/idea/model/ModuleTest.groovy
+++ b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/idea/model/ModuleTest.groovy
@@ -19,9 +19,6 @@ import org.gradle.api.JavaVersion
import org.gradle.api.internal.xml.XmlTransformer
import spock.lang.Specification
-/**
- * @author Hans Dockter
- */
class ModuleTest extends Specification {
final PathFactory pathFactory = new PathFactory()
final XmlTransformer xmlTransformer = new XmlTransformer()
diff --git a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/idea/model/ProjectLibraryTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/idea/model/ProjectLibraryTest.groovy
index 61909d3..2563ab5 100644
--- a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/idea/model/ProjectLibraryTest.groovy
+++ b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/idea/model/ProjectLibraryTest.groovy
@@ -16,11 +16,14 @@
package org.gradle.plugins.ide.idea.model
-import org.gradle.internal.SystemProperties
+import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
+import org.junit.Rule
import spock.lang.Specification
class ProjectLibraryTest extends Specification {
+ @Rule TestNameTestDirectoryProvider testDirProvider
+
def "has friendly defaults"() {
def library = new ProjectLibrary()
@@ -46,7 +49,7 @@ class ProjectLibraryTest extends Specification {
}
def "generates correct XML"() {
- def userHome = new File(SystemProperties.javaIoTmpDir)
+ def userHome = testDirProvider.testDirectory
def lib = new ProjectLibrary(name: "lib",
classes: [new File(userHome, "class/one.jar"), new File(userHome, "class/two.jar")] as LinkedHashSet,
diff --git a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/idea/model/ProjectTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/idea/model/ProjectTest.groovy
index 12b7c46..c8cd474 100644
--- a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/idea/model/ProjectTest.groovy
+++ b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/idea/model/ProjectTest.groovy
@@ -19,9 +19,6 @@ import org.gradle.api.JavaVersion
import org.gradle.api.internal.xml.XmlTransformer
import spock.lang.Specification
-/**
- * @author Hans Dockter
- */
class ProjectTest extends Specification {
final PathFactory pathFactory = new PathFactory()
final customModules = [path('file://$PROJECT_DIR$/gradle-idea-plugin.iml')]
diff --git a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/idea/model/internal/ModuleDependencyBuilderTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/idea/model/internal/ModuleDependencyBuilderTest.groovy
index 5f6035d..6cba7a3 100644
--- a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/idea/model/internal/ModuleDependencyBuilderTest.groovy
+++ b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/idea/model/internal/ModuleDependencyBuilderTest.groovy
@@ -16,15 +16,12 @@
package org.gradle.plugins.ide.idea.model.internal
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import spock.lang.Specification
-/**
- * @author Szczepan Faber, @date: 19.03.11
- */
class ModuleDependencyBuilderTest extends Specification {
- def project = HelperUtil.createRootProject()
+ def project = TestUtil.createRootProject()
def builder = new ModuleDependencyBuilder()
def "builds dependency for nonIdea project"() {
diff --git a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/internal/GeneratorTaskTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/internal/GeneratorTaskTest.groovy
index eb21192..cd7d850 100644
--- a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/internal/GeneratorTaskTest.groovy
+++ b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/internal/GeneratorTaskTest.groovy
@@ -18,7 +18,7 @@ package org.gradle.plugins.ide.internal
import org.gradle.plugins.ide.api.GeneratorTask
import org.gradle.plugins.ide.internal.generator.generator.Generator
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import org.junit.Rule
import spock.lang.Specification
@@ -27,7 +27,7 @@ class GeneratorTaskTest extends Specification {
final Generator<TestConfigurationObject> generator = Mock()
final File inputFile = tmpDir.file('input')
final File outputFile = tmpDir.file('output')
- final GeneratorTask<TestConfigurationObject> task = HelperUtil.createTask(GeneratorTask)
+ final GeneratorTask<TestConfigurationObject> task = TestUtil.createTask(GeneratorTask)
def setup() {
task.inputFile = inputFile
diff --git a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/internal/IdePluginTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/internal/IdePluginTest.groovy
index 6a1e00f..9ddf703 100644
--- a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/internal/IdePluginTest.groovy
+++ b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/internal/IdePluginTest.groovy
@@ -19,11 +19,11 @@ import org.gradle.api.DefaultTask
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.tasks.Delete
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import spock.lang.Specification
class IdePluginTest extends Specification {
- final Project project = HelperUtil.createRootProject()
+ final Project project = TestUtil.createRootProject()
def addsLifecycleTasks() {
when:
diff --git a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/internal/configurer/DeduplicationTargetTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/internal/configurer/DeduplicationTargetTest.groovy
index 4533691..b2d0173 100644
--- a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/internal/configurer/DeduplicationTargetTest.groovy
+++ b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/internal/configurer/DeduplicationTargetTest.groovy
@@ -16,20 +16,17 @@
package org.gradle.plugins.ide.internal.configurer
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import spock.lang.Specification
-/**
- * @author Szczepan Faber, @date: 14.03.11
- */
class DeduplicationTargetTest extends Specification {
def "knows candidate names"() {
when:
- def project = HelperUtil.createRootProject()
+ def project = TestUtil.createRootProject()
assert project.name == 'test'
- def childProject = HelperUtil.createChildProject(project, "child", new File("."))
- def grandChildProject = HelperUtil.createChildProject(childProject, "grandChild", new File("."))
+ def childProject = TestUtil.createChildProject(project, "child", new File("."))
+ def grandChildProject = TestUtil.createChildProject(childProject, "grandChild", new File("."))
then:
new DeduplicationTarget(project: project, moduleName: 'test' ).candidateNames == ['test']
@@ -39,9 +36,9 @@ class DeduplicationTargetTest extends Specification {
def "uses passed module name instead of project name"() {
when:
- def project = HelperUtil.createRootProject()
+ def project = TestUtil.createRootProject()
assert project.name == 'test'
- def childProject = HelperUtil.createChildProject(project, "child", new File("."))
+ def childProject = TestUtil.createChildProject(project, "child", new File("."))
then:
new DeduplicationTarget(project: project, moduleName: 'ROOT' ).candidateNames == ['ROOT']
diff --git a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/internal/configurer/ModuleNameDeduperTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/internal/configurer/ModuleNameDeduperTest.groovy
index 0be9b55..2d3f40d 100644
--- a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/internal/configurer/ModuleNameDeduperTest.groovy
+++ b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/internal/configurer/ModuleNameDeduperTest.groovy
@@ -18,9 +18,6 @@ package org.gradle.plugins.ide.internal.configurer
import spock.lang.Specification
-/**
- * @author Szczepan Faber, @date: 14.03.11
- */
class ModuleNameDeduperTest extends Specification {
public static class TargetStub extends DeduplicationTarget {
diff --git a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/internal/configurer/ProjectDeduperTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/internal/configurer/ProjectDeduperTest.groovy
index ee425d9..552bbb9 100644
--- a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/internal/configurer/ProjectDeduperTest.groovy
+++ b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/internal/configurer/ProjectDeduperTest.groovy
@@ -18,17 +18,14 @@
package org.gradle.plugins.ide.internal.configurer
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import spock.lang.Specification
-/**
- * @author Szczepan Faber, @date: 14.03.11
- */
class ProjectDeduperTest extends Specification {
- def project = HelperUtil.createRootProject()
- def childProject = HelperUtil.createChildProject(project, "child", new File("."))
- def grandChildProject = HelperUtil.createChildProject(childProject, "grandChild", new File("."))
+ def project = TestUtil.createRootProject()
+ def childProject = TestUtil.createChildProject(project, "child", new File("."))
+ def grandChildProject = TestUtil.createChildProject(childProject, "grandChild", new File("."))
def deduper = new ProjectDeduper()
diff --git a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/internal/tooling/GradleBuildBuilderTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/internal/tooling/GradleBuildBuilderTest.groovy
new file mode 100644
index 0000000..35fdc9a
--- /dev/null
+++ b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/internal/tooling/GradleBuildBuilderTest.groovy
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.plugins.ide.internal.tooling
+
+import org.gradle.util.TestUtil
+import spock.lang.Shared
+import spock.lang.Specification
+
+class GradleBuildBuilderTest extends Specification {
+ def builder = new GradleBuildBuilder()
+ @Shared def project = TestUtil.builder().withName("root").build()
+ @Shared def child1 = TestUtil.builder().withName("child1").withParent(project).build()
+ @Shared def child2 = TestUtil.builder().withName("child2").withParent(project).build()
+
+ def "builds model"() {
+ expect:
+ def model = builder.buildAll("org.gradle.tooling.model.gradle.GradleBuild", startProject)
+ model.rootProject.path == ":"
+ model.rootProject.name == "root"
+ model.rootProject.parent == null
+ model.rootProject.projectDirectory == project.projectDir
+ model.rootProject.children.size() == 2
+ model.rootProject.children.every { it.parent == model.rootProject }
+ model.projects*.name == ["root", "child1", "child2"]
+ model.projects*.path == [":", ":child1", ":child2"]
+
+ where:
+ startProject | _
+ project | _
+ child2 | _
+ }
+}
diff --git a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/internal/tooling/GradleProjectBuilderTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/internal/tooling/GradleProjectBuilderTest.groovy
new file mode 100644
index 0000000..0b01e27
--- /dev/null
+++ b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/internal/tooling/GradleProjectBuilderTest.groovy
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.plugins.ide.internal.tooling
+
+import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
+import org.gradle.util.TestUtil
+import org.junit.Rule
+import spock.lang.Specification
+
+class GradleProjectBuilderTest extends Specification {
+ @Rule TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider()
+ final def builder = new GradleProjectBuilder()
+
+ def "builds basics for project"() {
+ def buildFile = tmpDir.file("build.gradle") << "//empty"
+ def project = TestUtil.builder().withName("test").withProjectDir(tmpDir.testDirectory).build()
+ project.description = 'a test project'
+
+ when:
+ def model = builder.buildAll(project)
+
+ then:
+ model.path == ':'
+ model.name == 'test'
+ model.description == 'a test project'
+ model.buildScript.sourceFile == buildFile
+ }
+}
diff --git a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/internal/tooling/TasksFactoryTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/internal/tooling/TasksFactoryTest.groovy
new file mode 100644
index 0000000..e55ec83
--- /dev/null
+++ b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/internal/tooling/TasksFactoryTest.groovy
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.plugins.ide.internal.tooling
+
+import org.gradle.api.Project
+import org.gradle.api.internal.AbstractTask
+import org.gradle.plugins.ide.internal.tooling.eclipse.DefaultEclipseProject
+import org.gradle.util.TestUtil
+import spock.lang.Specification
+
+class TasksFactoryTest extends Specification {
+ final Project project = Mock()
+ final org.gradle.tooling.internal.protocol.eclipse.EclipseProjectVersion3 eclipseProject = new DefaultEclipseProject(null, null, null, null, [])
+ final task = TestUtil.createTask(AbstractTask)
+
+ def "does not return tasks"() {
+ TasksFactory factory = new TasksFactory(false)
+
+ when:
+ factory.allTasks = [:]
+ factory.allTasks.put(project, [task] as Set)
+ def tasks = factory.getTasks(project)
+
+ then:
+ tasks.empty
+ }
+
+ def "returns tasks"() {
+ TasksFactory factory = new TasksFactory(true)
+
+ when:
+ factory.allTasks = [:]
+ factory.allTasks.put(project, [task] as Set)
+ def tasks = factory.getTasks(project)
+
+ then:
+ tasks.size() == 1
+ }
+}
diff --git a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/internal/tooling/eclipse/DefaultEclipseProjectTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/internal/tooling/eclipse/DefaultEclipseProjectTest.groovy
new file mode 100644
index 0000000..b0c6eda
--- /dev/null
+++ b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/internal/tooling/eclipse/DefaultEclipseProjectTest.groovy
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.plugins.ide.internal.tooling.eclipse
+
+import spock.lang.Specification
+
+class DefaultEclipseProjectTest extends Specification {
+ def usesPathForToStringValue() {
+ def project = new DefaultEclipseProject("name", ":path", null, null, [])
+
+ expect:
+ project.toString() == "project ':path'"
+ }
+}
diff --git a/subprojects/ide/src/test/groovy/org/gradle/tooling/internal/provider/PublishArtifactToFileBuildOutcomeTransformerTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/tooling/internal/provider/PublishArtifactToFileBuildOutcomeTransformerTest.groovy
deleted file mode 100644
index b21daf6..0000000
--- a/subprojects/ide/src/test/groovy/org/gradle/tooling/internal/provider/PublishArtifactToFileBuildOutcomeTransformerTest.groovy
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.provider
-
-import org.gradle.api.Task
-import org.gradle.api.artifacts.PublishArtifact
-import org.gradle.api.internal.artifacts.publish.ArchivePublishArtifact
-import org.gradle.api.tasks.TaskDependency
-import org.gradle.plugins.ear.Ear
-import org.gradle.tooling.model.internal.outcomes.GradleFileBuildOutcome
-import spock.lang.Specification
-import spock.lang.Unroll
-import org.gradle.api.tasks.bundling.*
-
-import static org.gradle.tooling.internal.provider.FileOutcomeIdentifier.*
-import org.gradle.util.HelperUtil
-import org.gradle.api.Project
-
-class PublishArtifactToFileBuildOutcomeTransformerTest extends Specification {
-
- def transformer = new PublishArtifactToFileBuildOutcomeTransformer()
-
- Project project = HelperUtil.createRootProject()
-
- @Unroll
- "can create outcome for #taskClass archive artifact"(Class<? extends AbstractArchiveTask> taskClass, FileOutcomeIdentifier typeIdentifier) {
- given:
- AbstractArchiveTask task = Mock(taskClass)
- PublishArtifact artifact = new ArchivePublishArtifact(task)
-
- and:
- _ * task.getArchivePath() >> project.file("file")
-
- when:
- GradleFileBuildOutcome outcome = transformer.transform(artifact, project)
-
- then:
- outcome.typeIdentifier == typeIdentifier.typeIdentifier
- outcome.id == "file"
-
- where:
- taskClass | typeIdentifier
- Zip | ZIP_ARTIFACT
- Jar | JAR_ARTIFACT
- Ear | EAR_ARTIFACT
- Tar | TAR_ARTIFACT
- War | WAR_ARTIFACT
- AbstractArchiveTask | ARCHIVE_ARTIFACT
- }
-
- def "can handle generic publish artifact"() {
- given:
- def task = Mock(Task)
- def taskDependency = Mock(TaskDependency)
- def artifact = Mock(PublishArtifact)
-
- 1 * taskDependency.getDependencies(null) >>> [[task] as Set]
- 1 * task.getPath() >> "path"
- _ * artifact.getFile() >> project.file("file")
- 1 * artifact.getBuildDependencies() >> taskDependency
-
- when:
- def outcome = transformer.transform(artifact, project)
-
- then:
- outcome.typeIdentifier == UNKNOWN_ARTIFACT.typeIdentifier
- outcome.taskPath == "path"
- outcome.id == "file"
- }
-
-
-}
diff --git a/subprojects/ide/src/test/groovy/org/gradle/tooling/internal/provider/TasksFactoryTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/tooling/internal/provider/TasksFactoryTest.groovy
deleted file mode 100644
index eae6dbe..0000000
--- a/subprojects/ide/src/test/groovy/org/gradle/tooling/internal/provider/TasksFactoryTest.groovy
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.provider
-
-import org.gradle.api.Project
-import org.gradle.api.internal.AbstractTask
-import org.gradle.tooling.internal.eclipse.DefaultEclipseProject
-import org.gradle.util.HelperUtil
-import spock.lang.Specification
-
-class TasksFactoryTest extends Specification {
- final Project project = Mock()
- final org.gradle.tooling.internal.protocol.eclipse.EclipseProjectVersion3 eclipseProject = new DefaultEclipseProject(null, null, null, null, [])
- final task = HelperUtil.createTask(AbstractTask)
-
- def "does not return tasks"() {
- TasksFactory factory = new TasksFactory(false)
-
- when:
- factory.allTasks = [:]
- factory.allTasks.put(project, [task] as Set)
- def tasks = factory.getTasks(project)
-
- then:
- tasks.empty
- }
-
- def "returns tasks"() {
- TasksFactory factory = new TasksFactory(true)
-
- when:
- factory.allTasks = [:]
- factory.allTasks.put(project, [task] as Set)
- def tasks = factory.getTasks(project)
-
- then:
- tasks.size() == 1
- }
-}
diff --git a/subprojects/integ-test/integ-test.gradle b/subprojects/integ-test/integ-test.gradle
index 8be66bf..0220496 100644
--- a/subprojects/integ-test/integ-test.gradle
+++ b/subprojects/integ-test/integ-test.gradle
@@ -1,5 +1,5 @@
dependencies {
- groovy libraries.groovy
+ integTestCompile libraries.groovy
integTestCompile project(':toolingApi')
integTestCompile project(':launcher')
@@ -19,7 +19,6 @@ integTestTasks.all {
doFirst {
systemProperties['integTest.userGuideInfoDir'] = project(':docs').docbookSrc
systemProperties['integTest.userGuideOutputDir'] = new File(project(':docs').samplesSrcDir, "userguideOutput").absolutePath
- forkEvery = 15
}
// You can filter the userguide samples to be run by specifying this system property.
@@ -27,10 +26,6 @@ integTestTasks.all {
systemProperty "org.gradle.userguide.samples.filter", System.getProperty("org.gradle.userguide.samples.filter")
}
-daemonIntegTest {
- exclude "**/CrossVersionCompatibilityIntegrationTest.class" //ignored just in case to avoid old daemon implementation
-}
-
parallelIntegTest {
systemProperty "org.gradle.userguide.samples.exclude", "multiProjectBuildSrc,multiprojectMessagesHack"
}
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/api/tasks/TaskCommandLineConfigurationIntegrationSpec.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/api/tasks/TaskCommandLineConfigurationIntegrationSpec.groovy
deleted file mode 100644
index f7f8d78..0000000
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/api/tasks/TaskCommandLineConfigurationIntegrationSpec.groovy
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.tasks
-
-import org.gradle.integtests.fixtures.AbstractIntegrationSpec
-import spock.lang.Ignore
-
-/**
- * by Szczepan Faber, created at: 9/5/12
- */
-class TaskCommandLineConfigurationIntegrationSpec extends AbstractIntegrationSpec {
-
- final String someConfigurableTaskType = """
- import org.gradle.api.internal.tasks.CommandLineOption
-
- class SomeTask extends DefaultTask {
- boolean first
- String second
-
- @CommandLineOption(options = "first", description = "configures 'first' field")
- void setFirst(boolean first) {
- this.first = first
- }
-
- @CommandLineOption(options = "second", description = "configures 'second' field")
- void setSecond(String second) {
- this.second = second
- }
-
- //more stress
- void setSecond(Object second) {
- this.second = second.toString()
- }
-
- @TaskAction
- void renderFields() {
- println "first=" + first + ",second=" + second
- }
- }"""
-
- def "can configure task from command line in multiple projects"() {
- given:
- file("settings.gradle") << "include 'project2'"
- file("build.gradle") << """
- allprojects {
- task someTask(type: SomeTask)
- }
- task task1 //extra stress
- task task2
-
- $someConfigurableTaskType
-"""
-
- when:
- run 'someTask'
-
- then:
- output.contains 'first=false,second=null'
-
- when:
- run 'task1', 'someTask', '--first', '--second', 'hey buddy', 'task2'
-
- then:
- output.count('first=true,second=hey buddy') == 2
- result.assertTasksExecuted(":task1", ":someTask", ":project2:someTask", ":task2")
- }
-
- def "tasks can be configured with different options"() {
- given:
- file("settings.gradle") << "include 'project2'"
- file("build.gradle") << """
- allprojects {
- task someTask(type: SomeTask)
- }
-
- $someConfigurableTaskType
-"""
-
- when:
- run ':someTask', '--second', 'one', ':project2:someTask', '--second', 'two'
-
- then:
- result.assertTasksExecuted(":someTask", ":project2:someTask")
- output.count('second=one') == 1
- output.count('second=two') == 1
- }
-
- def "tasks are configured exclusively with their options"() {
- given:
- file("settings.gradle") << "include 'project2'"
- file("build.gradle") << """
- allprojects {
- task someTask(type: SomeTask)
- }
-
- $someConfigurableTaskType
-"""
-
- when:
- run ':someTask', '--second', 'one', ':project2:someTask', '--first'
-
- then:
- result.assertTasksExecuted(":someTask", ":project2:someTask")
- output.count('first=false,second=one') == 1 //--first flag was set only on the :project2:someTask
- output.count('first=true,second=null') == 1 //--second option was set only on the :someTask
- }
-
- def "task name that matches command value is not included in execution"() {
- given:
- file("build.gradle") << """
- task foo
- task someTask(type: SomeTask)
-
- $someConfigurableTaskType
-"""
-
- when:
- run 'someTask', '--second', 'foo'
-
- then:
- output.contains 'second=foo'
- result.assertTasksExecuted(":someTask") //no 'foo' task
- }
-
- def "multiple different tasks configured at single command line"() {
- given:
- file("build.gradle") << """
- task foo
- task someTask(type: SomeTask)
-
- $someConfigurableTaskType
-"""
-
- when:
- run 'someTask', '--second', 'foo', 'tasks', '--all'
-
- then:
- output.contains 'second=foo'
- result.assertTasksExecuted(":someTask", ":tasks")
- }
-
- def "different tasks match name but only one accepts the option"() {
- given:
- file("settings.gradle") << "include 'other'"
- file("build.gradle") << """
- task someTask(type: SomeTask)
- project(":other") {
- task someTask
- }
-
- $someConfigurableTaskType
-"""
-
- when:
- def failure = runAndFail 'someTask', '--first'
-
- then:
- failure.assertHasDescription("Problem configuring task :other:someTask from command line. Unknown command-line option '--first'.")
- }
-
- def "using an unknown option yields decent error message"() {
- given:
- file("build.gradle") << """
- task foo
- task someTask(type: SomeTask)
- task someTask2(type: SomeTask)
-
- $someConfigurableTaskType
-"""
-
- when:
- runAndFail 'someTask', '--second', 'foo', 'someTask2', '--secon', 'bar'
-
- then:
- failure.assertHasDescription("Problem configuring task :someTask2 from command line. Unknown command-line option '--secon'.")
-
- //TODO SF it's not fixable easily we would need to change some stuff in options parsing. See also ignore test method below.
-// when:
-// runAndFail 'someTask', '-second', 'foo'
-//
-// then:
-// failure.assertHasDescription("Problem configuring task :someTask from command line. Unknown command-line option '-second'.")
-
- when:
- runAndFail 'someTask', '--second'
-
- then:
- failure.assertHasDescription("Problem configuring task :someTask from command line. No argument was provided for command-line option '--second'.")
-
- when:
- runAndFail 'someTask', '--second', 'hey', '--second', 'buddy'
-
- then:
- failure.assertHasDescription("Problem configuring task :someTask from command line. Multiple arguments were provided for command-line option '--second'.")
- }
-
- def "single dash user error yields decent error message"() {
- when:
- runAndFail 'tasks', '-all'
-
- then:
- failure.assertHasDescription("Problem configuring task :tasks from command line. Unknown command-line option '-l'.")
- }
-
- @Ignore
- //more work & design decisions needed
- def "single dash error is detected in the subsequent option"() {
- given:
- file("build.gradle") << """
- task someTask(type: SomeTask)
-
- $someConfigurableTaskType
-"""
-
- when:
- runAndFail 'someTask', '--first', '-second', 'foo'
-
- then:
- failure.assertHasDescription("Incorrect command line arguments: [-l, -l]. Task options require double dash, for example: 'gradle tasks --all'.")
- }
-
- @Ignore
- //some existing problems with command line interface
- def "unfriendly behavior of command line parsing"() {
- when:
- run '-all'
-
- then:
- "should fail with a decent error, not internal error (applies to all CommandLineArgumentExceptions)"
- "should complain that there's no '-all' option"
-
- when:
- run 'tasks', '-refresh-dependenciess'
-
- then:
- "should fail in a consistent way as with '--refresh-dependenciess'"
- }
-}
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/debug/GradleBuildRunner.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/debug/GradleBuildRunner.groovy
index fc64f1a..aac6770 100644
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/debug/GradleBuildRunner.groovy
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/debug/GradleBuildRunner.groovy
@@ -20,8 +20,6 @@ import org.gradle.launcher.Main
/**
* Use this class to run/debug any gradle build from the IDE. Especially useful for learning & debugging Gradle internals.
- *
- * @author: Szczepan Faber, created at: 4/30/11
*/
class GradleBuildRunner {
public static void main(String[] args) {
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/debug/GradleRunConfiguration.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/debug/GradleRunConfiguration.groovy
index 4973cab..6b0d396 100644
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/debug/GradleRunConfiguration.groovy
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/debug/GradleRunConfiguration.groovy
@@ -21,8 +21,6 @@ import org.gradle.launcher.Main
/**
* Used by IDEA run configuration created as part of 'gradle idea' run.
* Required because dependency on 'launcher' project has scope 'test'.
- *
- * @author: Szczepan Faber, created at: 4/30/11
*/
class GradleRunConfiguration {
public static void main(String[] args) {
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/ApplicationIntegrationSpec.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/ApplicationIntegrationSpec.groovy
index ac87fb6..9864d0e 100644
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/ApplicationIntegrationSpec.groovy
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/ApplicationIntegrationSpec.groovy
@@ -97,7 +97,7 @@ class ApplicationIntegrationSpec extends AbstractIntegrationSpec {
and:
def distBase = file("build/install/app")
distBase.file("docs").directory
- distBase.file("docs/readme.txt").exists() == false
+ !distBase.file("docs/readme.txt").exists()
distBase.file("docs/READ-ME.txt").text == "Read me!!!"
}
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/ApplicationIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/ApplicationIntegrationTest.groovy
index b0cbb6b..d852b53 100644
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/ApplicationIntegrationTest.groovy
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/ApplicationIntegrationTest.groovy
@@ -67,6 +67,152 @@ class Main {
result.assertNormalExitValue()
}
+ def canUseDefaultJvmArgsToPassMultipleOptionsToJvmWhenRunningScript() {
+ file("build.gradle") << '''
+apply plugin: 'application'
+mainClassName = 'org.gradle.test.Main'
+applicationName = 'application'
+applicationDefaultJvmArgs = ['-DtestValue=value', '-DtestValue2=some value', '-DtestValue3=some value']
+'''
+ file('src/main/java/org/gradle/test/Main.java') << '''
+package org.gradle.test;
+
+class Main {
+ public static void main(String[] args) {
+ if (!"value".equals(System.getProperty("testValue"))) {
+ throw new RuntimeException("Expected system property not specified");
+ }
+ if (!"some value".equals(System.getProperty("testValue2"))) {
+ throw new RuntimeException("Expected system property not specified");
+ }
+ if (!"some value".equals(System.getProperty("testValue3"))) {
+ throw new RuntimeException("Expected system property not specified");
+ }
+ }
+}
+'''
+
+ when:
+ run 'install'
+
+ def builder = new ScriptExecuter()
+ builder.workingDir file('build/install/application/bin')
+ builder.executable "application"
+
+ def result = builder.run()
+
+ then:
+ result.assertNormalExitValue()
+ }
+
+ def canUseBothDefaultJvmArgsAndEnvironmentVariableToPassOptionsToJvmWhenRunningScript() {
+ file("build.gradle") << '''
+apply plugin: 'application'
+mainClassName = 'org.gradle.test.Main'
+applicationName = 'application'
+applicationDefaultJvmArgs = ['-Dvar1=value1', '-Dvar2=some value2']
+'''
+ file('src/main/java/org/gradle/test/Main.java') << '''
+package org.gradle.test;
+
+class Main {
+ public static void main(String[] args) {
+ if (!"value1".equals(System.getProperty("var1"))) {
+ throw new RuntimeException("Expected system property not specified");
+ }
+ if (!"some value2".equals(System.getProperty("var2"))) {
+ throw new RuntimeException("Expected system property not specified");
+ }
+ if (!"value3".equals(System.getProperty("var3"))) {
+ throw new RuntimeException("Expected system property not specified");
+ }
+ }
+}
+'''
+
+ when:
+ run 'install'
+
+ def builder = new ScriptExecuter()
+ builder.workingDir file('build/install/application/bin')
+ builder.executable "application"
+ builder.environment('APPLICATION_OPTS', '-Dvar3=value3')
+
+ def result = builder.run()
+
+ then:
+ result.assertNormalExitValue()
+ }
+
+ def canUseDefaultJvmArgsToPassMultipleOptionsWithShellMetacharactersToJvmWhenRunningScript() {
+ //even in single-quoted multi-line strings, backslashes must still be quoted
+ file("build.gradle") << '''
+apply plugin: 'application'
+mainClassName = 'org.gradle.test.Main'
+applicationName = 'application'
+applicationDefaultJvmArgs = ['-DtestValue=value',
+ /-DtestValue2=s\\o"me val'ue/ + '$PATH',
+ /-DtestValue3=so\\"me value%PATH%/,
+ ]
+'''
+ file('src/main/java/org/gradle/test/Main.java') << '''
+package org.gradle.test;
+
+class Main {
+ public static void main(String[] args) {
+ if (!"value".equals(System.getProperty("testValue"))) {
+ throw new RuntimeException("Expected system property not specified (testValue)");
+ }
+ if (!"s\\\\o\\"me val'ue$PATH".equals(System.getProperty("testValue2"))) {
+ throw new RuntimeException("Expected system property not specified (testValue2)");
+ }
+ if (!"so\\\\\\"me value%PATH%".equals(System.getProperty("testValue3"))) {
+ throw new RuntimeException("Expected system property not specified (testValue3)");
+ }
+ }
+}
+'''
+
+ when:
+ run 'install'
+
+ def builder = new ScriptExecuter()
+ builder.workingDir file('build/install/application/bin')
+ builder.executable "application"
+
+ def result = builder.run()
+
+ then:
+ result.assertNormalExitValue()
+ }
+
+ def canUseDefaultJvmArgsInRunTask() {
+ file("build.gradle") << '''
+ apply plugin: 'application'
+ mainClassName = 'org.gradle.test.Main'
+ applicationName = 'application'
+ applicationDefaultJvmArgs = ['-Dvar1=value1', '-Dvar2=value2']
+ '''
+ file('src/main/java/org/gradle/test/Main.java') << '''
+ package org.gradle.test;
+
+ class Main {
+ public static void main(String[] args) {
+ if (!"value1".equals(System.getProperty("var1"))) {
+ throw new RuntimeException("Expected system property not specified (var1)");
+ }
+ if (!"value2".equals(System.getProperty("var2"))) {
+ throw new RuntimeException("Expected system property not specified (var2)");
+ }
+ }
+ }
+ '''
+
+ expect:
+ run 'run'
+ }
+
+
def "can customize application name"() {
file('settings.gradle') << 'rootProject.name = "application"'
file('build.gradle') << '''
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/BuildAggregationIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/BuildAggregationIntegrationTest.groovy
index 8a8eb23..21b3bbc 100644
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/BuildAggregationIntegrationTest.groovy
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/BuildAggregationIntegrationTest.groovy
@@ -18,6 +18,7 @@ package org.gradle.integtests
import org.gradle.integtests.fixtures.AbstractIntegrationTest
import org.gradle.integtests.fixtures.executer.ExecutionFailure
import org.gradle.test.fixtures.file.TestFile
+import org.hamcrest.Matchers
import org.junit.Test
class BuildAggregationIntegrationTest extends AbstractIntegrationTest {
@@ -77,7 +78,7 @@ class BuildAggregationIntegrationTest extends AbstractIntegrationTest {
ExecutionFailure failure = executer.withTasks('build').runWithFailure()
failure.assertHasFileName("Build file '${other}'")
failure.assertHasLineNumber(2)
- failure.assertHasDescription('A problem occurred evaluating root project')
+ failure.assertThatDescription(Matchers.startsWith('A problem occurred evaluating root project'))
failure.assertHasCause('broken')
}
@@ -85,6 +86,6 @@ class BuildAggregationIntegrationTest extends AbstractIntegrationTest {
public void reportsBuildSrcFailure() {
file('buildSrc/src/main/java/Broken.java') << 'broken!'
ExecutionFailure failure = executer.runWithFailure()
- failure.assertHasDescription('Execution failed for task \':compileJava\'')
+ failure.assertHasDescription('Execution failed for task \':compileJava\'.')
}
}
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/BuildScriptClasspathIntegrationTest.java b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/BuildScriptClasspathIntegrationTest.java
index 950ce2f..7e1bdbf 100644
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/BuildScriptClasspathIntegrationTest.java
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/BuildScriptClasspathIntegrationTest.java
@@ -183,7 +183,6 @@ public class BuildScriptClasspathIntegrationTest extends AbstractIntegrationTest
"include 'child'"
);
testFile("build.gradle").writelns(
- "assert gradle.scriptClassLoader == buildscript.classLoader.parent",
"buildscript {",
" repositories { flatDir { dirs 'repo' }}",
" dependencies { classpath name: 'test', version: '1.3' }",
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/BuildScriptErrorIntegrationTest.java b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/BuildScriptErrorIntegrationTest.java
deleted file mode 100644
index 7a68f75..0000000
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/BuildScriptErrorIntegrationTest.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.integtests;
-
-import org.gradle.integtests.fixtures.AbstractIntegrationTest;
-import org.gradle.integtests.fixtures.executer.ExecutionFailure;
-import org.gradle.test.fixtures.file.TestFile;
-import org.junit.Ignore;
-import org.junit.Test;
-
-import static org.gradle.util.Matchers.containsLine;
-
-public class BuildScriptErrorIntegrationTest extends AbstractIntegrationTest {
- @Test
- public void reportsProjectEvaluationFailsWithGroovyException() {
- TestFile buildFile = testFile("build.gradle");
- buildFile.writelns("", "createTakk('do-stuff')");
- ExecutionFailure failure = usingBuildFile(buildFile).runWithFailure();
-
- failure.assertHasFileName(String.format("Build file '%s'", buildFile));
- failure.assertHasLineNumber(2);
- failure.assertHasDescription("A problem occurred evaluating root project 'reportsProjectEvaluationFailsWithGroovyException");
- failure.assertHasCause("Could not find method createTakk() for arguments [do-stuff] on root project 'reportsProjectEvaluationFailsWithGroovyException");
- }
-
- @Test
- public void reportsScriptCompilationException() {
- TestFile buildFile = testFile("build.gradle");
- buildFile.writelns(
- "// a comment",
- "import org.gradle.unknown.Unknown",
- "new Unknown()");
- ExecutionFailure failure = inTestDirectory().runWithFailure();
- failure.assertHasFileName(String.format("Build file '%s'", buildFile));
- failure.assertHasLineNumber(2);
- failure.assertHasDescription(String.format("Could not compile build file '%s'.", buildFile));
- failure.assertThatCause(containsLine(String.format("build file '%s': 2: unable to resolve class org.gradle.unknown.Unknown", buildFile)));
- }
-
- @Test
- public void reportsNestedProjectEvaluationFailsWithRuntimeException() {
- testFile("settings.gradle").write("include 'child'");
-
- TestFile buildFile = testFile("build.gradle");
- buildFile.writelns(
- "evaluationDependsOn 'child'",
- "task t");
-
- TestFile childBuildFile = testFile("child/build.gradle");
- childBuildFile.writelns(
- "def broken = { ->",
- " throw new RuntimeException('failure') }",
- "broken()");
- ExecutionFailure failure = inTestDirectory().withTasks("t").runWithFailure();
-
- failure.assertHasFileName(String.format("Build file '%s'", childBuildFile));
- failure.assertHasLineNumber(2);
- failure.assertHasDescription("A problem occurred evaluating project ':child'");
- failure.assertHasCause("failure");
- }
-
- @Test
- public void reportsTaskGraphReadyEventFailsWithRuntimeException() {
- TestFile buildFile = testFile("build.gradle");
- buildFile.writelns(
- "gradle.taskGraph.whenReady {",
- "throw new RuntimeException('broken closure')",
- "}",
- "task a");
-
- ExecutionFailure failure = usingBuildFile(buildFile).withTasks("a").runWithFailure();
-
- failure.assertHasFileName(String.format("Build file '%s'", buildFile));
- failure.assertHasLineNumber(2);
- failure.assertHasDescription("broken closure");
- failure.assertHasNoCause();
- }
-
- @Test @Ignore
- public void reportsTaskDependencyClosureFailsWithRuntimeException() {
- TestFile buildFile = testFile("build.gradle");
- buildFile.writelns(
- "task a",
- "a.dependsOn {",
- "throw new RuntimeException('broken')",
- "}");
-
- ExecutionFailure failure = usingBuildFile(buildFile).withTasks("a").runWithFailure();
-
- failure.assertHasFileName(String.format("Build file '%s'", buildFile));
- failure.assertHasLineNumber(3);
- failure.assertHasDescription("??");
- failure.assertHasCause("broken");
- }
-}
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/BuildScriptExecutionIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/BuildScriptExecutionIntegrationTest.groovy
index cb5cd9a..4dbf474 100644
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/BuildScriptExecutionIntegrationTest.groovy
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/BuildScriptExecutionIntegrationTest.groovy
@@ -41,7 +41,6 @@ assert "${buildScript.absolutePath.replace("\\", "\\\\")}" == buildscript.source
assert "${buildScript.toURI()}" == buildscript.sourceURI as String
assert buildscript.classLoader == getClass().classLoader.parent
assert buildscript.classLoader == Thread.currentThread().contextClassLoader
-assert gradle.scriptClassLoader == buildscript.classLoader.parent
Gradle.class.classLoader.loadClass('${implClassName}')
try {
buildscript.classLoader.loadClass('${implClassName}')
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/CacheProjectIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/CacheProjectIntegrationTest.groovy
index 7dd6d35..45d59e2 100644
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/CacheProjectIntegrationTest.groovy
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/CacheProjectIntegrationTest.groovy
@@ -21,7 +21,7 @@ import org.gradle.groovy.scripts.ScriptSource
import org.gradle.groovy.scripts.UriScriptSource
import org.gradle.integtests.fixtures.AbstractIntegrationTest
import org.gradle.test.fixtures.file.TestFile
-import org.gradle.test.fixtures.maven.MavenRepository
+import org.gradle.test.fixtures.maven.MavenHttpRepository
import org.gradle.test.fixtures.server.http.HttpServer
import org.gradle.util.GradleVersion
import org.junit.Before
@@ -30,9 +30,6 @@ import org.junit.Test
import static org.junit.Assert.assertEquals
-/**
- * @author Hans Dockter
- */
public class CacheProjectIntegrationTest extends AbstractIntegrationTest {
static final String TEST_FILE = "build/test.txt"
@@ -45,7 +42,7 @@ public class CacheProjectIntegrationTest extends AbstractIntegrationTest {
TestFile classFile
TestFile artifactsCache
- MavenRepository repo
+ MavenHttpRepository repo
@Before
public void setUp() {
@@ -62,11 +59,10 @@ public class CacheProjectIntegrationTest extends AbstractIntegrationTest {
classFile = userHomeDir.file("caches/$version/scripts/$source.className/ProjectScript/no_buildscript/classes/${source.className}.class")
artifactsCache = projectDir.file(".gradle/$version/taskArtifacts/taskArtifacts.bin")
- def repoDir = file("repo")
- repo = maven(repoDir)
- server.allowGetOrHead("/repo", repo.rootDir)
- repo.module("commons-io", "commons-io", "1.4").publish()
- repo.module("commons-lang", "commons-lang", "2.6").publish()
+ repo = new MavenHttpRepository(server, mavenRepo)
+
+ repo.module("commons-io", "commons-io", "1.4").publish().allowAll()
+ repo.module("commons-lang", "commons-lang", "2.6").publish().allowAll()
server.start()
}
@@ -167,7 +163,7 @@ public class CacheProjectIntegrationTest extends AbstractIntegrationTest {
String content = """
repositories {
maven{
- url "http://localhost:${server.port}/repo"
+ url "${repo.uri}"
}
}
configurations { compile }
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/CustomPluginIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/CustomPluginIntegrationTest.groovy
index aa729ba..57d576c 100755
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/CustomPluginIntegrationTest.groovy
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/CustomPluginIntegrationTest.groovy
@@ -155,7 +155,7 @@ apply plugin: 'groovy'
repositories { mavenCentral() }
dependencies {
compile gradleApi()
- groovy localGroovy()
+ compile localGroovy()
testCompile 'junit:junit:4.11'
}
"""
@@ -196,7 +196,7 @@ apply plugin: 'groovy'
repositories { mavenCentral() }
dependencies {
compile gradleApi()
- groovy localGroovy()
+ compile localGroovy()
testCompile 'junit:junit:4.11'
}
"""
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/DistributionLocatorIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/DistributionLocatorIntegrationTest.groovy
index d1dd28d..56d95e2 100644
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/DistributionLocatorIntegrationTest.groovy
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/DistributionLocatorIntegrationTest.groovy
@@ -18,11 +18,11 @@ package org.gradle.integtests
import org.gradle.util.DistributionLocator
import org.gradle.util.GradleVersion
+import org.gradle.util.Requires
+import org.gradle.util.TestPrecondition
import spock.lang.Specification
-/**
- * @author: Szczepan Faber, created at: 8/20/11
- */
+ at Requires(TestPrecondition.ONLINE)
class DistributionLocatorIntegrationTest extends Specification {
def locator = new DistributionLocator()
@@ -36,7 +36,7 @@ class DistributionLocatorIntegrationTest extends Specification {
def "locates snapshot versions"() {
expect:
- urlExist(locator.getDistributionFor(GradleVersion.version("1.3-20120919220026+0000")))
+ urlExist(locator.getDistributionFor(GradleVersion.version("1.6-20130321190822+0000")))
}
void urlExist(URI url) {
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/ExternalScriptErrorIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/ExternalScriptErrorIntegrationTest.groovy
deleted file mode 100755
index 22f3df7..0000000
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/ExternalScriptErrorIntegrationTest.groovy
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.integtests
-
-import org.gradle.integtests.fixtures.AbstractIntegrationTest
-import org.gradle.integtests.fixtures.executer.ExecutionFailure
-import org.gradle.test.fixtures.file.TestFile
-import org.junit.Test
-
-import static org.hamcrest.Matchers.containsString
-
-class ExternalScriptErrorIntegrationTest extends AbstractIntegrationTest {
- @Test
- public void reportsScriptEvaluationFailsWithGroovyException() {
- testFile('build.gradle') << '''
-apply { from 'other.gradle' }
-'''
- TestFile script = testFile('other.gradle') << '''
-
-doStuff()
-'''
-
- ExecutionFailure failure = inTestDirectory().runWithFailure()
-
- failure.assertHasFileName("Script '${script}'");
- failure.assertHasLineNumber(3);
- failure.assertHasDescription('A problem occurred evaluating script.');
- failure.assertHasCause('Could not find method doStuff() for arguments [] on root project');
- }
-
- @Test
- public void reportsScriptCompilationException() {
- testFile('build.gradle') << '''
-apply { from 'other.gradle' }
-'''
- TestFile script = testFile('other.gradle')
- script.text = 'import org.gradle()'
-
- ExecutionFailure failure = inTestDirectory().runWithFailure()
- failure.assertHasFileName("Script '${script}'");
- failure.assertHasLineNumber(1);
- failure.assertHasDescription("Could not compile script '${script}'");
- failure.assertThatCause(containsString("script '${script}': 1: unexpected token: ("))
- }
-
- @Test
- public void reportsMissingScript() {
- TestFile buildScript = testFile('build.gradle') << '''
-apply { from 'unknown.gradle' }
-'''
- TestFile script = testFile('unknown.gradle')
-
- ExecutionFailure failure = inTestDirectory().runWithFailure()
- failure.assertHasFileName("Build file '${buildScript}");
- failure.assertHasLineNumber(2);
- failure.assertHasDescription("A problem occurred evaluating root project");
- failure.assertHasCause("Could not read script '${script}' as it does not exist.");
- }
-
- @Test
- public void reportsTaskExecutionFailsWithRuntimeException() {
- testFile('build.gradle') << '''
-apply { from 'other.gradle' }
-'''
- TestFile script = testFile('other.gradle') << '''
-task doStuff << {
- throw new RuntimeException('fail')
-}
-'''
-
- ExecutionFailure failure = inTestDirectory().withTasks('doStuff').runWithFailure()
-
- failure.assertHasFileName("Script '${script}'");
- failure.assertHasLineNumber(3);
- failure.assertHasDescription('Execution failed for task \':doStuff\'');
- failure.assertHasCause('fail');
- }
-
-}
-
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/ExternalScriptExecutionIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/ExternalScriptExecutionIntegrationTest.groovy
index 11831c7..1c22a8e 100755
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/ExternalScriptExecutionIntegrationTest.groovy
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/ExternalScriptExecutionIntegrationTest.groovy
@@ -56,7 +56,6 @@ assert "${externalScript.absolutePath.replace("\\", "\\\\")}" == buildscript.sou
assert "${externalScript.toURI()}" == buildscript.sourceURI as String
assert buildscript.classLoader == getClass().classLoader.parent
assert buildscript.classLoader == Thread.currentThread().contextClassLoader
-assert gradle.scriptClassLoader == buildscript.classLoader.parent
assert project.buildscript.classLoader != buildscript.classLoader
Gradle.class.classLoader.loadClass('${implClassName}')
try {
@@ -93,7 +92,6 @@ new BuildSrcClass()
assert 'doStuff' == name
assert buildscript.classLoader == getClass().classLoader.parent
assert buildscript.classLoader == Thread.currentThread().contextClassLoader
-assert project.gradle.scriptClassLoader == buildscript.classLoader.parent
assert project.buildscript.classLoader != buildscript.classLoader
ext.someProp = 'value'
'''
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/IncrementalGroovyProjectBuildIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/IncrementalGroovyProjectBuildIntegrationTest.groovy
index f02eff3..716b889 100644
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/IncrementalGroovyProjectBuildIntegrationTest.groovy
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/IncrementalGroovyProjectBuildIntegrationTest.groovy
@@ -26,7 +26,7 @@ class IncrementalGroovyProjectBuildIntegrationTest extends AbstractIntegrationTe
file("src/main/groovy/BuildClass.java") << 'public class BuildClass { }'
file("build.gradle") << '''
apply plugin: 'groovy'
- dependencies { groovy localGroovy() }
+ dependencies { compile localGroovy() }
groovydoc {
link('http://download.oracle.com/javase/1.5.0/docs/api', 'java.,org.xml.,javax.,org.xml.')
}
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/IncrementalTasksIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/IncrementalTasksIntegrationTest.groovy
new file mode 100644
index 0000000..036cdde
--- /dev/null
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/IncrementalTasksIntegrationTest.groovy
@@ -0,0 +1,343 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests
+import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+
+class IncrementalTasksIntegrationTest extends AbstractIntegrationSpec {
+ def "setup"() {
+ buildFile << buildFileBase
+ buildFile << """
+ task incremental(type: IncrementalTask) {
+ inputDir = project.mkdir('inputs')
+ outputDir = project.mkdir('outputs')
+ prop = 'foo'
+ }
+"""
+ file('inputs/file0.txt') << "inputFile0"
+ file('inputs/file1.txt') << "inputFile1"
+ file('inputs/file2.txt') << "inputFile2"
+
+ file('outputs/file1.txt') << "outputFile1"
+ file('outputs/file2.txt') << "outputFile2"
+ }
+
+ private static String getBuildFileBase() {
+ """
+ class BaseIncrementalTask extends DefaultTask {
+ @InputDirectory
+ def File inputDir
+
+ @TaskAction
+ void execute(IncrementalTaskInputs inputs) {
+ assert !(inputs instanceof ExtensionAware)
+
+ if (project.hasProperty('forceFail')) {
+ throw new RuntimeException('failed')
+ }
+
+ incrementalExecution = inputs.incremental
+
+ inputs.outOfDate { change ->
+ if (change.added) {
+ addedFiles << change.file
+ } else {
+ changedFiles << change.file
+ }
+ }
+
+ inputs.removed { change ->
+ removedFiles << change.file
+ }
+
+ touchOutputs()
+ }
+
+ def touchOutputs() {
+ }
+
+ def addedFiles = []
+ def changedFiles = []
+ def removedFiles = []
+ def incrementalExecution
+ }
+
+ class IncrementalTask extends BaseIncrementalTask {
+ @Input
+ def String prop
+
+ @OutputDirectory
+ def File outputDir
+
+ @Override
+ def touchOutputs() {
+ outputDir.eachFile {
+ it << "more content"
+ }
+ }
+ }
+
+ ext {
+ incrementalExecution = true
+ added = []
+ changed = []
+ removed = []
+ }
+
+ task incrementalCheck(dependsOn: "incremental") << {
+ assert incremental.incrementalExecution == project.ext.incrementalExecution
+ assert incremental.addedFiles.collect({ it.name }).sort() == project.ext.added
+ assert incremental.changedFiles.collect({ it.name }).sort() == project.ext.changed
+ assert incremental.removedFiles.collect({ it.name }).sort() == project.ext.removed
+ }
+"""
+ }
+
+ def "incremental task is informed that all input files are 'out-of-date' when run for the first time"() {
+ expect:
+ executesWithRebuildContext()
+ }
+
+ def "incremental task is skipped when run with no changes since last execution"() {
+ given:
+ previousExecution()
+
+ when:
+ run "incremental"
+
+ then:
+ ":incremental" in skippedTasks
+ }
+
+ def "incremental task is informed of 'out-of-date' files when input file modified"() {
+ given:
+ previousExecution()
+
+ when:
+ file('inputs/file1.txt') << "changed content"
+
+ then:
+ executesWithIncrementalContext("ext.changed = ['file1.txt']");
+ }
+
+ def "incremental task is informed of 'out-of-date' files when input file added"() {
+ given:
+ previousExecution()
+
+ when:
+ file('inputs/file3.txt') << "file3 content"
+
+ then:
+ executesWithIncrementalContext("ext.added = ['file3.txt']")
+ }
+
+ def "incremental task is informed of 'out-of-date' files when input file removed"() {
+ given:
+ previousExecution()
+
+ when:
+ file('inputs/file2.txt').delete()
+
+ then:
+ executesWithIncrementalContext("ext.removed = ['file2.txt']")
+ }
+
+ def "incremental task is informed of 'out-of-date' files when all input files removed"() {
+ given:
+ previousExecution()
+
+ when:
+ file('inputs/file1.txt').delete()
+ file('inputs/file2.txt').delete()
+
+ then:
+ executesWithIncrementalContext("ext.removed = ['file1.txt', 'file2.txt']")
+ }
+
+ def "incremental task is informed of 'out-of-date' files with added, removed and modified files"() {
+ given:
+ previousExecution()
+
+ when:
+ file('inputs/file1.txt') << "changed content"
+ file('inputs/file2.txt').delete()
+ file('inputs/file3.txt') << "new file 3"
+ file('inputs/file4.txt') << "new file 4"
+
+ then:
+ executesWithIncrementalContext("""
+ext.changed = ['file1.txt']
+ext.removed = ['file2.txt']
+ext.added = ['file3.txt', 'file4.txt']
+""")
+ }
+
+ def "incremental task is informed of 'out-of-date' files when task has no declared outputs or properties"() {
+ given:
+ buildFile.text = buildFileBase
+ buildFile << """
+ task incremental(type: BaseIncrementalTask) {
+ inputDir = project.mkdir('inputs')
+ }
+"""
+ and:
+ previousExecution()
+
+ when:
+ file('inputs/file3.txt') << "file3 content"
+
+ then:
+ executesWithIncrementalContext("ext.added = ['file3.txt']")
+ }
+
+ def "incremental task is informed that all input files are 'out-of-date' when input property has changed"() {
+ given:
+ previousExecution()
+
+ when:
+ buildFile << "incremental.prop = 'changed'"
+
+ then:
+ executesWithRebuildContext()
+ }
+
+ def "incremental task is informed that all input files are 'out-of-date' when task class has changed"() {
+ given:
+ previousExecution()
+
+ when:
+ buildFile.text = buildFileBase
+ buildFile << """
+ class IncrementalTask2 extends BaseIncrementalTask {}
+ task incremental(type: IncrementalTask2) {
+ inputDir = project.mkdir('inputs')
+ }
+"""
+
+ then:
+ executesWithRebuildContext()
+ }
+
+ def "incremental task is informed that all input files are 'out-of-date' when output directory is changed"() {
+ given:
+ previousExecution()
+
+ when:
+ buildFile << "incremental.outputDir = project.mkdir('new-outputs')"
+
+ then:
+ executesWithRebuildContext()
+ }
+
+ def "incremental task is informed that all input files are 'out-of-date' when output file has changed"() {
+ given:
+ previousExecution()
+
+ when:
+ file("outputs/file1.txt") << "further change"
+
+ then:
+ executesWithRebuildContext()
+ }
+
+ def "incremental task is informed that all input files are 'out-of-date' when output file has been removed"() {
+ given:
+ previousExecution()
+
+ when:
+ file("outputs/file1.txt").delete()
+
+ then:
+ executesWithRebuildContext()
+ }
+
+ def "incremental task is informed that all input files are 'out-of-date' when all output files have been removed"() {
+ given:
+ previousExecution()
+
+ when:
+ file("outputs").deleteDir()
+
+ then:
+ executesWithRebuildContext()
+ }
+
+ def "incremental task is informed that all input files are 'out-of-date' when Task.upToDate() is false"() {
+ given:
+ previousExecution()
+
+ when:
+ buildFile << "incremental.outputs.upToDateWhen { false }"
+
+ then:
+ executesWithRebuildContext()
+ }
+
+ def "incremental task is informed that all input files are 'out-of-date' when gradle is executed with --rerun-tasks"() {
+ given:
+ previousExecution()
+
+ when:
+ executer.withArgument("--rerun-tasks")
+
+ then:
+ executesWithRebuildContext()
+ }
+
+ def "incremental task is informed of 'out-of-date' files since previous successful execution"() {
+ given:
+ previousExecution()
+
+ and:
+ file('inputs/file1.txt') << "changed content"
+
+ when:
+ failedExecution()
+
+ then:
+ executesWithIncrementalContext("ext.changed = ['file1.txt']");
+ }
+ /*
+ 7. Sad-day cases
+ - Incremental task has input files declared
+ - Incremental task action throws exception
+ - Incremental task action processes outOfDate files multiple times
+ - Attempt to process removed files without first processing outOfDate files
+ */
+
+ def previousExecution() {
+ run "incremental"
+ }
+
+ def failedExecution() {
+ executer.withArgument("-PforceFail=yep")
+ assert fails("incremental")
+ executer.withArguments()
+ }
+
+ def executesWithIncrementalContext(String fileChanges) {
+ buildFile << fileChanges
+ succeeds "incrementalCheck"
+ }
+
+ def executesWithRebuildContext() {
+ buildFile << """
+ ext.changed = ['file0.txt', 'file1.txt', 'file2.txt']
+ ext.incrementalExecution = false
+"""
+ succeeds "incrementalCheck"
+ }
+}
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/IncrementalTestIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/IncrementalTestIntegrationTest.groovy
deleted file mode 100644
index 80c9a7b..0000000
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/IncrementalTestIntegrationTest.groovy
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.integtests
-
-import org.gradle.integtests.fixtures.AbstractIntegrationTest
-import org.gradle.integtests.fixtures.JUnitXmlTestExecutionResult
-import org.gradle.integtests.fixtures.TestResources
-import org.junit.*
-
-class IncrementalTestIntegrationTest extends AbstractIntegrationTest {
-
- @Rule public final TestResources resources = new TestResources(testDirectoryProvider)
-
- @Before
- public void before() {
- executer.noExtraLogging()
- }
-
- @Test
- public void doesNotRunStaleTests() {
- executer.withTasks('test').runWithFailure().assertTestsFailed()
-
- file('src/test/java/Broken.java').assertIsFile().delete()
-
- executer.withTasks('test').run()
- }
-
- @Test
- public void executesTestsWhenSourceChanges() {
- executer.withTasks('test').run()
-
- // Change a production class
- file('src/main/java/MainClass.java').assertIsFile().copyFrom(file('NewMainClass.java'))
-
- executer.withTasks('test').run().assertTasksNotSkipped(':compileJava', ':classes', ':compileTestJava', ':testClasses', ':test')
- executer.withTasks('test').run().assertTasksNotSkipped()
-
- // Change a test class
- file('src/test/java/Ok.java').assertIsFile().copyFrom(file('NewOk.java'))
-
- executer.withTasks('test').run().assertTasksNotSkipped(':compileTestJava', ':testClasses', ':test')
- executer.withTasks('test').run().assertTasksNotSkipped()
- }
-
- @Test
- public void executesTestsWhenSelectedTestsChange() {
- executer.withTasks('test').run()
-
- def result = new JUnitXmlTestExecutionResult(testDirectory)
- result.assertTestClassesExecuted('JUnitTest')
-
- // Include more tests
- file('build.gradle').append 'test.include "**/*Extra*"\n'
-
- executer.withTasks('test').run().assertTasksNotSkipped(':test')
- result.assertTestClassesExecuted('JUnitTest', 'JUnitExtra')
-
- executer.withTasks('test').run().assertTasksNotSkipped()
-
- // Use single test execution
- executer.withTasks('test').withArguments('-Dtest.single=Ok').run().assertTasksNotSkipped(':test')
- executer.withTasks('test').run().assertTasksNotSkipped(':test')
- executer.withTasks('test').run().assertTasksNotSkipped()
-
- // Switch test framework
- file('build.gradle').append 'test.useTestNG()\n'
-
- //TODO this exposes a possible problem: When changing the test framework stale xml result files from former test framework are still present.
- executer.withTasks('cleanTest', 'test').run().assertTasksNotSkipped(':cleanTest',':test')
-
- result = new JUnitXmlTestExecutionResult(testDirectory)
- result.assertTestClassesExecuted('TestNGTest')
-
- executer.withTasks('test').run().assertTasksNotSkipped()
- }
-
- @Test @Ignore
- public void executesTestsWhenPropertiesChange() {
- Assert.fail()
- }
-}
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/InitScriptErrorIntegrationTest.java b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/InitScriptErrorIntegrationTest.java
deleted file mode 100644
index e4c7416..0000000
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/InitScriptErrorIntegrationTest.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.integtests;
-
-import org.gradle.integtests.fixtures.AbstractIntegrationTest;
-import org.gradle.integtests.fixtures.executer.ExecutionFailure;
-import org.gradle.test.fixtures.file.TestFile;
-import org.junit.Test;
-
-import static org.hamcrest.Matchers.containsString;
-
-public class InitScriptErrorIntegrationTest extends AbstractIntegrationTest {
- @Test
- public void reportsInitScriptEvaluationFailsWithGroovyException() {
- TestFile initScript = testFile("init.gradle");
- initScript.write("\ncreateTakk('do-stuff')");
- ExecutionFailure failure = inTestDirectory().usingInitScript(initScript).runWithFailure();
-
- failure.assertHasFileName(String.format("Initialization script '%s'", initScript));
- failure.assertHasLineNumber(2);
- failure.assertHasDescription("A problem occurred evaluating initialization script.");
- failure.assertHasCause("Could not find method createTakk() for arguments [do-stuff] on build.");
- }
-
- @Test
- public void reportsGroovyCompilationException() {
- TestFile initScript = testFile("init.gradle");
- initScript.writelns(
- "// a comment",
- "import org.gradle.unknown.Unknown",
- "new Unknown()");
- ExecutionFailure failure = inTestDirectory().usingInitScript(initScript).runWithFailure();
- failure.assertHasFileName(String.format("Initialization script '%s'", initScript));
- failure.assertHasLineNumber(2);
- failure.assertHasDescription(String.format("Could not compile initialization script '%s'.", initScript));
- failure.assertThatCause(containsString(String.format("initialization script '%s': 2: unable to resolve class org.gradle.unknown.Unknown", initScript)));
- }
-}
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/InitScriptExecutionIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/InitScriptExecutionIntegrationTest.groovy
index 28112e4..9605e00 100644
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/InitScriptExecutionIntegrationTest.groovy
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/InitScriptExecutionIntegrationTest.groovy
@@ -73,7 +73,6 @@ println 'error message'
assert gradle != null
assert initscript.classLoader == getClass().classLoader.parent
assert initscript.classLoader == Thread.currentThread().contextClassLoader
-assert scriptClassLoader == initscript.classLoader.parent
Gradle.class.classLoader.loadClass('${implClassName}')
try {
initscript.classLoader.loadClass('${implClassName}')
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/JavaProjectIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/JavaProjectIntegrationTest.groovy
index bb2b47f..6b60495 100644
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/JavaProjectIntegrationTest.groovy
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/JavaProjectIntegrationTest.groovy
@@ -15,11 +15,9 @@
*/
package org.gradle.integtests
-
import org.gradle.integtests.fixtures.AbstractIntegrationTest
import org.gradle.integtests.fixtures.executer.ExecutionFailure
import org.gradle.test.fixtures.file.TestFile
-import org.junit.Ignore
import org.junit.Test
class JavaProjectIntegrationTest extends AbstractIntegrationTest {
@@ -31,7 +29,7 @@ class JavaProjectIntegrationTest extends AbstractIntegrationTest {
ExecutionFailure failure = usingBuildFile(buildFile).withTasks("build").runWithFailure();
- failure.assertHasDescription("Execution failed for task ':compileJava'");
+ failure.assertHasDescription("Execution failed for task ':compileJava'.");
failure.assertHasCause("Compilation failed; see the compiler error output for details.");
}
@@ -44,7 +42,7 @@ class JavaProjectIntegrationTest extends AbstractIntegrationTest {
ExecutionFailure failure = usingBuildFile(buildFile).withTasks("build").runWithFailure();
- failure.assertHasDescription("Execution failed for task ':compileTestJava'");
+ failure.assertHasDescription("Execution failed for task ':compileTestJava'.");
failure.assertHasCause("Compilation failed; see the compiler error output for details.");
}
@@ -67,7 +65,7 @@ public class NotATest {}"""
ExecutionFailure failure = usingBuildFile(buildFile).withTasks("javadoc").runWithFailure();
- failure.assertHasDescription("Execution failed for task ':javadoc'");
+ failure.assertHasDescription("Execution failed for task ':javadoc'.");
failure.assertHasCause("Javadoc generation failed.");
}
@@ -121,8 +119,6 @@ version = ''
testFile("build/libs/empty.jar").assertIsFile();
}
- // TODO: translate to new source set/packaging model
- @Ignore
@Test
public void "task registered as a builder of resources is executed"() {
TestFile buildFile = testFile("build.gradle");
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/MixedNativeAndJvmProjectIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/MixedNativeAndJvmProjectIntegrationTest.groovy
new file mode 100644
index 0000000..d15047c
--- /dev/null
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/MixedNativeAndJvmProjectIntegrationTest.groovy
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests
+
+import org.gradle.integtests.fixtures.AbstractIntegrationSpec;
+
+public class MixedNativeAndJvmProjectIntegrationTest extends AbstractIntegrationSpec {
+
+ def "can combine java, cpp-exe and cpp-lib plugins in a single project"() {
+ settingsFile << "rootProject.name = 'test'"
+ buildFile << """
+ apply plugin: "java"
+ apply plugin: "cpp-exe"
+ apply plugin: "cpp-lib"
+
+ task checkBinaries << {
+ assert binaries.mainClasses instanceof ClassDirectoryBinary
+ assert binaries.mainExecutable instanceof ExecutableBinary
+ assert binaries.mainSharedLibrary instanceof SharedLibraryBinary
+ }
+"""
+ expect:
+ succeeds "checkBinaries"
+ }
+}
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/MultiProjectDependencyIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/MultiProjectDependencyIntegrationTest.groovy
index 6d04f14..ed4d7dd 100644
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/MultiProjectDependencyIntegrationTest.groovy
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/MultiProjectDependencyIntegrationTest.groovy
@@ -18,10 +18,9 @@ package org.gradle.integtests
import org.gradle.integtests.fixtures.AbstractIntegrationSpec
import org.gradle.integtests.fixtures.executer.GradleContextualExecuter
+import org.hamcrest.Matchers
import spock.lang.IgnoreIf
-import static org.hamcrest.Matchers.containsString
-
public class MultiProjectDependencyIntegrationTest extends AbstractIntegrationSpec {
def setup() {
@@ -159,7 +158,7 @@ project(':c') {
then:
failure.assertHasNoCause()
- failure.assertThatDescription(containsString("Circular dependency between tasks. Cycle includes [task ':a:compileJava', task ':a:jar']."))
+ failure.assertThatDescription(Matchers.startsWith("Circular dependency between the following tasks:"))
}
def "project dependency a->b->c->d and c fails"() {
@@ -247,15 +246,12 @@ project(':$from') {
}
def failingBuild(def project) {
+ file("$project/src/main/java/Foo.java") << "class Foo {}"
buildFile << """
project(':$project') {
- //fail needs to have a dependendency on compileJava
- //this way all the java project dependencies are built first in paralle mode
- //if 'fail 'does not have any dependencies it will be scheduled to execute very early in parallel mode
- task fail(dependsOn: compileJava) << {
+ compileJava.doFirst {
throw new RuntimeException('failure in $project')
}
- jar.dependsOn fail
}
"""
}
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/OsgiProjectSampleIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/OsgiProjectSampleIntegrationTest.groovy
index 6e332b9..7be6389 100644
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/OsgiProjectSampleIntegrationTest.groovy
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/OsgiProjectSampleIntegrationTest.groovy
@@ -28,9 +28,6 @@ import java.util.jar.Manifest
import static org.junit.Assert.assertEquals
import static org.junit.Assert.assertTrue
-/**
- * @author Hans Dockter
- */
class OsgiProjectSampleIntegrationTest extends AbstractIntegrationTest {
@Rule public final Sample sample = new Sample(testDirectoryProvider, 'osgi')
@@ -51,7 +48,7 @@ class OsgiProjectSampleIntegrationTest extends AbstractIntegrationTest {
static void checkManifest(Manifest manifest, start) {
assertEquals('Example Gradle Activator', manifest.mainAttributes.getValue('Bundle-Name'))
assertEquals('2', manifest.mainAttributes.getValue('Bundle-ManifestVersion'))
- assertEquals('Bnd-1.50.0', manifest.mainAttributes.getValue('Tool'))
+ assertEquals('Bnd-2.1.0.20130426-122213', manifest.mainAttributes.getValue('Tool'))
assertTrue(start <= Long.parseLong(manifest.mainAttributes.getValue('Bnd-LastModified')))
assertEquals('1.0.0', manifest.mainAttributes.getValue('Bundle-Version'))
assertEquals('gradle_tooling.osgi', manifest.mainAttributes.getValue('Bundle-SymbolicName'))
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/ParallelProjectExecutionIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/ParallelProjectExecutionIntegrationTest.groovy
index 556ab0b..23e16d3 100644
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/ParallelProjectExecutionIntegrationTest.groovy
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/ParallelProjectExecutionIntegrationTest.groovy
@@ -31,9 +31,15 @@ public class ParallelProjectExecutionIntegrationTest extends AbstractIntegration
buildFile << """
assert gradle.startParameter.parallelThreadCount != 0
allprojects {
- task pingServer << {
- URL url = new URL("http://localhost:${blockingServer.port}/" + project.path)
- println url.openConnection().getHeaderField('RESPONSE')
+ tasks.addRule("ping<>") { String name ->
+ if (name.startsWith("ping")) {
+ tasks.create(name) {
+ doLast {
+ URL url = new URL("http://localhost:${blockingServer.port}/" + path)
+ println url.openConnection().getHeaderField('RESPONSE')
+ }
+ }
+ }
}
}
"""
@@ -42,12 +48,11 @@ allprojects {
}
def "executes dependency project targets concurrently"() {
-
projectDependency from: 'a', to: ['b', 'c', 'd']
expect:
- blockingServer.expectConcurrentExecution(':b', ':c', ':d')
- blockingServer.expectConcurrentExecution(':a')
+ blockingServer.expectConcurrentExecution(':b:pingServer', ':c:pingServer', ':d:pingServer')
+ blockingServer.expectConcurrentExecution(':a:pingServer')
run ':a:pingServer'
}
@@ -59,9 +64,9 @@ allprojects {
projectDependency from: 'c', to: ['d']
expect:
- blockingServer.expectConcurrentExecution(':d')
- blockingServer.expectConcurrentExecution(':b', ':c')
- blockingServer.expectConcurrentExecution(':a')
+ blockingServer.expectConcurrentExecution(':d:pingServer')
+ blockingServer.expectConcurrentExecution(':b:pingServer', ':c:pingServer')
+ blockingServer.expectConcurrentExecution(':a:pingServer')
run ':a:pingServer'
}
@@ -72,7 +77,7 @@ allprojects {
failingBuild 'c'
when:
- blockingServer.expectConcurrentExecution(':b', ':c')
+ blockingServer.expectConcurrentExecution(':b:pingServer', ':c:pingServer')
fails ':a:pingServer'
@@ -81,6 +86,20 @@ allprojects {
failure.error =~ 'c failed'
}
+ def "tasks are executed when they are ready and not necessarily alphabetically"() {
+ buildFile << """
+ tasks.getByPath(':b:pingA').dependsOn(':a:pingA')
+ tasks.getByPath(':b:pingC').dependsOn([':b:pingA', ':b:pingB'])
+ """
+
+ expect:
+ //project a and b are both executed even though alphabetically more important task is blocked
+ blockingServer.expectConcurrentExecution(':b:pingB', ':a:pingA')
+ blockingServer.expectConcurrentExecution(':b:pingA')
+ blockingServer.expectConcurrentExecution(':b:pingC')
+
+ run 'b:pingC'
+ }
def projectDependency(def link) {
def from = link['from']
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/PluginCrossVersionIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/PluginCrossVersionIntegrationTest.groovy
deleted file mode 100644
index 1a87b0c..0000000
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/PluginCrossVersionIntegrationTest.groovy
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.integtests
-
-import org.gradle.integtests.fixtures.CrossVersionIntegrationSpec
-
-import org.gradle.integtests.fixtures.TargetVersions
-
- at TargetVersions('0.9-rc-3+')
-class PluginCrossVersionIntegrationTest extends CrossVersionIntegrationSpec {
- def "can use plugin compiled using previous Gradle version"() {
- given:
- file("producer/build.gradle") << """
-apply plugin: 'groovy'
-dependencies {
- groovy localGroovy()
- compile gradleApi()
-}
-"""
- file("producer/src/main/groovy/SomePlugin.groovy") << """
-import org.gradle.api.Plugin
-import org.gradle.api.Project
-import org.gradle.api.DefaultTask
-import org.gradle.api.tasks.*
-import org.gradle.api.internal.ConventionTask
-
-class SomePlugin implements Plugin<Project> {
- void apply(Project p) {
- p.tasks.add('do-stuff', CustomTask)
- p.tasks.add('customConventionTask', CustomConventionTask)
- p.tasks.add('customSourceTask', CustomSourceTask)
- }
-}
-
-class CustomTask extends DefaultTask {
- @TaskAction void go() { }
-}
-
-// ConventionTask leaks a lot of internal API so test for compatibility
-class CustomConventionTask extends ConventionTask {}
-
-// Same reason here, but less direct
-class CustomSourceTask extends SourceTask {}
-
-"""
-
- buildFile << """
-buildscript {
- dependencies { classpath fileTree(dir: "producer/build/libs", include: '*.jar') }
-}
-
-apply plugin: SomePlugin
-"""
-
- expect:
- version previous withTasks 'assemble' inDirectory(file("producer")) run()
- version current withTasks 'do-stuff' run()
- }
-}
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/ProfilingIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/ProfilingIntegrationTest.groovy
deleted file mode 100644
index 923585e..0000000
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/ProfilingIntegrationTest.groovy
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.integtests
-
-import org.gradle.integtests.fixtures.AbstractIntegrationSpec
-import org.jsoup.Jsoup
-import org.jsoup.nodes.Document
-
-class ProfilingIntegrationTest extends AbstractIntegrationSpec {
- def "can generate profiling report"() {
- file('settings.gradle') << 'include "a", "b", "c"'
- buildFile << '''
-allprojects {
- apply plugin: 'java'
-}
-'''
- when:
- executer.withArguments("--profile").withTasks("build").run()
-
- then:
- def reportFile = file('build/reports/profile').listFiles().find { it.name ==~ /profile-.+.html/ }
- Document document = Jsoup.parse(reportFile, null);
- !document.select("TD:contains(:jar)").isEmpty()
- !document.select("TD:contains(:a:jar)").isEmpty()
- !document.select("TD:contains(:b:jar)").isEmpty()
- !document.select("TD:contains(:c:jar)").isEmpty()
- }
-}
\ No newline at end of file
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/ProjectLayoutIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/ProjectLayoutIntegrationTest.groovy
index 55769d0..db68ded 100644
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/ProjectLayoutIntegrationTest.groovy
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/ProjectLayoutIntegrationTest.groovy
@@ -24,7 +24,8 @@ import org.junit.Test
class ProjectLayoutIntegrationTest extends AbstractIntegrationTest {
- @Rule public final TestResources resources = new TestResources(testDirectoryProvider)
+ @Rule
+ public final TestResources resources = new TestResources(testDirectoryProvider)
@Test
public void canHaveSomeSourceAndResourcesInSameDirectoryAndSomeInDifferentDirectories() {
@@ -172,4 +173,16 @@ sourceSets.main.java {
results.assertTestClassesExecuted('PersonTest')
results.testClass('PersonTest').assertTestsExecuted('ok')
}
+
+ @Test
+ public void projectPathsResolvedRelativeToRoot() {
+ file('relative/a/build.gradle') << """
+ task someTask
+ """
+ file('settings.gradle') << '''
+ include ':a'
+ project(':a').projectDir = new File('relative/a')
+ '''
+ executer.inDirectory(file('relative/a')).withTasks(':a:someTask').run()
+ }
}
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/SettingsScriptErrorIntegrationTest.java b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/SettingsScriptErrorIntegrationTest.java
deleted file mode 100644
index 078541d..0000000
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/SettingsScriptErrorIntegrationTest.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.integtests;
-
-import org.gradle.integtests.fixtures.AbstractIntegrationTest;
-import org.gradle.integtests.fixtures.executer.ExecutionFailure;
-import org.gradle.test.fixtures.file.TestFile;
-import org.junit.Test;
-
-import java.io.IOException;
-
-public class SettingsScriptErrorIntegrationTest extends AbstractIntegrationTest {
- @Test
- public void reportsSettingsScriptEvaluationFailsWithRuntimeException() throws IOException {
- TestFile settingsFile = testFile("some settings.gradle");
- settingsFile.writelns("", "", "throw new RuntimeException('<failure message>')");
-
- ExecutionFailure failure = executer.usingSettingsFile(settingsFile).runWithFailure();
-
- failure.assertHasFileName(String.format("Settings file '%s'", settingsFile));
- failure.assertHasLineNumber(3);
- failure.assertHasDescription("A problem occurred evaluating settings 'reportsSettingsScriptEvaluationFailsWithRuntimeException");
- failure.assertHasCause("<failure message>");
- }
-}
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/SettingsScriptExecutionIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/SettingsScriptExecutionIntegrationTest.groovy
index 05e2c79..67de4a7 100644
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/SettingsScriptExecutionIntegrationTest.groovy
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/SettingsScriptExecutionIntegrationTest.groovy
@@ -44,7 +44,6 @@ println 'error message'
assert settings != null
assert buildscript.classLoader == getClass().classLoader.parent
assert buildscript.classLoader == Thread.currentThread().contextClassLoader
-assert gradle.scriptClassLoader.parents[0] == buildscript.classLoader.parent.parent
Gradle.class.classLoader.loadClass('${implClassName}')
try {
buildscript.classLoader.loadClass('${implClassName}')
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/TaskDefinitionIntegrationSpec.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/TaskDefinitionIntegrationSpec.groovy
new file mode 100644
index 0000000..7f0cf6b
--- /dev/null
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/TaskDefinitionIntegrationSpec.groovy
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests
+
+import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+
+class TaskDefinitionIntegrationSpec extends AbstractIntegrationSpec {
+
+ def "unsupported task parameter fails with decent error message"() {
+ buildFile << "task a(Type:Copy)"
+ when:
+ fails 'a'
+ then:
+ failure.assertHasCause("Could not create task 'a': Unknown argument(s) in task definition: [Type]")
+ }
+}
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/TaskErrorExecutionIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/TaskErrorExecutionIntegrationTest.groovy
index 9c98581..ad54c58 100644
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/TaskErrorExecutionIntegrationTest.groovy
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/TaskErrorExecutionIntegrationTest.groovy
@@ -33,7 +33,7 @@ class TaskErrorExecutionIntegrationTest extends AbstractIntegrationTest {
failure.assertHasFileName(String.format("Build file '%s'", buildFile))
failure.assertHasLineNumber(3)
- failure.assertHasDescription("Execution failed for task ':do-stuff'")
+ failure.assertHasDescription("Execution failed for task ':do-stuff'.")
failure.assertHasCause("broken")
}
@@ -48,7 +48,7 @@ class TaskErrorExecutionIntegrationTest extends AbstractIntegrationTest {
failure.assertHasFileName(String.format("Build file '%s'", buildFile))
failure.assertHasLineNumber(2)
- failure.assertHasDescription("Execution failed for task ':brokenClosure'")
+ failure.assertHasDescription("Execution failed for task ':brokenClosure'.")
failure.assertHasCause("broken closure")
}
@@ -74,7 +74,7 @@ class TaskErrorExecutionIntegrationTest extends AbstractIntegrationTest {
ExecutionFailure failure = usingBuildFile(buildFile).withTasks("brokenJavaTask").runWithFailure()
- failure.assertHasDescription("Execution failed for task ':brokenJavaTask'")
+ failure.assertHasDescription("Execution failed for task ':brokenJavaTask'.")
failure.assertHasCause("broken action")
}
@@ -93,7 +93,7 @@ class TaskErrorExecutionIntegrationTest extends AbstractIntegrationTest {
failure.assertHasFileName(String.format("Build file '%s'", buildFile))
failure.assertHasLineNumber(3)
- failure.assertHasDescription("Execution failed for task ':a:a")
+ failure.assertHasDescription("Execution failed for task ':a:a'.")
failure.assertHasCause("broken")
}
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/TaskExecutionIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/TaskExecutionIntegrationTest.groovy
new file mode 100644
index 0000000..ace7512
--- /dev/null
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/TaskExecutionIntegrationTest.groovy
@@ -0,0 +1,341 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests
+import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+import org.gradle.util.TextUtil
+import org.junit.Test
+import spock.lang.Issue
+
+import static org.hamcrest.Matchers.startsWith
+
+public class TaskExecutionIntegrationTest extends AbstractIntegrationSpec {
+
+ def taskCanAccessTaskGraph() {
+ buildFile << """
+ boolean notified = false
+ task a(dependsOn: 'b') << { task ->
+ assert notified
+ assert gradle.taskGraph.hasTask(task)
+ assert gradle.taskGraph.hasTask(':a')
+ assert gradle.taskGraph.hasTask(a)
+ assert gradle.taskGraph.hasTask(':b')
+ assert gradle.taskGraph.hasTask(b)
+ assert gradle.taskGraph.allTasks.contains(task)
+ assert gradle.taskGraph.allTasks.contains(tasks.getByName('b'))
+ }
+ task b
+ gradle.taskGraph.whenReady { graph ->
+ assert graph.hasTask(':a')
+ assert graph.hasTask(a)
+ assert graph.hasTask(':b')
+ assert graph.hasTask(b)
+ assert graph.allTasks.contains(a)
+ assert graph.allTasks.contains(b)
+ notified = true
+ }
+"""
+ when:
+ succeeds "a"
+
+ then:
+ result.assertTasksExecuted(":b", ":a");
+ }
+
+ def executesAllTasksInASingleBuildAndEachTaskAtMostOnce() {
+ buildFile << """
+ gradle.taskGraph.whenReady { assert !project.hasProperty('graphReady'); ext.graphReady = true }
+ task a << { task -> project.ext.executedA = task }
+ task b << {
+ assert a == project.executedA
+ assert gradle.taskGraph.hasTask(':a')
+ }
+ task c(dependsOn: a)
+ task d(dependsOn: a)
+ task e(dependsOn: [a, d]);
+"""
+ expect:
+ run("a", "b").assertTasksExecuted(":a", ":b");
+ run("a", "a").assertTasksExecuted(":a");
+ run("c", "a").assertTasksExecuted(":a", ":c");
+ run("c", "e").assertTasksExecuted(":a", ":c", ":d", ":e");
+ }
+
+ def executesMultiProjectsTasksInASingleBuildAndEachTaskAtMostOnce() {
+ settingsFile << "include 'child1', 'child2'"
+ buildFile << """
+ task a
+ allprojects {
+ task b
+ task c(dependsOn: ['b', ':a'])
+ };
+"""
+
+ expect:
+ run("a", "c").assertTasksExecuted(":a", ":b", ":c", ":child1:b", ":child1:c", ":child2:b", ":child2:c");
+ run("b", ":child2:c").assertTasksExecuted(":b", ":child1:b", ":child2:b", ":a", ":child2:c");
+ }
+
+ @Test
+ def executesMultiProjectDefaultTasksInASingleBuildAndEachTaskAtMostOnce() {
+ settingsFile << "include 'child1', 'child2'"
+ buildFile << """
+ defaultTasks 'a', 'b'
+ task a
+ subprojects {
+ task a(dependsOn: ':a')
+ task b(dependsOn: ':a')
+ }
+"""
+
+ expect:
+ run().assertTasksExecuted(":a", ":child1:a", ":child2:a", ":child1:b", ":child2:b");
+ }
+
+ def executesProjectDefaultTasksWhenNoneSpecified() {
+ buildFile << """
+ task a
+ task b(dependsOn: a)
+ defaultTasks 'b'
+"""
+ expect:
+ run().assertTasksExecuted(":a", ":b");
+ }
+
+ def doesNotExecuteTaskActionsWhenDryRunSpecified() {
+ buildFile << """
+ task a << { fail() }
+ task b(dependsOn: a) << { fail() }
+ defaultTasks 'b'
+"""
+
+ expect:
+ // project defaults
+ executer.withArguments("-m").run().assertTasksExecuted(":a", ":b");
+ // named tasks
+ executer.withArguments("-m").withTasks("b").run().assertTasksExecuted(":a", ":b");
+ }
+
+ def executesTaskActionsInCorrectEnvironment() {
+ buildFile << """
+ // An action attached to built-in task
+ task a << { assert Thread.currentThread().contextClassLoader == getClass().classLoader }
+
+ // An action defined by a custom task
+ task b(type: CustomTask)
+ class CustomTask extends DefaultTask {
+ @TaskAction def go() {
+ assert Thread.currentThread().contextClassLoader == getClass().classLoader
+ }
+ }
+
+ // An action implementation
+ task c
+ c.doLast new Action<Task>() {
+ void execute(Task t) {
+ assert Thread.currentThread().contextClassLoader == getClass().classLoader
+ }
+ }
+"""
+ expect:
+ succeeds("a", "b", "c")
+ }
+
+ def excludesTasksWhenExcludePatternSpecified() {
+ settingsFile << "include 'sub'"
+ buildFile << """
+ task a
+ task b(dependsOn: a)
+ task c(dependsOn: [a, b])
+ task d(dependsOn: c)
+ defaultTasks 'd'
+"""
+ file("sub/build.gradle") << """
+ task c
+ task d(dependsOn: c)
+"""
+
+ expect:
+ // Exclude entire branch
+ executer.withTasks(":d").withArguments("-x", "c").run().assertTasksExecuted(":d");
+ // Exclude direct dependency
+ executer.withTasks(":d").withArguments("-x", "b").run().assertTasksExecuted(":a", ":c", ":d");
+ // Exclude using paths and multi-project
+ executer.withTasks("d").withArguments("-x", "c").run().assertTasksExecuted(":d", ":sub:d");
+ executer.withTasks("d").withArguments("-x", "sub:c").run().assertTasksExecuted(":a", ":b", ":c", ":d", ":sub:d");
+ executer.withTasks("d").withArguments("-x", ":sub:c").run().assertTasksExecuted(":a", ":b", ":c", ":d", ":sub:d");
+ executer.withTasks("d").withArguments("-x", "d").run().assertTasksExecuted();
+ // Project defaults
+ executer.withArguments("-x", "b").run().assertTasksExecuted(":a", ":c", ":d", ":sub:c", ":sub:d");
+ // Unknown task
+ executer.withTasks("d").withArguments("-x", "unknown").runWithFailure().assertThatDescription(startsWith("Task 'unknown' not found in root project"));
+ }
+
+ @Issue("http://issues.gradle.org/browse/GRADLE-2022")
+ def tryingToInstantiateTaskDirectlyFailsWithGoodErrorMessage() {
+ buildFile << """
+ new DefaultTask()
+"""
+ when:
+ fails "tasks"
+
+ then:
+ failure.assertHasCause("Task of type 'org.gradle.api.DefaultTask' has been instantiated directly which is not supported")
+ }
+
+ def "sensible error message for circular task dependency"() {
+ buildFile << """
+ task a(dependsOn: 'b')
+ task b(dependsOn: 'a')
+"""
+ when:
+ fails 'b'
+
+ then:
+ failure.assertHasDescription TextUtil.toPlatformLineSeparators("""Circular dependency between the following tasks:
+:a
+\\--- :b
+ \\--- :a (*)
+
+(*) - details omitted (listed previously)""")
+ }
+
+ def "placeolder actions not triggered when not requested"() {
+ buildFile << """
+ task a
+ tasks.addPlaceholderAction("b"){
+ println "placeholder action triggered"
+ task('b')
+ }
+"""
+ when:
+ succeeds 'a'
+
+ then:
+ !output.contains("placeholder action triggered")
+ }
+
+ def "explicit tasks are preferred over placeholder actions"() {
+ buildFile << """
+ task someTask << {println "explicit sometask"}
+ tasks.addPlaceholderAction("someTask"){
+ println "placeholder action triggered"
+ task someTask << {println "placeholder sometask"}
+ }
+"""
+ when:
+ succeeds 'sometask'
+
+ then:
+ output.contains("explicit sometask")
+ !output.contains("placeholder action triggered")
+
+ when:
+ succeeds 'someT'
+
+ then:
+ output.contains("explicit sometask")
+ !output.contains("placeholder action triggered")
+ }
+
+
+ def "honours mustRunAfter task ordering"() {
+ buildFile << """
+ task a {
+ mustRunAfter 'b'
+ }
+ task b
+ task c(dependsOn: ['a', 'b'])
+ task d
+ c.mustRunAfter d
+
+"""
+ when:
+ succeeds 'c', 'd'
+
+ then:
+ result.assertTasksExecuted(':d', ':b', ':a', ':c')
+ }
+
+ def "finalizer task is executed if a finalized task is executed"() {
+ buildFile << """
+ task a
+ task b {
+ doLast {}
+ finalizedBy a
+ }
+"""
+ when:
+ succeeds 'b'
+
+ then:
+ ":a" in executedTasks
+ }
+
+ def "finalizer task is executed even if the finalised task fails"() {
+ buildFile << """
+ task a
+ task b {
+ doLast { throw new RuntimeException() }
+ finalizedBy a
+ }
+"""
+ when:
+ fails 'b'
+
+ then:
+ ":a" in executedTasks
+ }
+
+ def "finalizer task is not executed if the finalized task does not run"() {
+ buildFile << """
+ task a {
+ doLast { throw new RuntimeException() }
+ }
+ task b
+ task c {
+ doLast {}
+ dependsOn a
+ finalizedBy b
+ onlyIf { false }
+ }
+"""
+ when:
+ fails 'c'
+
+ then:
+ !(":b" in executedTasks)
+ }
+
+ def "sensible error message for circular task dependency due to mustRunAfter"() {
+ buildFile << """
+ task a {
+ mustRunAfter 'b'
+ }
+ task b(dependsOn: 'a')
+"""
+ when:
+ fails 'b'
+
+ then:
+ failure.assertHasDescription TextUtil.toPlatformLineSeparators("""Circular dependency between the following tasks:
+:a
+\\--- :b
+ \\--- :a (*)
+
+(*) - details omitted (listed previously)""")
+ }
+}
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/TaskExecutionIntegrationTest.java b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/TaskExecutionIntegrationTest.java
deleted file mode 100644
index 35c532c..0000000
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/TaskExecutionIntegrationTest.java
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.integtests;
-
-import org.gradle.integtests.fixtures.AbstractIntegrationTest;
-import org.gradle.test.fixtures.file.TestFile;
-import org.junit.Test;
-import spock.lang.Issue;
-
-import static org.hamcrest.Matchers.startsWith;
-
-public class TaskExecutionIntegrationTest extends AbstractIntegrationTest {
- @Test
- public void taskCanAccessTaskGraph() {
- TestFile buildFile = testFile("build.gradle");
- buildFile.writelns(
- "boolean notified = false",
- "task a(dependsOn: 'b') << { task ->",
- " assert notified",
- " assert gradle.taskGraph.hasTask(task)",
- " assert gradle.taskGraph.hasTask(':a')",
- " assert gradle.taskGraph.hasTask(a)",
- " assert gradle.taskGraph.hasTask(':b')",
- " assert gradle.taskGraph.hasTask(b)",
- " assert gradle.taskGraph.allTasks.contains(task)",
- " assert gradle.taskGraph.allTasks.contains(tasks.getByName('b'))",
- "}",
- "task b",
- "gradle.taskGraph.whenReady { graph ->",
- " assert graph.hasTask(':a')",
- " assert graph.hasTask(a)",
- " assert graph.hasTask(':b')",
- " assert graph.hasTask(b)",
- " assert graph.allTasks.contains(a)",
- " assert graph.allTasks.contains(b)",
- " notified = true",
- "}");
- usingBuildFile(buildFile).withTasks("a").run().assertTasksExecuted(":b", ":a");
- }
-
- @Test
- public void executesAllTasksInASingleBuildAndEachTaskAtMostOnce() {
- TestFile buildFile = testFile("build.gradle");
- buildFile.writelns(
- "gradle.taskGraph.whenReady { assert !project.hasProperty('graphReady'); ext.graphReady = true }",
- "task a << { task -> project.ext.executedA = task }",
- "task b << { ",
- " assert a == project.executedA",
- " assert gradle.taskGraph.hasTask(':a')",
- "}",
- "task c(dependsOn: a)",
- "task d(dependsOn: a)",
- "task e(dependsOn: [a, d])");
- usingBuildFile(buildFile).withTasks("a", "b").run().assertTasksExecuted(":a", ":b");
- usingBuildFile(buildFile).withTasks("a", "a").run().assertTasksExecuted(":a");
- usingBuildFile(buildFile).withTasks("c", "a").run().assertTasksExecuted(":a", ":c");
- usingBuildFile(buildFile).withTasks("c", "e").run().assertTasksExecuted(":a", ":c", ":d", ":e");
- }
-
- @Test
- public void executesMultiProjectsTasksInASingleBuildAndEachTaskAtMostOnce() {
- testFile("settings.gradle").writelns("include 'child1', 'child2'");
- TestFile buildFile = testFile("build.gradle");
- buildFile.writelns(
- "task a",
- "allprojects {",
- " task b",
- " task c(dependsOn: ['b', ':a'])",
- "}");
- usingBuildFile(buildFile).withTasks("a", "c").run().assertTasksExecuted(":a", ":b", ":c", ":child1:b",
- ":child1:c", ":child2:b", ":child2:c");
- usingBuildFile(buildFile).withTasks("b", ":child2:c").run().assertTasksExecuted(":b", ":child1:b", ":child2:b",
- ":a", ":child2:c");
- }
-
- @Test
- public void executesMultiProjectDefaultTasksInASingleBuildAndEachTaskAtMostOnce() {
- testFile("settings.gradle").writelns("include 'child1', 'child2'");
- TestFile buildFile = testFile("build.gradle");
- buildFile.writelns("defaultTasks 'a', 'b'", "task a", "subprojects {", " task a(dependsOn: ':a')",
- " task b(dependsOn: ':a')", "}");
- usingBuildFile(buildFile).run().assertTasksExecuted(":a", ":child1:a", ":child2:a", ":child1:b", ":child2:b");
- }
-
- @Test
- public void executesProjectDefaultTasksWhenNoneSpecified() {
- TestFile buildFile = testFile("build.gradle");
- buildFile.writelns(
- "task a",
- "task b(dependsOn: a)",
- "defaultTasks 'b'"
- );
- usingBuildFile(buildFile).withTasks().run().assertTasksExecuted(":a", ":b");
- }
-
- @Test
- public void doesNotExecuteTaskActionsWhenDryRunSpecified() {
- TestFile buildFile = testFile("build.gradle");
- buildFile.writelns(
- "task a << { fail() }",
- "task b(dependsOn: a) << { fail() }",
- "defaultTasks 'b'"
- );
-
- // project defaults
- usingBuildFile(buildFile).withArguments("-m").run().assertTasksExecuted(":a", ":b");
- // named tasks
- usingBuildFile(buildFile).withArguments("-m").withTasks("b").run().assertTasksExecuted(":a", ":b");
- }
-
- @Test
- public void executesTaskActionsInCorrectEnvironment() {
- TestFile buildFile = testFile("build.gradle");
- buildFile.writelns(
- // An action attached to built-in task
- "task a << { assert Thread.currentThread().contextClassLoader == getClass().classLoader }",
- // An action defined by a custom task
- "task b(type: CustomTask)",
- "class CustomTask extends DefaultTask { @TaskAction def go() { assert Thread.currentThread().contextClassLoader == getClass().classLoader } } ",
- // An action implementation
- "task c; c.doLast new Action<Task>() { void execute(Task t) { assert Thread.currentThread().contextClassLoader == getClass().classLoader } }"
- );
-
- usingBuildFile(buildFile).withTasks("a", "b", "c").run();
- }
-
- @Test
- public void excludesTasksWhenExcludePatternSpecified() {
- testFile("settings.gradle").write("include 'sub'");
- TestFile buildFile = testFile("build.gradle");
- buildFile.writelns(
- "task a",
- "task b(dependsOn: a)",
- "task c(dependsOn: [a, b])",
- "task d(dependsOn: c)",
- "defaultTasks 'd'"
- );
- testFile("sub/build.gradle").writelns(
- "task c",
- "task d(dependsOn: c)"
- );
-
- // Exclude entire branch
- usingBuildFile(buildFile).withTasks(":d").withArguments("-x", "c").run().assertTasksExecuted(":d");
- // Exclude direct dependency
- usingBuildFile(buildFile).withTasks(":d").withArguments("-x", "b").run().assertTasksExecuted(":a", ":c", ":d");
- // Exclude using paths and multi-project
- usingBuildFile(buildFile).withTasks("d").withArguments("-x", "c").run().assertTasksExecuted(":d", ":sub:d");
- usingBuildFile(buildFile).withTasks("d").withArguments("-x", "sub:c").run().assertTasksExecuted(":a", ":b", ":c", ":d", ":sub:d");
- usingBuildFile(buildFile).withTasks("d").withArguments("-x", ":sub:c").run().assertTasksExecuted(":a", ":b", ":c", ":d", ":sub:d");
- usingBuildFile(buildFile).withTasks("d").withArguments("-x", "d").run().assertTasksExecuted();
- // Project defaults
- usingBuildFile(buildFile).withArguments("-x", "b").run().assertTasksExecuted(":a", ":c", ":d", ":sub:c", ":sub:d");
- // Unknown task
- usingBuildFile(buildFile).withTasks("d").withArguments("-x", "unknown").runWithFailure().assertThatDescription(startsWith("Task 'unknown' not found in root project"));
- }
-
- @Test
- @Issue("http://issues.gradle.org/browse/GRADLE-2022")
- public void tryingToInstantiateTaskDirectlyFailsWithGoodErrorMessage() {
- usingBuildFile(testFile("build.gradle").write("new DefaultTask()")).
- withTasks("tasks").
- runWithFailure().
- assertHasCause("Task of type 'org.gradle.api.DefaultTask' has been instantiated directly which is not supported");
- }
-}
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/TaskSubclassingBinaryCompatibilityCrossVersionSpec.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/TaskSubclassingBinaryCompatibilityCrossVersionSpec.groovy
new file mode 100644
index 0000000..47b3514
--- /dev/null
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/TaskSubclassingBinaryCompatibilityCrossVersionSpec.groovy
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests
+
+import org.gradle.integtests.fixtures.CrossVersionIntegrationSpec
+import org.gradle.integtests.fixtures.TargetVersions
+import org.gradle.util.GradleVersion
+
+/**
+ * Tests that task classes compiled against earlier versions of Gradle are still compatible.
+ */
+ at TargetVersions('0.9-rc-3+')
+class TaskSubclassingBinaryCompatibilityCrossVersionSpec extends CrossVersionIntegrationSpec {
+ def "can use task subclass compiled using previous Gradle version"() {
+ given:
+ def taskClasses = [
+ "DefaultTask", "SourceTask", "ConventionTask",
+ "Copy", "Sync", "Zip", "Jar", "Tar", "War", "Ear"
+ ]
+
+ // Ear plugin added in m4.
+ if (previous.version < GradleVersion.version("1.0-milestone-4")) {
+ taskClasses.remove("Ear")
+ }
+
+ Map<String, String> subclasses = taskClasses.collectEntries { ["custom" + it, it] }
+
+ file("producer/build.gradle") << """
+ apply plugin: 'groovy'
+ dependencies {
+ ${previous.version < GradleVersion.version("1.4-rc-1") ? "groovy" : "compile" } localGroovy()
+ compile gradleApi()
+ }
+ """
+
+ file("producer/src/main/groovy/SomePlugin.groovy") << """
+ import org.gradle.api.Plugin
+ import org.gradle.api.Project
+ import org.gradle.api.DefaultTask
+ import org.gradle.api.tasks.*
+ import org.gradle.api.tasks.bundling.*
+ ${taskClasses.contains("Ear") ? "import org.gradle.plugins.ear.Ear" : ""}
+ import org.gradle.api.internal.ConventionTask
+
+ class SomePlugin implements Plugin<Project> {
+ void apply(Project p) { """ <<
+ subclasses.collect { "p.tasks.add('${it.key}', ${it.key.capitalize()})" }.join("\n") << """
+ }
+ }
+ """ <<
+
+ subclasses.collect {
+ "class ${it.key.capitalize()} extends ${it.value} {}"
+ }.join("\n")
+
+ buildFile << """
+buildscript {
+ dependencies { classpath fileTree(dir: "producer/build/libs", include: '*.jar') }
+}
+
+apply plugin: SomePlugin
+"""
+
+ expect:
+ version previous withTasks 'assemble' inDirectory(file("producer")) run()
+ version current withTasks 'tasks' run()
+ }
+}
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/WaterProjectIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/WaterProjectIntegrationTest.groovy
index 68b74d6..9b5f2cf 100644
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/WaterProjectIntegrationTest.groovy
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/WaterProjectIntegrationTest.groovy
@@ -25,9 +25,6 @@ import org.junit.Test
import static org.junit.Assert.assertEquals
-/**
- * @author Hans Dockter
- */
class WaterProjectIntegrationTest {
final static String NL = SystemProperties.lineSeparator
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/WebProjectIntegrationTest.java b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/WebProjectIntegrationTest.java
index d8acaa5..d183533 100644
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/WebProjectIntegrationTest.java
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/WebProjectIntegrationTest.java
@@ -34,7 +34,7 @@ public class WebProjectIntegrationTest extends AbstractIntegrationTest {
}
@Test
- public void canCustomiseArchiveNamesUsingConventionProperties() {
+ public void canCustomizeArchiveNamesUsingConventionProperties() {
testFile("settings.gradle").writelns("rootProject.name = 'test'");
TestFile buildFile = testFile("build.gradle");
buildFile.writelns(
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/environment/BuildEnvironmentIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/environment/BuildEnvironmentIntegrationTest.groovy
index ab3ca6a..db712cb 100644
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/environment/BuildEnvironmentIntegrationTest.groovy
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/environment/BuildEnvironmentIntegrationTest.groovy
@@ -25,9 +25,6 @@ import org.gradle.util.TextUtil
import spock.lang.IgnoreIf
import spock.lang.Issue
-/**
- * @author: Szczepan Faber, created at: 8/11/11
- */
class BuildEnvironmentIntegrationTest extends AbstractIntegrationSpec {
def "canonicalizes working directory"() {
given:
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/fixture/TempDirIsUniquePerTestSpec.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/fixture/TempDirIsUniquePerTestSpec.groovy
index 517a83e..cc7544a 100644
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/fixture/TempDirIsUniquePerTestSpec.groovy
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/fixture/TempDirIsUniquePerTestSpec.groovy
@@ -21,9 +21,6 @@ import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
import org.junit.Rule
import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 3/14/12
- */
class TempDirIsUniquePerTestSpec extends Specification {
@Rule TestNameTestDirectoryProvider tmp = new TestNameTestDirectoryProvider();
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/logging/LoggingIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/logging/LoggingIntegrationTest.groovy
index 6f20307..c2859da 100644
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/logging/LoggingIntegrationTest.groovy
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/logging/LoggingIntegrationTest.groovy
@@ -26,9 +26,6 @@ import org.gradle.test.fixtures.file.TestFile
import org.junit.Rule
import org.junit.Test
-/**
- * @author Hans Dockter
- */
class LoggingIntegrationTest extends AbstractIntegrationTest {
@Rule public final TestResources resources = new TestResources(testDirectoryProvider)
@@ -247,39 +244,6 @@ class LoggingIntegrationTest extends AbstractIntegrationTest {
ExecutionResult result = run.call(level)
level.checkOuts(result)
}
-
- @Test
- public void deprecatedLogging() {
- LogLevel deprecated = new LogLevel(
- args: [],
- infoMessages: [['A deprecation warning']],
- errorMessages: [],
- allMessages: []
- )
-
- resources.maybeCopy('LoggingIntegrationTest/deprecated')
- ExecutionResult result = executer.withDeprecationChecksDisabled().withArguments(deprecated.args).withTasks('log').run()
- deprecated.checkOuts(result)
-
- // Ensure warnings are logged the second time
- ExecutionResult secondResult = executer.withDeprecationChecksDisabled().withArguments(deprecated.args).withTasks('log').run()
- deprecated.checkOuts(secondResult)
- }
-
- @Test
- public void deprecatedLoggingIsNotDisplayedWithQuietFlag() {
- LogLevel deprecated = new LogLevel(
- args: ['-q'],
- infoMessages: [],
- errorMessages: [],
- allMessages: [['A deprecation warning']]
- )
-
- resources.maybeCopy('LoggingIntegrationTest/deprecated')
- ExecutionResult result = executer.withArguments(deprecated.args).withTasks('log').run()
-
- deprecated.checkOuts(result)
- }
}
class LogLevel {
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/publish/ivy/IvyHttpPublishIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/publish/ivy/IvyHttpPublishIntegrationTest.groovy
index 6719171..1f22d18 100644
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/publish/ivy/IvyHttpPublishIntegrationTest.groovy
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/publish/ivy/IvyHttpPublishIntegrationTest.groovy
@@ -20,12 +20,11 @@ package org.gradle.integtests.publish.ivy
import org.gradle.integtests.fixtures.AbstractIntegrationSpec
import org.gradle.integtests.fixtures.executer.ProgressLoggingFixture
import org.gradle.test.fixtures.file.TestFile
-import org.gradle.test.fixtures.ivy.IvyFileModule
-import org.gradle.test.fixtures.ivy.IvyModule
+import org.gradle.test.fixtures.ivy.IvyHttpModule
+import org.gradle.test.fixtures.ivy.IvyHttpRepository
import org.gradle.test.fixtures.server.http.HttpServer
import org.gradle.util.GradleVersion
import org.gradle.util.Jvm
-import org.gradle.util.TextUtil
import org.hamcrest.Matchers
import org.junit.Rule
import org.mortbay.jetty.HttpStatus
@@ -40,16 +39,15 @@ credentials {
password 'bad'
}
'''
- @Rule
- public final HttpServer server = new HttpServer()
-
@Rule ProgressLoggingFixture progressLogging = new ProgressLoggingFixture(executer, temporaryFolder)
+ @Rule HttpServer server = new HttpServer()
- private IvyModule module
+ private IvyHttpModule module
+ private IvyHttpRepository ivyHttpRepo
def setup() {
- module = ivyRepo.module("org.gradle", "publish", "2")
- module.moduleDir.mkdirs()
+ ivyHttpRepo = new IvyHttpRepository(server, ivyRepo)
+ module = ivyHttpRepo.module("org.gradle", "publish", "2")
server.expectUserAgent(matchesNameAndVersion("Gradle", GradleVersion.current().getVersion()))
}
@@ -65,30 +63,29 @@ group = 'org.gradle'
uploadArchives {
repositories {
ivy {
- url "http://localhost:${server.port}"
+ url "${ivyHttpRepo.uri}"
}
}
}
"""
- when:
- expectUpload('/org.gradle/publish/2/publish-2.jar', module, module.jarFile, HttpStatus.ORDINAL_200_OK)
- expectUpload('/org.gradle/publish/2/ivy-2.xml', module, module.ivyFile, HttpStatus.ORDINAL_201_Created)
-
and:
- succeeds 'uploadArchives'
+ module.expectJarPut()
+ module.expectJarSha1Put()
+ module.expectIvyPut(HttpStatus.ORDINAL_201_Created)
+ module.expectIvySha1Put(HttpStatus.ORDINAL_201_Created)
- then:
- module.ivyFile.assertIsFile()
- module.assertChecksumPublishedFor(module.ivyFile)
+ when:
+ run 'uploadArchives'
+ then:
+ module.assertIvyAndJarFilePublished()
module.jarFile.assertIsCopyOf(file('build/libs/publish-2.jar'))
- module.assertChecksumPublishedFor(module.jarFile)
+
and:
- progressLogging.uploadProgressLogged("http://localhost:${server.port}/org.gradle/publish/2/ivy-2.xml")
- progressLogging.uploadProgressLogged("http://localhost:${server.port}/org.gradle/publish/2/publish-2.jar")
+ progressLogging.uploadProgressLogged(module.ivyFileUri)
+ progressLogging.uploadProgressLogged(module.jarFileUri)
}
-
@Unroll
def "can publish to authenticated repository using #authScheme auth"() {
given:
@@ -106,29 +103,29 @@ uploadArchives {
username 'testuser'
password 'password'
}
- url "http://localhost:${server.port}"
+ url "${ivyHttpRepo.uri}"
}
}
}
"""
- when:
+ and:
server.authenticationScheme = authScheme
- expectUpload('/org.gradle/publish/2/publish-2.jar', module, module.jarFile, 'testuser', 'password')
- expectUpload('/org.gradle/publish/2/ivy-2.xml', module, module.ivyFile, 'testuser', 'password')
+ module.expectJarPut('testuser', 'password')
+ module.expectJarSha1Put('testuser', 'password')
+ module.expectIvyPut('testuser', 'password')
+ module.expectIvySha1Put('testuser', 'password')
- then:
- succeeds 'uploadArchives'
+ when:
+ run 'uploadArchives'
- and:
- module.ivyFile.assertIsFile()
- module.assertChecksumPublishedFor(module.ivyFile)
+ then:
+ module.assertIvyAndJarFilePublished()
module.jarFile.assertIsCopyOf(file('build/libs/publish-2.jar'))
- module.assertChecksumPublishedFor(module.jarFile)
and:
- progressLogging.uploadProgressLogged("http://localhost:${server.port}/org.gradle/publish/2/ivy-2.xml")
- progressLogging.uploadProgressLogged("http://localhost:${server.port}/org.gradle/publish/2/publish-2.jar")
+ progressLogging.uploadProgressLogged(module.ivyFileUri)
+ progressLogging.uploadProgressLogged(module.jarFileUri)
where:
authScheme << [HttpServer.AuthScheme.BASIC, HttpServer.AuthScheme.DIGEST]
@@ -139,7 +136,7 @@ uploadArchives {
given:
server.start()
- when:
+ and:
settingsFile << 'rootProject.name = "publish"'
buildFile << """
apply plugin: 'java'
@@ -149,7 +146,7 @@ uploadArchives {
repositories {
ivy {
$creds
- url "http://localhost:${server.port}"
+ url "${ivyHttpRepo.uri}"
}
}
}
@@ -157,12 +154,12 @@ uploadArchives {
and:
server.authenticationScheme = authScheme
- server.allowPut('/org.gradle/publish/2/publish-2.jar', 'testuser', 'password')
+ server.allowPut('/repo/org.gradle/publish/2/publish-2.jar', 'testuser', 'password')
- then:
+ when:
fails 'uploadArchives'
- and:
+ then:
failure.assertHasDescription('Execution failed for task \':uploadArchives\'.')
failure.assertHasCause('Could not publish configuration \'archives\'')
failure.assertThatCause(Matchers.containsString('Received status code 401 from server: Unauthorized'))
@@ -185,7 +182,7 @@ apply plugin: 'java'
uploadArchives {
repositories {
ivy {
- url "${repositoryUrl}"
+ url "${ivyHttpRepo.uri}"
}
}
}
@@ -226,31 +223,33 @@ uploadArchives {
uploadArchives {
repositories {
ivy {
- artifactPattern "http://localhost:${server.port}/primary/[module]/[artifact]-[revision].[ext]"
+ artifactPattern "${ivyHttpRepo.artifactPattern}"
artifactPattern "http://localhost:${server.port}/alternative/[module]/[artifact]-[revision].[ext]"
- ivyPattern "http://localhost:${server.port}/primary-ivy/[module]/ivy-[revision].xml"
+ ivyPattern "${ivyHttpRepo.ivyPattern}"
ivyPattern "http://localhost:${server.port}/secondary-ivy/[module]/ivy-[revision].xml"
}
}
}
"""
+ and:
+ module.expectJarPut()
+ module.expectJarSha1Put()
+ module.expectIvyPut()
+ module.expectIvySha1Put()
+
when:
- expectUpload('/primary/publish/publish-2.jar', module, module.jarFile, HttpStatus.ORDINAL_200_OK)
- expectUpload('/primary-ivy/publish/ivy-2.xml', module, module.ivyFile)
+ run 'uploadArchives'
then:
- succeeds 'uploadArchives'
-
- and:
- module.ivyFile.assertIsFile()
+ module.assertIvyAndJarFilePublished()
module.jarFile.assertIsCopyOf(file('build/libs/publish-2.jar'))
}
public void "can publish large artifact (tools.jar) to authenticated repository"() {
given:
server.start()
- def toolsJar = TextUtil.escapeString(Jvm.current().toolsJar)
+ def toolsJar = Jvm.current().toolsJar
settingsFile << 'rootProject.name = "publish"'
buildFile << """
@@ -262,8 +261,8 @@ configurations {
tools
}
artifacts {
- tools(file('$toolsJar')) {
- name 'tools'
+ tools(file('${toolsJar.toURI()}')) {
+ name 'publish'
}
}
@@ -274,24 +273,24 @@ uploadTools {
username 'testuser'
password 'password'
}
- url "http://localhost:${server.port}"
+ url "${ivyHttpRepo.uri}"
}
}
}
"""
+ and:
+ module.expectJarPut('testuser', 'password')
+ module.expectJarSha1Put('testuser', 'password')
+ module.expectIvyPut('testuser', 'password')
+ module.expectIvySha1Put('testuser', 'password')
+
when:
- def uploadedToolsJar = module.moduleDir.file('toolsJar')
- expectUpload('/org.gradle/publish/2/tools-2.jar', module, uploadedToolsJar, 'testuser', 'password')
- expectUpload('/org.gradle/publish/2/ivy-2.xml', module, module.ivyFile, 'testuser', 'password')
+ run 'uploadTools'
then:
- succeeds 'uploadTools'
-
- and:
- module.ivyFile.assertIsFile()
- uploadedToolsJar.assertIsCopyOf(new TestFile(toolsJar));
-
+ module.assertIvyAndJarFilePublished()
+ module.jarFile.assertIsCopyOf(new TestFile(toolsJar))
}
public void "does not upload meta-data file if artifact upload fails"() {
@@ -306,29 +305,19 @@ group = 'org.gradle'
uploadArchives {
repositories {
ivy {
- url "http://localhost:${server.port}"
+ url "${ivyHttpRepo.uri}"
}
}
}
"""
- when:
- server.expectPut("/org.gradle/publish/2/publish-2.jar", module.jarFile, HttpStatus.ORDINAL_500_Internal_Server_Error)
+ and:
+ module.expectJarPut(HttpStatus.ORDINAL_500_Internal_Server_Error)
- then:
+ when:
fails 'uploadArchives'
- and:
+ then:
module.jarFile.assertExists()
module.ivyFile.assertDoesNotExist()
}
-
- private void expectUpload(String path, IvyFileModule module, TestFile file, int statusCode = HttpStatus.ORDINAL_200_OK) {
- server.expectPut(path, file, statusCode)
- server.expectPut("${path}.sha1", module.sha1File(file), statusCode)
- }
-
- private void expectUpload(String path, IvyFileModule module, TestFile file, String username, String password) {
- server.expectPut(path, username, password, file)
- server.expectPut("${path}.sha1", username, password, module.sha1File(file))
- }
}
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/publish/ivy/IvyLocalPublishIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/publish/ivy/IvyLocalPublishIntegrationTest.groovy
index 26dbd40..9f1335e 100644
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/publish/ivy/IvyLocalPublishIntegrationTest.groovy
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/publish/ivy/IvyLocalPublishIntegrationTest.groovy
@@ -41,11 +41,8 @@ uploadArchives {
succeeds 'uploadArchives'
then:
- module.ivyFile.assertIsFile()
- module.assertChecksumPublishedFor(module.ivyFile)
-
+ module.assertIvyAndJarFilePublished()
module.jarFile.assertIsCopyOf(file('build/libs/publish-2.jar'))
- module.assertChecksumPublishedFor(module.jarFile)
}
@Issue("GRADLE-2456")
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/publish/ivy/IvySFtpPublishIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/publish/ivy/IvySFtpPublishIntegrationTest.groovy
index 6247e45..0995405 100644
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/publish/ivy/IvySFtpPublishIntegrationTest.groovy
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/publish/ivy/IvySFtpPublishIntegrationTest.groovy
@@ -48,13 +48,18 @@ class IvySFtpPublishIntegrationTest extends AbstractIntegrationSpec {
}
}
"""
- when:
+ and:
+ executer.withDeprecationChecksDisabled()
+
+ when:
run "uploadArchives"
+
then:
sftpServer.hasFile("repos/libs/org.gradle/publish/publish-2.jar")
sftpServer.hasFile("repos/libs/org.gradle/publish/ivy-2.xml");
sftpServer.file("repos/libs/org.gradle/publish/publish-2.jar").assertIsCopyOf(file('build/libs/publish-2.jar'))
+
and:
progressLogging.uploadProgressLogged("repos/libs/org.gradle/publish/ivy-2.xml")
progressLogging.uploadProgressLogged("repos/libs/org.gradle/publish/publish-2.jar")
@@ -81,6 +86,10 @@ class IvySFtpPublishIntegrationTest extends AbstractIntegrationSpec {
}
}
"""
+
+ and:
+ executer.withDeprecationChecksDisabled()
+
when:
fails "uploadArchives"
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/publish/ivy/IvyUrlResolverPublishIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/publish/ivy/IvyUrlResolverPublishIntegrationTest.groovy
new file mode 100644
index 0000000..2f07b8a
--- /dev/null
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/publish/ivy/IvyUrlResolverPublishIntegrationTest.groovy
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests.publish.ivy
+
+import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+import org.gradle.integtests.fixtures.executer.ProgressLoggingFixture
+import org.gradle.test.fixtures.ivy.IvyHttpModule
+import org.gradle.test.fixtures.ivy.IvyHttpRepository
+import org.gradle.test.fixtures.server.http.HttpServer
+import org.junit.Rule
+
+public class IvyUrlResolverPublishIntegrationTest extends AbstractIntegrationSpec {
+ @Rule ProgressLoggingFixture progressLogging = new ProgressLoggingFixture(executer, temporaryFolder)
+ @Rule HttpServer server = new HttpServer()
+
+ private IvyHttpModule module
+ private IvyHttpRepository ivyHttpRepo
+
+ def setup() {
+ ivyHttpRepo = new IvyHttpRepository(server, ivyRepo)
+ module = ivyHttpRepo.module("org.gradle", "publish", "2")
+ }
+
+ public void canPublishToAnHttpRepository() {
+ given:
+ server.start()
+
+ settingsFile << 'rootProject.name = "publish"'
+ buildFile << """
+apply plugin: 'java'
+version = '2'
+group = 'org.gradle'
+
+uploadArchives {
+ repositories {
+ add(new org.apache.ivy.plugins.resolver.URLResolver()) {
+ addIvyPattern("${ivyHttpRepo.ivyPattern}")
+ addArtifactPattern("${ivyHttpRepo.artifactPattern}")
+ }
+ }
+}
+"""
+
+ and:
+ module.expectJarPut();
+ module.expectIvyPut();
+
+ and:
+ executer.withDeprecationChecksDisabled()
+
+ when:
+ run 'uploadArchives'
+
+ then:
+ module.ivyFile.assertIsFile()
+ module.jarFile.assertIsCopyOf(file('build/libs/publish-2.jar'))
+
+ and:
+ progressLogging.uploadProgressLogged(module.jarFileUri)
+ progressLogging.uploadProgressLogged(module.ivyFileUri)
+ }
+}
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/publish/ivy/SamplesIvyPublishIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/publish/ivy/SamplesIvyPublishIntegrationTest.groovy
index 13cc507..89ed11a 100644
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/publish/ivy/SamplesIvyPublishIntegrationTest.groovy
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/publish/ivy/SamplesIvyPublishIntegrationTest.groovy
@@ -20,9 +20,6 @@ import org.gradle.integtests.fixtures.Sample
import org.junit.Rule
import org.junit.Test
-/**
- * @author Hans Dockter
- */
public class SamplesIvyPublishIntegrationTest extends AbstractIntegrationTest {
@Rule
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/publish/maven/SamplesMavenPomGenerationIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/publish/maven/SamplesMavenPomGenerationIntegrationTest.groovy
index 29598c4..17612a4 100644
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/publish/maven/SamplesMavenPomGenerationIntegrationTest.groovy
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/publish/maven/SamplesMavenPomGenerationIntegrationTest.groovy
@@ -30,9 +30,6 @@ import org.junit.Before
import org.junit.Rule
import org.junit.Test
-/**
- * @author Hans Dockter
- */
class SamplesMavenPomGenerationIntegrationTest extends AbstractIntegrationTest {
private TestFile pomProjectDir
@@ -49,7 +46,7 @@ class SamplesMavenPomGenerationIntegrationTest extends AbstractIntegrationTest {
def repo = maven(pomProjectDir.file('pomRepo'))
def module = repo.module('deployGroup', 'mywar', '1.0MVN')
- executer.inDirectory(pomProjectDir).withTasks('uploadArchives').withArguments("--stacktrace").run()
+ executer.inDirectory(pomProjectDir).withTasks('uploadArchives').run()
compareXmlWithIgnoringOrder(expectedPom('1.0MVN', "deployGroup"), module.pomFile.text)
module.moduleDir.file("mywar-1.0MVN.war").assertIsCopyOf(pomProjectDir.file("target/libs/mywar-1.0.war"))
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/publish/maven/SamplesMavenQuickstartIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/publish/maven/SamplesMavenQuickstartIntegrationTest.groovy
index f40ad61..5259bac 100755
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/publish/maven/SamplesMavenQuickstartIntegrationTest.groovy
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/publish/maven/SamplesMavenQuickstartIntegrationTest.groovy
@@ -28,9 +28,6 @@ import org.junit.Before
import org.junit.Rule
import org.junit.Test
-/**
- * @author Hans Dockter
- */
class SamplesMavenQuickstartIntegrationTest extends AbstractIntegrationTest {
@Rule public Resources resources = new Resources();
@Rule public final Sample sample = new Sample(testDirectoryProvider, 'maven/quickstart')
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/AutoTestedSamplesCoreIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/AutoTestedSamplesCoreIntegrationTest.groovy
index baf8110..b3633d3 100644
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/AutoTestedSamplesCoreIntegrationTest.groovy
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/AutoTestedSamplesCoreIntegrationTest.groovy
@@ -19,9 +19,6 @@ package org.gradle.integtests.samples
import org.gradle.integtests.fixtures.AbstractAutoTestedSamplesTest
import org.junit.Test
-/**
- * @author Szczepan Faber, created at: 3/28/11
- */
class AutoTestedSamplesCoreIntegrationTest extends AbstractAutoTestedSamplesTest {
@Test
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/AutoTestedSamplesPluginsIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/AutoTestedSamplesPluginsIntegrationTest.groovy
index 44e5f1b..e63ad62 100644
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/AutoTestedSamplesPluginsIntegrationTest.groovy
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/AutoTestedSamplesPluginsIntegrationTest.groovy
@@ -19,9 +19,6 @@ package org.gradle.integtests.samples
import org.gradle.integtests.fixtures.AbstractAutoTestedSamplesTest
import org.junit.Test
-/**
- * @author Szczepan Faber, created at: 3/28/11
- */
class AutoTestedSamplesPluginsIntegrationTest extends AbstractAutoTestedSamplesTest {
@Test
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/JUnitSamplesIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/JUnitSamplesIntegrationTest.groovy
new file mode 100644
index 0000000..9e7dcf7
--- /dev/null
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/JUnitSamplesIntegrationTest.groovy
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests.samples
+
+import org.gradle.integtests.fixtures.AbstractIntegrationTest
+import org.gradle.integtests.fixtures.DefaultTestExecutionResult
+import org.gradle.integtests.fixtures.Sample
+import org.gradle.test.fixtures.file.TestFile
+import org.junit.Rule
+import org.junit.Test
+
+public class JUnitSamplesIntegrationTest extends AbstractIntegrationTest {
+
+ @Rule
+ public final Sample sample = new Sample(testDirectoryProvider, 'testing/junit')
+
+ @Test
+ public void categegoriesSample() {
+ TestFile projectDir = sample.dir.file("categories")
+
+ // Build and test projects
+ executer.inDirectory(projectDir).withTasks('clean', 'build').withArguments("--no-opt").run()
+
+ // Check tests have run
+ DefaultTestExecutionResult result = new DefaultTestExecutionResult(projectDir)
+ result.assertTestClassesExecuted('org.gradle.junit.CategorizedJUnitTest')
+ }
+}
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesCodeQualityIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesCodeQualityIntegrationTest.groovy
index e603b85..a743894 100755
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesCodeQualityIntegrationTest.groovy
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesCodeQualityIntegrationTest.groovy
@@ -21,9 +21,6 @@ import org.gradle.test.fixtures.file.TestFile
import org.junit.Rule
import org.junit.Test
-/**
- * @author Hans Dockter
- */
class SamplesCodeQualityIntegrationTest extends AbstractIntegrationTest {
@Rule public final Sample sample = new Sample(testDirectoryProvider, 'codeQuality')
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesExcludesAndClassifiersIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesExcludesAndClassifiersIntegrationTest.groovy
index 365d1a8..5d9589f 100644
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesExcludesAndClassifiersIntegrationTest.groovy
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesExcludesAndClassifiersIntegrationTest.groovy
@@ -25,9 +25,6 @@ import static org.hamcrest.Matchers.containsString
import static org.hamcrest.Matchers.not
import static org.junit.Assert.assertThat
-/**
- * @author Hans Dockter
- */
class SamplesExcludesAndClassifiersIntegrationTest extends AbstractIntegrationTest {
@Rule public final Sample sample = new Sample(testDirectoryProvider, 'userguide/artifacts/excludesAndClassifiers')
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesGroovyMultiProjectIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesGroovyMultiProjectIntegrationTest.groovy
index cf34f36..3536ccd 100644
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesGroovyMultiProjectIntegrationTest.groovy
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesGroovyMultiProjectIntegrationTest.groovy
@@ -24,9 +24,6 @@ import org.junit.Test
import static org.hamcrest.Matchers.containsString
-/**
- * @author Hans Dockter
- */
class SamplesGroovyMultiProjectIntegrationTest extends AbstractIntegrationTest {
static final String TEST_PROJECT_NAME = 'testproject'
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesJUnitIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesJUnitIntegrationTest.groovy
new file mode 100644
index 0000000..432e832
--- /dev/null
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesJUnitIntegrationTest.groovy
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests.samples
+
+import org.gradle.integtests.fixtures.AbstractIntegrationTest
+import org.gradle.integtests.fixtures.DefaultTestExecutionResult
+import org.gradle.integtests.fixtures.Sample
+import org.gradle.test.fixtures.file.TestFile
+import org.junit.Rule
+import org.junit.Test
+
+public class SamplesJUnitIntegrationTest extends AbstractIntegrationTest {
+
+ @Rule
+ public final Sample sample = new Sample(testDirectoryProvider, 'testing/junit')
+
+ @Test
+ public void categoriesSample() {
+ TestFile projectDir = sample.dir.file("categories")
+
+ // Build and test projects
+ executer.inDirectory(projectDir).withTasks('clean', 'build').run()
+
+ // Check tests have run
+ DefaultTestExecutionResult result = new DefaultTestExecutionResult(projectDir)
+ result.assertTestClassesExecuted('org.gradle.junit.CategorizedJUnitTest')
+ }
+}
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesJavaBaseIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesJavaBaseIntegrationTest.groovy
index 6313f15..dcbc393 100644
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesJavaBaseIntegrationTest.groovy
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesJavaBaseIntegrationTest.groovy
@@ -23,9 +23,6 @@ import org.gradle.test.fixtures.file.TestFile
import org.junit.Rule
import org.junit.Test
-/**
- * @author Hans Dockter
- */
class SamplesJavaBaseIntegrationTest extends AbstractIntegrationTest {
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesJavaCustomizedLayoutIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesJavaCustomizedLayoutIntegrationTest.groovy
index 7424337..13e6a49 100644
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesJavaCustomizedLayoutIntegrationTest.groovy
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesJavaCustomizedLayoutIntegrationTest.groovy
@@ -23,9 +23,6 @@ import org.gradle.test.fixtures.file.TestFile
import org.junit.Rule
import org.junit.Test
-/**
- * @author Hans Dockter
- */
class SamplesJavaCustomizedLayoutIntegrationTest extends AbstractIntegrationTest {
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesJavaMultiProjectIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesJavaMultiProjectIntegrationTest.groovy
index aafa6f5..9fecf84 100644
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesJavaMultiProjectIntegrationTest.groovy
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesJavaMultiProjectIntegrationTest.groovy
@@ -28,9 +28,6 @@ import org.junit.Test
import static org.hamcrest.Matchers.containsString
-/**
- * @author Hans Dockter
- */
class SamplesJavaMultiProjectIntegrationTest extends AbstractIntegrationTest {
static final String JAVA_PROJECT_NAME = 'java/multiproject'
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesJavaProjectWithIntTestsIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesJavaProjectWithIntTestsIntegrationTest.groovy
index da03b3c..e427174 100644
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesJavaProjectWithIntTestsIntegrationTest.groovy
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesJavaProjectWithIntTestsIntegrationTest.groovy
@@ -23,9 +23,6 @@ import org.gradle.test.fixtures.file.TestFile
import org.junit.Rule
import org.junit.Test
-/**
- * @author Hans Dockter
- */
class SamplesJavaProjectWithIntTestsIntegrationTest extends AbstractIntegrationTest {
@Rule public final Sample sample = new Sample(testDirectoryProvider, 'java/withIntegrationTests')
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesJavaQuickstartIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesJavaQuickstartIntegrationTest.groovy
index c5cfe15..94938a7 100644
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesJavaQuickstartIntegrationTest.groovy
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesJavaQuickstartIntegrationTest.groovy
@@ -28,9 +28,6 @@ import java.util.jar.Manifest
import static org.hamcrest.Matchers.equalTo
import static org.junit.Assert.assertThat
-/**
- * @author Hans Dockter
- */
class SamplesJavaQuickstartIntegrationTest extends AbstractIntegrationTest {
@Rule public final Sample sample = new Sample(testDirectoryProvider, 'java/quickstart')
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesRepositoriesIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesRepositoriesIntegrationTest.groovy
index 83a82d8..a95fef0 100644
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesRepositoriesIntegrationTest.groovy
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesRepositoriesIntegrationTest.groovy
@@ -24,9 +24,6 @@ import org.junit.Test
import static org.hamcrest.Matchers.equalTo
import static org.junit.Assert.assertThat
-/**
- * @author Hans Dockter
- */
class SamplesRepositoriesIntegrationTest extends AbstractIntegrationTest {
@Rule public final Sample sample = new Sample(testDirectoryProvider, 'userguide/artifacts/defineRepository')
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesWebProjectIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesWebProjectIntegrationTest.groovy
index 2ea1387..ca5c187 100644
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesWebProjectIntegrationTest.groovy
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesWebProjectIntegrationTest.groovy
@@ -21,13 +21,10 @@ import org.gradle.integtests.fixtures.Sample
import org.gradle.test.fixtures.file.TestFile
import org.junit.Rule
-/**
- * @author Hans Dockter
- */
class SamplesWebProjectIntegrationTest extends AbstractIntegrationSpec {
- static final String WEB_PROJECT_NAME = 'customised'
+ static final String WEB_PROJECT_NAME = 'customized'
- @Rule public final Sample sample = new Sample(temporaryFolder, 'webApplication/customised')
+ @Rule public final Sample sample = new Sample(temporaryFolder, 'webApplication/customized')
def "can build war"() {
when:
@@ -36,7 +33,7 @@ class SamplesWebProjectIntegrationTest extends AbstractIntegrationSpec {
then:
TestFile tmpDir = file('unjar')
- sample.dir.file("build/libs/customised-1.0.war").unzipTo(tmpDir)
+ sample.dir.file("build/libs/customized-1.0.war").unzipTo(tmpDir)
tmpDir.assertHasDescendants(
'root.txt',
'META-INF/MANIFEST.MF',
@@ -74,7 +71,7 @@ task runWarTest(dependsOn: jettyRunWar) << {
}
private void callServlet() {
- URL url = new URL("http://localhost:\$httpPort/customised/hello")
+ URL url = new URL("http://localhost:\$httpPort/customized/hello")
println url.text
jettyStop.execute()
}
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesWebQuickstartIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesWebQuickstartIntegrationTest.groovy
index 03bdf3e..06107ce 100644
--- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesWebQuickstartIntegrationTest.groovy
+++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesWebQuickstartIntegrationTest.groovy
@@ -23,9 +23,6 @@ import org.junit.Rule
import spock.lang.Timeout
import spock.lang.Unroll
-/**
- * @author Hans Dockter
- */
class SamplesWebQuickstartIntegrationTest extends AbstractIntegrationSpec {
@Rule public final Sample sample = new Sample(temporaryFolder, 'webApplication/quickstart')
diff --git a/subprojects/integ-test/src/integTest/resources/org/gradle/integtests/ExecIntegrationTest/canExecuteCommands/canExecuteCommands.gradle b/subprojects/integ-test/src/integTest/resources/org/gradle/integtests/ExecIntegrationTest/canExecuteCommands/canExecuteCommands.gradle
index 1950843..681f6fd 100644
--- a/subprojects/integ-test/src/integTest/resources/org/gradle/integtests/ExecIntegrationTest/canExecuteCommands/canExecuteCommands.gradle
+++ b/subprojects/integ-test/src/integTest/resources/org/gradle/integtests/ExecIntegrationTest/canExecuteCommands/canExecuteCommands.gradle
@@ -12,6 +12,7 @@ task execTask(type: Exec) {
doLast {
assert testFile.exists()
}
+ assert delegate instanceof ExtensionAware
}
task execByMethod {
@@ -19,8 +20,9 @@ task execByMethod {
ext.testFile = file("$buildDir/$name")
doFirst {
exec {
- executable = Jvm.current().getJavaExecutable()
+ executable Jvm.current().getJavaExecutable()
args '-cp', sourceSets.main.runtimeClasspath.asPath, 'org.gradle.TestMain', projectDir, testFile
+ assert !(delegate instanceof ExtensionAware)
}
}
doLast {
diff --git a/subprojects/integ-test/src/integTest/resources/org/gradle/integtests/ExecIntegrationTest/canExecuteJava/canExecuteJava.gradle b/subprojects/integ-test/src/integTest/resources/org/gradle/integtests/ExecIntegrationTest/canExecuteJava/canExecuteJava.gradle
index 1e3a688..9edead9 100644
--- a/subprojects/integ-test/src/integTest/resources/org/gradle/integtests/ExecIntegrationTest/canExecuteJava/canExecuteJava.gradle
+++ b/subprojects/integ-test/src/integTest/resources/org/gradle/integtests/ExecIntegrationTest/canExecuteJava/canExecuteJava.gradle
@@ -10,14 +10,16 @@ task javaexecTask(type: JavaExec, dependsOn: classes) {
doLast {
assert testFile.exists()
}
+ assert delegate instanceof ExtensionAware
}
task javaexecByMethod(dependsOn: classes) {
ext.testFile = file("$buildDir/$name")
doFirst {
javaexec {
+ assert !(delegate instanceof ExtensionAware)
classpath(sourceSets.main.output.classesDir)
- main = 'org.gradle.TestMain'
+ main 'org.gradle.TestMain'
args projectDir, testFile
}
}
diff --git a/subprojects/integ-test/src/integTest/resources/org/gradle/integtests/logging/LoggingIntegrationTest/deprecated/build.gradle b/subprojects/integ-test/src/integTest/resources/org/gradle/integtests/logging/LoggingIntegrationTest/deprecated/build.gradle
deleted file mode 100644
index 597f51c..0000000
--- a/subprojects/integ-test/src/integTest/resources/org/gradle/integtests/logging/LoggingIntegrationTest/deprecated/build.gradle
+++ /dev/null
@@ -1,7 +0,0 @@
-
-task log {
- DeprecationLogger.nagUserWith("A deprecation warning")
- doLast {
- DeprecationLogger.nagUserWith("A deprecation warning")
- }
-}
\ No newline at end of file
diff --git a/subprojects/integ-test/src/integTest/resources/org/gradle/integtests/logging/LoggingIntegrationTest/logging/project1/build.gradle b/subprojects/integ-test/src/integTest/resources/org/gradle/integtests/logging/LoggingIntegrationTest/logging/project1/build.gradle
index ca46ce9..1d34dc4 100644
--- a/subprojects/integ-test/src/integTest/resources/org/gradle/integtests/logging/LoggingIntegrationTest/logging/project1/build.gradle
+++ b/subprojects/integ-test/src/integTest/resources/org/gradle/integtests/logging/LoggingIntegrationTest/logging/project1/build.gradle
@@ -41,11 +41,9 @@ task logInfo {
}
// END SNIPPET task-capture-stdout
-task nestedBuildLog << {
- def startParam = project.gradle.startParameter.newBuild()
- startParam.currentDir = rootProject.file('nestedBuild')
- startParam.taskNames = ['log']
- GradleLauncher.newInstance(startParam).run().rethrowFailure()
+task nestedBuildLog(type: GradleBuild) {
+ startParameter.currentDir = rootProject.file('nestedBuild')
+ startParameter.taskNames = ['log']
}
task log(dependsOn: [logInfo, logLifecycle, nestedBuildLog]) << {
diff --git a/subprojects/internal-integ-testing/internal-integ-testing.gradle b/subprojects/internal-integ-testing/internal-integ-testing.gradle
index 61cd919..5babe61 100644
--- a/subprojects/internal-integ-testing/internal-integ-testing.gradle
+++ b/subprojects/internal-integ-testing/internal-integ-testing.gradle
@@ -14,7 +14,7 @@
* limitations under the License.
*/
dependencies {
- groovy libraries.groovy
+ compile libraries.groovy
compile project(":internalTesting")
compile project(':cli')
compile project(':launcher')
@@ -32,7 +32,7 @@ useClassycle()
task prepareVersionsInfo(type: PrepareVersionsInfo) {
url = "http://services.gradle.org/versions/all"
- destDir = file("$buildDir/generated-resources/main")
+ destDir = generatedResourcesDir
destFileName = "all-released-versions.json"
offline = gradle.startParameter.offline
}
diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/AbstractAutoTestedSamplesTest.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/AbstractAutoTestedSamplesTest.groovy
index 9d536a8..5f5dade 100644
--- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/AbstractAutoTestedSamplesTest.groovy
+++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/AbstractAutoTestedSamplesTest.groovy
@@ -16,9 +16,6 @@
package org.gradle.integtests.fixtures
-/**
- * @author Szczepan Faber, created at: 4/2/11
- */
class AbstractAutoTestedSamplesTest extends AbstractIntegrationTest {
def util = new AutoTestedSamplesUtil()
@@ -29,7 +26,7 @@ class AbstractAutoTestedSamplesTest extends AbstractIntegrationTest {
def buildFile = testFile('build.gradle')
buildFile.text = sample
- usingBuildFile(buildFile).withQuietLogging().withTasks('help').withArguments("-s").run()
+ usingBuildFile(buildFile).withTasks('help').withArguments("-s").run()
}
}
diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/AbstractCompatibilityTestRunner.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/AbstractCompatibilityTestRunner.java
index bbee5a9..1bcb387 100755
--- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/AbstractCompatibilityTestRunner.java
+++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/AbstractCompatibilityTestRunner.java
@@ -22,8 +22,6 @@ import org.gradle.integtests.fixtures.executer.UnderDevelopmentGradleDistributio
import org.gradle.integtests.fixtures.versions.ReleasedVersionDistributions;
import org.gradle.internal.jvm.Jvm;
import org.gradle.internal.os.OperatingSystem;
-import org.gradle.test.fixtures.file.TestDirectoryProvider;
-import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider;
import org.gradle.util.CollectionUtils;
import org.gradle.util.GradleVersion;
@@ -40,22 +38,18 @@ import static org.gradle.util.CollectionUtils.*;
public abstract class AbstractCompatibilityTestRunner extends AbstractMultiTestRunner {
private static final String VERSIONS_SYSPROP_NAME = "org.gradle.integtest.versions";
- private final TestDirectoryProvider testDirectoryProvider = new TestNameTestDirectoryProvider();
protected final GradleDistribution current = new UnderDevelopmentGradleDistribution();
protected final List<GradleDistribution> previous;
protected AbstractCompatibilityTestRunner(Class<?> target) {
- this(target, null);
+ this(target, System.getProperty(VERSIONS_SYSPROP_NAME, "latest"));
}
- protected AbstractCompatibilityTestRunner(Class<?> target, String versionStr) {
+ private AbstractCompatibilityTestRunner(Class<?> target, String versionStr) {
super(target);
validateTestName(target);
previous = new ArrayList<GradleDistribution>();
- if (versionStr == null) {
- versionStr = System.getProperty(VERSIONS_SYSPROP_NAME, "latest");
- }
final ReleasedVersionDistributions previousVersions = new ReleasedVersionDistributions();
if (versionStr.equals("latest")) {
previous.add(previousVersions.getMostRecentFinalRelease());
@@ -76,11 +70,7 @@ public abstract class AbstractCompatibilityTestRunner extends AbstractMultiTestR
String[] versions = versionStr.split(",");
List<GradleVersion> gradleVersions = CollectionUtils.sort(collect(Arrays.asList(versions), new Transformer<GradleVersion, String>() {
public GradleVersion transform(String versionString) {
- GradleVersion gradleVersion = GradleVersion.version(versionString);
- if (!gradleVersion.isValid()) {
- throw new RuntimeException("Specified Gradle version '" + versionString + "' is not a valid Gradle version");
- }
- return gradleVersion;
+ return GradleVersion.version(versionString);
}
}), Collections.reverseOrder());
@@ -126,7 +116,7 @@ public abstract class AbstractCompatibilityTestRunner extends AbstractMultiTestR
}
@Override
- protected boolean isEnabled() {
+ protected boolean isTestEnabled(TestDetails testDetails) {
return false;
}
diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/AbstractIntegrationSpec.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/AbstractIntegrationSpec.groovy
index 2ee4618..8516c7c 100644
--- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/AbstractIntegrationSpec.groovy
+++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/AbstractIntegrationSpec.groovy
@@ -46,6 +46,11 @@ class AbstractIntegrationSpec extends Specification implements TestDirectoryProv
testDirectory.file('build.gradle')
}
+ protected TestFile buildScript(String script) {
+ buildFile.text = script
+ buildFile
+ }
+
protected TestFile getSettingsFile() {
testDirectory.file('settings.gradle')
}
@@ -127,7 +132,14 @@ class AbstractIntegrationSpec extends Specification implements TestDirectoryProv
assert !skippedTasks.contains(it)
}
}
-
+
+ protected void skipped(String... tasks) {
+ tasks.each {
+ assert it in executedTasks
+ assert skippedTasks.contains(it)
+ }
+ }
+
protected void failureHasCause(String cause) {
failure.assertHasCause(cause)
}
diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/AbstractMultiTestRunner.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/AbstractMultiTestRunner.java
index d02941f..275c627 100755
--- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/AbstractMultiTestRunner.java
+++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/AbstractMultiTestRunner.java
@@ -15,11 +15,14 @@
*/
package org.gradle.integtests.fixtures;
-import org.junit.internal.runners.ErrorReportingRunner;
+import org.gradle.api.Nullable;
+import org.gradle.internal.UncheckedException;
import org.junit.runner.Description;
import org.junit.runner.RunWith;
import org.junit.runner.Runner;
-import org.junit.runner.manipulation.*;
+import org.junit.runner.manipulation.Filter;
+import org.junit.runner.manipulation.Filterable;
+import org.junit.runner.manipulation.NoTestsRemainException;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunListener;
import org.junit.runner.notification.RunNotifier;
@@ -28,15 +31,18 @@ import org.junit.runners.Suite;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.RunnerBuilder;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
import java.util.*;
/**
* A base class for those test runners which execute a test multiple times.
*/
-public abstract class AbstractMultiTestRunner extends Runner implements Filterable, Sortable {
+public abstract class AbstractMultiTestRunner extends Runner implements Filterable {
protected final Class<?> target;
- private Description description;
private final List<Execution> executions = new ArrayList<Execution>();
+ private Description description;
+ private Description templateDescription;
protected AbstractMultiTestRunner(Class<?> target) {
this.target = target;
@@ -64,19 +70,17 @@ public abstract class AbstractMultiTestRunner extends Runner implements Filterab
invalidateDescription();
}
- public void sort(Sorter sorter) {
- initExecutions();
- for (Execution execution : executions) {
- execution.sort(sorter);
- }
- invalidateDescription();
- }
-
private void initExecutions() {
if (executions.isEmpty()) {
+ try {
+ Runner runner = createRunnerFor(Arrays.asList(target));
+ templateDescription = runner.getDescription();
+ } catch (InitializationError initializationError) {
+ throw UncheckedException.throwAsUncheckedException(initializationError);
+ }
createExecutions();
for (Execution execution : executions) {
- execution.init(target);
+ execution.init(target, templateDescription);
}
}
}
@@ -93,6 +97,7 @@ public abstract class AbstractMultiTestRunner extends Runner implements Filterab
private void invalidateDescription() {
description = null;
+ templateDescription = null;
}
protected abstract void createExecutions();
@@ -101,106 +106,107 @@ public abstract class AbstractMultiTestRunner extends Runner implements Filterab
executions.add(execution);
}
- protected static abstract class Execution implements Sortable, Filterable {
- private Runner runner;
- protected Class<?> target;
- private final Map<Description, Description> descriptionTranslations = new HashMap<Description, Description>();
-
- final void init(Class<?> target) {
- this.target = target;
- if (isEnabled()) {
- List<? extends Class<?>> targetClasses = loadTargetClasses();
- RunnerBuilder runnerBuilder = new RunnerBuilder() {
- @Override
- public Runner runnerForClass(Class<?> testClass) {
+ private static Runner createRunnerFor(List<? extends Class<?>> targetClasses) throws InitializationError {
+ RunnerBuilder runnerBuilder = new RunnerBuilder() {
+ @Override
+ public Runner runnerForClass(Class<?> testClass) throws Throwable {
+ for (Class<?> candidate = testClass; candidate != null; candidate = candidate.getSuperclass()) {
+ RunWith runWith = candidate.getAnnotation(RunWith.class);
+ if (runWith != null && !AbstractMultiTestRunner.class.isAssignableFrom(runWith.value())) {
try {
- for (Class<?> candidate = testClass; candidate != null; candidate = candidate.getSuperclass()) {
- RunWith runWith = candidate.getAnnotation(RunWith.class);
- if (runWith != null && !AbstractMultiTestRunner.class.isAssignableFrom(runWith.value())) {
- try {
- return (Runner)runWith.value().getConstructors()[0].newInstance(testClass);
- } catch (Exception e) {
- return new ErrorReportingRunner(testClass, e);
- }
- }
- }
- return new BlockJUnit4ClassRunner(testClass);
- } catch (InitializationError initializationError) {
- return new ErrorReportingRunner(testClass, initializationError);
+ return (Runner)runWith.value().getConstructors()[0].newInstance(testClass);
+ } catch (InvocationTargetException e) {
+ throw e.getTargetException();
}
}
- };
- try {
- runner = new Suite(runnerBuilder, targetClasses.toArray(new Class<?>[targetClasses.size()]));
- } catch (InitializationError initializationError) {
- runner = new ErrorReportingRunner(target, initializationError);
}
+ return new BlockJUnit4ClassRunner(testClass);
}
+ };
+ return new Suite(runnerBuilder, targetClasses.toArray(new Class<?>[targetClasses.size()]));
+ }
+
+ protected static abstract class Execution implements Filterable {
+ protected Class<?> target;
+ private Description templateDescription;
+ private final Map<Description, Description> descriptionTranslations = new HashMap<Description, Description>();
+ private final Set<Description> enabledTests = new LinkedHashSet<Description>();
+ private final Set<Description> disabledTests = new LinkedHashSet<Description>();
+
+ final void init(Class<?> target, Description templateDescription) {
+ this.target = target;
+ this.templateDescription = templateDescription;
+ }
+
+ private Runner createExecutionRunner() throws InitializationError {
+ List<? extends Class<?>> targetClasses = loadTargetClasses();
+ return createRunnerFor(targetClasses);
}
final void addDescriptions(Description parent) {
- if (runner != null) {
- map(runner.getDescription(), parent);
- }
+ map(templateDescription, parent);
}
final void run(final RunNotifier notifier) {
- if (runner == null) {
- Description description = Description.createSuiteDescription(String.format("%s(%s)", getDisplayName(), target.getName()));
- notifier.fireTestIgnored(description);
- return;
- }
-
RunNotifier nested = new RunNotifier();
- nested.addListener(new RunListener() {
- @Override
- public void testStarted(Description description) {
- Description translated = descriptionTranslations.get(description);
- notifier.fireTestStarted(translated);
- }
+ NestedRunListener nestedListener = new NestedRunListener(notifier);
+ nested.addListener(nestedListener);
- @Override
- public void testFailure(Failure failure) {
- Description translated = descriptionTranslations.get(failure.getDescription());
- notifier.fireTestFailure(new Failure(translated, failure.getException()));
- }
+ try {
+ runEnabledTests(nested);
+ } finally {
+ nestedListener.cleanup();
+ }
- @Override
- public void testAssumptionFailure(Failure failure) {
- Description translated = descriptionTranslations.get(failure.getDescription());
- notifier.fireTestAssumptionFailed(new Failure(translated, failure.getException()));
- }
+ for (Description disabledTest : disabledTests) {
+ nested.fireTestStarted(disabledTest);
+ nested.fireTestIgnored(disabledTest);
+ }
+ }
- @Override
- public void testIgnored(Description description) {
- Description translated = descriptionTranslations.get(description);
- notifier.fireTestIgnored(translated);
- }
+ private void runEnabledTests(RunNotifier nested) {
+ if (enabledTests.isEmpty()) {
+ return;
+ }
- @Override
- public void testFinished(Description description) {
- Description translated = descriptionTranslations.get(description);
- notifier.fireTestFinished(translated);
- }
- });
+ Runner runner;
+ try {
+ runner = createExecutionRunner();
+ } catch (Throwable t) {
+ runner = new CannotExecuteRunner(getDisplayName(), target, t);
+ }
- before();
try {
- runner.run(nested);
- } finally {
- after();
+ if (!disabledTests.isEmpty()) {
+ ((Filterable) runner).filter(new Filter() {
+ @Override
+ public boolean shouldRun(Description description) {
+ return !disabledTests.contains(description);
+ }
+
+ @Override
+ public String describe() {
+ return "disabled tests";
+ }
+ });
+ }
+ } catch (NoTestsRemainException e) {
+ return;
}
+
+ runner.run(nested);
}
- public void filter(Filter filter) throws NoTestsRemainException {
- if (runner instanceof Filterable) {
- ((Filterable) runner).filter(filter);
- }
+ private Description translateDescription(Description description) {
+ return descriptionTranslations.containsKey(description) ? descriptionTranslations.get(description) : description;
}
- public void sort(Sorter sorter) {
- if (runner instanceof Sortable) {
- ((Sortable) runner).sort(sorter);
+ public void filter(Filter filter) throws NoTestsRemainException {
+ for (Map.Entry<Description, Description> entry : descriptionTranslations.entrySet()) {
+ if (!filter.shouldRun(entry.getKey())) {
+ enabledTests.remove(entry.getValue());
+ disabledTests.remove(entry.getValue());
+ }
}
}
@@ -213,9 +219,14 @@ public abstract class AbstractMultiTestRunner extends Runner implements Filterab
private void map(Description source, Description parent) {
for (Description child : source.getChildren()) {
Description mappedChild;
- if (child.getMethodName()!= null) {
+ if (child.getMethodName() != null) {
mappedChild = Description.createSuiteDescription(String.format("%s [%s](%s)", child.getMethodName(), getDisplayName(), child.getClassName()));
parent.addChild(mappedChild);
+ if (!isTestEnabled(new TestDescriptionBackedTestDetails(source, child))) {
+ disabledTests.add(child);
+ } else {
+ enabledTests.add(child);
+ }
} else {
mappedChild = Description.createSuiteDescription(child.getClassName());
}
@@ -230,17 +241,134 @@ public abstract class AbstractMultiTestRunner extends Runner implements Filterab
protected abstract String getDisplayName();
/**
- * Returns true if this execution should be executed, false if it should be ignored. Default is true.
+ * Returns true if the given test should be executed, false if it should be ignored. Default is true.
*/
- protected boolean isEnabled() {
+ protected boolean isTestEnabled(TestDetails testDetails) {
return true;
}
/**
+ * Checks that this execution can be executed, throwing an exception if not.
+ */
+ protected void assertCanExecute() {
+ }
+
+ /**
* Loads the target classes for this execution. Default is the target class that this runner was constructed with.
*/
protected List<? extends Class<?>> loadTargetClasses() {
return Collections.singletonList(target);
}
+
+ private static class CannotExecuteRunner extends Runner {
+ private final Description description;
+ private final Throwable failure;
+
+ public CannotExecuteRunner(String displayName, Class<?> testClass, Throwable failure) {
+ description = Description.createSuiteDescription(String.format("%s(%s)", displayName, testClass.getName()));
+ this.failure = failure;
+ }
+
+ @Override
+ public Description getDescription() {
+ return description;
+ }
+
+ @Override
+ public void run(RunNotifier notifier) {
+ Description description = getDescription();
+ notifier.fireTestStarted(description);
+ notifier.fireTestFailure(new Failure(description, failure));
+ notifier.fireTestFinished(description);
+ }
+ }
+
+ private class NestedRunListener extends RunListener {
+ private final RunNotifier notifier;
+ boolean started;
+ boolean complete;
+
+ public NestedRunListener(RunNotifier notifier) {
+ this.notifier = notifier;
+ }
+
+ @Override
+ public void testStarted(Description description) {
+ Description translated = translateDescription(description);
+ notifier.fireTestStarted(translated);
+ if (!started && !complete) {
+ try {
+ assertCanExecute();
+ started = true;
+ before();
+ } catch (Throwable t) {
+ notifier.fireTestFailure(new Failure(translated, t));
+ }
+ }
+ }
+
+ @Override
+ public void testFailure(Failure failure) {
+ Description translated = translateDescription(failure.getDescription());
+ notifier.fireTestFailure(new Failure(translated, failure.getException()));
+ }
+
+ @Override
+ public void testAssumptionFailure(Failure failure) {
+ Description translated = translateDescription(failure.getDescription());
+ notifier.fireTestAssumptionFailed(new Failure(translated, failure.getException()));
+ }
+
+ @Override
+ public void testIgnored(Description description) {
+ Description translated = translateDescription(description);
+ notifier.fireTestIgnored(translated);
+ }
+
+ @Override
+ public void testFinished(Description description) {
+ Description translated = translateDescription(description);
+ notifier.fireTestFinished(translated);
+ }
+
+ public void cleanup() {
+ if (started) {
+ after();
+ }
+ // Prevent further tests (ignored) from triggering start actions
+ complete = true;
+ }
+ }
+ }
+
+ public interface TestDetails {
+ /**
+ * Locates the given annotation for the test. May be inherited from test class.
+ */
+ @Nullable
+ <A extends Annotation> A getAnnotation(Class<A> type);
+ }
+
+ private static class TestDescriptionBackedTestDetails implements TestDetails {
+ private final Description parent;
+ private final Description test;
+
+ private TestDescriptionBackedTestDetails(Description parent, Description test) {
+ this.parent = parent;
+ this.test = test;
+ }
+
+ @Override
+ public String toString() {
+ return test.toString();
+ }
+
+ public <A extends Annotation> A getAnnotation(Class<A> type) {
+ A annotation = test.getAnnotation(type);
+ if (annotation != null) {
+ return annotation;
+ }
+ return parent.getAnnotation(type);
+ }
}
}
diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/AutoTestedSamplesUtil.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/AutoTestedSamplesUtil.groovy
index 7edd8fb..3f8e99e 100644
--- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/AutoTestedSamplesUtil.groovy
+++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/AutoTestedSamplesUtil.groovy
@@ -18,9 +18,6 @@ package org.gradle.integtests.fixtures
import org.gradle.internal.SystemProperties
-/**
- * @author: Szczepan Faber, created at: 3/28/11
- */
class AutoTestedSamplesUtil {
String includes = '**/*.groovy **/*.java'
diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/AvailableJavaHomes.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/AvailableJavaHomes.java
index 8d0308f..f72b871 100755
--- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/AvailableJavaHomes.java
+++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/AvailableJavaHomes.java
@@ -15,12 +15,14 @@
*/
package org.gradle.integtests.fixtures;
+import org.gradle.internal.jvm.Jre;
import org.gradle.internal.jvm.Jvm;
import org.gradle.internal.os.OperatingSystem;
import org.gradle.util.GFileUtils;
import java.io.File;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
/**
@@ -51,12 +53,15 @@ abstract public class AvailableJavaHomes {
}
if (OperatingSystem.current().isMacOsX()) {
- File registeredJvms = new File("/Library/Java/JavaVirtualMachines");
- if (registeredJvms.isDirectory()) {
- for (File candidate : registeredJvms.listFiles()) {
- javaHome = GFileUtils.canonicalise(new File(candidate, "Contents/Home"));
- if (!javaHome.equals(jvm.getJavaHome()) && javaHome.isDirectory() && new File(javaHome, "bin/java").isFile()) {
- return javaHome;
+ // Search in the install dir used by the Apple jvms, followed by the install dir used by the OpenJDK jvms
+ List<File> installDirs = Arrays.asList(new File("/System/Library/Java/JavaVirtualMachines"), new File("/Library/Java/JavaVirtualMachines"));
+ for (File installDir : installDirs) {
+ if (installDir.isDirectory()) {
+ for (File candidate : installDir.listFiles()) {
+ javaHome = GFileUtils.canonicalise(new File(candidate, "Contents/Home"));
+ if (!javaHome.equals(jvm.getJavaHome()) && javaHome.isDirectory() && new File(javaHome, "bin/java").isFile()) {
+ return javaHome;
+ }
}
}
}
@@ -105,25 +110,13 @@ abstract public class AvailableJavaHomes {
*/
public static File getBestJre() {
Jvm jvm = Jvm.current();
- File jreHome;
-
- if (OperatingSystem.current().isWindows()) {
- if (jvm.getJavaVersion().isJava6()) {
- jreHome = new File(jvm.getJavaHome().getParentFile(), "jre6");
- if (jreHome.isDirectory() && new File(jreHome, "bin/java.exe").isFile()) {
- return jreHome;
- }
- }
- if (jvm.getJavaVersion().isJava7()) {
- jreHome = new File(jvm.getJavaHome().getParentFile(), "jre7");
- if (jreHome.isDirectory() && new File(jreHome, "bin/java.exe").isFile()) {
- return jreHome;
- }
- }
+ Jre jre = jvm.getStandaloneJre();
+ if (jre != null) {
+ return jre.getHomeDir();
}
- jreHome = new File(jvm.getJavaHome(), "jre");
- if (jreHome.isDirectory()) {
- return jreHome;
+ jre = jvm.getJre();
+ if (jre != null) {
+ return jre.getHomeDir();
}
return null;
}
diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/CrossVersionTestRunner.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/CrossVersionTestRunner.groovy
index 1839598..c267285 100755
--- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/CrossVersionTestRunner.groovy
+++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/CrossVersionTestRunner.groovy
@@ -91,7 +91,7 @@ class CrossVersionTestRunner extends AbstractCompatibilityTestRunner {
}
@Override
- protected boolean isEnabled() {
+ protected boolean isTestEnabled(AbstractMultiTestRunner.TestDetails testDetails) {
return enabled
}
}
diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/IntegrationTestHint.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/IntegrationTestHint.java
index 8ce0ca2..9b9abfb 100644
--- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/IntegrationTestHint.java
+++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/IntegrationTestHint.java
@@ -16,9 +16,6 @@
package org.gradle.integtests.fixtures;
-/**
- * @author Szczepan Faber, @date: 25.03.11
- */
public class IntegrationTestHint extends RuntimeException {
public IntegrationTestHint(Throwable cause) {
diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/KillProcessAvailability.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/KillProcessAvailability.groovy
index 1a2fb0f..87c9759 100644
--- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/KillProcessAvailability.groovy
+++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/KillProcessAvailability.groovy
@@ -19,9 +19,6 @@ package org.gradle.integtests.fixtures
import org.gradle.internal.os.OperatingSystem
import org.gradle.process.internal.ExecHandleBuilder
-/**
- * by Szczepan Faber, created at: 9/24/12
- */
class KillProcessAvailability {
final static CAN_KILL
diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/TestNGExecutionResult.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/TestNGExecutionResult.groovy
index 0772dca..cbb9ef2 100644
--- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/TestNGExecutionResult.groovy
+++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/TestNGExecutionResult.groovy
@@ -20,9 +20,6 @@ import groovy.util.slurpersupport.GPathResult
import org.gradle.test.fixtures.file.TestFile
import org.hamcrest.Matcher
-/**
- * by Szczepan Faber, created at: 11/3/11
- */
class TestNGExecutionResult implements TestExecutionResult {
private final TestFile projectDir
private GPathResult resultsXml
@@ -139,10 +136,18 @@ private class TestNgTestClassExecutionResult implements TestClassExecutionResult
throw new UnsupportedOperationException();
}
+ TestClassExecutionResult assertTestCaseStdout(String testCaseName, Matcher<? super String> matcher) {
+ throw new UnsupportedOperationException();
+ }
+
TestClassExecutionResult assertStderr(Matcher<? super String> matcher) {
throw new UnsupportedOperationException();
}
+ TestClassExecutionResult assertTestCaseStderr(String testCaseName, Matcher<? super String> matcher) {
+ throw new UnsupportedOperationException();
+ }
+
TestClassExecutionResult assertConfigMethodPassed(String name) {
def testMethodNode = findConfigMethod(name)
org.junit.Assert.assertEquals('PASS', testMethodNode. at status as String)
diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/UserGuideSamplesRunner.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/UserGuideSamplesRunner.groovy
index c7fe692..793771c 100644
--- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/UserGuideSamplesRunner.groovy
+++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/UserGuideSamplesRunner.groovy
@@ -99,6 +99,9 @@ class UserGuideSamplesRunner extends Runner {
try {
cleanup(sampleRun)
for (run in sampleRun.runs) {
+ if (run.brokenForParallel && GradleContextualExecuter.parallel) {
+ continue
+ }
runSample(run)
}
} catch (Throwable t) {
@@ -130,7 +133,7 @@ class UserGuideSamplesRunner extends Runner {
def expectedResult = replaceWithPlatformNewLines(buildContext.userGuideOutputDir.file(run.outputFile).text)
expectedResult = replaceWithRealSamplesDir(expectedResult)
try {
- result.assertOutputEquals(expectedResult, run.ignoreExtraLines)
+ result.assertOutputEquals(expectedResult, run.ignoreExtraLines, run.ignoreLineOrder)
} catch (AssertionError e) {
println 'Expected Result:'
println expectedResult
@@ -184,12 +187,14 @@ class UserGuideSamplesRunner extends Runner {
def args = sample.'@args'
def outputFile = sample.'@outputFile'
boolean ignoreExtraLines = Boolean.valueOf(sample.'@ignoreExtraLines')
+ boolean ignoreLineOrder = Boolean.valueOf(sample.'@ignoreLineOrder')
def run = new GradleRun(id: id)
run.subDir = dir
run.args = args ? args.split('\\s+') as List : []
run.outputFile = outputFile
run.ignoreExtraLines = ignoreExtraLines as boolean
+ run.ignoreLineOrder = ignoreLineOrder as boolean
sample.file.each { file -> run.files << file.'@path' }
sample.dir.each { file -> run.dirs << file.'@path' }
@@ -201,6 +206,9 @@ class UserGuideSamplesRunner extends Runner {
samplesByDir.get('userguide/tutorial/properties').each { it.envs['ORG_GRADLE_PROJECT_envProjectProp'] = 'envPropertyValue' }
samplesByDir.get('userguide/buildlifecycle/taskExecutionEvents')*.expectFailure = true
samplesByDir.get('userguide/buildlifecycle/buildProjectEvaluateEvents')*.expectFailure = true
+ samplesByDir.get('userguide/tasks/finalizersWithFailure')*.expectFailure = true
+ samplesByDir.get('userguide/multiproject/dependencies/firstMessages/messages')*.brokenForParallel = true
+ samplesByDir.get('userguide/multiproject/dependencies/messagesHack/messages')*.brokenForParallel = true
Map<String, SampleRun> samplesById = new TreeMap<String, SampleRun>()
@@ -241,6 +249,8 @@ Please run 'gradle docs:userguideDocbook' first"""
String outputFile
boolean expectFailure
boolean ignoreExtraLines
+ boolean ignoreLineOrder
+ boolean brokenForParallel
List files = []
List dirs = []
diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/AnyOrderOutputMatcher.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/AnyOrderOutputMatcher.groovy
new file mode 100644
index 0000000..d5a710f
--- /dev/null
+++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/AnyOrderOutputMatcher.groovy
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests.fixtures.executer
+
+import org.junit.Assert
+import org.gradle.internal.SystemProperties
+
+/**
+ * Checks that all lines contained in the expected output are present in the actual output, in any order.
+ */
+class AnyOrderOutputMatcher extends SequentialOutputMatcher {
+ private static final String NL = SystemProperties.lineSeparator
+
+ protected void assertOutputLinesMatch(List<String> expectedLines, List<String> actualLines, boolean ignoreExtraLines, String actual) {
+ List<String> unmatchedLines = new ArrayList<String>(actualLines)
+ expectedLines.removeAll('')
+ unmatchedLines.removeAll('')
+
+ expectedLines.each { expectedLine ->
+ def matchedLine = unmatchedLines.find { actualLine ->
+ compare(expectedLine, actualLine)
+ }
+ if (matchedLine) {
+ unmatchedLines.remove(matchedLine)
+ } else {
+ Assert.fail("Line missing from output.${NL}${expectedLine}${NL}---${NL}Actual output:${NL}$actual${NL}---")
+ }
+ }
+
+ if (!(ignoreExtraLines || unmatchedLines.empty)) {
+ def unmatched = unmatchedLines.join(NL)
+ Assert.fail("Extra lines in output.${NL}${unmatched}${NL}---${NL}Actual output:${NL}$actual${NL}---")
+ }
+ }
+}
diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/DefaultGradleDistribution.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/DefaultGradleDistribution.java
index 61b9de6..52ee5f2 100644
--- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/DefaultGradleDistribution.java
+++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/DefaultGradleDistribution.java
@@ -34,6 +34,11 @@ public class DefaultGradleDistribution implements GradleDistribution {
this.binDistribution = binDistribution;
}
+ @Override
+ public String toString() {
+ return version.toString();
+ }
+
public TestFile getGradleHomeDir() {
return gradleHomeDir;
}
@@ -52,11 +57,11 @@ public class DefaultGradleDistribution implements GradleDistribution {
public boolean worksWith(Jvm jvm) {
// Milestone 4 was broken on the IBM jvm
- if (jvm.isIbmJvm() && version == GradleVersion.version("1.0-milestone-4")) {
+ if (jvm.isIbmJvm() && isVersion("1.0-milestone-4")) {
return false;
}
// 0.9-rc-1 was broken for Java 5
- if (version == GradleVersion.version("0.9-rc-1")) {
+ if (isVersion("0.9-rc-1")) {
return jvm.getJavaVersion().isJava6Compatible();
}
@@ -66,7 +71,7 @@ public class DefaultGradleDistribution implements GradleDistribution {
public boolean worksWith(OperatingSystem os) {
// 1.0-milestone-5 was broken where jna was not available
//noinspection SimplifiableIfStatement
- if (version == GradleVersion.version("1.0-milestone-5")) {
+ if (isVersion("1.0-milestone-5")) {
return os.isWindows() || os.isMacOsX() || os.isLinux();
} else {
return true;
@@ -75,7 +80,7 @@ public class DefaultGradleDistribution implements GradleDistribution {
public boolean isDaemonSupported() {
// Milestone 7 was broken on the IBM jvm
- if (Jvm.current().isIbmJvm() && version == GradleVersion.version("1.0-milestone-7")) {
+ if (Jvm.current().isIbmJvm() && isVersion("1.0-milestone-7")) {
return false;
}
@@ -100,8 +105,19 @@ public class DefaultGradleDistribution implements GradleDistribution {
return isSameOrNewer("1.0-milestone-3");
}
+ public boolean isToolingApiNonAsciiOutputSupported() {
+ if (OperatingSystem.current().isWindows()) {
+ return !isVersion("1.0-milestone-7") && !isVersion("1.0-milestone-8") && !isVersion("1.0-milestone-8a");
+ }
+ return true;
+ }
+
public int getArtifactCacheLayoutVersion() {
- if (isSameOrNewer("1.4-rc-1")) {
+ if (isSameOrNewer("1.7-rc-1")) {
+ return 26;
+ } else if (isSameOrNewer("1.6-rc-1")) {
+ return 24;
+ } else if (isSameOrNewer("1.4-rc-1")) {
return 23;
} else if (isSameOrNewer("1.3")) {
return 15;
@@ -146,7 +162,7 @@ public class DefaultGradleDistribution implements GradleDistribution {
protected boolean isVersion(String otherVersionString) {
GradleVersion otherVersion = GradleVersion.version(otherVersionString);
- return version.compareTo(otherVersion) == 0 || (version.isSnapshot() && version.getVersionBase().equals(otherVersion.getVersionBase()));
+ return version.compareTo(otherVersion) == 0 || (version.isSnapshot() && version.getBaseVersion().equals(otherVersion.getBaseVersion()));
}
}
diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/DependencyResolutionFailure.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/DependencyResolutionFailure.groovy
index 8962401..305b553 100644
--- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/DependencyResolutionFailure.groovy
+++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/DependencyResolutionFailure.groovy
@@ -19,9 +19,6 @@ package org.gradle.integtests.fixtures.executer
import static org.gradle.util.Matchers.*;
import org.hamcrest.Matcher
-/**
- * by Szczepan Faber, created at: 12/12/12
- */
public class DependencyResolutionFailure {
private final ExecutionFailure failure
diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/DetailedExecutionFailure.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/DetailedExecutionFailure.groovy
index af93967..29f8295 100644
--- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/DetailedExecutionFailure.groovy
+++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/DetailedExecutionFailure.groovy
@@ -18,9 +18,6 @@ package org.gradle.integtests.fixtures.executer
import static org.hamcrest.Matchers.startsWith
-/**
- * by Szczepan Faber, created at: 11/26/12
- */
class DetailedExecutionFailure {
ExecutionFailure failure
@@ -31,6 +28,6 @@ class DetailedExecutionFailure {
public assertTestsFailed() {
failure
.assertHasDescription("Execution failed for task ':test'.")
- .assertThatCause(startsWith("There were failing tests."));
+ .assertThatCause(startsWith("There were failing tests"));
}
}
diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/DownloadableGradleDistribution.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/DownloadableGradleDistribution.groovy
index 5000654..a8c4f08 100644
--- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/DownloadableGradleDistribution.groovy
+++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/DownloadableGradleDistribution.groovy
@@ -20,6 +20,7 @@ import org.gradle.CacheUsage
import org.gradle.api.Action
import org.gradle.cache.PersistentCache
import org.gradle.cache.internal.*
+import org.gradle.cache.internal.locklistener.NoOpFileLockContentionHandler
import org.gradle.internal.nativeplatform.services.NativeServices
import org.gradle.test.fixtures.file.TestFile
import org.gradle.util.GradleVersion
@@ -34,7 +35,7 @@ abstract class DownloadableGradleDistribution extends DefaultGradleDistribution
new DefaultProcessMetaDataProvider(
NativeServices.getInstance().get(org.gradle.internal.nativeplatform.ProcessEnvironment)),
20 * 60 * 1000 // allow up to 20 minutes to download a distribution
- )).create()
+ , new NoOpFileLockContentionHandler() )).create()
}
protected TestFile versionDir
diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/ExecutionResult.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/ExecutionResult.java
index 828d3ab..91aaf92 100644
--- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/ExecutionResult.java
+++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/ExecutionResult.java
@@ -23,7 +23,7 @@ public interface ExecutionResult {
String getError();
- ExecutionResult assertOutputEquals(String expectedOutput, boolean ignoreExtraLines);
+ ExecutionResult assertOutputEquals(String expectedOutput, boolean ignoreExtraLines, boolean ignoreLineOrder);
/**
* Returns the tasks have been executed in order (includes tasks that were skipped). Note: ignores buildSrc tasks.
diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/GradleDistribution.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/GradleDistribution.java
index 263aaae..15da8e5 100644
--- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/GradleDistribution.java
+++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/GradleDistribution.java
@@ -68,6 +68,11 @@ public interface GradleDistribution {
boolean isToolingApiSupported();
/**
+ * Returns true if the tooling API provider of this distribution correctly handles non-ASCII characters in logging output.
+ */
+ boolean isToolingApiNonAsciiOutputSupported();
+
+ /**
* Returns the version of the artifact cache layout
*/
int getArtifactCacheLayoutVersion();
diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/InProcessGradleExecuter.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/InProcessGradleExecuter.java
index 28a8100..caf3579 100755
--- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/InProcessGradleExecuter.java
+++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/InProcessGradleExecuter.java
@@ -16,7 +16,6 @@
package org.gradle.integtests.fixtures.executer;
-import org.gradle.BuildListener;
import org.gradle.BuildResult;
import org.gradle.GradleLauncher;
import org.gradle.StartParameter;
@@ -25,17 +24,15 @@ import org.gradle.api.Task;
import org.gradle.api.execution.TaskExecutionGraph;
import org.gradle.api.execution.TaskExecutionGraphListener;
import org.gradle.api.execution.TaskExecutionListener;
-import org.gradle.api.initialization.Settings;
import org.gradle.api.internal.LocationAwareException;
import org.gradle.api.internal.classpath.DefaultModuleRegistry;
import org.gradle.api.internal.file.IdentityFileResolver;
-import org.gradle.api.invocation.Gradle;
-import org.gradle.api.logging.LogLevel;
import org.gradle.api.logging.StandardOutputListener;
import org.gradle.api.tasks.TaskState;
import org.gradle.cli.CommandLineParser;
import org.gradle.cli.ParsedCommandLine;
import org.gradle.execution.MultipleBuildFailures;
+import org.gradle.initialization.BuildLayoutParameters;
import org.gradle.initialization.DefaultCommandLineConverter;
import org.gradle.initialization.DefaultGradleLauncherFactory;
import org.gradle.internal.Factory;
@@ -43,8 +40,10 @@ import org.gradle.internal.jvm.Jvm;
import org.gradle.internal.nativeplatform.ProcessEnvironment;
import org.gradle.internal.nativeplatform.services.NativeServices;
import org.gradle.launcher.Main;
-import org.gradle.launcher.daemon.configuration.GradlePropertiesConfigurer;
+import org.gradle.launcher.cli.converter.LayoutToPropertiesConverter;
+import org.gradle.launcher.cli.converter.PropertiesToStartParameterConverter;
import org.gradle.launcher.daemon.registry.DaemonRegistry;
+import org.gradle.logging.ShowStacktrace;
import org.gradle.process.internal.JavaExecHandleBuilder;
import org.gradle.test.fixtures.file.TestDirectoryProvider;
import org.gradle.util.DeprecationLogger;
@@ -58,8 +57,10 @@ import java.nio.charset.Charset;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.regex.Pattern;
-import static org.gradle.util.Matchers.*;
+import static org.gradle.util.Matchers.hasMessage;
+import static org.gradle.util.Matchers.isEmpty;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
@@ -89,7 +90,7 @@ class InProcessGradleExecuter extends AbstractGradleExecuter {
throw new UnexpectedBuildFailure(e);
}
return assertResult(new InProcessExecutionResult(buildListener.executedTasks, buildListener.skippedTasks,
- outputListener.toString(), errorListener.toString()));
+ new OutputScrapingExecutionResult(outputListener.toString(), errorListener.toString())));
}
@Override
@@ -102,7 +103,7 @@ class InProcessGradleExecuter extends AbstractGradleExecuter {
throw new AssertionError("expected build to fail but it did not.");
} catch (GradleException e) {
return assertResult(new InProcessExecutionFailure(buildListener.executedTasks, buildListener.skippedTasks,
- outputListener.writer.toString(), errorListener.writer.toString(), e));
+ new OutputScrapingExecutionFailure(outputListener.writer.toString(), errorListener.writer.toString()), e));
}
}
@@ -144,22 +145,30 @@ class InProcessGradleExecuter extends AbstractGradleExecuter {
System.getProperties().putAll(implicitJvmSystemProperties);
StartParameter parameter = new StartParameter();
- parameter.setLogLevel(LogLevel.INFO);
- parameter.setSearchUpwards(true);
parameter.setCurrentDir(getWorkingDir());
+ parameter.setShowStacktrace(ShowStacktrace.ALWAYS);
CommandLineParser parser = new CommandLineParser();
DefaultCommandLineConverter converter = new DefaultCommandLineConverter();
converter.configure(parser);
ParsedCommandLine parsedCommandLine = parser.parse(getAllArgs());
- converter.convert(parsedCommandLine, parameter);
- //I'm not sure if below is safe
- new GradlePropertiesConfigurer().configureStartParameter(parameter);
+ BuildLayoutParameters layout = converter.getLayoutConverter().convert(parsedCommandLine);
+
+ Map<String, String> properties = new HashMap<String, String>();
+ new LayoutToPropertiesConverter().convert(layout, properties);
+ converter.getSystemPropertiesConverter().convert(parsedCommandLine, properties);
+
+ new PropertiesToStartParameterConverter().convert(properties, parameter);
+ converter.convert(parsedCommandLine, parameter);
- DefaultGradleLauncherFactory factory = (DefaultGradleLauncherFactory) GradleLauncher.getFactory();
+ DefaultGradleLauncherFactory factory = DeprecationLogger.whileDisabled(new Factory<DefaultGradleLauncherFactory>() {
+ public DefaultGradleLauncherFactory create() {
+ return (DefaultGradleLauncherFactory) GradleLauncher.getFactory();
+ }
+ });
factory.addListener(listener);
- GradleLauncher gradleLauncher = GradleLauncher.newInstance(parameter);
+ GradleLauncher gradleLauncher = factory.newInstance(parameter);
gradleLauncher.addStandardOutputListener(outputListener);
gradleLauncher.addStandardErrorListener(errorListener);
try {
@@ -195,7 +204,7 @@ class InProcessGradleExecuter extends AbstractGradleExecuter {
assertFalse(isRequireGradleHome());
}
- private static class BuildListenerImpl implements TaskExecutionGraphListener, BuildListener {
+ private static class BuildListenerImpl implements TaskExecutionGraphListener {
private final List<String> executedTasks = new CopyOnWriteArrayList<String>();
private final Set<String> skippedTasks = new CopyOnWriteArraySet<String>();
@@ -203,26 +212,6 @@ class InProcessGradleExecuter extends AbstractGradleExecuter {
List<Task> planned = new ArrayList<Task>(graph.getAllTasks());
graph.addTaskExecutionListener(new TaskListenerImpl(planned, executedTasks, skippedTasks));
}
-
- public void buildStarted(Gradle gradle) {
- DeprecationLogger.setLogTrace(true);
- }
-
- public void settingsEvaluated(Settings settings) {
-
- }
-
- public void projectsLoaded(Gradle gradle) {
-
- }
-
- public void projectsEvaluated(Gradle gradle) {
-
- }
-
- public void buildFinished(BuildResult result) {
- DeprecationLogger.setLogTrace(false);
- }
}
private static class OutputListenerImpl implements StandardOutputListener {
@@ -279,28 +268,25 @@ class InProcessGradleExecuter extends AbstractGradleExecuter {
public static class InProcessExecutionResult implements ExecutionResult {
private final List<String> plannedTasks;
private final Set<String> skippedTasks;
- private final String output;
- private final String error;
+ private final OutputScrapingExecutionResult outputResult;
- public InProcessExecutionResult(List<String> plannedTasks, Set<String> skippedTasks, String output,
- String error) {
+ public InProcessExecutionResult(List<String> plannedTasks, Set<String> skippedTasks, OutputScrapingExecutionResult outputResult) {
this.plannedTasks = plannedTasks;
this.skippedTasks = skippedTasks;
- this.output = output;
- this.error = error;
+ this.outputResult = outputResult;
}
public String getOutput() {
- return output;
+ return outputResult.getOutput();
}
- public ExecutionResult assertOutputEquals(String expectedOutput, boolean ignoreExtraLines) {
- new SequentialOutputMatcher().assertOutputMatches(expectedOutput, getOutput(), ignoreExtraLines);
+ public ExecutionResult assertOutputEquals(String expectedOutput, boolean ignoreExtraLines, boolean ignoreLineOrder) {
+ outputResult.assertOutputEquals(expectedOutput, ignoreExtraLines, ignoreLineOrder);
return this;
}
public String getError() {
- return error;
+ return outputResult.getError();
}
public List<String> getExecutedTasks() {
@@ -310,6 +296,7 @@ class InProcessGradleExecuter extends AbstractGradleExecuter {
public ExecutionResult assertTasksExecuted(String... taskPaths) {
List<String> expected = Arrays.asList(taskPaths);
assertThat(plannedTasks, equalTo(expected));
+ outputResult.assertTasksExecuted(taskPaths);
return this;
}
@@ -320,11 +307,13 @@ class InProcessGradleExecuter extends AbstractGradleExecuter {
public ExecutionResult assertTasksSkipped(String... taskPaths) {
Set<String> expected = new HashSet<String>(Arrays.asList(taskPaths));
assertThat(skippedTasks, equalTo(expected));
+ outputResult.assertTasksSkipped(taskPaths);
return this;
}
public ExecutionResult assertTaskSkipped(String taskPath) {
assertThat(skippedTasks, hasItem(taskPath));
+ outputResult.assertTaskSkipped(taskPath);
return this;
}
@@ -332,11 +321,13 @@ class InProcessGradleExecuter extends AbstractGradleExecuter {
Set<String> expected = new HashSet<String>(Arrays.asList(taskPaths));
Set<String> notSkipped = getNotSkippedTasks();
assertThat(notSkipped, equalTo(expected));
+ outputResult.assertTasksNotSkipped(taskPaths);
return this;
}
public ExecutionResult assertTaskNotSkipped(String taskPath) {
assertThat(getNotSkippedTasks(), hasItem(taskPath));
+ outputResult.assertTaskNotSkipped(taskPath);
return this;
}
@@ -348,22 +339,41 @@ class InProcessGradleExecuter extends AbstractGradleExecuter {
}
private static class InProcessExecutionFailure extends InProcessExecutionResult implements ExecutionFailure {
+ private static final Pattern LOCATION_PATTERN = Pattern.compile("(?m)^((\\w+ )+'.+') line: (\\d+)$");
+ private final OutputScrapingExecutionFailure outputFailure;
private final GradleException failure;
+ private final String fileName;
+ private final String lineNumber;
+ private final String description;
- public InProcessExecutionFailure(List<String> tasks, Set<String> skippedTasks, String output, String error,
+ public InProcessExecutionFailure(List<String> tasks, Set<String> skippedTasks, OutputScrapingExecutionFailure outputFailure,
GradleException failure) {
- super(tasks, skippedTasks, output, error);
+ super(tasks, skippedTasks, outputFailure);
+ this.outputFailure = outputFailure;
this.failure = failure;
+
+ // Chop up the exception message into its expected parts
+ java.util.regex.Matcher matcher = LOCATION_PATTERN.matcher(failure.getMessage());
+ if (matcher.find()) {
+ fileName = matcher.group(1);
+ lineNumber = matcher.group(3);
+ description = failure.getMessage().substring(matcher.end()).trim();
+ } else {
+ fileName = "";
+ lineNumber = "";
+ description = failure.getMessage().trim();
+ }
}
public ExecutionFailure assertHasLineNumber(int lineNumber) {
- assertThat(failure.getMessage(), containsString(String.format(" line: %d", lineNumber)));
+ assertThat(this.lineNumber, equalTo(String.valueOf(lineNumber)));
+ outputFailure.assertHasLineNumber(lineNumber);
return this;
-
}
public ExecutionFailure assertHasFileName(String filename) {
- assertThat(failure.getMessage(), startsWith(String.format("%s", filename)));
+ assertThat(this.fileName, equalTo(filename));
+ outputFailure.assertHasFileName(filename);
return this;
}
@@ -376,6 +386,7 @@ class InProcessGradleExecuter extends AbstractGradleExecuter {
List<Throwable> causes = new ArrayList<Throwable>();
extractCauses(failure, causes);
assertThat(causes, Matchers.<Throwable>hasItem(hasMessage(matcher)));
+ outputFailure.assertThatCause(matcher);
return this;
}
@@ -399,16 +410,18 @@ class InProcessGradleExecuter extends AbstractGradleExecuter {
} else {
assertThat(failure.getCause(), nullValue());
}
+ outputFailure.assertHasNoCause();
return this;
}
public ExecutionFailure assertHasDescription(String context) {
- assertThatDescription(startsWith(context));
+ assertThatDescription(equalTo(context));
return this;
}
public ExecutionFailure assertThatDescription(Matcher<String> matcher) {
- assertThat(failure.getMessage(), containsLine(matcher));
+ assertThat(description, matcher);
+ outputFailure.assertThatDescription(matcher);
return this;
}
diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/InitScriptExecuterFixture.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/InitScriptExecuterFixture.groovy
index 4133565..c4b1c73 100644
--- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/InitScriptExecuterFixture.groovy
+++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/InitScriptExecuterFixture.groovy
@@ -16,14 +16,11 @@
package org.gradle.integtests.fixtures.executer
-import org.junit.rules.MethodRule
import org.gradle.test.fixtures.file.TestDirectoryProvider
-import org.junit.runners.model.Statement
+import org.junit.rules.MethodRule
import org.junit.runners.model.FrameworkMethod
+import org.junit.runners.model.Statement
-/**
- * by Szczepan Faber, created at: 2/1/13
- */
abstract class InitScriptExecuterFixture implements MethodRule {
GradleExecuter executer
diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/OutputScrapingExecutionFailure.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/OutputScrapingExecutionFailure.java
index 94963b3..6dec17c 100644
--- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/OutputScrapingExecutionFailure.java
+++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/OutputScrapingExecutionFailure.java
@@ -17,30 +17,71 @@ package org.gradle.integtests.fixtures.executer;
import org.hamcrest.Matcher;
+import java.util.ArrayList;
+import java.util.List;
import java.util.regex.Pattern;
-import static org.hamcrest.Matchers.not;
-import static org.gradle.util.Matchers.containsLine;
-import static org.gradle.util.Matchers.matchesRegexp;
-import static org.hamcrest.Matchers.containsString;
+import static org.gradle.util.Matchers.isEmpty;
+import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.startsWith;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
public class OutputScrapingExecutionFailure extends OutputScrapingExecutionResult implements ExecutionFailure {
- private final Pattern causePattern = Pattern.compile("(?m)\\s*> ");
+ private static final Pattern CAUSE_PATTERN = Pattern.compile("(?m)^\\s*> ");
+ private static final Pattern DESCRIPTION_PATTERN = Pattern.compile("(?ms)^\\* What went wrong:$(.+)^\\* Try:$");
+ private static final Pattern LOCATION_PATTERN = Pattern.compile("(?ms)^\\* Where:((.+)'.+') line: (\\d+)$");
+ private final String description;
+ private final String lineNumber;
+ private final String fileName;
+ private final List<String> causes = new ArrayList<String>();
public OutputScrapingExecutionFailure(String output, String error) {
super(output, error);
+
+ java.util.regex.Matcher matcher = LOCATION_PATTERN.matcher(error);
+ if (matcher.find()) {
+ fileName = matcher.group(1).trim();
+ lineNumber = matcher.group(3);
+ } else {
+ fileName = "";
+ lineNumber = "";
+ }
+
+ matcher = DESCRIPTION_PATTERN.matcher(error);
+ String problem;
+ if (matcher.find()) {
+ problem = matcher.group(1);
+ } else {
+ problem = "";
+ }
+
+ matcher = CAUSE_PATTERN.matcher(problem);
+ if (!matcher.find()) {
+ description = problem.trim();
+ } else {
+ description = problem.substring(0, matcher.start()).trim();
+ while (true) {
+ int pos = matcher.end();
+ if (matcher.find(pos)) {
+ String cause = problem.substring(pos, matcher.start());
+ causes.add(cause);
+ } else {
+ String cause = problem.substring(pos);
+ causes.add(cause);
+ break;
+ }
+ }
+ }
}
public ExecutionFailure assertHasLineNumber(int lineNumber) {
- assertThat(getError(), containsString(String.format(" line: %d", lineNumber)));
+ assertThat(this.lineNumber, equalTo(String.valueOf(lineNumber)));
return this;
}
public ExecutionFailure assertHasFileName(String filename) {
- assertThat(getError(), containsLine(startsWith(filename)));
+ assertThat(this.fileName, equalTo(filename));
return this;
}
@@ -50,42 +91,27 @@ public class OutputScrapingExecutionFailure extends OutputScrapingExecutionResul
}
public ExecutionFailure assertThatCause(Matcher<String> matcher) {
- String error = getError();
- java.util.regex.Matcher regExpMatcher = causePattern.matcher(error);
- int pos = 0;
- while (pos < error.length()) {
- if (!regExpMatcher.find(pos)) {
- break;
- }
- int start = regExpMatcher.end();
- String cause;
- if (regExpMatcher.find(start)) {
- cause = error.substring(start, regExpMatcher.start());
- pos = regExpMatcher.start();
- } else {
- cause = error.substring(start);
- pos = error.length();
- }
+ for (String cause : causes) {
if (matcher.matches(cause)) {
return this;
}
}
- fail(String.format("No matching cause found in '%s'", error));
+ fail(String.format("No matching cause found in %s", causes));
return this;
}
public ExecutionFailure assertHasNoCause() {
- assertThat(getError(), not(matchesRegexp(causePattern)));
+ assertThat(causes, isEmpty());
return this;
}
public ExecutionFailure assertHasDescription(String context) {
- assertThatDescription(startsWith(context));
+ assertThatDescription(equalTo(context));
return this;
}
public ExecutionFailure assertThatDescription(Matcher<String> matcher) {
- assertThat(getError(), containsLine(matcher));
+ assertThat(description, matcher);
return this;
}
diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/OutputScrapingExecutionResult.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/OutputScrapingExecutionResult.java
index ba3bc85..227c153 100644
--- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/OutputScrapingExecutionResult.java
+++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/OutputScrapingExecutionResult.java
@@ -36,7 +36,7 @@ public class OutputScrapingExecutionResult implements ExecutionResult {
private final Pattern skippedTaskPattern = Pattern.compile("(:\\S+?(:\\S+?)*)\\s+((SKIPPED)|(UP-TO-DATE))");
//for example: ':hey' or ':a SKIPPED' or ':foo:bar:baz UP-TO-DATE' but not ':a FOO'
- private final Pattern taskPattern = Pattern.compile("(:\\S+?(:\\S+?)*)((\\s+SKIPPED)|(\\s+UP-TO-DATE)|(\\s*))");
+ private final Pattern taskPattern = Pattern.compile("(:\\S+?(:\\S+?)*)((\\s+SKIPPED)|(\\s+UP-TO-DATE)|(\\s+FAILED)|(\\s*))");
public OutputScrapingExecutionResult(String output, String error) {
this.output = output;
@@ -47,8 +47,9 @@ public class OutputScrapingExecutionResult implements ExecutionResult {
return output;
}
- public ExecutionResult assertOutputEquals(String expectedOutput, boolean ignoreExtraLines) {
- new SequentialOutputMatcher().assertOutputMatches(expectedOutput, getOutput(), ignoreExtraLines);
+ public ExecutionResult assertOutputEquals(String expectedOutput, boolean ignoreExtraLines, boolean ignoreLineOrder) {
+ SequentialOutputMatcher matcher = ignoreLineOrder ? new AnyOrderOutputMatcher() : new SequentialOutputMatcher();
+ matcher.assertOutputMatches(expectedOutput, getOutput(), ignoreExtraLines);
return this;
}
diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/ParallelForkingGradleHandle.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/ParallelForkingGradleHandle.java
index e233b2b..fecee7f 100644
--- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/ParallelForkingGradleHandle.java
+++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/ParallelForkingGradleHandle.java
@@ -68,8 +68,9 @@ public class ParallelForkingGradleHandle extends ForkingGradleHandle {
}
@Override
- public ExecutionResult assertOutputEquals(String expectedOutput, boolean ignoreExtraLines) {
- new ParallelOutputMatcher().assertOutputMatches(expectedOutput, getOutput(), ignoreExtraLines);
+ public ExecutionResult assertOutputEquals(String expectedOutput, boolean ignoreExtraLines, boolean ignoreLineOrder) {
+ // We always ignore line order for matching out of parallel builds
+ new AnyOrderOutputMatcher().assertOutputMatches(expectedOutput, getOutput(), ignoreExtraLines);
return this;
}
}
diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/ParallelOutputMatcher.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/ParallelOutputMatcher.groovy
deleted file mode 100644
index 4b06e58..0000000
--- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/ParallelOutputMatcher.groovy
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.integtests.fixtures.executer
-
-import org.junit.Assert
-import org.gradle.internal.SystemProperties
-
-/**
- * Checks that all lines contained in the expected output are present in the actual output, in any order.
- */
-class ParallelOutputMatcher extends SequentialOutputMatcher {
- private static final String NL = SystemProperties.lineSeparator
-
- protected void assertOutputLinesMatch(List<String> expectedLines, List<String> actualLines, boolean ignoreExtraLines, String actual) {
- List<String> unmatchedLines = new ArrayList<String>(actualLines)
- expectedLines.removeAll('')
- unmatchedLines.removeAll('')
-
- expectedLines.each { expectedLine ->
- def matchedLine = unmatchedLines.find { actualLine ->
- compare(expectedLine, actualLine)
- }
- if (matchedLine) {
- unmatchedLines.remove(matchedLine)
- } else {
- Assert.fail("Line missing from output.${NL}${expectedLine}${NL}---${NL}Actual output:${NL}$actual${NL}---")
- }
- }
-
- if (!(ignoreExtraLines || unmatchedLines.empty)) {
- def unmatched = unmatchedLines.join(NL)
- Assert.fail("Extra lines in output.${NL}${unmatched}${NL}---${NL}Actual output:${NL}$actual${NL}---")
- }
- }
-}
diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/AbstractModule.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/AbstractModule.groovy
new file mode 100644
index 0000000..71156bc
--- /dev/null
+++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/AbstractModule.groovy
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.test.fixtures
+
+import org.gradle.test.fixtures.file.TestFile
+import org.gradle.util.hash.HashUtil
+
+abstract class AbstractModule {
+ /**
+ * @param cl A closure that is passed a writer to use to generate the content.
+ */
+ protected void publish(TestFile file, Closure cl) {
+ def hashBefore = file.exists() ? getHash(file, "sha1") : null
+ def tmpFile = file.parentFile.file("${file.name}.tmp")
+
+ tmpFile.withWriter("utf-8") {
+ cl.call(it)
+ }
+
+ def hashAfter = getHash(tmpFile, "sha1")
+ if (hashAfter == hashBefore) {
+ // Already published
+ return
+ }
+
+ assert !file.exists() || file.delete()
+ assert tmpFile.renameTo(file)
+ onPublish(file)
+ }
+
+ protected abstract onPublish(TestFile file)
+
+ TestFile getSha1File(TestFile file) {
+ getHashFile(file, "sha1")
+ }
+
+ TestFile sha1File(TestFile file) {
+ hashFile(file, "sha1", 40)
+ }
+
+ TestFile getMd5File(TestFile file) {
+ getHashFile(file, "md5")
+ }
+
+ TestFile md5File(TestFile file) {
+ hashFile(file, "md5", 32)
+ }
+
+ private TestFile hashFile(TestFile file, String algorithm, int len) {
+ def hashFile = getHashFile(file, algorithm)
+ def hash = getHash(file, algorithm)
+ hashFile.text = String.format("%0${len}x", hash)
+ return hashFile
+ }
+
+ private TestFile getHashFile(TestFile file, String algorithm) {
+ file.parentFile.file("${file.name}.${algorithm}")
+ }
+
+ protected BigInteger getHash(TestFile file, String algorithm) {
+ HashUtil.createHash(file, algorithm.toUpperCase()).asBigInteger()
+ }
+}
diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/ivy/AbstractIvyModule.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/ivy/AbstractIvyModule.groovy
deleted file mode 100644
index 63528d6..0000000
--- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/ivy/AbstractIvyModule.groovy
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.test.fixtures.ivy
-
-abstract class AbstractIvyModule implements IvyModule {
-
- IvyDescriptor getIvy() {
- return new IvyDescriptor(ivyFile)
- }
-
-}
diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/ivy/IvyDescriptor.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/ivy/IvyDescriptor.groovy
index 2eeb441..1eb1373 100644
--- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/ivy/IvyDescriptor.groovy
+++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/ivy/IvyDescriptor.groovy
@@ -90,7 +90,9 @@ class IvyDescriptor {
expected.each {
String key = StringUtils.substringBefore(it, "@")
String conf = StringUtils.substringAfter(it, "@") + "->default"
+ assert dependencies.containsKey(key)
assert dependencies[key].hasConf(conf)
}
+ true
}
}
diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/ivy/IvyFileModule.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/ivy/IvyFileModule.groovy
index c28754a..07e0263 100644
--- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/ivy/IvyFileModule.groovy
+++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/ivy/IvyFileModule.groovy
@@ -19,10 +19,10 @@ import org.apache.ivy.core.IvyPatternHelper
import org.apache.ivy.core.module.id.ModuleRevisionId
import org.gradle.api.Action
import org.gradle.api.internal.xml.XmlTransformer
+import org.gradle.test.fixtures.AbstractModule
import org.gradle.test.fixtures.file.TestFile
-import org.gradle.util.hash.HashUtil
-class IvyFileModule extends AbstractIvyModule {
+class IvyFileModule extends AbstractModule implements IvyModule {
final String ivyPattern
final String artifactPattern
final TestFile moduleDir
@@ -44,13 +44,16 @@ class IvyFileModule extends AbstractIvyModule {
this.organisation = organisation
this.module = module
this.revision = revision
- artifact([:])
- configurations['runtime'] = [extendsFrom: [], transitive: true]
- configurations['default'] = [extendsFrom: ['runtime'], transitive: true]
+ configurations['runtime'] = [extendsFrom: [], transitive: true, visibility: 'public']
+ configurations['default'] = [extendsFrom: ['runtime'], transitive: true, visibility: 'public']
}
- IvyFileModule configuration(String name, List extendsFrom = []) {
- configurations[name] = [extendsFrom: extendsFrom, transitive: true]
+ IvyDescriptor getIvy() {
+ return new IvyDescriptor(ivyFile)
+ }
+
+ IvyFileModule configuration(Map<String, ?> options = [:], String name) {
+ configurations[name] = [extendsFrom: options.extendsFrom ?: [], transitive: options.transitive ?: true, visibility: options.visibility ?: 'public']
return this
}
@@ -64,7 +67,7 @@ class IvyFileModule extends AbstractIvyModule {
* @param options Can specify any of name, type or classifier
* @return this
*/
- IvyFileModule artifact(Map<String, ?> options) {
+ IvyFileModule artifact(Map<String, ?> options = [:]) {
artifacts << [name: options.name ?: module, type: options.type ?: 'jar', classifier: options.classifier ?: null, conf: options.conf ?: '*']
return this
}
@@ -109,10 +112,6 @@ class IvyFileModule extends AbstractIvyModule {
return moduleDir.file(path)
}
- TestFile sha1File(File file) {
- return moduleDir.file("${file.name}.sha1")
- }
-
TestFile artifactFile(String name) {
return file(artifacts.find { it.name == name })
}
@@ -131,22 +130,26 @@ class IvyFileModule extends AbstractIvyModule {
IvyModule publish() {
moduleDir.createDir()
+ if (artifacts.empty) {
+ artifact([:])
+ }
+
artifacts.each { artifact ->
def artifactFile = file(artifact)
- publish(artifactFile) {
- artifactFile.text = "${artifactFile.name} : $publishCount"
+ publish(artifactFile) { Writer writer ->
+ writer << "${artifactFile.name} : $artifactContent"
}
}
if (noMetaData) {
return this
}
- publish(ivyFile) {
- transformer.transform(ivyFile, new Action<Writer>() {
+ publish(ivyFile) { Writer writer ->
+ transformer.transform(writer, new Action<Writer>() {
void execute(Writer ivyFileWriter) {
ivyFileWriter << """<?xml version="1.0" encoding="UTF-8"?>
<ivy-module version="1.0" xmlns:m="http://ant.apache.org/ivy/maven">
- <!-- ${publishCount} -->
+ <!-- ${getArtifactContent()} -->
<info organisation="${organisation}"
module="${module}"
revision="${revision}"
@@ -154,13 +157,14 @@ class IvyFileModule extends AbstractIvyModule {
/>
<configurations>"""
configurations.each { name, config ->
- ivyFileWriter << "<conf name='$name' visibility='public'"
+ ivyFileWriter << "<conf name='$name'"
if (config.extendsFrom) {
ivyFileWriter << " extends='${config.extendsFrom.join(',')}'"
}
if (!config.transitive) {
ivyFileWriter << " transitive='false'"
}
+ ivyFileWriter << " visibility='$config.visibility'"
ivyFileWriter << "/>"
}
ivyFileWriter << """</configurations>
@@ -194,13 +198,14 @@ class IvyFileModule extends AbstractIvyModule {
return moduleDir.file("${artifact.name}-${revision}${artifact.classifier ? '-' + artifact.classifier : ''}.${artifact.type}")
}
- private publish(File file, Closure cl) {
- def lastModifiedTime = file.exists() ? file.lastModified() : null
- cl.call(file)
- if (lastModifiedTime != null) {
- file.setLastModified(lastModifiedTime + 2000)
- }
- sha1File(file).text = getHash(file, "SHA1")
+ @Override
+ protected onPublish(TestFile file) {
+ sha1File(file)
+ }
+
+ private String getArtifactContent() {
+ // Some content to include in each artifact, so that its size and content varies on each publish
+ return (0..publishCount).join("-")
}
/**
@@ -212,24 +217,28 @@ class IvyFileModule extends AbstractIvyModule {
allFileNames.addAll([name, "${name}.sha1"])
}
assert moduleDir.list() as Set == allFileNames
+ for (name in names) {
+ assertChecksumPublishedFor(moduleDir.file(name))
+ }
}
void assertChecksumPublishedFor(TestFile testFile) {
def sha1File = sha1File(testFile)
sha1File.assertIsFile()
- new BigInteger(sha1File.text, 16) == new BigInteger(getHash(testFile, "SHA1"), 16)
- }
-
- String getHash(File file, String algorithm) {
- return HashUtil.createHash(file, algorithm).asHexString()
+ assert new BigInteger(sha1File.text, 16) == getHash(testFile, "SHA1")
}
void assertNotPublished() {
ivyFile.assertDoesNotExist()
}
+ void assertIvyAndJarFilePublished() {
+ assertArtifactsPublished(ivyFile.name, jarFile.name)
+ assertPublished()
+ }
+
void assertPublished() {
- assert ivyFile.assertExists()
+ assert ivyFile.assertIsFile()
assert ivy.organisation == organisation
assert ivy.module == module
assert ivy.revision == revision
diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/ivy/IvyFileRepository.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/ivy/IvyFileRepository.groovy
index 6abdc4d..7b7e0c0 100644
--- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/ivy/IvyFileRepository.groovy
+++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/ivy/IvyFileRepository.groovy
@@ -59,6 +59,14 @@ class IvyFileRepository implements IvyRepository {
}
IvyFileModule module(String organisation, String module, Object revision = '1.0') {
+ return createModule(organisation, module, revision as String)
+ }
+
+ IvyFileModule module(String module) {
+ return createModule("org.gradle.test", module, '1.0')
+ }
+
+ private IvyFileModule createModule(String organisation, String module, String revision) {
def revisionString = revision.toString()
def path = IvyPatternHelper.substitute(dirPattern, ModuleRevisionId.newInstance(organisation, module, revisionString))
def moduleDir = rootDir.file(path)
diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/ivy/IvyHttpModule.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/ivy/IvyHttpModule.groovy
index 52dca48..3d2a03a 100644
--- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/ivy/IvyHttpModule.groovy
+++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/ivy/IvyHttpModule.groovy
@@ -18,8 +18,9 @@ package org.gradle.test.fixtures.ivy
import org.gradle.test.fixtures.file.TestFile
import org.gradle.test.fixtures.server.http.HttpServer
+import org.mortbay.jetty.HttpStatus
-class IvyHttpModule extends AbstractIvyModule {
+class IvyHttpModule implements IvyModule {
private final IvyFileModule backingModule
private final HttpServer server
private final String prefix
@@ -30,6 +31,10 @@ class IvyHttpModule extends AbstractIvyModule {
this.backingModule = backingModule
}
+ IvyDescriptor getIvy() {
+ return backingModule.ivy
+ }
+
IvyHttpModule publish() {
backingModule.publish()
return this
@@ -65,6 +70,11 @@ class IvyHttpModule extends AbstractIvyModule {
return this
}
+ IvyModule withXml(Closure action) {
+ backingModule.withXml(action)
+ return this
+ }
+
String getIvyFileUri() {
return "http://localhost:${server.port}$prefix/$ivyFile.name"
}
@@ -105,6 +115,14 @@ class IvyHttpModule extends AbstractIvyModule {
server.expectHeadBroken("$prefix/$ivyFile.name")
}
+ void expectIvyPut(int status = HttpStatus.ORDINAL_200_OK) {
+ server.expectPut("$prefix/$ivyFile.name", ivyFile, status)
+ }
+
+ void expectIvyPut(String userName, String password) {
+ server.expectPut("$prefix/$ivyFile.name", userName, password, ivyFile)
+ }
+
void expectIvySha1Get() {
server.expectGet("$prefix/${ivyFile.name}.sha1", backingModule.sha1File(ivyFile))
}
@@ -113,6 +131,14 @@ class IvyHttpModule extends AbstractIvyModule {
server.expectGetMissing("$prefix/${ivyFile.name}.sha1")
}
+ void expectIvySha1Put(int status = HttpStatus.ORDINAL_200_OK) {
+ server.expectPut("$prefix/${ivyFile.name}.sha1", backingModule.getSha1File(ivyFile), status)
+ }
+
+ void expectIvySha1Put(String userName, String password) {
+ server.expectPut("$prefix/${ivyFile.name}.sha1", userName, password, backingModule.getSha1File(ivyFile))
+ }
+
void expectJarGet() {
server.expectGet("$prefix/$jarFile.name", jarFile)
}
@@ -133,6 +159,14 @@ class IvyHttpModule extends AbstractIvyModule {
server.expectHeadMissing("$prefix/$jarFile.name")
}
+ void expectJarPut(int status = HttpStatus.ORDINAL_200_OK) {
+ server.expectPut("$prefix/$jarFile.name", jarFile, status)
+ }
+
+ void expectJarPut(String userName, String password) {
+ server.expectPut("$prefix/$jarFile.name", userName, password, jarFile)
+ }
+
void expectJarSha1Get() {
server.expectGet("$prefix/${jarFile.name}.sha1", backingModule.sha1File(jarFile))
}
@@ -141,6 +175,14 @@ class IvyHttpModule extends AbstractIvyModule {
server.expectGetMissing("$prefix/${jarFile.name}.sha1")
}
+ void expectJarSha1Put() {
+ server.expectPut("$prefix/${jarFile.name}.sha1", backingModule.getSha1File(jarFile))
+ }
+
+ void expectJarSha1Put(String userName, String password) {
+ server.expectPut("$prefix/${jarFile.name}.sha1", userName, password, backingModule.getSha1File(jarFile))
+ }
+
void expectArtifactGet(String name) {
def artifactFile = backingModule.artifactFile(name)
server.expectGet("$prefix/$artifactFile.name", artifactFile)
@@ -169,6 +211,10 @@ class IvyHttpModule extends AbstractIvyModule {
def artifactFile = backingModule.file(mappedOptions)
server.expectGet("$prefix/${artifactFile.name}.sha1", backingModule.sha1File(artifactFile))
}
+
+ void assertIvyAndJarFilePublished() {
+ backingModule.assertIvyAndJarFilePublished()
+ }
}
diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/ivy/IvyModule.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/ivy/IvyModule.java
index 9d1e47b..26a5fd7 100644
--- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/ivy/IvyModule.java
+++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/ivy/IvyModule.java
@@ -16,6 +16,7 @@
package org.gradle.test.fixtures.ivy;
+import groovy.lang.Closure;
import org.gradle.test.fixtures.file.TestFile;
import java.util.Map;
@@ -38,15 +39,23 @@ public interface IvyModule {
IvyModule artifact(Map<String, ?> options);
+ IvyModule withXml(Closure action);
+
/**
* Publishes ivy.xml plus all artifacts with different content to previous publication.
*/
IvyModule publishWithChangedContent();
/**
- * Publishes ivy.xml plus all artifacts
+ * Publishes ivy.xml plus all artifacts. Publishes only those artifacts whose content has changed since the
+ * last call to {@code #publish()}.
*/
IvyModule publish();
IvyDescriptor getIvy();
+
+ /**
+ * Assert that exactly the ivy.xml and jar file for this module, plus checksum files, have been published.
+ */
+ void assertIvyAndJarFilePublished();
}
diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/maven/HttpArtifact.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/maven/HttpArtifact.groovy
index 8ee2afe..36be0e9 100644
--- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/maven/HttpArtifact.groovy
+++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/maven/HttpArtifact.groovy
@@ -46,6 +46,10 @@ abstract class HttpArtifact extends HttpResource {
return new BasicHttpResource(server, getSha1File(), "${path}.sha1")
}
+ URI getUri() {
+ return new URI("http://localhost:${server.port}${path}")
+ }
+
protected String getPath() {
"${modulePath}/${file.name}"
}
diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/maven/MavenDependency.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/maven/MavenDependency.groovy
index c439240..45ee411 100644
--- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/maven/MavenDependency.groovy
+++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/maven/MavenDependency.groovy
@@ -27,4 +27,9 @@ class MavenDependency {
assert this.type == type
return this
}
+
+ @Override
+ public String toString() {
+ return String.format("MavenDependency %s:%s:%s:%s@%s", groupId, artifactId, version, classifier, type)
+ }
}
diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/maven/MavenFileModule.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/maven/MavenFileModule.groovy
index 9b33a43..5a06715 100644
--- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/maven/MavenFileModule.groovy
+++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/maven/MavenFileModule.groovy
@@ -16,12 +16,12 @@
package org.gradle.test.fixtures.maven
import groovy.xml.MarkupBuilder
+import org.gradle.test.fixtures.AbstractModule
import org.gradle.test.fixtures.file.TestFile
-import org.gradle.util.hash.HashUtil
import java.text.SimpleDateFormat
-class MavenFileModule implements MavenModule {
+class MavenFileModule extends AbstractModule implements MavenModule {
private static final String MAVEN_METADATA_FILE = "maven-metadata.xml"
final TestFile moduleDir
final String groupId
@@ -225,10 +225,10 @@ class MavenFileModule implements MavenModule {
updateRootMavenMetaData(rootMavenMetaData)
if (uniqueSnapshots && version.endsWith("-SNAPSHOT")) {
- publish(metaDataFile) {
- metaDataFile.text = """
+ publish(metaDataFile) { Writer writer ->
+ writer << """
<metadata>
- <!-- $publishCount -->
+ <!-- ${getArtifactContent()} -->
<groupId>$groupId</groupId>
<artifactId>$artifactId</artifactId>
<version>$version</version>
@@ -244,11 +244,11 @@ class MavenFileModule implements MavenModule {
}
}
- publish(pomFile) {
+ publish(pomFile) { Writer writer ->
def pomPackaging = packaging ?: type;
- pomFile.text = ""
- pomFile << """
+ writer << """
<project xmlns="http://maven.apache.org/POM/4.0.0">
+ <!-- ${getArtifactContent()} -->
<modelVersion>4.0.0</modelVersion>
<groupId>$groupId</groupId>
<artifactId>$artifactId</artifactId>
@@ -257,17 +257,17 @@ class MavenFileModule implements MavenModule {
<description>Published on $publishTimestamp</description>"""
if (parentPomSection) {
- pomFile << "\n$parentPomSection\n"
+ writer << "\n$parentPomSection\n"
}
if (!dependencies.empty) {
- pomFile << """
+ writer << """
<dependencies>"""
}
dependencies.each { dependency ->
def typeAttribute = dependency['type'] == null ? "" : "<type>$dependency.type</type>"
- pomFile << """
+ writer << """
<dependency>
<groupId>$dependency.groupId</groupId>
<artifactId>$dependency.artifactId</artifactId>
@@ -277,11 +277,11 @@ class MavenFileModule implements MavenModule {
}
if (!dependencies.empty) {
- pomFile << """
+ writer << """
</dependencies>"""
}
- pomFile << "\n</project>"
+ writer << "\n</project>"
}
artifacts.each { artifact ->
@@ -294,25 +294,23 @@ class MavenFileModule implements MavenModule {
private void updateRootMavenMetaData(TestFile rootMavenMetaData) {
def allVersions = rootMavenMetaData.exists() ? new XmlParser().parseText(rootMavenMetaData.text).versioning.versions.version*.value().flatten() : []
allVersions << version;
- publish(rootMavenMetaData) {
- rootMavenMetaData.withWriter {writer ->
- def builder = new MarkupBuilder(writer)
- builder.metadata {
- groupId(groupId)
- artifactId(artifactId)
- version(allVersions.max())
- versioning {
- if (uniqueSnapshots && version.endsWith("-SNAPSHOT")) {
- snapshot {
- timestamp(timestampFormat.format(publishTimestamp))
- buildNumber(publishCount)
- lastUpdated(updateFormat.format(publishTimestamp))
- }
- } else {
- versions {
- allVersions.each {currVersion ->
- version(currVersion)
- }
+ publish(rootMavenMetaData) { Writer writer ->
+ def builder = new MarkupBuilder(writer)
+ builder.metadata {
+ groupId(groupId)
+ artifactId(artifactId)
+ version(allVersions.max())
+ versioning {
+ if (uniqueSnapshots && version.endsWith("-SNAPSHOT")) {
+ snapshot {
+ timestamp(timestampFormat.format(publishTimestamp))
+ buildNumber(publishCount)
+ lastUpdated(updateFormat.format(publishTimestamp))
+ }
+ } else {
+ versions {
+ allVersions.each {currVersion ->
+ version(currVersion)
}
}
}
@@ -323,21 +321,24 @@ class MavenFileModule implements MavenModule {
private File publishArtifact(Map<String, ?> artifact) {
def artifactFile = artifactFile(artifact)
- publish(artifactFile) {
- if (type != 'pom') {
- artifactFile.text = "${artifactFile.name} : $publishCount"
- }
+ if (type == 'pom') {
+ return artifactFile
+ }
+ publish(artifactFile) { Writer writer ->
+ writer << "${artifactFile.name} : $artifactContent"
}
return artifactFile
}
- private publish(File file, Closure cl) {
- def lastModifiedTime = file.exists() ? file.lastModified() : null
- cl.call(file)
- if (lastModifiedTime != null) {
- file.setLastModified(lastModifiedTime + 2000)
- }
- createHashFiles(file)
+ @Override
+ protected onPublish(TestFile file) {
+ sha1File(file)
+ md5File(file)
+ }
+
+ private String getArtifactContent() {
+ // Some content to include in each artifact, so that its size and content varies on each publish
+ return (0..publishCount).join("-")
}
private Map<String, Object> toArtifact(Map<String, ?> options) {
@@ -346,39 +347,4 @@ class MavenFileModule implements MavenModule {
assert options.isEmpty(): "Unknown options : ${options.keySet()}"
return artifact
}
-
- private void createHashFiles(File file) {
- sha1File(file)
- md5File(file)
- }
-
- TestFile getSha1File(File file) {
- getHashFile(file, "sha1")
- }
-
- TestFile sha1File(File file) {
- hashFile(file, "sha1");
- }
-
- TestFile getMd5File(File file) {
- getHashFile(file, "md5")
- }
-
- TestFile md5File(File file) {
- hashFile(file, "md5")
- }
-
- private TestFile hashFile(TestFile file, String algorithm) {
- def hashFile = getHashFile(file, algorithm)
- hashFile.text = getHash(file, algorithm)
- return hashFile
- }
-
- protected TestFile getHashFile(TestFile file, String algorithm) {
- file.parentFile.file("${file.name}.${algorithm}")
- }
-
- protected String getHash(TestFile file, String algorithm) {
- HashUtil.createHash(file, algorithm.toUpperCase()).asHexString()
- }
}
diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/maven/MavenModule.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/maven/MavenModule.groovy
index 5a4dace..1c40d99 100644
--- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/maven/MavenModule.groovy
+++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/maven/MavenModule.groovy
@@ -22,7 +22,8 @@ import org.gradle.test.fixtures.file.TestFile
interface MavenModule {
/**
- * Publishes the pom.xml plus main artifact, plus any additional artifacts for this module.
+ * Publishes the pom.xml plus main artifact, plus any additional artifacts for this module. Publishes only those artifacts whose content has
+ * changed since the last call to {@code #publish()}.
*/
MavenModule publish()
diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/maven/MavenScope.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/maven/MavenScope.groovy
index b67f38a..161cd92 100644
--- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/maven/MavenScope.groovy
+++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/maven/MavenScope.groovy
@@ -40,7 +40,7 @@ class MavenScope {
MavenDependency expectDependency(String key) {
final dependency = dependencies[key]
if (dependency == null) {
- throw new AssertionError("Could not find expected dependency $dep. Actual: ${dependencies.values()}")
+ throw new AssertionError("Could not find expected dependency $key. Actual: ${dependencies.values()}")
}
return dependency
}
diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/publish/Identifier.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/publish/Identifier.java
deleted file mode 100644
index cf46a7e..0000000
--- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/publish/Identifier.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright 2013 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.test.fixtures.publish;
-
-import org.gradle.internal.os.OperatingSystem;
-import org.gradle.util.GUtil;
-
-public class Identifier {
- private static final String PUNCTUATION_CHARS = "-'!@#$%^&*()_+=,.?{}[]<>";
- private static final String NON_ASCII_CHARS = "-√æず∫ʙぴ₦ガき∆ç√∫";
- private static final String FILESYSTEM_RESERVED_CHARS = "-./\\?%*:|\"<>";
- private static final String XML_MARKUP_CHARS = "-<with>some<xml-markup/></with>";
-
- private final String suffix;
-
- public Identifier(String suffix) {
- this.suffix = GUtil.elvis(suffix, "");
- }
-
- public Identifier withPunctuation() {
- return new Identifier(suffix + PUNCTUATION_CHARS);
- }
-
- public Identifier withNonAscii() {
- return new Identifier(suffix + NON_ASCII_CHARS);
- }
-
- public Identifier withReservedFileSystemChars() {
- return new Identifier(suffix + FILESYSTEM_RESERVED_CHARS);
- }
-
- public Identifier withMarkup() {
- return new Identifier(suffix + XML_MARKUP_CHARS);
- }
-
- public Identifier withWhiteSpace() {
- return new Identifier(suffix + " with white space");
- }
-
- public Identifier safeForFileName() {
- return without(getUnsupportedFileNameCharacters());
- }
-
- public Identifier without(String toRemove) {
- String newSuffix = suffix;
- for (char c : toRemove.toCharArray()) {
- newSuffix = newSuffix.replace(c, '-');
- }
- return new Identifier(newSuffix);
- }
-
- private static String getUnsupportedFileNameCharacters() {
- if (OperatingSystem.current().isWindows()) {
- return "<>:\"/\\|?*";
- }
- return "/\\";
- }
-
- public String decorate(String prefix) {
- return prefix + suffix;
- }
-
- @Override
- public String toString() {
- return suffix;
- }
-
- public static Identifier getPunctuation() {
- return new Identifier("").withPunctuation();
- }
-
- public static Identifier getNonAscii() {
- return new Identifier("").withNonAscii();
- }
-
- public static Identifier getFileSystemReserved() {
- return new Identifier("").withReservedFileSystemChars();
- }
-
- public static Identifier getXmlMarkup() {
- return new Identifier("").withMarkup();
- }
-
- public static Identifier getWhiteSpace() {
- return new Identifier("").withWhiteSpace();
- }
-}
diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/HttpServer.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/HttpServer.groovy
index 289c797..551b3fd 100755
--- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/HttpServer.groovy
+++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/HttpServer.groovy
@@ -21,19 +21,18 @@ import org.gradle.util.GFileUtils
import org.gradle.util.hash.HashUtil
import org.hamcrest.Matcher
import org.junit.rules.ExternalResource
+import org.mortbay.jetty.*
import org.mortbay.jetty.bio.SocketConnector
import org.mortbay.jetty.handler.AbstractHandler
import org.mortbay.jetty.handler.HandlerCollection
+import org.mortbay.jetty.security.*
import org.slf4j.Logger
import org.slf4j.LoggerFactory
-import java.security.Principal
-import java.util.zip.GZIPOutputStream
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
-
-import org.mortbay.jetty.*
-import org.mortbay.jetty.security.*
+import java.security.Principal
+import java.util.zip.GZIPOutputStream
class HttpServer extends ExternalResource {
@@ -191,13 +190,6 @@ class HttpServer extends ExternalResource {
}
/**
- * Adds a given file at the given URL. The source file can be either a file or a directory.
- */
- void allowHead(String path, File srcFile) {
- allow(path, true, ['HEAD'], fileHandler(path, srcFile))
- }
-
- /**
* Adds a given file at the given URL with the given credentials. The source file can be either a file or a directory.
*/
void allowGetOrHead(String path, String username, String password, File srcFile) {
@@ -408,13 +400,15 @@ class HttpServer extends ExternalResource {
if (sendLastModified) {
response.setDateHeader(HttpHeaders.LAST_MODIFIED, lastModified ?: file.lastModified())
}
- response.setContentLength((contentLength ?: file.length()) as int)
+ def content = file.bytes
+ response.setContentLength((contentLength ?: content.length) as int)
response.setContentType(new MimeTypes().getMimeByExtension(file.name).toString())
if (sendSha1Header) {
- response.addHeader("X-Checksum-Sha1", HashUtil.sha1(file).asHexString())
+ response.addHeader("X-Checksum-Sha1", HashUtil.sha1(content).asHexString())
}
- addEtag(response, file.bytes, etags)
- response.outputStream << new FileInputStream(file)
+
+ addEtag(response, content, etags)
+ response.outputStream << content
}
private addEtag(HttpServletResponse response, byte[] bytes, etagStrategy) {
@@ -486,6 +480,7 @@ class HttpServer extends ExternalResource {
response.sendError(500, "unexpected username '${request.remoteUser}'")
return
}
+ destFile.parentFile.mkdirs()
destFile.bytes = request.inputStream.bytes
}
}))
diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/ServletContainer.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/ServletContainer.groovy
new file mode 100644
index 0000000..ea5dcac
--- /dev/null
+++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/ServletContainer.groovy
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.test.fixtures.server.http
+
+import org.mortbay.jetty.Server
+import org.mortbay.jetty.webapp.WebAppContext
+
+class ServletContainer {
+ private final Server webServer = new Server(0)
+ private final warFile
+
+ ServletContainer(File warFile) {
+ this.warFile = warFile
+ }
+
+ int getPort() {
+ webServer.connectors[0].localPort
+ }
+
+ void start() {
+ def context = new WebAppContext()
+ context.war = warFile
+ webServer.addHandler(context)
+ webServer.start()
+ }
+
+ void stop() {
+ webServer.stop()
+ }
+}
diff --git a/subprojects/internal-testing/internal-testing.gradle b/subprojects/internal-testing/internal-testing.gradle
index 4fb6bf8..67ebc99 100644
--- a/subprojects/internal-testing/internal-testing.gradle
+++ b/subprojects/internal-testing/internal-testing.gradle
@@ -18,10 +18,11 @@
Provides generally useful test utilities, used for unit and integration testing.
*/
dependencies {
- groovy libraries.groovy
+ compile libraries.groovy
compile project(":baseServices")
compile project(":native")
+ compile libraries.guava
compile libraries.commons_lang
compile libraries.commons_io
compile libraries.ant
diff --git a/subprojects/internal-testing/src/main/groovy/org/gradle/integtests/fixtures/DefaultTestExecutionResult.groovy b/subprojects/internal-testing/src/main/groovy/org/gradle/integtests/fixtures/DefaultTestExecutionResult.groovy
index f73be8d..6a5f5ed 100644
--- a/subprojects/internal-testing/src/main/groovy/org/gradle/integtests/fixtures/DefaultTestExecutionResult.groovy
+++ b/subprojects/internal-testing/src/main/groovy/org/gradle/integtests/fixtures/DefaultTestExecutionResult.groovy
@@ -90,9 +90,17 @@ class DefaultTestExecutionResult implements TestExecutionResult {
this
}
+ TestClassExecutionResult assertTestCaseStdout(String testCaseName, Matcher<? super String> matcher) {
+ testClassResults*.assertTestCaseStdout(testCaseName, matcher)
+ }
+
TestClassExecutionResult assertStderr(Matcher<? super String> matcher) {
testClassResults*.assertStderr(matcher)
this
}
+
+ TestClassExecutionResult assertTestCaseStderr(String testCaseName, Matcher<? super String> matcher) {
+ testClassResults*.assertTestCaseStderr(testCaseName, matcher)
+ }
}
}
diff --git a/subprojects/internal-testing/src/main/groovy/org/gradle/integtests/fixtures/HtmlTestExecutionResult.groovy b/subprojects/internal-testing/src/main/groovy/org/gradle/integtests/fixtures/HtmlTestExecutionResult.groovy
index 7f88634..06d11ab 100644
--- a/subprojects/internal-testing/src/main/groovy/org/gradle/integtests/fixtures/HtmlTestExecutionResult.groovy
+++ b/subprojects/internal-testing/src/main/groovy/org/gradle/integtests/fixtures/HtmlTestExecutionResult.groovy
@@ -37,13 +37,12 @@ class HtmlTestExecutionResult implements TestExecutionResult {
return this
}
- def indexContainsTestClass(String... testClasses) {
+ def indexContainsTestClass(String... expectedTestClasses) {
def indexFile = new File(htmlReportDirectory, "index.html")
assert indexFile.exists()
Document html = Jsoup.parse(indexFile, null)
- testClasses.each { testClass ->
- assert html.select("a").find { it.text() == testClass } != null
- }
+ def executedTestClasses = html.select("div:has(h2:contains(Classes)).tab a").collect { it.text() }
+ assert executedTestClasses.containsAll(expectedTestClasses)
}
def assertHtmlReportForTestClassExists(String... classNames) {
@@ -115,6 +114,7 @@ class HtmlTestExecutionResult implements TestExecutionResult {
}
TestClassExecutionResult assertTestFailed(String name, Matcher<? super String>... messageMatchers) {
+ assert testsFailures.containsKey(name)
def message = testsFailures[name];
messageMatchers.each { it.matches(message) }
return this
@@ -138,9 +138,18 @@ class HtmlTestExecutionResult implements TestExecutionResult {
return this;
}
+ TestClassExecutionResult assertTestCaseStdout(String testCaseName, Matcher<? super String> matcher) {
+ throw new UnsupportedOperationException()
+ }
+
TestClassExecutionResult assertStderr(Matcher<? super String> matcher) {
matcher.matches(html.select("div#tab3 > span > pre").text())
return this;
}
+
+ TestClassExecutionResult assertTestCaseStderr(String testCaseName, Matcher<? super String> matcher) {
+ throw new UnsupportedOperationException()
+ }
+
}
}
diff --git a/subprojects/internal-testing/src/main/groovy/org/gradle/integtests/fixtures/JUnitTestClassExecutionResult.groovy b/subprojects/internal-testing/src/main/groovy/org/gradle/integtests/fixtures/JUnitTestClassExecutionResult.groovy
new file mode 100644
index 0000000..a6f1544
--- /dev/null
+++ b/subprojects/internal-testing/src/main/groovy/org/gradle/integtests/fixtures/JUnitTestClassExecutionResult.groovy
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests.fixtures
+
+import groovy.util.slurpersupport.GPathResult
+import groovy.util.slurpersupport.NodeChild
+import org.hamcrest.Matcher
+import org.hamcrest.Matchers
+import org.junit.Assert
+
+class JUnitTestClassExecutionResult implements TestClassExecutionResult {
+ GPathResult testClassNode
+ String testClassName
+ boolean checked
+ TestResultOutputAssociation outputAssociation
+
+ def JUnitTestClassExecutionResult(GPathResult testClassNode, String testClassName, TestResultOutputAssociation outputAssociation) {
+ this.outputAssociation = outputAssociation
+ this.testClassNode = testClassNode
+ this.testClassName = testClassName
+ }
+
+ def JUnitTestClassExecutionResult(String content, String testClassName, TestResultOutputAssociation outputAssociation) {
+ this(new XmlSlurper().parse(new StringReader(content)), testClassName, outputAssociation)
+ }
+
+ TestClassExecutionResult assertTestsExecuted(String... testNames) {
+ Map<String, Node> testMethods = findTests()
+ Assert.assertThat(testMethods.keySet(), Matchers.equalTo(testNames as Set))
+ this
+ }
+
+ TestClassExecutionResult assertTestCount(int tests, int failures, int errors) {
+ assert testClassNode. at tests == tests
+ assert testClassNode. at failures == failures
+ assert testClassNode. at errors == errors
+ this
+ }
+
+ TestClassExecutionResult assertTestPassed(String name) {
+ Map<String, Node> testMethods = findTests()
+ Assert.assertThat(testMethods.keySet(), Matchers.hasItem(name))
+ Assert.assertThat(testMethods[name].failure.size(), Matchers.equalTo(0))
+ this
+ }
+
+ TestClassExecutionResult assertTestFailed(String name, Matcher<? super String>... messageMatchers) {
+ Map<String, Node> testMethods = findTests()
+ Assert.assertThat(testMethods.keySet(), Matchers.hasItem(name))
+
+ def failures = testMethods[name].failure
+ Assert.assertThat("Expected ${messageMatchers.length} failures. Found: $failures", failures.size(), Matchers.equalTo(messageMatchers.length))
+
+ for (int i = 0; i < messageMatchers.length; i++) {
+ Assert.assertThat(failures[i]. at message.text(), messageMatchers[i])
+ }
+ this
+ }
+
+ TestClassExecutionResult assertTestSkipped(String name) {
+ throw new UnsupportedOperationException()
+ }
+
+ TestClassExecutionResult assertTestsSkipped(String... testNames) {
+ Map<String, Node> testMethods = findIgnoredTests()
+ Assert.assertThat(testMethods.keySet(), Matchers.equalTo(testNames as Set))
+ this
+ }
+
+ TestClassExecutionResult assertConfigMethodPassed(String name) {
+ throw new UnsupportedOperationException();
+ }
+
+ TestClassExecutionResult assertConfigMethodFailed(String name) {
+ throw new UnsupportedOperationException();
+ }
+
+ TestClassExecutionResult assertStdout(Matcher<? super String> matcher) {
+ def stdout = testClassNode.'system-out'[0].text();
+ Assert.assertThat(stdout, matcher)
+ this
+ }
+
+ TestClassExecutionResult assertStderr(Matcher<? super String> matcher) {
+ def stderr = testClassNode.'system-err'[0].text();
+ Assert.assertThat(stderr, matcher)
+ this
+ }
+
+ TestClassExecutionResult assertTestCaseStderr(String testCaseName, Matcher<? super String> matcher) {
+ def stderr = testCase(testCaseName).'system-err'[0].text();
+ Assert.assertThat(stderr, matcher)
+ this
+ }
+
+ TestClassExecutionResult assertTestCaseStdout(String testCaseName, Matcher<? super String> matcher) {
+ def stderr = testCase(testCaseName).'system-out'[0].text();
+ Assert.assertThat(stderr, matcher)
+ this
+ }
+
+ private NodeChild testCase(String name) {
+ testClassNode.testcase.find { it. at name == name }
+ }
+
+ private def findTests() {
+ if (!checked) {
+ Assert.assertThat(testClassNode.name(), Matchers.equalTo('testsuite'))
+ Assert.assertThat(testClassNode. at name.text(), Matchers.equalTo(testClassName))
+ Assert.assertThat(testClassNode. at tests.text(), Matchers.not(Matchers.equalTo('')))
+ Assert.assertThat(testClassNode. at failures.text(), Matchers.not(Matchers.equalTo('')))
+ Assert.assertThat(testClassNode. at errors.text(), Matchers.not(Matchers.equalTo('')))
+ Assert.assertThat(testClassNode. at time.text(), Matchers.not(Matchers.equalTo('')))
+ Assert.assertThat(testClassNode. at timestamp.text(), Matchers.not(Matchers.equalTo('')))
+ Assert.assertThat(testClassNode. at hostname.text(), Matchers.not(Matchers.equalTo('')))
+ Assert.assertThat(testClassNode.properties.size(), Matchers.equalTo(1))
+ testClassNode.testcase.each { node ->
+ Assert.assertThat(node. at classname.text(), Matchers.equalTo(testClassName))
+ Assert.assertThat(node. at name.text(), Matchers.not(Matchers.equalTo('')))
+ Assert.assertThat(node. at time.text(), Matchers.not(Matchers.equalTo('')))
+ node.failure.each { failure ->
+ Assert.assertThat(failure. at message.size(), Matchers.equalTo(1))
+ Assert.assertThat(failure. at type.text(), Matchers.not(Matchers.equalTo('')))
+ Assert.assertThat(failure.text(), Matchers.not(Matchers.equalTo('')))
+ }
+ def matcher = Matchers.equalTo(outputAssociation == TestResultOutputAssociation.WITH_TESTCASE ? 1 : 0)
+ Assert.assertThat(node.'system-err'.size(), matcher)
+ Assert.assertThat(node.'system-out'.size(), matcher)
+ }
+ if (outputAssociation == TestResultOutputAssociation.WITH_SUITE) {
+ Assert.assertThat(testClassNode.'system-out'.size(), Matchers.equalTo(1))
+ Assert.assertThat(testClassNode.'system-err'.size(), Matchers.equalTo(1))
+ }
+ checked = true
+ }
+ Map testMethods = [:]
+ testClassNode.testcase.each { testMethods[it. at name.text()] = it }
+ return testMethods
+ }
+
+ private def findIgnoredTests() {
+ Map testMethods = [:]
+ testClassNode."ignored-testcase".each { testMethods[it. at name.text()] = it }
+ return testMethods
+ }
+}
diff --git a/subprojects/internal-testing/src/main/groovy/org/gradle/integtests/fixtures/JUnitXmlTestExecutionResult.groovy b/subprojects/internal-testing/src/main/groovy/org/gradle/integtests/fixtures/JUnitXmlTestExecutionResult.groovy
index 48ee3e1..001d322 100644
--- a/subprojects/internal-testing/src/main/groovy/org/gradle/integtests/fixtures/JUnitXmlTestExecutionResult.groovy
+++ b/subprojects/internal-testing/src/main/groovy/org/gradle/integtests/fixtures/JUnitXmlTestExecutionResult.groovy
@@ -15,17 +15,21 @@
*/
package org.gradle.integtests.fixtures
-import groovy.util.slurpersupport.GPathResult
import org.gradle.test.fixtures.file.TestFile
-import org.hamcrest.Matcher
import static org.hamcrest.Matchers.*
import static org.junit.Assert.assertThat
class JUnitXmlTestExecutionResult implements TestExecutionResult {
private final TestFile buildDir
+ private final TestResultOutputAssociation outputAssociation
def JUnitXmlTestExecutionResult(TestFile projectDir, String buildDirName = 'build') {
+ this(projectDir, TestResultOutputAssociation.WITH_SUITE, buildDirName)
+ }
+
+ def JUnitXmlTestExecutionResult(TestFile projectDir, TestResultOutputAssociation outputAssociation, String buildDirName = 'build') {
+ this.outputAssociation = outputAssociation
this.buildDir = projectDir.file(buildDirName)
}
@@ -40,7 +44,7 @@ class JUnitXmlTestExecutionResult implements TestExecutionResult {
}
TestClassExecutionResult testClass(String testClass) {
- return new JUnitTestClassExecutionResult(findTestClass(testClass), testClass)
+ return new JUnitTestClassExecutionResult(findTestClass(testClass), testClass, outputAssociation)
}
private def findTestClass(String testClass) {
@@ -69,116 +73,3 @@ class JUnitXmlTestExecutionResult implements TestExecutionResult {
}
}
-class JUnitTestClassExecutionResult implements TestClassExecutionResult {
- GPathResult testClassNode
- String testClassName
- boolean checked
-
- def JUnitTestClassExecutionResult(GPathResult testClassNode, String testClassName) {
- this.testClassNode = testClassNode
- this.testClassName = testClassName
- }
-
- def JUnitTestClassExecutionResult(String content, String testClassName) {
- this(new XmlSlurper().parse(new StringReader(content)), testClassName)
- }
-
- TestClassExecutionResult assertTestsExecuted(String... testNames) {
- Map<String, Node> testMethods = findTests()
- assertThat(testMethods.keySet(), equalTo(testNames as Set))
- this
- }
-
- TestClassExecutionResult assertTestCount(int tests, int failures, int errors) {
- assert testClassNode. at tests == tests
- assert testClassNode. at failures == failures
- assert testClassNode. at errors == errors
- this
- }
-
- TestClassExecutionResult assertTestPassed(String name) {
- Map<String, Node> testMethods = findTests()
- assertThat(testMethods.keySet(), hasItem(name))
- assertThat(testMethods[name].failure.size(), equalTo(0))
- this
- }
-
- TestClassExecutionResult assertTestFailed(String name, Matcher<? super String>... messageMatchers) {
- Map<String, Node> testMethods = findTests()
- assertThat(testMethods.keySet(), hasItem(name))
-
- def failures = testMethods[name].failure
- assertThat("Expected ${messageMatchers.length} failures. Found: $failures", failures.size(), equalTo(messageMatchers.length))
-
- for (int i = 0; i < messageMatchers.length; i++) {
- assertThat(failures[i]. at message.text(), messageMatchers[i])
- }
- this
- }
-
- TestClassExecutionResult assertTestSkipped(String name) {
- throw new UnsupportedOperationException()
- }
-
- TestClassExecutionResult assertTestsSkipped(String... testNames) {
- Map<String, Node> testMethods = findIgnoredTests()
- assertThat(testMethods.keySet(), equalTo(testNames as Set))
- this
- }
-
- TestClassExecutionResult assertConfigMethodPassed(String name) {
- throw new UnsupportedOperationException();
- }
-
- TestClassExecutionResult assertConfigMethodFailed(String name) {
- throw new UnsupportedOperationException();
- }
-
- TestClassExecutionResult assertStdout(Matcher<? super String> matcher) {
- def stdout = testClassNode.'system-out'[0].text();
- assertThat(stdout, matcher)
- this
- }
-
- TestClassExecutionResult assertStderr(Matcher<? super String> matcher) {
- def stderr = testClassNode.'system-err'[0].text();
- assertThat(stderr, matcher)
- this
- }
-
- private def findTests() {
- if (!checked) {
- assertThat(testClassNode.name(), equalTo('testsuite'))
- assertThat(testClassNode. at name.text(), equalTo(testClassName))
- assertThat(testClassNode. at tests.text(), not(equalTo('')))
- assertThat(testClassNode. at failures.text(), not(equalTo('')))
- assertThat(testClassNode. at errors.text(), not(equalTo('')))
- assertThat(testClassNode. at time.text(), not(equalTo('')))
- assertThat(testClassNode. at timestamp.text(), not(equalTo('')))
- assertThat(testClassNode. at hostname.text(), not(equalTo('')))
- assertThat(testClassNode.properties.size(), equalTo(1))
- testClassNode.testcase.each { node ->
- assertThat(node. at classname.text(), equalTo(testClassName))
- assertThat(node. at name.text(), not(equalTo('')))
- assertThat(node. at time.text(), not(equalTo('')))
- node.failure.each { failure ->
- assertThat(failure. at message.size(), equalTo(1))
- assertThat(failure. at type.text(), not(equalTo('')))
- assertThat(failure.text(), not(equalTo('')))
- }
- }
- assertThat(testClassNode.'system-out'.size(), equalTo(1))
- assertThat(testClassNode.'system-err'.size(), equalTo(1))
- checked = true
- }
- Map testMethods = [:]
- testClassNode.testcase.each { testMethods[it. at name.text()] = it }
- return testMethods
- }
-
- private def findIgnoredTests() {
- Map testMethods = [:]
- testClassNode."ignored-testcase".each { testMethods[it. at name.text()] = it }
- return testMethods
- }
-}
diff --git a/subprojects/internal-testing/src/main/groovy/org/gradle/integtests/fixtures/TestClassExecutionResult.java b/subprojects/internal-testing/src/main/groovy/org/gradle/integtests/fixtures/TestClassExecutionResult.java
index 027b1bd..270ca53 100644
--- a/subprojects/internal-testing/src/main/groovy/org/gradle/integtests/fixtures/TestClassExecutionResult.java
+++ b/subprojects/internal-testing/src/main/groovy/org/gradle/integtests/fixtures/TestClassExecutionResult.java
@@ -58,5 +58,9 @@ public interface TestClassExecutionResult {
TestClassExecutionResult assertStdout(Matcher<? super String> matcher);
+ TestClassExecutionResult assertTestCaseStdout(String testCaseName, Matcher<? super String> matcher);
+
TestClassExecutionResult assertStderr(Matcher<? super String> matcher);
+
+ TestClassExecutionResult assertTestCaseStderr(String testCaseName, Matcher<? super String> matcher);
}
diff --git a/subprojects/internal-testing/src/main/groovy/org/gradle/integtests/fixtures/TestResultOutputAssociation.java b/subprojects/internal-testing/src/main/groovy/org/gradle/integtests/fixtures/TestResultOutputAssociation.java
new file mode 100644
index 0000000..39a90a4
--- /dev/null
+++ b/subprojects/internal-testing/src/main/groovy/org/gradle/integtests/fixtures/TestResultOutputAssociation.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests.fixtures;
+
+public enum TestResultOutputAssociation {
+ WITH_SUITE,
+ WITH_TESTCASE
+}
diff --git a/subprojects/internal-testing/src/main/groovy/org/gradle/test/fixtures/archive/ArchiveTestFixture.groovy b/subprojects/internal-testing/src/main/groovy/org/gradle/test/fixtures/archive/ArchiveTestFixture.groovy
new file mode 100644
index 0000000..c6b8b21
--- /dev/null
+++ b/subprojects/internal-testing/src/main/groovy/org/gradle/test/fixtures/archive/ArchiveTestFixture.groovy
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.test.fixtures.archive
+
+import com.google.common.collect.ArrayListMultimap
+import com.google.common.collect.ListMultimap
+import org.hamcrest.Matcher
+
+import static org.hamcrest.MatcherAssert.assertThat
+import static org.hamcrest.Matchers.equalTo
+import static org.hamcrest.Matchers.hasItem
+import static org.junit.Assert.assertEquals
+
+class ArchiveTestFixture {
+ private final ListMultimap<String, String> filesByRelativePath = ArrayListMultimap.create()
+
+ protected void add(String relativePath, String content) {
+ filesByRelativePath.put(relativePath, content)
+ }
+
+ def assertContainsFile(String relativePath, int occurrences = 1) {
+ assertEquals(occurrences, filesByRelativePath.get(relativePath).size())
+ this
+ }
+
+ String content(String relativePath) {
+ List<String> files = filesByRelativePath.get(relativePath)
+ assertEquals(1, files.size())
+ files.get(0)
+ }
+
+ Integer countFiles(String relativePath) {
+ filesByRelativePath.get(relativePath).size()
+ }
+
+ def hasDescendants(String... relativePaths) {
+ assertThat(relativePaths as Set, equalTo(filesByRelativePath.keySet()))
+ def expectedCounts = ArrayListMultimap.create()
+ for (String fileName : relativePaths) {
+ expectedCounts.put(fileName, fileName)
+ }
+ for (String fileName : relativePaths) {
+ assertEquals(expectedCounts.get(fileName).size(), filesByRelativePath.get(fileName).size())
+ }
+ this
+ }
+
+ /**
+ * Asserts that there is exactly one file present with the given path, and that this file has the given content.
+ */
+ def assertFileContent(String relativePath, String fileContent) {
+ assertFileContent(relativePath, equalTo(fileContent))
+ }
+
+ def assertFileContent(String relativePath, Matcher contentMatcher) {
+ assertThat(content(relativePath), contentMatcher)
+ this
+ }
+
+ /**
+ * Asserts that there is a file present with the given path and content.
+ */
+ def assertFilePresent(String relativePath, String fileContent) {
+ assertThat(filesByRelativePath.get(relativePath), hasItem(fileContent))
+ this
+ }
+}
diff --git a/subprojects/internal-testing/src/main/groovy/org/gradle/test/fixtures/archive/JarTestFixture.groovy b/subprojects/internal-testing/src/main/groovy/org/gradle/test/fixtures/archive/JarTestFixture.groovy
new file mode 100644
index 0000000..52ef03b
--- /dev/null
+++ b/subprojects/internal-testing/src/main/groovy/org/gradle/test/fixtures/archive/JarTestFixture.groovy
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.test.fixtures.archive
+
+class JarTestFixture extends ZipTestFixture {
+
+ JarTestFixture(File file) {
+ super(file)
+ }
+
+ /**
+ * Asserts that the given service is defined in this jar file.
+ */
+ def hasService(String serviceName, String serviceImpl) {
+ assertFilePresent("META-INF/services/$serviceName", serviceImpl)
+ }
+}
diff --git a/subprojects/internal-testing/src/main/groovy/org/gradle/test/fixtures/archive/TarTestFixture.groovy b/subprojects/internal-testing/src/main/groovy/org/gradle/test/fixtures/archive/TarTestFixture.groovy
new file mode 100644
index 0000000..55a6f99
--- /dev/null
+++ b/subprojects/internal-testing/src/main/groovy/org/gradle/test/fixtures/archive/TarTestFixture.groovy
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.test.fixtures.archive
+
+import org.apache.tools.tar.TarEntry
+import org.apache.tools.tar.TarInputStream
+import org.gradle.test.fixtures.file.TestFile
+
+class TarTestFixture extends ArchiveTestFixture {
+ private final TestFile tarFile
+
+ public TarTestFixture(TestFile tarFile) {
+ this.tarFile = tarFile
+
+ tarFile.withInputStream { inputStream ->
+ TarInputStream tarInputStream = new TarInputStream(inputStream)
+ for (TarEntry tarEntry = tarInputStream.nextEntry; tarEntry != null; tarEntry = tarInputStream.nextEntry) {
+ if (tarEntry.directory) {
+ continue
+ }
+ ByteArrayOutputStream stream = new ByteArrayOutputStream()
+ tarInputStream.copyEntryContents(stream)
+ add(tarEntry.name, new String(stream.toByteArray(), "utf-8"))
+ }
+ }
+ }
+}
diff --git a/subprojects/internal-testing/src/main/groovy/org/gradle/test/fixtures/archive/ZipTestFixture.groovy b/subprojects/internal-testing/src/main/groovy/org/gradle/test/fixtures/archive/ZipTestFixture.groovy
new file mode 100644
index 0000000..71a5ca9
--- /dev/null
+++ b/subprojects/internal-testing/src/main/groovy/org/gradle/test/fixtures/archive/ZipTestFixture.groovy
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.test.fixtures.archive
+
+import java.util.zip.ZipFile
+
+class ZipTestFixture extends ArchiveTestFixture {
+ ZipTestFixture(File file) {
+ def zipFile = new ZipFile(file)
+ try {
+ def entries = zipFile.entries()
+ while (entries.hasMoreElements()) {
+ def entry = entries.nextElement()
+ def content = zipFile.getInputStream(entry).text
+ if (!entry.directory) {
+ add(entry.name, content)
+ }
+ }
+ } finally {
+ zipFile.close();
+ }
+ }
+}
diff --git a/subprojects/internal-testing/src/main/groovy/org/gradle/test/fixtures/encoding/Identifier.java b/subprojects/internal-testing/src/main/groovy/org/gradle/test/fixtures/encoding/Identifier.java
new file mode 100644
index 0000000..a781534
--- /dev/null
+++ b/subprojects/internal-testing/src/main/groovy/org/gradle/test/fixtures/encoding/Identifier.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.test.fixtures.encoding;
+
+import org.gradle.internal.os.OperatingSystem;
+
+public class Identifier {
+ private static final String PUNCTUATION_CHARS = "-'!@#$%^&*()_+=,.?{}[]<>";
+ private static final String NON_ASCII_CHARS = "-√æず∫ʙぴ₦ガき∆ç√∫";
+ private static final String FILESYSTEM_RESERVED_CHARS = "-./\\?%*:|\"<>";
+ private static final String XML_MARKUP_CHARS = "-<with>some<xml-markup/></with>";
+
+ private final String suffix;
+
+ public Identifier(String suffix) {
+ this.suffix = suffix == null ? "" : suffix;
+ }
+
+ public Identifier withPunctuation() {
+ return new Identifier(suffix + PUNCTUATION_CHARS);
+ }
+
+ public Identifier withNonAscii() {
+ return new Identifier(suffix + NON_ASCII_CHARS);
+ }
+
+ public Identifier withReservedFileSystemChars() {
+ return new Identifier(suffix + FILESYSTEM_RESERVED_CHARS);
+ }
+
+ public Identifier withMarkup() {
+ return new Identifier(suffix + XML_MARKUP_CHARS);
+ }
+
+ public Identifier withWhiteSpace() {
+ return new Identifier(suffix + " with white space");
+ }
+
+ public Identifier safeForFileName() {
+ return without(getUnsupportedFileNameCharacters());
+ }
+
+ public Identifier without(String toRemove) {
+ String newSuffix = suffix;
+ for (char c : toRemove.toCharArray()) {
+ newSuffix = newSuffix.replace(c, '-');
+ }
+ return new Identifier(newSuffix);
+ }
+
+ private static String getUnsupportedFileNameCharacters() {
+ if (OperatingSystem.current().isWindows()) {
+ return "<>:\"/\\|?*";
+ }
+ return "/\\";
+ }
+
+ public String decorate(String prefix) {
+ return prefix + suffix;
+ }
+
+ @Override
+ public String toString() {
+ return suffix;
+ }
+
+ public static Identifier getPunctuation() {
+ return new Identifier("").withPunctuation();
+ }
+
+ public static Identifier getNonAscii() {
+ return new Identifier("").withNonAscii();
+ }
+
+ public static Identifier getFileSystemReserved() {
+ return new Identifier("").withReservedFileSystemChars();
+ }
+
+ public static Identifier getXmlMarkup() {
+ return new Identifier("").withMarkup();
+ }
+
+ public static Identifier getWhiteSpace() {
+ return new Identifier("").withWhiteSpace();
+ }
+}
diff --git a/subprojects/internal-testing/src/main/groovy/org/gradle/test/fixtures/file/ExecOutput.groovy b/subprojects/internal-testing/src/main/groovy/org/gradle/test/fixtures/file/ExecOutput.groovy
new file mode 100644
index 0000000..2b1c77d
--- /dev/null
+++ b/subprojects/internal-testing/src/main/groovy/org/gradle/test/fixtures/file/ExecOutput.groovy
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.test.fixtures.file
+
+class ExecOutput {
+ ExecOutput(String rawOutput, String error) {
+ this.rawOutput = rawOutput
+ this.out = rawOutput.replaceAll("\r\n|\r", "\n")
+ this.error = error
+ }
+
+ String rawOutput
+ String out
+ String error
+}
diff --git a/subprojects/internal-testing/src/main/groovy/org/gradle/test/fixtures/file/TestFile.java b/subprojects/internal-testing/src/main/groovy/org/gradle/test/fixtures/file/TestFile.java
index 13c3b34..d6ee06a 100644
--- a/subprojects/internal-testing/src/main/groovy/org/gradle/test/fixtures/file/TestFile.java
+++ b/subprojects/internal-testing/src/main/groovy/org/gradle/test/fixtures/file/TestFile.java
@@ -101,6 +101,10 @@ public class TestFile extends File {
return files;
}
+ public TestFile withExtension(String extension) {
+ return getParentFile().file(getName().replaceAll("\\..*$", "." + extension));
+ }
+
public TestFile writelns(String... lines) {
return writelns(Arrays.asList(lines));
}
@@ -539,8 +543,12 @@ public class TestFile extends File {
}
}
- public Map<String, ?> exec(Object... args) {
- return new TestFileHelper(this).exec(args);
+ public ExecOutput exec(Object... args) {
+ return new TestFileHelper(this).execute(Arrays.asList(args), null);
+ }
+
+ public ExecOutput execute(List args, List env) {
+ return new TestFileHelper(this).execute(args, env);
}
public class Snapshot {
diff --git a/subprojects/internal-testing/src/main/groovy/org/gradle/test/fixtures/file/TestFileHelper.groovy b/subprojects/internal-testing/src/main/groovy/org/gradle/test/fixtures/file/TestFileHelper.groovy
index 1f09902..eff2077 100755
--- a/subprojects/internal-testing/src/main/groovy/org/gradle/test/fixtures/file/TestFileHelper.groovy
+++ b/subprojects/internal-testing/src/main/groovy/org/gradle/test/fixtures/file/TestFileHelper.groovy
@@ -173,14 +173,18 @@ class TestFileHelper {
return process.inputStream.text.trim()
}
- Map<String, ?> exec(Object... args) {
- def process = ([file.absolutePath] + (args as List)).execute()
- def output = process.inputStream.text
- def error = process.errorStream.text
+ ExecOutput exec(List args) {
+ return execute(args, null)
+ }
+
+ ExecOutput execute(List args, List env) {
+ def process = ([file.absolutePath] + args).execute(env, null)
+ String output = process.inputStream.text
+ String error = process.errorStream.text
if (process.waitFor() != 0) {
throw new RuntimeException("Could not execute $file. Error: $error, Output: $output")
}
- return [out: output, error: error]
+ return new ExecOutput(output, error)
}
public void zipTo(TestFile zipFile, boolean nativeTools) {
diff --git a/subprojects/internal-testing/src/main/groovy/org/gradle/test/fixtures/file/WorkspaceTest.groovy b/subprojects/internal-testing/src/main/groovy/org/gradle/test/fixtures/file/WorkspaceTest.groovy
new file mode 100644
index 0000000..50061dc
--- /dev/null
+++ b/subprojects/internal-testing/src/main/groovy/org/gradle/test/fixtures/file/WorkspaceTest.groovy
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.test.fixtures.file
+
+import org.junit.Rule
+import spock.lang.Specification
+
+class WorkspaceTest extends Specification {
+
+ @Rule final TestNameTestDirectoryProvider temporaryFolder = new TestNameTestDirectoryProvider()
+
+ TestFile getTestDirectory() {
+ temporaryFolder.testDirectory
+ }
+
+ TestFile file(Object... path) {
+ getTestDirectory().file(path)
+ }
+
+}
diff --git a/subprojects/internal-testing/src/main/groovy/org/gradle/testing/internal/util/Network.groovy b/subprojects/internal-testing/src/main/groovy/org/gradle/testing/internal/util/Network.groovy
deleted file mode 100644
index 3475ac1..0000000
--- a/subprojects/internal-testing/src/main/groovy/org/gradle/testing/internal/util/Network.groovy
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.testing.internal.util
-
-class Network {
-
- static boolean isOffline() {
- try {
- new URL("http://google.com").openConnection().openStream()
- false
- } catch (IOException) {
- true
- }
- }
-}
diff --git a/subprojects/internal-testing/src/main/groovy/org/gradle/util/Assertions.groovy b/subprojects/internal-testing/src/main/groovy/org/gradle/util/Assertions.groovy
index 3019184..c27fa81 100644
--- a/subprojects/internal-testing/src/main/groovy/org/gradle/util/Assertions.groovy
+++ b/subprojects/internal-testing/src/main/groovy/org/gradle/util/Assertions.groovy
@@ -16,9 +16,6 @@
package org.gradle.util;
-/**
- * by Szczepan Faber, created at: 12/18/12
- */
class Assertions {
private final Object source
diff --git a/subprojects/internal-testing/src/main/groovy/org/gradle/util/JUnit4GroovyMockery.java b/subprojects/internal-testing/src/main/groovy/org/gradle/util/JUnit4GroovyMockery.java
index 0adf6f3..1a8212e 100644
--- a/subprojects/internal-testing/src/main/groovy/org/gradle/util/JUnit4GroovyMockery.java
+++ b/subprojects/internal-testing/src/main/groovy/org/gradle/util/JUnit4GroovyMockery.java
@@ -16,9 +16,6 @@
package org.gradle.util;
-/**
- * @author Hans Dockter
- */
import groovy.lang.Closure;
import org.codehaus.groovy.runtime.InvokerInvocationException;
diff --git a/subprojects/internal-testing/src/main/groovy/org/gradle/util/ReflectionEqualsMatcher.java b/subprojects/internal-testing/src/main/groovy/org/gradle/util/ReflectionEqualsMatcher.java
index db84653..66bd065 100644
--- a/subprojects/internal-testing/src/main/groovy/org/gradle/util/ReflectionEqualsMatcher.java
+++ b/subprojects/internal-testing/src/main/groovy/org/gradle/util/ReflectionEqualsMatcher.java
@@ -19,9 +19,6 @@ import org.apache.commons.lang.builder.EqualsBuilder;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
-/**
- * @author Hans Dockter
-*/
public class ReflectionEqualsMatcher<T> extends BaseMatcher<T> {
private T toMatch;
diff --git a/subprojects/internal-testing/src/main/groovy/org/gradle/util/Resources.java b/subprojects/internal-testing/src/main/groovy/org/gradle/util/Resources.java
index 774560e..c5e9db2 100755
--- a/subprojects/internal-testing/src/main/groovy/org/gradle/util/Resources.java
+++ b/subprojects/internal-testing/src/main/groovy/org/gradle/util/Resources.java
@@ -53,7 +53,7 @@ public class Resources implements MethodRule {
if (resource == null) {
return null;
}
- assertEquals("file", resource.getProtocol());
+ assertEquals(String.format("Cannot handle resource URI %s", resource), "file", resource.getProtocol());
File file;
try {
file = new File(resource.toURI());
diff --git a/subprojects/internal-testing/src/main/groovy/org/gradle/util/TestClassLoader.groovy b/subprojects/internal-testing/src/main/groovy/org/gradle/util/TestClassLoader.groovy
new file mode 100644
index 0000000..fb76246
--- /dev/null
+++ b/subprojects/internal-testing/src/main/groovy/org/gradle/util/TestClassLoader.groovy
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.util
+
+/**
+ * A custom ClassLoader implementation. Used in various places to test that we work with things that are not a
+ * URLClassLoader.
+ */
+class TestClassLoader extends ClassLoader {
+ private final List<File> classpath
+
+ TestClassLoader(ClassLoader classLoader, List<File> classpath) {
+ super(classLoader)
+ this.classpath = classpath
+ }
+
+ @Override
+ protected URL findResource(String name) {
+ for (File file : classpath) {
+ if (file.directory) {
+ def classFile = new File(file, name)
+ if (classFile.exists()) {
+ return classFile.toURI().toURL()
+ }
+ } else if (file.isFile()) {
+ def url = new URL("jar:${file.toURI().toURL()}!/${name}")
+ try {
+ url.openStream().close()
+ return url
+ } catch (FileNotFoundException) {
+ // Ignore
+ }
+ }
+ }
+ return null
+ }
+
+ @Override
+ protected Class<?> findClass(String name) throws ClassNotFoundException {
+ String resource = name.replace('.', '/') + '.class'
+ URL url = findResource(resource)
+ if (url == null) {
+ throw new ClassNotFoundException("Could not find class '${name}'")
+ }
+ def byteCode = url.bytes
+ return defineClass(name, byteCode, 0, byteCode.length)
+ }
+}
diff --git a/subprojects/internal-testing/src/main/groovy/org/gradle/util/TestPrecondition.groovy b/subprojects/internal-testing/src/main/groovy/org/gradle/util/TestPrecondition.groovy
index 56fbc3a..aa5345f 100755
--- a/subprojects/internal-testing/src/main/groovy/org/gradle/util/TestPrecondition.groovy
+++ b/subprojects/internal-testing/src/main/groovy/org/gradle/util/TestPrecondition.groovy
@@ -69,6 +69,9 @@ enum TestPrecondition {
LINUX({
OperatingSystem.current().linux
}),
+ NOT_LINUX({
+ !LINUX.fulfilled
+ }),
UNIX({
OperatingSystem.current().unix
}),
@@ -93,12 +96,19 @@ enum TestPrecondition {
NOT_JDK7({
!JDK7.fulfilled
}),
- CAN_RESOLVE_UNICODE_POM({
- // Ivy parsing Maven POM files with unicode characters is broken in JDK1.6 on Linux (& Unknown OS)
- !(JDK6.fulfilled && (LINUX.fulfilled || UNKNOWN_OS.fulfilled))
- }),
JDK7_POSIX({
JDK7.fulfilled && NOT_WINDOWS.fulfilled
+ }),
+ ONLINE({
+ try {
+ new URL("http://google.com").openConnection().openStream()
+ true
+ } catch (IOException) {
+ false
+ }
+ }),
+ CAN_INSTALL_EXECUTABLE({
+ FILE_PERMISSIONS.fulfilled || WINDOWS.fulfilled
});
/**
diff --git a/subprojects/internal-testing/src/test/groovy/org/gradle/util/AssertionsTest.groovy b/subprojects/internal-testing/src/test/groovy/org/gradle/util/AssertionsTest.groovy
index a85c621..99aa43c 100644
--- a/subprojects/internal-testing/src/test/groovy/org/gradle/util/AssertionsTest.groovy
+++ b/subprojects/internal-testing/src/test/groovy/org/gradle/util/AssertionsTest.groovy
@@ -20,9 +20,6 @@ import spock.lang.Specification
import static org.gradle.util.Assertions.assertThat
-/**
- * by Szczepan Faber, created at: 12/18/12
- */
class AssertionsTest extends Specification {
static class Foo {
diff --git a/subprojects/internal-testing/src/test/groovy/org/gradle/util/TempDirIsUniquePerTestSpec.groovy b/subprojects/internal-testing/src/test/groovy/org/gradle/util/TempDirIsUniquePerTestSpec.groovy
index 5885d21..7f9bf4e 100644
--- a/subprojects/internal-testing/src/test/groovy/org/gradle/util/TempDirIsUniquePerTestSpec.groovy
+++ b/subprojects/internal-testing/src/test/groovy/org/gradle/util/TempDirIsUniquePerTestSpec.groovy
@@ -19,9 +19,6 @@ import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
import org.junit.Rule
import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 3/14/12
- */
class TempDirIsUniquePerTestSpec extends Specification {
@Rule TestNameTestDirectoryProvider temp = new TestNameTestDirectoryProvider()
diff --git a/subprojects/ivy/ivy.gradle b/subprojects/ivy/ivy.gradle
index 197b993..3a118e1 100644
--- a/subprojects/ivy/ivy.gradle
+++ b/subprojects/ivy/ivy.gradle
@@ -17,11 +17,11 @@
dependencies {
- groovy libraries.groovy
compile project(':core'),
project(':publish'),
project(':plugins') // for base plugin to get archives conf
+ testCompile libraries.groovy
integTestCompile project(":ear")
}
diff --git a/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishArtifactCustomisationIntegTest.groovy b/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishArtifactCustomisationIntegTest.groovy
deleted file mode 100644
index f1b645c..0000000
--- a/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishArtifactCustomisationIntegTest.groovy
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
- * Copyright 2013 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.publish.ivy
-
-import org.gradle.test.fixtures.ivy.IvyDescriptorArtifact
-
-class IvyPublishArtifactCustomisationIntegTest extends AbstractIvyPublishIntegTest {
-
- def module = ivyRepo.module("org.gradle.test", "ivyPublish", "2.4")
-
- public void "can publish custom artifacts"() {
- given:
- createBuildScripts("""
- publications {
- ivy(IvyPublication) {
- artifact "customFile.txt"
- artifact customDocsTask.outputFile
- artifact customJar
- }
- }
-""", """
- publishing {
- publishIvyPublicationToIvyRepository.dependsOn(customDocsTask)
- }
-""")
-
- when:
- succeeds 'publish'
-
- then:
- module.assertPublished()
- module.assertArtifactsPublished("ivy-2.4.xml", "ivyPublish-2.4.txt", "ivyPublish-2.4.html", "ivyPublish-2.4.jar")
-
- and:
- def ivy = module.ivy
- ivy.expectArtifact('ivyPublish', 'txt').hasType("txt").hasConf(null)
- ivy.expectArtifact('ivyPublish', 'html').hasType("html").hasConf(null)
- ivy.expectArtifact('ivyPublish', 'jar').hasType("jar").hasConf(null)
-
- and:
- resolveArtifacts(module) == ["ivyPublish-2.4.html", "ivyPublish-2.4.jar", "ivyPublish-2.4.txt"]
- }
-
- def "can configure custom artifacts when creating"() {
- given:
- createBuildScripts("""
- publications {
- ivy(IvyPublication) {
- configurations {
- foo
- bar
- "default" {
- extend "foo"
- }
- }
- artifact("customFile.txt") {
- name "customFile"
- classifier "classified"
- conf "foo,bar"
- }
- artifact(customDocsTask.outputFile) {
- name "docs"
- extension "htm"
- builtBy customDocsTask
- }
- artifact(customJar) {
- extension "war"
- type "web-archive"
- conf "*"
- }
- }
- }
-""")
- when:
- succeeds 'publish'
-
- then:
- module.assertPublished()
- module.assertArtifactsPublished("ivy-2.4.xml", "docs-2.4.htm", "customFile-2.4-classified.txt", "ivyPublish-2.4.war")
-
- and:
- def ivy = module.ivy
- ivy.expectArtifact("ivyPublish", "war").hasType("web-archive").hasConf(["*"])
- ivy.expectArtifact("docs", "htm").hasType("html").hasConf(null)
- ivy.expectArtifact("customFile", "txt", "classified").hasType("txt").hasConf(["foo", "bar"])
-
- and:
- resolveArtifacts(module) == ["customFile-2.4-classified.txt", "docs-2.4.htm", "ivyPublish-2.4.war"]
- }
-
- def "can publish custom file artifacts with map notation"() {
- given:
- createBuildScripts("""
- publications {
- ivy(IvyPublication) {
- configurations {
- foo
- bar
- "default" {
- extend "foo"
- }
- }
- artifact source: "customFile.txt", name: "customFile", classifier: "classified", conf: "foo,bar"
- artifact source: customDocsTask.outputFile, name: "docs", extension: "htm", builtBy: customDocsTask
- artifact source: customJar, extension: "war", type: "web-archive", conf: "*"
- }
- }
-""")
- when:
- succeeds 'publish'
-
- then:
- module.assertPublished()
- module.assertArtifactsPublished("ivy-2.4.xml", "docs-2.4.htm", "customFile-2.4-classified.txt", "ivyPublish-2.4.war")
-
- and:
- def ivy = module.ivy
- ivy.expectArtifact("ivyPublish", "war").hasType("web-archive").hasConf(["*"])
- ivy.expectArtifact("docs", "htm").hasType("html").hasConf(null)
- ivy.expectArtifact("customFile", "txt", "classified").hasType("txt").hasConf(["foo", "bar"])
-
- and:
- resolveArtifacts(module) == ["customFile-2.4-classified.txt", "docs-2.4.htm", "ivyPublish-2.4.war"]
- }
-
- def "can set custom artifacts to override component artifacts"() {
- given:
- createBuildScripts("""
- publications {
- ivy(IvyPublication) {
- from components.java
- artifacts = ["customFile.txt", customDocsTask.outputFile, customJar]
- }
- }
-""", """
- publishing {
- publishIvyPublicationToIvyRepository.dependsOn(customDocsTask)
- }
-""")
- when:
- succeeds 'publish'
-
- then:
- module.assertPublished()
- module.assertArtifactsPublished("ivy-2.4.xml", "ivyPublish-2.4.txt", "ivyPublish-2.4.html", "ivyPublish-2.4.jar")
- module.ivy.artifacts.collect({"${it.name}.${it.ext}"}) as Set == ["ivyPublish.txt", "ivyPublish.html", "ivyPublish.jar"] as Set
- }
-
- def "can configure custom artifacts post creation"() {
- given:
- createBuildScripts("""
- publications {
- ivy(IvyPublication) {
- configurations {
- mod_conf {}
- other {}
- }
- artifact source: "customFile.txt", name: "customFile"
- artifact source: customDocsTask.outputFile, name: "docs", builtBy: customDocsTask
- artifact source: customJar
- }
- }
-""", """
- publishing.publications.ivy.artifacts.each {
- it.extension = "mod"
- it.conf = "mod_conf"
- }
-""")
- when:
- succeeds 'publish'
-
- then:
- module.assertPublished()
- module.assertArtifactsPublished("ivy-2.4.xml", "customFile-2.4.mod", "docs-2.4.mod", "ivyPublish-2.4.mod")
-
- for (IvyDescriptorArtifact artifact : module.ivy.artifacts) {
- artifact.ext == "mod"
- artifact.conf == "mod-conf"
- }
- }
-
- def "can publish artifact with no extension"() {
- given:
- file("no-extension") << "some content"
- createBuildScripts("""
- publications {
- ivy(IvyPublication) {
- artifact source: 'no-extension', name: 'no-extension', type: 'ext-less'
- }
- }
-""")
- when:
- succeeds 'publish'
-
- then:
- module.assertPublished()
- module.assertArtifactsPublished("ivy-2.4.xml", "no-extension-2.4")
- module.ivy.expectArtifact("no-extension").hasAttributes("", "ext-less", null)
-
- // TODO:DAZ Fix publication with empty extension so it can be resolved
-// and:
-// resolveArtifacts(module) == ["no-extension-2.4"]
- }
-
- def "can publish artifact with classifier"() {
- given:
- createBuildScripts("""
- publications {
- ivy(IvyPublication) {
- artifact source: customJar, classifier: "classy"
- }
- }
-""")
- when:
- succeeds 'publish'
-
- then:
- module.assertPublished()
- module.assertArtifactsPublished("ivy-2.4.xml", "ivyPublish-2.4-classy.jar")
- module.ivy.expectArtifact("ivyPublish").hasAttributes("jar", "jar", null, "classy")
-
- and:
- resolveArtifacts(module) == ["ivyPublish-2.4-classy.jar"]
- }
-
- def "can add custom configurations"() {
- given:
- createBuildScripts("""
- publications {
- ivy(IvyPublication) {
- configurations {
- runtime
- base {}
- custom {
- extend "runtime"
- extend "base"
- }
- }
- }
- }
-""")
-
- when:
- succeeds 'publish'
-
- then:
- module.assertPublished()
- def ivy = module.ivy
- ivy.configurations.keySet() == ["base", "custom", "runtime"] as Set
- ivy.configurations["runtime"].extend == null
- ivy.configurations["base"].extend == null
- ivy.configurations["custom"].extend == ["runtime", "base"] as Set
- }
-
- def "reports failure publishing when validation fails"() {
- given:
- file("a-directory.dir").createDir()
-
- createBuildScripts("""
- publications {
- ivy(IvyPublication) {
- artifact "a-directory.dir"
- }
- }
-""")
- when:
- fails 'publish'
-
- then:
- failure.assertHasDescription("Execution failed for task ':publishIvyPublicationToIvyRepository'.")
- failure.assertHasCause("Failed to publish publication 'ivy' to repository 'ivy'")
- failure.assertHasCause("Invalid publication 'ivy': artifact file is a directory")
- }
-
- private createBuildScripts(def publications, def append = "") {
- file("customFile.txt") << "some content"
- settingsFile << "rootProject.name = 'ivyPublish'"
- buildFile << """
- apply plugin: 'java'
- apply plugin: 'ivy-publish'
-
- group = 'org.gradle.test'
- version = '2.4'
-
- task customDocsTask {
- ext.outputFile = file('customDocs.html')
- doLast {
- outputFile << '<html/>'
- }
- }
-
- task customJar(type: Jar) {
- from file("customFile.txt")
- baseName "customJar"
- }
-
- publishing {
- repositories {
- ivy { url "${ivyRepo.uri}" }
- }
- $publications
- }
-
- $append
- """
- }
-}
diff --git a/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishArtifactCustomizationIntegTest.groovy b/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishArtifactCustomizationIntegTest.groovy
new file mode 100644
index 0000000..384818e
--- /dev/null
+++ b/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishArtifactCustomizationIntegTest.groovy
@@ -0,0 +1,321 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.publish.ivy
+
+import org.gradle.test.fixtures.ivy.IvyDescriptorArtifact
+
+class IvyPublishArtifactCustomizationIntegTest extends AbstractIvyPublishIntegTest {
+
+ def module = ivyRepo.module("org.gradle.test", "ivyPublish", "2.4")
+
+ public void "can publish custom artifacts"() {
+ given:
+ createBuildScripts("""
+ publications {
+ ivy(IvyPublication) {
+ artifact "customFile.txt"
+ artifact customDocsTask.outputFile
+ artifact customJar
+ }
+ }
+""", """
+ publishing {
+ publishIvyPublicationToIvyRepository.dependsOn(customDocsTask)
+ }
+""")
+
+ when:
+ succeeds 'publish'
+
+ then:
+ module.assertPublished()
+ module.assertArtifactsPublished("ivy-2.4.xml", "ivyPublish-2.4.txt", "ivyPublish-2.4.html", "ivyPublish-2.4.jar")
+
+ and:
+ def ivy = module.ivy
+ ivy.expectArtifact('ivyPublish', 'txt').hasType("txt").hasConf(null)
+ ivy.expectArtifact('ivyPublish', 'html').hasType("html").hasConf(null)
+ ivy.expectArtifact('ivyPublish', 'jar').hasType("jar").hasConf(null)
+
+ and:
+ resolveArtifacts(module) == ["ivyPublish-2.4.html", "ivyPublish-2.4.jar", "ivyPublish-2.4.txt"]
+ }
+
+ def "can configure custom artifacts when creating"() {
+ given:
+ createBuildScripts("""
+ publications {
+ ivy(IvyPublication) {
+ configurations {
+ foo {}
+ bar {}
+ "default" {
+ extend "foo"
+ }
+ }
+ artifact("customFile.txt") {
+ name "customFile"
+ classifier "classified"
+ conf "foo,bar"
+ }
+ artifact(customDocsTask.outputFile) {
+ name "docs"
+ extension "htm"
+ builtBy customDocsTask
+ }
+ artifact(customJar) {
+ extension "war"
+ type "web-archive"
+ conf "*"
+ }
+ }
+ }
+""")
+ when:
+ succeeds 'publish'
+
+ then:
+ module.assertPublished()
+ module.assertArtifactsPublished("ivy-2.4.xml", "docs-2.4.htm", "customFile-2.4-classified.txt", "ivyPublish-2.4.war")
+
+ and:
+ def ivy = module.ivy
+ ivy.expectArtifact("ivyPublish", "war").hasType("web-archive").hasConf(["*"])
+ ivy.expectArtifact("docs", "htm").hasType("html").hasConf(null)
+ ivy.expectArtifact("customFile", "txt", "classified").hasType("txt").hasConf(["foo", "bar"])
+
+ and:
+ resolveArtifacts(module) == ["customFile-2.4-classified.txt", "docs-2.4.htm", "ivyPublish-2.4.war"]
+ }
+
+ def "can publish custom file artifacts with map notation"() {
+ given:
+ createBuildScripts("""
+ publications {
+ ivy(IvyPublication) {
+ configurations {
+ foo {}
+ bar {}
+ "default" {
+ extend "foo"
+ }
+ }
+ artifact source: "customFile.txt", name: "customFile", classifier: "classified", conf: "foo,bar"
+ artifact source: customDocsTask.outputFile, name: "docs", extension: "htm", builtBy: customDocsTask
+ artifact source: customJar, extension: "war", type: "web-archive", conf: "*"
+ }
+ }
+""")
+ when:
+ succeeds 'publish'
+
+ then:
+ module.assertPublished()
+ module.assertArtifactsPublished("ivy-2.4.xml", "docs-2.4.htm", "customFile-2.4-classified.txt", "ivyPublish-2.4.war")
+
+ and:
+ def ivy = module.ivy
+ ivy.expectArtifact("ivyPublish", "war").hasType("web-archive").hasConf(["*"])
+ ivy.expectArtifact("docs", "htm").hasType("html").hasConf(null)
+ ivy.expectArtifact("customFile", "txt", "classified").hasType("txt").hasConf(["foo", "bar"])
+
+ and:
+ resolveArtifacts(module) == ["customFile-2.4-classified.txt", "docs-2.4.htm", "ivyPublish-2.4.war"]
+ }
+
+ def "can set custom artifacts to override component artifacts"() {
+ given:
+ createBuildScripts("""
+ publications {
+ ivy(IvyPublication) {
+ from components.java
+ artifacts = ["customFile.txt", customDocsTask.outputFile, customJar]
+ }
+ }
+""", """
+ publishing {
+ publishIvyPublicationToIvyRepository.dependsOn(customDocsTask)
+ }
+""")
+ when:
+ succeeds 'publish'
+
+ then:
+ module.assertPublished()
+ module.assertArtifactsPublished("ivy-2.4.xml", "ivyPublish-2.4.txt", "ivyPublish-2.4.html", "ivyPublish-2.4.jar")
+ module.ivy.artifacts.collect({"${it.name}.${it.ext}"}) as Set == ["ivyPublish.txt", "ivyPublish.html", "ivyPublish.jar"] as Set
+ }
+
+ def "can configure custom artifacts post creation"() {
+ given:
+ createBuildScripts("""
+ publications {
+ ivy(IvyPublication) {
+ configurations {
+ mod_conf {}
+ other {}
+ }
+ artifact source: "customFile.txt", name: "customFile"
+ artifact source: customDocsTask.outputFile, name: "docs", builtBy: customDocsTask
+ artifact source: customJar
+ }
+ }
+""", """
+ publishing.publications.ivy.artifacts.each {
+ it.extension = "mod"
+ it.conf = "mod_conf"
+ }
+""")
+ when:
+ succeeds 'publish'
+
+ then:
+ module.assertPublished()
+ module.assertArtifactsPublished("ivy-2.4.xml", "customFile-2.4.mod", "docs-2.4.mod", "ivyPublish-2.4.mod")
+
+ for (IvyDescriptorArtifact artifact : module.ivy.artifacts) {
+ artifact.ext == "mod"
+ artifact.conf == "mod-conf"
+ }
+ }
+
+ def "can publish artifact with no extension"() {
+ given:
+ file("no-extension") << "some content"
+ createBuildScripts("""
+ publications {
+ ivy(IvyPublication) {
+ artifact source: 'no-extension', name: 'no-extension', type: 'ext-less'
+ }
+ }
+""")
+ when:
+ succeeds 'publish'
+
+ then:
+ module.assertPublished()
+ module.assertArtifactsPublished("ivy-2.4.xml", "no-extension-2.4")
+ module.ivy.expectArtifact("no-extension").hasAttributes("", "ext-less", null)
+
+ // TODO:DAZ Fix publication with empty extension so it can be resolved
+// and:
+// resolveArtifacts(module) == ["no-extension-2.4"]
+ }
+
+ def "can publish artifact with classifier"() {
+ given:
+ createBuildScripts("""
+ publications {
+ ivy(IvyPublication) {
+ artifact source: customJar, classifier: "classy"
+ }
+ }
+""")
+ when:
+ succeeds 'publish'
+
+ then:
+ module.assertPublished()
+ module.assertArtifactsPublished("ivy-2.4.xml", "ivyPublish-2.4-classy.jar")
+ module.ivy.expectArtifact("ivyPublish").hasAttributes("jar", "jar", null, "classy")
+
+ and:
+ resolveArtifacts(module) == ["ivyPublish-2.4-classy.jar"]
+ }
+
+ def "can add custom configurations"() {
+ given:
+ createBuildScripts("""
+ publications {
+ ivy(IvyPublication) {
+ configurations {
+ runtime {}
+ base {}
+ custom {
+ extend "runtime"
+ extend "base"
+ }
+ }
+ }
+ }
+""")
+
+ when:
+ succeeds 'publish'
+
+ then:
+ module.assertPublished()
+ def ivy = module.ivy
+ ivy.configurations.keySet() == ["base", "custom", "runtime"] as Set
+ ivy.configurations["runtime"].extend == null
+ ivy.configurations["base"].extend == null
+ ivy.configurations["custom"].extend == ["runtime", "base"] as Set
+ }
+
+ def "reports failure publishing when validation fails"() {
+ given:
+ file("a-directory.dir").createDir()
+
+ createBuildScripts("""
+ publications {
+ ivy(IvyPublication) {
+ artifact "a-directory.dir"
+ }
+ }
+""")
+ when:
+ fails 'publish'
+
+ then:
+ failure.assertHasDescription("Execution failed for task ':publishIvyPublicationToIvyRepository'.")
+ failure.assertHasCause("Failed to publish publication 'ivy' to repository 'ivy'")
+ failure.assertHasCause("Invalid publication 'ivy': artifact file is a directory")
+ }
+
+ private createBuildScripts(def publications, def append = "") {
+ file("customFile.txt") << "some content"
+ settingsFile << "rootProject.name = 'ivyPublish'"
+ buildFile << """
+ apply plugin: 'java'
+ apply plugin: 'ivy-publish'
+
+ group = 'org.gradle.test'
+ version = '2.4'
+
+ task customDocsTask {
+ ext.outputFile = file('customDocs.html')
+ doLast {
+ outputFile << '<html/>'
+ }
+ }
+
+ task customJar(type: Jar) {
+ from file("customFile.txt")
+ baseName "customJar"
+ }
+
+ publishing {
+ repositories {
+ ivy { url "${ivyRepo.uri}" }
+ }
+ $publications
+ }
+
+ $append
+ """
+ }
+}
diff --git a/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishBasicIntegTest.groovy b/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishBasicIntegTest.groovy
index dee5167..116e935 100644
--- a/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishBasicIntegTest.groovy
+++ b/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishBasicIntegTest.groovy
@@ -72,7 +72,7 @@ public class IvyPublishBasicIntegTest extends AbstractIvyPublishIntegTest {
configurations.isEmpty()
artifacts.isEmpty()
dependencies.isEmpty()
- status == "release"
+ status == "integration"
}
and:
@@ -91,7 +91,6 @@ public class IvyPublishBasicIntegTest extends AbstractIvyPublishIntegTest {
group = 'group'
version = '1.0'
- status = 'integration'
publishing {
repositories {
@@ -150,7 +149,7 @@ public class IvyPublishBasicIntegTest extends AbstractIvyPublishIntegTest {
fails 'publish'
then:
- failure.assertHasDescription("A problem occurred configuring the 'publishing' extension")
+ failure.assertHasDescription("A problem occurred configuring root project 'bad-project'.")
failure.assertHasCause("Ivy publication 'ivy' cannot include multiple components")
}
diff --git a/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishCoordinatesIntegTest.groovy b/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishCoordinatesIntegTest.groovy
new file mode 100644
index 0000000..ed730fa
--- /dev/null
+++ b/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishCoordinatesIntegTest.groovy
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.publish.ivy
+
+public class IvyPublishCoordinatesIntegTest extends AbstractIvyPublishIntegTest {
+
+ def "can publish single jar with specified coordinates"() {
+ given:
+ def module = ivyRepo.module('org.custom', 'custom', '2.2')
+
+ and:
+ settingsFile << "rootProject.name = 'root'"
+ buildFile << """
+ apply plugin: 'ivy-publish'
+ apply plugin: 'java'
+
+ group = 'group'
+ version = '1.0'
+
+ publishing {
+ repositories {
+ ivy { url "${ivyRepo.uri}" }
+ }
+ publications {
+ ivy(IvyPublication) {
+ from components.java
+ organisation "org.custom"
+ module "custom"
+ revision "2.2"
+ }
+ }
+ }
+ """
+
+ when:
+ succeeds 'publish'
+
+ then:
+ file('build/libs/root-1.0.jar').assertExists()
+
+ and:
+ module.assertPublishedAsJavaModule()
+ module.moduleDir.file('custom-2.2.jar').assertIsCopyOf(file('build/libs/root-1.0.jar'))
+
+ and:
+ resolveArtifacts(module) == ['custom-2.2.jar']
+ }
+
+ def "can produce multiple separate publications for single project"() {
+ given:
+ def module = ivyRepo.module('org.custom', 'custom', '2.2')
+ def apiModule = ivyRepo.module('org.custom', 'custom-api', '2')
+
+ and:
+ settingsFile << "rootProject.name = 'root'"
+ buildFile << """
+ apply plugin: 'ivy-publish'
+ apply plugin: 'java'
+
+ group = 'group'
+ version = '1.0'
+
+ task apiJar(type: Jar) {
+ from sourceSets.main.output
+ baseName "root-api"
+ exclude "**/impl/**"
+ }
+
+ publishing {
+ repositories {
+ ivy { url "${ivyRepo.uri}" }
+ }
+ publications {
+ ivy(IvyPublication) {
+ organisation "org.custom"
+ module "custom"
+ revision "2.2"
+ from components.java
+ }
+ ivyApi(IvyPublication) {
+ organisation "org.custom"
+ module "custom-api"
+ revision "2"
+ configurations {
+ runtime {}
+ "default" {
+ extend "runtime"
+ }
+ }
+ artifact(apiJar) {
+ conf "runtime"
+ }
+ }
+ }
+ }
+ """
+
+ when:
+ succeeds 'publish'
+
+ then:
+ file('build/libs').assertHasDescendants("root-1.0.jar", "root-api-1.0.jar")
+
+ and:
+ module.assertPublishedAsJavaModule()
+ module.moduleDir.file('custom-2.2.jar').assertIsCopyOf(file('build/libs/root-1.0.jar'))
+
+ and:
+ apiModule.assertPublishedAsJavaModule()
+ apiModule.moduleDir.file('custom-api-2.jar').assertIsCopyOf(file('build/libs/root-api-1.0.jar'))
+
+ and:
+ resolveArtifacts(module) == ['custom-2.2.jar']
+ resolveArtifacts(apiModule) == ['custom-api-2.jar']
+ }
+
+}
diff --git a/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishCrossVersionIntegrationTest.groovy b/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishCrossVersionIntegrationTest.groovy
index 7ae9c64..1a2c2cd 100644
--- a/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishCrossVersionIntegrationTest.groovy
+++ b/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishCrossVersionIntegrationTest.groovy
@@ -31,9 +31,9 @@ class IvyPublishCrossVersionIntegrationTest extends CrossVersionIntegrationSpec
projectPublishedUsingMavenPublishPlugin('java')
expect:
- consumePublicationWithPreviousVersion('')
+ consumePublicationWithPreviousVersion()
- file('build/resolved').assertHasDescendants("published-${publishedVersion}.jar", 'commons-collections-3.0.jar')
+ file('build/resolved').assertHasDescendants("published-1.9.jar", 'test-project-1.2.jar')
}
def "ivy war publication generated by ivy-publish plugin can be consumed by previous versions of Gradle"() {
@@ -41,12 +41,14 @@ class IvyPublishCrossVersionIntegrationTest extends CrossVersionIntegrationSpec
projectPublishedUsingMavenPublishPlugin('web')
expect:
- consumePublicationWithPreviousVersion('@war')
+ consumePublicationWithPreviousVersion()
- file('build/resolved').assertHasDescendants("published-${publishedVersion}.war")
+ file('build/resolved').assertHasDescendants("published-1.9.war")
}
def projectPublishedUsingMavenPublishPlugin(def componentToPublish) {
+ repo.module("org.gradle", "test-project", "1.2").publish()
+
settingsFile.text = "rootProject.name = 'published'"
buildFile.text = """
@@ -54,13 +56,13 @@ apply plugin: 'war'
apply plugin: 'ivy-publish'
group = 'org.gradle.crossversion'
-version = '${publishedVersion}'
+version = '1.9'
repositories {
- mavenCentral()
+ ivy { url "${repo.uri}" }
}
dependencies {
- compile "commons-collections:commons-collections:3.0"
+ compile "org.gradle:test-project:1.2"
}
publishing {
repositories {
@@ -68,7 +70,7 @@ publishing {
}
publications {
ivy(IvyPublication) {
- from components['${componentToPublish}']
+ from components.${componentToPublish}
}
}
}
@@ -77,7 +79,7 @@ publishing {
version current withTasks 'publish' run()
}
- def consumePublicationWithPreviousVersion(def artifact) {
+ def consumePublicationWithPreviousVersion() {
settingsFile.text = "rootProject.name = 'consumer'"
def repositoryDefinition
@@ -106,12 +108,10 @@ configurations {
lib
}
repositories {
- mavenCentral()
-
$repositoryDefinition
}
dependencies {
- lib 'org.gradle.crossversion:published:${publishedVersion}${artifact}'
+ lib 'org.gradle.crossversion:published:1.9'
}
task retrieve(type: Sync) {
into 'build/resolved'
@@ -119,10 +119,6 @@ task retrieve(type: Sync) {
}
"""
- version previous withDeprecationChecksDisabled() withTasks 'retrieve' run()
- }
-
- def getPublishedVersion() {
- "1.9"
+ version previous requireOwnGradleUserHomeDir() withDeprecationChecksDisabled() withTasks 'retrieve' run()
}
}
diff --git a/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishDescriptorCustomisationIntegTest.groovy b/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishDescriptorCustomisationIntegTest.groovy
deleted file mode 100644
index dc59e1e..0000000
--- a/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishDescriptorCustomisationIntegTest.groovy
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.publish.ivy
-
-import org.gradle.integtests.fixtures.AbstractIntegrationSpec
-import org.gradle.test.fixtures.ivy.IvyDescriptor
-
-class IvyPublishDescriptorCustomisationIntegTest extends AbstractIntegrationSpec {
-
- def module = ivyRepo.module("org.gradle", "publish", "2")
-
- def setup() {
- settingsFile << """
- rootProject.name = "${module.module}"
- """
-
- buildFile << """
- apply plugin: 'java'
- apply plugin: 'ivy-publish'
-
- version = '${module.revision}'
- group = '${module.organisation}'
-
- publishing {
- repositories {
- ivy { url "${ivyRepo.uri}" }
- }
- publications {
- ivy(IvyPublication) {
- from components.java
- }
- }
- }
- """
- }
-
- def "can customise descriptor xml during publication"() {
- when:
- succeeds 'publish'
-
- then:
- ":jar" in executedTasks
-
- and:
- module.ivy.revision == "2"
-
- when:
- buildFile << """
- publishing {
- publications {
- ivy {
- descriptor {
- withXml {
- asNode().info[0].appendNode('description', 'Customized descriptor')
- }
- }
- }
- }
- }
- """
- succeeds 'publish'
-
-
- then:
- ":jar" in skippedTasks
-
- and:
- module.ivy.description == "Customized descriptor"
- }
-
- def "can generate ivy.xml without publishing"() {
- given:
- def moduleName = module.module
- buildFile << """
- publishing {
- generateIvyModuleDescriptor {
- destination = 'generated-ivy.xml'
- }
- }
- """
-
- when:
- succeeds 'generateIvyModuleDescriptor'
-
- then:
- file('generated-ivy.xml').assertIsFile()
- IvyDescriptor ivy = new IvyDescriptor(file('generated-ivy.xml'))
- ivy.expectArtifact(moduleName).hasAttributes("jar", "jar", ["runtime"])
- module.ivyFile.assertDoesNotExist()
- }
-
- def "produces sensible error when withXML fails"() {
- when:
- buildFile << """
- publishing {
- publications {
- ivy {
- descriptor.withXml {
- asNode().foo = "3"
- }
- }
- }
- }
- """
- fails 'publish'
-
- then:
- failure.assertHasDescription("Execution failed for task ':generateIvyModuleDescriptor'")
- failure.assertHasCause("Could not apply withXml() to Ivy module descriptor")
- failure.assertHasCause("No such property: foo for class: groovy.util.Node")
- }
-
- def "produces sensible error when withXML modifies publication coordinates"() {
- when:
- buildFile << """
- publishing {
- publications {
- ivy {
- descriptor.withXml {
- asNode().info[0]. at revision = "2.1"
- }
- }
- }
- }
- """
- fails 'publish'
-
- then:
- failure.assertHasDescription("Execution failed for task ':publishIvyPublicationToIvyRepository'")
- failure.assertHasCause("Failed to publish publication 'ivy' to repository 'ivy'")
- failure.assertHasCause("Invalid publication 'ivy': supplied revision does not match ivy descriptor (cannot edit revision directly in the ivy descriptor file).")
- }
-}
diff --git a/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishDescriptorCustomizationIntegTest.groovy b/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishDescriptorCustomizationIntegTest.groovy
new file mode 100644
index 0000000..4a7030f
--- /dev/null
+++ b/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishDescriptorCustomizationIntegTest.groovy
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.publish.ivy
+
+import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+import org.gradle.test.fixtures.ivy.IvyDescriptor
+
+class IvyPublishDescriptorCustomizationIntegTest extends AbstractIntegrationSpec {
+
+ def module = ivyRepo.module("org.gradle", "publish", "2")
+
+ def setup() {
+ settingsFile << """
+ rootProject.name = "${module.module}"
+ """
+
+ buildFile << """
+ apply plugin: 'java'
+ apply plugin: 'ivy-publish'
+
+ version = '${module.revision}'
+ group = '${module.organisation}'
+
+ publishing {
+ repositories {
+ ivy { url "${ivyRepo.uri}" }
+ }
+ publications {
+ ivy(IvyPublication) {
+ from components.java
+ }
+ }
+ }
+ """
+ }
+
+ def "can customize descriptor xml during publication"() {
+ when:
+ succeeds 'publish'
+
+ then:
+ ":jar" in executedTasks
+
+ and:
+ module.ivy.revision == "2"
+
+ when:
+ buildFile << """
+ publishing {
+ publications {
+ ivy {
+ descriptor {
+ status "custom-status"
+ withXml {
+ asNode().info[0].appendNode('description', 'Customized descriptor')
+ }
+ }
+ }
+ }
+ }
+ """
+ succeeds 'publish'
+
+
+ then:
+ ":jar" in skippedTasks
+
+ and:
+ module.ivy.description == "Customized descriptor"
+ module.ivy.status == "custom-status"
+ }
+
+ def "can generate ivy.xml without publishing"() {
+ given:
+ def moduleName = module.module
+ buildFile << """
+ publishing {
+ generateDescriptorFileForIvyPublication {
+ destination = 'generated-ivy.xml'
+ }
+ }
+ """
+
+ when:
+ succeeds 'generateDescriptorFileForIvyPublication'
+
+ then:
+ file('generated-ivy.xml').assertIsFile()
+ IvyDescriptor ivy = new IvyDescriptor(file('generated-ivy.xml'))
+ ivy.expectArtifact(moduleName).hasAttributes("jar", "jar", ["runtime"])
+ module.ivyFile.assertDoesNotExist()
+ }
+
+ def "produces sensible error when withXML fails"() {
+ when:
+ buildFile << """
+ publishing {
+ publications {
+ ivy {
+ descriptor.withXml {
+ asNode().foo = "3"
+ }
+ }
+ }
+ }
+ """
+ fails 'publish'
+
+ then:
+ failure.assertHasDescription("Execution failed for task ':generateDescriptorFileForIvyPublication'.")
+ failure.assertHasCause("Could not apply withXml() to Ivy module descriptor")
+ failure.assertHasCause("No such property: foo for class: groovy.util.Node")
+ }
+
+ def "produces sensible error when withXML modifies publication coordinates"() {
+ when:
+ buildFile << """
+ publishing {
+ publications {
+ ivy {
+ descriptor.withXml {
+ asNode().info[0]. at revision = "2.1"
+ }
+ }
+ }
+ }
+ """
+ fails 'publish'
+
+ then:
+ failure.assertHasDescription("Execution failed for task ':publishIvyPublicationToIvyRepository'.")
+ failure.assertHasCause("Failed to publish publication 'ivy' to repository 'ivy'")
+ failure.assertHasCause("Invalid publication 'ivy': supplied revision does not match ivy descriptor (cannot edit revision directly in the ivy descriptor file).")
+ }
+}
diff --git a/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishHttpIntegTest.groovy b/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishHttpIntegTest.groovy
index 054fd5c..e438628 100644
--- a/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishHttpIntegTest.groovy
+++ b/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishHttpIntegTest.groovy
@@ -20,10 +20,10 @@ import org.gradle.integtests.fixtures.AbstractIntegrationSpec
import org.gradle.integtests.fixtures.executer.ProgressLoggingFixture
import org.gradle.internal.jvm.Jvm
import org.gradle.test.fixtures.file.TestFile
-import org.gradle.test.fixtures.ivy.IvyFileModule
+import org.gradle.test.fixtures.ivy.IvyHttpModule
+import org.gradle.test.fixtures.ivy.IvyHttpRepository
import org.gradle.test.fixtures.server.http.HttpServer
import org.gradle.util.GradleVersion
-import org.gradle.util.TextUtil
import org.hamcrest.Matchers
import org.junit.Rule
import org.mortbay.jetty.HttpStatus
@@ -38,16 +38,15 @@ credentials {
password 'bad'
}
'''
- @Rule
- public final HttpServer server = new HttpServer()
-
@Rule ProgressLoggingFixture progressLogging = new ProgressLoggingFixture(executer, temporaryFolder)
+ @Rule HttpServer server = new HttpServer()
- private IvyFileModule module
+ private IvyHttpModule module
+ private IvyHttpRepository ivyHttpRepo
def setup() {
- module = ivyRepo.module("org.gradle", "publish", "2")
- module.moduleDir.mkdirs()
+ ivyHttpRepo = new IvyHttpRepository(server, ivyRepo)
+ module = ivyHttpRepo.module("org.gradle", "publish", "2")
server.expectUserAgent(matchesNameAndVersion("Gradle", GradleVersion.current().getVersion()))
}
@@ -64,7 +63,7 @@ credentials {
publishing {
repositories {
- ivy { url "http://localhost:${server.port}" }
+ ivy { url "${ivyHttpRepo.uri}" }
}
publications {
ivy(IvyPublication) {
@@ -74,25 +73,24 @@ credentials {
}
"""
- when:
- expectUpload('/org.gradle/publish/2/publish-2.jar', module, module.jarFile, HttpStatus.ORDINAL_200_OK)
- expectUpload('/org.gradle/publish/2/ivy-2.xml', module, module.ivyFile, HttpStatus.ORDINAL_201_Created)
-
and:
+ module.expectJarPut()
+ module.expectJarSha1Put()
+ module.expectIvyPut(HttpStatus.ORDINAL_201_Created)
+ module.expectIvySha1Put(HttpStatus.ORDINAL_201_Created)
+
+ when:
succeeds 'publish'
then:
- module.ivyFile.assertIsFile()
- module.assertChecksumPublishedFor(module.ivyFile)
-
+ module.assertIvyAndJarFilePublished()
module.jarFile.assertIsCopyOf(file('build/libs/publish-2.jar'))
- module.assertChecksumPublishedFor(module.jarFile)
+
and:
- progressLogging.uploadProgressLogged("http://localhost:${server.port}/org.gradle/publish/2/ivy-2.xml")
- progressLogging.uploadProgressLogged("http://localhost:${server.port}/org.gradle/publish/2/publish-2.jar")
+ progressLogging.uploadProgressLogged(module.ivyFileUri)
+ progressLogging.uploadProgressLogged(module.jarFileUri)
}
-
@Unroll
def "can publish to authenticated repository using #authScheme auth"() {
given:
@@ -113,7 +111,7 @@ credentials {
username 'testuser'
password 'password'
}
- url "http://localhost:${server.port}"
+ url "${ivyHttpRepo.uri}"
}
}
publications {
@@ -124,23 +122,23 @@ credentials {
}
"""
- when:
+ and:
server.authenticationScheme = authScheme
- expectUpload('/org.gradle/publish/2/publish-2.jar', module, module.jarFile, 'testuser', 'password')
- expectUpload('/org.gradle/publish/2/ivy-2.xml', module, module.ivyFile, 'testuser', 'password')
+ module.expectJarPut('testuser', 'password')
+ module.expectJarSha1Put('testuser', 'password')
+ module.expectIvyPut('testuser', 'password')
+ module.expectIvySha1Put('testuser', 'password')
- then:
- succeeds 'publish'
+ when:
+ run 'publish'
- and:
- module.ivyFile.assertIsFile()
- module.assertChecksumPublishedFor(module.ivyFile)
+ then:
+ module.assertIvyAndJarFilePublished()
module.jarFile.assertIsCopyOf(file('build/libs/publish-2.jar'))
- module.assertChecksumPublishedFor(module.jarFile)
and:
- progressLogging.uploadProgressLogged("http://localhost:${server.port}/org.gradle/publish/2/ivy-2.xml")
- progressLogging.uploadProgressLogged("http://localhost:${server.port}/org.gradle/publish/2/publish-2.jar")
+ progressLogging.uploadProgressLogged(module.ivyFileUri)
+ progressLogging.uploadProgressLogged(module.jarFileUri)
where:
authScheme << [HttpServer.AuthScheme.BASIC, HttpServer.AuthScheme.DIGEST]
@@ -151,7 +149,7 @@ credentials {
given:
server.start()
- when:
+ and:
settingsFile << 'rootProject.name = "publish"'
buildFile << """
apply plugin: 'java'
@@ -162,7 +160,7 @@ credentials {
repositories {
ivy {
$creds
- url "http://localhost:${server.port}"
+ url "${ivyHttpRepo.uri}"
}
}
publications {
@@ -175,12 +173,12 @@ credentials {
and:
server.authenticationScheme = authScheme
- server.allowPut('/org.gradle/publish/2/publish-2.jar', 'testuser', 'password')
+ server.allowPut('/repo/org.gradle/publish/2/publish-2.jar', 'testuser', 'password')
- then:
+ when:
fails 'publish'
- and:
+ then:
failure.assertHasDescription('Execution failed for task \':publishIvyPublicationToIvyRepository\'.')
failure.assertHasCause('Failed to publish publication \'ivy\' to repository \'ivy\'')
failure.assertThatCause(Matchers.containsString('Received status code 401 from server: Unauthorized'))
@@ -206,7 +204,7 @@ credentials {
publishing {
repositories {
ivy {
- url "${repositoryUrl}"
+ url "${ivyHttpRepo.uri}"
}
}
publications {
@@ -217,13 +215,13 @@ credentials {
}
"""
- when:
+ and:
server.addBroken("/")
- then:
+ when:
fails 'publish'
- and:
+ then:
failure.assertHasDescription('Execution failed for task \':publishIvyPublicationToIvyRepository\'.')
failure.assertHasCause('Failed to publish publication \'ivy\' to repository \'ivy\'')
failure.assertThatCause(Matchers.containsString('Received status code 500 from server: broken'))
@@ -254,9 +252,9 @@ credentials {
publishing {
repositories {
ivy {
- artifactPattern "http://localhost:${server.port}/primary/[module]/[artifact]-[revision].[ext]"
+ artifactPattern "${ivyHttpRepo.artifactPattern}"
artifactPattern "http://localhost:${server.port}/alternative/[module]/[artifact]-[revision].[ext]"
- ivyPattern "http://localhost:${server.port}/primary-ivy/[module]/ivy-[revision].xml"
+ ivyPattern "${ivyHttpRepo.ivyPattern}"
ivyPattern "http://localhost:${server.port}/secondary-ivy/[module]/ivy-[revision].xml"
}
}
@@ -268,22 +266,24 @@ credentials {
}
"""
+ and:
+ module.expectJarPut()
+ module.expectJarSha1Put()
+ module.expectIvyPut()
+ module.expectIvySha1Put()
+
when:
- expectUpload('/primary/publish/publish-2.jar', module, module.jarFile, HttpStatus.ORDINAL_200_OK)
- expectUpload('/primary-ivy/publish/ivy-2.xml', module, module.ivyFile)
+ run 'publish'
then:
- succeeds 'publish'
-
- and:
- module.ivyFile.assertIsFile()
+ module.assertIvyAndJarFilePublished()
module.jarFile.assertIsCopyOf(file('build/libs/publish-2.jar'))
}
public void "can publish large artifact (tools.jar) to authenticated repository"() {
given:
server.start()
- def toolsJar = TextUtil.escapeString(Jvm.current().toolsJar)
+ def toolsJar = Jvm.current().toolsJar
settingsFile << 'rootProject.name = "publish"'
buildFile << """
@@ -299,15 +299,15 @@ credentials {
username 'testuser'
password 'password'
}
- url "http://localhost:${server.port}"
+ url "${ivyHttpRepo.uri}"
}
}
publications {
ivy(IvyPublication) {
configurations {
runtime {
- artifact('$toolsJar') {
- name 'tools'
+ artifact('${toolsJar.toURI()}') {
+ name 'publish'
}
}
}
@@ -316,18 +316,18 @@ credentials {
}
"""
+ and:
+ module.expectJarPut('testuser', 'password')
+ module.expectJarSha1Put('testuser', 'password')
+ module.expectIvyPut('testuser', 'password')
+ module.expectIvySha1Put('testuser', 'password')
+
when:
- def uploadedToolsJar = module.moduleDir.file('toolsJar')
- expectUpload('/org.gradle/publish/2/tools-2.jar', module, uploadedToolsJar, 'testuser', 'password')
- expectUpload('/org.gradle/publish/2/ivy-2.xml', module, module.ivyFile, 'testuser', 'password')
+ run 'publish'
then:
- succeeds 'publish'
-
- and:
module.ivyFile.assertIsFile()
- uploadedToolsJar.assertIsCopyOf(new TestFile(toolsJar));
-
+ module.jarFile.assertIsCopyOf(new TestFile(toolsJar))
}
public void "does not upload meta-data file if artifact upload fails"() {
@@ -345,7 +345,7 @@ credentials {
publishing {
repositories {
ivy {
- url "http://localhost:${server.port}"
+ url "${ivyHttpRepo.uri}"
}
}
publications {
@@ -355,24 +355,15 @@ credentials {
}
}
"""
- when:
- server.expectPut("/org.gradle/publish/2/publish-2.jar", module.jarFile, HttpStatus.ORDINAL_500_Internal_Server_Error)
- then:
+ and:
+ module.expectJarPut(HttpStatus.ORDINAL_500_Internal_Server_Error)
+
+ when:
fails ':publish'
- and:
+ then:
module.jarFile.assertExists()
module.ivyFile.assertDoesNotExist()
}
-
- private void expectUpload(String path, IvyFileModule module, TestFile file, int statusCode = HttpStatus.ORDINAL_200_OK) {
- server.expectPut(path, file, statusCode)
- server.expectPut("${path}.sha1", module.sha1File(file), statusCode)
- }
-
- private void expectUpload(String path, IvyFileModule module, TestFile file, String username, String password) {
- server.expectPut(path, username, password, file)
- server.expectPut("${path}.sha1", username, password, module.sha1File(file))
- }
-}
+}
\ No newline at end of file
diff --git a/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishIdentifierValidationIntegTest.groovy b/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishIdentifierValidationIntegTest.groovy
index 4a7f501..1967e27 100644
--- a/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishIdentifierValidationIntegTest.groovy
+++ b/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishIdentifierValidationIntegTest.groovy
@@ -15,7 +15,7 @@
*/
package org.gradle.api.publish.ivy
-import org.gradle.test.fixtures.publish.Identifier
+import org.gradle.test.fixtures.encoding.Identifier
import spock.lang.Unroll
class IvyPublishIdentifierValidationIntegTest extends AbstractIvyPublishIntegTest {
@@ -147,7 +147,7 @@ class IvyPublishIdentifierValidationIntegTest extends AbstractIvyPublishIntegTes
fails 'publish'
then:
- failure.assertHasDescription "Execution failed for task ':publishIvyPublicationToIvyRepository'"
+ failure.assertHasDescription "Execution failed for task ':publishIvyPublicationToIvyRepository'."
failure.assertHasCause "Failed to publish publication 'ivy' to repository 'ivy'"
failure.assertHasCause "Invalid publication 'ivy': organisation cannot be empty."
}
diff --git a/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishJavaIntegTest.groovy b/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishJavaIntegTest.groovy
index b507d5b..3e1402c 100644
--- a/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishJavaIntegTest.groovy
+++ b/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishJavaIntegTest.groovy
@@ -45,7 +45,6 @@ class IvyPublishJavaIntegTest extends AbstractIvyPublishIntegTest {
expectArtifact("publishTest").hasAttributes("jar", "jar", ["runtime"])
}
- // TODO:DAZ For some reason this doesn't work inside the with block. Investigate.
ivyModule.ivy.assertDependsOn("commons-collections:commons-collections:3.2.1 at runtime", "commons-io:commons-io:1.4 at runtime")
and:
diff --git a/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishMultiProjectIntegTest.groovy b/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishMultiProjectIntegTest.groovy
index 0bb29d9..7d921c8 100644
--- a/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishMultiProjectIntegTest.groovy
+++ b/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishMultiProjectIntegTest.groovy
@@ -41,6 +41,62 @@ class IvyPublishMultiProjectIntegTest extends AbstractIvyPublishIntegTest {
resolveArtifacts(project1) == ['project1-1.0.jar', 'project2-2.0.jar', 'project3-3.0.jar']
}
+ def "project dependencies reference publication identity of dependent project"() {
+ def project3 = ivyRepo.module("changed.org", "changed-module", "changed")
+
+ createBuildScripts("""
+project(":project3") {
+ publishing {
+ publications.ivy {
+ organisation "changed.org"
+ module "changed-module"
+ revision "changed"
+ }
+ }
+}
+""")
+
+ when:
+ run "publish"
+
+ then:
+ project1.assertPublishedAsJavaModule()
+ project1.ivy.assertDependsOn("org.gradle.test:project2:2.0 at runtime", "changed.org:changed-module:changed at runtime")
+
+ project2.assertPublishedAsJavaModule()
+ project2.ivy.assertDependsOn("changed.org:changed-module:changed at runtime")
+
+ project3.assertPublishedAsJavaModule()
+ project3.ivy.dependencies.isEmpty()
+
+ and:
+ resolveArtifacts(project1) == ['changed-module-changed.jar', 'project1-1.0.jar', 'project2-2.0.jar']
+ }
+
+ def "reports failure when project dependency references a project with multiple publications"() {
+ createBuildScripts("""
+project(":project3") {
+ publishing {
+ publications {
+ extraIvy(IvyPublication) {
+ from components.java
+ organisation "extra.org"
+ module "extra-module"
+ revision "extra"
+ }
+ }
+ }
+}
+""")
+
+ when:
+ fails "publish"
+
+ then:
+ failure.assertHasDescription "A problem occurred configuring project ':project1'."
+ failure.assertHasCause "Publishing is not yet able to resolve a dependency on a project with multiple different publications."
+ }
+
def "ivy-publish plugin does not take archivesBaseName into account"() {
createBuildScripts("""
project(":project2") {
diff --git a/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/SamplesIvyPublishIntegrationTest.groovy b/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/SamplesIvyPublishIntegrationTest.groovy
index 45ace6b..65c4869 100644
--- a/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/SamplesIvyPublishIntegrationTest.groovy
+++ b/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/SamplesIvyPublishIntegrationTest.groovy
@@ -16,6 +16,7 @@
package org.gradle.api.publish.ivy
import org.gradle.integtests.fixtures.AbstractIntegrationSpec
import org.gradle.integtests.fixtures.Sample
+import org.gradle.test.fixtures.ivy.IvyFileModule
import org.gradle.util.TextUtil
import org.junit.Rule
@@ -23,6 +24,7 @@ public class SamplesIvyPublishIntegrationTest extends AbstractIntegrationSpec {
@Rule public final Sample quickstart = new Sample(temporaryFolder, "ivy-publish/quickstart")
@Rule public final Sample javaProject = new Sample(temporaryFolder, "ivy-publish/java-multi-project")
@Rule public final Sample customization = new Sample(temporaryFolder, "ivy-publish/descriptor-customization")
+ @Rule public final Sample multiPublish = new Sample(temporaryFolder, "ivy-publish/multiple-publications")
def "quickstart sample"() {
given:
@@ -71,10 +73,6 @@ public class SamplesIvyPublishIntegrationTest extends AbstractIntegrationSpec {
actualIvyXmlText == getExpectedIvyOutput(javaProject.dir.file("output-ivy.xml"))
}
- String getExpectedIvyOutput(def outputFile) {
- outputFile.readLines()[1..-1].join(TextUtil.getPlatformLineSeparator()).trim()
- }
-
def "descriptor-customization sample"() {
given:
sample customization
@@ -90,4 +88,40 @@ public class SamplesIvyPublishIntegrationTest extends AbstractIntegrationSpec {
module.assertPublished()
module.ivy.description == "A demonstration of ivy descriptor customization"
}
+
+ def "multiple-publications sample"() {
+ given:
+ sample multiPublish
+
+ and:
+ def fileRepo = ivy(multiPublish.dir.file("build/repo"))
+ def project1sample = fileRepo.module("org.gradle.sample", "project1-sample", "1.1")
+ def project2api = fileRepo.module("org.gradle.sample", "project2-api", "2")
+ def project2impl = fileRepo.module("org.gradle.sample.impl", "project2-impl", "2.3")
+
+ when:
+ succeeds "publish"
+
+ then:
+ project1sample.assertPublishedAsJavaModule()
+ verifyIvyFile(project1sample, "output/project1.ivy.xml")
+
+ and:
+ project2api.assertPublishedAsJavaModule()
+ verifyIvyFile(project2api, "output/project2-api.ivy.xml")
+
+ and:
+ project2impl.assertPublishedAsJavaModule()
+ verifyIvyFile(project2impl, "output/project2-impl.ivy.xml")
+ }
+
+ private void verifyIvyFile(IvyFileModule project1sample, String outputFileName) {
+ def actualIvyXmlText = project1sample.ivyFile.text.replaceFirst('publication="\\d+"', 'publication="«PUBLICATION-TIME-STAMP»"').trim()
+ assert actualIvyXmlText == getExpectedIvyOutput(multiPublish.dir.file(outputFileName))
+ }
+
+ String getExpectedIvyOutput(File outputFile) {
+ assert outputFile.file
+ outputFile.readLines()[1..-1].join(TextUtil.getPlatformLineSeparator()).trim()
+ }
}
diff --git a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/IvyArtifactSet.java b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/IvyArtifactSet.java
index 170d649..f56860b 100644
--- a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/IvyArtifactSet.java
+++ b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/IvyArtifactSet.java
@@ -27,7 +27,7 @@ import org.gradle.api.Incubating;
* <pre autoTested="true">
* apply plugin: 'ivy-publish'
*
- * def publication = publishing.publications.add("my-pub", IvyPublication)
+ * def publication = publishing.publications.create("my-pub", IvyPublication)
* def artifacts = publication.artifacts
*
* artifacts.matching({
diff --git a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/IvyConfigurationContainer.java b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/IvyConfigurationContainer.java
index af5db87..245b023 100644
--- a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/IvyConfigurationContainer.java
+++ b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/IvyConfigurationContainer.java
@@ -28,7 +28,7 @@ import org.gradle.api.NamedDomainObjectContainer;
* <pre autoTested="true">
* apply plugin: 'ivy-publish'
*
- * def publication = publishing.publications.add("my-pub", IvyPublication)
+ * def publication = publishing.publications.create("my-pub", IvyPublication)
* def configurations = publication.configurations
*
* configurations.create("extended", { extend "default"})
diff --git a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/IvyDependency.java b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/IvyDependency.java
index cfa641c..f1aa84a 100644
--- a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/IvyDependency.java
+++ b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/IvyDependency.java
@@ -27,6 +27,21 @@ import org.gradle.api.internal.HasInternalProtocol;
public interface IvyDependency {
/**
+ * The organisation value for this dependency.
+ */
+ String getOrganisation();
+
+ /**
+ * The module value for this dependency.
+ */
+ String getModule();
+
+ /**
+ * The revision value for this dependency.
+ */
+ String getRevision();
+
+ /**
* The configuration mapping string that will be output for this dependency.
* A null value indicates that no "conf" attribute will be written for this dependency.
*
diff --git a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/IvyModuleDescriptor.java b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/IvyModuleDescriptor.java
index f7022fa..0bf2598 100644
--- a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/IvyModuleDescriptor.java
+++ b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/IvyModuleDescriptor.java
@@ -69,4 +69,14 @@ public interface IvyModuleDescriptor {
*/
void withXml(Action<? super XmlProvider> action);
+ /**
+ * Returns the status for this publication.
+ */
+ String getStatus();
+
+ /**
+ * Sets the status for this publication.
+ */
+ void setStatus(String status);
+
}
diff --git a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/IvyPublication.java b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/IvyPublication.java
index b517987..727d7c2 100644
--- a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/IvyPublication.java
+++ b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/IvyPublication.java
@@ -29,7 +29,9 @@ import org.gradle.api.publish.Publication;
* <pre>
* publishing {
* publications {
- * myPublicationName(IvyPublication)
+ * myPublicationName(IvyPublication) {
+ * // Configure the publication here
+ * }
* }
* }
* </pre>
@@ -148,7 +150,7 @@ public interface IvyPublication extends Publication {
* publications {
* ivy(IvyPublication) {
* configurations {
- * testCompile
+ * testCompile {}
* testRuntime {
* extend "testCompile"
* }
@@ -189,7 +191,7 @@ public interface IvyPublication extends Publication {
* classifier "source"
* }
*
- * task genDocs << {
+ * task genDocs << {
* // Generate 'my-docs-file.htm'
* }
*
@@ -222,7 +224,7 @@ public interface IvyPublication extends Publication {
* classifier "source"
* }
- * task genDocs << {
+ * task genDocs << {
* // Generate 'my-docs-file.htm'
* }
*
@@ -251,7 +253,10 @@ public interface IvyPublication extends Publication {
IvyArtifact artifact(Object source, Action<? super IvyArtifact> config);
/**
- * Clears any previously added artifacts from {@link #getArtifacts} and creates artifacts from the specified sources.
+ * The complete set of artifacts for this publication.
+ *
+ * <p>
+ * Setting this property will clear any previously added artifacts and create artifacts from the specified sources.
* Each supplied source is interpreted as per {@link #artifact(Object)}.
*
* For example, to exclude the dependencies declared by a component and instead use a custom set of artifacts:
@@ -273,14 +278,45 @@ public interface IvyPublication extends Publication {
* }
* </pre>
*
+ * @return the artifacts.
+ */
+ IvyArtifactSet getArtifacts();
+
+ /**
+ * Sets the artifacts for this publication. Each supplied value is interpreted as per {@link #artifact(Object)}.
+ *
* @param sources The set of artifacts for this publication.
*/
void setArtifacts(Iterable<?> sources);
/**
- * Returns the complete set of artifacts for this publication.
- * @return the artifacts.
+ * Returns the organisation for this publication.
*/
- IvyArtifactSet getArtifacts();
+ String getOrganisation();
+
+ /**
+ * Sets the organisation for this publication.
+ */
+ void setOrganisation(String organisation);
+
+ /**
+ * Returns the module for this publication.
+ */
+ String getModule();
+
+ /**
+ * Sets the module for this publication.
+ */
+ void setModule(String module);
+
+ /**
+ * Returns the revision for this publication.
+ */
+ String getRevision();
+
+ /**
+ * Sets the revision for this publication.
+ */
+ void setRevision(String revision);
}
diff --git a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/artifact/DefaultIvyArtifact.java b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/artifact/DefaultIvyArtifact.java
index 8b17fea..d9b1ef1 100644
--- a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/artifact/DefaultIvyArtifact.java
+++ b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/artifact/DefaultIvyArtifact.java
@@ -93,4 +93,9 @@ public class DefaultIvyArtifact implements IvyArtifact {
public TaskDependency getBuildDependencies() {
return buildDependencies;
}
+
+ @Override
+ public String toString() {
+ return String.format("%s %s:%s:%s:%s", getClass().getSimpleName(), getName(), getType(), getExtension(), getClassifier());
+ }
}
diff --git a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/artifact/IvyArtifactNotationParserFactory.java b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/artifact/IvyArtifactNotationParserFactory.java
index 0f99230..efebd28 100644
--- a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/artifact/IvyArtifactNotationParserFactory.java
+++ b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/artifact/IvyArtifactNotationParserFactory.java
@@ -25,6 +25,7 @@ import org.gradle.api.internal.notations.api.UnsupportedNotationException;
import org.gradle.api.internal.notations.parsers.MapKey;
import org.gradle.api.internal.notations.parsers.MapNotationParser;
import org.gradle.api.internal.notations.parsers.TypedNotationParser;
+import org.gradle.api.internal.plugins.DslObject;
import org.gradle.api.publish.ivy.IvyArtifact;
import org.gradle.api.publish.ivy.internal.publisher.IvyPublicationIdentity;
import org.gradle.api.tasks.bundling.AbstractArchiveTask;
@@ -33,18 +34,17 @@ import org.gradle.internal.reflect.Instantiator;
import java.io.File;
import java.util.Collection;
+import java.util.concurrent.Callable;
public class IvyArtifactNotationParserFactory implements Factory<NotationParser<IvyArtifact>> {
private final Instantiator instantiator;
private final FileResolver fileResolver;
- private final String defaultArtifactName;
+ private final IvyPublicationIdentity publicationIdentity;
public IvyArtifactNotationParserFactory(Instantiator instantiator, FileResolver fileResolver, IvyPublicationIdentity publicationIdentity) {
this.instantiator = instantiator;
this.fileResolver = fileResolver;
-
- // TODO - Need to handle name being modified after addition of artifacts, once we have that functionality.
- this.defaultArtifactName = publicationIdentity.getModule();
+ this.publicationIdentity = publicationIdentity;
}
public NotationParser<IvyArtifact> create() {
@@ -71,6 +71,20 @@ public class IvyArtifactNotationParserFactory implements Factory<NotationParser<
return parserBuilder.toComposite();
}
+ private DefaultIvyArtifact createDefaultIvyArtifact(File file, String extension, String type, String classifier) {
+ DefaultIvyArtifact ivyArtifact = instantiator.newInstance(
+ DefaultIvyArtifact.class,
+ file, null, extension, type, classifier
+ );
+ // TODO:DAZ Find a good way to handle this with lazy configuration
+ new DslObject(ivyArtifact).getConventionMapping().map("name", new Callable<String>() {
+ public String call() throws Exception {
+ return publicationIdentity.getModule();
+ }
+ });
+ return ivyArtifact;
+ }
+
private class ArchiveTaskNotationParser extends TypedNotationParser<AbstractArchiveTask, IvyArtifact> {
private ArchiveTaskNotationParser() {
super(AbstractArchiveTask.class);
@@ -78,10 +92,8 @@ public class IvyArtifactNotationParserFactory implements Factory<NotationParser<
@Override
protected IvyArtifact parseType(AbstractArchiveTask archiveTask) {
- DefaultIvyArtifact ivyArtifact = instantiator.newInstance(
- DefaultIvyArtifact.class,
- archiveTask.getArchivePath(), defaultArtifactName, archiveTask.getExtension(), archiveTask.getExtension(), archiveTask.getClassifier()
- );
+ DefaultIvyArtifact ivyArtifact = createDefaultIvyArtifact(
+ archiveTask.getArchivePath(), archiveTask.getExtension(), archiveTask.getExtension(), archiveTask.getClassifier());
ivyArtifact.builtBy(archiveTask);
return ivyArtifact;
}
@@ -94,10 +106,8 @@ public class IvyArtifactNotationParserFactory implements Factory<NotationParser<
@Override
protected IvyArtifact parseType(PublishArtifact publishArtifact) {
- DefaultIvyArtifact ivyArtifact = instantiator.newInstance(
- DefaultIvyArtifact.class,
- publishArtifact.getFile(), defaultArtifactName, publishArtifact.getExtension(), publishArtifact.getType(), publishArtifact.getClassifier()
- );
+ DefaultIvyArtifact ivyArtifact = createDefaultIvyArtifact(
+ publishArtifact.getFile(), publishArtifact.getExtension(), publishArtifact.getType(), publishArtifact.getClassifier());
ivyArtifact.builtBy(publishArtifact.getBuildDependencies());
return ivyArtifact;
}
@@ -117,10 +127,7 @@ public class IvyArtifactNotationParserFactory implements Factory<NotationParser<
protected IvyArtifact parseFile(File file) {
String extension = StringUtils.substringAfterLast(file.getName(), ".");
- return instantiator.newInstance(
- DefaultIvyArtifact.class,
- file, defaultArtifactName, extension, extension, null
- );
+ return createDefaultIvyArtifact(file, extension, extension, null);
}
public void describe(Collection<String> candidateFormats) {
diff --git a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/dependency/DefaultIvyDependency.java b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/dependency/DefaultIvyDependency.java
index 8fcfa5d..e354459 100644
--- a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/dependency/DefaultIvyDependency.java
+++ b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/dependency/DefaultIvyDependency.java
@@ -16,22 +16,48 @@
package org.gradle.api.publish.ivy.internal.dependency;
-import org.gradle.api.artifacts.ModuleDependency;
+import org.gradle.api.artifacts.DependencyArtifact;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
public class DefaultIvyDependency implements IvyDependencyInternal {
- private ModuleDependency dependency;
- private String confMapping;
+ private final String organisation;
+ private final String module;
+ private final String revision;
+ private final String confMapping;
+ private final List<DependencyArtifact> artifacts = new ArrayList<DependencyArtifact>();
- public DefaultIvyDependency(ModuleDependency dependency, String confMapping) {
- this.dependency = dependency;
+ public DefaultIvyDependency(String organisation, String module, String revision, String confMapping) {
+ this.organisation = organisation;
+ this.module = module;
+ this.revision = revision;
this.confMapping = confMapping;
}
- public ModuleDependency getModuleDependency() {
- return dependency;
+ public DefaultIvyDependency(String organisation, String module, String revision, String confMapping, Collection<DependencyArtifact> artifacts) {
+ this(organisation, module, revision, confMapping);
+ this.artifacts.addAll(artifacts);
+ }
+
+ public String getOrganisation() {
+ return organisation;
+ }
+
+ public String getModule() {
+ return module;
+ }
+
+ public String getRevision() {
+ return revision;
}
public String getConfMapping() {
return confMapping;
}
+
+ public Iterable<DependencyArtifact> getArtifacts() {
+ return artifacts;
+ }
}
diff --git a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/dependency/IvyDependencyInternal.java b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/dependency/IvyDependencyInternal.java
index b1a5a48..27af113 100644
--- a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/dependency/IvyDependencyInternal.java
+++ b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/dependency/IvyDependencyInternal.java
@@ -16,9 +16,9 @@
package org.gradle.api.publish.ivy.internal.dependency;
-import org.gradle.api.artifacts.ModuleDependency;
+import org.gradle.api.artifacts.DependencyArtifact;
import org.gradle.api.publish.ivy.IvyDependency;
public interface IvyDependencyInternal extends IvyDependency {
- ModuleDependency getModuleDependency();
+ Iterable<DependencyArtifact> getArtifacts();
}
diff --git a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/plugins/IvyPublicationDynamicDescriptorGenerationTaskCreator.java b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/plugins/IvyPublicationDynamicDescriptorGenerationTaskCreator.java
index d5567c9..f54c7ce 100644
--- a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/plugins/IvyPublicationDynamicDescriptorGenerationTaskCreator.java
+++ b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/plugins/IvyPublicationDynamicDescriptorGenerationTaskCreator.java
@@ -23,6 +23,7 @@ import org.gradle.api.internal.plugins.DslObject;
import org.gradle.api.publish.PublicationContainer;
import org.gradle.api.publish.ivy.internal.publication.IvyPublicationInternal;
import org.gradle.api.publish.ivy.tasks.GenerateIvyDescriptor;
+import org.gradle.api.publish.plugins.PublishingPlugin;
import java.io.File;
import java.util.concurrent.Callable;
@@ -49,8 +50,9 @@ public class IvyPublicationDynamicDescriptorGenerationTaskCreator {
String publicationName = publication.getName();
String descriptorTaskName = calculateDescriptorTaskName(publicationName);
- GenerateIvyDescriptor descriptorTask = project.getTasks().add(descriptorTaskName, GenerateIvyDescriptor.class);
+ GenerateIvyDescriptor descriptorTask = project.getTasks().create(descriptorTaskName, GenerateIvyDescriptor.class);
descriptorTask.setDescription(String.format("Generates the Ivy Module Descriptor XML file for publication '%s'.", publication.getName()));
+ descriptorTask.setGroup(PublishingPlugin.PUBLISH_TASK_GROUP);
descriptorTask.setDescriptor(publication.getDescriptor());
ConventionMapping descriptorTaskConventionMapping = new DslObject(descriptorTask).getConventionMapping();
@@ -64,10 +66,7 @@ public class IvyPublicationDynamicDescriptorGenerationTaskCreator {
}
private String calculateDescriptorTaskName(String publicationName) {
- return String.format(
- "generate%sIvyModuleDescriptor",
- publicationName.toLowerCase().equals("ivy") ? "" : capitalize(publicationName)
- );
+ return String.format("generateDescriptorFileFor%sPublication", capitalize(publicationName));
}
}
diff --git a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/plugins/IvyPublishDynamicTaskCreator.java b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/plugins/IvyPublishDynamicTaskCreator.java
index 119fd8f..47e712a 100644
--- a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/plugins/IvyPublishDynamicTaskCreator.java
+++ b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/plugins/IvyPublishDynamicTaskCreator.java
@@ -25,6 +25,7 @@ import org.gradle.api.artifacts.repositories.IvyArtifactRepository;
import org.gradle.api.publish.PublicationContainer;
import org.gradle.api.publish.ivy.internal.publication.IvyPublicationInternal;
import org.gradle.api.publish.ivy.tasks.PublishToIvyRepository;
+import org.gradle.api.publish.plugins.PublishingPlugin;
import org.gradle.api.tasks.TaskContainer;
import static org.apache.commons.lang.StringUtils.capitalize;
@@ -73,10 +74,10 @@ public class IvyPublishDynamicTaskCreator {
String publishTaskName = calculatePublishTaskName(publicationName, repositoryName);
if (tasks.findByName(publishTaskName) == null) {
- PublishToIvyRepository publishTask = tasks.add(publishTaskName, PublishToIvyRepository.class);
+ PublishToIvyRepository publishTask = tasks.create(publishTaskName, PublishToIvyRepository.class);
publishTask.setPublication(publication);
publishTask.setRepository(repository);
- publishTask.setGroup("publishing");
+ publishTask.setGroup(PublishingPlugin.PUBLISH_TASK_GROUP);
publishTask.setDescription(String.format("Publishes Ivy publication '%s' to Ivy repository '%s'.", publicationName, repositoryName));
publishLifecycleTask.dependsOn(publishTask);
diff --git a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/publication/DefaultIvyModuleDescriptor.java b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/publication/DefaultIvyModuleDescriptor.java
index 3b736eb..60da380 100644
--- a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/publication/DefaultIvyModuleDescriptor.java
+++ b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/publication/DefaultIvyModuleDescriptor.java
@@ -18,6 +18,7 @@ package org.gradle.api.publish.ivy.internal.publication;
import org.gradle.api.Action;
import org.gradle.api.XmlProvider;
+import org.gradle.api.artifacts.Module;
import org.gradle.api.internal.UserCodeAction;
import org.gradle.api.publish.ivy.IvyArtifact;
import org.gradle.api.publish.ivy.IvyConfiguration;
@@ -31,7 +32,7 @@ public class DefaultIvyModuleDescriptor implements IvyModuleDescriptorInternal {
private final ActionBroadcast<XmlProvider> xmlActions = new ActionBroadcast<XmlProvider>();
private final IvyPublicationInternal ivyPublication;
- private String status;
+ private String status = Module.DEFAULT_STATUS;
public DefaultIvyModuleDescriptor(IvyPublicationInternal ivyPublication) {
this.ivyPublication = ivyPublication;
diff --git a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/publication/DefaultIvyPublication.java b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/publication/DefaultIvyPublication.java
index 10967f0..c4be876 100644
--- a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/publication/DefaultIvyPublication.java
+++ b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/publication/DefaultIvyPublication.java
@@ -19,13 +19,17 @@ package org.gradle.api.publish.ivy.internal.publication;
import org.gradle.api.Action;
import org.gradle.api.InvalidUserDataException;
import org.gradle.api.artifacts.ModuleDependency;
+import org.gradle.api.artifacts.ModuleVersionIdentifier;
+import org.gradle.api.artifacts.ProjectDependency;
import org.gradle.api.artifacts.PublishArtifact;
import org.gradle.api.component.SoftwareComponent;
import org.gradle.api.file.FileCollection;
+import org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier;
import org.gradle.api.internal.component.SoftwareComponentInternal;
import org.gradle.api.internal.component.Usage;
import org.gradle.api.internal.file.UnionFileCollection;
import org.gradle.api.internal.notations.api.NotationParser;
+import org.gradle.api.publish.internal.ProjectDependencyPublicationResolver;
import org.gradle.api.publish.ivy.IvyArtifact;
import org.gradle.api.publish.ivy.IvyConfigurationContainer;
import org.gradle.api.publish.ivy.IvyModuleDescriptor;
@@ -98,11 +102,24 @@ public class DefaultIvyPublication implements IvyPublicationInternal {
for (ModuleDependency dependency : usage.getDependencies()) {
// TODO: When we support multiple components or configurable dependencies, we'll need to merge the confs of multiple dependencies with same id.
String confMapping = String.format("%s->%s", conf, dependency.getConfiguration());
- ivyDependencies.add(new DefaultIvyDependency(dependency, confMapping));
+ if (dependency instanceof ProjectDependency) {
+ addProjectDependency((ProjectDependency) dependency, confMapping);
+ } else {
+ addModuleDependency(dependency, confMapping);
+ }
}
}
}
+ private void addProjectDependency(ProjectDependency dependency, String confMapping) {
+ ModuleVersionIdentifier identifier = new ProjectDependencyPublicationResolver().resolve(dependency);
+ ivyDependencies.add(new DefaultIvyDependency(identifier.getGroup(), identifier.getName(), identifier.getVersion(), confMapping));
+ }
+
+ private void addModuleDependency(ModuleDependency dependency, String confMapping) {
+ ivyDependencies.add(new DefaultIvyDependency(dependency.getGroup(), dependency.getName(), dependency.getVersion(), confMapping, dependency.getArtifacts()));
+ }
+
public void configurations(Action<? super IvyConfigurationContainer> config) {
config.execute(configurations);
}
@@ -130,6 +147,30 @@ public class DefaultIvyPublication implements IvyPublicationInternal {
return ivyArtifacts;
}
+ public String getOrganisation() {
+ return publicationIdentity.getOrganisation();
+ }
+
+ public void setOrganisation(String organisation) {
+ publicationIdentity.setOrganisation(organisation);
+ }
+
+ public String getModule() {
+ return publicationIdentity.getModule();
+ }
+
+ public void setModule(String module) {
+ publicationIdentity.setModule(module);
+ }
+
+ public String getRevision() {
+ return publicationIdentity.getRevision();
+ }
+
+ public void setRevision(String revision) {
+ publicationIdentity.setRevision(revision);
+ }
+
public FileCollection getPublishableFiles() {
return new UnionFileCollection(ivyArtifacts.getFiles(), descriptorFile);
}
@@ -153,4 +194,7 @@ public class DefaultIvyPublication implements IvyPublicationInternal {
return descriptorFile.getSingleFile();
}
+ public ModuleVersionIdentifier getCoordinates() {
+ return new DefaultModuleVersionIdentifier(getOrganisation(), getModule(), getRevision());
+ }
}
diff --git a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/publication/IvyModuleDescriptorInternal.java b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/publication/IvyModuleDescriptorInternal.java
index 3279c7b..b075184 100644
--- a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/publication/IvyModuleDescriptorInternal.java
+++ b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/publication/IvyModuleDescriptorInternal.java
@@ -37,8 +37,4 @@ public interface IvyModuleDescriptorInternal extends IvyModuleDescriptor {
Set<IvyDependencyInternal> getDependencies();
Action<XmlProvider> getXmlAction();
-
- String getStatus();
-
- void setStatus(String status);
}
diff --git a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/publication/IvyPublicationInternal.java b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/publication/IvyPublicationInternal.java
index 8552d14..c3e5926 100644
--- a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/publication/IvyPublicationInternal.java
+++ b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/publication/IvyPublicationInternal.java
@@ -17,6 +17,7 @@
package org.gradle.api.publish.ivy.internal.publication;
import org.gradle.api.file.FileCollection;
+import org.gradle.api.publish.internal.PublicationInternal;
import org.gradle.api.publish.ivy.IvyPublication;
import org.gradle.api.publish.ivy.internal.dependency.IvyDependencyInternal;
import org.gradle.api.publish.ivy.internal.publisher.IvyNormalizedPublication;
@@ -24,7 +25,7 @@ import org.gradle.api.publish.ivy.internal.publisher.IvyPublicationIdentity;
import java.util.Set;
-public interface IvyPublicationInternal extends IvyPublication {
+public interface IvyPublicationInternal extends IvyPublication, PublicationInternal {
IvyPublicationIdentity getIdentity();
diff --git a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/publisher/ContextualizingIvyPublisher.java b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/publisher/ContextualizingIvyPublisher.java
new file mode 100644
index 0000000..1af648a
--- /dev/null
+++ b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/publisher/ContextualizingIvyPublisher.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.publish.ivy.internal.publisher;
+
+import org.apache.ivy.Ivy;
+import org.gradle.api.Action;
+import org.gradle.api.internal.artifacts.ivyservice.IvyContextManager;
+import org.gradle.api.internal.artifacts.repositories.PublicationAwareRepository;
+
+public class ContextualizingIvyPublisher implements IvyPublisher {
+ private final IvyPublisher ivyPublisher;
+ private final IvyContextManager ivyContextManager;
+
+ public ContextualizingIvyPublisher(IvyPublisher ivyPublisher, IvyContextManager ivyContextManager) {
+ this.ivyPublisher = ivyPublisher;
+ this.ivyContextManager = ivyContextManager;
+ }
+
+ public void publish(final IvyNormalizedPublication publication, final PublicationAwareRepository repository) {
+ ivyContextManager.withIvy(new Action<Ivy>() {
+ public void execute(Ivy ivy) {
+ ivyPublisher.publish(publication, repository);
+ }
+ });
+ }
+}
diff --git a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/publisher/DependencyResolverIvyPublisher.java b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/publisher/DependencyResolverIvyPublisher.java
index c53c8af..5afab27 100644
--- a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/publisher/DependencyResolverIvyPublisher.java
+++ b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/publisher/DependencyResolverIvyPublisher.java
@@ -18,10 +18,12 @@ package org.gradle.api.publish.ivy.internal.publisher;
import org.apache.ivy.core.module.descriptor.Artifact;
import org.apache.ivy.core.module.descriptor.DefaultArtifact;
+import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor;
import org.apache.ivy.core.module.id.ModuleRevisionId;
-import org.apache.ivy.plugins.resolver.DependencyResolver;
import org.gradle.api.UncheckedIOException;
import org.gradle.api.artifacts.Dependency;
+import org.gradle.api.internal.artifacts.DefaultModuleVersionPublishMetaData;
+import org.gradle.api.internal.artifacts.ModuleVersionPublisher;
import org.gradle.api.internal.artifacts.ivyservice.IvyUtil;
import org.gradle.api.internal.artifacts.repositories.PublicationAwareRepository;
import org.gradle.api.publish.ivy.IvyArtifact;
@@ -29,26 +31,30 @@ import org.gradle.util.GUtil;
import java.io.IOException;
import java.util.Collections;
+import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class DependencyResolverIvyPublisher implements IvyPublisher {
public void publish(IvyNormalizedPublication publication, PublicationAwareRepository repository) {
- DependencyResolver dependencyResolver = repository.createPublisher();
+ ModuleVersionPublisher publisher = repository.createPublisher();
IvyPublicationIdentity projectIdentity = publication.getProjectIdentity();
Map<String, String> extraAttributes = Collections.emptyMap();
ModuleRevisionId moduleRevisionId = IvyUtil.createModuleRevisionId(projectIdentity.getOrganisation(), projectIdentity.getModule(), projectIdentity.getRevision(), extraAttributes);
+ DefaultModuleDescriptor moduleDescriptor = new DefaultModuleDescriptor(moduleRevisionId, "integration", new Date());
+ DefaultModuleVersionPublishMetaData publishMetaData = new DefaultModuleVersionPublishMetaData(moduleDescriptor);
try {
-
for (IvyArtifact publishArtifact : publication.getArtifacts()) {
Artifact ivyArtifact = createIvyArtifact(publishArtifact, moduleRevisionId);
- dependencyResolver.publish(ivyArtifact, publishArtifact.getFile(), true);
+ publishMetaData.addArtifact(ivyArtifact, publishArtifact.getFile());
}
Artifact artifact = DefaultArtifact.newIvyArtifact(moduleRevisionId, null);
- dependencyResolver.publish(artifact, publication.getDescriptorFile(), true);
+ publishMetaData.addArtifact(artifact, publication.getDescriptorFile());
+
+ publisher.publish(publishMetaData);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
diff --git a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/publisher/IvyDescriptorFileGenerator.java b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/publisher/IvyDescriptorFileGenerator.java
index 277066b..8207cfc 100644
--- a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/publisher/IvyDescriptorFileGenerator.java
+++ b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/publisher/IvyDescriptorFileGenerator.java
@@ -20,8 +20,6 @@ import org.gradle.api.Action;
import org.gradle.api.UncheckedIOException;
import org.gradle.api.XmlProvider;
import org.gradle.api.artifacts.DependencyArtifact;
-import org.gradle.api.artifacts.ModuleDependency;
-import org.gradle.api.artifacts.ProjectDependency;
import org.gradle.api.internal.xml.SimpleXmlWriter;
import org.gradle.api.internal.xml.XmlTransformer;
import org.gradle.api.publish.ivy.IvyArtifact;
@@ -93,7 +91,7 @@ public class IvyDescriptorFileGenerator {
private void writeDescriptor(final Writer writer) throws IOException {
OptionalAttributeXmlWriter xmlWriter = new OptionalAttributeXmlWriter(writer, " ", IVY_FILE_ENCODING);
xmlWriter.startElement("ivy-module").attribute("version", "2.0");
- if (hasClassifier()) {
+ if (usesClassifier()) {
xmlWriter.attribute("xmlns:m", "http://ant.apache.org/ivy/maven");
}
@@ -110,14 +108,15 @@ public class IvyDescriptorFileGenerator {
writeDependencies(xmlWriter);
xmlWriter.endElement();
}
- private boolean hasClassifier() {
+
+ private boolean usesClassifier() {
for (IvyArtifact artifact : artifacts) {
if (artifact.getClassifier() != null) {
return true;
}
}
for (IvyDependencyInternal dependency : this.dependencies) {
- for (DependencyArtifact dependencyArtifact : dependency.getModuleDependency().getArtifacts()) {
+ for (DependencyArtifact dependencyArtifact : dependency.getArtifacts()) {
if (dependencyArtifact.getClassifier() != null) {
return true;
}
@@ -157,14 +156,13 @@ public class IvyDescriptorFileGenerator {
private void writeDependencies(OptionalAttributeXmlWriter xmlWriter) throws IOException {
xmlWriter.startElement("dependencies");
for (IvyDependencyInternal dependency : dependencies) {
- ModuleDependency dep = dependency.getModuleDependency();
xmlWriter.startElement("dependency")
- .attribute("org", dep.getGroup())
- .attribute("name", getDependencyName(dep))
- .attribute("rev", dep.getVersion())
+ .attribute("org", dependency.getOrganisation())
+ .attribute("name", dependency.getModule())
+ .attribute("rev", dependency.getRevision())
.attribute("conf", dependency.getConfMapping());
- for (DependencyArtifact dependencyArtifact : dep.getArtifacts()) {
+ for (DependencyArtifact dependencyArtifact : dependency.getArtifacts()) {
printDependencyArtifact(dependencyArtifact, xmlWriter);
}
xmlWriter.endElement();
@@ -172,10 +170,6 @@ public class IvyDescriptorFileGenerator {
xmlWriter.endElement();
}
- private String getDependencyName(ModuleDependency dep) {
- return dep instanceof ProjectDependency ? ((ProjectDependency) dep).getDependencyProject().getName() : dep.getName();
- }
-
private void printDependencyArtifact(DependencyArtifact dependencyArtifact, OptionalAttributeXmlWriter xmlWriter) throws IOException {
// TODO Use IvyArtifact here
xmlWriter.startElement("artifact")
diff --git a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/publisher/ValidatingIvyPublisher.java b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/publisher/ValidatingIvyPublisher.java
index 0cd5202..b24ac39 100644
--- a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/publisher/ValidatingIvyPublisher.java
+++ b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/publisher/ValidatingIvyPublisher.java
@@ -18,25 +18,24 @@ package org.gradle.api.publish.ivy.internal.publisher;
import org.apache.commons.lang.ObjectUtils;
import org.apache.ivy.core.module.id.ModuleRevisionId;
-import org.apache.ivy.plugins.parser.ParserSettings;
import org.gradle.api.InvalidUserDataException;
-import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.DisconnectedParserSettings;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.DisconnectedDescriptorParseContext;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.DescriptorParseContext;
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.IvyXmlModuleDescriptorParser;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.MetaDataParseException;
import org.gradle.api.internal.artifacts.repositories.PublicationAwareRepository;
import org.gradle.api.publish.internal.PublicationFieldValidator;
import org.gradle.api.publish.ivy.InvalidIvyPublicationException;
import org.gradle.api.publish.ivy.IvyArtifact;
-import org.gradle.internal.UncheckedException;
import java.io.File;
-import java.net.URL;
-import java.text.ParseException;
import java.util.HashSet;
import java.util.Set;
public class ValidatingIvyPublisher implements IvyPublisher {
- private final ParserSettings parserSettings = new DisconnectedParserSettings();
+ private final DescriptorParseContext parserSettings = new DisconnectedDescriptorParseContext();
private final IvyPublisher delegate;
+ private IvyXmlModuleDescriptorParser moduleDescriptorParser = new IvyXmlModuleDescriptorParser();
public ValidatingIvyPublisher(IvyPublisher delegate) {
this.delegate = delegate;
@@ -69,14 +68,10 @@ public class ValidatingIvyPublisher implements IvyPublisher {
}
private ModuleRevisionId parseIvyFile(IvyNormalizedPublication publication) {
-
try {
- URL ivyFileLocation = publication.getDescriptorFile().toURI().toURL();
- return new IvyXmlModuleDescriptorParser().parseDescriptor(parserSettings, ivyFileLocation, true).getModuleRevisionId();
- } catch (ParseException pe) {
+ return moduleDescriptorParser.parseDescriptor(parserSettings, publication.getDescriptorFile(), true).getModuleRevisionId();
+ } catch (MetaDataParseException pe) {
throw new InvalidIvyPublicationException(publication.getName(), pe.getLocalizedMessage(), pe);
- } catch (Exception ex) {
- throw UncheckedException.throwAsUncheckedException(ex);
}
}
diff --git a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/plugins/IvyPublishPlugin.java b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/plugins/IvyPublishPlugin.java
index 9f309fb..1928550 100644
--- a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/plugins/IvyPublishPlugin.java
+++ b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/plugins/IvyPublishPlugin.java
@@ -21,10 +21,7 @@ import org.gradle.api.artifacts.Module;
import org.gradle.api.internal.artifacts.configurations.DependencyMetaDataProvider;
import org.gradle.api.internal.file.FileResolver;
import org.gradle.api.internal.notations.api.NotationParser;
-import org.gradle.api.publish.Publication;
import org.gradle.api.publish.PublishingExtension;
-import org.gradle.api.publish.internal.PublicationContainerInternal;
-import org.gradle.api.publish.internal.PublicationFactory;
import org.gradle.api.publish.ivy.IvyArtifact;
import org.gradle.api.publish.ivy.IvyPublication;
import org.gradle.api.publish.ivy.internal.artifact.IvyArtifactNotationParserFactory;
@@ -63,19 +60,16 @@ public class IvyPublishPlugin implements Plugin<Project> {
// Create the default publication
project.getExtensions().configure(PublishingExtension.class, new Action<PublishingExtension>() {
- public void execute(PublishingExtension publishingExtension) {
- final PublishingExtension extension = project.getExtensions().getByType(PublishingExtension.class);
-
- final PublicationContainerInternal publicationContainer = (PublicationContainerInternal) extension.getPublications();
- publicationContainer.registerFactory(IvyPublication.class, new IvyPublicationFactory(dependencyMetaDataProvider, instantiator, fileResolver));
-
- TaskContainer tasks = project.getTasks();
+ public void execute(PublishingExtension extension) {
+ // Register factory for IvyPublication
+ extension.getPublications().registerFactory(IvyPublication.class, new IvyPublicationFactory(dependencyMetaDataProvider, instantiator, fileResolver));
// Create generate descriptor tasks
IvyPublicationDynamicDescriptorGenerationTaskCreator descriptorGenerationTaskCreator = new IvyPublicationDynamicDescriptorGenerationTaskCreator(project);
descriptorGenerationTaskCreator.monitor(extension.getPublications());
// Create publish tasks automatically for any Ivy publication and repository combinations
+ TaskContainer tasks = project.getTasks();
Task publishLifecycleTask = tasks.getByName(PublishingPlugin.PUBLISH_LIFECYCLE_TASK_NAME);
IvyPublishDynamicTaskCreator publishTaskCreator = new IvyPublishDynamicTaskCreator(tasks, publishLifecycleTask);
publishTaskCreator.monitor(extension.getPublications(), extension.getRepositories());
@@ -84,7 +78,7 @@ public class IvyPublishPlugin implements Plugin<Project> {
}
- private class IvyPublicationFactory implements PublicationFactory {
+ private class IvyPublicationFactory implements NamedDomainObjectFactory<IvyPublication> {
private final Instantiator instantiator;
private final DependencyMetaDataProvider dependencyMetaDataProvider;
private final FileResolver fileResolver;
@@ -95,16 +89,14 @@ public class IvyPublishPlugin implements Plugin<Project> {
this.fileResolver = fileResolver;
}
- public Publication create(String name) {
+ public IvyPublication create(String name) {
Module module = dependencyMetaDataProvider.getModule();
IvyPublicationIdentity publicationIdentity = new DefaultIvyPublicationIdentity(module.getGroup(), module.getName(), module.getVersion());
NotationParser<IvyArtifact> notationParser = new IvyArtifactNotationParserFactory(instantiator, fileResolver, publicationIdentity).create();
- DefaultIvyPublication ivyPublication = instantiator.newInstance(
+ return instantiator.newInstance(
DefaultIvyPublication.class,
name, instantiator, publicationIdentity, notationParser
);
- ivyPublication.getDescriptor().setStatus(module.getStatus());
- return ivyPublication;
}
}
}
diff --git a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/tasks/PublishToIvyRepository.java b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/tasks/PublishToIvyRepository.java
index 9eea44b..3723916 100644
--- a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/tasks/PublishToIvyRepository.java
+++ b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/tasks/PublishToIvyRepository.java
@@ -22,17 +22,15 @@ import org.gradle.api.InvalidUserDataException;
import org.gradle.api.artifacts.repositories.IvyArtifactRepository;
import org.gradle.api.file.FileCollection;
import org.gradle.api.internal.Cast;
+import org.gradle.api.internal.artifacts.DependencyManagementServices;
+import org.gradle.api.internal.artifacts.ivyservice.IvyContextManager;
import org.gradle.api.internal.artifacts.repositories.PublicationAwareRepository;
import org.gradle.api.publish.internal.PublishOperation;
import org.gradle.api.publish.ivy.IvyPublication;
-import org.gradle.api.publish.ivy.internal.publisher.DependencyResolverIvyPublisher;
-import org.gradle.api.publish.ivy.internal.publisher.IvyNormalizedPublication;
import org.gradle.api.publish.ivy.internal.publication.IvyPublicationInternal;
-import org.gradle.api.publish.ivy.internal.publisher.IvyPublisher;
-import org.gradle.api.publish.ivy.internal.publisher.ValidatingIvyPublisher;
+import org.gradle.api.publish.ivy.internal.publisher.*;
import org.gradle.api.tasks.TaskAction;
-import javax.inject.Inject;
import java.util.concurrent.Callable;
/**
@@ -46,7 +44,6 @@ public class PublishToIvyRepository extends DefaultTask {
private IvyPublicationInternal publication;
private IvyArtifactRepository repository;
- @Inject
public PublishToIvyRepository() {
// Allow the publication to participate in incremental build
@@ -142,6 +139,7 @@ public class PublishToIvyRepository extends DefaultTask {
IvyNormalizedPublication normalizedPublication = publication.asNormalisedPublication();
IvyPublisher publisher = new DependencyResolverIvyPublisher();
publisher = new ValidatingIvyPublisher(publisher);
+ publisher = new ContextualizingIvyPublisher(publisher, getServices().get(DependencyManagementServices.class).get(IvyContextManager.class));
publisher.publish(normalizedPublication, Cast.cast(PublicationAwareRepository.class, repository));
}
}.run();
diff --git a/subprojects/ivy/src/test/groovy/org/gradle/api/publish/ivy/internal/artifact/IvyArtifactNotationParserFactoryTest.groovy b/subprojects/ivy/src/test/groovy/org/gradle/api/publish/ivy/internal/artifact/IvyArtifactNotationParserFactoryTest.groovy
index 0f309cc..60f4f83 100644
--- a/subprojects/ivy/src/test/groovy/org/gradle/api/publish/ivy/internal/artifact/IvyArtifactNotationParserFactoryTest.groovy
+++ b/subprojects/ivy/src/test/groovy/org/gradle/api/publish/ivy/internal/artifact/IvyArtifactNotationParserFactoryTest.groovy
@@ -15,9 +15,10 @@
*/
package org.gradle.api.publish.ivy.internal.artifact
-
import org.gradle.api.Task
import org.gradle.api.artifacts.PublishArtifact
+import org.gradle.api.internal.AsmBackedClassGenerator
+import org.gradle.api.internal.ClassGeneratorBackedInstantiator
import org.gradle.api.internal.file.FileResolver
import org.gradle.api.internal.notations.api.NotationParser
import org.gradle.api.publish.ivy.IvyArtifact
@@ -26,11 +27,11 @@ import org.gradle.api.tasks.TaskDependency
import org.gradle.api.tasks.bundling.Jar
import org.gradle.internal.reflect.DirectInstantiator
import org.gradle.internal.reflect.Instantiator
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import spock.lang.Specification
public class IvyArtifactNotationParserFactoryTest extends Specification {
- Instantiator instantiator = new DirectInstantiator()
+ Instantiator instantiator = new ClassGeneratorBackedInstantiator(new AsmBackedClassGenerator(), new DirectInstantiator())
def fileNotationParser = Mock(NotationParser)
def taskDependency = Mock(TaskDependency)
def publishArtifact = Stub(PublishArtifact) {
@@ -134,7 +135,7 @@ public class IvyArtifactNotationParserFactoryTest extends Specification {
def "creates IvyArtifact for ArchivePublishArtifact"() {
when:
- def rootProject = HelperUtil.createRootProject()
+ def rootProject = TestUtil.createRootProject()
def archive = rootProject.task(type: Jar, {})
archive.setBaseName("base-name")
archive.setExtension('extension')
diff --git a/subprojects/ivy/src/test/groovy/org/gradle/api/publish/ivy/internal/plugins/IvyPublicationDynamicDescriptorGenerationTaskCreatorTest.groovy b/subprojects/ivy/src/test/groovy/org/gradle/api/publish/ivy/internal/plugins/IvyPublicationDynamicDescriptorGenerationTaskCreatorTest.groovy
index 0c5113a..4ca5422 100644
--- a/subprojects/ivy/src/test/groovy/org/gradle/api/publish/ivy/internal/plugins/IvyPublicationDynamicDescriptorGenerationTaskCreatorTest.groovy
+++ b/subprojects/ivy/src/test/groovy/org/gradle/api/publish/ivy/internal/plugins/IvyPublicationDynamicDescriptorGenerationTaskCreatorTest.groovy
@@ -23,12 +23,12 @@ import org.gradle.api.publish.ivy.internal.publication.IvyModuleDescriptorIntern
import org.gradle.api.publish.ivy.internal.publication.IvyPublicationInternal
import org.gradle.api.publish.ivy.tasks.GenerateIvyDescriptor
import org.gradle.api.publish.plugins.PublishingPlugin
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import spock.lang.Specification
class IvyPublicationDynamicDescriptorGenerationTaskCreatorTest extends Specification {
- def project = HelperUtil.createRootProject()
+ def project = TestUtil.createRootProject()
def creator = new IvyPublicationDynamicDescriptorGenerationTaskCreator(project)
PublishingExtension publishing
@@ -54,7 +54,7 @@ class IvyPublicationDynamicDescriptorGenerationTaskCreatorTest extends Specifica
then:
descriptorGeneratorTasks.size() == 1
- GenerateIvyDescriptor task = project.tasks.generateIvyModuleDescriptor
+ GenerateIvyDescriptor task = project.tasks.generateDescriptorFileForIvyPublication
task.description != null
when:
@@ -62,7 +62,7 @@ class IvyPublicationDynamicDescriptorGenerationTaskCreatorTest extends Specifica
then:
descriptorGeneratorTasks.size() == 2
- def task2 = project.tasks.generateOtherIvyModuleDescriptor
+ def task2 = project.tasks.generateDescriptorFileForOtherPublication
task2
}
diff --git a/subprojects/ivy/src/test/groovy/org/gradle/api/publish/ivy/internal/plugins/IvyPublishDynamicTaskCreatorTest.groovy b/subprojects/ivy/src/test/groovy/org/gradle/api/publish/ivy/internal/plugins/IvyPublishDynamicTaskCreatorTest.groovy
index 7d5df98..a15916e 100644
--- a/subprojects/ivy/src/test/groovy/org/gradle/api/publish/ivy/internal/plugins/IvyPublishDynamicTaskCreatorTest.groovy
+++ b/subprojects/ivy/src/test/groovy/org/gradle/api/publish/ivy/internal/plugins/IvyPublishDynamicTaskCreatorTest.groovy
@@ -22,12 +22,12 @@ import org.gradle.api.publish.ivy.IvyPublication
import org.gradle.api.publish.ivy.internal.publication.IvyPublicationInternal
import org.gradle.api.publish.ivy.tasks.PublishToIvyRepository
import org.gradle.api.publish.plugins.PublishingPlugin
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import spock.lang.Specification
class IvyPublishDynamicTaskCreatorTest extends Specification {
- def project = HelperUtil.createRootProject()
+ def project = TestUtil.createRootProject()
def lifecycleTask = project.task("pl")
def creator = new IvyPublishDynamicTaskCreator(project.tasks, lifecycleTask)
diff --git a/subprojects/ivy/src/test/groovy/org/gradle/api/publish/ivy/internal/publication/DefaultIvyPublicationTest.groovy b/subprojects/ivy/src/test/groovy/org/gradle/api/publish/ivy/internal/publication/DefaultIvyPublicationTest.groovy
index a3cc01c..c4bffa8 100644
--- a/subprojects/ivy/src/test/groovy/org/gradle/api/publish/ivy/internal/publication/DefaultIvyPublicationTest.groovy
+++ b/subprojects/ivy/src/test/groovy/org/gradle/api/publish/ivy/internal/publication/DefaultIvyPublicationTest.groovy
@@ -15,18 +15,23 @@
*/
package org.gradle.api.publish.ivy.internal.publication
-
import org.gradle.api.InvalidUserDataException
-import org.gradle.api.artifacts.DependencySet
+import org.gradle.api.artifacts.DependencyArtifact
import org.gradle.api.artifacts.ModuleDependency
+import org.gradle.api.artifacts.ProjectDependency
import org.gradle.api.artifacts.PublishArtifact
-import org.gradle.api.artifacts.PublishArtifactSet
import org.gradle.api.internal.AsmBackedClassGenerator
import org.gradle.api.internal.ClassGeneratorBackedInstantiator
+import org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier
import org.gradle.api.internal.component.SoftwareComponentInternal
import org.gradle.api.internal.component.Usage
import org.gradle.api.internal.file.collections.SimpleFileCollection
import org.gradle.api.internal.notations.api.NotationParser
+import org.gradle.api.internal.plugins.ExtensionContainerInternal
+import org.gradle.api.internal.project.ProjectInternal
+import org.gradle.api.publish.PublishingExtension
+import org.gradle.api.publish.internal.DefaultPublicationContainer
+import org.gradle.api.publish.internal.PublicationInternal
import org.gradle.api.publish.ivy.IvyArtifact
import org.gradle.api.publish.ivy.internal.publisher.IvyPublicationIdentity
import org.gradle.internal.reflect.DirectInstantiator
@@ -59,6 +64,14 @@ class DefaultIvyPublicationTest extends Specification {
publication.name == "pub-name"
}
+ def "status property is defaults to 'integration'"() {
+ when:
+ def publication = createPublication()
+
+ then:
+ publication.descriptor.status == "integration"
+ }
+
def "empty publishableFiles and artifacts when no component is added"() {
when:
def publication = createPublication()
@@ -72,23 +85,15 @@ class DefaultIvyPublicationTest extends Specification {
def "adopts configurations, artifacts and publishableFiles from added component"() {
given:
def publication = createPublication()
-
- def component = Mock(SoftwareComponentInternal)
- def usage1 = Mock(Usage)
def artifact = Mock(PublishArtifact)
def ivyArtifact = createArtifact()
when:
- component.usages >> [usage1]
- usage1.name >> "runtime"
- usage1.artifacts >> [artifact]
- usage1.dependencies >> []
-
notationParser.parseNotation(artifact) >> ivyArtifact
1 * ivyArtifact.setConf("runtime")
and:
- publication.from(component)
+ publication.from(componentWithArtifact(artifact))
then:
publication.publishableFiles.files == [descriptorFile, artifactFile] as Set
@@ -102,55 +107,146 @@ class DefaultIvyPublicationTest extends Specification {
publication.dependencies.empty
}
- def "adopts dependencies from added component"() {
+ def "adopts module dependency from added component"() {
given:
def publication = createPublication()
-
- def component = Mock(SoftwareComponentInternal)
- def usage1 = Mock(Usage)
def moduleDependency = Mock(ModuleDependency)
+ def artifact = Mock(DependencyArtifact)
when:
- component.usages >> [usage1]
- usage1.name >> "runtime"
- usage1.artifacts >> []
- usage1.dependencies >> [moduleDependency]
-
+ moduleDependency.group >> "org"
+ moduleDependency.name >> "name"
+ moduleDependency.version >> "version"
moduleDependency.configuration >> "dep-configuration"
+ moduleDependency.artifacts >> [artifact]
and:
- publication.from(component)
+ publication.from(componentWithDependency(moduleDependency))
then:
publication.publishableFiles.files == [descriptorFile] as Set
publication.artifacts.empty
+
and:
publication.dependencies.size() == 1
def ivyDependency = publication.dependencies.asList().first()
- ivyDependency.moduleDependency == moduleDependency
- ivyDependency.confMapping == "runtime->dep-configuration"
+
+ with (ivyDependency) {
+ organisation == "org"
+ module == "name"
+ revision == "version"
+ confMapping == "runtime->dep-configuration"
+ artifacts == [artifact]
+ }
}
- def "cannot add multiple components"() {
+ def "adopts dependency on project with single publications"() {
given:
def publication = createPublication()
- def component = Mock(SoftwareComponentInternal)
- def usage = Mock(Usage)
- def publishArtifactSet = Mock(PublishArtifactSet)
- def dependencySet = Mock(DependencySet)
+ def projectDependency = Mock(ProjectDependency)
+ def extensionContainer = Mock(ExtensionContainerInternal)
+ def publishingExtension = Mock(PublishingExtension)
+ def publications = new DefaultPublicationContainer(new DirectInstantiator())
+ publications.add(otherPublication("ivyPub1", "pub-org", "pub-module", "pub-revision"))
when:
- publication.from(component)
+ projectDependency.configuration >> "dep-configuration"
+ projectDependency.artifacts >> []
+ projectDependency.dependencyProject >> Stub(ProjectInternal) {
+ getExtensions() >> extensionContainer
+ }
+ extensionContainer.findByType(PublishingExtension) >> publishingExtension
+ publishingExtension.publications >> publications
+
+ and:
+ publication.from(componentWithDependency(projectDependency))
then:
- component.usages >> [usage]
- usage.name >> "runtime"
- usage.artifacts >> publishArtifactSet
- publishArtifactSet.iterator() >> [].iterator()
- usage.dependencies >> dependencySet
- dependencySet.iterator() >> [].iterator()
+ publication.publishableFiles.files == [descriptorFile] as Set
+ publication.artifacts.empty
+
+ and:
+ publication.dependencies.size() == 1
+ def ivyDependency = publication.dependencies.asList().first()
+
+ with (ivyDependency) {
+ organisation == "pub-org"
+ module == "pub-module"
+ revision == "pub-revision"
+ confMapping == "runtime->dep-configuration"
+ artifacts == []
+ }
+ }
+
+ def "fails to resolve dependency on project with multiple publications"() {
+ given:
+ def publication = createPublication()
+ def projectDependency = Mock(ProjectDependency)
+ def extensionContainer = Mock(ExtensionContainerInternal)
+ def publishingExtension = Mock(PublishingExtension)
+ def publications = new DefaultPublicationContainer(new DirectInstantiator())
+ publications.add(otherPublication("ivyPub1", "pub-org", "pub-module", "pub-revision"))
+ publications.add(otherPublication("ivyPub2", "pub-org-2", "pub-module-2", "pub-revision-2"))
when:
+ projectDependency.configuration >> "dep-configuration"
+ projectDependency.artifacts >> []
+ projectDependency.dependencyProject >> Stub(ProjectInternal) {
+ getExtensions() >> extensionContainer
+ }
+ extensionContainer.findByType(PublishingExtension) >> publishingExtension
+ publishingExtension.publications >> publications
+
+ and:
+ publication.from(componentWithDependency(projectDependency))
+
+ then:
+ def e = thrown(UnsupportedOperationException)
+ e.message == "Publishing is not yet able to resolve a dependency on a project with multiple different publications."
+ }
+
+ def "adopts dependency on project without a publication"() {
+ given:
+ def publication = createPublication()
+ def projectDependency = Mock(ProjectDependency)
+ def extensionContainer = Mock(ExtensionContainerInternal)
+
+ when:
+ projectDependency.group >> "dep-group"
+ projectDependency.name >> "dep-name-1"
+ projectDependency.version >> "dep-version"
+ projectDependency.configuration >> "dep-configuration"
+ projectDependency.dependencyProject >> Stub(ProjectInternal) {
+ getExtensions() >> extensionContainer
+ getName() >> "project-name"
+ }
+ projectDependency.artifacts >> []
+ extensionContainer.findByType(PublishingExtension) >> null
+
+ and:
+ publication.from(componentWithDependency(projectDependency))
+
+ then:
+ publication.publishableFiles.files == [descriptorFile] as Set
+ publication.artifacts.empty
+
+ and:
+ publication.dependencies.size() == 1
+ with (publication.dependencies.asList().first()) {
+ organisation == "dep-group"
+ module == "project-name"
+ revision == "dep-version"
+ confMapping == "runtime->dep-configuration"
+ artifacts == []
+ }
+ }
+
+ def "cannot add multiple components"() {
+ given:
+ def publication = createPublication()
+
+ when:
+ publication.from(createComponent([], []))
publication.from(Mock(SoftwareComponentInternal))
then:
@@ -244,4 +340,31 @@ class DefaultIvyPublicationTest extends Specification {
}
return artifact
}
+
+ def componentWithDependency(ModuleDependency dependency) {
+ return createComponent([], [dependency])
+ }
+
+ def componentWithArtifact(def artifact) {
+ return createComponent([artifact], [])
+ }
+
+ def createComponent(def artifacts, def dependencies) {
+ def usage = Stub(Usage) {
+ getName() >> "runtime"
+ getArtifacts() >> artifacts
+ getDependencies() >> dependencies
+ }
+ def component = Stub(SoftwareComponentInternal) {
+ getUsages() >> [usage]
+ }
+ return component
+ }
+
+ def otherPublication(String name, String org, String module, String revision) {
+ def pub = Mock(PublicationInternal)
+ pub.name >> name
+ pub.coordinates >> new DefaultModuleVersionIdentifier(org, module, revision)
+ return pub
+ }
}
diff --git a/subprojects/ivy/src/test/groovy/org/gradle/api/publish/ivy/internal/publisher/IvyDescriptorFileGeneratorTest.groovy b/subprojects/ivy/src/test/groovy/org/gradle/api/publish/ivy/internal/publisher/IvyDescriptorFileGeneratorTest.groovy
index 9b88a47..268d700 100644
--- a/subprojects/ivy/src/test/groovy/org/gradle/api/publish/ivy/internal/publisher/IvyDescriptorFileGeneratorTest.groovy
+++ b/subprojects/ivy/src/test/groovy/org/gradle/api/publish/ivy/internal/publisher/IvyDescriptorFileGeneratorTest.groovy
@@ -16,11 +16,8 @@
package org.gradle.api.publish.ivy.internal.publisher
import org.gradle.api.Action
-import org.gradle.api.Project
import org.gradle.api.XmlProvider
import org.gradle.api.artifacts.DependencyArtifact
-import org.gradle.api.artifacts.ModuleDependency
-import org.gradle.api.artifacts.ProjectDependency
import org.gradle.api.publish.ivy.internal.artifact.DefaultIvyArtifact
import org.gradle.api.publish.ivy.internal.dependency.DefaultIvyDependency
import org.gradle.api.publish.ivy.internal.publication.DefaultIvyConfiguration
@@ -28,7 +25,6 @@ import org.gradle.api.publish.ivy.internal.publication.DefaultIvyPublicationIden
import org.gradle.test.fixtures.file.TestDirectoryProvider
import org.gradle.test.fixtures.file.TestFile
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
-import org.gradle.util.CollectionUtils
import org.gradle.util.TextUtil
import spock.lang.Specification
@@ -136,33 +132,16 @@ class IvyDescriptorFileGeneratorTest extends Specification {
}
}
def "writes supplied dependencies"() {
- def projectDependency = Mock(ProjectDependency)
- def moduleDependency = Mock(ModuleDependency)
when:
- projectDependency.artifacts >> new HashSet<DependencyArtifact>()
- projectDependency.group >> "dep-group"
- projectDependency.name >> "dep-name-1"
- projectDependency.version >> "dep-version"
- projectDependency.dependencyProject >> Stub(Project) {
- getName() >> "project-name"
- }
-
- and:
- moduleDependency.artifacts >> new HashSet<DependencyArtifact>()
- moduleDependency.group >> "dep-group"
- moduleDependency.name >> "dep-name-2"
- moduleDependency.version >> "dep-version"
-
- and:
- generator.addDependency(new DefaultIvyDependency(projectDependency, "confMappingProject"))
- generator.addDependency(new DefaultIvyDependency(moduleDependency, null))
+ generator.addDependency(new DefaultIvyDependency('dep-group', 'dep-name-1', 'dep-version', "confMappingProject"))
+ generator.addDependency(new DefaultIvyDependency('dep-group', 'dep-name-2', 'dep-version', null))
then:
with (ivyXml) {
dependencies.dependency.size() == 2
with (dependencies[0].dependency[0]) {
it. at org == "dep-group"
- it. at name == "project-name"
+ it. at name == "dep-name-1"
it. at rev == "dep-version"
it. at conf == "confMappingProject"
}
@@ -176,15 +155,10 @@ class IvyDescriptorFileGeneratorTest extends Specification {
}
def "writes dependency with artifacts"() {
- def dependency = Mock(ModuleDependency)
def artifact1 = Mock(DependencyArtifact)
def artifact2 = Mock(DependencyArtifact)
when:
- dependency.artifacts >> CollectionUtils.toSet([artifact1, artifact2])
- dependency.group >> "dep-group"
- dependency.name >> "dep-name"
- dependency.version >> "dep-version"
artifact1.name >> "artifact-1"
artifact1.type >> "type-1"
artifact1.extension >> "ext-1"
@@ -194,7 +168,7 @@ class IvyDescriptorFileGeneratorTest extends Specification {
artifact2.classifier >> "classy"
and:
- generator.addDependency(new DefaultIvyDependency(dependency, "confMapping"))
+ generator.addDependency(new DefaultIvyDependency('dep-group', 'dep-name', 'dep-version', "confMapping", [artifact1, artifact2]))
then:
includesMavenNamespace()
diff --git a/subprojects/ivy/src/test/groovy/org/gradle/api/publish/ivy/internal/publisher/ValidatingIvyPublisherTest.groovy b/subprojects/ivy/src/test/groovy/org/gradle/api/publish/ivy/internal/publisher/ValidatingIvyPublisherTest.groovy
index ab19830..f6fa348 100644
--- a/subprojects/ivy/src/test/groovy/org/gradle/api/publish/ivy/internal/publisher/ValidatingIvyPublisherTest.groovy
+++ b/subprojects/ivy/src/test/groovy/org/gradle/api/publish/ivy/internal/publisher/ValidatingIvyPublisherTest.groovy
@@ -132,8 +132,7 @@ public class ValidatingIvyPublisherTest extends Specification {
then:
def e = thrown InvalidIvyPublicationException
- e.message.startsWith "Invalid publication 'pub-name': Problem occurred while parsing ivy file: " +
- "Cannot add artifact 'name.ext(type)' to configuration 'unknown' of module the-group#the-artifact;the-version because this configuration doesn't exist!"
+ e.message == "Invalid publication 'pub-name': Could not parse Ivy file ${ivyFile.toURI()}"
}
def "validates artifact attributes"() {
diff --git a/subprojects/ivy/src/test/groovy/org/gradle/api/publish/ivy/plugins/IvyPublishPluginTest.groovy b/subprojects/ivy/src/test/groovy/org/gradle/api/publish/ivy/plugins/IvyPublishPluginTest.groovy
index 2a27d4e..9b1bf64 100644
--- a/subprojects/ivy/src/test/groovy/org/gradle/api/publish/ivy/plugins/IvyPublishPluginTest.groovy
+++ b/subprojects/ivy/src/test/groovy/org/gradle/api/publish/ivy/plugins/IvyPublishPluginTest.groovy
@@ -21,12 +21,12 @@ import org.gradle.api.publish.PublishingExtension
import org.gradle.api.publish.ivy.IvyPublication
import org.gradle.api.publish.ivy.internal.publication.DefaultIvyPublication
import org.gradle.api.publish.ivy.internal.publication.IvyPublicationInternal
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import spock.lang.Specification
class IvyPublishPluginTest extends Specification {
- Project project = HelperUtil.createRootProject()
+ Project project = TestUtil.createRootProject()
PublishingExtension publishing
def setup() {
@@ -41,7 +41,7 @@ class IvyPublishPluginTest extends Specification {
def "publication can be added"() {
when:
- publishing.publications.add("test", IvyPublication)
+ publishing.publications.create("test", IvyPublication)
then:
publishing.publications.size() == 1
@@ -50,7 +50,7 @@ class IvyPublishPluginTest extends Specification {
def "creates publish task for publication and repository"() {
when:
- publishing.publications.add("test", IvyPublication)
+ publishing.publications.create("test", IvyPublication)
publishing.repositories { ivy { url = "http://foo.com" } }
def publishTask = project.tasks["publishTestPublicationToIvyRepository"]
@@ -63,10 +63,10 @@ class IvyPublishPluginTest extends Specification {
when:
project.group = "foo"
project.version = 1.0
- project.status = "integration"
+ project.status = "another"
and:
- publishing.publications.add("test", IvyPublication)
+ publishing.publications.create("test", IvyPublication)
then:
with (publishing.publications.test) {
@@ -89,7 +89,7 @@ class IvyPublishPluginTest extends Specification {
def "can configure descriptor"() {
given:
- publishing.publications.add("ivy", IvyPublication)
+ publishing.publications.create("ivy", IvyPublication)
IvyPublicationInternal publication = publishing.publications.ivy
when:
diff --git a/subprojects/ivy/src/test/groovy/org/gradle/api/publish/ivy/tasks/PublishToIvyRepositoryTest.groovy b/subprojects/ivy/src/test/groovy/org/gradle/api/publish/ivy/tasks/PublishToIvyRepositoryTest.groovy
index 191f145..3fe58ec 100644
--- a/subprojects/ivy/src/test/groovy/org/gradle/api/publish/ivy/tasks/PublishToIvyRepositoryTest.groovy
+++ b/subprojects/ivy/src/test/groovy/org/gradle/api/publish/ivy/tasks/PublishToIvyRepositoryTest.groovy
@@ -21,7 +21,7 @@ import org.gradle.api.artifacts.repositories.IvyArtifactRepository
import org.gradle.api.publish.ivy.IvyPublication
import org.gradle.api.publish.ivy.internal.publisher.IvyNormalizedPublication
import org.gradle.api.publish.ivy.internal.publication.IvyPublicationInternal
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import spock.lang.Specification
class PublishToIvyRepositoryTest extends Specification {
@@ -38,7 +38,7 @@ class PublishToIvyRepositoryTest extends Specification {
def repository = Mock(IvyArtifactRepository) {}
def setup() {
- project = HelperUtil.createRootProject()
+ project = TestUtil.createRootProject()
publish = createPublish("publish")
}
@@ -70,7 +70,7 @@ class PublishToIvyRepositoryTest extends Specification {
}
PublishToIvyRepository createPublish(String name) {
- project.tasks.add(name, PublishToIvyRepository)
+ project.tasks.create(name, PublishToIvyRepository)
}
}
diff --git a/subprojects/jacoco/jacoco.gradle b/subprojects/jacoco/jacoco.gradle
new file mode 100644
index 0000000..b675202
--- /dev/null
+++ b/subprojects/jacoco/jacoco.gradle
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+
+
+dependencies {
+ compile libraries.groovy
+ compile project(':core')
+ compile project(':plugins')
+ compile project(':reporting')
+ testCompile libraries.jsoup
+}
+
+useTestFixtures()
\ No newline at end of file
diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginGoodBehaviourTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginGoodBehaviourTest.groovy
new file mode 100644
index 0000000..36bff84
--- /dev/null
+++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginGoodBehaviourTest.groovy
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.testing.jacoco.plugins
+
+import org.gradle.integtests.fixtures.WellBehavedPluginTest
+
+
+class JacocoPluginGoodBehaviourTest extends WellBehavedPluginTest {
+ // The jacoco plugin does not add tasks to an empty project.
+ // We apply the java plugin too here in this test to check that
+ // the jacoco plugin behaves well when used together
+ // with the java plugin (a typical scenario).
+
+ def setup(){
+ buildFile << """
+ apply plugin:'java'
+ """
+ }
+}
diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginIntegrationTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginIntegrationTest.groovy
new file mode 100644
index 0000000..44d2643
--- /dev/null
+++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginIntegrationTest.groovy
@@ -0,0 +1,199 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.testing.jacoco.plugins
+
+import org.gradle.api.Project
+import org.gradle.api.reporting.ReportingExtension
+import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+import org.gradle.testing.jacoco.tasks.JacocoMerge
+
+class JacocoPluginIntegrationTest extends AbstractIntegrationSpec {
+
+ private static final String REPORTING_BASE = "${Project.DEFAULT_BUILD_DIR_NAME}/${ReportingExtension.DEFAULT_REPORTS_DIR_NAME}"
+ private static final String REPORT_HTML_DEFAULT_PATH = "${REPORTING_BASE}/jacoco/test/html/index.html"
+ private static final String REPORT_XML_DEFAULT_PATH = "${REPORTING_BASE}/jacoco/test/jacocoTestReport.xml"
+ private static final String REPORT_CSV_DEFAULT_REPORT = "${REPORTING_BASE}/jacoco/test/jacocoTestReport.csv"
+
+ def setup() {
+ buildFile << """
+ apply plugin: "java"
+ apply plugin: "jacoco"
+
+ repositories {
+ mavenCentral()
+ }
+ dependencies {
+ testCompile 'junit:junit:4.11'
+ }
+ """
+ createTestFiles()
+ }
+
+ void generatesHtmlReportOnlyAsDefault() {
+ when:
+ succeeds('test', 'jacocoTestReport')
+
+ then:
+ file(REPORTING_BASE).listFiles().collect { it.name } as Set == ["jacoco", "tests"] as Set
+ file(REPORT_HTML_DEFAULT_PATH).exists()
+ file("${REPORTING_BASE}/jacoco/test").listFiles().collect { it.name } == ["html"]
+ }
+
+ void canConfigureReportsInJacocoTestReport() {
+ given:
+ buildFile << """
+ jacocoTestReport {
+ reports {
+ xml.enabled true
+ csv.enabled true
+ html.destination "\${buildDir}/jacocoHtml"
+ }
+ }
+ """
+
+ when:
+ succeeds('test', 'jacocoTestReport')
+
+ then:
+ file("build/jacocoHtml/index.html").exists()
+ file(REPORT_XML_DEFAULT_PATH).exists()
+ file(REPORT_CSV_DEFAULT_REPORT).exists()
+ }
+
+ void respectsReportingBaseDir() {
+ given:
+ buildFile << """
+ jacocoTestReport {
+ reports.xml.enabled = true
+ reports.csv.enabled = true
+ }
+ reporting{
+ baseDir = "\$buildDir/customReports"
+ }"""
+
+ when:
+ succeeds('test', 'jacocoTestReport')
+
+ then:
+ file("build/customReports/jacoco/test/html/index.html").exists()
+ file("build/customReports/jacoco/test/jacocoTestReport.xml").exists()
+ file("build/customReports/jacoco/test/jacocoTestReport.csv").exists()
+ }
+
+ void canConfigureReportDirectory() {
+ given:
+ def customReportDirectory = "customJacocoReportDir"
+ buildFile << """
+ jacocoTestReport {
+ reports.xml.enabled = true
+ reports.csv.enabled = true
+ }
+ jacoco {
+ reportsDir = new File(buildDir, "$customReportDirectory")
+ }
+ """
+
+ when:
+ succeeds('test', 'jacocoTestReport')
+
+ then:
+ file("build/${customReportDirectory}/test/html/index.html").exists()
+ file("build/${customReportDirectory}/test/jacocoTestReport.xml").exists()
+ file("build/${customReportDirectory}/test/jacocoTestReport.csv").exists()
+ }
+
+ void jacocoReportIsIncremental() {
+ when:
+ succeeds('test', 'jacocoTestReport')
+
+ then:
+ file(REPORT_HTML_DEFAULT_PATH).exists()
+
+ when:
+ succeeds('jacocoTestReport')
+
+ then:
+ skippedTasks.contains(":jacocoTestReport")
+ file(REPORT_HTML_DEFAULT_PATH).exists()
+
+ when:
+ file("${REPORTING_BASE}/jacoco/test/html/.resources").deleteDir()
+ succeeds('test', 'jacocoTestReport')
+
+ then:
+ !skippedTasks.contains(":jacocoTestReport")
+ file(REPORT_HTML_DEFAULT_PATH).exists()
+ }
+
+ void jacocoTestReportIsSkippedIfNoCoverageDataAvailable() {
+ when:
+ def executionResult = succeeds('jacocoTestReport')
+ then:
+ executionResult.assertTaskSkipped(':jacocoTestReport')
+ }
+
+ void canUseCoverageDataFromPreviousRunForCoverageReport() {
+ when:
+ succeeds('jacocoTestReport')
+
+ then:
+ skippedTasks.contains(":jacocoTestReport")
+ !file(REPORT_HTML_DEFAULT_PATH).exists()
+
+ when:
+ succeeds('test')
+
+ and:
+ succeeds('jacocoTestReport')
+
+ then:
+ executedTasks.contains(":jacocoTestReport")
+ file(REPORT_HTML_DEFAULT_PATH).exists()
+ }
+
+ void canMergeCoverageData() {
+ given:
+ buildFile << """
+ task otherTests(type: Test) {
+ binResultsDir file("bin")
+ testSrcDirs = test.testSrcDirs
+ testClassesDir = test.testClassesDir
+ classpath = test.classpath
+ }
+
+ task jacocoMerge(type: ${JacocoMerge.name}) {
+ executionData test, otherTests
+ }
+ """
+ when:
+ succeeds 'jacocoMerge'
+
+ then:
+ ":jacocoMerge" in nonSkippedTasks
+ ":test" in nonSkippedTasks
+ ":otherTests" in nonSkippedTasks
+ file("build/jacoco/jacocoMerge.exec").exists()
+ }
+
+ private void createTestFiles() {
+ file("src/main/java/org/gradle/Class1.java") <<
+ "package org.gradle; public class Class1 { public boolean isFoo(Object arg) { return true; } }"
+ file("src/test/java/org/gradle/Class1Test.java") <<
+ "package org.gradle; import org.junit.Test; public class Class1Test { @Test public void someTest() { new Class1().isFoo(\"test\"); } }"
+ }
+}
+
diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoVersionIntegTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoVersionIntegTest.groovy
new file mode 100644
index 0000000..86b29e9
--- /dev/null
+++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoVersionIntegTest.groovy
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.testing.jacoco.plugins
+
+import org.gradle.integtests.fixtures.MultiVersionIntegrationSpec
+import org.gradle.integtests.fixtures.TargetVersions
+import org.jsoup.Jsoup
+import org.jsoup.nodes.Document
+import org.jsoup.select.Elements
+import org.junit.Test
+import static org.junit.Assert.*
+
+ at TargetVersions(['0.6.0.201210061924', '0.6.2.201302030002'])
+class JacocoVersionIntegTest extends MultiVersionIntegrationSpec {
+
+ @Test
+ public void canRunVersions() {
+ given:
+ buildFile << """
+ apply plugin: "java"
+ apply plugin: "jacoco"
+
+ repositories {
+ mavenCentral()
+ }
+
+ dependencies {
+ testCompile 'junit:junit:4.10'
+ }
+ jacoco {
+ toolVersion = '$version'
+ }
+ """
+ createTestFiles();
+ when:
+ executer.withArgument("-d")
+ succeeds('test', 'jacocoTestReport')
+ then:
+ correctJacocoVersionUsed()
+ file("build/reports/jacoco/test/html/index.html").exists()
+ }
+
+ private void createTestFiles() {
+ file("src/main/java/org/gradle/Class1.java") <<
+ "package org.gradle; public class Class1 { public boolean isFoo(Object arg) { return true; } }"
+ file("src/test/java/org/gradle/Class1Test.java") <<
+ "package org.gradle; import org.junit.Test; public class Class1Test { @Test public void someTest() { new Class1().isFoo(\"test\"); } }"
+ }
+
+ def correctJacocoVersionUsed() {
+ Document parsedHtmlReport = Jsoup.parse(file("build/reports/jacoco/test/html/index.html"), "UTF-8")
+ Elements footer = parsedHtmlReport.select("div.footer:has(a[href=http://www.eclemma.org/jacoco])")
+ assertTrue footer.text().contains(version)
+ true
+ }
+}
diff --git a/subprojects/jacoco/src/main/groovy/org/gradle/internal/jacoco/JacocoAgentJar.groovy b/subprojects/jacoco/src/main/groovy/org/gradle/internal/jacoco/JacocoAgentJar.groovy
new file mode 100644
index 0000000..33a555b
--- /dev/null
+++ b/subprojects/jacoco/src/main/groovy/org/gradle/internal/jacoco/JacocoAgentJar.groovy
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.jacoco
+
+import org.gradle.api.Project
+import org.gradle.api.file.FileCollection
+
+/**
+ * Helper to resolve the {@code jacocoagent.jar} from inside
+ * of the {@code org.jacoco.agent.jar}.
+ */
+class JacocoAgentJar {
+ private final Project project
+ private File agentJar
+ FileCollection agentConf
+
+ /**
+ * Constructs a new agent JAR wrapper.
+ * @param project a project that can be used to resolve files
+ * @param agentConf the configuration that the agent JAR is located in
+ */
+ JacocoAgentJar(Project project) {
+ this.project = project
+ }
+
+ /**
+ * Unzips the resolved {@code org.jacoco.agent.jar} to retrieve
+ * the {@code jacocoagent.jar}.
+ * @return a file pointing to the {@code jacocoagent.jar}
+ */
+ File getJar() {
+ if (!agentJar) {
+ agentJar = project.zipTree(getAgentConf().singleFile).filter { it.name == 'jacocoagent.jar' }.singleFile
+ }
+ return agentJar
+ }
+
+ boolean supportsJmx() {
+ def pre062 = getAgentConf().any {
+ it.name ==~ /org.jacoco.agent-([0]\.[0-6]\.[0-1\.].*)\.jar/
+ }
+ return !pre062
+ }
+}
diff --git a/subprojects/jacoco/src/main/groovy/org/gradle/internal/jacoco/JacocoReportsContainerImpl.java b/subprojects/jacoco/src/main/groovy/org/gradle/internal/jacoco/JacocoReportsContainerImpl.java
new file mode 100644
index 0000000..672cfc4
--- /dev/null
+++ b/subprojects/jacoco/src/main/groovy/org/gradle/internal/jacoco/JacocoReportsContainerImpl.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.jacoco;
+
+import org.gradle.api.Task;
+import org.gradle.api.reporting.ConfigurableReport;
+import org.gradle.api.reporting.DirectoryReport;
+import org.gradle.api.reporting.Report;
+import org.gradle.api.reporting.SingleFileReport;
+import org.gradle.api.reporting.internal.TaskGeneratedSingleDirectoryReport;
+import org.gradle.api.reporting.internal.TaskGeneratedSingleFileReport;
+import org.gradle.api.reporting.internal.TaskReportContainer;
+import org.gradle.testing.jacoco.tasks.JacocoReportsContainer;
+
+public class JacocoReportsContainerImpl extends TaskReportContainer<Report> implements JacocoReportsContainer {
+
+ public JacocoReportsContainerImpl(Task task) {
+ super(ConfigurableReport.class, task);
+ add(TaskGeneratedSingleDirectoryReport.class, "html", task, "index.html");
+ add(TaskGeneratedSingleFileReport.class, "xml", task);
+ add(TaskGeneratedSingleFileReport.class, "csv", task);
+ }
+
+ public DirectoryReport getHtml() {
+ return (DirectoryReport)getByName("html");
+ }
+
+ public SingleFileReport getXml() {
+ return (SingleFileReport)getByName("xml");
+ }
+
+ public SingleFileReport getCsv() {
+ return (SingleFileReport)getByName("csv");
+ }
+}
diff --git a/subprojects/jacoco/src/main/groovy/org/gradle/testing/jacoco/plugins/JacocoPlugin.groovy b/subprojects/jacoco/src/main/groovy/org/gradle/testing/jacoco/plugins/JacocoPlugin.groovy
new file mode 100644
index 0000000..7b18db7
--- /dev/null
+++ b/subprojects/jacoco/src/main/groovy/org/gradle/testing/jacoco/plugins/JacocoPlugin.groovy
@@ -0,0 +1,188 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.testing.jacoco.plugins
+
+import org.gradle.api.Incubating
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.api.plugins.JavaPlugin
+import org.gradle.api.plugins.ReportingBasePlugin
+import org.gradle.api.reporting.Report
+import org.gradle.api.reporting.ReportingExtension
+import org.gradle.api.tasks.testing.Test
+import org.gradle.internal.jacoco.JacocoAgentJar
+import org.gradle.internal.reflect.Instantiator
+import org.gradle.testing.jacoco.tasks.JacocoBase
+import org.gradle.testing.jacoco.tasks.JacocoMerge
+import org.gradle.testing.jacoco.tasks.JacocoReport
+
+import javax.inject.Inject
+
+/**
+ * Plugin that provides support for generating Jacoco coverage data.
+ */
+ at Incubating
+class JacocoPlugin implements Plugin<Project> {
+ static final String AGENT_CONFIGURATION_NAME = 'jacocoAgent'
+ static final String ANT_CONFIGURATION_NAME = 'jacocoAnt'
+ static final String PLUGIN_EXTENSION_NAME = 'jacoco'
+ private final Instantiator instantiator
+
+ private Project project
+
+ /**
+ * Applies the plugin to the given project.
+ * @param project the project to apply to
+ */
+ @Inject
+ JacocoPlugin(Instantiator instantiator) {
+ this.instantiator = instantiator
+ }
+
+ void apply(Project project) {
+ project.plugins.apply(ReportingBasePlugin)
+ this.project = project
+ addJacocoConfigurations()
+ JacocoAgentJar agent = instantiator.newInstance(JacocoAgentJar, project)
+ JacocoPluginExtension extension = project.extensions.create(PLUGIN_EXTENSION_NAME, JacocoPluginExtension, project, agent)
+ ReportingExtension reportingExtension = project.extensions.getByName(ReportingExtension.NAME)
+ extension.conventionMapping.reportsDir = { reportingExtension.file("jacoco") }
+
+ configureAgentDependencies(agent, extension)
+ configureTaskClasspathDefaults(extension)
+ applyToDefaultTasks(extension)
+ configureDefaultOutputPathForJacocoMerge()
+ configureJacocoReportDefaults(project, extension)
+ addDefaultReportTasks(extension)
+ }
+
+ private void configureJacocoReportDefaults(Project project, extension) {
+ project.tasks.withType(JacocoReport) { reportTask ->
+ reportTask.reports.all { report ->
+ report.conventionMapping.with {
+ enabled = report.name == "html"
+ if (report.outputType == Report.OutputType.DIRECTORY) {
+ destination = { new File(extension.reportsDir, "${reportTask.name}/${report.name}") }
+ } else {
+ destination = { new File(extension.reportsDir, "${reportTask.name}/${reportTask.name}.${report.name}") }
+ }
+ }
+ }
+ }
+ }
+
+ def configureDefaultOutputPathForJacocoMerge() {
+ project.tasks.withType(JacocoMerge) { task ->
+ task.conventionMapping.destinationFile = { new File(project.buildDir, "/jacoco/${task.name}.exec") }
+ }
+ }
+
+ /**
+ * Creates the configurations used by plugin.
+ * @param project the project to add the configurations to
+ */
+ private void addJacocoConfigurations() {
+ this.project.configurations.create(AGENT_CONFIGURATION_NAME).with {
+ visible = false
+ transitive = true
+ description = 'The Jacoco agent to use to get coverage data.'
+ }
+ this.project.configurations.create(ANT_CONFIGURATION_NAME).with {
+ visible = false
+ transitive = true
+ description = 'The Jacoco ant tasks to use to get execute Gradle tasks.'
+ }
+ }
+
+ /**
+ * Configures the agent dependencies using the 'jacocoAnt' configuration.
+ * Uses the version declared in 'toolVersion' of the Jacoco extension if no dependencies are explicitly declared.
+ * @param project the project to add the dependencies to
+ * @param extension the extension that has the tool version to use
+ */
+ private void configureAgentDependencies(JacocoAgentJar jacocoAgentJar, JacocoPluginExtension extension) {
+ jacocoAgentJar.conventionMapping.with {
+ agentConf = {
+ def config = this.project.configurations[AGENT_CONFIGURATION_NAME]
+ if (config.dependencies.empty) {
+ this.project.dependencies {
+ jacocoAgent "org.jacoco:org.jacoco.agent:${extension.toolVersion}"
+ }
+ }
+ config
+ }
+ }
+ }
+
+ /**
+ * Configures the classpath for Jacoco tasks using the 'jacocoAnt' configuration.
+ * Uses the version information declared in 'toolVersion' of the Jacoco extension if no dependencies are explicitly declared.
+ * @param extension the JacocoPluginExtension
+ */
+ private void configureTaskClasspathDefaults(JacocoPluginExtension extension) {
+ this.project.tasks.withType(JacocoBase) { task ->
+ task.conventionMapping.with {
+ jacocoClasspath = {
+ def config = this.project.configurations[ANT_CONFIGURATION_NAME]
+ if (config.dependencies.empty) {
+ this.project.dependencies {
+ jacocoAnt "org.jacoco:org.jacoco.ant:${extension.toolVersion}"
+ }
+ }
+ config
+ }
+ }
+ }
+ }
+
+ /**
+ * Applies the Jacoco agent to all tasks of type {@code Test}.
+ * @param extension the extension to apply Jacoco with
+ */
+ private void applyToDefaultTasks(JacocoPluginExtension extension) {
+ project.tasks.withType(Test) {
+ extension.applyTo(it)
+ }
+ }
+
+ /**
+ * Adds report tasks for specific default test tasks.
+ * @param extension the extension describing the test task names
+ */
+ private void addDefaultReportTasks(JacocoPluginExtension extension) {
+ this.project.plugins.withType(JavaPlugin) {
+ this.project.tasks.withType(Test) { task ->
+ if (task.name == JavaPlugin.TEST_TASK_NAME) {
+ JacocoReport reportTask = this.project.tasks.create("jacoco${task.name.capitalize()}Report", JacocoReport)
+ reportTask.executionData task
+ reportTask.sourceSets(this.project.sourceSets.main)
+ reportTask.conventionMapping.with {
+ reportTask.reports.all { report ->
+ report.conventionMapping.with {
+ enabled = { true }
+ if (report.outputType == Report.OutputType.DIRECTORY) {
+ destination = { new File(extension.reportsDir, "${task.name}/${report.name}") }
+ } else {
+ destination = { new File(extension.reportsDir, "${task.name}/${reportTask.name}.${report.name}") }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/subprojects/jacoco/src/main/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginExtension.groovy b/subprojects/jacoco/src/main/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginExtension.groovy
new file mode 100644
index 0000000..b7b8fe9
--- /dev/null
+++ b/subprojects/jacoco/src/main/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginExtension.groovy
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.testing.jacoco.plugins
+
+import org.gradle.api.Incubating
+import org.gradle.api.Project
+import org.gradle.api.logging.Logger
+import org.gradle.api.tasks.TaskCollection
+import org.gradle.internal.jacoco.JacocoAgentJar
+import org.gradle.process.JavaForkOptions
+
+import static org.gradle.api.logging.Logging.getLogger
+
+/**
+ * Extension including common properties and methods for Jacoco.
+ */
+ at Incubating
+class JacocoPluginExtension {
+ static final String TASK_EXTENSION_NAME = 'jacoco'
+
+ Logger logger = getLogger(getClass())
+ /**
+ * Version of Jacoco JARs to use.
+ */
+ String toolVersion = '0.6.2.201302030002'
+
+ protected final Project project
+
+ /**
+ * The directory where reports will be generated.
+ */
+ File reportsDir
+
+ private final JacocoAgentJar agent
+
+ /**
+ * Creates a Jacoco plugin extension.
+ * @param project the project the extension is attached to
+ * @param agent the agent JAR to be used by Jacoco
+ */
+ JacocoPluginExtension(Project project, JacocoAgentJar agent) {
+ this.project = project
+ this.agent = agent
+ }
+
+ /**
+ * Applies Jacoco to the given task. Configuration options will be
+ * provided on a task extension named {@link #TASK_EXTENSION_NAME}.
+ * Jacoco will be run as an agent during the execution of the task.
+ * @param task the task to apply Jacoco to.
+ */
+ void applyTo(JavaForkOptions task) {
+ logger.debug "Applying Jacoco to $task.name"
+ JacocoTaskExtension extension = task.extensions.create(TASK_EXTENSION_NAME, JacocoTaskExtension, agent, task)
+ task.jacoco.conventionMapping.destinationFile = { project.file("${project.buildDir}/jacoco/${task.name}.exec") }
+ task.doFirst {
+ //add agent
+ if (extension.enabled) {
+ task.jvmArgs extension.getAsJvmArg()
+ }
+ }
+ }
+
+ /**
+ * Applies Jacoco to all of the given tasks.
+ * @param tasks the tasks to apply Jacoco to
+ * @see #applyTo(JavaForkOptions)
+ */
+ void applyTo(TaskCollection tasks) {
+ tasks.withType(JavaForkOptions) {
+ applyTo(it)
+ }
+ }
+}
diff --git a/subprojects/jacoco/src/main/groovy/org/gradle/testing/jacoco/plugins/JacocoTaskExtension.groovy b/subprojects/jacoco/src/main/groovy/org/gradle/testing/jacoco/plugins/JacocoTaskExtension.groovy
new file mode 100644
index 0000000..4139ea8
--- /dev/null
+++ b/subprojects/jacoco/src/main/groovy/org/gradle/testing/jacoco/plugins/JacocoTaskExtension.groovy
@@ -0,0 +1,189 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.testing.jacoco.plugins
+
+import org.gradle.api.Incubating
+import org.gradle.internal.jacoco.JacocoAgentJar
+import org.gradle.process.JavaForkOptions
+import org.gradle.util.GFileUtils
+
+/**
+ * Extension for tasks that should run with a Jacoco agent
+ * to generate coverage execution data.
+ */
+ at Incubating
+class JacocoTaskExtension {
+ JacocoAgentJar agent
+
+ /**
+ * Whether or not the task should generate execution data.
+ * Defaults to {@code true}.
+ */
+ boolean enabled = true
+
+ /**
+ * The path for the execution data to be written to.
+ */
+ File destinationFile
+
+ /**
+ * Whether or not data should be appended if the {@code destinationFile}
+ * already exists. Defaults to {@code true}.
+ */
+ boolean append = true
+
+ /**
+ * List of class names that should be included in analysis. Names
+ * can use wildcards (* and ?). If left empty, all classes will
+ * be included. Defaults to an empty list.
+ */
+ List<String> includes = []
+
+ /**
+ * List of class names that should be excluded from analysis. Names
+ * can use wildcard (* and ?). Defaults to an empty list.
+ */
+ List<String> excludes = []
+
+ /**
+ * List of classloader names that should be excluded from analysis. Names
+ * can use wildcards (* and ?). Defaults to an empty list.
+ */
+ List<String> excludeClassLoaders = []
+
+ /**
+ * An identifier for the session written to the execution data. Defaults
+ * to an auto-generated identifier.
+ */
+ String sessionId
+
+ /**
+ * Whether or not to dump the coverage data at VM shutdown. Defaults to {@code true}.
+ */
+ boolean dumpOnExit = true
+
+ /**
+ * THe type of output to generate. Defaults to {@link Output#FILE}.
+ */
+ Output output = Output.FILE
+
+ /**
+ * IP address or hostname to use with {@link Output#TCP_SERVER} or
+ * {@link Output#TCP_CLIENT}. Defaults to localhost.
+ */
+ String address
+
+ /**
+ * Port to bind to for {@link Output#TCP_SERVER} or {@link Output#TCP_CLIENT}.
+ * Defaults to 6300.
+ */
+ int port
+
+ /**
+ * Path to dump all class files the agent sees are dumped to. Defaults to no dumps.
+ */
+ File classDumpFile
+
+ /**
+ * Whether or not to expose functionality via JMX under {@code org.jacoco:type=Runtime}.
+ * Defaults to {@code false}.
+ *
+ * The configuration of the jmx property is only taken into account if the used JaCoCo version
+ * supports this option (JaCoCo version >= 0.6.2)
+ */
+ boolean jmx = false
+
+ /**
+ * The task we extend
+ */
+ private JavaForkOptions task
+
+ /**
+ * Creates a Jacoco task extension.
+ * @param project the project the task is attached to
+ * @param agent the agent JAR to use for analysis
+ */
+ JacocoTaskExtension(JacocoAgentJar agent, JavaForkOptions task) {
+ this.agent = agent
+ this.task = task;
+ }
+
+ /**
+ * Gets all properties in the format expected of the agent JVM argument.
+ * @return state of extension in a JVM argument
+ */
+ String getAsJvmArg() {
+ StringBuilder builder = new StringBuilder()
+ boolean anyArgs = false
+ File workingDirectory = task.getWorkingDir()
+ Closure arg = { name, value ->
+ if (value instanceof Boolean || value) {
+ if (anyArgs) {
+ builder << ','
+ }
+ builder << name
+ builder << '='
+ if (value instanceof Collection) {
+ builder << value.join(':')
+ } else if (value instanceof File) {
+ builder << GFileUtils.relativePath(workingDirectory, value)
+ } else {
+ builder << value
+ }
+ anyArgs = true
+ }
+ }
+
+ builder << '-javaagent:'
+
+ builder << GFileUtils.relativePath(task.getWorkingDir(), agent.jar)
+ builder << '='
+ arg 'destfile', getDestinationFile()
+ arg 'append', getAppend()
+ arg 'includes', getIncludes()
+ arg 'excludes', getExcludes()
+ arg 'exclclassloader', getExcludeClassLoaders()
+ arg 'sessionid', getSessionId()
+ arg 'dumponexit', getDumpOnExit()
+ arg 'output', getOutput().asArg
+ arg 'address', getAddress()
+ arg 'port', getPort()
+ arg 'classdumpdir', classDumpFile
+
+ if (agent.supportsJmx()) {
+ arg 'jmx', getJmx()
+ }
+ return builder.toString()
+ }
+
+/**
+ * The types of output that the agent
+ * can use for execution data.
+ */
+ enum Output {
+ FILE,
+ TCP_SERVER,
+ TCP_CLIENT,
+ NONE
+
+ /**
+ * Gets type in format of agent argument.
+ */
+ String getAsArg() {
+ return toString().toLowerCase().replaceAll('_', '')
+ }
+ }
+}
\ No newline at end of file
diff --git a/subprojects/jacoco/src/main/groovy/org/gradle/testing/jacoco/tasks/JacocoBase.groovy b/subprojects/jacoco/src/main/groovy/org/gradle/testing/jacoco/tasks/JacocoBase.groovy
new file mode 100644
index 0000000..ec4768f
--- /dev/null
+++ b/subprojects/jacoco/src/main/groovy/org/gradle/testing/jacoco/tasks/JacocoBase.groovy
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.testing.jacoco.tasks
+
+import org.gradle.api.DefaultTask
+import org.gradle.api.Incubating
+import org.gradle.api.file.FileCollection
+import org.gradle.api.tasks.InputFiles
+
+/**
+ * Base class for Jacoco tasks.
+ */
+ at Incubating
+abstract class JacocoBase extends DefaultTask {
+ /**
+ * Classpath containing Jacoco classes for use by the task.
+ */
+ @InputFiles
+ FileCollection jacocoClasspath
+}
diff --git a/subprojects/jacoco/src/main/groovy/org/gradle/testing/jacoco/tasks/JacocoMerge.groovy b/subprojects/jacoco/src/main/groovy/org/gradle/testing/jacoco/tasks/JacocoMerge.groovy
new file mode 100644
index 0000000..43df564
--- /dev/null
+++ b/subprojects/jacoco/src/main/groovy/org/gradle/testing/jacoco/tasks/JacocoMerge.groovy
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.testing.jacoco.tasks
+
+import org.gradle.api.Incubating
+import org.gradle.api.Task
+import org.gradle.api.file.FileCollection
+import org.gradle.api.tasks.InputFiles
+import org.gradle.api.tasks.OutputFile
+import org.gradle.api.tasks.TaskAction
+import org.gradle.api.tasks.TaskCollection
+import org.gradle.testing.jacoco.plugins.JacocoTaskExtension
+
+/**
+ * Task to merge multiple execution data files into one.
+ */
+ at Incubating
+class JacocoMerge extends JacocoBase {
+ /**
+ * Collection of execution data files to merge.
+ */
+ @InputFiles
+ FileCollection executionData
+
+ /**
+ * File to write merged execution data to.
+ */
+ @OutputFile
+ File destinationFile
+
+ @TaskAction
+ void merge() {
+ getAnt().taskdef(name: 'jacocoMerge', classname: 'org.jacoco.ant.MergeTask', classpath: getJacocoClasspath().asPath)
+ getAnt().jacocoMerge(destfile: getDestinationFile()) {
+ getExecutionData().addToAntBuilder(ant, 'resources')
+ }
+ }
+
+ /**
+ * Adds execution data files to be merged.
+ * @param files one or more files to merge
+ */
+ void executionData(Object... files) {
+ if (this.executionData == null) {
+ this.executionData = getProject().files(files)
+ } else {
+ this.executionData += getProject().files(files)
+ }
+ }
+
+ /**
+ * Adds execution data generated by a task to the list
+ * of those to merge. Only tasks
+ * with a {@link JacocoTaskExtension} will be included;
+ * all others will be ignored.
+ * @param tasks one or more tasks to merge
+ */
+ void executionData(Task... tasks) {
+ tasks.each { task ->
+ JacocoTaskExtension extension = task.extensions.findByType(JacocoTaskExtension)
+ if (extension != null) {
+ executionData(project.files(extension.destinationFile) {
+ builtBy task
+ })
+ }
+ }
+ }
+
+ /**
+ * Adds execution data generated by the given tasks to
+ * the list of those merged.
+ * Only tasks with a {@link JacocoTaskExtension} will
+ * be included; all others will be ignored.
+ * @param tasks one or more tasks to merge
+ */
+ void executionData(TaskCollection tasks) {
+ tasks.all { executionData(it) }
+ }
+}
diff --git a/subprojects/jacoco/src/main/groovy/org/gradle/testing/jacoco/tasks/JacocoReport.groovy b/subprojects/jacoco/src/main/groovy/org/gradle/testing/jacoco/tasks/JacocoReport.groovy
new file mode 100644
index 0000000..01027e7
--- /dev/null
+++ b/subprojects/jacoco/src/main/groovy/org/gradle/testing/jacoco/tasks/JacocoReport.groovy
@@ -0,0 +1,258 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.testing.jacoco.tasks
+
+import org.gradle.api.Incubating
+import org.gradle.api.Task
+import org.gradle.api.file.FileCollection
+import org.gradle.api.reporting.Reporting
+import org.gradle.api.tasks.*
+import org.gradle.internal.jacoco.JacocoReportsContainerImpl
+import org.gradle.internal.reflect.Instantiator
+import org.gradle.testing.jacoco.plugins.JacocoTaskExtension
+
+import javax.inject.Inject
+
+/**
+ * Task to generate HTML, Xml and CSV reports of Jacoco coverage data.
+ */
+ at Incubating
+class JacocoReport extends JacocoBase implements Reporting<JacocoReportsContainer> {
+ /**
+ * Collection of execution data files to analyze.
+ */
+ @InputFiles
+ FileCollection executionData
+
+ /**
+ * Source sets that coverage should be reported for.
+ */
+ @InputFiles
+ FileCollection sourceDirectories
+
+ /**
+ * Source sets that coverage should be reported for.
+ */
+ @InputFiles
+ FileCollection classDirectories
+
+ /**
+ * Additional class dirs that coverage data should be reported for.
+ */
+ @Optional
+ @InputFiles
+ FileCollection additionalClassDirs
+
+ /**
+ * Additional source dirs for the classes coverage data is being reported for.
+ */
+ @Optional
+ @InputFiles
+ FileCollection additionalSourceDirs
+
+ @Nested
+ private final JacocoReportsContainerImpl reports
+
+ @Inject JacocoReport(Instantiator instantiator) {
+ reports = instantiator.newInstance(JacocoReportsContainerImpl, this)
+ onlyIf { getExecutionData().every { it.exists() } }
+ }
+
+ @TaskAction
+ void generate() {
+ getAnt().taskdef(name: 'jacocoReport', classname: 'org.jacoco.ant.ReportTask', classpath: getJacocoClasspath().asPath)
+ getAnt().jacocoReport {
+ executiondata {
+ getExecutionData().addToAntBuilder(getAnt(), 'resources')
+ }
+ structure(name: getProject().getName()) {
+ classfiles {
+ getAllClassDirs().filter { it.exists() }.addToAntBuilder(getAnt(), 'resources')
+ }
+ sourcefiles {
+ getAllSourceDirs().filter { it.exists() }.addToAntBuilder(getAnt(), 'resources')
+ }
+ }
+ if(reports.html.isEnabled()) {
+ html(destdir: reports.html.destination)
+ }
+ if(reports.xml.isEnabled()) {
+ xml(destfile: reports.xml.destination)
+ }
+ if(reports.csv.isEnabled()) {
+ csv(destfile: reports.csv.destination)
+ }
+ }
+ }
+
+ /**
+ * Adds execution data files to be used during coverage
+ * analysis.
+ * @param files one or more files to add
+ */
+ void executionData(Object... files) {
+ if (this.executionData == null) {
+ this.executionData = getProject().files(files)
+ } else {
+ this.executionData += getProject().files(files)
+ }
+ }
+
+ /**
+ * Adds execution data generated by a task to the list
+ * of those used during coverage analysis. Only tasks
+ * with a {@link JacocoTaskExtension} will be included;
+ * all others will be ignored.
+ * @param tasks one or more tasks to add
+ */
+ void executionData(Task... tasks) {
+ tasks.each { task ->
+ JacocoTaskExtension extension = task.extensions.findByType(JacocoTaskExtension)
+ if (extension != null) {
+ executionData({ extension.destinationFile })
+ mustRunAfter(task)
+ }
+ }
+ }
+
+ /**
+ * Adds execution data generated by the given tasks to
+ * the list of those used during coverage analysis.
+ * Only tasks with a {@link JacocoTaskExtension} will
+ * be included; all others will be ignored.
+ * @param tasks one or more tasks to add
+ */
+ void executionData(TaskCollection tasks) {
+ tasks.all { executionData(it) }
+ }
+
+ /**
+ * Gets the class directories that coverage will
+ * be reported for. All classes in these directories
+ * will be included in the report.
+ * @return class dirs to report coverage of
+ */
+ FileCollection getAllClassDirs() {
+ def additionalDirs = getAdditionalClassDirs()
+ if (additionalDirs == null) {
+ return classDirectories
+ }
+ return classDirectories + getAdditionalClassDirs()
+ }
+
+ /**
+ * Gets the source directories for the classes that will
+ * be reported on. Source will be obtained from these
+ * directories only for the classes included in the report.
+ * @return source directories for the classes reported on
+ * @see #getAllClassDirs()
+ */
+ FileCollection getAllSourceDirs() {
+ def additionalDirs = getAdditionalSourceDirs()
+ if (additionalDirs == null) {
+ return sourceDirectories
+ }
+ return sourceDirectories + getAdditionalSourceDirs()
+ }
+
+ /**
+ * Adds a source set to the list to be reported on. The
+ * output of this source set will be used as classes to
+ * include in the report. The source for this source set
+ * will be used for any classes included in the report.
+ * @param sourceSets one or more source sets to report on
+ */
+ void sourceSets(SourceSet... sourceSets) {
+ getProject().afterEvaluate {
+ sourceSets.each { sourceSet ->
+ if (this.sourceDirectories == null) {
+ this.sourceDirectories = sourceSet.allJava
+ } else {
+ this.sourceDirectories = this.sourceDirectories + sourceSet.allJava
+ }
+ if (this.classDirectories == null) {
+ this.classDirectories = sourceSet.output
+ } else {
+ this.classDirectories = this.classDirectories + sourceSet.output
+ }
+ }
+ }
+ }
+
+ /**
+ * Adds additional class directories to those
+ * that will be included in the report.
+ * @param dirs one or more directories containing
+ * classes to report coverage of
+ */
+ void additionalClassDirs(File... dirs) {
+ additionalClassDirs(getProject().files(dirs))
+ }
+
+ /**
+ * Adds additional class directories to those
+ * that will be included in the report.
+ * @param dirs a {@code FileCollection} of directories
+ * containing classes to report coverage of
+ */
+ void additionalClassDirs(FileCollection dirs) {
+ if (this.additionalClassDirs == null) {
+ this.additionalClassDirs = dirs
+ } else {
+ this.additionalClassDirs += dirs
+ }
+ }
+
+ /**
+ * Adds additional source directories to be used
+ * for any classes included in the report.
+ * @param dirs one or more directories containing
+ * source files for the classes included in the report
+ */
+ void additionalSourceDirs(File... dirs) {
+ additionalSourceDirs(getProject().files(dirs))
+ }
+
+ /**
+ * Adds additional source directories to be used
+ * for any classes included in the report.
+ * @param dirs a {@code FileCollection} of directories
+ * containing source files for the classes included in
+ * the report
+ */
+ void additionalSourceDirs(FileCollection dirs) {
+ if (this.additionalSourceDirs == null) {
+ this.additionalSourceDirs = dirs
+ } else {
+ this.additionalSourceDirs += dirs
+ }
+ }
+
+ /**
+ * Configures the reports to be generated by this task.
+ */
+ JacocoReportsContainer reports(Closure closure) {
+ reports.configure(closure)
+ }
+
+ /**
+ * Returns the reports to be generated by this task.
+ */
+ JacocoReportsContainer getReports() {
+ return reports
+ }
+
+}
diff --git a/subprojects/jacoco/src/main/groovy/org/gradle/testing/jacoco/tasks/JacocoReportsContainer.java b/subprojects/jacoco/src/main/groovy/org/gradle/testing/jacoco/tasks/JacocoReportsContainer.java
new file mode 100644
index 0000000..907af98
--- /dev/null
+++ b/subprojects/jacoco/src/main/groovy/org/gradle/testing/jacoco/tasks/JacocoReportsContainer.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.testing.jacoco.tasks;
+
+import org.gradle.api.Incubating;
+import org.gradle.api.reporting.*;
+
+/**
+ * The reporting configuration for the the {@link JacocoReport} task.
+ */
+ at Incubating
+public interface JacocoReportsContainer extends ReportContainer<Report> {
+ /**
+ * The JaCoCo HTML report
+ *
+ * @return The JaCoCo HTML report
+ */
+ DirectoryReport getHtml();
+
+ /**
+ * The JaCoCo (single file) XML report
+ *
+ * @return The JaCoCo (single file) XML report
+ */
+ SingleFileReport getXml();
+
+ /**
+ * The JaCoCo (single file) CSV report
+ *
+ * @return The JaCoCo (single file) CSV report
+ */
+ SingleFileReport getCsv();
+}
diff --git a/subprojects/jacoco/src/main/groovy/org/gradle/testing/jacoco/tasks/package-info.java b/subprojects/jacoco/src/main/groovy/org/gradle/testing/jacoco/tasks/package-info.java
new file mode 100644
index 0000000..67becd9
--- /dev/null
+++ b/subprojects/jacoco/src/main/groovy/org/gradle/testing/jacoco/tasks/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+/**
+ * Tasks to work with the JaCoCo code coverage library.
+ */
+package org.gradle.testing.jacoco.tasks;
\ No newline at end of file
diff --git a/subprojects/jacoco/src/main/resources/META-INF/gradle-plugins/jacoco.properties b/subprojects/jacoco/src/main/resources/META-INF/gradle-plugins/jacoco.properties
new file mode 100644
index 0000000..6d71042
--- /dev/null
+++ b/subprojects/jacoco/src/main/resources/META-INF/gradle-plugins/jacoco.properties
@@ -0,0 +1 @@
+implementation-class=org.gradle.testing.jacoco.plugins.JacocoPlugin
diff --git a/subprojects/jacoco/src/test/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginSpec.groovy b/subprojects/jacoco/src/test/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginSpec.groovy
new file mode 100644
index 0000000..3d2d7e6
--- /dev/null
+++ b/subprojects/jacoco/src/test/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginSpec.groovy
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.testing.jacoco.plugins
+
+import org.gradle.api.Project
+import org.gradle.api.tasks.JavaExec
+import org.gradle.api.tasks.testing.Test
+import org.gradle.testing.jacoco.tasks.JacocoReport
+import org.gradle.util.TestUtil
+import spock.lang.Specification
+
+class JacocoPluginSpec extends Specification {
+ Project project = TestUtil.createRootProject()
+
+ def setup() {
+ project.apply plugin: 'jacoco'
+ }
+
+ def 'jacoco plugin adds coverage report for test task when java plugin applied'() {
+ when:
+ project.apply plugin:"java"
+ and:
+ project.evaluate()
+ then:
+ project.test.extensions.getByType(JacocoTaskExtension) != null
+ project.jacocoTestReport instanceof JacocoReport
+ project.jacocoTestReport.sourceDirectories == project.sourceSets.main.allJava
+ project.jacocoTestReport.classDirectories == project.sourceSets.main.output
+ }
+
+ def 'jacoco applied to specific JavaExec task'() {
+ given:
+ JavaExec task = project.tasks.create('exec', JavaExec)
+ when:
+ project.jacoco.applyTo(task)
+ then:
+ task.extensions.getByType(JacocoTaskExtension) != null
+ }
+
+ def 'jacoco applied to Test task'() {
+ given:
+ Test task = project.tasks.create('customTest', Test)
+ expect:
+ task.extensions.getByType(JacocoTaskExtension) != null
+ }
+}
diff --git a/subprojects/jacoco/src/test/groovy/org/gradle/testing/jacoco/plugins/JacocoTaskExtensionSpec.groovy b/subprojects/jacoco/src/test/groovy/org/gradle/testing/jacoco/plugins/JacocoTaskExtensionSpec.groovy
new file mode 100644
index 0000000..da8c566
--- /dev/null
+++ b/subprojects/jacoco/src/test/groovy/org/gradle/testing/jacoco/plugins/JacocoTaskExtensionSpec.groovy
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.testing.jacoco.plugins
+
+import org.gradle.internal.jacoco.JacocoAgentJar
+import org.gradle.process.JavaForkOptions
+import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
+import org.junit.Rule
+import spock.lang.Specification
+
+class JacocoTaskExtensionSpec extends Specification {
+ JacocoAgentJar agent = Mock()
+ JavaForkOptions task = Mock()
+ JacocoTaskExtension extension = new JacocoTaskExtension(agent, task)
+ @Rule final TestNameTestDirectoryProvider temporaryFolder = new TestNameTestDirectoryProvider()
+
+ def 'asJvmArg with default arguments assembles correct string'() {
+ setup:
+ agent.supportsJmx() >> true
+ agent.jar >> temporaryFolder.file('fakeagent.jar')
+ task.getWorkingDir() >> temporaryFolder.file(".")
+ expect:
+ extension.asJvmArg == "-javaagent:fakeagent.jar=append=true,dumponexit=true,output=file,jmx=false"
+ }
+
+ def 'supports jacocoagent with no jmx support'() {
+ given:
+ agent.supportsJmx() >> false
+ agent.jar >> temporaryFolder.file('fakeagent.jar')
+ task.getWorkingDir() >> temporaryFolder.file("workingDir")
+
+ expect:
+ extension.asJvmArg == "-javaagent:../fakeagent.jar=append=true,dumponexit=true,output=file"
+ }
+
+ def 'asJvmArg with all arguments assembles correct string'() {
+ given:
+ agent.supportsJmx() >> true
+ agent.jar >> temporaryFolder.file('workingDir/subfolder/fakeagent.jar')
+ task.getWorkingDir() >> temporaryFolder.file("workingDir")
+
+ extension.with {
+ destinationFile = temporaryFolder.file('build/jacoco/fake.exec')
+ append = false
+ includes = ['org.*', '*.?acoco*']
+ excludes = ['org.?joberstar']
+ excludeClassLoaders = ['com.sun.*', 'org.fak?.*']
+ sessionId = 'testSession'
+ dumpOnExit = false
+ output = JacocoTaskExtension.Output.TCP_SERVER
+ address = '1.1.1.1'
+ port = 100
+ classDumpFile = temporaryFolder.file('build/jacoco-dump')
+ jmx = true
+ }
+
+ def expected = new StringBuilder().with { builder ->
+ builder << "-javaagent:subfolder/fakeagent.jar="
+ builder << "destfile=../build/jacoco/fake.exec,"
+ builder << "append=false,"
+ builder << "includes=org.*:*.?acoco*,"
+ builder << "excludes=org.?joberstar,"
+ builder << "exclclassloader=com.sun.*:org.fak?.*,"
+ builder << "sessionid=testSession,"
+ builder << "dumponexit=false,"
+ builder << "output=tcpserver,"
+ builder << "address=1.1.1.1,"
+ builder << "port=100,"
+ builder << "classdumpdir=../build/jacoco-dump,"
+ builder << "jmx=true"
+ builder.toString()
+ }
+ expect:
+ extension.asJvmArg == expected
+ }
+
+ def 'asJvmArg fails if agent cannot extract the JAR'() {
+ given:
+ agent.jar >> { throw new Exception() }
+ when:
+ extension.asJvmArg
+ then:
+ thrown Exception
+ }
+
+}
diff --git a/subprojects/javascript/javascript.gradle b/subprojects/javascript/javascript.gradle
index ce4823b..78f0a42 100644
--- a/subprojects/javascript/javascript.gradle
+++ b/subprojects/javascript/javascript.gradle
@@ -15,7 +15,7 @@
*/
dependencies {
- groovy libraries.groovy
+ compile libraries.groovy
compile "org.mozilla:rhino:1.7R3"
compile "com.google.code.gson:gson:2.2.1" // used by JsHint
diff --git a/subprojects/javascript/src/main/groovy/org/gradle/plugins/javascript/coffeescript/CoffeeScriptBasePlugin.groovy b/subprojects/javascript/src/main/groovy/org/gradle/plugins/javascript/coffeescript/CoffeeScriptBasePlugin.groovy
index a20e82a..922e817 100644
--- a/subprojects/javascript/src/main/groovy/org/gradle/plugins/javascript/coffeescript/CoffeeScriptBasePlugin.groovy
+++ b/subprojects/javascript/src/main/groovy/org/gradle/plugins/javascript/coffeescript/CoffeeScriptBasePlugin.groovy
@@ -54,7 +54,7 @@ class CoffeeScriptBasePlugin implements Plugin<Project> {
}
private Configuration addJsConfiguration(ConfigurationContainer configurations, DependencyHandler dependencies, CoffeeScriptExtension extension) {
- Configuration configuration = configurations.add(CoffeeScriptExtension.JS_CONFIGURATION_NAME)
+ Configuration configuration = configurations.create(CoffeeScriptExtension.JS_CONFIGURATION_NAME)
configuration.incoming.beforeResolve(new Action<ResolvableDependencies>() {
void execute(ResolvableDependencies resolvableDependencies) {
if (configuration.dependencies.empty) {
diff --git a/subprojects/javascript/src/main/groovy/org/gradle/plugins/javascript/envjs/EnvJsPlugin.groovy b/subprojects/javascript/src/main/groovy/org/gradle/plugins/javascript/envjs/EnvJsPlugin.groovy
index 70de3d9..301bf91 100644
--- a/subprojects/javascript/src/main/groovy/org/gradle/plugins/javascript/envjs/EnvJsPlugin.groovy
+++ b/subprojects/javascript/src/main/groovy/org/gradle/plugins/javascript/envjs/EnvJsPlugin.groovy
@@ -83,7 +83,7 @@ class EnvJsPlugin implements Plugin<Project> {
}
Configuration addConfiguration(ConfigurationContainer configurations, DependencyHandler dependencies, EnvJsExtension extension) {
- Configuration configuration = configurations.add(EnvJsExtension.CONFIGURATION_NAME)
+ Configuration configuration = configurations.create(EnvJsExtension.CONFIGURATION_NAME)
configuration.incoming.beforeResolve(new Action<ResolvableDependencies>() {
void execute(ResolvableDependencies resolvableDependencies) {
if (configuration.dependencies.empty) {
diff --git a/subprojects/javascript/src/main/groovy/org/gradle/plugins/javascript/jshint/JsHintPlugin.groovy b/subprojects/javascript/src/main/groovy/org/gradle/plugins/javascript/jshint/JsHintPlugin.groovy
index 30039b9..767ce78 100644
--- a/subprojects/javascript/src/main/groovy/org/gradle/plugins/javascript/jshint/JsHintPlugin.groovy
+++ b/subprojects/javascript/src/main/groovy/org/gradle/plugins/javascript/jshint/JsHintPlugin.groovy
@@ -58,7 +58,7 @@ class JsHintPlugin implements Plugin<Project> {
}
Configuration addConfiguration(ConfigurationContainer configurations, DependencyHandler dependencies, JsHintExtension extension) {
- Configuration configuration = configurations.add(JsHintExtension.CONFIGURATION_NAME)
+ Configuration configuration = configurations.create(JsHintExtension.CONFIGURATION_NAME)
configuration.incoming.beforeResolve(new Action<ResolvableDependencies>() {
void execute(ResolvableDependencies resolvableDependencies) {
if (configuration.dependencies.empty) {
diff --git a/subprojects/jetty/jetty.gradle b/subprojects/jetty/jetty.gradle
index 6f54116..8b8e054 100644
--- a/subprojects/jetty/jetty.gradle
+++ b/subprojects/jetty/jetty.gradle
@@ -14,7 +14,7 @@
* limitations under the License.
*/
dependencies {
- groovy libraries.groovy
+ compile libraries.groovy
compile project(':core')
compile project(':plugins')
diff --git a/subprojects/jetty/src/main/java/org/gradle/api/plugins/jetty/AbstractJettyRunTask.java b/subprojects/jetty/src/main/java/org/gradle/api/plugins/jetty/AbstractJettyRunTask.java
index 257ce8a..0d37e46 100644
--- a/subprojects/jetty/src/main/java/org/gradle/api/plugins/jetty/AbstractJettyRunTask.java
+++ b/subprojects/jetty/src/main/java/org/gradle/api/plugins/jetty/AbstractJettyRunTask.java
@@ -74,19 +74,12 @@ public abstract class AbstractJettyRunTask extends ConventionTask {
*/
private File overrideWebXml;
- /**
- * The interval in seconds to scan the webapp for changes and restart the context if necessary. Ignored if reload is enabled. Disabled by default.
- */
private int scanIntervalSeconds;
- /**
- * reload can be set to either 'automatic' or 'manual' <p/> if 'manual' then the context can be reloaded by a linefeed in the console if 'automatic' then traditional reloading on changed files is
- * enabled.
- */
protected String reload;
/**
- * Location of a jetty xml configuration file whose contents will be applied before any plugin configuration. Optional.
+ * Location of a jetty XML configuration file whose contents will be applied before any plugin configuration. Optional.
*/
private File jettyConfig;
@@ -413,10 +406,22 @@ public abstract class AbstractJettyRunTask extends ConventionTask {
this.overrideWebXml = overrideWebXml;
}
+ /**
+ * Returns the interval in seconds between scanning the web app for file changes.
+ * If file changes are detected, the web app is reloaded. Only relevant
+ * if {@code reload} is set to {@code "automatic"}. Defaults to {@code 0},
+ * which <em>disables</em> automatic reloading.
+ */
public int getScanIntervalSeconds() {
return scanIntervalSeconds;
}
+ /**
+ * Sets the interval in seconds between scanning the web app for file changes.
+ * If file changes are detected, the web app is reloaded. Only relevant
+ * if {@code reload} is set to {@code "automatic"}. Defaults to {@code 0},
+ * which <em>disables</em> automatic reloading.
+ */
public void setScanIntervalSeconds(int scanIntervalSeconds) {
this.scanIntervalSeconds = scanIntervalSeconds;
}
@@ -440,10 +445,30 @@ public abstract class AbstractJettyRunTask extends ConventionTask {
this.webAppConfig = webAppConfig;
}
+ /**
+ * Returns the reload mode, which is either {@code "automatic"} or {@code "manual"}.
+ *
+ * <p>In automatic mode, the web app is scanned for file changes every n seconds, where n is
+ * determined by the {@code scanIntervalSeconds} property. (Note that {@code scanIntervalSeconds}
+ * defaults to {@code 0}, which <em>disables</em> automatic reloading.) If files changes are
+ * detected, the web app is reloaded.
+ *
+ * <p>In manual mode, the web app is reloaded whenever the Enter key is pressed.
+ */
public String getReload() {
return reload;
}
+ /**
+ * Sets the reload mode, which is either {@code "automatic"} or {@code "manual"}.
+ *
+ * <p>In automatic mode, the web app is scanned for file changes every n seconds, where n is
+ * determined by the {@code scanIntervalSeconds} property. (Note that {@code scanIntervalSeconds}
+ * defaults to {@code 0}, which <em>disables</em> automatic reloading.) If files changes are
+ * detected, the web app is reloaded.
+ *
+ * <p>In manual mode, the web app is reloaded whenever the Enter key is pressed.
+ */
public void setReload(String reload) {
this.reload = reload;
}
diff --git a/subprojects/jetty/src/main/java/org/gradle/api/plugins/jetty/JettyPlugin.java b/subprojects/jetty/src/main/java/org/gradle/api/plugins/jetty/JettyPlugin.java
index f08091b..b21d1e8 100644
--- a/subprojects/jetty/src/main/java/org/gradle/api/plugins/jetty/JettyPlugin.java
+++ b/subprojects/jetty/src/main/java/org/gradle/api/plugins/jetty/JettyPlugin.java
@@ -31,8 +31,6 @@ import java.util.concurrent.Callable;
/**
* <p>A {@link Plugin} which extends the {@link WarPlugin} to add tasks which run the web application using an embedded
* Jetty web container.</p>
- *
- * @author Hans Dockter
*/
public class JettyPlugin implements Plugin<Project> {
public static final String JETTY_RUN = "jettyRun";
@@ -74,13 +72,13 @@ public class JettyPlugin implements Plugin<Project> {
}
});
- JettyRunWar jettyRunWar = project.getTasks().add(JETTY_RUN_WAR, JettyRunWar.class);
+ JettyRunWar jettyRunWar = project.getTasks().create(JETTY_RUN_WAR, JettyRunWar.class);
jettyRunWar.setDescription("Assembles the webapp into a war and deploys it to Jetty.");
jettyRunWar.setGroup(WarPlugin.WEB_APP_GROUP);
}
private void configureJettyStop(Project project, final JettyPluginConvention jettyConvention) {
- JettyStop jettyStop = project.getTasks().add(JETTY_STOP, JettyStop.class);
+ JettyStop jettyStop = project.getTasks().create(JETTY_STOP, JettyStop.class);
jettyStop.setDescription("Stops Jetty.");
jettyStop.setGroup(WarPlugin.WEB_APP_GROUP);
jettyStop.getConventionMapping().map("stopPort", new Callable<Object>() {
@@ -116,7 +114,7 @@ public class JettyPlugin implements Plugin<Project> {
}
});
- JettyRun jettyRun = project.getTasks().add(JETTY_RUN, JettyRun.class);
+ JettyRun jettyRun = project.getTasks().create(JETTY_RUN, JettyRun.class);
jettyRun.setDescription("Uses your files as and where they are and deploys them to Jetty.");
jettyRun.setGroup(WarPlugin.WEB_APP_GROUP);
}
diff --git a/subprojects/jetty/src/main/java/org/gradle/api/plugins/jetty/JettyPluginConvention.java b/subprojects/jetty/src/main/java/org/gradle/api/plugins/jetty/JettyPluginConvention.java
index 749b340..7021820 100644
--- a/subprojects/jetty/src/main/java/org/gradle/api/plugins/jetty/JettyPluginConvention.java
+++ b/subprojects/jetty/src/main/java/org/gradle/api/plugins/jetty/JettyPluginConvention.java
@@ -17,8 +17,6 @@ package org.gradle.api.plugins.jetty;
/**
* Convention properties and methods added by the {@link org.gradle.api.plugins.jetty.JettyPlugin}.
- *
- * @author Hans Dockter
*/
public class JettyPluginConvention {
private Integer stopPort;
diff --git a/subprojects/jetty/src/main/java/org/gradle/api/plugins/jetty/JettyRun.java b/subprojects/jetty/src/main/java/org/gradle/api/plugins/jetty/JettyRun.java
index 440ccde..18d0d29 100644
--- a/subprojects/jetty/src/main/java/org/gradle/api/plugins/jetty/JettyRun.java
+++ b/subprojects/jetty/src/main/java/org/gradle/api/plugins/jetty/JettyRun.java
@@ -53,8 +53,6 @@ import java.util.Set;
* automatically performing a hot redeploy when necessary. This allows the developer to concentrate on coding changes to
* the project using their IDE of choice and have those changes immediately and transparently reflected in the running
* web container, eliminating development time that is wasted on rebuilding, reassembling and redeploying. </p>
- *
- * @author janb
*/
public class JettyRun extends AbstractJettyRunTask {
private static Logger logger = LoggerFactory.getLogger(JettyRun.class);
@@ -75,7 +73,7 @@ public class JettyRun extends AbstractJettyRunTask {
private File webXml;
/**
- * Root directory for all html/jsp etc files.
+ * Root directory for all HTML/JSP etc files.
*/
private File webAppSourceDirectory;
diff --git a/subprojects/jetty/src/test/groovy/org/gradle/api/plugins/jetty/JettyPluginTest.groovy b/subprojects/jetty/src/test/groovy/org/gradle/api/plugins/jetty/JettyPluginTest.groovy
index 219ba03..b122cd1 100644
--- a/subprojects/jetty/src/test/groovy/org/gradle/api/plugins/jetty/JettyPluginTest.groovy
+++ b/subprojects/jetty/src/test/groovy/org/gradle/api/plugins/jetty/JettyPluginTest.groovy
@@ -18,14 +18,14 @@ package org.gradle.api.plugins.jetty
import org.gradle.api.Project
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.plugins.WarPlugin
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import org.junit.Test
import static org.gradle.util.Matchers.*
import static org.hamcrest.Matchers.*
import static org.junit.Assert.*
public class JettyPluginTest {
- private final Project project = HelperUtil.createRootProject()
+ private final Project project = TestUtil.createRootProject()
@Test
public void appliesWarPluginAndAddsConventionToProject() {
@@ -59,11 +59,11 @@ public class JettyPluginTest {
public void addsMappingToNewJettyTasks() {
new JettyPlugin().apply(project)
- def task = project.tasks.add('customRun', JettyRun)
+ def task = project.tasks.create('customRun', JettyRun)
assertThat(task, dependsOn(JavaPlugin.CLASSES_TASK_NAME))
assertThat(task.httpPort, equalTo(project.httpPort))
- task = project.tasks.add('customWar', JettyRunWar)
+ task = project.tasks.create('customWar', JettyRunWar)
assertThat(task, dependsOn(WarPlugin.WAR_TASK_NAME))
assertThat(task.httpPort, equalTo(project.httpPort))
}
diff --git a/subprojects/language-base/language-base.gradle b/subprojects/language-base/language-base.gradle
new file mode 100644
index 0000000..290970f
--- /dev/null
+++ b/subprojects/language-base/language-base.gradle
@@ -0,0 +1,7 @@
+dependencies {
+ compile libraries.groovy
+ compile project(":core")
+}
+
+useClassycle()
+useTestFixtures()
diff --git a/subprojects/language-base/src/main/groovy/org/gradle/language/base/Binary.java b/subprojects/language-base/src/main/groovy/org/gradle/language/base/Binary.java
new file mode 100644
index 0000000..f67f0b1
--- /dev/null
+++ b/subprojects/language-base/src/main/groovy/org/gradle/language/base/Binary.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.language.base;
+
+import org.gradle.api.Incubating;
+import org.gradle.api.Named;
+import org.gradle.api.internal.HasInternalProtocol;
+
+/**
+ * A physical binary artifact, which can run on a particular platform or runtime.
+ */
+ at Incubating @HasInternalProtocol
+public interface Binary extends BuildableModelElement, Named {
+}
diff --git a/subprojects/language-base/src/main/groovy/org/gradle/language/base/BinaryContainer.java b/subprojects/language-base/src/main/groovy/org/gradle/language/base/BinaryContainer.java
new file mode 100644
index 0000000..20d7f1a
--- /dev/null
+++ b/subprojects/language-base/src/main/groovy/org/gradle/language/base/BinaryContainer.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.language.base;
+
+import org.gradle.api.*;
+
+/**
+ * A container for project binaries, which represent physical artifacts that can run on a particular platform or runtime.
+ * Added to a project by the {@link org.gradle.language.base.plugins.LanguageBasePlugin}.
+ */
+ at Incubating
+public interface BinaryContainer extends ExtensiblePolymorphicDomainObjectContainer<Binary> {}
diff --git a/subprojects/language-base/src/main/groovy/org/gradle/language/base/BuildableModelElement.java b/subprojects/language-base/src/main/groovy/org/gradle/language/base/BuildableModelElement.java
new file mode 100644
index 0000000..2db579c
--- /dev/null
+++ b/subprojects/language-base/src/main/groovy/org/gradle/language/base/BuildableModelElement.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.language.base;
+
+import org.gradle.api.Buildable;
+import org.gradle.api.Incubating;
+import org.gradle.api.Task;
+
+/**
+ * A model element that is directly buildable.
+ * Such an element mirrors a specified lifecycle task in the DAG, and can accept dependencies which are then associated with the lifecycle task.
+ */
+ at Incubating
+public interface BuildableModelElement extends Buildable {
+ /**
+ * Associates a 'lifecycle' task with the construction of this element.
+ */
+ void setLifecycleTask(Task lifecycleTask);
+
+ /**
+ * Adds a task that is required for the construction of this element.
+ * A task added this way is then added as a dependency of the associated lifecycle task.
+ */
+ void dependsOn(Object... tasks);
+}
\ No newline at end of file
diff --git a/subprojects/language-base/src/main/groovy/org/gradle/language/base/FunctionalSourceSet.java b/subprojects/language-base/src/main/groovy/org/gradle/language/base/FunctionalSourceSet.java
new file mode 100644
index 0000000..93a59eb
--- /dev/null
+++ b/subprojects/language-base/src/main/groovy/org/gradle/language/base/FunctionalSourceSet.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.language.base;
+
+import org.gradle.api.ExtensiblePolymorphicDomainObjectContainer;
+import org.gradle.api.Incubating;
+import org.gradle.api.Named;
+
+/**
+ * A container holding {@link LanguageSourceSet}s with a similar function
+ * (production code, test code, etc.).
+ */
+ at Incubating
+public interface FunctionalSourceSet extends ExtensiblePolymorphicDomainObjectContainer<LanguageSourceSet>, Named {}
diff --git a/subprojects/language-base/src/main/groovy/org/gradle/language/base/LanguageSourceSet.java b/subprojects/language-base/src/main/groovy/org/gradle/language/base/LanguageSourceSet.java
new file mode 100644
index 0000000..6057976
--- /dev/null
+++ b/subprojects/language-base/src/main/groovy/org/gradle/language/base/LanguageSourceSet.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.language.base;
+
+import org.gradle.api.Action;
+import org.gradle.api.Buildable;
+import org.gradle.api.Incubating;
+import org.gradle.api.Named;
+import org.gradle.api.file.SourceDirectorySet;
+import org.gradle.api.internal.HasInternalProtocol;
+
+/**
+ * A set of sources for a programming language.
+ */
+ at Incubating
+ at HasInternalProtocol
+public interface LanguageSourceSet extends Named, Buildable {
+ // TODO: do we want to keep using SourceDirectorySet in the new API?
+ // would feel more natural if dirs could be added directly to LanguageSourceSet
+ // could also think about extending SourceDirectorySet
+ SourceDirectorySet getSource();
+
+ /**
+ * Configure the sources
+ */
+ void source(Action<SourceDirectorySet> config);
+
+}
diff --git a/subprojects/language-base/src/main/groovy/org/gradle/language/base/ProjectSourceSet.java b/subprojects/language-base/src/main/groovy/org/gradle/language/base/ProjectSourceSet.java
new file mode 100644
index 0000000..fabe493
--- /dev/null
+++ b/subprojects/language-base/src/main/groovy/org/gradle/language/base/ProjectSourceSet.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.language.base;
+
+import org.gradle.api.Incubating;
+import org.gradle.api.NamedDomainObjectContainer;
+
+/**
+ * A container of {@link FunctionalSourceSet}s. Added to a project by the
+ * {@link org.gradle.language.base.plugins.LanguageBasePlugin}.
+ */
+ at Incubating
+public interface ProjectSourceSet extends NamedDomainObjectContainer<FunctionalSourceSet> {}
diff --git a/subprojects/language-base/src/main/groovy/org/gradle/language/base/internal/AbstractBuildableModelElement.java b/subprojects/language-base/src/main/groovy/org/gradle/language/base/internal/AbstractBuildableModelElement.java
new file mode 100644
index 0000000..3517cd9
--- /dev/null
+++ b/subprojects/language-base/src/main/groovy/org/gradle/language/base/internal/AbstractBuildableModelElement.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.language.base.internal;
+
+import org.gradle.api.Task;
+import org.gradle.api.internal.tasks.DefaultTaskDependency;
+import org.gradle.api.tasks.TaskDependency;
+import org.gradle.language.base.BuildableModelElement;
+
+import java.util.Collections;
+import java.util.Set;
+
+public class AbstractBuildableModelElement implements BuildableModelElement {
+ private final DefaultTaskDependency buildDependencies = new DefaultTaskDependency();
+ private Task lifecycleTask;
+
+ public void setLifecycleTask(Task lifecycleTask) {
+ this.lifecycleTask = lifecycleTask;
+ lifecycleTask.dependsOn(buildDependencies);
+ }
+
+ public TaskDependency getBuildDependencies() {
+ return new TaskDependency() {
+ public Set<? extends Task> getDependencies(Task other) {
+ if (lifecycleTask == null) {
+ return buildDependencies.getDependencies(other);
+ }
+ return Collections.singleton(lifecycleTask);
+ }
+ };
+ }
+
+ public void dependsOn(Object... tasks) {
+ buildDependencies.add(tasks);
+ }
+
+}
diff --git a/subprojects/language-base/src/main/groovy/org/gradle/language/base/internal/BinaryInternal.java b/subprojects/language-base/src/main/groovy/org/gradle/language/base/internal/BinaryInternal.java
new file mode 100644
index 0000000..d45b4a5
--- /dev/null
+++ b/subprojects/language-base/src/main/groovy/org/gradle/language/base/internal/BinaryInternal.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.language.base.internal;
+
+import org.gradle.language.base.Binary;
+
+public interface BinaryInternal extends Binary {
+ BinaryNamingScheme getNamingScheme();
+}
diff --git a/subprojects/language-base/src/main/groovy/org/gradle/language/base/internal/BinaryNamingScheme.java b/subprojects/language-base/src/main/groovy/org/gradle/language/base/internal/BinaryNamingScheme.java
new file mode 100644
index 0000000..4299ae2
--- /dev/null
+++ b/subprojects/language-base/src/main/groovy/org/gradle/language/base/internal/BinaryNamingScheme.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.language.base.internal;
+
+import org.gradle.api.Nullable;
+
+public interface BinaryNamingScheme {
+ String getLifecycleTaskName();
+
+ String getTaskName(@Nullable String verb);
+
+ String getTaskName(@Nullable String verb, @Nullable String target);
+
+ String getOutputDirectoryBase();
+
+ String getDescription();
+}
diff --git a/subprojects/language-base/src/main/groovy/org/gradle/language/base/internal/DefaultBinaryContainer.java b/subprojects/language-base/src/main/groovy/org/gradle/language/base/internal/DefaultBinaryContainer.java
new file mode 100644
index 0000000..33a9ed0
--- /dev/null
+++ b/subprojects/language-base/src/main/groovy/org/gradle/language/base/internal/DefaultBinaryContainer.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.language.base.internal;
+
+import org.gradle.api.internal.DefaultPolymorphicDomainObjectContainer;
+import org.gradle.internal.reflect.Instantiator;
+import org.gradle.language.base.BinaryContainer;
+import org.gradle.language.base.Binary;
+
+public class DefaultBinaryContainer extends DefaultPolymorphicDomainObjectContainer<Binary> implements BinaryContainer {
+ public DefaultBinaryContainer(Instantiator instantiator) {
+ super(Binary.class, instantiator);
+ }
+}
diff --git a/subprojects/language-base/src/main/groovy/org/gradle/language/base/internal/DefaultBinaryNamingScheme.java b/subprojects/language-base/src/main/groovy/org/gradle/language/base/internal/DefaultBinaryNamingScheme.java
new file mode 100644
index 0000000..556debe
--- /dev/null
+++ b/subprojects/language-base/src/main/groovy/org/gradle/language/base/internal/DefaultBinaryNamingScheme.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.language.base.internal;
+
+import org.gradle.api.Nullable;
+import org.gradle.util.GUtil;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class DefaultBinaryNamingScheme implements BinaryNamingScheme {
+ private final String baseName;
+ private final String typeString;
+ private final String dimensionPrefix;
+ private final List<String> dimensions;
+
+ public DefaultBinaryNamingScheme(String baseName) {
+ this(baseName, "", new ArrayList<String>());
+ }
+
+ public DefaultBinaryNamingScheme withTypeString(String newTypeString) {
+ return new DefaultBinaryNamingScheme(baseName, newTypeString, dimensions);
+ }
+
+ public DefaultBinaryNamingScheme withVariantDimension(String dimension) {
+ List<String> newDimensions = new ArrayList<String>(dimensions);
+ newDimensions.add(dimension);
+ return new DefaultBinaryNamingScheme(baseName, typeString, newDimensions);
+ }
+
+ private DefaultBinaryNamingScheme(String baseName, String typeString, List<String> dimensions) {
+ this.baseName = baseName;
+ this.typeString = typeString;
+ this.dimensions = dimensions;
+ this.dimensionPrefix = createPrefix(dimensions);
+ }
+
+ private String createPrefix(List<String> dimensions) {
+ if (dimensions.isEmpty()) {
+ return "";
+ }
+ return makeName(dimensions.toArray(new String[dimensions.size()]));
+ }
+
+ public String getLifecycleTaskName() {
+ return getTaskName(null, null);
+ }
+
+ public String getOutputDirectoryBase() {
+ StringBuilder builder = new StringBuilder(makeName(baseName, typeString));
+ if (dimensionPrefix.length() > 0) {
+ builder.append('/');
+ builder.append(dimensionPrefix);
+ }
+ return builder.toString();
+ }
+
+ public String getDescription() {
+ return String.format("%s '%s'", GUtil.toWords(typeString), getLifecycleTaskName());
+ }
+
+ public String getTaskName(@Nullable String verb) {
+ return getTaskName(verb, null);
+ }
+
+ public String getTaskName(@Nullable String verb, @Nullable String target) {
+ return makeName(verb, dimensionPrefix, baseName, typeString, target);
+ }
+
+ public String makeName(String... words) {
+ StringBuilder builder = new StringBuilder();
+ for (String word : words) {
+ if (word == null || word.length() == 0) {
+ continue;
+ }
+ if (builder.length() == 0) {
+ appendUncapitalized(builder, word);
+ } else {
+ appendCapitalized(builder, word);
+ }
+ }
+ return builder.toString();
+ }
+
+ private void appendCapitalized(StringBuilder builder, String word) {
+ builder.append(Character.toTitleCase(word.charAt(0))).append(word.substring(1));
+ }
+
+ private void appendUncapitalized(StringBuilder builder, String word) {
+ builder.append(Character.toLowerCase(word.charAt(0))).append(word.substring(1));
+ }
+}
diff --git a/subprojects/language-base/src/main/groovy/org/gradle/language/base/internal/DefaultFunctionalSourceSet.java b/subprojects/language-base/src/main/groovy/org/gradle/language/base/internal/DefaultFunctionalSourceSet.java
new file mode 100644
index 0000000..923b3ad
--- /dev/null
+++ b/subprojects/language-base/src/main/groovy/org/gradle/language/base/internal/DefaultFunctionalSourceSet.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.language.base.internal;
+
+import org.gradle.language.base.FunctionalSourceSet;
+import org.gradle.language.base.LanguageSourceSet;
+import org.gradle.api.internal.DefaultPolymorphicDomainObjectContainer;
+import org.gradle.internal.reflect.Instantiator;
+
+public class DefaultFunctionalSourceSet extends DefaultPolymorphicDomainObjectContainer<LanguageSourceSet> implements FunctionalSourceSet {
+ private final String name;
+
+ public DefaultFunctionalSourceSet(String name, Instantiator instantiator) {
+ super(LanguageSourceSet.class, instantiator);
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+}
diff --git a/subprojects/language-base/src/main/groovy/org/gradle/language/base/internal/DefaultProjectSourceSet.java b/subprojects/language-base/src/main/groovy/org/gradle/language/base/internal/DefaultProjectSourceSet.java
new file mode 100644
index 0000000..4e7d9b4
--- /dev/null
+++ b/subprojects/language-base/src/main/groovy/org/gradle/language/base/internal/DefaultProjectSourceSet.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.language.base.internal;
+
+import org.gradle.api.internal.AbstractNamedDomainObjectContainer;
+import org.gradle.language.base.FunctionalSourceSet;
+import org.gradle.language.base.ProjectSourceSet;
+import org.gradle.internal.reflect.Instantiator;
+
+public class DefaultProjectSourceSet extends AbstractNamedDomainObjectContainer<FunctionalSourceSet> implements ProjectSourceSet {
+ public DefaultProjectSourceSet(Instantiator instantiator) {
+ super(FunctionalSourceSet.class, instantiator);
+ }
+
+ @Override
+ protected FunctionalSourceSet doCreate(String name) {
+ return getInstantiator().newInstance(DefaultFunctionalSourceSet.class, name, getInstantiator());
+ }
+}
diff --git a/subprojects/language-base/src/main/groovy/org/gradle/language/base/internal/LanguageSourceSetInternal.java b/subprojects/language-base/src/main/groovy/org/gradle/language/base/internal/LanguageSourceSetInternal.java
new file mode 100644
index 0000000..29ccb39
--- /dev/null
+++ b/subprojects/language-base/src/main/groovy/org/gradle/language/base/internal/LanguageSourceSetInternal.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.language.base.internal;
+
+import org.gradle.language.base.LanguageSourceSet;
+
+public interface LanguageSourceSetInternal extends LanguageSourceSet {
+
+ // TODO:DAZ This doesn't feel right. Need some better modelling.
+ // TODO:DAZ Use this for ClassDirectoryBinary task names as well: need to hack the naming scheme to maintain back-compatibility
+ /**
+ * A unique name for this source set across all functional source sets.
+ */
+ String getFullName();
+
+}
diff --git a/subprojects/language-base/src/main/groovy/org/gradle/language/base/package-info.java b/subprojects/language-base/src/main/groovy/org/gradle/language/base/package-info.java
new file mode 100644
index 0000000..363df29
--- /dev/null
+++ b/subprojects/language-base/src/main/groovy/org/gradle/language/base/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+/**
+ * General purpose types for language support.
+ */
+ at Incubating
+package org.gradle.language.base;
+
+import org.gradle.api.Incubating;
\ No newline at end of file
diff --git a/subprojects/language-base/src/main/groovy/org/gradle/language/base/plugins/LanguageBasePlugin.java b/subprojects/language-base/src/main/groovy/org/gradle/language/base/plugins/LanguageBasePlugin.java
new file mode 100644
index 0000000..85ee2cb
--- /dev/null
+++ b/subprojects/language-base/src/main/groovy/org/gradle/language/base/plugins/LanguageBasePlugin.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.language.base.plugins;
+
+import org.gradle.api.*;
+import org.gradle.internal.reflect.Instantiator;
+import org.gradle.language.base.BinaryContainer;
+import org.gradle.language.base.internal.BinaryInternal;
+import org.gradle.language.base.internal.DefaultBinaryContainer;
+import org.gradle.language.base.internal.DefaultProjectSourceSet;
+
+import javax.inject.Inject;
+
+/**
+ * Base plugin for language support.
+ *
+ * Adds a {@link org.gradle.language.base.BinaryContainer} named {@code binaries} to the project.
+ * Adds a {@link org.gradle.language.base.ProjectSourceSet} named {@code sources} to the project.
+ */
+ at Incubating
+public class LanguageBasePlugin implements Plugin<Project> {
+ // TODO:DAZ Find a good way to share this with the BuildPlugin, without introducing dependency on plugins module
+ public static final String BUILD_GROUP = "build";
+
+ private final Instantiator instantiator;
+
+
+ @Inject
+ public LanguageBasePlugin(Instantiator instantiator) {
+ this.instantiator = instantiator;
+ }
+
+ public void apply(final Project target) {
+ target.getExtensions().create("sources", DefaultProjectSourceSet.class, instantiator);
+ final BinaryContainer binaries = target.getExtensions().create("binaries", DefaultBinaryContainer.class, instantiator);
+
+ binaries.withType(BinaryInternal.class).all(new Action<BinaryInternal>() {
+ public void execute(BinaryInternal binary) {
+ Task binaryLifecycleTask = target.task(binary.getNamingScheme().getLifecycleTaskName());
+ binaryLifecycleTask.setGroup(BUILD_GROUP);
+ binaryLifecycleTask.setDescription(String.format("Assembles %s.", binary));
+ binary.setLifecycleTask(binaryLifecycleTask);
+ }
+ });
+ }
+}
diff --git a/subprojects/language-base/src/main/groovy/org/gradle/language/base/plugins/package-info.java b/subprojects/language-base/src/main/groovy/org/gradle/language/base/plugins/package-info.java
new file mode 100644
index 0000000..32d27e2
--- /dev/null
+++ b/subprojects/language-base/src/main/groovy/org/gradle/language/base/plugins/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+/**
+ * Base plugins for language support.
+ */
+ at Incubating
+package org.gradle.language.base.plugins;
+
+import org.gradle.api.Incubating;
\ No newline at end of file
diff --git a/subprojects/language-base/src/test/groovy/org/gradle/language/base/internal/BuildableModelElementTest.groovy b/subprojects/language-base/src/test/groovy/org/gradle/language/base/internal/BuildableModelElementTest.groovy
new file mode 100644
index 0000000..d8df9cd
--- /dev/null
+++ b/subprojects/language-base/src/test/groovy/org/gradle/language/base/internal/BuildableModelElementTest.groovy
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.language.base.internal
+
+import org.gradle.api.DefaultTask
+import org.gradle.api.Task
+import org.gradle.util.TestUtil
+import spock.lang.Specification
+
+public class BuildableModelElementTest extends Specification {
+
+ def element = new TestBuildableModelElement()
+ def dependedOn1 = Stub(Task)
+ def dependedOn2 = Stub(Task)
+ def lifecycleTask = TestUtil.createTask(DefaultTask)
+
+ def "has direct dependencies with no lifecycle task set"() {
+ when:
+ element.dependsOn(dependedOn1, dependedOn2)
+
+ then:
+ element.getBuildDependencies().getDependencies(Stub(Task)) == [dependedOn1, dependedOn2] as Set
+ }
+
+ def "has intervening lifecycle task as dependency when set"() {
+ when:
+ element.dependsOn(dependedOn1)
+ element.setLifecycleTask(lifecycleTask)
+ element.dependsOn(dependedOn2)
+
+ then:
+ element.getBuildDependencies().getDependencies(Stub(Task)) == [lifecycleTask] as Set
+
+ and:
+ lifecycleTask.getTaskDependencies().getDependencies(Stub(Task)) == [dependedOn1, dependedOn2] as Set
+ }
+
+ class TestBuildableModelElement extends AbstractBuildableModelElement {
+
+ }
+}
diff --git a/subprojects/language-base/src/test/groovy/org/gradle/language/base/internal/DefaultBinaryNamingSchemeTest.groovy b/subprojects/language-base/src/test/groovy/org/gradle/language/base/internal/DefaultBinaryNamingSchemeTest.groovy
new file mode 100644
index 0000000..bd17ba5
--- /dev/null
+++ b/subprojects/language-base/src/test/groovy/org/gradle/language/base/internal/DefaultBinaryNamingSchemeTest.groovy
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.language.base.internal
+
+import spock.lang.Specification
+
+class DefaultBinaryNamingSchemeTest extends Specification {
+ def "generates task names for native binaries"() {
+ expect:
+ def namingScheme = createNamingScheme(baseName, type, dimensions)
+ namingScheme.getTaskName(verb, target) == taskName
+
+ where:
+ baseName | type | dimensions | verb | target | taskName
+ "test" | "" | [] | null | null | "test"
+ "test" | "type" | [] | null | null | "testType"
+ "test" | "type" | [] | null | "classes" | "testTypeClasses"
+ "test" | "" | [] | null | "classes" | "testClasses"
+ "test" | "type" | [] | "assemble" | null | "assembleTestType"
+ "test" | "type" | [] | "compile" | "java" | "compileTestTypeJava"
+ "test" | "type" | ["one", "two"] | null | null | "oneTwoTestType"
+ "test" | "type" | ["one", "two"] | null | "classes" | "oneTwoTestTypeClasses"
+ "test" | "type" | ["one", "two"] | "assemble" | null | "assembleOneTwoTestType"
+ "test" | "type" | ["one", "two"] | "compile" | "java" | "compileOneTwoTestTypeJava"
+ }
+
+ def "generates task name with extended inputs"() {
+ expect:
+ def namingScheme = createNamingScheme("theBinary", "theType", ['firstDimension', 'secondDimension'])
+ namingScheme.getTaskName("theVerb", "theTarget") == "theVerbFirstDimensionSecondDimensionTheBinaryTheTypeTheTarget"
+ }
+
+ def "generates base name and output directory"() {
+ def namingScheme = createNamingScheme(baseName, "", dimensions)
+
+ expect:
+ namingScheme.getLifecycleTaskName() == lifecycleName
+ namingScheme.getOutputDirectoryBase() == outputDir
+
+ where:
+ baseName | dimensions | lifecycleName | outputDir
+ "test" | [] | "test" | "test"
+ "test" | ["one", "two"] | "oneTwoTest" | "test/oneTwo"
+ "mainLibrary" | ["enterpriseEdition", "osx_x64", "static"] | "enterpriseEditionOsx_x64StaticMainLibrary" | "mainLibrary/enterpriseEditionOsx_x64Static"
+ "mainLibrary" | ["EnterpriseEdition", "Osx_x64", "Static"] | "enterpriseEditionOsx_x64StaticMainLibrary" | "mainLibrary/enterpriseEditionOsx_x64Static"
+ }
+
+ private DefaultBinaryNamingScheme createNamingScheme(def baseName, def type, def dimensions) {
+ def namingScheme = new DefaultBinaryNamingScheme(baseName).withTypeString(type)
+ for (String dimension : dimensions) {
+ namingScheme = namingScheme.withVariantDimension(dimension)
+ }
+ return namingScheme
+ }
+}
diff --git a/subprojects/language-jvm/language-jvm.gradle b/subprojects/language-jvm/language-jvm.gradle
new file mode 100644
index 0000000..19b6518
--- /dev/null
+++ b/subprojects/language-jvm/language-jvm.gradle
@@ -0,0 +1,7 @@
+dependencies {
+ compile libraries.groovy
+ compile project(":languageBase")
+ compile project(":core")
+}
+
+useClassycle()
diff --git a/subprojects/language-jvm/src/main/groovy/org/gradle/language/java/JavaSourceSet.java b/subprojects/language-jvm/src/main/groovy/org/gradle/language/java/JavaSourceSet.java
new file mode 100644
index 0000000..1b698a1
--- /dev/null
+++ b/subprojects/language-jvm/src/main/groovy/org/gradle/language/java/JavaSourceSet.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.language.java;
+
+import org.gradle.api.Incubating;
+import org.gradle.language.jvm.Classpath;
+import org.gradle.language.base.LanguageSourceSet;
+
+/**
+ * A set of sources passed to the Java compiler.
+ */
+ at Incubating
+public interface JavaSourceSet extends LanguageSourceSet {
+ Classpath getCompileClasspath();
+}
diff --git a/subprojects/language-jvm/src/main/groovy/org/gradle/language/java/internal/DefaultJavaSourceSet.java b/subprojects/language-jvm/src/main/groovy/org/gradle/language/java/internal/DefaultJavaSourceSet.java
new file mode 100644
index 0000000..0c783c0
--- /dev/null
+++ b/subprojects/language-jvm/src/main/groovy/org/gradle/language/java/internal/DefaultJavaSourceSet.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.language.java.internal;
+
+import org.apache.commons.lang.StringUtils;
+import org.gradle.api.Action;
+import org.gradle.api.Task;
+import org.gradle.api.file.SourceDirectorySet;
+import org.gradle.language.base.internal.LanguageSourceSetInternal;
+import org.gradle.language.jvm.Classpath;
+import org.gradle.language.base.FunctionalSourceSet;
+import org.gradle.language.java.JavaSourceSet;
+import org.gradle.api.tasks.TaskDependency;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class DefaultJavaSourceSet implements JavaSourceSet, LanguageSourceSetInternal {
+ private final String name;
+ private final SourceDirectorySet source;
+ private final Classpath compileClasspath;
+ private final FunctionalSourceSet parent;
+
+ public DefaultJavaSourceSet(String name, SourceDirectorySet source, Classpath compileClasspath, FunctionalSourceSet parent) {
+ this.name = name;
+ this.source = source;
+ this.compileClasspath = compileClasspath;
+ this.parent = parent;
+ }
+
+ public Classpath getCompileClasspath() {
+ return compileClasspath;
+ }
+
+ public SourceDirectorySet getSource() {
+ return source;
+ }
+
+ public void source(Action<SourceDirectorySet> config) {
+ config.execute(getSource());
+ }
+
+ public TaskDependency getBuildDependencies() {
+ return new TaskDependency() {
+ public Set<? extends Task> getDependencies(Task task) {
+ Set<Task> dependencies = new HashSet<Task>();
+ dependencies.addAll(compileClasspath.getBuildDependencies().getDependencies(task));
+ dependencies.addAll(source.getBuildDependencies().getDependencies(task));
+ return dependencies;
+ }
+ };
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getFullName() {
+ return parent.getName() + StringUtils.capitalize(name);
+ }
+
+ public String toString() {
+ return String.format("source set '%s:%s'", parent.getName(), name);
+ }
+}
diff --git a/subprojects/language-jvm/src/main/groovy/org/gradle/language/java/package-info.java b/subprojects/language-jvm/src/main/groovy/org/gradle/language/java/package-info.java
new file mode 100644
index 0000000..2acd1a6
--- /dev/null
+++ b/subprojects/language-jvm/src/main/groovy/org/gradle/language/java/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+/**
+ * Types for Java language support.
+ */
+ at Incubating
+package org.gradle.language.java;
+
+import org.gradle.api.Incubating;
\ No newline at end of file
diff --git a/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/ClassDirectoryBinary.java b/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/ClassDirectoryBinary.java
new file mode 100644
index 0000000..e8b852b
--- /dev/null
+++ b/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/ClassDirectoryBinary.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.language.jvm;
+
+import org.gradle.api.DomainObjectCollection;
+import org.gradle.api.Incubating;
+import org.gradle.language.base.Binary;
+import org.gradle.language.base.LanguageSourceSet;
+
+import java.io.File;
+
+/**
+ * An exploded binary containing resources and compiled class files.
+ */
+// TODO: maybe we need to allow additional dirs like SourceSetOutput does
+// (esp. for backwards compatibility). Wonder if it's still necessary to distinguish
+// between classes and resources dirs, instead of just maintaining a collection of dirs.
+// As far as generated resources are concerned, it might be better to model
+// them as an additional (Buildable) ResourceSet.
+ at Incubating
+public interface ClassDirectoryBinary extends Binary {
+ File getClassesDir();
+ void setClassesDir(File dir);
+ File getResourcesDir();
+ void setResourcesDir(File dir);
+ DomainObjectCollection<LanguageSourceSet> getSource();
+}
diff --git a/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/Classpath.java b/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/Classpath.java
new file mode 100644
index 0000000..3603ba3
--- /dev/null
+++ b/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/Classpath.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.language.jvm;
+
+import org.gradle.api.Buildable;
+import org.gradle.api.Incubating;
+import org.gradle.api.file.FileCollection;
+
+/**
+ * A collection of files to be used as a class path.
+ */
+ at Incubating
+public interface Classpath extends Buildable {
+ FileCollection getFiles();
+}
diff --git a/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/ResourceSet.java b/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/ResourceSet.java
new file mode 100644
index 0000000..8e6a489
--- /dev/null
+++ b/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/ResourceSet.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.language.jvm;
+
+import org.gradle.api.Incubating;
+import org.gradle.language.base.LanguageSourceSet;
+
+/**
+ * A set of resource files.
+ */
+ at Incubating
+public interface ResourceSet extends LanguageSourceSet {}
diff --git a/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/internal/ClassDirectoryBinaryNamingScheme.java b/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/internal/ClassDirectoryBinaryNamingScheme.java
new file mode 100644
index 0000000..7e8870e
--- /dev/null
+++ b/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/internal/ClassDirectoryBinaryNamingScheme.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.language.jvm.internal;
+
+import org.gradle.api.Nullable;
+import org.gradle.language.base.internal.BinaryNamingScheme;
+import org.gradle.util.GUtil;
+
+class ClassDirectoryBinaryNamingScheme implements BinaryNamingScheme {
+ private final String baseName;
+ private final String collapsedName;
+
+ public ClassDirectoryBinaryNamingScheme(String baseName) {
+ this.baseName = baseName;
+ this.collapsedName = collapseMain(this.baseName);
+ }
+
+ private static String collapseMain(String name) {
+ return name.equals("main") ? "" : name;
+ }
+
+ public String getDescription() {
+ return String.format("classes '%s'", baseName);
+ }
+
+ public String getLifecycleTaskName() {
+ return getTaskName(null, "classes");
+ }
+
+ public String getTaskName(@Nullable String verb) {
+ return getTaskName(verb, null);
+ }
+
+ public String getTaskName(@Nullable String verb, @Nullable String target) {
+ String name = baseName;
+ if (target != null) {
+ name = collapsedName;
+ }
+ return GUtil.toLowerCamelCase(String.format("%s %s %s", nullToEmpty(verb), name, nullToEmpty(target)));
+ }
+
+ private String nullToEmpty(String input) {
+ return input == null ? "" : input;
+ }
+
+ public String getOutputDirectoryBase() {
+ return baseName;
+ }
+}
diff --git a/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/internal/DefaultClassDirectoryBinary.java b/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/internal/DefaultClassDirectoryBinary.java
new file mode 100644
index 0000000..0392302
--- /dev/null
+++ b/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/internal/DefaultClassDirectoryBinary.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.language.jvm.internal;
+
+import org.gradle.api.DomainObjectCollection;
+import org.gradle.api.internal.DefaultDomainObjectSet;
+import org.gradle.language.base.LanguageSourceSet;
+import org.gradle.language.base.internal.AbstractBuildableModelElement;
+import org.gradle.language.base.internal.BinaryInternal;
+import org.gradle.language.base.internal.BinaryNamingScheme;
+import org.gradle.language.jvm.ClassDirectoryBinary;
+
+import java.io.File;
+
+public class DefaultClassDirectoryBinary extends AbstractBuildableModelElement implements ClassDirectoryBinary, BinaryInternal {
+ private final BinaryNamingScheme namingScheme;
+ private final DomainObjectCollection<LanguageSourceSet> source = new DefaultDomainObjectSet<LanguageSourceSet>(LanguageSourceSet.class);
+ private final String name;
+ private File classesDir;
+ private File resourcesDir;
+
+ public DefaultClassDirectoryBinary(String name) {
+ this.name = name;
+ this.namingScheme = new ClassDirectoryBinaryNamingScheme(removeClassesSuffix(name));
+ }
+
+ private String removeClassesSuffix(String name) {
+ if (name.endsWith("Classes")) {
+ return name.substring(0, name.length() - 7);
+ }
+ return name;
+ }
+
+ public BinaryNamingScheme getNamingScheme() {
+ return namingScheme;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public File getClassesDir() {
+ return classesDir;
+ }
+
+ public void setClassesDir(File classesDir) {
+ this.classesDir = classesDir;
+ }
+
+ public File getResourcesDir() {
+ return resourcesDir;
+ }
+
+ public void setResourcesDir(File resourcesDir) {
+ this.resourcesDir = resourcesDir;
+ }
+
+ public DomainObjectCollection<LanguageSourceSet> getSource() {
+ return source;
+ }
+
+ public String toString() {
+ return namingScheme.getDescription();
+ }
+
+}
diff --git a/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/internal/DefaultClasspath.java b/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/internal/DefaultClasspath.java
new file mode 100644
index 0000000..3c8385b
--- /dev/null
+++ b/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/internal/DefaultClasspath.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.language.jvm.internal;
+
+import org.gradle.api.file.FileCollection;
+import org.gradle.api.internal.file.FileResolver;
+import org.gradle.api.internal.file.collections.DefaultConfigurableFileCollection;
+import org.gradle.api.internal.tasks.TaskResolver;
+import org.gradle.language.jvm.Classpath;
+import org.gradle.api.tasks.TaskDependency;
+
+public class DefaultClasspath implements Classpath {
+ private final FileCollection files;
+
+ public DefaultClasspath(FileResolver fileResolver, TaskResolver taskResolver) {
+ files = new DefaultConfigurableFileCollection(fileResolver, taskResolver);
+ }
+
+ public FileCollection getFiles() {
+ return files;
+ }
+
+ public TaskDependency getBuildDependencies() {
+ return files.getBuildDependencies();
+ }
+}
diff --git a/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/internal/DefaultResourceSet.java b/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/internal/DefaultResourceSet.java
new file mode 100644
index 0000000..7167f75
--- /dev/null
+++ b/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/internal/DefaultResourceSet.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.language.jvm.internal;
+
+import org.apache.commons.lang.StringUtils;
+import org.gradle.api.Action;
+import org.gradle.api.file.SourceDirectorySet;
+import org.gradle.language.base.FunctionalSourceSet;
+import org.gradle.api.tasks.TaskDependency;
+import org.gradle.language.base.internal.LanguageSourceSetInternal;
+import org.gradle.language.jvm.ResourceSet;
+
+public class DefaultResourceSet implements ResourceSet, LanguageSourceSetInternal {
+ private final String name;
+ private final SourceDirectorySet source;
+ private final FunctionalSourceSet parent;
+
+ public DefaultResourceSet(String name, SourceDirectorySet source, FunctionalSourceSet parent) {
+ this.name = name;
+ this.source = source;
+ this.parent = parent;
+ }
+
+ public SourceDirectorySet getSource() {
+ return source;
+ }
+
+ public void source(Action<SourceDirectorySet> config) {
+ config.execute(getSource());
+ }
+
+ public TaskDependency getBuildDependencies() {
+ return source.getBuildDependencies();
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getFullName() {
+ return parent.getName() + StringUtils.capitalize(name);
+ }
+
+ public String toString() {
+ return String.format("source set '%s:%s'", parent.getName(), name);
+ }
+}
diff --git a/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/internal/SimpleStaleClassCleaner.java b/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/internal/SimpleStaleClassCleaner.java
new file mode 100644
index 0000000..d8bf3c8
--- /dev/null
+++ b/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/internal/SimpleStaleClassCleaner.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.language.jvm.internal;
+
+import org.gradle.api.internal.TaskOutputsInternal;
+
+import java.io.File;
+
+public class SimpleStaleClassCleaner extends StaleClassCleaner {
+ private final TaskOutputsInternal taskOutputs;
+
+ public SimpleStaleClassCleaner(TaskOutputsInternal taskOutputs) {
+ this.taskOutputs = taskOutputs;
+ }
+
+ @Override
+ public void execute() {
+ String prefix = getDestinationDir().getAbsolutePath() + File.separator;
+ for (File f : taskOutputs.getPreviousFiles()) {
+ if (f.getAbsolutePath().startsWith(prefix)) {
+ f.delete();
+ }
+ }
+ }
+}
diff --git a/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/internal/StaleClassCleaner.java b/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/internal/StaleClassCleaner.java
new file mode 100644
index 0000000..e781dec
--- /dev/null
+++ b/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/internal/StaleClassCleaner.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.language.jvm.internal;
+
+import org.gradle.api.file.FileCollection;
+
+import java.io.File;
+
+public abstract class StaleClassCleaner {
+ private File destinationDir;
+ FileCollection source;
+
+ public abstract void execute();
+
+ public FileCollection getSource() {
+ return source;
+ }
+
+ public void setSource(FileCollection source) {
+ this.source = source;
+ }
+
+ public void setDestinationDir(File destinationDir) {
+ this.destinationDir = destinationDir;
+ }
+
+ public File getDestinationDir() {
+ return destinationDir;
+ }
+}
diff --git a/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/package-info.java b/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/package-info.java
new file mode 100644
index 0000000..84ff9f3
--- /dev/null
+++ b/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+/**
+ * Types for support for JVM languages.
+ */
+ at Incubating
+package org.gradle.language.jvm;
+
+import org.gradle.api.Incubating;
\ No newline at end of file
diff --git a/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/plugins/JvmLanguagePlugin.java b/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/plugins/JvmLanguagePlugin.java
new file mode 100644
index 0000000..8c3d3a6
--- /dev/null
+++ b/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/plugins/JvmLanguagePlugin.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.language.jvm.plugins;
+
+import org.gradle.api.*;
+import org.gradle.api.internal.ConventionMapping;
+import org.gradle.api.internal.file.DefaultSourceDirectorySet;
+import org.gradle.api.internal.file.FileResolver;
+import org.gradle.api.internal.plugins.DslObject;
+import org.gradle.api.tasks.Copy;
+import org.gradle.internal.reflect.Instantiator;
+import org.gradle.language.base.BinaryContainer;
+import org.gradle.language.base.FunctionalSourceSet;
+import org.gradle.language.base.ProjectSourceSet;
+import org.gradle.language.base.internal.BinaryInternal;
+import org.gradle.language.base.internal.BinaryNamingScheme;
+import org.gradle.language.base.plugins.LanguageBasePlugin;
+import org.gradle.language.jvm.ClassDirectoryBinary;
+import org.gradle.language.jvm.ResourceSet;
+import org.gradle.language.jvm.internal.DefaultClassDirectoryBinary;
+import org.gradle.language.jvm.internal.DefaultResourceSet;
+import org.gradle.language.jvm.tasks.ProcessResources;
+
+import javax.inject.Inject;
+import java.io.File;
+import java.util.concurrent.Callable;
+
+/**
+ * Base plugin for JVM language support. Applies the {@link org.gradle.language.base.plugins.LanguageBasePlugin}.
+ * Registers the {@link org.gradle.language.jvm.ClassDirectoryBinary} element type for the {@link org.gradle.language.base.BinaryContainer}.
+ * Adds a lifecycle task named {@code classes} for each {@link org.gradle.language.jvm.ClassDirectoryBinary}.
+ * Registers the {@link org.gradle.language.jvm.ResourceSet} element type for each {@link org.gradle.language.base.FunctionalSourceSet} added to {@link org.gradle.language.base.ProjectSourceSet}.
+ * Adds a {@link Copy} task named {@code processXYZResources} for each {@link org.gradle.language.jvm.ResourceSet} added to a {@link org.gradle.language.jvm.ClassDirectoryBinary}.
+ */
+ at Incubating
+public class JvmLanguagePlugin implements Plugin<Project> {
+ private final Instantiator instantiator;
+ private final FileResolver fileResolver;
+
+ @Inject
+ public JvmLanguagePlugin(Instantiator instantiator, FileResolver fileResolver) {
+ this.instantiator = instantiator;
+ this.fileResolver = fileResolver;
+ }
+
+ public void apply(final Project target) {
+ target.getPlugins().apply(LanguageBasePlugin.class);
+
+ ProjectSourceSet projectSourceSet = target.getExtensions().getByType(ProjectSourceSet.class);
+ projectSourceSet.all(new Action<FunctionalSourceSet>() {
+ public void execute(final FunctionalSourceSet functionalSourceSet) {
+ functionalSourceSet.registerFactory(ResourceSet.class, new NamedDomainObjectFactory<ResourceSet>() {
+ public ResourceSet create(String name) {
+ return instantiator.newInstance(DefaultResourceSet.class, name,
+ instantiator.newInstance(DefaultSourceDirectorySet.class, name, fileResolver), functionalSourceSet);
+ }
+ });
+ }
+ });
+
+ BinaryContainer binaryContainer = target.getExtensions().getByType(BinaryContainer.class);
+ binaryContainer.registerFactory(ClassDirectoryBinary.class, new NamedDomainObjectFactory<ClassDirectoryBinary>() {
+ public ClassDirectoryBinary create(String name) {
+ return instantiator.newInstance(DefaultClassDirectoryBinary.class, name);
+ };
+ });
+
+ binaryContainer.withType(ClassDirectoryBinary.class).all(new Action<ClassDirectoryBinary>() {
+ public void execute(final ClassDirectoryBinary binary) {
+ final BinaryNamingScheme namingScheme = ((BinaryInternal) binary).getNamingScheme();
+ ConventionMapping conventionMapping = new DslObject(binary).getConventionMapping();
+ conventionMapping.map("classesDir", new Callable<File>() {
+ public File call() throws Exception {
+ return new File(new File(target.getBuildDir(), "classes"), namingScheme.getOutputDirectoryBase());
+ }
+ });
+ binary.getSource().withType(ResourceSet.class).all(new Action<ResourceSet>() {
+ public void execute(ResourceSet resourceSet) {
+ // TODO: handle case where binary has multiple ResourceSet's
+ Copy resourcesTask = target.getTasks().create(namingScheme.getTaskName("process", "resources"), ProcessResources.class);
+ resourcesTask.setDescription(String.format("Processes %s.", resourceSet));
+ new DslObject(resourcesTask).getConventionMapping().map("destinationDir", new Callable<File>() {
+ public File call() throws Exception {
+ return binary.getResourcesDir();
+ }
+ });
+ binary.dependsOn(resourcesTask);
+ resourcesTask.from(resourceSet.getSource());
+ }
+ });
+ }
+ });
+ }
+}
diff --git a/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/plugins/package-info.java b/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/plugins/package-info.java
new file mode 100644
index 0000000..4465713
--- /dev/null
+++ b/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/plugins/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+/**
+ * Base plugins that add support for JVM languages.
+ */
+ at Incubating
+package org.gradle.language.jvm.plugins;
+
+import org.gradle.api.Incubating;
\ No newline at end of file
diff --git a/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/tasks/ProcessResources.java b/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/tasks/ProcessResources.java
new file mode 100644
index 0000000..a41e9de
--- /dev/null
+++ b/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/tasks/ProcessResources.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.language.jvm.tasks;
+
+import org.gradle.api.tasks.Copy;
+import org.gradle.language.jvm.internal.SimpleStaleClassCleaner;
+import org.gradle.language.jvm.internal.StaleClassCleaner;
+
+/**
+ * Copies resources from their source to their target directory, potentially processing them.
+ * Makes sure no stale resources remain in the target directory.
+ */
+public class ProcessResources extends Copy {
+
+ @Override
+ protected void copy() {
+ StaleClassCleaner cleaner = new SimpleStaleClassCleaner(getOutputs());
+ cleaner.setDestinationDir(getDestinationDir());
+ cleaner.execute();
+ super.copy();
+ }
+}
\ No newline at end of file
diff --git a/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/tasks/package-info.java b/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/tasks/package-info.java
new file mode 100644
index 0000000..74d24d7
--- /dev/null
+++ b/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/tasks/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+/**
+ * Tasks for support for JVM languages.
+ */
+ at Incubating
+package org.gradle.language.jvm.tasks;
+
+import org.gradle.api.Incubating;
\ No newline at end of file
diff --git a/subprojects/language-jvm/src/test/groovy/org/gradle/language/java/internal/DefaultJavaSourceSetTest.groovy b/subprojects/language-jvm/src/test/groovy/org/gradle/language/java/internal/DefaultJavaSourceSetTest.groovy
new file mode 100644
index 0000000..4bfc76b
--- /dev/null
+++ b/subprojects/language-jvm/src/test/groovy/org/gradle/language/java/internal/DefaultJavaSourceSetTest.groovy
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.language.java.internal
+
+import org.gradle.api.file.SourceDirectorySet
+import org.gradle.language.jvm.Classpath
+import org.gradle.language.base.FunctionalSourceSet
+import spock.lang.Specification
+
+class DefaultJavaSourceSetTest extends Specification {
+ def "has useful String representation"() {
+ def functionalSourceSet = Stub(FunctionalSourceSet) {
+ getName() >> "mainX"
+ }
+ def resourceSet = new DefaultJavaSourceSet("javaX", Stub(SourceDirectorySet), Stub(Classpath), functionalSourceSet)
+
+ expect:
+ resourceSet.toString() == "source set 'mainX:javaX'"
+ }
+}
diff --git a/subprojects/language-jvm/src/test/groovy/org/gradle/language/jvm/internal/ClassDirectoryBinaryNamingSchemeTest.groovy b/subprojects/language-jvm/src/test/groovy/org/gradle/language/jvm/internal/ClassDirectoryBinaryNamingSchemeTest.groovy
new file mode 100644
index 0000000..fbf0d5e
--- /dev/null
+++ b/subprojects/language-jvm/src/test/groovy/org/gradle/language/jvm/internal/ClassDirectoryBinaryNamingSchemeTest.groovy
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.language.jvm.internal
+
+import org.gradle.language.base.internal.DefaultBinaryNamingScheme
+import spock.lang.Specification
+
+class ClassDirectoryBinaryNamingSchemeTest extends Specification {
+
+ def "generates task names for class directory binaries"() {
+ expect:
+ def namer = new ClassDirectoryBinaryNamingScheme(name)
+ namer.getTaskName(verb, target) == taskName
+
+ where:
+ name | verb | target | taskName
+ "main" | null | null | "main"
+ "main" | "compile" | null | "compileMain"
+ "main" | null | "resources" | "resources"
+ "main" | "compile" | "java" | "compileJava"
+
+ "test" | null | null | "test"
+ "test" | "compile" | null | "compileTest"
+ "test" | null | "resources" | "testResources"
+ "test" | "compile" | "java" | "compileTestJava"
+ }
+
+ def "generates task name with extended inputs"() {
+ expect:
+ def namer = new DefaultBinaryNamingScheme("theClassesBinary")
+ namer.getTaskName("theVerb", "theTarget") == "theVerbTheClassesBinaryTheTarget"
+ }
+
+ def "generates base name and output directory"() {
+ def namer = new ClassDirectoryBinaryNamingScheme(baseName)
+
+ expect:
+ namer.getLifecycleTaskName() == lifecycleName
+ namer.getOutputDirectoryBase() == outputDir
+
+ where:
+ baseName | lifecycleName | outputDir
+ "main" | "classes" | "main"
+ "test" | "testClasses" | "test"
+ }
+}
diff --git a/subprojects/language-jvm/src/test/groovy/org/gradle/language/jvm/internal/DefaultClassDirectoryBinaryTest.groovy b/subprojects/language-jvm/src/test/groovy/org/gradle/language/jvm/internal/DefaultClassDirectoryBinaryTest.groovy
new file mode 100644
index 0000000..d74c42f
--- /dev/null
+++ b/subprojects/language-jvm/src/test/groovy/org/gradle/language/jvm/internal/DefaultClassDirectoryBinaryTest.groovy
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.language.jvm.internal;
+
+import spock.lang.Specification;
+
+public class DefaultClassDirectoryBinaryTest extends Specification {
+ def "uses short task names for binary with name 'mainClasses'"() {
+ when:
+ def binary = new DefaultClassDirectoryBinary("mainClasses")
+
+ then:
+ binary.name == 'mainClasses'
+
+ and:
+ binary.namingScheme.lifecycleTaskName == 'classes'
+ binary.namingScheme.getTaskName(null, null) == 'main'
+ binary.namingScheme.getTaskName("compile", null) == 'compileMain'
+ binary.namingScheme.getTaskName(null, "groovy") == 'groovy'
+ binary.namingScheme.getTaskName("compile", "groovy") == 'compileGroovy'
+ }
+
+ def "uses medium task names for binary with name 'otherClasses'"() {
+ when:
+ def binary = new DefaultClassDirectoryBinary("otherClasses")
+
+ then:
+ binary.name == 'otherClasses'
+
+ and:
+ binary.namingScheme.lifecycleTaskName == 'otherClasses'
+ binary.namingScheme.getTaskName(null, null) == 'other'
+ binary.namingScheme.getTaskName("compile", null) == 'compileOther'
+ binary.namingScheme.getTaskName(null, "groovy") == 'otherGroovy'
+ binary.namingScheme.getTaskName("compile", "groovy") == 'compileOtherGroovy'
+ }
+
+ def "uses long task names for binary with name 'otherBinary'"() {
+ when:
+ def binary = new DefaultClassDirectoryBinary("otherBinary")
+
+ then:
+ binary.name == 'otherBinary'
+
+ and:
+ binary.namingScheme.lifecycleTaskName == 'otherBinaryClasses'
+ binary.namingScheme.getTaskName(null, null) == 'otherBinary'
+ binary.namingScheme.getTaskName("compile", null) == 'compileOtherBinary'
+ binary.namingScheme.getTaskName(null, "groovy") == 'otherBinaryGroovy'
+ binary.namingScheme.getTaskName("compile", "groovy") == 'compileOtherBinaryGroovy'
+ }
+
+ def "has a useful toString() representation"() {
+ expect:
+ def binary = new DefaultClassDirectoryBinary(name)
+ binary.toString() == displayName
+
+ where:
+ name | displayName
+ 'mainClasses' | 'classes \'main\''
+ 'otherClasses' | 'classes \'other\''
+ 'otherBinary' | 'classes \'otherBinary\''
+ }
+}
diff --git a/subprojects/language-jvm/src/test/groovy/org/gradle/language/jvm/internal/DefaultResourceSetTest.groovy b/subprojects/language-jvm/src/test/groovy/org/gradle/language/jvm/internal/DefaultResourceSetTest.groovy
new file mode 100644
index 0000000..31231fb
--- /dev/null
+++ b/subprojects/language-jvm/src/test/groovy/org/gradle/language/jvm/internal/DefaultResourceSetTest.groovy
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.language.jvm.internal
+
+import org.gradle.api.file.SourceDirectorySet
+import org.gradle.language.base.FunctionalSourceSet
+import spock.lang.Specification
+
+class DefaultResourceSetTest extends Specification {
+ def "has useful String representation"() {
+ def functionalSourceSet = Stub(FunctionalSourceSet) {
+ getName() >> "mainX"
+ }
+ def resourceSet = new DefaultResourceSet("resourcesX", Stub(SourceDirectorySet), functionalSourceSet)
+
+ expect:
+ resourceSet.toString() == "source set 'mainX:resourcesX'"
+ }
+}
diff --git a/subprojects/launcher/launcher.gradle b/subprojects/launcher/launcher.gradle
index acdde9a..721dd48 100644
--- a/subprojects/launcher/launcher.gradle
+++ b/subprojects/launcher/launcher.gradle
@@ -3,8 +3,6 @@ configurations {
}
dependencies {
- groovy libraries.groovy
-
compile project(':baseServices')
compile project(':core')
compile project(':cli')
@@ -14,9 +12,15 @@ dependencies {
compile libraries.slf4j_api
+ testCompile libraries.groovy
+
startScriptGenerator project(':plugins')
}
+if (!javaVersion.java6Compatible) {
+ sourceSets.main.java.exclude '**/jdk6/**'
+}
+
useTestFixtures()
jar {
@@ -26,10 +30,6 @@ jar {
}
}
-test {
- forkEvery = 10
-}
-
task startScripts(type: StartScriptGenerator) {
startScriptsDir = new File("$buildDir/startScripts")
classpath = configurations.startScriptGenerator
diff --git a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/ConfigurationOnDemandIntegrationTest.groovy b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/ConfigurationOnDemandIntegrationTest.groovy
index 07371b1..8422e5b 100644
--- a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/ConfigurationOnDemandIntegrationTest.groovy
+++ b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/ConfigurationOnDemandIntegrationTest.groovy
@@ -20,9 +20,6 @@ import org.gradle.integtests.fixtures.AbstractIntegrationSpec
import org.gradle.integtests.fixtures.executer.ProjectLifecycleFixture
import org.junit.Rule
-/**
- * by Szczepan Faber, created at: 11/21/12
- */
class ConfigurationOnDemandIntegrationTest extends AbstractIntegrationSpec {
@Rule ProjectLifecycleFixture fixture = new ProjectLifecycleFixture(executer, temporaryFolder)
diff --git a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/EnablingParallelExecutionIntegrationTest.groovy b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/EnablingParallelExecutionIntegrationTest.groovy
index 56af0fc..eb4e769 100644
--- a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/EnablingParallelExecutionIntegrationTest.groovy
+++ b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/EnablingParallelExecutionIntegrationTest.groovy
@@ -21,9 +21,6 @@ import org.gradle.integtests.fixtures.AbstractIntegrationSpec
import org.gradle.integtests.fixtures.executer.GradleContextualExecuter
import spock.lang.IgnoreIf
-/**
- * by Szczepan Faber, created at: 11/21/12
- */
@IgnoreIf({ GradleContextualExecuter.parallel })
class EnablingParallelExecutionIntegrationTest extends AbstractIntegrationSpec {
diff --git a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/GradleConfigurabilityIntegrationSpec.groovy b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/GradleConfigurabilityIntegrationSpec.groovy
index d5d3470..baa27f6 100644
--- a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/GradleConfigurabilityIntegrationSpec.groovy
+++ b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/GradleConfigurabilityIntegrationSpec.groovy
@@ -26,9 +26,6 @@ import org.gradle.util.TestPrecondition
import org.gradle.util.TextUtil
import spock.lang.IgnoreIf
-/**
- * by Szczepan Faber, created at: 1/20/12
- */
@IgnoreIf( { GradleContextualExecuter.embedded })
class GradleConfigurabilityIntegrationSpec extends AbstractIntegrationSpec {
@@ -74,7 +71,6 @@ assert java.lang.management.ManagementFactory.runtimeMXBean.inputArguments.conta
javaLink.usingNativeTools().deleteDir()
}
- //TODO SF add coverage for reconnecting to those daemons.
def "honours jvm sys property that contain a space in gradle.properties"() {
given:
file("gradle.properties") << 'org.gradle.jvmargs=-Dsome-prop="i have space"'
diff --git a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonFeedbackIntegrationSpec.groovy b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonFeedbackIntegrationSpec.groovy
index 41eec24..891f339 100644
--- a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonFeedbackIntegrationSpec.groovy
+++ b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonFeedbackIntegrationSpec.groovy
@@ -23,9 +23,6 @@ import spock.lang.Timeout
import static org.gradle.test.fixtures.ConcurrentTestUtil.poll
-/**
- * by Szczepan Faber, created at: 1/20/12
- */
class DaemonFeedbackIntegrationSpec extends DaemonIntegrationSpec {
def setup() {
executer.requireIsolatedDaemons()
diff --git a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonInitialCommunicationFailureIntegrationSpec.groovy b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonInitialCommunicationFailureIntegrationSpec.groovy
index 82249cc..b4dd847 100644
--- a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonInitialCommunicationFailureIntegrationSpec.groovy
+++ b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonInitialCommunicationFailureIntegrationSpec.groovy
@@ -26,9 +26,6 @@ import spock.lang.Issue
import static org.gradle.test.fixtures.ConcurrentTestUtil.poll
-/**
- * by Szczepan Faber, created at: 1/20/12
- */
@IgnoreIf({ !KillProcessAvailability.CAN_KILL })
class DaemonInitialCommunicationFailureIntegrationSpec extends DaemonIntegrationSpec {
diff --git a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonIntegrationSpec.groovy b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonIntegrationSpec.groovy
index b9935db..f3b7ebc 100644
--- a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonIntegrationSpec.groovy
+++ b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonIntegrationSpec.groovy
@@ -21,9 +21,6 @@ import org.gradle.integtests.fixtures.AbstractIntegrationSpec
import org.gradle.integtests.fixtures.executer.DaemonGradleExecuter
import org.slf4j.LoggerFactory
-/**
- * by Szczepan Faber, created at: 2/1/12
- */
class DaemonIntegrationSpec extends AbstractIntegrationSpec {
String output
diff --git a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonLifecycleSpec.groovy b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonLifecycleSpec.groovy
index adce874..141a5a3 100644
--- a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonLifecycleSpec.groovy
+++ b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonLifecycleSpec.groovy
@@ -95,7 +95,7 @@ class DaemonLifecycleSpec extends DaemonIntegrationSpec {
""")
builds << executer.start()
}
- //TODO SF - rewrite the lifecycle spec so that it uses the TestableDaemon
+ //TODO - rewrite the lifecycle spec so that it uses the TestableDaemon
}
void completeBuild(buildNum = 0) {
diff --git a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DispachingFailureIntegrationSpec.groovy b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DispachingFailureIntegrationSpec.groovy
index 19ce0df..20f43a6 100644
--- a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DispachingFailureIntegrationSpec.groovy
+++ b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DispachingFailureIntegrationSpec.groovy
@@ -16,9 +16,6 @@
package org.gradle.launcher.daemon
-/**
- * by Szczepan Faber, created at: 1/20/12
- */
class DispachingFailureIntegrationSpec extends DaemonIntegrationSpec {
def "failing build does not make the daemon send corrupted message"() {
diff --git a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/EmbeddedDaemonSmokeTest.groovy b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/EmbeddedDaemonSmokeTest.groovy
index 9cd957c..c4652d8 100644
--- a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/EmbeddedDaemonSmokeTest.groovy
+++ b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/EmbeddedDaemonSmokeTest.groovy
@@ -22,7 +22,6 @@ import org.gradle.launcher.daemon.client.EmbeddedDaemonClientServices
import org.gradle.launcher.exec.DefaultBuildActionParameters
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
import org.gradle.tooling.internal.provider.ConfiguringBuildAction
-import org.gradle.tooling.internal.provider.ExecuteBuildAction
import org.junit.Rule
import spock.lang.Specification
@@ -65,7 +64,8 @@ class EmbeddedDaemonSmokeTest extends Specification {
}
def cleanup() {
- daemonClientServices?.close()
+ // TODO:ADAM - switch this back on
+// daemonClientServices?.close()
}
}
\ No newline at end of file
diff --git a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/ExecuteBuildAction.java b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/ExecuteBuildAction.java
new file mode 100644
index 0000000..e2d9871
--- /dev/null
+++ b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/ExecuteBuildAction.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.launcher.daemon;
+
+import org.gradle.initialization.BuildAction;
+import org.gradle.initialization.BuildController;
+
+import java.io.Serializable;
+
+public class ExecuteBuildAction implements BuildAction<Void>, Serializable {
+ public Void run(BuildController buildController) {
+ buildController.run();
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/SingleUseDaemonIntegrationTest.groovy b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/SingleUseDaemonIntegrationTest.groovy
index 8f9ad3a..5a193d2 100644
--- a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/SingleUseDaemonIntegrationTest.groovy
+++ b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/SingleUseDaemonIntegrationTest.groovy
@@ -19,6 +19,7 @@ package org.gradle.launcher.daemon
import org.gradle.integtests.fixtures.AbstractIntegrationSpec
import org.gradle.integtests.fixtures.AvailableJavaHomes
import org.gradle.integtests.fixtures.executer.GradleContextualExecuter
+import org.gradle.launcher.daemon.client.SingleUseDaemonClient
import org.gradle.util.TextUtil
import org.spockframework.runtime.SpockAssertionError
import org.spockframework.runtime.SpockTimeoutError
@@ -138,6 +139,6 @@ assert System.getProperty('some-prop') == 'some-value'
}
private def wasForked() {
- result.output.contains('fork a new JVM')
+ result.output.contains(SingleUseDaemonClient.MESSAGE)
}
}
diff --git a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/StoppingDaemonIntegrationSpec.groovy b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/StoppingDaemonIntegrationSpec.groovy
index a1ce784..48d8bb7 100644
--- a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/StoppingDaemonIntegrationSpec.groovy
+++ b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/StoppingDaemonIntegrationSpec.groovy
@@ -19,9 +19,6 @@ package org.gradle.launcher.daemon
import org.gradle.launcher.daemon.logging.DaemonMessages
import org.gradle.test.fixtures.ConcurrentTestUtil
import org.gradle.util.TextUtil
-/**
- * by Szczepan Faber, created at: 1/20/12
- */
class StoppingDaemonIntegrationSpec extends DaemonIntegrationSpec {
def "can handle multiple concurrent stop requests"() {
given:
diff --git a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/testing/DaemonContextParser.java b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/testing/DaemonContextParser.java
index 8f44b57..c44a7c4 100644
--- a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/testing/DaemonContextParser.java
+++ b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/testing/DaemonContextParser.java
@@ -26,9 +26,6 @@ import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-/**
- * by Szczepan Faber, created at: 2/13/12
- */
public class DaemonContextParser {
public static DaemonContext parseFrom(String source) {
Pattern pattern = Pattern.compile("^.*DefaultDaemonContext\\[uid=([^\\n]+),javaHome=([^\\n]+),daemonRegistryDir=([^\\n]+),pid=([^\\n]+),idleTimeout=(.+?),daemonOpts=([^\\n]+)].*",
diff --git a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/testing/DaemonLogsAnalyzer.groovy b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/testing/DaemonLogsAnalyzer.groovy
index 00cb479..26266ba 100644
--- a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/testing/DaemonLogsAnalyzer.groovy
+++ b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/testing/DaemonLogsAnalyzer.groovy
@@ -19,9 +19,6 @@ package org.gradle.launcher.daemon.testing
import org.gradle.launcher.daemon.registry.DaemonRegistry
import org.gradle.launcher.daemon.registry.DaemonRegistryServices
-/**
- * by Szczepan Faber, created at: 9/3/12
- */
class DaemonLogsAnalyzer {
private List<File> daemonLogs
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/GradleMain.java b/subprojects/launcher/src/main/java/org/gradle/launcher/GradleMain.java
index cb42a3a..3515c06 100644
--- a/subprojects/launcher/src/main/java/org/gradle/launcher/GradleMain.java
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/GradleMain.java
@@ -18,9 +18,6 @@ package org.gradle.launcher;
import org.gradle.launcher.bootstrap.ProcessBootstrap;
-/**
- * @author Steven Devijver, Hans Dockter
- */
public class GradleMain {
public static void main(String[] args) throws Exception {
new ProcessBootstrap().run("org.gradle.launcher.Main", args);
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/Main.java b/subprojects/launcher/src/main/java/org/gradle/launcher/Main.java
index 85b33be..001bead 100644
--- a/subprojects/launcher/src/main/java/org/gradle/launcher/Main.java
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/Main.java
@@ -15,16 +15,14 @@
*/
package org.gradle.launcher;
-import org.gradle.launcher.cli.CommandLineActionFactory;
import org.gradle.launcher.bootstrap.EntryPoint;
import org.gradle.launcher.bootstrap.ExecutionListener;
+import org.gradle.launcher.cli.CommandLineActionFactory;
import java.util.Arrays;
/**
* The main command-line entry-point for Gradle.
- *
- * @author Hans Dockter
*/
public class Main extends EntryPoint {
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/bootstrap/ProcessBootstrap.java b/subprojects/launcher/src/main/java/org/gradle/launcher/bootstrap/ProcessBootstrap.java
index 78b064c..c147c81 100644
--- a/subprojects/launcher/src/main/java/org/gradle/launcher/bootstrap/ProcessBootstrap.java
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/bootstrap/ProcessBootstrap.java
@@ -20,9 +20,9 @@ import org.gradle.api.internal.DefaultClassPathProvider;
import org.gradle.api.internal.DefaultClassPathRegistry;
import org.gradle.api.internal.classpath.DefaultModuleRegistry;
import org.gradle.internal.classpath.ClassPath;
-import org.gradle.util.ClassLoaderFactory;
-import org.gradle.util.DefaultClassLoaderFactory;
-import org.gradle.util.MutableURLClassLoader;
+import org.gradle.internal.classloader.ClassLoaderFactory;
+import org.gradle.internal.classloader.DefaultClassLoaderFactory;
+import org.gradle.internal.classloader.MutableURLClassLoader;
import java.lang.reflect.Method;
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/cli/BuildActionsFactory.java b/subprojects/launcher/src/main/java/org/gradle/launcher/cli/BuildActionsFactory.java
index 5a1f320..3c4ec12 100644
--- a/subprojects/launcher/src/main/java/org/gradle/launcher/cli/BuildActionsFactory.java
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/cli/BuildActionsFactory.java
@@ -19,15 +19,19 @@ package org.gradle.launcher.cli;
import org.gradle.StartParameter;
import org.gradle.api.Action;
import org.gradle.api.internal.Actions;
-import org.gradle.cli.CommandLineConverter;
+import org.gradle.internal.service.scopes.GlobalScopeServices;
import org.gradle.cli.CommandLineParser;
import org.gradle.cli.ParsedCommandLine;
+import org.gradle.cli.SystemPropertiesCommandLineConverter;
import org.gradle.configuration.GradleLauncherMetaData;
-import org.gradle.initialization.DefaultCommandLineConverter;
-import org.gradle.initialization.DefaultGradleLauncherFactory;
+import org.gradle.initialization.*;
import org.gradle.internal.SystemProperties;
import org.gradle.internal.service.ServiceRegistry;
import org.gradle.launcher.bootstrap.ExecutionListener;
+import org.gradle.launcher.cli.converter.DaemonCommandLineConverter;
+import org.gradle.launcher.cli.converter.LayoutToPropertiesConverter;
+import org.gradle.launcher.cli.converter.PropertiesToDaemonParametersConverter;
+import org.gradle.launcher.cli.converter.PropertiesToStartParameterConverter;
import org.gradle.launcher.daemon.bootstrap.ForegroundDaemonMain;
import org.gradle.launcher.daemon.client.DaemonClient;
import org.gradle.launcher.daemon.client.DaemonClientServices;
@@ -36,46 +40,81 @@ import org.gradle.launcher.daemon.client.StopDaemonClientServices;
import org.gradle.launcher.daemon.configuration.CurrentProcess;
import org.gradle.launcher.daemon.configuration.DaemonParameters;
import org.gradle.launcher.daemon.configuration.ForegroundDaemonConfiguration;
-import org.gradle.launcher.daemon.configuration.GradlePropertiesConfigurer;
+import org.gradle.launcher.exec.BuildActionExecuter;
import org.gradle.launcher.exec.BuildActionParameters;
-import org.gradle.launcher.exec.GradleLauncherActionExecuter;
-import org.gradle.launcher.exec.InProcessGradleLauncherActionExecuter;
+import org.gradle.launcher.exec.InProcessBuildActionExecuter;
import java.lang.management.ManagementFactory;
+import java.util.HashMap;
+import java.util.Map;
class BuildActionsFactory implements CommandLineAction {
+
private static final String FOREGROUND = "foreground";
- private static final String DAEMON = "daemon";
- private static final String NO_DAEMON = "no-daemon";
private static final String STOP = "stop";
+
private final ServiceRegistry loggingServices;
- private final CommandLineConverter<StartParameter> startParameterConverter;
- private final GradlePropertiesConfigurer propertiesConfigurer;
+ private final LayoutCommandLineConverter layoutConverter;
+
+ private final SystemPropertiesCommandLineConverter propertiesConverter;
+ private final LayoutToPropertiesConverter layoutToPropertiesConverter;
+
+ private final PropertiesToStartParameterConverter propertiesToStartParameterConverter;
+ private final DefaultCommandLineConverter commandLineConverter;
+
+ private final DaemonCommandLineConverter daemonConverter;
+ private final PropertiesToDaemonParametersConverter propertiesToDaemonParametersConverter;
BuildActionsFactory(ServiceRegistry loggingServices) {
- this(loggingServices, new DefaultCommandLineConverter(), new GradlePropertiesConfigurer());
+ this(loggingServices, new DefaultCommandLineConverter());
}
- BuildActionsFactory(ServiceRegistry loggingServices, CommandLineConverter<StartParameter> commandLineConverter,
- GradlePropertiesConfigurer propertiesConfigurer) {
+ BuildActionsFactory(ServiceRegistry loggingServices, DefaultCommandLineConverter commandLineConverter,
+ DaemonCommandLineConverter daemonConverter, LayoutCommandLineConverter layoutConverter,
+ SystemPropertiesCommandLineConverter propertiesConverter,
+ LayoutToPropertiesConverter layoutToPropertiesConverter,
+ PropertiesToStartParameterConverter propertiesToStartParameterConverter,
+ PropertiesToDaemonParametersConverter propertiesToDaemonParametersConverter) {
this.loggingServices = loggingServices;
- this.startParameterConverter = commandLineConverter;
- this.propertiesConfigurer = propertiesConfigurer;
+ this.commandLineConverter = commandLineConverter;
+ this.daemonConverter = daemonConverter;
+ this.layoutConverter = layoutConverter;
+ this.propertiesConverter = propertiesConverter;
+ this.layoutToPropertiesConverter = layoutToPropertiesConverter;
+ this.propertiesToStartParameterConverter = propertiesToStartParameterConverter;
+ this.propertiesToDaemonParametersConverter = propertiesToDaemonParametersConverter;
+ }
+
+ private BuildActionsFactory(ServiceRegistry loggingServices, DefaultCommandLineConverter commandLineConverter) {
+ this(loggingServices, commandLineConverter, new DaemonCommandLineConverter(),
+ commandLineConverter.getLayoutConverter(), commandLineConverter.getSystemPropertiesConverter(),
+ new LayoutToPropertiesConverter(), new PropertiesToStartParameterConverter(), new PropertiesToDaemonParametersConverter());
}
public void configureCommandLineParser(CommandLineParser parser) {
- startParameterConverter.configure(parser);
+ commandLineConverter.configure(parser);
+ daemonConverter.configure(parser);
parser.option(FOREGROUND).hasDescription("Starts the Gradle daemon in the foreground.").incubating();
- parser.option(DAEMON).hasDescription("Uses the Gradle daemon to run the build. Starts the daemon if not running.");
- parser.option(NO_DAEMON).hasDescription("Do not use the Gradle daemon to run the build.");
parser.option(STOP).hasDescription("Stops the Gradle daemon if it is running.");
}
public Action<? super ExecutionListener> createAction(CommandLineParser parser, ParsedCommandLine commandLine) {
+ BuildLayoutParameters layout = new BuildLayoutParameters();
+ layoutConverter.convert(commandLine, layout);
+
+ Map<String, String> properties = new HashMap<String, String>();
+ layoutToPropertiesConverter.convert(layout, properties);
+ propertiesConverter.convert(commandLine, properties);
+
StartParameter startParameter = new StartParameter();
- startParameterConverter.convert(commandLine, startParameter);
- DaemonParameters daemonParameters = propertiesConfigurer.configureParameters(startParameter);
+ propertiesToStartParameterConverter.convert(properties, startParameter);
+ commandLineConverter.convert(commandLine, startParameter);
+
+ DaemonParameters daemonParameters = new DaemonParameters(layout);
+ propertiesToDaemonParametersConverter.convert(properties, daemonParameters);
+ daemonConverter.convert(commandLine, daemonParameters);
+
if (commandLine.hasOption(STOP)) {
return stopAllDaemons(daemonParameters, loggingServices);
}
@@ -84,7 +123,7 @@ class BuildActionsFactory implements CommandLineAction {
daemonParameters.getUid(), daemonParameters.getBaseDir(), daemonParameters.getIdleTimeout());
return Actions.toAction(new ForegroundDaemonMain(conf));
}
- if (useDaemon(commandLine, daemonParameters)) {
+ if (daemonParameters.isEnabled()) {
return runBuildWithDaemon(startParameter, daemonParameters, loggingServices);
}
if (canUseCurrentProcess(daemonParameters)) {
@@ -99,13 +138,6 @@ class BuildActionsFactory implements CommandLineAction {
return Actions.toAction(new StopDaemonAction(stopClient));
}
- private boolean useDaemon(ParsedCommandLine commandLine, DaemonParameters daemonParameters) {
- boolean useDaemon = daemonParameters.isEnabled();
- useDaemon = useDaemon || commandLine.hasOption(DAEMON);
- useDaemon = useDaemon && !commandLine.hasOption(NO_DAEMON);
- return useDaemon;
- }
-
private Action<? super ExecutionListener> runBuildWithDaemon(StartParameter startParameter, DaemonParameters daemonParameters, ServiceRegistry loggingServices) {
// Create a client that will match based on the daemon startup parameters.
DaemonClientServices clientServices = new DaemonClientServices(loggingServices, daemonParameters, System.in);
@@ -119,7 +151,8 @@ class BuildActionsFactory implements CommandLineAction {
}
private Action<? super ExecutionListener> runBuildInProcess(StartParameter startParameter, DaemonParameters daemonParameters, ServiceRegistry loggingServices) {
- InProcessGradleLauncherActionExecuter executer = new InProcessGradleLauncherActionExecuter(new DefaultGradleLauncherFactory(loggingServices));
+ GlobalScopeServices globalServices = new GlobalScopeServices(loggingServices);
+ InProcessBuildActionExecuter executer = new InProcessBuildActionExecuter(globalServices.get(GradleLauncherFactory.class));
return daemonBuildAction(startParameter, daemonParameters, executer);
}
@@ -139,7 +172,7 @@ class BuildActionsFactory implements CommandLineAction {
return daemonBuildAction(startParameter, daemonParameters, client);
}
- private Action<? super ExecutionListener> daemonBuildAction(StartParameter startParameter, DaemonParameters daemonParameters, GradleLauncherActionExecuter<BuildActionParameters> executer) {
+ private Action<? super ExecutionListener> daemonBuildAction(StartParameter startParameter, DaemonParameters daemonParameters, BuildActionExecuter<BuildActionParameters> executer) {
return Actions.toAction(
new RunBuildAction(executer, startParameter, SystemProperties.getCurrentDir(), clientMetaData(), getBuildStartTime(), daemonParameters.getEffectiveSystemProperties(), System.getenv()));
}
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/cli/ExecuteBuildAction.java b/subprojects/launcher/src/main/java/org/gradle/launcher/cli/ExecuteBuildAction.java
index cd49211..078237d 100644
--- a/subprojects/launcher/src/main/java/org/gradle/launcher/cli/ExecuteBuildAction.java
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/cli/ExecuteBuildAction.java
@@ -15,30 +15,22 @@
*/
package org.gradle.launcher.cli;
-import org.gradle.BuildResult;
-import org.gradle.GradleLauncher;
import org.gradle.StartParameter;
-import org.gradle.initialization.GradleLauncherAction;
-import org.gradle.launcher.exec.InitializationAware;
+import org.gradle.initialization.BuildAction;
+import org.gradle.initialization.BuildController;
import java.io.Serializable;
-public class ExecuteBuildAction implements GradleLauncherAction<Void>, InitializationAware, Serializable {
+public class ExecuteBuildAction implements BuildAction<Void>, Serializable {
private final StartParameter startParameter;
public ExecuteBuildAction(StartParameter startParameter) {
this.startParameter = startParameter;
}
- public StartParameter configureStartParameter() {
- return startParameter;
- }
-
- public BuildResult run(GradleLauncher launcher) {
- return launcher.run();
- }
-
- public Void getResult() {
+ public Void run(BuildController buildController) {
+ buildController.setStartParameter(startParameter);
+ buildController.run();
return null;
}
}
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/cli/RunBuildAction.java b/subprojects/launcher/src/main/java/org/gradle/launcher/cli/RunBuildAction.java
index 548fe47..4b98551 100644
--- a/subprojects/launcher/src/main/java/org/gradle/launcher/cli/RunBuildAction.java
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/cli/RunBuildAction.java
@@ -19,7 +19,7 @@ import org.gradle.StartParameter;
import org.gradle.initialization.BuildClientMetaData;
import org.gradle.launcher.exec.BuildActionParameters;
import org.gradle.launcher.exec.DefaultBuildActionParameters;
-import org.gradle.launcher.exec.GradleLauncherActionExecuter;
+import org.gradle.launcher.exec.BuildActionExecuter;
import org.gradle.util.GUtil;
import java.io.File;
@@ -27,7 +27,7 @@ import java.util.HashMap;
import java.util.Map;
public class RunBuildAction implements Runnable {
- private final GradleLauncherActionExecuter<BuildActionParameters> executer;
+ private final BuildActionExecuter<BuildActionParameters> executer;
private final StartParameter startParameter;
private final File currentDir;
private final BuildClientMetaData clientMetaData;
@@ -35,7 +35,7 @@ public class RunBuildAction implements Runnable {
private final Map<String, String> systemProperties;
private final Map<String, String> envVariables;
- public RunBuildAction(GradleLauncherActionExecuter<BuildActionParameters> executer, StartParameter startParameter, File currentDir, BuildClientMetaData clientMetaData, long startTime, Map<?, ?> systemProperties, Map<String, String> envVariables) {
+ public RunBuildAction(BuildActionExecuter<BuildActionParameters> executer, StartParameter startParameter, File currentDir, BuildClientMetaData clientMetaData, long startTime, Map<?, ?> systemProperties, Map<String, String> envVariables) {
this.executer = executer;
this.startParameter = startParameter;
this.currentDir = currentDir;
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/cli/converter/DaemonCommandLineConverter.java b/subprojects/launcher/src/main/java/org/gradle/launcher/cli/converter/DaemonCommandLineConverter.java
new file mode 100644
index 0000000..80166cf
--- /dev/null
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/cli/converter/DaemonCommandLineConverter.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.launcher.cli.converter;
+
+import org.gradle.cli.AbstractCommandLineConverter;
+import org.gradle.cli.CommandLineArgumentException;
+import org.gradle.cli.CommandLineParser;
+import org.gradle.cli.ParsedCommandLine;
+import org.gradle.initialization.BuildLayoutParameters;
+import org.gradle.launcher.daemon.configuration.DaemonParameters;
+
+public class DaemonCommandLineConverter extends AbstractCommandLineConverter<DaemonParameters> {
+
+ private static final String DAEMON = "daemon";
+ private static final String NO_DAEMON = "no-daemon";
+
+ protected DaemonParameters newInstance() {
+ return new DaemonParameters(new BuildLayoutParameters());
+ }
+
+ public DaemonParameters convert(ParsedCommandLine args, DaemonParameters target) throws CommandLineArgumentException {
+ if (args.hasOption(NO_DAEMON)) {
+ return target.setEnabled(false);
+ }
+ if (args.hasOption(DAEMON)) {
+ return target.setEnabled(true);
+ }
+ return target;
+ }
+
+ public void configure(CommandLineParser parser) {
+ parser.option(DAEMON).hasDescription("Uses the Gradle daemon to run the build. Starts the daemon if not running.");
+ parser.option(NO_DAEMON).hasDescription("Do not use the Gradle daemon to run the build.");
+ parser.allowOneOf(DAEMON, NO_DAEMON);
+ }
+}
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/cli/converter/LayoutToPropertiesConverter.java b/subprojects/launcher/src/main/java/org/gradle/launcher/cli/converter/LayoutToPropertiesConverter.java
new file mode 100644
index 0000000..cc31c85
--- /dev/null
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/cli/converter/LayoutToPropertiesConverter.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.launcher.cli.converter;
+
+import org.gradle.api.Project;
+import org.gradle.api.UncheckedIOException;
+import org.gradle.initialization.BuildLayoutParameters;
+import org.gradle.initialization.layout.BuildLayout;
+import org.gradle.initialization.layout.BuildLayoutFactory;
+import org.gradle.launcher.daemon.configuration.GradleProperties;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Map;
+import java.util.Properties;
+
+public class LayoutToPropertiesConverter {
+ public Map<String, String> convert(BuildLayoutParameters layout, Map<String, String> properties) {
+ configureFromBuildDir(layout.getProjectDir(), layout.getSearchUpwards(), properties);
+ configureFromGradleUserHome(layout.getGradleUserHomeDir(), properties);
+ properties.putAll((Map) System.getProperties());
+ return properties;
+ }
+
+ private void configureFromGradleUserHome(File gradleUserHomeDir, Map<String, String> result) {
+ maybeConfigureFrom(new File(gradleUserHomeDir, Project.GRADLE_PROPERTIES), result);
+ }
+
+ private void configureFromBuildDir(File currentDir, boolean searchUpwards, Map<String, String> result) {
+ BuildLayoutFactory factory = new BuildLayoutFactory();
+ BuildLayout layout = factory.getLayoutFor(currentDir, searchUpwards);
+ maybeConfigureFrom(new File(layout.getRootDirectory(), Project.GRADLE_PROPERTIES), result);
+ }
+
+ private void maybeConfigureFrom(File propertiesFile, Map<String, String> result) {
+ if (!propertiesFile.isFile()) {
+ return;
+ }
+
+ Properties properties = new Properties();
+ try {
+ FileInputStream inputStream = new FileInputStream(propertiesFile);
+ try {
+ properties.load(inputStream);
+ } finally {
+ inputStream.close();
+ }
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+
+ for (Object key : properties.keySet()) {
+ if (GradleProperties.ALL.contains(key.toString())) {
+ result.put(key.toString(), properties.get(key).toString());
+ }
+ }
+ }
+}
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/cli/converter/PropertiesToDaemonParametersConverter.java b/subprojects/launcher/src/main/java/org/gradle/launcher/cli/converter/PropertiesToDaemonParametersConverter.java
new file mode 100644
index 0000000..d5a22f0
--- /dev/null
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/cli/converter/PropertiesToDaemonParametersConverter.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.launcher.cli.converter;
+
+import org.gradle.api.GradleException;
+import org.gradle.internal.jvm.JavaHomeException;
+import org.gradle.internal.jvm.Jvm;
+import org.gradle.launcher.daemon.configuration.DaemonParameters;
+import org.gradle.process.internal.JvmOptions;
+
+import java.io.File;
+import java.util.Map;
+
+import static org.gradle.launcher.daemon.configuration.GradleProperties.*;
+
+public class PropertiesToDaemonParametersConverter {
+ public void convert(Map<String, String> properties, DaemonParameters target) {
+ String prop = properties.get(IDLE_TIMEOUT_PROPERTY);
+ if (prop != null) {
+ try {
+ target.setIdleTimeout(new Integer(prop));
+ } catch (NumberFormatException e) {
+ throw new GradleException(String.format("Unable to parse %s property. The value should be an int but is: %s", IDLE_TIMEOUT_PROPERTY, prop));
+ }
+ }
+
+ prop = properties.get(JVM_ARGS_PROPERTY);
+ if (prop != null) {
+ target.setJvmArgs(JvmOptions.fromString(prop));
+ }
+
+ prop = properties.get(JAVA_HOME_PROPERTY);
+ if (prop != null) {
+ File javaHome = new File(prop);
+ if (!javaHome.isDirectory()) {
+ throw new GradleException(String.format("Java home supplied via '%s' is invalid. Invalid directory: %s", JAVA_HOME_PROPERTY, prop));
+ }
+ try {
+ Jvm.forHome(javaHome);
+ } catch (JavaHomeException e) {
+ throw new GradleException(String.format("Java home supplied via '%s' seems to be invalid: %s", JAVA_HOME_PROPERTY, prop));
+ }
+ target.setJavaHome(javaHome);
+ }
+
+ prop = properties.get(BASE_DIR_PROPERTY);
+ if (prop != null) {
+ target.setBaseDir(new File(prop));
+ }
+
+ target.setEnabled(isTrue(properties.get(DAEMON_ENABLED_PROPERTY)));
+ target.setDebug(isTrue(properties.get(DEBUG_MODE_PROPERTY)));
+ }
+}
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/cli/converter/PropertiesToStartParameterConverter.java b/subprojects/launcher/src/main/java/org/gradle/launcher/cli/converter/PropertiesToStartParameterConverter.java
new file mode 100644
index 0000000..361b87c
--- /dev/null
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/cli/converter/PropertiesToStartParameterConverter.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.launcher.cli.converter;
+
+import org.gradle.StartParameter;
+import org.gradle.launcher.daemon.configuration.GradleProperties;
+
+import java.util.Map;
+
+import static org.gradle.launcher.daemon.configuration.GradleProperties.isTrue;
+
+public class PropertiesToStartParameterConverter {
+ public StartParameter convert(Map<String, String> properties, StartParameter startParameter) {
+ startParameter.setConfigureOnDemand(isTrue(properties.get(GradleProperties.CONFIGURE_ON_DEMAND_PROPERTY)));
+
+ String parallel = properties.get(GradleProperties.PARALLEL_PROPERTY);
+ if (isTrue(parallel)) {
+ startParameter.setParallelThreadCount(-1);
+ }
+ return startParameter;
+ }
+}
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/DaemonExecHandleBuilder.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/DaemonExecHandleBuilder.java
index 0686b98..634e4ff 100644
--- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/DaemonExecHandleBuilder.java
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/DaemonExecHandleBuilder.java
@@ -23,9 +23,6 @@ import org.gradle.process.internal.ExecHandleBuilder;
import java.io.File;
import java.util.List;
-/**
- * by Szczepan Faber, created at: 5/7/12
- */
public class DaemonExecHandleBuilder {
ExecHandleBuilder builder = new ExecHandleBuilder();
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/bootstrap/DaemonGreeter.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/bootstrap/DaemonGreeter.java
index 54bfe35..eb49e9b 100644
--- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/bootstrap/DaemonGreeter.java
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/bootstrap/DaemonGreeter.java
@@ -22,9 +22,6 @@ import org.gradle.launcher.daemon.diagnostics.DaemonDiagnostics;
import org.gradle.launcher.daemon.logging.DaemonMessages;
import org.gradle.process.ExecResult;
-/**
- * by Szczepan Faber, created at: 1/19/12
- */
public class DaemonGreeter {
private final DocumentationRegistry documentationRegistry;
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/bootstrap/DaemonOutputConsumer.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/bootstrap/DaemonOutputConsumer.java
index c1f7b36..9b623d4 100644
--- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/bootstrap/DaemonOutputConsumer.java
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/bootstrap/DaemonOutputConsumer.java
@@ -27,9 +27,6 @@ import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Scanner;
-/**
-* by Szczepan Faber, created at: 4/28/12
-*/
public class DaemonOutputConsumer implements StreamsHandler {
private final static Logger LOGGER = Logging.getLogger(DaemonOutputConsumer.class);
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/bootstrap/DaemonStartupCommunication.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/bootstrap/DaemonStartupCommunication.java
index fc76f56..3a8e61c 100644
--- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/bootstrap/DaemonStartupCommunication.java
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/bootstrap/DaemonStartupCommunication.java
@@ -24,9 +24,6 @@ import org.gradle.launcher.daemon.logging.DaemonMessages;
import java.io.File;
import java.io.PrintStream;
-/**
- * by Szczepan Faber, created at: 4/10/12
- */
public class DaemonStartupCommunication {
private static final String DELIM = ";:"; //this very simple delim should be safe for any kind of path.
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/DaemonClient.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/DaemonClient.java
index ad0bf4d..24958eb 100644
--- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/DaemonClient.java
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/DaemonClient.java
@@ -19,7 +19,7 @@ import org.gradle.api.GradleException;
import org.gradle.api.internal.specs.ExplainingSpec;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
-import org.gradle.initialization.GradleLauncherAction;
+import org.gradle.initialization.BuildAction;
import org.gradle.internal.UncheckedException;
import org.gradle.internal.concurrent.ExecutorFactory;
import org.gradle.internal.id.IdGenerator;
@@ -27,8 +27,8 @@ import org.gradle.launcher.daemon.context.DaemonContext;
import org.gradle.launcher.daemon.diagnostics.DaemonDiagnostics;
import org.gradle.launcher.daemon.logging.DaemonMessages;
import org.gradle.launcher.daemon.protocol.*;
+import org.gradle.launcher.exec.BuildActionExecuter;
import org.gradle.launcher.exec.BuildActionParameters;
-import org.gradle.launcher.exec.GradleLauncherActionExecuter;
import org.gradle.logging.internal.OutputEvent;
import org.gradle.logging.internal.OutputEventListener;
import org.gradle.messaging.remote.internal.Connection;
@@ -50,9 +50,10 @@ import java.util.Set;
* <li>If the build is started, the client may send zero or more {@link ForwardInput} messages followed by exactly one {@link CloseInput} message.</li>
* <li>The daemon sends exactly one {@link Result} message. It may no longer send any messages.</li>
* <li>The client sends a {@link CloseInput} message, if not already sent. It may no longer send any {@link ForwardInput} messages.</li>
- * <li>The client sends a {@link Finished} message. It may no longer messages.</li>
+ * <li>The client sends a {@link Finished} message once it has received the {@link Result} message.
+ * It may no longer send any messages.</li>
* <li>The client closes the connection.</li>
- * <li>The daemon closes the connection.</li>
+ * <li>The daemon closes the connection once it has received the {@link Finished} message.</li>
* </ul>
*
* <p>To stop a daemon:</p>
@@ -61,15 +62,16 @@ import java.util.Set;
* <li>The client creates a connection to daemon.</li>
* <li>The client sends exactly one {@link Stop} message.</li>
* <li>The daemon sends exactly one {@link Result} message. It may no longer send any messages.</li>
- * <li>The client sends a {@link Finished} message. It may no longer messages.</li>
+ * <li>The client sends a {@link Finished} message once it has received the {@link Result} message.
+ * It may no longer send any messages.</li>
* <li>The client closes the connection.</li>
- * <li>The daemon closes the connection.</li>
+ * <li>The daemon closes the connection once it has received the {@link Finished} message.</li>
* </ul>
*
* <p>
* If the daemon returns a {@code null} message before returning a {@link Result} object, it has terminated unexpectedly for some reason.
*/
-public class DaemonClient implements GradleLauncherActionExecuter<BuildActionParameters> {
+public class DaemonClient implements BuildActionExecuter<BuildActionParameters> {
private static final Logger LOGGER = Logging.getLogger(DaemonClient.class);
private static final int STOP_TIMEOUT_SECONDS = 30;
private final DaemonConnector connector;
@@ -79,7 +81,7 @@ public class DaemonClient implements GradleLauncherActionExecuter<BuildActionPar
private final ExecutorFactory executorFactory;
private final IdGenerator<?> idGenerator;
- //TODO SF - outputEventListener and buildStandardInput are per-build settings
+ //TODO - outputEventListener and buildStandardInput are per-build settings
//so down the road we should refactor the code accordingly and potentially attach them to BuildActionParameters
public DaemonClient(DaemonConnector connector, OutputEventListener outputEventListener, ExplainingSpec<DaemonContext> compatibilitySpec,
InputStream buildStandardInput, ExecutorFactory executorFactory, IdGenerator<?> idGenerator) {
@@ -140,7 +142,7 @@ public class DaemonClient implements GradleLauncherActionExecuter<BuildActionPar
* @param action The action
* @throws org.gradle.launcher.exec.ReportedException On failure, when the failure has already been logged/reported.
*/
- public <T> T execute(GradleLauncherAction<T> action, BuildActionParameters parameters) {
+ public <T> T execute(BuildAction<T> action, BuildActionParameters parameters) {
Build build = new Build(idGenerator.generateId(), action, parameters);
int saneNumberOfAttempts = 100; //is it sane enough?
for (int i = 1; i < saneNumberOfAttempts; i++) {
@@ -154,7 +156,7 @@ public class DaemonClient implements GradleLauncherActionExecuter<BuildActionPar
connection.stop();
}
}
- //TODO SF if we want to keep below sanity it should include the errors that were accumulated above.
+ //TODO it would be nice if below includes the errors that were accumulated above.
throw new NoUsableDaemonFoundException("Unable to find a usable idle daemon. I have connected to "
+ saneNumberOfAttempts + " different daemons but I could not use any of them to run build: " + build + ".");
}
@@ -165,11 +167,11 @@ public class DaemonClient implements GradleLauncherActionExecuter<BuildActionPar
LOGGER.info("Connected to the daemon. Dispatching {} request.", build);
connection.dispatch(build);
result = connection.receive();
- } catch (Exception e) {
- LOGGER.debug("Unable to perform initial dispatch/receive with the daemon.", e);
+ } catch (StaleDaemonAddressException e) {
+ LOGGER.debug("Connected to a stale daemon address.", e);
//We might fail hard here on the assumption that something weird happened to the daemon.
//However, since we haven't yet started running the build, we can recover by just trying again...
- throw new DaemonInitialConnectException("Problem when attempted to send and receive first result from the daemon.");
+ throw new DaemonInitialConnectException("Connected to a stale daemon address.", e);
}
if (result == null) {
throw new DaemonInitialConnectException("The first result from the daemon was empty. Most likely the process died immediately after connection.");
@@ -231,7 +233,7 @@ public class DaemonClient implements GradleLauncherActionExecuter<BuildActionPar
}
private IllegalStateException invalidResponse(Object response, Build command) {
- //TODO SF we could include diagnostics here (they might be available).
+ //TODO diagnostics could be included in the exception (they might be available).
return new IllegalStateException(String.format(
"Received invalid response from the daemon: '%s' is a result of a type we don't have a strategy to handle."
+ "Earlier, '%s' request was sent to the daemon.", response, command));
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/DaemonClientConnection.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/DaemonClientConnection.java
index 5976309..42842f2 100644
--- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/DaemonClientConnection.java
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/DaemonClientConnection.java
@@ -15,7 +15,7 @@
*/
package org.gradle.launcher.daemon.client;
-import org.gradle.api.GradleException;
+import org.gradle.api.Nullable;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
import org.gradle.messaging.remote.internal.Connection;
@@ -24,15 +24,16 @@ import org.gradle.messaging.remote.internal.Connection;
* A simple wrapper for the connection to a daemon plus its password.
*/
public class DaemonClientConnection implements Connection<Object> {
- final Connection<Object> connection;
- private final String uid;
- final Runnable onFailure;
private final static Logger LOG = Logging.getLogger(DaemonClientConnection.class);
+ private final Connection<Object> connection;
+ private final String uid;
+ private final StaleAddressDetector staleAddressDetector;
+ private boolean hasReceived;
- public DaemonClientConnection(Connection<Object> connection, String uid, Runnable onFailure) {
+ public DaemonClientConnection(Connection<Object> connection, String uid, StaleAddressDetector staleAddressDetector) {
this.connection = connection;
this.uid = uid;
- this.onFailure = onFailure;
+ this.staleAddressDetector = staleAddressDetector;
}
public void requestStop() {
@@ -44,25 +45,31 @@ public class DaemonClientConnection implements Connection<Object> {
return uid;
}
- public void dispatch(Object message) {
+ public void dispatch(Object message) throws DaemonConnectionException {
LOG.debug("thread {}: dispatching {}", Thread.currentThread().getId(), message.getClass());
try {
connection.dispatch(message);
} catch (Exception e) {
LOG.debug("Problem dispatching message to the daemon. Performing 'on failure' operation...");
- onFailure.run();
- throw new GradleException("Unable to dispatch the message to the daemon.", e);
+ if (!hasReceived && staleAddressDetector.maybeStaleAddress(e)) {
+ throw new StaleDaemonAddressException("Could not dispatch a message to the daemon.", e);
+ }
+ throw new DaemonConnectionException("Could not dispatch a message to the daemon.", e);
}
}
- public Object receive() {
+ @Nullable
+ public Object receive() throws DaemonConnectionException {
try {
- Object result = connection.receive();
- return result;
+ return connection.receive();
} catch (Exception e) {
LOG.debug("Problem receiving message to the daemon. Performing 'on failure' operation...");
- onFailure.run();
- throw new GradleException("Unable to receive a message from the daemon.", e);
+ if (!hasReceived && staleAddressDetector.maybeStaleAddress(e)) {
+ throw new StaleDaemonAddressException("Could not receive a message from the daemon.", e);
+ }
+ throw new DaemonConnectionException("Could not receive a message from the daemon.", e);
+ } finally {
+ hasReceived = true;
}
}
@@ -70,4 +77,11 @@ public class DaemonClientConnection implements Connection<Object> {
LOG.debug("thread {}: connection stop", Thread.currentThread().getId());
connection.stop();
}
+
+ interface StaleAddressDetector {
+ /**
+ * @return true if the failure should be considered due to a stale address.
+ */
+ boolean maybeStaleAddress(Exception failure);
+ }
}
\ No newline at end of file
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/DaemonClientServicesSupport.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/DaemonClientServicesSupport.java
index 5df35c2..fbe570e 100644
--- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/DaemonClientServicesSupport.java
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/DaemonClientServicesSupport.java
@@ -16,11 +16,13 @@
package org.gradle.launcher.daemon.client;
import org.gradle.api.internal.DocumentationRegistry;
-import org.gradle.api.internal.GradleDistributionLocator;
import org.gradle.api.internal.classpath.DefaultModuleRegistry;
import org.gradle.internal.concurrent.DefaultExecutorFactory;
import org.gradle.internal.concurrent.ExecutorFactory;
-import org.gradle.internal.id.*;
+import org.gradle.internal.id.CompositeIdGenerator;
+import org.gradle.internal.id.IdGenerator;
+import org.gradle.internal.id.LongIdGenerator;
+import org.gradle.internal.id.UUIDGenerator;
import org.gradle.internal.nativeplatform.ProcessEnvironment;
import org.gradle.internal.nativeplatform.services.NativeServices;
import org.gradle.internal.service.DefaultServiceRegistry;
@@ -32,9 +34,6 @@ import org.gradle.launcher.daemon.registry.DaemonRegistry;
import org.gradle.logging.internal.OutputEventListener;
import org.gradle.messaging.remote.internal.OutgoingConnector;
import org.gradle.messaging.remote.internal.inet.TcpOutgoingConnector;
-import org.gradle.internal.id.CompositeIdGenerator;
-import org.gradle.internal.id.LongIdGenerator;
-import org.gradle.internal.id.UUIDGenerator;
import java.io.InputStream;
@@ -106,7 +105,7 @@ abstract public class DaemonClientServicesSupport extends DefaultServiceRegistry
}
protected DocumentationRegistry createDocumentationRegistry() {
- return new DocumentationRegistry(get(GradleDistributionLocator.class));
+ return new DocumentationRegistry();
}
protected DefaultModuleRegistry createModuleRegistry() {
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/DaemonConnectionException.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/DaemonConnectionException.java
new file mode 100644
index 0000000..30c0969
--- /dev/null
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/DaemonConnectionException.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.launcher.daemon.client;
+
+/**
+ * Thrown when there is some problem using a daemon connection.
+ */
+public class DaemonConnectionException extends RuntimeException {
+ public DaemonConnectionException(String message) {
+ super(message);
+ }
+
+ public DaemonConnectionException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/DaemonConnector.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/DaemonConnector.java
index 8a645c8..e509f33 100644
--- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/DaemonConnector.java
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/DaemonConnector.java
@@ -15,11 +15,12 @@
*/
package org.gradle.launcher.daemon.client;
+import org.gradle.api.Nullable;
import org.gradle.api.internal.specs.ExplainingSpec;
import org.gradle.launcher.daemon.context.DaemonContext;
/**
- * A daemon connector establishes a connection to either an already running daemon, or a newly started daemon.
+ * A daemon connector establishes a connection to a daemon.
*/
public interface DaemonConnector {
@@ -28,6 +29,7 @@ public interface DaemonConnector {
*
* @return A connection to a matching daemon, or null if none running.
*/
+ @Nullable
public DaemonClientConnection maybeConnect(ExplainingSpec<DaemonContext> constraint);
/**
@@ -37,6 +39,9 @@ public interface DaemonConnector {
*/
public DaemonClientConnection connect(ExplainingSpec<DaemonContext> constraint);
- public DaemonClientConnection createConnection(ExplainingSpec<DaemonContext> constraint);
+ /**
+ * Starts a new daemon and returns a connection to it.
+ */
+ public DaemonClientConnection startDaemon(ExplainingSpec<DaemonContext> constraint);
}
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/DaemonInitialConnectException.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/DaemonInitialConnectException.java
index cc38063..e3ac62e 100644
--- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/DaemonInitialConnectException.java
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/DaemonInitialConnectException.java
@@ -21,4 +21,8 @@ class DaemonInitialConnectException extends GradleException {
public DaemonInitialConnectException(String message) {
super(message);
}
+
+ public DaemonInitialConnectException(String message, Throwable cause) {
+ super(message, cause);
+ }
}
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/DefaultDaemonConnector.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/DefaultDaemonConnector.java
index 2e38c85..8f0474a 100644
--- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/DefaultDaemonConnector.java
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/DefaultDaemonConnector.java
@@ -15,7 +15,6 @@
*/
package org.gradle.launcher.daemon.client;
-import org.gradle.api.GradleException;
import org.gradle.api.internal.specs.ExplainingSpec;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
@@ -70,20 +69,20 @@ public class DefaultDaemonConnector implements DaemonConnector {
return connection;
}
- return createConnection(constraint);
+ return startDaemon(constraint);
}
private DaemonClientConnection findConnection(List<DaemonInfo> daemonInfos, ExplainingSpec<DaemonContext> constraint) {
- for (DaemonInfo daemonInfo : daemonInfos) {
+ for (final DaemonInfo daemonInfo : daemonInfos) {
if (!constraint.isSatisfiedBy(daemonInfo.getContext())) {
- LOGGER.debug("Found daemon (address: {}, idle: {}) however it's context does not match the desired criteria.\n"
+ LOGGER.debug("Found daemon (address: {}, idle: {}) however its context does not match the desired criteria.\n"
+ constraint.whyUnsatisfied(daemonInfo.getContext()) + "\n"
+ " Looking for a different daemon...", daemonInfo.getAddress(), daemonInfo.isIdle());
continue;
}
try {
- return connectToDaemon(daemonInfo);
+ return connectToDaemon(daemonInfo, new CleanupOnStaleAddress(daemonInfo, true));
} catch (ConnectException e) {
LOGGER.debug("Cannot connect to the daemon at " + daemonInfo.getAddress() + " due to " + e + ". Trying a different daemon...");
}
@@ -91,24 +90,24 @@ public class DefaultDaemonConnector implements DaemonConnector {
return null;
}
- public DaemonClientConnection createConnection(ExplainingSpec<DaemonContext> constraint) {
+ public DaemonClientConnection startDaemon(ExplainingSpec<DaemonContext> constraint) {
LOGGER.info("Starting Gradle daemon");
final DaemonStartupInfo startupInfo = daemonStarter.startDaemon();
LOGGER.debug("Started Gradle Daemon: {}", startupInfo);
long expiry = System.currentTimeMillis() + connectTimeout;
do {
+ DaemonClientConnection daemonConnection = connectToDaemonWithId(startupInfo, constraint);
+ if (daemonConnection != null) {
+ return daemonConnection;
+ }
try {
Thread.sleep(200L);
} catch (InterruptedException e) {
throw UncheckedException.throwAsUncheckedException(e);
}
- DaemonClientConnection daemonConnection = connectToDaemonWithId(startupInfo, constraint);
- if (daemonConnection != null) {
- return daemonConnection;
- }
} while (System.currentTimeMillis() < expiry);
- throw new GradleException("Timeout waiting to connect to Gradle daemon.\n" + startupInfo.describe());
+ throw new DaemonConnectionException("Timeout waiting to connect to the Gradle daemon.\n" + startupInfo.describe());
}
private DaemonClientConnection connectToDaemonWithId(DaemonStartupInfo startupInfo, ExplainingSpec<DaemonContext> constraint) throws ConnectException {
@@ -117,39 +116,43 @@ public class DefaultDaemonConnector implements DaemonConnector {
if (daemonInfo.getContext().getUid().equals(startupInfo.getUid())) {
try {
if (!constraint.isSatisfiedBy(daemonInfo.getContext())) {
- throw new GradleException("The newly created daemon process has a different context than expected."
+ throw new DaemonConnectionException("The newly created daemon process has a different context than expected."
+ "\nIt won't be possible to reconnect to this daemon. Context mismatch: "
+ "\n" + constraint.whyUnsatisfied(daemonInfo.getContext()));
}
- return connectToDaemon(daemonInfo);
+ return connectToDaemon(daemonInfo, new CleanupOnStaleAddress(daemonInfo, false));
} catch (ConnectException e) {
- throw new GradleException("The forked daemon process died before we could connect.\n" + startupInfo.describe(), e);
+ throw new DaemonConnectionException("Could not connect to the Gradle daemon.\n" + startupInfo.describe(), e);
}
}
}
return null;
}
- private DaemonClientConnection connectToDaemon(final DaemonInfo daemonInfo) throws ConnectException {
- Runnable onFailure = new Runnable() {
- public void run() {
- LOGGER.info(DaemonMessages.REMOVING_DAEMON_ADDRESS_ON_FAILURE + daemonInfo);
- try {
- daemonRegistry.remove(daemonInfo.getAddress());
- } catch (Exception e) {
- //If we cannot remove then the file is corrupt or the registry is empty. We can ignore it here.
- LOGGER.info("Problem removing the address from the registry due to: " + e + ". It will be cleaned up later.");
- //TODO SF, actually we probably want always safely remove so it would be good to reduce the duplication.
- }
- }
- };
+ private DaemonClientConnection connectToDaemon(DaemonInfo daemonInfo, DaemonClientConnection.StaleAddressDetector staleAddressDetector) throws ConnectException {
Connection<Object> connection;
try {
connection = connector.connect(daemonInfo.getAddress(), getClass().getClassLoader());
} catch (ConnectException e) {
- onFailure.run();
+ staleAddressDetector.maybeStaleAddress(e);
throw e;
}
- return new DaemonClientConnection(connection, daemonInfo.getContext().getUid(), onFailure);
+ return new DaemonClientConnection(connection, daemonInfo.getContext().getUid(), staleAddressDetector);
+ }
+
+ private class CleanupOnStaleAddress implements DaemonClientConnection.StaleAddressDetector {
+ private final DaemonInfo daemonInfo;
+ private final boolean exposeAsStale;
+
+ public CleanupOnStaleAddress(DaemonInfo daemonInfo, boolean exposeAsStale) {
+ this.daemonInfo = daemonInfo;
+ this.exposeAsStale = exposeAsStale;
+ }
+
+ public boolean maybeStaleAddress(Exception failure) {
+ LOGGER.info(DaemonMessages.REMOVING_DAEMON_ADDRESS_ON_FAILURE + daemonInfo);
+ daemonRegistry.remove(daemonInfo.getAddress());
+ return exposeAsStale;
+ }
}
}
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/EmbeddedDaemonClientServices.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/EmbeddedDaemonClientServices.java
index 665780e..5b653d2 100644
--- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/EmbeddedDaemonClientServices.java
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/EmbeddedDaemonClientServices.java
@@ -15,7 +15,9 @@
*/
package org.gradle.launcher.daemon.client;
-import org.gradle.initialization.DefaultGradleLauncherFactory;
+import org.gradle.internal.service.scopes.GlobalScopeServices;
+import org.gradle.initialization.BuildLayoutParameters;
+import org.gradle.initialization.GradleLauncherFactory;
import org.gradle.internal.Factory;
import org.gradle.internal.concurrent.ExecutorFactory;
import org.gradle.internal.nativeplatform.ProcessEnvironment;
@@ -65,13 +67,13 @@ public class EmbeddedDaemonClientServices extends DaemonClientServicesSupport {
protected DaemonCommandExecuter createDaemonCommandExecuter() {
LoggingManagerInternal mgr = getLoggingServices().getFactory(LoggingManagerInternal.class).create();
- return new DefaultDaemonCommandExecuter(new DefaultGradleLauncherFactory(getLoggingServices()),
- get(ProcessEnvironment.class), mgr, new File("dummy"));
+ return new DefaultDaemonCommandExecuter(get(GradleLauncherFactory.class), get(ProcessEnvironment.class), mgr, new File("dummy"));
}
public EmbeddedDaemonClientServices(ServiceRegistry loggingServices, boolean displayOutput) {
super(loggingServices, System.in);
this.displayOutput = displayOutput;
+ add(new GlobalScopeServices(loggingServices));
add(EmbeddedDaemonFactory.class, new EmbeddedDaemonFactory());
}
@@ -90,7 +92,7 @@ public class EmbeddedDaemonClientServices extends DaemonClientServicesSupport {
@Override
protected void configureDaemonContextBuilder(DaemonContextBuilder builder) {
builder.setUid(UUID.randomUUID().toString());
- builder.setDaemonRegistryDir(new DaemonDir(new DaemonParameters().getBaseDir()).getRegistry());
+ builder.setDaemonRegistryDir(new DaemonDir(new DaemonParameters(new BuildLayoutParameters()).getBaseDir()).getRegistry());
}
protected DaemonServerConnector createDaemonServerConnector() {
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/NoUsableDaemonFoundException.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/NoUsableDaemonFoundException.java
index 078d774..ad7ccf6 100644
--- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/NoUsableDaemonFoundException.java
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/NoUsableDaemonFoundException.java
@@ -18,9 +18,6 @@ package org.gradle.launcher.daemon.client;
import org.gradle.api.GradleException;
-/**
-* by Szczepan Faber, created at: 2/24/12
-*/
public class NoUsableDaemonFoundException extends GradleException {
public NoUsableDaemonFoundException(String message) {
super(message);
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/SingleUseDaemonClient.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/SingleUseDaemonClient.java
index b103b94..748e2f1 100644
--- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/SingleUseDaemonClient.java
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/SingleUseDaemonClient.java
@@ -19,7 +19,9 @@ package org.gradle.launcher.daemon.client;
import org.gradle.api.internal.DocumentationRegistry;
import org.gradle.api.internal.specs.ExplainingSpec;
import org.gradle.api.internal.specs.ExplainingSpecs;
-import org.gradle.initialization.GradleLauncherAction;
+import org.gradle.api.logging.Logger;
+import org.gradle.api.logging.Logging;
+import org.gradle.initialization.BuildAction;
import org.gradle.internal.concurrent.ExecutorFactory;
import org.gradle.internal.id.IdGenerator;
import org.gradle.launcher.daemon.context.DaemonContext;
@@ -27,13 +29,12 @@ import org.gradle.launcher.daemon.protocol.Build;
import org.gradle.launcher.daemon.protocol.BuildAndStop;
import org.gradle.launcher.exec.BuildActionParameters;
import org.gradle.logging.internal.OutputEventListener;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import java.io.InputStream;
public class SingleUseDaemonClient extends DaemonClient {
- private static final Logger LOGGER = LoggerFactory.getLogger(SingleUseDaemonClient.class);
+ public static final String MESSAGE = "To honour the JVM settings for this build a new JVM will be forked.";
+ private static final Logger LOGGER = Logging.getLogger(SingleUseDaemonClient.class);
private final DocumentationRegistry documentationRegistry;
public SingleUseDaemonClient(DaemonConnector connector, OutputEventListener outputEventListener, ExplainingSpec<DaemonContext> compatibilitySpec, InputStream buildStandardInput,
@@ -43,13 +44,11 @@ public class SingleUseDaemonClient extends DaemonClient {
}
@Override
- public <T> T execute(GradleLauncherAction<T> action, BuildActionParameters parameters) {
- LOGGER.warn("Note: in order to honour the org.gradle.jvmargs and/or org.gradle.java.home values specified for this build, it is necessary to fork a new JVM.");
- LOGGER.warn("To avoid the slowdown associated with this extra process, you might want to consider running Gradle with the daemon enabled.");
- LOGGER.warn("Please see the user guide chapter on the daemon at {}.", documentationRegistry.getDocumentationFor("gradle_daemon"));
+ public <T> T execute(BuildAction<T> action, BuildActionParameters parameters) {
+ LOGGER.lifecycle("{} Please consider using the daemon: {}.", MESSAGE, documentationRegistry.getDocumentationFor("gradle_daemon"));
Build build = new BuildAndStop(getIdGenerator().generateId(), action, parameters);
- DaemonClientConnection daemonConnection = getConnector().createConnection(ExplainingSpecs.<DaemonContext>satisfyAll());
+ DaemonClientConnection daemonConnection = getConnector().startDaemon(ExplainingSpecs.<DaemonContext>satisfyAll());
return (T) executeBuild(build, daemonConnection);
}
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/StaleDaemonAddressException.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/StaleDaemonAddressException.java
new file mode 100644
index 0000000..a24dce6
--- /dev/null
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/StaleDaemonAddressException.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.launcher.daemon.client;
+
+/**
+ * Thrown when connected to a stale daemon address.
+ *
+ * This is thrown instead of using an initial handshake on the connection, to avoid the latency of a round trip to the
+ * daemon before starting the build.
+ */
+public class StaleDaemonAddressException extends DaemonConnectionException {
+ public StaleDaemonAddressException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/StopDaemonClientServices.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/StopDaemonClientServices.java
index 82284a3..2c0801b 100644
--- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/StopDaemonClientServices.java
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/StopDaemonClientServices.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012 the original author or authors.
+ * Copyright 2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/StopDispatcher.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/StopDispatcher.java
index d77e259..7c665fc 100644
--- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/StopDispatcher.java
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/StopDispatcher.java
@@ -25,9 +25,6 @@ import org.gradle.launcher.daemon.protocol.Result;
import org.gradle.launcher.daemon.protocol.Stop;
import org.gradle.messaging.remote.internal.Connection;
-/**
- * @author: Szczepan Faber, created at: 9/13/11
- */
public class StopDispatcher {
private static final Logger LOGGER = Logging.getLogger(StopDispatcher.class);
private final IdGenerator<?> idGenerator;
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/configuration/DaemonParameters.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/configuration/DaemonParameters.java
index f0758c2..6f2f025 100644
--- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/configuration/DaemonParameters.java
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/configuration/DaemonParameters.java
@@ -17,6 +17,7 @@ package org.gradle.launcher.daemon.configuration;
import org.gradle.StartParameter;
import org.gradle.api.internal.file.IdentityFileResolver;
+import org.gradle.initialization.BuildLayoutParameters;
import org.gradle.internal.jvm.Jvm;
import org.gradle.process.internal.JvmOptions;
import org.gradle.util.GUtil;
@@ -39,13 +40,10 @@ public class DaemonParameters {
private boolean enabled;
private File javaHome;
- public DaemonParameters(String uid) {
- this.uid = uid;
+ public DaemonParameters(BuildLayoutParameters layout) {
+ this.uid = UUID.randomUUID().toString();
jvmOptions.setAllJvmArgs(getDefaultJvmArgs());
- }
-
- public DaemonParameters() {
- this(UUID.randomUUID().toString());
+ baseDir = new File(layout.getGradleUserHomeDir(), "daemon");
}
List<String> getDefaultJvmArgs() {
@@ -126,24 +124,16 @@ public class DaemonParameters {
jvmOptions.setAllJvmArgs(jvmArgs);
}
- public void configureFrom(GradleProperties gradleProperties) {
- if (gradleProperties.getIdleTimeout() != null) {
- idleTimeout = gradleProperties.getIdleTimeout();
- }
- if (gradleProperties.getJvmArgs() != null) {
- setJvmArgs(JvmOptions.fromString(gradleProperties.getJvmArgs()));
- }
- if (gradleProperties.isDaemonEnabled()) {
- enabled = true;
- }
- if (gradleProperties.getJavaHome() != null) {
- javaHome = gradleProperties.getJavaHome();
- }
- if (gradleProperties.isDebugMode()) {
- jvmOptions.setDebug(true);
- }
- if (gradleProperties.getDaemonBaseDir() != null) {
- baseDir = gradleProperties.getDaemonBaseDir();
- }
+ public void setDebug(boolean debug) {
+ jvmOptions.setDebug(debug);
+ }
+
+ public DaemonParameters setBaseDir(File baseDir) {
+ this.baseDir = baseDir;
+ return this;
+ }
+
+ public boolean getDebug() {
+ return jvmOptions.getDebug();
}
}
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/configuration/DaemonServerConfiguration.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/configuration/DaemonServerConfiguration.java
index a91bcec..121011c 100644
--- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/configuration/DaemonServerConfiguration.java
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/configuration/DaemonServerConfiguration.java
@@ -19,9 +19,6 @@ package org.gradle.launcher.daemon.configuration;
import java.io.File;
import java.util.List;
-/**
- * by Szczepan Faber, created at: 2/21/12
- */
public interface DaemonServerConfiguration {
File getBaseDir();
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/configuration/DefaultDaemonServerConfiguration.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/configuration/DefaultDaemonServerConfiguration.java
index 8e0f898..3d4e706 100644
--- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/configuration/DefaultDaemonServerConfiguration.java
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/configuration/DefaultDaemonServerConfiguration.java
@@ -19,9 +19,6 @@ package org.gradle.launcher.daemon.configuration;
import java.io.File;
import java.util.List;
-/**
- * by Szczepan Faber, created at: 2/21/12
- */
public class DefaultDaemonServerConfiguration implements DaemonServerConfiguration {
private final String daemonUid;
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/configuration/ForegroundDaemonConfiguration.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/configuration/ForegroundDaemonConfiguration.java
index d5fd87f..b8e815c 100644
--- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/configuration/ForegroundDaemonConfiguration.java
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/configuration/ForegroundDaemonConfiguration.java
@@ -18,9 +18,6 @@ package org.gradle.launcher.daemon.configuration;
import java.io.File;
-/**
- * by Szczepan Faber, created at: 2/21/12
- */
public class ForegroundDaemonConfiguration extends DefaultDaemonServerConfiguration {
public ForegroundDaemonConfiguration(String daemonUid, File daemonBaseDir, int idleTimeoutMs) {
// Foreground daemon cannot be 'told' what's his startup options as the client sits in the same process so we will infer the jvm opts from the inputArguments()
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/configuration/GradleProperties.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/configuration/GradleProperties.java
index a8642f6..043c0e6 100644
--- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/configuration/GradleProperties.java
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/configuration/GradleProperties.java
@@ -16,30 +16,14 @@
package org.gradle.launcher.daemon.configuration;
-import org.gradle.StartParameter;
-import org.gradle.api.GradleException;
-import org.gradle.api.Nullable;
-import org.gradle.api.Project;
-import org.gradle.api.UncheckedIOException;
-import org.gradle.initialization.layout.BuildLayout;
-import org.gradle.initialization.layout.BuildLayoutFactory;
-import org.gradle.internal.jvm.JavaHomeException;
-import org.gradle.internal.jvm.Jvm;
-import org.gradle.util.GFileUtils;
+import java.util.Set;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.util.Map;
-import java.util.Properties;
+import static com.google.common.collect.Sets.newHashSet;
-/**
- * by Szczepan Faber, created at: 1/22/13
- */
public class GradleProperties {
public static final String IDLE_TIMEOUT_PROPERTY = "org.gradle.daemon.idletimeout";
- public static final String BASE_DIR_PROPERTY = "org.gradle.daemon.registry.base";
+ public static final String BASE_DIR_PROPERTY = "org.gradle.daemon.registry.base"; //TODO SF rename to daemon...
public static final String JVM_ARGS_PROPERTY = "org.gradle.jvmargs";
public static final String JAVA_HOME_PROPERTY = "org.gradle.java.home";
public static final String DAEMON_ENABLED_PROPERTY = "org.gradle.daemon";
@@ -47,155 +31,10 @@ public class GradleProperties {
public static final String CONFIGURE_ON_DEMAND_PROPERTY = "org.gradle.configureondemand";
public static final String PARALLEL_PROPERTY = "org.gradle.parallel";
- private File daemonBaseDir;
- private String jvmArgs;
-
- private Integer idleTimeout;
- private boolean daemonEnabled;
- private File javaHome;
- private boolean debugMode;
- private boolean configureOnDemand;
- private boolean parallelMode;
-
- public boolean isDaemonEnabled() {
- return daemonEnabled;
- }
-
- @Nullable
- public File getDaemonBaseDir() {
- return daemonBaseDir;
- }
-
- public Integer getIdleTimeout() {
- return idleTimeout;
- }
-
- @Nullable
- public File getJavaHome() {
- return javaHome;
- }
-
- public String getJvmArgs() {
- return jvmArgs;
- }
-
- public boolean isDebugMode() {
- return debugMode;
- }
-
- private void setBaseDir(File baseDir) {
- this.daemonBaseDir = GFileUtils.canonicalise(baseDir);
- }
-
- public GradleProperties configureFromGradleUserHome(File gradleUserHomeDir) {
- setBaseDir(new File(gradleUserHomeDir, "daemon"));
- maybeConfigureFrom(new File(gradleUserHomeDir, Project.GRADLE_PROPERTIES));
- return this;
- }
-
- public GradleProperties configureFromSystemProperties(Map<?, ?> properties) {
- Object propertyValue = properties.get(BASE_DIR_PROPERTY);
- if (propertyValue != null) {
- setBaseDir(new File(propertyValue.toString()));
- }
- configureFrom(properties);
- return this;
- }
-
- public GradleProperties configureFromBuildDir(File currentDir, boolean searchUpwards) {
- BuildLayoutFactory factory = new BuildLayoutFactory();
- BuildLayout layout = factory.getLayoutFor(currentDir, searchUpwards);
- maybeConfigureFrom(new File(layout.getRootDirectory(), Project.GRADLE_PROPERTIES));
- return this;
- }
-
- private void maybeConfigureFrom(File propertiesFile) {
- if (!propertiesFile.isFile()) {
- return;
- }
-
- Properties properties = new Properties();
- try {
- FileInputStream inputStream = new FileInputStream(propertiesFile);
- try {
- properties.load(inputStream);
- } finally {
- inputStream.close();
- }
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
-
- configureFrom(properties);
- }
-
- GradleProperties configureFrom(Map<?, ?> properties) {
- Object propertyValue = properties.get(IDLE_TIMEOUT_PROPERTY);
- if (propertyValue != null) {
- try {
- idleTimeout = new Integer(propertyValue.toString());
- } catch (NumberFormatException e) {
- throw new GradleException(String.format("Unable to parse %s property. The value should be an int but is: %s", IDLE_TIMEOUT_PROPERTY, propertyValue));
- }
- }
- propertyValue = properties.get(JVM_ARGS_PROPERTY);
- if (propertyValue != null) {
- jvmArgs = propertyValue.toString();
- }
- propertyValue = properties.get(DAEMON_ENABLED_PROPERTY);
- if (propertyValue != null) {
- daemonEnabled = isTrue(propertyValue);
- }
-
- propertyValue = properties.get(JAVA_HOME_PROPERTY);
- if (propertyValue != null) {
- javaHome = new File(propertyValue.toString());
- if (!javaHome.isDirectory()) {
- throw new GradleException(String.format("Java home supplied via '%s' is invalid. Dir does not exist: %s", JAVA_HOME_PROPERTY, propertyValue));
- }
- try {
- Jvm.forHome(javaHome);
- } catch (JavaHomeException e) {
- throw new GradleException(String.format("Java home supplied via '%s' seems to be invalid: %s", JAVA_HOME_PROPERTY, propertyValue));
- }
- }
-
- propertyValue = properties.get(DEBUG_MODE_PROPERTY);
- if (propertyValue != null) {
- debugMode = isTrue(propertyValue);
- }
-
- propertyValue = properties.get(CONFIGURE_ON_DEMAND_PROPERTY);
- if (propertyValue != null) {
- configureOnDemand = isTrue(propertyValue);
- }
-
- propertyValue = properties.get(PARALLEL_PROPERTY);
- if (propertyValue != null) {
- parallelMode = isTrue(propertyValue);
- }
-
- return this;
- }
-
- public void updateStartParameter(StartParameter startParameter) {
- if (configureOnDemand) {
- startParameter.setConfigureOnDemand(configureOnDemand);
- }
- if (parallelMode && !startParameter.isParallelThreadCountConfigured()) {
- startParameter.setParallelThreadCount(-1);
- }
- }
-
- public boolean isConfigureOnDemand() {
- return configureOnDemand;
- }
-
- public boolean isParallelMode() {
- return parallelMode;
- }
+ public static final Set<String> ALL = newHashSet(IDLE_TIMEOUT_PROPERTY, BASE_DIR_PROPERTY, JVM_ARGS_PROPERTY,
+ JAVA_HOME_PROPERTY, DAEMON_ENABLED_PROPERTY, DEBUG_MODE_PROPERTY, CONFIGURE_ON_DEMAND_PROPERTY, PARALLEL_PROPERTY);
- private static boolean isTrue(Object propertyValue) {
- return propertyValue.toString().equalsIgnoreCase("true");
+ public static boolean isTrue(Object propertyValue) {
+ return propertyValue != null && propertyValue.toString().equalsIgnoreCase("true");
}
-}
+}
\ No newline at end of file
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/configuration/GradlePropertiesConfigurer.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/configuration/GradlePropertiesConfigurer.java
deleted file mode 100644
index 4948ca1..0000000
--- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/configuration/GradlePropertiesConfigurer.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2013 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.launcher.daemon.configuration;
-
-import org.gradle.StartParameter;
-
-import java.io.File;
-import java.util.Map;
-
-/**
- * by Szczepan Faber, created at: 1/22/13
- */
-public class GradlePropertiesConfigurer {
-
- public GradleProperties prepareProperties(File projectDir, boolean searchUpwards, File gradleUserHomeDir, Map<?, ?> systemProperties) {
- return new GradleProperties()
- .configureFromBuildDir(projectDir, searchUpwards)
- .configureFromGradleUserHome(gradleUserHomeDir)
- .configureFromSystemProperties(systemProperties);
- }
-
- public DaemonParameters configureParameters(StartParameter startParameter) {
- DaemonParameters out = new DaemonParameters();
- GradleProperties properties = configureStartParameter(startParameter);
- out.configureFrom(properties);
- return out;
- }
-
- public GradleProperties configureStartParameter(StartParameter startParameter) {
- GradleProperties properties = this.prepareProperties(startParameter.getCurrentDir(), startParameter.isSearchUpwards(), startParameter.getGradleUserHomeDir(), startParameter.getMergedSystemProperties());
- properties.updateStartParameter(startParameter);
- return properties;
- }
-}
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/diagnostics/DaemonDiagnostics.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/diagnostics/DaemonDiagnostics.java
index 15282d4..8f29a35 100644
--- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/diagnostics/DaemonDiagnostics.java
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/diagnostics/DaemonDiagnostics.java
@@ -23,8 +23,6 @@ import java.io.Serializable;
/**
* Contains some daemon diagnostics information useful for the client.
- * <p>
- * by Szczepan Faber, created at: 2/28/12
*/
public class DaemonDiagnostics implements Serializable {
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/diagnostics/DaemonStartupInfo.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/diagnostics/DaemonStartupInfo.java
index 4dfc94e..a1a8a6d 100644
--- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/diagnostics/DaemonStartupInfo.java
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/diagnostics/DaemonStartupInfo.java
@@ -16,9 +16,6 @@
package org.gradle.launcher.daemon.diagnostics;
-/**
- * by Szczepan Faber, created at 4/6/12
- */
public class DaemonStartupInfo {
private String uid;
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/protocol/Build.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/protocol/Build.java
index b167706..4c7115f 100644
--- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/protocol/Build.java
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/protocol/Build.java
@@ -15,20 +15,20 @@
*/
package org.gradle.launcher.daemon.protocol;
-import org.gradle.initialization.GradleLauncherAction;
+import org.gradle.initialization.BuildAction;
import org.gradle.launcher.exec.BuildActionParameters;
public class Build extends Command {
- private final GradleLauncherAction<?> action;
+ private final BuildAction<?> action;
private final BuildActionParameters parameters;
- public Build(Object identifier, GradleLauncherAction<?> action, BuildActionParameters parameters) {
+ public Build(Object identifier, BuildAction<?> action, BuildActionParameters parameters) {
super(identifier);
this.action = action;
this.parameters = parameters;
}
- public GradleLauncherAction<?> getAction() {
+ public BuildAction<?> getAction() {
return action;
}
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/protocol/BuildAndStop.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/protocol/BuildAndStop.java
index b428089..314a07c 100644
--- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/protocol/BuildAndStop.java
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/protocol/BuildAndStop.java
@@ -16,11 +16,11 @@
package org.gradle.launcher.daemon.protocol;
-import org.gradle.initialization.GradleLauncherAction;
+import org.gradle.initialization.BuildAction;
import org.gradle.launcher.exec.BuildActionParameters;
public class BuildAndStop extends Build {
- public BuildAndStop(Object identifier, GradleLauncherAction<?> action, BuildActionParameters parameters) {
+ public BuildAndStop(Object identifier, BuildAction<?> action, BuildActionParameters parameters) {
super(identifier, action, parameters);
}
}
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/registry/DaemonRegistryContent.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/registry/DaemonRegistryContent.java
index 8955cbb..60a5caf 100644
--- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/registry/DaemonRegistryContent.java
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/registry/DaemonRegistryContent.java
@@ -24,9 +24,6 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
-/**
- * @author: Szczepan Faber, created at: 8/29/11
- */
public class DaemonRegistryContent implements Serializable {
private Map<Address, DaemonInfo> infosMap = new HashMap<Address, DaemonInfo>();
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/registry/DaemonRegistryServices.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/registry/DaemonRegistryServices.java
index 27e05bb..a35b50e 100644
--- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/registry/DaemonRegistryServices.java
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/registry/DaemonRegistryServices.java
@@ -15,13 +15,14 @@
*/
package org.gradle.launcher.daemon.registry;
-import org.gradle.internal.Factory;
import org.gradle.api.internal.cache.Cache;
import org.gradle.api.internal.cache.CacheAccessSerializer;
import org.gradle.api.internal.cache.MapBackedCache;
import org.gradle.cache.internal.DefaultFileLockManager;
import org.gradle.cache.internal.DefaultProcessMetaDataProvider;
import org.gradle.cache.internal.FileLockManager;
+import org.gradle.cache.internal.locklistener.NoOpFileLockContentionHandler;
+import org.gradle.internal.Factory;
import org.gradle.internal.nativeplatform.ProcessEnvironment;
import org.gradle.internal.nativeplatform.services.NativeServices;
import org.gradle.internal.service.DefaultServiceRegistry;
@@ -58,7 +59,7 @@ public class DaemonRegistryServices extends DefaultServiceRegistry {
}
protected FileLockManager createFileLockManager() {
- return new DefaultFileLockManager(new DefaultProcessMetaDataProvider(get(ProcessEnvironment.class)));
+ return new DefaultFileLockManager(new DefaultProcessMetaDataProvider(get(ProcessEnvironment.class)), new NoOpFileLockContentionHandler());
}
protected DaemonRegistry createDaemonRegistry() {
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/registry/PersistentDaemonRegistry.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/registry/PersistentDaemonRegistry.java
index 6bf935d..13677e6 100644
--- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/registry/PersistentDaemonRegistry.java
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/registry/PersistentDaemonRegistry.java
@@ -18,7 +18,6 @@ package org.gradle.launcher.daemon.registry;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
-import org.gradle.messaging.serialize.DefaultSerializer;
import org.gradle.cache.PersistentStateCache;
import org.gradle.cache.internal.FileIntegrityViolationSuppressingPersistentStateCacheDecorator;
import org.gradle.cache.internal.FileLockManager;
@@ -26,6 +25,7 @@ import org.gradle.cache.internal.OnDemandFileAccess;
import org.gradle.cache.internal.SimpleStateCache;
import org.gradle.launcher.daemon.context.DaemonContext;
import org.gradle.messaging.remote.Address;
+import org.gradle.messaging.serialize.DefaultSerializer;
import java.io.File;
import java.util.LinkedList;
@@ -35,8 +35,6 @@ import java.util.concurrent.locks.ReentrantLock;
/**
* Access to daemon registry files. Useful also for testing.
- *
- * @author: Szczepan Faber, created at: 8/18/11
*/
public class PersistentDaemonRegistry implements DaemonRegistry {
private final PersistentStateCache<DaemonRegistryContent> cache;
@@ -128,12 +126,13 @@ public class PersistentDaemonRegistry implements DaemonRegistry {
try {
cache.update(new PersistentStateCache.UpdateAction<DaemonRegistryContent>() {
public DaemonRegistryContent update(DaemonRegistryContent oldValue) {
- assertCacheNotEmpty(oldValue);
- DaemonInfo daemonInfo = oldValue.getInfo(address);
- daemonInfo.setIdle(false);
+ DaemonInfo daemonInfo = oldValue != null ? oldValue.getInfo(address) : null;
+ if (daemonInfo != null) {
+ daemonInfo.setIdle(false);
+ }
+ // Else, has been removed by something else - ignore
return oldValue;
- }
- });
+ }});
} finally {
lock.unlock();
}
@@ -145,8 +144,11 @@ public class PersistentDaemonRegistry implements DaemonRegistry {
try {
cache.update(new PersistentStateCache.UpdateAction<DaemonRegistryContent>() {
public DaemonRegistryContent update(DaemonRegistryContent oldValue) {
- assertCacheNotEmpty(oldValue);
- oldValue.getInfo(address).setIdle(true);
+ DaemonInfo daemonInfo = oldValue != null ? oldValue.getInfo(address) : null;
+ if (daemonInfo != null) {
+ daemonInfo.setIdle(true);
+ }
+ // Else, has been removed by something else - ignore
return oldValue;
}
});
@@ -155,7 +157,7 @@ public class PersistentDaemonRegistry implements DaemonRegistry {
}
}
- public synchronized void store(final Address address, final DaemonContext daemonContext, final String password, final boolean idle) {
+ public void store(final Address address, final DaemonContext daemonContext, final String password, final boolean idle) {
lock.lock();
LOGGER.debug("Storing daemon address: {}, context: {}", address, daemonContext);
try {
@@ -178,10 +180,4 @@ public class PersistentDaemonRegistry implements DaemonRegistry {
public String toString() {
return String.format("PersistentDaemonRegistry[file=%s]", registryFile);
}
-
- private void assertCacheNotEmpty(Object value) {
- if (value == null) {
- throw new EmptyRegistryException("Registry is empty!");
- }
- }
}
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/DaemonServices.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/DaemonServices.java
index 4c61fae..b72a3b5 100644
--- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/DaemonServices.java
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/DaemonServices.java
@@ -15,9 +15,10 @@
*/
package org.gradle.launcher.daemon.server;
+import org.gradle.internal.service.scopes.GlobalScopeServices;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
-import org.gradle.initialization.DefaultGradleLauncherFactory;
+import org.gradle.initialization.GradleLauncherFactory;
import org.gradle.internal.concurrent.DefaultExecutorFactory;
import org.gradle.internal.concurrent.ExecutorFactory;
import org.gradle.internal.nativeplatform.ProcessEnvironment;
@@ -41,18 +42,17 @@ import java.util.UUID;
*/
public class DaemonServices extends DefaultServiceRegistry {
private final DaemonServerConfiguration configuration;
- private final ServiceRegistry loggingServices;
private final LoggingManagerInternal loggingManager;
private final static Logger LOGGER = Logging.getLogger(DaemonServices.class);
public DaemonServices(DaemonServerConfiguration configuration, ServiceRegistry loggingServices,
LoggingManagerInternal loggingManager) {
this.configuration = configuration;
- this.loggingServices = loggingServices;
this.loggingManager = loggingManager;
add(NativeServices.getInstance());
add(new DaemonRegistryServices(configuration.getBaseDir()));
+ add(new GlobalScopeServices(loggingServices));
}
protected ExecutorFactory createExecutorFactory() {
@@ -86,7 +86,7 @@ public class DaemonServices extends DefaultServiceRegistry {
get(DaemonContext.class),
"password",
new DefaultDaemonCommandExecuter(
- new DefaultGradleLauncherFactory(loggingServices),
+ get(GradleLauncherFactory.class),
get(ProcessEnvironment.class),
loggingManager,
getDaemonLogFile()),
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/DomainRegistryUpdater.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/DomainRegistryUpdater.java
index 20ff490..b07b1bd 100644
--- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/DomainRegistryUpdater.java
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/DomainRegistryUpdater.java
@@ -24,9 +24,6 @@ import org.gradle.launcher.daemon.logging.DaemonMessages;
import org.gradle.launcher.daemon.registry.DaemonRegistry;
import org.gradle.messaging.remote.Address;
-/**
-* @author: Szczepan Faber, created at: 9/12/11
-*/
class DomainRegistryUpdater implements Stoppable {
private static final Logger LOGGER = Logging.getLogger(DomainRegistryUpdater.class);
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/SynchronizedDispatchConnection.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/SynchronizedDispatchConnection.java
index 255d460..8a8ee89 100644
--- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/SynchronizedDispatchConnection.java
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/SynchronizedDispatchConnection.java
@@ -24,8 +24,6 @@ import org.slf4j.LoggerFactory;
/**
* Connection decorator that synchronizes dispatching.
- * <p>
- * by Szczepan Faber, created at: 2/27/12
*/
public class SynchronizedDispatchConnection<T> implements Connection<T> {
private static final Logger LOGGER = LoggerFactory.getLogger(SynchronizedDispatchConnection.class);
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/exec/ExecuteBuild.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/exec/ExecuteBuild.java
index 093c5ef..bf7deb3 100644
--- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/exec/ExecuteBuild.java
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/exec/ExecuteBuild.java
@@ -20,7 +20,7 @@ import org.gradle.api.logging.Logging;
import org.gradle.initialization.GradleLauncherFactory;
import org.gradle.launcher.daemon.logging.DaemonMessages;
import org.gradle.launcher.daemon.protocol.Build;
-import org.gradle.launcher.exec.InProcessGradleLauncherActionExecuter;
+import org.gradle.launcher.exec.InProcessBuildActionExecuter;
import org.gradle.launcher.exec.ReportedException;
/**
@@ -40,7 +40,7 @@ public class ExecuteBuild extends BuildCommandOnly {
protected void doBuild(DaemonCommandExecution execution, Build build) {
LOGGER.info("Executing build with daemon context: {}", execution.getDaemonContext());
- InProcessGradleLauncherActionExecuter executer = new InProcessGradleLauncherActionExecuter(launcherFactory);
+ InProcessBuildActionExecuter executer = new InProcessBuildActionExecuter(launcherFactory);
try {
execution.setResult(executer.execute(build.getAction(), build.getParameters()));
} catch (ReportedException e) {
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/exec/ForwardClientInput.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/exec/ForwardClientInput.java
index 5dafad2..f36d81a 100644
--- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/exec/ForwardClientInput.java
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/exec/ForwardClientInput.java
@@ -15,6 +15,7 @@
*/
package org.gradle.launcher.daemon.server.exec;
+import org.apache.commons.io.IOUtils;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
import org.gradle.internal.UncheckedException;
@@ -73,7 +74,8 @@ public class ForwardClientInput implements DaemonCommandAction {
});
} finally {
execution.getConnection().onStdin(null);
- replacementStdin.close();
+ IOUtils.closeQuietly(replacementStdin);
+ IOUtils.closeQuietly(inputSource);
}
} catch (Exception e) {
throw UncheckedException.throwAsUncheckedException(e);
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/exec/BuildActionExecuter.java b/subprojects/launcher/src/main/java/org/gradle/launcher/exec/BuildActionExecuter.java
new file mode 100644
index 0000000..d6cb1f7
--- /dev/null
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/exec/BuildActionExecuter.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.launcher.exec;
+
+import org.gradle.initialization.BuildAction;
+
+public interface BuildActionExecuter<P> {
+ /**
+ * Executes the given action, and returns the result.
+ *
+ * @param action The action
+ * @param <T> The result type
+ * @return The result.
+ */
+ <T> T execute(BuildAction<T> action, P actionParameters);
+}
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/exec/GradleLauncherActionExecuter.java b/subprojects/launcher/src/main/java/org/gradle/launcher/exec/GradleLauncherActionExecuter.java
deleted file mode 100644
index 99ade21..0000000
--- a/subprojects/launcher/src/main/java/org/gradle/launcher/exec/GradleLauncherActionExecuter.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.launcher.exec;
-
-import org.gradle.initialization.GradleLauncherAction;
-
-public interface GradleLauncherActionExecuter<P> {
- /**
- * Executes the given action, and returns the result. The given action may also implement {@link InitializationAware <T>}.
- *
- * @param action The action
- * @param <T> The result type
- * @return The result.
- */
- <T> T execute(GradleLauncherAction<T> action, P actionParameters);
-}
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/exec/InProcessBuildActionExecuter.java b/subprojects/launcher/src/main/java/org/gradle/launcher/exec/InProcessBuildActionExecuter.java
new file mode 100644
index 0000000..4e07adf
--- /dev/null
+++ b/subprojects/launcher/src/main/java/org/gradle/launcher/exec/InProcessBuildActionExecuter.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.launcher.exec;
+
+import org.gradle.BuildResult;
+import org.gradle.GradleLauncher;
+import org.gradle.StartParameter;
+import org.gradle.initialization.BuildController;
+import org.gradle.initialization.BuildAction;
+import org.gradle.initialization.GradleLauncherFactory;
+
+public class InProcessBuildActionExecuter implements BuildActionExecuter<BuildActionParameters> {
+ private final GradleLauncherFactory gradleLauncherFactory;
+
+ public InProcessBuildActionExecuter(GradleLauncherFactory gradleLauncherFactory) {
+ this.gradleLauncherFactory = gradleLauncherFactory;
+ }
+
+ public <T> T execute(BuildAction<T> action, BuildActionParameters actionParameters) {
+ DefaultBuildController buildController = new DefaultBuildController(gradleLauncherFactory, actionParameters);
+ return action.run(buildController);
+ }
+
+ private static class DefaultBuildController implements BuildController {
+ private final BuildActionParameters actionParameters;
+ private final GradleLauncherFactory gradleLauncherFactory;
+ private GradleLauncher gradleLauncher;
+ private StartParameter startParameter = new StartParameter();
+
+ private DefaultBuildController(GradleLauncherFactory gradleLauncherFactory, BuildActionParameters actionParameters) {
+ this.gradleLauncherFactory = gradleLauncherFactory;
+ this.actionParameters = actionParameters;
+ }
+
+ public void setStartParameter(StartParameter startParameter) {
+ if (gradleLauncher != null) {
+ throw new IllegalStateException("Cannot change start parameter after launcher has been created.");
+ }
+ this.startParameter = startParameter;
+ }
+
+ public GradleLauncher getLauncher() {
+ if (gradleLauncher == null) {
+ gradleLauncher = gradleLauncherFactory.newInstance(startParameter, actionParameters.getBuildRequestMetaData());
+ }
+ return gradleLauncher;
+ }
+
+ public void run() {
+ check(getLauncher().run());
+ }
+
+ public void configure() {
+ check(getLauncher().getBuildAnalysis());
+ }
+
+ private void check(BuildResult buildResult) {
+ if (buildResult.getFailure() != null) {
+ throw new ReportedException(buildResult.getFailure());
+ }
+ }
+ }
+}
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/exec/InProcessGradleLauncherActionExecuter.java b/subprojects/launcher/src/main/java/org/gradle/launcher/exec/InProcessGradleLauncherActionExecuter.java
deleted file mode 100644
index e9feb3e..0000000
--- a/subprojects/launcher/src/main/java/org/gradle/launcher/exec/InProcessGradleLauncherActionExecuter.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.launcher.exec;
-
-import org.gradle.BuildResult;
-import org.gradle.GradleLauncher;
-import org.gradle.StartParameter;
-import org.gradle.initialization.GradleLauncherAction;
-import org.gradle.initialization.GradleLauncherFactory;
-
-public class InProcessGradleLauncherActionExecuter implements GradleLauncherActionExecuter<BuildActionParameters> {
- private final GradleLauncherFactory gradleLauncherFactory;
-
- public InProcessGradleLauncherActionExecuter(GradleLauncherFactory gradleLauncherFactory) {
- this.gradleLauncherFactory = gradleLauncherFactory;
- }
-
- public <T> T execute(GradleLauncherAction<T> action, BuildActionParameters actionParameters) {
- StartParameter startParameter = new StartParameter();
- if (action instanceof InitializationAware) {
- InitializationAware initializationAware = (InitializationAware) action;
- startParameter = initializationAware.configureStartParameter();
- }
- GradleLauncher gradleLauncher = gradleLauncherFactory.newInstance(startParameter, actionParameters.getBuildRequestMetaData());
- BuildResult buildResult = action.run(gradleLauncher);
- Throwable failure = buildResult.getFailure();
- if (failure != null) {
- throw new ReportedException(failure);
- }
- return action.getResult();
- }
-}
diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/exec/InitializationAware.java b/subprojects/launcher/src/main/java/org/gradle/launcher/exec/InitializationAware.java
deleted file mode 100644
index 87fdb09..0000000
--- a/subprojects/launcher/src/main/java/org/gradle/launcher/exec/InitializationAware.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.launcher.exec;
-
-import org.gradle.StartParameter;
-
-public interface InitializationAware {
- StartParameter configureStartParameter();
-}
diff --git a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/BuildActionResult.java b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/BuildActionResult.java
new file mode 100644
index 0000000..3206cb5
--- /dev/null
+++ b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/BuildActionResult.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.provider;
+
+import org.gradle.api.Nullable;
+
+import java.io.Serializable;
+
+public class BuildActionResult implements Serializable {
+ @Nullable
+ final SerializedPayload result;
+ @Nullable
+ final SerializedPayload failure;
+
+ public BuildActionResult(SerializedPayload result, SerializedPayload failure) {
+ this.result = result;
+ this.failure = failure;
+ }
+}
diff --git a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/BuildModelAction.java b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/BuildModelAction.java
new file mode 100644
index 0000000..1635719
--- /dev/null
+++ b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/BuildModelAction.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.provider;
+
+import org.gradle.api.Action;
+import org.gradle.api.internal.GradleInternal;
+import org.gradle.api.internal.project.ProjectInternal;
+import org.gradle.initialization.*;
+import org.gradle.tooling.internal.protocol.InternalUnsupportedModelException;
+import org.gradle.tooling.provider.model.ToolingModelBuilder;
+import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry;
+import org.gradle.tooling.provider.model.UnknownModelException;
+
+import java.io.Serializable;
+import java.util.concurrent.atomic.AtomicReference;
+
+public class BuildModelAction implements BuildAction<BuildActionResult>, Serializable {
+ private final boolean runTasks;
+ private final String modelName;
+
+ public BuildModelAction(String modelName, boolean runTasks) {
+ this.modelName = modelName;
+ this.runTasks = runTasks;
+ }
+
+ public BuildActionResult run(BuildController buildController) {
+ DefaultGradleLauncher launcher = (DefaultGradleLauncher) buildController.getLauncher();
+ final PayloadSerializer payloadSerializer = launcher.getGradle().getServices().get(PayloadSerializer.class);
+
+ // The following is all very awkward because the contract for BuildController is still just a
+ // rough wrapper around GradleLauncher, which means we can only get at the model and various
+ // services by using listeners.
+
+ final AtomicReference<Object> model = new AtomicReference<Object>();
+ final AtomicReference<RuntimeException> failure = new AtomicReference<RuntimeException>();
+ final Action<GradleInternal> action = new Action<GradleInternal>() {
+ public void execute(GradleInternal gradle) {
+ ToolingModelBuilderRegistry builderRegistry = getToolingModelBuilderRegistry(gradle);
+ ToolingModelBuilder builder;
+ try {
+ builder = builderRegistry.getBuilder(modelName);
+ } catch (UnknownModelException e) {
+ failure.set((InternalUnsupportedModelException) (new InternalUnsupportedModelException().initCause(e)));
+ return;
+ }
+ Object result = builder.buildAll(modelName, gradle.getDefaultProject());
+ model.set(result);
+ }
+ };
+
+ if (runTasks) {
+ launcher.addListener(new TasksCompletionListener() {
+ public void onTasksFinished(GradleInternal gradle) {
+ action.execute(gradle);
+ }
+ });
+ buildController.run();
+ } else {
+ launcher.addListener(new ModelConfigurationListener() {
+ public void onConfigure(GradleInternal gradle) {
+ // Currently need to force everything to be configured
+ ensureAllProjectsEvaluated(gradle);
+ action.execute(gradle);
+ }
+ });
+ buildController.configure();
+ }
+
+ if (failure.get() != null) {
+ throw failure.get();
+ }
+ return new BuildActionResult(payloadSerializer.serialize(model.get()), null);
+ }
+
+ private ToolingModelBuilderRegistry getToolingModelBuilderRegistry(GradleInternal gradle) {
+ return gradle.getDefaultProject().getServices().get(ToolingModelBuilderRegistry.class);
+ }
+
+ private void ensureAllProjectsEvaluated(GradleInternal gradle) {
+ gradle.getRootProject().allprojects((Action) new Action<ProjectInternal>() {
+ public void execute(ProjectInternal projectInternal) {
+ projectInternal.evaluate();
+ }
+ });
+ }
+}
diff --git a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/ClassLoaderDetails.java b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/ClassLoaderDetails.java
new file mode 100644
index 0000000..2976587
--- /dev/null
+++ b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/ClassLoaderDetails.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.provider;
+
+import org.gradle.internal.classloader.ClassLoaderSpec;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+public class ClassLoaderDetails implements Serializable {
+ // TODO:ADAM - using a UUID means we create a ClassLoader hierarchy for each daemon process we talk to. Instead, use the spec to decide whether to reuse a ClassLoader
+ final UUID uuid;
+ final ClassLoaderSpec spec;
+ final List<ClassLoaderDetails> parents = new ArrayList<ClassLoaderDetails>();
+
+ public ClassLoaderDetails(UUID uuid, ClassLoaderSpec spec) {
+ this.uuid = uuid;
+ this.spec = spec;
+ }
+}
diff --git a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/ClasspathInferer.java b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/ClasspathInferer.java
new file mode 100644
index 0000000..cd2c1f6
--- /dev/null
+++ b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/ClasspathInferer.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.provider;
+
+import com.google.common.collect.MapMaker;
+import net.jcip.annotations.ThreadSafe;
+import org.gradle.api.GradleException;
+import org.gradle.internal.classloader.ClasspathUtil;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.Type;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.*;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+ at ThreadSafe
+public class ClasspathInferer {
+ private static final Logger LOGGER = LoggerFactory.getLogger(ClasspathInferer.class);
+ private final Lock lock = new ReentrantLock();
+ private final Map<Class<?>, Collection<URL>> classPathCache;
+
+ public ClasspathInferer() {
+ this.classPathCache = new MapMaker().weakKeys().makeMap();
+ }
+
+ public void getClassPathFor(Class<?> targetClass, Collection<URL> dest) {
+ lock.lock();
+ try {
+ Collection<URL> classPath = classPathCache.get(targetClass);
+ if (classPath == null) {
+ Set<Class<?>> visited = new HashSet<Class<?>>();
+ classPath = new LinkedHashSet<URL>();
+ find(targetClass, visited, classPath);
+ classPathCache.put(targetClass, classPath);
+ }
+ dest.addAll(classPath);
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Locates the classpath required by the given target class. Traverses the dependency graph of classes used by the specified class and collects the result in the given collection.
+ */
+ private void find(Class<?> target, Collection<Class<?>> visited, Collection<URL> dest) {
+ ClassLoader targetClassLoader = target.getClassLoader();
+ if (targetClassLoader == null) {
+ // A system class, skip it
+ return;
+ }
+ if (!visited.add(target)) {
+ // Already seen this class, skip it
+ return;
+ }
+
+ String resourceName = target.getName().replace(".", "/") + ".class";
+ URL resource = targetClassLoader.getResource(resourceName);
+ try {
+ if (resource == null) {
+ LOGGER.warn("Could not determine classpath for {}", target);
+ return;
+ }
+
+ File classPathRoot = ClasspathUtil.getClasspathForResource(resource, resourceName);
+ dest.add(classPathRoot.toURI().toURL());
+
+ // To determine the dependencies of the class, load up the byte code and look for CONSTANT_Class entries in the constant pool
+
+ ClassReader reader;
+ InputStream inputStream = resource.openStream();
+ try {
+ reader = new ClassReader(inputStream);
+ } finally {
+ inputStream.close();
+ }
+
+ char[] charBuffer = new char[reader.getMaxStringLength()];
+ for (int i = 1; i < reader.getItemCount(); i++) {
+ int itemOffset = reader.getItem(i);
+ if (itemOffset > 0 && reader.readByte(itemOffset - 1) == 7) {
+ // A CONSTANT_Class entry, read the class descriptor
+ String classDescriptor = reader.readUTF8(itemOffset, charBuffer);
+ Type type = Type.getObjectType(classDescriptor);
+ while (type.getSort() == Type.ARRAY) {
+ type = type.getElementType();
+ }
+ if (type.getSort() != Type.OBJECT) {
+ // A primitive type
+ continue;
+ }
+ String className = type.getClassName();
+ if (className.equals(target.getName())) {
+ // A reference to this class
+ continue;
+ }
+
+ Class<?> cl;
+ try {
+ cl = Class.forName(className, false, targetClassLoader);
+ } catch (ClassNotFoundException e) {
+ // This is fine, just ignore it
+ LOGGER.warn("Could not determine classpath for {}", target);
+ continue;
+ }
+ find(cl, visited, dest);
+ }
+ }
+ } catch (Exception e) {
+ throw new GradleException(String.format("Could not determine the class-path for %s.", target), e);
+ }
+ }
+}
diff --git a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/ClientProvidedBuildAction.java b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/ClientProvidedBuildAction.java
new file mode 100644
index 0000000..004925e
--- /dev/null
+++ b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/ClientProvidedBuildAction.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.provider;
+
+import org.gradle.api.Action;
+import org.gradle.api.internal.GradleInternal;
+import org.gradle.api.internal.project.ProjectInternal;
+import org.gradle.initialization.BuildAction;
+import org.gradle.initialization.BuildController;
+import org.gradle.initialization.DefaultGradleLauncher;
+import org.gradle.initialization.ModelConfigurationListener;
+import org.gradle.tooling.internal.protocol.InternalBuildAction;
+import org.gradle.tooling.internal.protocol.InternalBuildActionFailureException;
+import org.gradle.tooling.internal.protocol.InternalBuildController;
+
+import java.io.Serializable;
+import java.util.concurrent.atomic.AtomicReference;
+
+class ClientProvidedBuildAction implements BuildAction<BuildActionResult>, Serializable {
+ private final SerializedPayload action;
+
+ public ClientProvidedBuildAction(SerializedPayload action) {
+ this.action = action;
+ }
+
+ public BuildActionResult run(final BuildController buildController) {
+ final DefaultGradleLauncher gradleLauncher = (DefaultGradleLauncher) buildController.getLauncher();
+ final PayloadSerializer payloadSerializer = gradleLauncher.getGradle().getServices().get(PayloadSerializer.class);
+ final InternalBuildAction<?> action = (InternalBuildAction<?>) payloadSerializer.deserialize(this.action);
+
+ // The following is all very awkward because the contract for BuildController is still just a
+ // rough wrapper around GradleLauncher, which means we can only get at the model and various
+ // services by using listeners.
+
+ final AtomicReference<Object> result = new AtomicReference<Object>();
+ final AtomicReference<RuntimeException> failure = new AtomicReference<RuntimeException>();
+
+ gradleLauncher.addListener(new ModelConfigurationListener() {
+ public void onConfigure(final GradleInternal gradle) {
+ // Currently need to force everything to be configured
+ ensureAllProjectsEvaluated(gradle);
+ InternalBuildController internalBuildController = new DefaultBuildController(gradle);
+ Object model = null;
+ try {
+ model = action.execute(internalBuildController);
+ } catch (RuntimeException e) {
+ failure.set(new InternalBuildActionFailureException(e));
+ }
+ result.set(model);
+ }
+ });
+ buildController.configure();
+
+ if (failure.get() != null) {
+ return new BuildActionResult(null, payloadSerializer.serialize(failure.get()));
+ }
+ return new BuildActionResult(payloadSerializer.serialize(result.get()), null);
+ }
+
+ private void ensureAllProjectsEvaluated(GradleInternal gradle) {
+ gradle.getRootProject().allprojects((Action) new Action<ProjectInternal>() {
+ public void execute(ProjectInternal projectInternal) {
+ projectInternal.evaluate();
+ }
+ });
+ }
+}
diff --git a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/ClientSidePayloadClassLoaderRegistry.java b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/ClientSidePayloadClassLoaderRegistry.java
new file mode 100644
index 0000000..643c916
--- /dev/null
+++ b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/ClientSidePayloadClassLoaderRegistry.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.provider;
+
+import net.jcip.annotations.ThreadSafe;
+import org.gradle.internal.classloader.MutableURLClassLoader;
+
+import java.lang.ref.Reference;
+import java.lang.ref.WeakReference;
+import java.net.URL;
+import java.util.*;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+ at ThreadSafe
+public class ClientSidePayloadClassLoaderRegistry implements PayloadClassLoaderRegistry {
+ private static final short CLIENT_CLASS_LOADER_ID = 1;
+ private final PayloadClassLoaderRegistry delegate;
+ private final Lock lock = new ReentrantLock();
+ private final ClasspathInferer classpathInferer;
+ private final Map<UUID, LocalClassLoader> classLoaders = new LinkedHashMap<UUID, LocalClassLoader>();
+
+ public ClientSidePayloadClassLoaderRegistry(PayloadClassLoaderRegistry delegate, ClasspathInferer classpathInferer) {
+ this.delegate = delegate;
+ this.classpathInferer = classpathInferer;
+ }
+
+ public SerializeMap newSerializeSession() {
+ final Set<ClassLoader> candidates = new LinkedHashSet<ClassLoader>();
+ final Set<URL> classPath = new LinkedHashSet<URL>();
+
+ return new SerializeMap() {
+ public short visitClass(Class<?> target) {
+ classpathInferer.getClassPathFor(target, classPath);
+ candidates.add(target.getClassLoader());
+ return CLIENT_CLASS_LOADER_ID;
+ }
+
+ public Map<Short, ClassLoaderDetails> getClassLoaders() {
+ lock.lock();
+ UUID uuid;
+ try {
+ uuid = getUuid(candidates);
+ } finally {
+ lock.unlock();
+ }
+ return Collections.singletonMap(CLIENT_CLASS_LOADER_ID, new ClassLoaderDetails(uuid, new MutableURLClassLoader.Spec(new ArrayList<URL>(classPath))));
+ }
+ };
+ }
+
+ public DeserializeMap newDeserializeSession() {
+ final DeserializeMap deserializeMap = delegate.newDeserializeSession();
+ return new DeserializeMap() {
+ public Class<?> resolveClass(ClassLoaderDetails classLoaderDetails, String className) throws ClassNotFoundException {
+ Set<ClassLoader> candidates;
+ lock.lock();
+ try {
+ candidates = getClassLoaders(classLoaderDetails.uuid);
+ } finally {
+ lock.unlock();
+ }
+ if (candidates != null) {
+ // TODO:ADAM - This isn't quite right
+ for (ClassLoader candidate : candidates) {
+ try {
+ return candidate.loadClass(className);
+ } catch (ClassNotFoundException e) {
+ // Ignore
+ }
+ }
+ throw new UnsupportedOperationException("Unexpected class received in response.");
+ }
+ return deserializeMap.resolveClass(classLoaderDetails, className);
+ }
+ };
+ }
+
+ private Set<ClassLoader> getClassLoaders(UUID uuid) {
+ LocalClassLoader localClassLoader = classLoaders.get(uuid);
+ if (localClassLoader == null) {
+ return null;
+ }
+ Set<ClassLoader> candidates = new LinkedHashSet<ClassLoader>();
+ for (Reference<ClassLoader> reference : localClassLoader.classLoaders) {
+ ClassLoader classLoader = reference.get();
+ if (classLoader != null) {
+ candidates.add(classLoader);
+ }
+ }
+ return candidates;
+ }
+
+ private UUID getUuid(Set<ClassLoader> candidates) {
+ for (LocalClassLoader localClassLoader : new ArrayList<LocalClassLoader>(classLoaders.values())) {
+ Set<ClassLoader> localCandidates = new LinkedHashSet<ClassLoader>();
+ for (Reference<ClassLoader> reference : localClassLoader.classLoaders) {
+ ClassLoader cl = reference.get();
+ if (cl != null) {
+ localCandidates.add(cl);
+ }
+ }
+ if (localCandidates.isEmpty()) {
+ classLoaders.remove(localClassLoader.uuid);
+ continue;
+ }
+ if (localCandidates.equals(candidates)) {
+ return localClassLoader.uuid;
+ }
+ }
+
+ LocalClassLoader details = new LocalClassLoader(UUID.randomUUID());
+ for (ClassLoader candidate : candidates) {
+ details.classLoaders.add(new WeakReference<ClassLoader>(candidate));
+ }
+ classLoaders.put(details.uuid, details);
+ return details.uuid;
+ }
+
+ private static class LocalClassLoader {
+ private final Set<Reference<ClassLoader>> classLoaders = new LinkedHashSet<Reference<ClassLoader>>();
+ private final UUID uuid;
+
+ private LocalClassLoader(UUID uuid) {
+ this.uuid = uuid;
+ }
+ }
+}
diff --git a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/ConfiguringBuildAction.java b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/ConfiguringBuildAction.java
index d1537d6..ba7c97b 100644
--- a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/ConfiguringBuildAction.java
+++ b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/ConfiguringBuildAction.java
@@ -15,41 +15,40 @@
*/
package org.gradle.tooling.internal.provider;
-import org.gradle.BuildResult;
-import org.gradle.GradleLauncher;
import org.gradle.StartParameter;
import org.gradle.api.logging.LogLevel;
import org.gradle.cli.CommandLineArgumentException;
+import org.gradle.initialization.BuildAction;
+import org.gradle.initialization.BuildController;
import org.gradle.initialization.DefaultCommandLineConverter;
-import org.gradle.initialization.GradleLauncherAction;
-import org.gradle.launcher.daemon.configuration.GradleProperties;
-import org.gradle.launcher.exec.InitializationAware;
-import org.gradle.logging.ShowStacktrace;
+import org.gradle.launcher.cli.converter.PropertiesToStartParameterConverter;
import org.gradle.tooling.internal.protocol.exceptions.InternalUnsupportedBuildArgumentException;
import org.gradle.tooling.internal.provider.connection.ProviderOperationParameters;
import java.io.File;
import java.io.Serializable;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
-class ConfiguringBuildAction<T> implements GradleLauncherAction<T>, InitializationAware, Serializable {
+class ConfiguringBuildAction<T> implements BuildAction<T>, Serializable {
private LogLevel buildLogLevel;
private List<String> arguments;
private List<String> tasks;
- private GradleLauncherAction<T> action;
+ private BuildAction<? extends T> action;
private File projectDirectory;
private File gradleUserHomeDir;
private Boolean searchUpwards;
+ private Map<String, String> properties = new HashMap<String, String>();
// Important that this is constructed on the client so that it has the right gradleHomeDir internally
private final StartParameter startParameterTemplate = new StartParameter();
- private boolean configureOnDemand;
public ConfiguringBuildAction() {}
- public ConfiguringBuildAction(ProviderOperationParameters parameters, GradleLauncherAction<T> action, GradleProperties gradleProperties) {
- this.configureOnDemand = gradleProperties.isConfigureOnDemand();
+ public ConfiguringBuildAction(ProviderOperationParameters parameters, BuildAction<? extends T> action, Map<String, String> properties) {
+ this.properties.putAll(properties);
this.gradleUserHomeDir = parameters.getGradleUserHomeDir();
this.projectDirectory = parameters.getProjectDir();
this.searchUpwards = parameters.isSearchUpwards();
@@ -59,21 +58,23 @@ class ConfiguringBuildAction<T> implements GradleLauncherAction<T>, Initializati
this.action = action;
}
- public StartParameter configureStartParameter() {
+ StartParameter configureStartParameter() {
+ return configureStartParameter(new PropertiesToStartParameterConverter());
+ }
+
+ StartParameter configureStartParameter(PropertiesToStartParameterConverter propertiesToStartParameterConverter) {
StartParameter startParameter = startParameterTemplate.newInstance();
+
startParameter.setProjectDir(projectDirectory);
if (gradleUserHomeDir != null) {
startParameter.setGradleUserHomeDir(gradleUserHomeDir);
}
- if (searchUpwards != null) {
- startParameter.setSearchUpwards(searchUpwards);
- }
if (tasks != null) {
startParameter.setTaskNames(tasks);
}
- startParameter.setConfigureOnDemand(configureOnDemand);
+ propertiesToStartParameterConverter.convert(properties, startParameter);
if (arguments != null) {
DefaultCommandLineConverter converter = new DefaultCommandLineConverter();
@@ -91,19 +92,19 @@ class ConfiguringBuildAction<T> implements GradleLauncherAction<T>, Initializati
}
}
+ if (searchUpwards != null) {
+ startParameter.setSearchUpwards(searchUpwards);
+ }
+
if (buildLogLevel != null) {
startParameter.setLogLevel(buildLogLevel);
}
- startParameter.setShowStacktrace(ShowStacktrace.ALWAYS);
return startParameter;
}
- public BuildResult run(GradleLauncher launcher) {
- return action.run(launcher);
- }
-
- public T getResult() {
- return action.getResult();
+ public T run(BuildController buildController) {
+ buildController.setStartParameter(configureStartParameter());
+ return action.run(buildController);
}
}
diff --git a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/ConnectionScopeServices.java b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/ConnectionScopeServices.java
new file mode 100644
index 0000000..f02391e
--- /dev/null
+++ b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/ConnectionScopeServices.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.provider;
+
+import org.gradle.initialization.GradleLauncherFactory;
+import org.gradle.internal.service.DefaultServiceRegistry;
+import org.gradle.internal.service.scopes.GlobalScopeServices;
+import org.gradle.logging.LoggingServiceRegistry;
+import org.gradle.tooling.internal.adapter.ProtocolToModelAdapter;
+
+public class ConnectionScopeServices extends DefaultServiceRegistry {
+ public ConnectionScopeServices() {
+ LoggingServiceRegistry loggingServices = LoggingServiceRegistry.newEmbeddableLogging();
+ add(LoggingServiceRegistry.class, loggingServices);
+ add(new GlobalScopeServices(loggingServices));
+ }
+
+ protected ProviderConnection createProviderConnection() {
+ return new ProviderConnection(
+ get(LoggingServiceRegistry.class),
+ get(GradleLauncherFactory.class),
+ new PayloadSerializer(
+ new ClientSidePayloadClassLoaderRegistry(
+ new DefaultPayloadClassLoaderRegistry(
+ new ModelClassLoaderFactory()),
+ new ClasspathInferer()))
+ );
+ }
+
+ protected ProtocolToModelAdapter createProtocolToModelAdapter() {
+ return new ProtocolToModelAdapter();
+ }
+}
diff --git a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/DaemonBuildActionExecuter.java b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/DaemonBuildActionExecuter.java
new file mode 100644
index 0000000..5c0086b
--- /dev/null
+++ b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/DaemonBuildActionExecuter.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.provider;
+
+import org.gradle.configuration.GradleLauncherMetaData;
+import org.gradle.initialization.BuildAction;
+import org.gradle.internal.SystemProperties;
+import org.gradle.launcher.daemon.configuration.DaemonParameters;
+import org.gradle.launcher.exec.BuildActionExecuter;
+import org.gradle.launcher.exec.BuildActionParameters;
+import org.gradle.launcher.exec.DefaultBuildActionParameters;
+import org.gradle.launcher.exec.ReportedException;
+import org.gradle.tooling.internal.protocol.BuildExceptionVersion1;
+import org.gradle.tooling.internal.provider.connection.ProviderOperationParameters;
+
+public class DaemonBuildActionExecuter implements BuildActionExecuter<ProviderOperationParameters> {
+ private final BuildActionExecuter<BuildActionParameters> executer;
+ private final DaemonParameters parameters;
+
+ public DaemonBuildActionExecuter(BuildActionExecuter<BuildActionParameters> executer, DaemonParameters parameters) {
+ this.executer = executer;
+ this.parameters = parameters;
+ }
+
+ public <T> T execute(BuildAction<T> action, ProviderOperationParameters actionParameters) {
+ BuildActionParameters parameters = new DefaultBuildActionParameters(new GradleLauncherMetaData(), actionParameters.getStartTime(),
+ this.parameters.getEffectiveSystemProperties(), System.getenv(), SystemProperties.getCurrentDir(), actionParameters.getBuildLogLevel());
+ try {
+ return executer.execute(action, parameters);
+ } catch (ReportedException e) {
+ throw new BuildExceptionVersion1(e.getCause());
+ }
+ }
+}
diff --git a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/DaemonGradleLauncherActionExecuter.java b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/DaemonGradleLauncherActionExecuter.java
deleted file mode 100644
index d9cdc86..0000000
--- a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/DaemonGradleLauncherActionExecuter.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.provider;
-
-import org.gradle.configuration.GradleLauncherMetaData;
-import org.gradle.initialization.GradleLauncherAction;
-import org.gradle.internal.SystemProperties;
-import org.gradle.launcher.daemon.configuration.DaemonParameters;
-import org.gradle.launcher.exec.BuildActionParameters;
-import org.gradle.launcher.exec.DefaultBuildActionParameters;
-import org.gradle.launcher.exec.GradleLauncherActionExecuter;
-import org.gradle.launcher.exec.ReportedException;
-import org.gradle.tooling.internal.protocol.BuildExceptionVersion1;
-import org.gradle.tooling.internal.provider.connection.ProviderOperationParameters;
-
-public class DaemonGradleLauncherActionExecuter implements GradleLauncherActionExecuter<ProviderOperationParameters> {
- private final GradleLauncherActionExecuter<BuildActionParameters> executer;
- private final DaemonParameters parameters;
-
- public DaemonGradleLauncherActionExecuter(GradleLauncherActionExecuter<BuildActionParameters> executer, DaemonParameters parameters) {
- this.executer = executer;
- this.parameters = parameters;
- }
-
- public <T> T execute(GradleLauncherAction<T> action, ProviderOperationParameters actionParameters) {
- BuildActionParameters parameters = new DefaultBuildActionParameters(new GradleLauncherMetaData(), actionParameters.getStartTime(),
- this.parameters.getEffectiveSystemProperties(), System.getenv(), SystemProperties.getCurrentDir(), actionParameters.getBuildLogLevel());
- try {
- return executer.execute(action, parameters);
- } catch (ReportedException e) {
- throw new BuildExceptionVersion1(e.getCause());
- }
- }
-}
diff --git a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/DefaultBuildController.java b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/DefaultBuildController.java
new file mode 100644
index 0000000..170bfee
--- /dev/null
+++ b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/DefaultBuildController.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.provider;
+
+import org.gradle.api.internal.GradleInternal;
+import org.gradle.api.internal.project.ProjectInternal;
+import org.gradle.tooling.internal.gradle.GradleProjectIdentity;
+import org.gradle.tooling.internal.protocol.*;
+import org.gradle.tooling.internal.provider.connection.ProviderBuildResult;
+import org.gradle.tooling.provider.model.ToolingModelBuilder;
+import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry;
+import org.gradle.tooling.provider.model.UnknownModelException;
+
+class DefaultBuildController implements InternalBuildController {
+ private final GradleInternal gradle;
+
+ public DefaultBuildController(GradleInternal gradle) {
+ this.gradle = gradle;
+ }
+
+ public BuildResult<?> getBuildModel() throws BuildExceptionVersion1 {
+ return new ProviderBuildResult<Object>(gradle);
+ }
+
+ public BuildResult<?> getModel(Object target, ModelIdentifier modelIdentifier) throws BuildExceptionVersion1, InternalUnsupportedModelException {
+ ToolingModelBuilderRegistry modelBuilderRegistry;
+ ProjectInternal project;
+ if (target == null) {
+ project = gradle.getDefaultProject();
+ } else if (target instanceof GradleProjectIdentity) {
+ GradleProjectIdentity gradleProject = (GradleProjectIdentity) target;
+ project = gradle.getRootProject().project(gradleProject.getPath());
+ } else {
+ throw new IllegalArgumentException("Don't know how to build models for " + target);
+ }
+ modelBuilderRegistry = project.getServices().get(ToolingModelBuilderRegistry.class);
+
+ ToolingModelBuilder builder;
+ try {
+ builder = modelBuilderRegistry.getBuilder(modelIdentifier.getName());
+ } catch (UnknownModelException e) {
+ throw (InternalUnsupportedModelException) (new InternalUnsupportedModelException()).initCause(e);
+ }
+ Object model = builder.buildAll(modelIdentifier.getName(), project);
+ return new ProviderBuildResult<Object>(model);
+ }
+}
diff --git a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/DefaultConnection.java b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/DefaultConnection.java
index 918f141..bdef5e5 100644
--- a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/DefaultConnection.java
+++ b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/DefaultConnection.java
@@ -15,173 +15,143 @@
*/
package org.gradle.tooling.internal.provider;
-import org.gradle.StartParameter;
-import org.gradle.api.logging.LogLevel;
-import org.gradle.initialization.GradleLauncherAction;
-import org.gradle.internal.Factory;
-import org.gradle.launcher.daemon.client.DaemonClient;
-import org.gradle.launcher.daemon.client.DaemonClientServices;
-import org.gradle.launcher.daemon.configuration.DaemonParameters;
-import org.gradle.launcher.daemon.configuration.GradleProperties;
-import org.gradle.launcher.daemon.configuration.GradlePropertiesConfigurer;
-import org.gradle.launcher.exec.BuildActionParameters;
-import org.gradle.launcher.exec.GradleLauncherActionExecuter;
-import org.gradle.logging.LoggingManagerInternal;
-import org.gradle.logging.LoggingServiceRegistry;
-import org.gradle.logging.internal.OutputEventRenderer;
-import org.gradle.process.internal.streams.SafeStreams;
-import org.gradle.tooling.internal.build.DefaultBuildEnvironment;
-import org.gradle.tooling.internal.consumer.protocoladapter.ProtocolToModelAdapter;
+import org.gradle.tooling.internal.adapter.ProtocolToModelAdapter;
+import org.gradle.tooling.internal.consumer.versioning.ModelMapping;
import org.gradle.tooling.internal.protocol.*;
+import org.gradle.tooling.internal.protocol.exceptions.InternalUnsupportedBuildArgumentException;
import org.gradle.tooling.internal.provider.connection.*;
-import org.gradle.util.GUtil;
import org.gradle.util.GradleVersion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.File;
-import java.util.List;
-
-public class DefaultConnection implements InternalConnection, BuildActionRunner, ConfigurableConnection {
+public class DefaultConnection implements InternalConnection, BuildActionRunner, ConfigurableConnection, ModelBuilder, InternalBuildActionExecutor {
private static final Logger LOGGER = LoggerFactory.getLogger(DefaultConnection.class);
- private final EmbeddedExecuterSupport embeddedExecuterSupport;
- private final ProtocolToModelAdapter adapter = new ProtocolToModelAdapter();
+ private final ProtocolToModelAdapter adapter;
+ private final ConnectionScopeServices services;
+ private final ProviderConnection connection;
+ /**
+ * This is used by consumers 1.0-milestone-3 and later
+ */
public DefaultConnection() {
- LOGGER.debug("Provider implementation created.");
- //embedded use of the tooling api is not supported publicly so we don't care about its thread safety
- //we can still keep this state:
- embeddedExecuterSupport = new EmbeddedExecuterSupport();
- LOGGER.debug("Embedded executer support created.");
+ LOGGER.debug("Tooling API provider {} created.", GradleVersion.current().getVersion());
+ services = new ConnectionScopeServices();
+ adapter = services.get(ProtocolToModelAdapter.class);
+ connection = services.get(ProviderConnection.class);
}
+ /**
+ * This is used by consumers 1.2-rc-1 and later.
+ */
public void configure(ConnectionParameters parameters) {
- ProviderConnectionParameters providerConnectionParameters = new ProtocolToModelAdapter().adapt(ProviderConnectionParameters.class, parameters);
- configureLogging(providerConnectionParameters.getVerboseLogging());
+ ProviderConnectionParameters providerConnectionParameters = adapter.adapt(ProviderConnectionParameters.class, parameters);
+ connection.configure(providerConnectionParameters);
}
- public void configureLogging(boolean verboseLogging) {
- LogLevel providerLogLevel = verboseLogging? LogLevel.DEBUG : LogLevel.INFO;
- LOGGER.debug("Configuring logging to level: {}", providerLogLevel);
- LoggingManagerInternal loggingManager = embeddedExecuterSupport.getLoggingServices().newInstance(LoggingManagerInternal.class);
- loggingManager.setLevel(providerLogLevel);
- loggingManager.start();
+ /**
+ * This method was used by consumers 1.0-rc-1 through to 1.1. Later consumers use {@link #configure(org.gradle.tooling.internal.protocol.ConnectionParameters)} instead.
+ */
+ public void configureLogging(final boolean verboseLogging) {
+ ProviderConnectionParameters providerConnectionParameters = adapter.adapt(ProviderConnectionParameters.class, new VerboseLoggingOnlyConnectionParameters(verboseLogging));
+ connection.configure(providerConnectionParameters);
}
+ /**
+ * This is used by consumers 1.0-milestone-3 and later
+ */
public ConnectionMetaDataVersion1 getMetaData() {
- return new ConnectionMetaDataVersion1() {
- public String getVersion() {
- return GradleVersion.current().getVersion();
- }
-
- public String getDisplayName() {
- return String.format("Gradle %s", getVersion());
- }
- };
+ return new DefaultConnectionMetaData();
}
+ /**
+ * This is used by consumers 1.0-milestone-3 and later
+ */
public void stop() {
+ // TODO:ADAM - switch this on again
+// services.close();
}
+ /**
+ * This is used by consumers 1.0-milestone-3 to 1.1.
+ */
@Deprecated
public void executeBuild(BuildParametersVersion1 buildParameters, BuildOperationParametersVersion1 operationParameters) {
logTargetVersion();
- run(Void.class, new AdaptedOperationParameters(operationParameters, buildParameters.getTasks()));
+ connection.run(ModelIdentifier.NULL_MODEL, new AdaptedOperationParameters(operationParameters, buildParameters.getTasks()));
}
+ /**
+ * This is used by consumers 1.0-milestone-3 to 1.0-milestone-7
+ */
@Deprecated
public ProjectVersion3 getModel(Class<? extends ProjectVersion3> type, BuildOperationParametersVersion1 parameters) {
logTargetVersion();
- return run(type, new AdaptedOperationParameters(parameters));
+ return run(type, parameters);
}
+ /**
+ * This is used by consumers 1.0-milestone-8 to 1.1
+ */
@Deprecated
public <T> T getTheModel(Class<T> type, BuildOperationParametersVersion1 parameters) {
logTargetVersion();
- return run(type, new AdaptedOperationParameters(parameters));
+ return run(type, parameters);
+ }
+
+ private <T> T run(Class<T> type, BuildOperationParametersVersion1 parameters) {
+ String modelName = new ModelMapping().getModelNameFromProtocolType(type);
+ return (T) connection.run(modelName, new AdaptedOperationParameters(parameters));
}
+ /**
+ * This is used by consumers 1.2-rc-1 to 1.5
+ */
+ @Deprecated
public <T> BuildResult<T> run(Class<T> type, BuildParameters buildParameters) throws UnsupportedOperationException, IllegalStateException {
logTargetVersion();
- ProviderOperationParameters providerParameters = adapter.adapt(ProviderOperationParameters.class, buildParameters, BuildLogLevelMixIn.class);
- T result = run(type, providerParameters);
+ ProviderOperationParameters providerParameters = toProviderParameters(buildParameters);
+ String modelName = new ModelMapping().getModelNameFromProtocolType(type);
+ T result = (T) connection.run(modelName, providerParameters);
return new ProviderBuildResult<T>(result);
}
- private <T> T run(Class<T> type, ProviderOperationParameters providerParameters) {
- List<String> tasks = providerParameters.getTasks();
- if (type.equals(Void.class) && tasks == null) {
- throw new IllegalArgumentException("No model type or tasks specified.");
- }
- GradleProperties gradleProperties = initGradleProperties(providerParameters);
- if (type == InternalBuildEnvironment.class) {
- //we don't really need to launch the daemon to acquire information needed for BuildEnvironment
- if (tasks != null) {
- throw new IllegalArgumentException("Cannot run tasks and fetch the build environment model.");
- }
- DaemonParameters daemonParameters = init(providerParameters, gradleProperties);
- DefaultBuildEnvironment out = new DefaultBuildEnvironment(
- GradleVersion.current().getVersion(),
- daemonParameters.getEffectiveJavaHome(),
- daemonParameters.getEffectiveJvmArgs());
-
- return type.cast(out);
- }
-
- DelegatingBuildModelAction<T> action = new DelegatingBuildModelAction<T>(type, tasks != null);
- return run(action, providerParameters, gradleProperties);
+ /**
+ * This is used by consumers 1.6-rc-1 and later
+ */
+ public BuildResult<?> getModel(ModelIdentifier modelIdentifier, BuildParameters operationParameters) throws UnsupportedOperationException, IllegalStateException {
+ logTargetVersion();
+ ProviderOperationParameters providerParameters = toProviderParameters(operationParameters);
+ Object result = connection.run(modelIdentifier.getName(), providerParameters);
+ return new ProviderBuildResult<Object>(result);
}
- private void logTargetVersion() {
- LOGGER.info("Tooling API uses target gradle version:" + " {}.", GradleVersion.current().getVersion());
+ /**
+ * This is used by consumers 1.8-rc-1 and later.
+ */
+ public <T> BuildResult<T> run(InternalBuildAction<T> action, BuildParameters operationParameters) throws BuildExceptionVersion1, InternalUnsupportedBuildArgumentException, IllegalStateException {
+ logTargetVersion();
+ ProviderOperationParameters providerParameters = toProviderParameters(operationParameters);
+ Object results = connection.run(action, providerParameters);
+ return new ProviderBuildResult<T>((T) results);
}
- private <T> T run(GradleLauncherAction<T> action, ProviderOperationParameters operationParameters, GradleProperties gradleProperties) {
- GradleLauncherActionExecuter<ProviderOperationParameters> executer = createExecuter(operationParameters);
- ConfiguringBuildAction<T> configuringAction = new ConfiguringBuildAction<T>(operationParameters, action, gradleProperties);
- return executer.execute(configuringAction, operationParameters);
+ private void logTargetVersion() {
+ LOGGER.info("Tooling API is using target Gradle version: {}.", GradleVersion.current().getVersion());
}
- private GradleLauncherActionExecuter<ProviderOperationParameters> createExecuter(ProviderOperationParameters operationParameters) {
- LoggingServiceRegistry loggingServices;
- DaemonParameters daemonParams = init(operationParameters, initGradleProperties(operationParameters));
- GradleLauncherActionExecuter<BuildActionParameters> executer;
- if (Boolean.TRUE.equals(operationParameters.isEmbedded())) {
- loggingServices = embeddedExecuterSupport.getLoggingServices();
- executer = embeddedExecuterSupport.getExecuter();
- } else {
- loggingServices = embeddedExecuterSupport.getLoggingServices().newLogging();
- loggingServices.get(OutputEventRenderer.class).configure(operationParameters.getBuildLogLevel());
- DaemonClientServices clientServices = new DaemonClientServices(loggingServices, daemonParams, operationParameters.getStandardInput(SafeStreams.emptyInput()));
- executer = clientServices.get(DaemonClient.class);
- }
- Factory<LoggingManagerInternal> loggingManagerFactory = loggingServices.getFactory(LoggingManagerInternal.class);
- return new LoggingBridgingGradleLauncherActionExecuter(new DaemonGradleLauncherActionExecuter(executer, daemonParams), loggingManagerFactory);
+ private ProviderOperationParameters toProviderParameters(BuildParameters buildParameters) {
+ return adapter.adapt(ProviderOperationParameters.class, buildParameters, BuildLogLevelMixIn.class);
}
- private DaemonParameters init(ProviderOperationParameters operationParameters, GradleProperties gradleProperties) {
- DaemonParameters daemonParams = new DaemonParameters();
-
- daemonParams.configureFrom(gradleProperties);
+ private static class VerboseLoggingOnlyConnectionParameters {
+ private final boolean verboseLogging;
- //override the params with the explicit settings provided by the tooling api
- List<String> defaultJvmArgs = daemonParams.getAllJvmArgs();
- daemonParams.setJvmArgs(operationParameters.getJvmArguments(defaultJvmArgs));
- File defaultJavaHome = daemonParams.getEffectiveJavaHome();
- daemonParams.setJavaHome(operationParameters.getJavaHome(defaultJavaHome));
-
- if (operationParameters.getDaemonMaxIdleTimeValue() != null && operationParameters.getDaemonMaxIdleTimeUnits() != null) {
- int idleTimeout = (int) operationParameters.getDaemonMaxIdleTimeUnits().toMillis(operationParameters.getDaemonMaxIdleTimeValue());
- daemonParams.setIdleTimeout(idleTimeout);
+ public VerboseLoggingOnlyConnectionParameters(boolean verboseLogging) {
+ this.verboseLogging = verboseLogging;
}
- return daemonParams;
- }
- private GradleProperties initGradleProperties(ProviderOperationParameters operationParameters) {
- File gradleUserHomeDir = GUtil.elvis(operationParameters.getGradleUserHomeDir(), StartParameter.DEFAULT_GRADLE_USER_HOME);
- boolean searchUpwards = operationParameters.isSearchUpwards() != null ? operationParameters.isSearchUpwards() : true;
- return new GradlePropertiesConfigurer()
- .prepareProperties(operationParameters.getProjectDir(), searchUpwards, gradleUserHomeDir, System.getProperties());
+ public boolean getVerboseLogging() {
+ return verboseLogging;
+ }
}
-
}
\ No newline at end of file
diff --git a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/DefaultConnectionMetaData.java b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/DefaultConnectionMetaData.java
new file mode 100644
index 0000000..fda63f8
--- /dev/null
+++ b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/DefaultConnectionMetaData.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.provider;
+
+import org.gradle.tooling.internal.protocol.ConnectionMetaDataVersion1;
+import org.gradle.util.GradleVersion;
+
+class DefaultConnectionMetaData implements ConnectionMetaDataVersion1 {
+ public String getVersion() {
+ return GradleVersion.current().getVersion();
+ }
+
+ public String getDisplayName() {
+ return String.format("Gradle %s", getVersion());
+ }
+}
diff --git a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/DefaultPayloadClassLoaderRegistry.java b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/DefaultPayloadClassLoaderRegistry.java
new file mode 100644
index 0000000..4148ddc
--- /dev/null
+++ b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/DefaultPayloadClassLoaderRegistry.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.provider;
+
+import com.google.common.collect.MapMaker;
+import net.jcip.annotations.ThreadSafe;
+import org.gradle.internal.classloader.ClassLoaderSpec;
+import org.gradle.internal.classloader.ClassLoaderVisitor;
+import org.gradle.internal.classloader.MutableURLClassLoader;
+import org.gradle.util.CollectionUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.URL;
+import java.util.*;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+ at ThreadSafe
+public class DefaultPayloadClassLoaderRegistry implements PayloadClassLoaderRegistry {
+ private static final Logger LOGGER = LoggerFactory.getLogger(DefaultPayloadClassLoaderRegistry.class);
+ private final Lock lock = new ReentrantLock();
+ private final ModelClassLoaderFactory classLoaderFactory;
+ private Map<ClassLoader, ClassLoaderDetails> classLoaderDetails;
+ private Map<UUID, ClassLoader> classLoaderIds;
+
+ public DefaultPayloadClassLoaderRegistry(ModelClassLoaderFactory modelClassLoaderFactory) {
+ classLoaderDetails = new MapMaker().weakKeys().makeMap();
+ classLoaderIds = new MapMaker().weakValues().makeMap();
+ this.classLoaderFactory = modelClassLoaderFactory;
+ }
+
+ public SerializeMap newSerializeSession() {
+ return new SerializeMap() {
+ final Map<ClassLoader, Short> classLoaderIds = new HashMap<ClassLoader, Short>();
+ final Map<Short, ClassLoaderDetails> classLoaderDetails = new HashMap<Short, ClassLoaderDetails>();
+
+ public short visitClass(Class<?> target) {
+ ClassLoader classLoader = target.getClassLoader();
+ Short id = classLoaderIds.get(classLoader);
+ if (id != null) {
+ return id;
+ }
+ if (classLoaderIds.size() == Short.MAX_VALUE) {
+ throw new UnsupportedOperationException();
+ }
+ ClassLoaderDetails details = getDetails(classLoader);
+ id = (short) (classLoaderIds.size() + 1);
+
+ classLoaderIds.put(classLoader, id);
+ classLoaderDetails.put(id, details);
+
+ return id;
+ }
+
+ public Map<Short, ClassLoaderDetails> getClassLoaders() {
+ return classLoaderDetails;
+ }
+ };
+ }
+
+ public DeserializeMap newDeserializeSession() {
+ return new DeserializeMap() {
+ public Class<?> resolveClass(ClassLoaderDetails classLoaderDetails, String className) throws ClassNotFoundException {
+ ClassLoader classLoader = getClassLoader(classLoaderDetails);
+ return Class.forName(className, false, classLoader);
+ }
+ };
+ }
+
+ private ClassLoader getClassLoader(ClassLoaderDetails details) {
+ lock.lock();
+ try {
+ ClassLoader classLoader = classLoaderIds.get(details.uuid);
+ if (classLoader != null) {
+ return classLoader;
+ }
+
+ List<ClassLoader> parents = new ArrayList<ClassLoader>();
+ for (ClassLoaderDetails parentDetails : details.parents) {
+ parents.add(getClassLoader(parentDetails));
+ }
+ if (parents.isEmpty()) {
+ parents.add(classLoaderFactory.getClassLoaderFor(ClassLoaderSpec.SYSTEM_CLASS_LOADER, null));
+ }
+
+ LOGGER.info("Creating ClassLoader {} from {} and {}.", details.uuid, details.spec, parents);
+
+ classLoader = classLoaderFactory.getClassLoaderFor(details.spec, parents);
+ classLoaderIds.put(details.uuid, classLoader);
+ classLoaderDetails.put(classLoader, details);
+ return classLoader;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ private ClassLoaderDetails getDetails(ClassLoader classLoader) {
+ lock.lock();
+ try {
+ ClassLoaderDetails details = classLoaderDetails.get(classLoader);
+ if (details != null) {
+ return details;
+ }
+
+ ClassLoaderSpecVisitor visitor = new ClassLoaderSpecVisitor(classLoader);
+ visitor.visit(classLoader);
+
+ if (visitor.spec == null) {
+ if (visitor.classPath == null) {
+ visitor.spec = ClassLoaderSpec.SYSTEM_CLASS_LOADER;
+ } else {
+ visitor.spec = new MutableURLClassLoader.Spec(CollectionUtils.toList(visitor.classPath));
+ }
+ }
+
+ UUID uuid = UUID.randomUUID();
+ details = new ClassLoaderDetails(uuid, visitor.spec);
+ for (ClassLoader parent : visitor.parents) {
+ details.parents.add(getDetails(parent));
+ }
+
+ classLoaderDetails.put(classLoader, details);
+ classLoaderIds.put(details.uuid, classLoader);
+ return details;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ private static class ClassLoaderSpecVisitor extends ClassLoaderVisitor {
+ final ClassLoader classLoader;
+ final List<ClassLoader> parents = new ArrayList<ClassLoader>();
+ ClassLoaderSpec spec;
+ URL[] classPath;
+
+ public ClassLoaderSpecVisitor(ClassLoader classLoader) {
+ this.classLoader = classLoader;
+ }
+
+ @Override
+ public void visit(ClassLoader candidate) {
+ if (candidate == classLoader) {
+ super.visit(candidate);
+ } else {
+ parents.add(candidate);
+ }
+ }
+
+ @Override
+ public void visitClassPath(URL[] classPath) {
+ this.classPath = classPath;
+ }
+
+ @Override
+ public void visitSpec(ClassLoaderSpec spec) {
+ this.spec = spec;
+ }
+ }
+}
diff --git a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/DelegatingBuildModelAction.java b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/DelegatingBuildModelAction.java
deleted file mode 100644
index 9cec903..0000000
--- a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/DelegatingBuildModelAction.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.provider;
-
-import org.gradle.BuildResult;
-import org.gradle.GradleLauncher;
-import org.gradle.initialization.ClassLoaderRegistry;
-import org.gradle.initialization.DefaultGradleLauncher;
-import org.gradle.initialization.GradleLauncherAction;
-import org.gradle.internal.UncheckedException;
-
-import java.io.Serializable;
-import java.lang.reflect.InvocationTargetException;
-
-class DelegatingBuildModelAction<T> implements GradleLauncherAction<T>, Serializable {
- private transient GradleLauncherAction<T> action;
- private final Class<? extends T> type;
- private final boolean runTasks;
-
- public DelegatingBuildModelAction(Class<T> type, boolean runTasks) {
- this.type = type;
- this.runTasks = runTasks;
- }
-
- public T getResult() {
- return action.getResult();
- }
-
- public BuildResult run(GradleLauncher launcher) {
- loadAction((DefaultGradleLauncher) launcher);
- return action.run(launcher);
- }
-
- @SuppressWarnings("unchecked")
- private void loadAction(DefaultGradleLauncher launcher) {
- ClassLoaderRegistry classLoaderRegistry = launcher.getGradle().getServices().get(ClassLoaderRegistry.class);
- try {
- action = (GradleLauncherAction<T>) classLoaderRegistry.getRootClassLoader().loadClass("org.gradle.tooling.internal.provider.BuildModelAction").getConstructor(Class.class, Boolean.TYPE).newInstance(type, runTasks);
- } catch (InvocationTargetException e) {
- throw UncheckedException.unwrapAndRethrow(e);
- } catch (Exception e) {
- throw UncheckedException.throwAsUncheckedException(e);
- }
- }
-}
diff --git a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/DeserializeMap.java b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/DeserializeMap.java
new file mode 100644
index 0000000..0e185ad
--- /dev/null
+++ b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/DeserializeMap.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.provider;
+
+public interface DeserializeMap {
+ /**
+ * Loads a serialized Class.
+ */
+ Class<?> resolveClass(ClassLoaderDetails classLoaderDetails, String className) throws ClassNotFoundException;
+}
diff --git a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/EmbeddedExecuterSupport.java b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/EmbeddedExecuterSupport.java
deleted file mode 100644
index da96a62..0000000
--- a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/EmbeddedExecuterSupport.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.provider;
-
-import org.gradle.initialization.DefaultGradleLauncherFactory;
-import org.gradle.launcher.exec.BuildActionParameters;
-import org.gradle.launcher.exec.GradleLauncherActionExecuter;
-import org.gradle.launcher.exec.InProcessGradleLauncherActionExecuter;
-import org.gradle.logging.LoggingServiceRegistry;
-
-/**
- * by Szczepan Faber, created at: 12/6/11
- */
-public class EmbeddedExecuterSupport {
-
- private DefaultGradleLauncherFactory gradleLauncherFactory;
- private LoggingServiceRegistry embeddedLogging;
-
- public EmbeddedExecuterSupport() {
- embeddedLogging = LoggingServiceRegistry.newEmbeddableLogging();
- gradleLauncherFactory = new DefaultGradleLauncherFactory(embeddedLogging);
- }
-
- public GradleLauncherActionExecuter<BuildActionParameters> getExecuter() {
- return new InProcessGradleLauncherActionExecuter(gradleLauncherFactory);
- }
-
- public LoggingServiceRegistry getLoggingServices() {
- return embeddedLogging;
- }
-}
\ No newline at end of file
diff --git a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/ExecuteBuildAction.java b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/ExecuteBuildAction.java
deleted file mode 100644
index eeb2558..0000000
--- a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/ExecuteBuildAction.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.provider;
-
-import org.gradle.BuildResult;
-import org.gradle.GradleLauncher;
-import org.gradle.initialization.GradleLauncherAction;
-
-import java.io.Serializable;
-
-public class ExecuteBuildAction implements GradleLauncherAction<Void>, Serializable {
-
- public Void getResult() {
- return null;
- }
-
- public BuildResult run(GradleLauncher gradleLauncher) {
- return gradleLauncher.run();
- }
-}
\ No newline at end of file
diff --git a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/LoggingBridgingBuildActionExecuter.java b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/LoggingBridgingBuildActionExecuter.java
new file mode 100644
index 0000000..7ebe715
--- /dev/null
+++ b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/LoggingBridgingBuildActionExecuter.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.provider;
+
+import org.gradle.initialization.BuildAction;
+import org.gradle.internal.Factory;
+import org.gradle.launcher.exec.BuildActionExecuter;
+import org.gradle.logging.LoggingManagerInternal;
+import org.gradle.logging.internal.*;
+import org.gradle.tooling.internal.protocol.ProgressListenerVersion1;
+import org.gradle.tooling.internal.provider.connection.ProviderOperationParameters;
+
+/**
+ * A {@link org.gradle.launcher.exec.BuildActionExecuter} which routes Gradle logging to those listeners specified in the {@link ProviderOperationParameters} provided with a tooling api build
+ * request.
+ */
+public class LoggingBridgingBuildActionExecuter implements BuildActionExecuter<ProviderOperationParameters> {
+ private final Factory<LoggingManagerInternal> loggingManagerFactory;
+ private final BuildActionExecuter<ProviderOperationParameters> executer;
+
+ public LoggingBridgingBuildActionExecuter(BuildActionExecuter<ProviderOperationParameters> executer, Factory<LoggingManagerInternal> loggingManagerFactory) {
+ this.executer = executer;
+ this.loggingManagerFactory = loggingManagerFactory;
+ }
+
+ public <T> T execute(BuildAction<T> action, ProviderOperationParameters actionParameters) {
+ LoggingManagerInternal loggingManager = loggingManagerFactory.create();
+ if (actionParameters.getStandardOutput() != null) {
+ loggingManager.addStandardOutputListener(new StreamBackedStandardOutputListener(actionParameters.getStandardOutput()));
+ }
+ if (actionParameters.getStandardError() != null) {
+ loggingManager.addStandardErrorListener(new StreamBackedStandardOutputListener(actionParameters.getStandardError()));
+ }
+ ProgressListenerVersion1 progressListener = actionParameters.getProgressListener();
+ OutputEventListenerAdapter listener = new OutputEventListenerAdapter(progressListener);
+ loggingManager.addOutputEventListener(listener);
+ loggingManager.setLevel(actionParameters.getBuildLogLevel());
+ loggingManager.start();
+ try {
+ return executer.execute(action, actionParameters);
+ } finally {
+ loggingManager.stop();
+ }
+ }
+
+ private static class OutputEventListenerAdapter implements OutputEventListener {
+ private final ProgressListenerVersion1 progressListener;
+
+ public OutputEventListenerAdapter(ProgressListenerVersion1 progressListener) {
+ this.progressListener = progressListener;
+ }
+
+ public void onOutput(OutputEvent event) {
+ if (event instanceof ProgressStartEvent) {
+ ProgressStartEvent startEvent = (ProgressStartEvent) event;
+ progressListener.onOperationStart(startEvent.getDescription());
+ } else if (event instanceof ProgressCompleteEvent) {
+ progressListener.onOperationEnd();
+ }
+ }
+ }
+}
diff --git a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/LoggingBridgingGradleLauncherActionExecuter.java b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/LoggingBridgingGradleLauncherActionExecuter.java
deleted file mode 100644
index c05a704..0000000
--- a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/LoggingBridgingGradleLauncherActionExecuter.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.provider;
-
-import org.gradle.initialization.GradleLauncherAction;
-import org.gradle.internal.Factory;
-import org.gradle.launcher.exec.GradleLauncherActionExecuter;
-import org.gradle.logging.LoggingManagerInternal;
-import org.gradle.logging.internal.*;
-import org.gradle.tooling.internal.protocol.ProgressListenerVersion1;
-import org.gradle.tooling.internal.provider.connection.ProviderOperationParameters;
-
-/**
- * A {@link org.gradle.launcher.exec.GradleLauncherActionExecuter} which routes Gradle logging to those listeners specified in the {@link ProviderOperationParameters} provided with a tooling api build
- * request.
- */
-public class LoggingBridgingGradleLauncherActionExecuter implements GradleLauncherActionExecuter<ProviderOperationParameters> {
- private final Factory<LoggingManagerInternal> loggingManagerFactory;
- private final GradleLauncherActionExecuter<ProviderOperationParameters> executer;
-
- public LoggingBridgingGradleLauncherActionExecuter(GradleLauncherActionExecuter<ProviderOperationParameters> executer, Factory<LoggingManagerInternal> loggingManagerFactory) {
- this.executer = executer;
- this.loggingManagerFactory = loggingManagerFactory;
- }
-
- public <T> T execute(GradleLauncherAction<T> action, ProviderOperationParameters actionParameters) {
- LoggingManagerInternal loggingManager = loggingManagerFactory.create();
- if (actionParameters.getStandardOutput() != null) {
- loggingManager.addStandardOutputListener(new StreamBackedStandardOutputListener(actionParameters.getStandardOutput()));
- }
- if (actionParameters.getStandardError() != null) {
- loggingManager.addStandardErrorListener(new StreamBackedStandardOutputListener(actionParameters.getStandardError()));
- }
- ProgressListenerVersion1 progressListener = actionParameters.getProgressListener();
- OutputEventListenerAdapter listener = new OutputEventListenerAdapter(progressListener);
- loggingManager.addOutputEventListener(listener);
- loggingManager.setLevel(actionParameters.getBuildLogLevel());
- loggingManager.start();
- try {
- return executer.execute(action, actionParameters);
- } finally {
- loggingManager.stop();
- }
- }
-
- private static class OutputEventListenerAdapter implements OutputEventListener {
- private final ProgressListenerVersion1 progressListener;
-
- public OutputEventListenerAdapter(ProgressListenerVersion1 progressListener) {
- this.progressListener = progressListener;
- }
-
- public void onOutput(OutputEvent event) {
- if (event instanceof ProgressStartEvent) {
- ProgressStartEvent startEvent = (ProgressStartEvent) event;
- progressListener.onOperationStart(startEvent.getDescription());
- } else if (event instanceof ProgressCompleteEvent) {
- progressListener.onOperationEnd();
- }
- }
- }
-}
diff --git a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/ModelClassLoaderFactory.java b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/ModelClassLoaderFactory.java
new file mode 100644
index 0000000..5315005
--- /dev/null
+++ b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/ModelClassLoaderFactory.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.provider;
+
+import org.gradle.internal.classloader.*;
+import org.gradle.tooling.provider.model.internal.LegacyConsumerInterface;
+import org.objectweb.asm.*;
+
+import java.net.URL;
+import java.util.Arrays;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+public class ModelClassLoaderFactory {
+ private final ClassLoader rootClassLoader;
+ private final ClassLoaderFactory classLoaderFactory = new DefaultClassLoaderFactory();
+
+ public ModelClassLoaderFactory() {
+ ClassLoader parent = getClass().getClassLoader();
+ FilteringClassLoader filter = new FilteringClassLoader(parent);
+ filter.allowPackage("org.gradle.tooling.internal.protocol");
+ rootClassLoader = filter;
+ }
+
+ public ClassLoader getClassLoaderFor(ClassLoaderSpec spec, List<? extends ClassLoader> parents) {
+ if (spec.equals(ClassLoaderSpec.SYSTEM_CLASS_LOADER)) {
+ return rootClassLoader;
+ }
+ if (spec instanceof MutableURLClassLoader.Spec) {
+ MutableURLClassLoader.Spec clSpec = (MutableURLClassLoader.Spec) spec;
+ if (parents.size() != 1) {
+ throw new IllegalStateException("Expected exactly one parent ClassLoader");
+ }
+ return new MixInClassLoader(parents.get(0), clSpec.getClasspath());
+ }
+ return classLoaderFactory.createClassLoader(spec, parents);
+ }
+
+ private static class MixInClassLoader extends TransformingClassLoader {
+ public MixInClassLoader(ClassLoader parent, List<URL> classPath) {
+ super(parent, classPath);
+ }
+
+ @Override
+ protected byte[] transform(byte[] bytes) {
+ // First scan for annotation, and short circuit transformation if not present
+ ClassReader classReader = new ClassReader(bytes);
+
+ AnnotationDetector detector = new AnnotationDetector();
+ classReader.accept(detector, ClassReader.SKIP_DEBUG | ClassReader.SKIP_CODE);
+ if (!detector.found) {
+ return bytes;
+ }
+
+ if (findLoadedClass(detector.interfaceName) == null) {
+ // TODO:ADAM - need to do this earlier
+ ClassWriter emptyWriter = new ClassWriter(0);
+ emptyWriter.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC | Opcodes.ACC_INTERFACE, detector.interfaceName.replace(".", "/"), null, Type.getType(Object.class).getInternalName(), null);
+ emptyWriter.visitEnd();
+ byte[] emptyBytecode = emptyWriter.toByteArray();
+ defineClass(detector.interfaceName, emptyBytecode, 0, emptyBytecode.length);
+ }
+
+ ClassWriter classWriter = new ClassWriter(0);
+ classReader.accept(new TransformingAdapter(classWriter, detector.interfaceName), 0);
+ bytes = classWriter.toByteArray();
+ return bytes;
+ }
+
+ private static class AnnotationDetector extends ClassVisitor {
+ private static final String ANNOTATION_DESCRIPTOR = Type.getType(LegacyConsumerInterface.class).getDescriptor();
+ String interfaceName;
+ private boolean found;
+
+ private AnnotationDetector() {
+ super(Opcodes.ASM4);
+ }
+
+ public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+ if (desc.equals(ANNOTATION_DESCRIPTOR)) {
+ found = true;
+ }
+ return new AnnotationVisitor(Opcodes.ASM4) {
+
+ @Override
+ public void visit(String name, Object value) {
+ if (name.equals("value")) {
+ interfaceName = value.toString();
+ }
+ }
+ };
+ }
+ }
+
+ private static class TransformingAdapter extends ClassVisitor {
+ private final String mixInInterface;
+
+ public TransformingAdapter(ClassWriter classWriter, String mixInInterface) {
+ super(Opcodes.ASM4, classWriter);
+ this.mixInInterface = mixInInterface;
+ }
+
+ @Override
+ public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
+ Set<String> allInterfaces = new LinkedHashSet<String>(Arrays.asList(interfaces));
+ allInterfaces.add(mixInInterface.replace(".", "/"));
+ super.visit(version, access, name, signature, superName, allInterfaces.toArray(new String[allInterfaces.size()]));
+ }
+ }
+ }
+}
diff --git a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/PayloadClassLoaderRegistry.java b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/PayloadClassLoaderRegistry.java
new file mode 100644
index 0000000..68fd217
--- /dev/null
+++ b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/PayloadClassLoaderRegistry.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.provider;
+
+import net.jcip.annotations.ThreadSafe;
+
+ at ThreadSafe
+public interface PayloadClassLoaderRegistry {
+ SerializeMap newSerializeSession();
+
+ DeserializeMap newDeserializeSession();
+}
diff --git a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/PayloadSerializer.java b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/PayloadSerializer.java
new file mode 100644
index 0000000..ab4405c
--- /dev/null
+++ b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/PayloadSerializer.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.provider;
+
+import net.jcip.annotations.ThreadSafe;
+import org.gradle.api.Transformer;
+import org.gradle.internal.UncheckedException;
+import org.gradle.internal.jvm.Jvm;
+
+import java.io.*;
+import java.lang.reflect.Proxy;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+ at ThreadSafe
+public class PayloadSerializer {
+ private static final short SYSTEM_CLASS_LOADER_ID = (short) -1;
+ private static final Set<ClassLoader> SYSTEM_CLASS_LOADERS = new HashSet<ClassLoader>();
+ private final Transformer<ObjectStreamClass, Class<?>> classLookup;
+ private final PayloadClassLoaderRegistry classLoaderRegistry;
+
+ static {
+ for (ClassLoader cl = ClassLoader.getSystemClassLoader().getParent(); cl != null; cl = cl.getParent()) {
+ SYSTEM_CLASS_LOADERS.add(cl);
+ }
+ }
+
+ public PayloadSerializer(PayloadClassLoaderRegistry registry) {
+ classLoaderRegistry = registry;
+
+ // On Java 6, there is a public method to lookup a class descriptor given a class. On Java 5, we have to use reflection
+ // TODO:ADAM - move this into the service registry
+ if (Jvm.current().getJavaVersion().isJava6Compatible()) {
+ // Use the public method
+ try {
+ classLookup = (Transformer<ObjectStreamClass, Class<?>>) getClass().getClassLoader().loadClass("org.gradle.tooling.internal.provider.jdk6.Jdk6ClassLookup").newInstance();
+ } catch (Exception e) {
+ throw UncheckedException.throwAsUncheckedException(e);
+ }
+ } else {
+ // Use Java 5 fallback which uses reflection
+ classLookup = new ReflectionClassLookup();
+ }
+ }
+
+ public SerializedPayload serialize(Object payload) {
+ final SerializeMap map = classLoaderRegistry.newSerializeSession();
+ try {
+ ByteArrayOutputStream content = new ByteArrayOutputStream();
+ final ObjectOutputStream objectStream = new ObjectOutputStream(content) {
+ @Override
+ protected void writeClassDescriptor(ObjectStreamClass desc) throws IOException {
+ Class<?> targetClass = desc.forClass();
+ writeClass(targetClass);
+ }
+
+ @Override
+ protected void annotateProxyClass(Class<?> cl) throws IOException {
+ writeInt(cl.getInterfaces().length);
+ for (Class<?> type : cl.getInterfaces()) {
+ writeClass(type);
+ }
+ }
+
+ private void writeClass(Class<?> targetClass) throws IOException {
+ writeClassLoader(targetClass);
+ writeUTF(targetClass.getName());
+ }
+
+ private void writeClassLoader(Class<?> targetClass) throws IOException {
+ ClassLoader classLoader = targetClass.getClassLoader();
+ if (classLoader == null || SYSTEM_CLASS_LOADERS.contains(classLoader)) {
+ writeShort(SYSTEM_CLASS_LOADER_ID);
+ } else {
+ writeShort(map.visitClass(targetClass));
+ }
+ }
+ };
+
+ objectStream.writeObject(payload);
+ objectStream.close();
+
+ Map<Short, ClassLoaderDetails> classLoaders = map.getClassLoaders();
+ if (classLoaders.containsKey(SYSTEM_CLASS_LOADER_ID)) {
+ throw new IllegalArgumentException("Unexpected ClassLoader id found");
+ }
+ return new SerializedPayload(classLoaders, content.toByteArray());
+ } catch (IOException e) {
+ throw UncheckedException.throwAsUncheckedException(e);
+ }
+ }
+
+ public Object deserialize(SerializedPayload payload) {
+ final DeserializeMap map = classLoaderRegistry.newDeserializeSession();
+ try {
+ final ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader().getParent();
+ final Map<Short, ClassLoaderDetails> classLoaderDetails = (Map<Short, ClassLoaderDetails>) payload.getHeader();
+
+ final ObjectInputStream objectStream = new ObjectInputStream(new ByteArrayInputStream(payload.getSerializedModel())) {
+ @Override
+ protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException {
+ Class<?> aClass = readClass();
+ ObjectStreamClass descriptor = classLookup.transform(aClass);
+ if (descriptor == null) {
+ throw new ClassNotFoundException(aClass.getName());
+ }
+ return descriptor;
+ }
+
+ @Override
+ protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
+ return desc.forClass();
+ }
+
+ private Class<?> readClass() throws IOException, ClassNotFoundException {
+ short id = readShort();
+ String className = readUTF();
+ if (id == SYSTEM_CLASS_LOADER_ID) {
+ return Class.forName(className, false, systemClassLoader);
+ }
+ ClassLoaderDetails classLoader = classLoaderDetails.get(id);
+ return map.resolveClass(classLoader, className);
+ }
+
+ @Override
+ protected Class<?> resolveProxyClass(String[] interfaces) throws IOException, ClassNotFoundException {
+ int count = readInt();
+ Class<?>[] actualInterfaces = new Class<?>[count];
+ for (int i = 0; i < count; i++) {
+ actualInterfaces[i] = readClass();
+ }
+ return Proxy.getProxyClass(actualInterfaces[0].getClassLoader(), actualInterfaces);
+ }
+ };
+ return objectStream.readObject();
+ } catch (Exception e) {
+ throw UncheckedException.throwAsUncheckedException(e);
+ }
+ }
+}
diff --git a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/ProviderConnection.java b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/ProviderConnection.java
new file mode 100644
index 0000000..2fd6489
--- /dev/null
+++ b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/ProviderConnection.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.provider;
+
+import org.gradle.StartParameter;
+import org.gradle.api.logging.LogLevel;
+import org.gradle.initialization.BuildAction;
+import org.gradle.initialization.BuildLayoutParameters;
+import org.gradle.initialization.GradleLauncherFactory;
+import org.gradle.internal.Factory;
+import org.gradle.launcher.cli.converter.LayoutToPropertiesConverter;
+import org.gradle.launcher.cli.converter.PropertiesToDaemonParametersConverter;
+import org.gradle.launcher.daemon.client.DaemonClient;
+import org.gradle.launcher.daemon.client.DaemonClientServices;
+import org.gradle.launcher.daemon.configuration.DaemonParameters;
+import org.gradle.launcher.exec.BuildActionExecuter;
+import org.gradle.launcher.exec.BuildActionParameters;
+import org.gradle.launcher.exec.InProcessBuildActionExecuter;
+import org.gradle.logging.LoggingManagerInternal;
+import org.gradle.logging.LoggingServiceRegistry;
+import org.gradle.logging.internal.OutputEventRenderer;
+import org.gradle.process.internal.streams.SafeStreams;
+import org.gradle.tooling.internal.build.DefaultBuildEnvironment;
+import org.gradle.tooling.internal.consumer.versioning.ModelMapping;
+import org.gradle.tooling.internal.protocol.InternalBuildAction;
+import org.gradle.tooling.internal.protocol.InternalBuildEnvironment;
+import org.gradle.tooling.internal.protocol.ModelIdentifier;
+import org.gradle.tooling.internal.provider.connection.ProviderConnectionParameters;
+import org.gradle.tooling.internal.provider.connection.ProviderOperationParameters;
+import org.gradle.util.GUtil;
+import org.gradle.util.GradleVersion;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class ProviderConnection {
+ private static final Logger LOGGER = LoggerFactory.getLogger(ProviderConnection.class);
+ private final PayloadSerializer payloadSerializer;
+ private final LoggingServiceRegistry loggingServices;
+ private final GradleLauncherFactory gradleLauncherFactory;
+
+ public ProviderConnection(LoggingServiceRegistry loggingServices, GradleLauncherFactory gradleLauncherFactory, PayloadSerializer payloadSerializer) {
+ this.loggingServices = loggingServices;
+ this.gradleLauncherFactory = gradleLauncherFactory;
+ this.payloadSerializer = payloadSerializer;
+ }
+
+ public void configure(ProviderConnectionParameters parameters) {
+ LogLevel providerLogLevel = parameters.getVerboseLogging() ? LogLevel.DEBUG : LogLevel.INFO;
+ LOGGER.debug("Configuring logging to level: {}", providerLogLevel);
+ LoggingManagerInternal loggingManager = loggingServices.newInstance(LoggingManagerInternal.class);
+ loggingManager.setLevel(providerLogLevel);
+ loggingManager.start();
+ }
+
+ public Object run(String modelName, ProviderOperationParameters providerParameters) {
+ List<String> tasks = providerParameters.getTasks();
+ if (modelName.equals(ModelIdentifier.NULL_MODEL) && tasks == null) {
+ throw new IllegalArgumentException("No model type or tasks specified.");
+ }
+ Parameters params = initParams(providerParameters);
+ Class<?> type = new ModelMapping().getProtocolTypeFromModelName(modelName);
+ if (type == InternalBuildEnvironment.class) {
+ //we don't really need to launch the daemon to acquire information needed for BuildEnvironment
+ if (tasks != null) {
+ throw new IllegalArgumentException("Cannot run tasks and fetch the build environment model.");
+ }
+ return new DefaultBuildEnvironment(
+ GradleVersion.current().getVersion(),
+ params.daemonParams.getEffectiveJavaHome(),
+ params.daemonParams.getEffectiveJvmArgs());
+ }
+
+ BuildAction<BuildActionResult> action = new BuildModelAction(modelName, tasks != null);
+ return run(action, providerParameters, params.properties);
+ }
+
+ public Object run(InternalBuildAction<?> clientAction, ProviderOperationParameters providerParameters) {
+ SerializedPayload serializedAction = payloadSerializer.serialize(clientAction);
+ Parameters params = initParams(providerParameters);
+ BuildAction<BuildActionResult> action = new ClientProvidedBuildAction(serializedAction);
+ return run(action, providerParameters, params.properties);
+ }
+
+ private Object run(BuildAction<? extends BuildActionResult> action, ProviderOperationParameters operationParameters, Map<String, String> properties) {
+ BuildActionExecuter<ProviderOperationParameters> executer = createExecuter(operationParameters);
+ ConfiguringBuildAction<BuildActionResult> configuringAction = new ConfiguringBuildAction<BuildActionResult>(operationParameters, action, properties);
+ BuildActionResult result = executer.execute(configuringAction, operationParameters);
+ if (result.failure != null) {
+ throw (RuntimeException) payloadSerializer.deserialize(result.failure);
+ }
+ return payloadSerializer.deserialize(result.result);
+ }
+
+ private BuildActionExecuter<ProviderOperationParameters> createExecuter(ProviderOperationParameters operationParameters) {
+ LoggingServiceRegistry loggingServices;
+ Parameters params = initParams(operationParameters);
+ BuildActionExecuter<BuildActionParameters> executer;
+ if (Boolean.TRUE.equals(operationParameters.isEmbedded())) {
+ loggingServices = this.loggingServices;
+ executer = new InProcessBuildActionExecuter(gradleLauncherFactory);
+ } else {
+ loggingServices = this.loggingServices.newLogging();
+ loggingServices.get(OutputEventRenderer.class).configure(operationParameters.getBuildLogLevel());
+ DaemonClientServices clientServices = new DaemonClientServices(loggingServices, params.daemonParams, operationParameters.getStandardInput(SafeStreams.emptyInput()));
+ executer = clientServices.get(DaemonClient.class);
+ }
+ Factory<LoggingManagerInternal> loggingManagerFactory = loggingServices.getFactory(LoggingManagerInternal.class);
+ return new LoggingBridgingBuildActionExecuter(new DaemonBuildActionExecuter(executer, params.daemonParams), loggingManagerFactory);
+ }
+
+ private Parameters initParams(ProviderOperationParameters operationParameters) {
+ BuildLayoutParameters layout = new BuildLayoutParameters()
+ .setGradleUserHomeDir(GUtil.elvis(operationParameters.getGradleUserHomeDir(), StartParameter.DEFAULT_GRADLE_USER_HOME))
+ .setSearchUpwards(operationParameters.isSearchUpwards() != null ? operationParameters.isSearchUpwards() : true)
+ .setProjectDir(operationParameters.getProjectDir());
+
+ Map<String, String> properties = new HashMap<String, String>();
+ new LayoutToPropertiesConverter().convert(layout, properties);
+
+ DaemonParameters daemonParams = new DaemonParameters(layout);
+ new PropertiesToDaemonParametersConverter().convert(properties, daemonParams);
+
+ //override the params with the explicit settings provided by the tooling api
+ List<String> defaultJvmArgs = daemonParams.getAllJvmArgs();
+ daemonParams.setJvmArgs(operationParameters.getJvmArguments(defaultJvmArgs));
+ File defaultJavaHome = daemonParams.getEffectiveJavaHome();
+ daemonParams.setJavaHome(operationParameters.getJavaHome(defaultJavaHome));
+
+ if (operationParameters.getDaemonMaxIdleTimeValue() != null && operationParameters.getDaemonMaxIdleTimeUnits() != null) {
+ int idleTimeout = (int) operationParameters.getDaemonMaxIdleTimeUnits().toMillis(operationParameters.getDaemonMaxIdleTimeValue());
+ daemonParams.setIdleTimeout(idleTimeout);
+ }
+ return new Parameters(daemonParams, properties);
+ }
+
+ private static class Parameters {
+ DaemonParameters daemonParams;
+ Map<String, String> properties;
+
+ public Parameters(DaemonParameters daemonParams, Map<String, String> properties) {
+ this.daemonParams = daemonParams;
+ this.properties = properties;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/ReflectionClassLookup.java b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/ReflectionClassLookup.java
new file mode 100644
index 0000000..abeca6c
--- /dev/null
+++ b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/ReflectionClassLookup.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.provider;
+
+import org.gradle.api.Transformer;
+import org.gradle.internal.UncheckedException;
+
+import java.io.ObjectStreamClass;
+import java.lang.reflect.Method;
+
+public class ReflectionClassLookup implements Transformer<ObjectStreamClass, Class<?>> {
+ private final Method lookupMethod;
+
+ public ReflectionClassLookup() {
+ try {
+ lookupMethod = ObjectStreamClass.class.getDeclaredMethod("lookup", Class.class, Boolean.TYPE);
+ lookupMethod.setAccessible(true);
+ } catch (NoSuchMethodException e) {
+ throw UncheckedException.throwAsUncheckedException(e);
+ }
+ }
+
+ public ObjectStreamClass transform(Class<?> original) {
+ try {
+ return (ObjectStreamClass) lookupMethod.invoke(null, original, true);
+ } catch (Exception e) {
+ throw UncheckedException.throwAsUncheckedException(e);
+ }
+ }
+}
diff --git a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/SerializeMap.java b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/SerializeMap.java
new file mode 100644
index 0000000..5509d4d
--- /dev/null
+++ b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/SerializeMap.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.provider;
+
+import java.util.Map;
+
+public interface SerializeMap {
+ /**
+ * Visits a class to be serialized, returning the id of the deserialize ClassLoader to associate this class with.
+ * The id is unique only for this serialization.
+ *
+ * @return The ClassLoader id.
+ */
+ short visitClass(Class<?> target);
+
+ /**
+ * Returns the set of ClassLoaders to use in to deserialize the graph.
+ *
+ * @return The map from ClassLoader id to details to use create that ClassLoader.
+ */
+ Map<Short, ClassLoaderDetails> getClassLoaders();
+}
diff --git a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/SerializedPayload.java b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/SerializedPayload.java
new file mode 100644
index 0000000..682ab6c
--- /dev/null
+++ b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/SerializedPayload.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.provider;
+
+import java.io.Serializable;
+
+public class SerializedPayload implements Serializable {
+ private final byte[] serializedModel;
+ private final Object header;
+
+ public SerializedPayload(Object header, byte[] serializedModel) {
+ this.header = header;
+ this.serializedModel = serializedModel;
+ }
+
+ public Object getHeader() {
+ return header;
+ }
+
+ public byte[] getSerializedModel() {
+ return serializedModel;
+ }
+}
diff --git a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/ToolingGlobalScopeServices.java b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/ToolingGlobalScopeServices.java
new file mode 100644
index 0000000..ac3e18e
--- /dev/null
+++ b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/ToolingGlobalScopeServices.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.provider;
+
+import org.gradle.internal.service.DefaultServiceRegistry;
+
+class ToolingGlobalScopeServices extends DefaultServiceRegistry {
+ protected PayloadSerializer createPayloadSerializer() {
+ return new PayloadSerializer(
+ new DefaultPayloadClassLoaderRegistry(
+ new ModelClassLoaderFactory()));
+ }
+}
diff --git a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/ToolingServices.java b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/ToolingServices.java
new file mode 100644
index 0000000..4cff19e
--- /dev/null
+++ b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/ToolingServices.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.provider;
+
+import org.gradle.internal.service.scopes.PluginServiceRegistry;
+import org.gradle.internal.service.ServiceRegistry;
+
+public class ToolingServices implements PluginServiceRegistry {
+ public ServiceRegistry createGlobalServices(ServiceRegistry parent) {
+ return new ToolingGlobalScopeServices();
+ }
+
+}
diff --git a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/connection/AdaptedOperationParameters.java b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/connection/AdaptedOperationParameters.java
index 4c9f31a..59e01d3 100644
--- a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/connection/AdaptedOperationParameters.java
+++ b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/connection/AdaptedOperationParameters.java
@@ -17,9 +17,9 @@
package org.gradle.tooling.internal.provider.connection;
import org.gradle.api.logging.LogLevel;
+import org.gradle.tooling.internal.adapter.CompatibleIntrospector;
import org.gradle.tooling.internal.protocol.BuildOperationParametersVersion1;
import org.gradle.tooling.internal.protocol.ProgressListenerVersion1;
-import org.gradle.tooling.internal.reflect.CompatibleIntrospector;
import java.io.File;
import java.io.InputStream;
@@ -28,9 +28,6 @@ import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;
-/**
- * by Szczepan Faber, created at: 12/20/11
- */
public class AdaptedOperationParameters implements ProviderOperationParameters {
private final BuildOperationParametersVersion1 delegate;
diff --git a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/connection/ProviderOperationParameters.java b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/connection/ProviderOperationParameters.java
index 0650cde..03f8702 100644
--- a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/connection/ProviderOperationParameters.java
+++ b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/connection/ProviderOperationParameters.java
@@ -27,8 +27,6 @@ import java.util.concurrent.TimeUnit;
/**
* Defines what information is needed on the provider side regarding the build operation.
- * <p>
- * by Szczepan Faber, created at: 12/20/11
*/
public interface ProviderOperationParameters {
boolean getVerboseLogging(boolean defaultValue);
diff --git a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/jdk6/Jdk6ClassLookup.java b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/jdk6/Jdk6ClassLookup.java
new file mode 100644
index 0000000..6dbdf40
--- /dev/null
+++ b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/jdk6/Jdk6ClassLookup.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.provider.jdk6;
+
+import org.gradle.api.Transformer;
+
+import java.io.ObjectStreamClass;
+
+public class Jdk6ClassLookup implements Transformer<ObjectStreamClass, Class<?>> {
+ public ObjectStreamClass transform(Class<?> original) {
+ return ObjectStreamClass.lookupAny(original);
+ }
+}
diff --git a/subprojects/launcher/src/main/resources/META-INF/services/org.gradle.internal.service.scopes.PluginServiceRegistry b/subprojects/launcher/src/main/resources/META-INF/services/org.gradle.internal.service.scopes.PluginServiceRegistry
new file mode 100644
index 0000000..af8bd56
--- /dev/null
+++ b/subprojects/launcher/src/main/resources/META-INF/services/org.gradle.internal.service.scopes.PluginServiceRegistry
@@ -0,0 +1 @@
+org.gradle.tooling.internal.provider.ToolingServices
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/launcher/cli/BuildActionsFactoryTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/launcher/cli/BuildActionsFactoryTest.groovy
index 5ccf12e..7aebba1 100644
--- a/subprojects/launcher/src/test/groovy/org/gradle/launcher/cli/BuildActionsFactoryTest.groovy
+++ b/subprojects/launcher/src/test/groovy/org/gradle/launcher/cli/BuildActionsFactoryTest.groovy
@@ -15,17 +15,20 @@
*/
package org.gradle.launcher.cli
-import org.gradle.StartParameter
-import org.gradle.cli.CommandLineConverter
import org.gradle.cli.CommandLineParser
+import org.gradle.cli.SystemPropertiesCommandLineConverter
+import org.gradle.initialization.DefaultCommandLineConverter
+import org.gradle.initialization.LayoutCommandLineConverter
import org.gradle.internal.os.OperatingSystem
import org.gradle.internal.service.ServiceRegistry
+import org.gradle.launcher.cli.converter.DaemonCommandLineConverter
+import org.gradle.launcher.cli.converter.LayoutToPropertiesConverter
+import org.gradle.launcher.cli.converter.PropertiesToDaemonParametersConverter
+import org.gradle.launcher.cli.converter.PropertiesToStartParameterConverter
import org.gradle.launcher.daemon.bootstrap.DaemonMain
import org.gradle.launcher.daemon.client.DaemonClient
import org.gradle.launcher.daemon.client.SingleUseDaemonClient
-import org.gradle.launcher.daemon.configuration.DaemonParameters
-import org.gradle.launcher.daemon.configuration.GradlePropertiesConfigurer
-import org.gradle.launcher.exec.InProcessGradleLauncherActionExecuter
+import org.gradle.launcher.exec.InProcessBuildActionExecuter
import org.gradle.logging.ProgressLoggerFactory
import org.gradle.logging.internal.OutputEventListener
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
@@ -38,19 +41,21 @@ class BuildActionsFactoryTest extends Specification {
public final SetSystemProperties sysProperties = new SetSystemProperties();
@Rule
TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider();
- final CommandLineConverter<StartParameter> startParameterConverter = Mock()
- final ServiceRegistry loggingServices = Mock()
- final GradlePropertiesConfigurer configurer = Stub()
- final BuildActionsFactory factory = new BuildActionsFactory(loggingServices, startParameterConverter, configurer)
+ ServiceRegistry loggingServices = Mock()
+ PropertiesToDaemonParametersConverter propertiesToDaemonParametersConverter = Stub()
- def setup() {
+ BuildActionsFactory factory = new BuildActionsFactory(
+ loggingServices, Stub(DefaultCommandLineConverter), new DaemonCommandLineConverter(),
+ Stub(LayoutCommandLineConverter), Stub(SystemPropertiesCommandLineConverter),
+ Stub(LayoutToPropertiesConverter), Stub(PropertiesToStartParameterConverter),
+ propertiesToDaemonParametersConverter)
+
+ def setup() {
_ * loggingServices.get(OutputEventListener) >> Mock(OutputEventListener)
_ * loggingServices.get(ProgressLoggerFactory) >> Mock(ProgressLoggerFactory)
}
def "executes build"() {
- configurer.configureParameters(_ as StartParameter) >> new DaemonParameters()
-
when:
def action = convert('args')
@@ -59,8 +64,6 @@ class BuildActionsFactoryTest extends Specification {
}
def "by default daemon is not used"() {
- configurer.configureParameters(_) >> new DaemonParameters().setEnabled(false)
-
when:
def action = convert('args')
@@ -69,8 +72,6 @@ class BuildActionsFactoryTest extends Specification {
}
def "daemon is used when command line option is used"() {
- configurer.configureParameters(_) >> new DaemonParameters().setEnabled(false)
-
when:
def action = convert('--daemon', 'args')
@@ -78,19 +79,7 @@ class BuildActionsFactoryTest extends Specification {
isDaemon action
}
- def "daemon is used when daemon parameters say so"() {
- configurer.configureParameters(_) >> new DaemonParameters().setEnabled(true)
-
- when:
- def action = convert('args')
-
- then:
- isDaemon action
- }
-
def "does not use daemon when no-daemon command line option issued"() {
- configurer.configureParameters(_) >> new DaemonParameters().setEnabled(true)
-
when:
def action = convert('--no-daemon', 'args')
@@ -99,8 +88,6 @@ class BuildActionsFactoryTest extends Specification {
}
def "stops daemon"() {
- configurer.configureParameters(_) >> new DaemonParameters()
-
when:
def action = convert('--stop')
@@ -110,8 +97,6 @@ class BuildActionsFactoryTest extends Specification {
}
def "runs daemon in foreground"() {
- configurer.configureParameters(_) >> new DaemonParameters()
-
when:
def action = convert('--foreground')
@@ -124,7 +109,7 @@ class BuildActionsFactoryTest extends Specification {
given:
def javaHome = tmpDir.createDir("javahome")
javaHome.createFile(OperatingSystem.current().getExecutableName("bin/java"))
- configurer.configureParameters(_) >> new DaemonParameters().setJavaHome(javaHome.canonicalFile)
+ propertiesToDaemonParametersConverter.convert(_, _) >> { args -> args[1].javaHome = javaHome }
when:
def action = convert()
@@ -149,7 +134,7 @@ class BuildActionsFactoryTest extends Specification {
void isInProcess(def action) {
// Relying on impl of Actions.toAction(Runnable)
assert action.runnable instanceof RunBuildAction
- assert action.runnable.executer instanceof InProcessGradleLauncherActionExecuter
+ assert action.runnable.executer instanceof InProcessBuildActionExecuter
}
void isSingleUseDaemon(def action) {
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/launcher/cli/RunBuildActionTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/launcher/cli/RunBuildActionTest.groovy
index eca6cc0..93e275c 100644
--- a/subprojects/launcher/src/test/groovy/org/gradle/launcher/cli/RunBuildActionTest.groovy
+++ b/subprojects/launcher/src/test/groovy/org/gradle/launcher/cli/RunBuildActionTest.groovy
@@ -18,12 +18,12 @@ package org.gradle.launcher.cli
import org.gradle.StartParameter
import org.gradle.initialization.BuildClientMetaData
import org.gradle.launcher.exec.BuildActionParameters
-import org.gradle.launcher.exec.GradleLauncherActionExecuter
+import org.gradle.launcher.exec.BuildActionExecuter
import spock.lang.Specification
import org.gradle.api.logging.LogLevel
class RunBuildActionTest extends Specification {
- final GradleLauncherActionExecuter<BuildActionParameters> client = Mock()
+ final BuildActionExecuter<BuildActionParameters> client = Mock()
final StartParameter startParameter = Mock()
final BuildClientMetaData clientMetaData = Mock()
final File currentDir = new File('current-dir')
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/launcher/cli/converter/DaemonCommandLineConverterTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/launcher/cli/converter/DaemonCommandLineConverterTest.groovy
new file mode 100644
index 0000000..05873ef
--- /dev/null
+++ b/subprojects/launcher/src/test/groovy/org/gradle/launcher/cli/converter/DaemonCommandLineConverterTest.groovy
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.launcher.cli.converter
+
+import org.gradle.cli.CommandLineParser
+import org.gradle.launcher.daemon.configuration.DaemonParameters
+import spock.lang.Specification
+
+class DaemonCommandLineConverterTest extends Specification {
+
+ def "converts daemon options"() {
+ expect:
+ !convert([]).enabled
+ !convert(['--no-daemon']).enabled
+ convert(['--daemon']).enabled
+ convert(['--no-daemon', '--daemon']).enabled
+ }
+
+ private DaemonParameters convert(Iterable args) {
+ CommandLineParser parser = new CommandLineParser()
+ def converter = new DaemonCommandLineConverter()
+ converter.configure(parser)
+ converter.convert(args)
+ }
+}
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/launcher/cli/converter/LayoutToPropertiesConverterTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/launcher/cli/converter/LayoutToPropertiesConverterTest.groovy
new file mode 100644
index 0000000..4327a2f
--- /dev/null
+++ b/subprojects/launcher/src/test/groovy/org/gradle/launcher/cli/converter/LayoutToPropertiesConverterTest.groovy
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.launcher.cli.converter
+
+import org.gradle.initialization.BuildLayoutParameters
+import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
+import org.gradle.util.SetSystemProperties
+import org.junit.Rule
+import spock.lang.Specification
+
+import static org.gradle.launcher.daemon.configuration.GradleProperties.IDLE_TIMEOUT_PROPERTY
+import static org.gradle.launcher.daemon.configuration.GradleProperties.JVM_ARGS_PROPERTY
+
+class LayoutToPropertiesConverterTest extends Specification {
+
+ @Rule SetSystemProperties sysProperties = new SetSystemProperties()
+ @Rule TestNameTestDirectoryProvider temp = new TestNameTestDirectoryProvider()
+ def converter = new LayoutToPropertiesConverter()
+ BuildLayoutParameters layout
+ Map<String, String> props = new HashMap<String, String>()
+
+ def setup() {
+ layout = new BuildLayoutParameters()
+ .setGradleUserHomeDir(temp.createDir("gradleHome"))
+ .setProjectDir(temp.createDir("projectDir"))
+ .setSearchUpwards(false)
+ }
+
+ def "only configures gradle properties"() {
+ when:
+ temp.file("gradleHome/gradle.properties") << "foo=bar"
+
+ then:
+ converter.convert(layout, props).foo == null
+ }
+
+ def "configures from gradle home dir"() {
+ when:
+ temp.file("gradleHome/gradle.properties") << "$JVM_ARGS_PROPERTY=-Xmx1024m -Dprop=value"
+
+ then:
+ converter.convert(layout, props).get(JVM_ARGS_PROPERTY) == '-Xmx1024m -Dprop=value'
+ }
+
+ def "configures from project dir"() {
+ when:
+ temp.file("projectDir/gradle.properties") << "$IDLE_TIMEOUT_PROPERTY=125"
+
+ then:
+ converter.convert(layout, props).get(IDLE_TIMEOUT_PROPERTY) == "125"
+ }
+
+ def "configures from root dir in a multiproject build"() {
+ when:
+ temp.file("projectDir/settings.gradle") << "include 'foo'"
+ temp.file("projectDir/gradle.properties") << "$JVM_ARGS_PROPERTY=-Xmx128m"
+ layout.setProjectDir(temp.file("projectDir/foo"))
+ layout.searchUpwards = true
+
+ then:
+ converter.convert(layout, props).get(JVM_ARGS_PROPERTY) == '-Xmx128m'
+ }
+
+ def "gradle home properties take precedence over project dir properties"() {
+ when:
+ temp.file("gradleHome/gradle.properties") << "$JVM_ARGS_PROPERTY=-Xmx1024m"
+ temp.file("projectDir/gradle.properties") << "$JVM_ARGS_PROPERTY=-Xmx512m"
+
+ then:
+ converter.convert(layout, props).get(JVM_ARGS_PROPERTY) == '-Xmx1024m'
+ }
+
+ def "system property takes precedence over gradle home"() {
+ when:
+ temp.file("gradleHome/gradle.properties") << "$JVM_ARGS_PROPERTY=-Xmx1024m"
+ System.setProperty(JVM_ARGS_PROPERTY, '-Xmx2048m')
+
+ then:
+ converter.convert(layout, props).get(JVM_ARGS_PROPERTY) == '-Xmx2048m'
+ }
+}
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/launcher/cli/converter/PropertiesToDaemonParametersConverterTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/launcher/cli/converter/PropertiesToDaemonParametersConverterTest.groovy
new file mode 100644
index 0000000..ca449e7
--- /dev/null
+++ b/subprojects/launcher/src/test/groovy/org/gradle/launcher/cli/converter/PropertiesToDaemonParametersConverterTest.groovy
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.launcher.cli.converter
+
+import org.gradle.api.GradleException
+import org.gradle.initialization.BuildLayoutParameters
+import org.gradle.internal.jvm.Jvm
+import org.gradle.launcher.daemon.configuration.DaemonParameters
+import org.gradle.launcher.daemon.configuration.GradleProperties
+import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
+import org.junit.Rule
+import spock.lang.Specification
+
+import static org.gradle.launcher.daemon.configuration.GradleProperties.*
+
+class PropertiesToDaemonParametersConverterTest extends Specification {
+
+ @Rule TestNameTestDirectoryProvider temp = new TestNameTestDirectoryProvider()
+
+ def converter = new PropertiesToDaemonParametersConverter()
+ def params = new DaemonParameters(new BuildLayoutParameters())
+
+ def "can configure jvm args combined with a system property"() {
+ when:
+ converter.convert([(JVM_ARGS_PROPERTY): '-Xmx512m -Dprop=value'], params)
+
+ then:
+ params.effectiveJvmArgs.contains('-Xmx512m')
+ !params.effectiveJvmArgs.contains('-Dprop=value')
+
+ params.systemProperties == [prop: 'value']
+ }
+
+ def "supports 'empty' system properties"() {
+ when:
+ converter.convert([(JVM_ARGS_PROPERTY): "-Dfoo= -Dbar"], params)
+
+ then:
+ params.systemProperties == [foo: '', bar: '']
+ }
+
+ def "configures from gradle properties"() {
+ when:
+ converter.convert([
+ (JVM_ARGS_PROPERTY): '-Xmx256m',
+ (JAVA_HOME_PROPERTY): Jvm.current().javaHome.absolutePath,
+ (DAEMON_ENABLED_PROPERTY): "true",
+ (BASE_DIR_PROPERTY): new File("baseDir").absolutePath,
+ (IDLE_TIMEOUT_PROPERTY): "115",
+ (DEBUG_MODE_PROPERTY): "true",
+ ], params)
+
+ then:
+ params.effectiveJvmArgs.contains("-Xmx256m")
+ params.debug
+ params.effectiveJavaHome == Jvm.current().javaHome
+ params.enabled
+ params.baseDir == new File("baseDir").absoluteFile
+ params.idleTimeout == 115
+ }
+
+ def "shows nice message for dummy java home"() {
+ when:
+ converter.convert([(JAVA_HOME_PROPERTY) : "/invalid/path"], params)
+
+ then:
+ def ex = thrown(GradleException)
+ ex.message.contains 'org.gradle.java.home'
+ ex.message.contains '/invalid/path'
+ }
+
+ def "shows nice message for invalid java home"() {
+ def dummyDir = temp.createDir("foobar")
+ when:
+ converter.convert([(GradleProperties.JAVA_HOME_PROPERTY) : dummyDir.absolutePath], params)
+
+ then:
+ def ex = thrown(GradleException)
+ ex.message.contains 'org.gradle.java.home'
+ ex.message.contains 'foobar'
+ }
+
+ def "shows nice message for invalid idle timeout"() {
+ when:
+ converter.convert((GradleProperties.IDLE_TIMEOUT_PROPERTY): 'asdf', params)
+
+ then:
+ def ex = thrown(GradleException)
+ ex.message.contains 'org.gradle.daemon.idletimeout'
+ ex.message.contains 'asdf'
+ }
+}
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/launcher/cli/converter/PropertiesToStartParameterConverterTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/launcher/cli/converter/PropertiesToStartParameterConverterTest.groovy
new file mode 100644
index 0000000..5c93357
--- /dev/null
+++ b/subprojects/launcher/src/test/groovy/org/gradle/launcher/cli/converter/PropertiesToStartParameterConverterTest.groovy
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.launcher.cli.converter
+
+import org.gradle.StartParameter
+import spock.lang.Specification
+
+import static org.gradle.launcher.daemon.configuration.GradleProperties.CONFIGURE_ON_DEMAND_PROPERTY
+import static org.gradle.launcher.daemon.configuration.GradleProperties.PARALLEL_PROPERTY
+
+class PropertiesToStartParameterConverterTest extends Specification {
+
+ def converter = new PropertiesToStartParameterConverter()
+
+ def "converts"() {
+ expect:
+ converter.convert([(PARALLEL_PROPERTY): "true"], new StartParameter()).parallelThreadCount == -1
+ converter.convert([(PARALLEL_PROPERTY): "false"], new StartParameter()).parallelThreadCount == 0
+ converter.convert([(CONFIGURE_ON_DEMAND_PROPERTY): "TRUE"], new StartParameter()).configureOnDemand
+ !converter.convert([(CONFIGURE_ON_DEMAND_PROPERTY): "xxx"], new StartParameter()).configureOnDemand
+ }
+}
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/DaemonExecHandleBuilderSpec.groovy b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/DaemonExecHandleBuilderSpec.groovy
index 2fb3ff3..8303cb3 100644
--- a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/DaemonExecHandleBuilderSpec.groovy
+++ b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/DaemonExecHandleBuilderSpec.groovy
@@ -20,9 +20,6 @@ import org.gradle.launcher.daemon.bootstrap.DaemonOutputConsumer
import org.gradle.process.internal.ExecHandleBuilder
import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 5/7/12
- */
class DaemonExecHandleBuilderSpec extends Specification {
def builder = Mock(ExecHandleBuilder)
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/bootstrap/DaemonGreeterTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/bootstrap/DaemonGreeterTest.groovy
index 662ea81..686dd4a 100644
--- a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/bootstrap/DaemonGreeterTest.groovy
+++ b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/bootstrap/DaemonGreeterTest.groovy
@@ -22,9 +22,6 @@ import org.gradle.launcher.daemon.logging.DaemonMessages
import org.gradle.process.ExecResult
import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 4/10/12
- */
class DaemonGreeterTest extends Specification {
DocumentationRegistry registry = Mock()
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/bootstrap/DaemonOutputConsumerTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/bootstrap/DaemonOutputConsumerTest.groovy
index 15beb53..3ad3084 100644
--- a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/bootstrap/DaemonOutputConsumerTest.groovy
+++ b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/bootstrap/DaemonOutputConsumerTest.groovy
@@ -20,9 +20,6 @@ package org.gradle.launcher.daemon.bootstrap
import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 4/28/12
- */
class DaemonOutputConsumerTest extends Specification {
def consumer = new DaemonOutputConsumer()
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/bootstrap/DaemonStartupCommunicationSpec.groovy b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/bootstrap/DaemonStartupCommunicationSpec.groovy
index c9a682a..9afa0fc 100644
--- a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/bootstrap/DaemonStartupCommunicationSpec.groovy
+++ b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/bootstrap/DaemonStartupCommunicationSpec.groovy
@@ -18,9 +18,6 @@ package org.gradle.launcher.daemon.bootstrap
import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 4/10/12
- */
class DaemonStartupCommunicationSpec extends Specification {
def comm = new DaemonStartupCommunication()
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/client/DaemonClientConnectionTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/client/DaemonClientConnectionTest.groovy
index 75c177f..44f51c9 100644
--- a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/client/DaemonClientConnectionTest.groovy
+++ b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/client/DaemonClientConnectionTest.groovy
@@ -16,31 +16,29 @@
package org.gradle.launcher.daemon.client
-import org.gradle.api.GradleException
import org.gradle.messaging.remote.internal.Connection
import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 8/31/12
- */
class DaemonClientConnectionTest extends Specification {
final delegate = Mock(Connection)
- final onFailure = Mock(Runnable)
- final connection = new DaemonClientConnection(delegate, 'id', onFailure)
+ final staleAddressDetector = Mock(DaemonClientConnection.StaleAddressDetector)
+ final connection = new DaemonClientConnection(delegate, 'id', staleAddressDetector)
def "stops"() {
when:
connection.stop()
+
then:
1 * delegate.stop()
- 0 * onFailure.run()
+ 0 * staleAddressDetector._
when:
connection.requestStop()
+
then:
1 * delegate.requestStop()
- 0 * onFailure.run()
+ 0 * staleAddressDetector._
}
def "dispatches messages"() {
@@ -49,7 +47,7 @@ class DaemonClientConnectionTest extends Specification {
then:
1 * delegate.dispatch("foo")
- 0 * onFailure.run()
+ 0 * staleAddressDetector._
}
def "receives messages"() {
@@ -61,33 +59,75 @@ class DaemonClientConnectionTest extends Specification {
then:
"bar" == out
- 0 * onFailure.run()
+ 0 * staleAddressDetector._
}
- def "handles failed dispatch"() {
+ def "treats failure to dispatch before receiving as a stale address"() {
+ def failure = new FooException()
+
given:
- delegate.dispatch("foo") >> { throw new FooException() }
+ delegate.dispatch("foo") >> { throw failure }
when:
connection.dispatch("foo")
then:
- def ex = thrown(GradleException)
- ex.cause instanceof FooException
- 1 * onFailure.run()
+ def ex = thrown(StaleDaemonAddressException)
+ ex.cause == failure
+ 1 * staleAddressDetector.maybeStaleAddress(failure) >> true
+ 0 * staleAddressDetector._
+ }
+
+ def "handles failed dispatch"() {
+ def failure = new FooException()
+
+ given:
+ delegate.receive() >> "result"
+ delegate.dispatch("broken") >> { throw failure }
+
+ when:
+ connection.receive()
+ connection.dispatch("broken")
+
+ then:
+ def ex = thrown(DaemonConnectionException)
+ ex.class == DaemonConnectionException
+ ex.cause == failure
+ 0 * staleAddressDetector._
+ }
+
+ def "treats failure to receive first message as a stale address"() {
+ def failure = new FooException()
+
+ given:
+ delegate.receive() >> { throw failure }
+
+ when:
+ connection.receive()
+
+ then:
+ def ex = thrown(StaleDaemonAddressException)
+ ex.cause == failure
+ 1 * staleAddressDetector.maybeStaleAddress(failure) >> true
+ 0 * staleAddressDetector._
}
def "handles failed receive"() {
+ def failure = new FooException()
+
given:
- delegate.receive() >> { throw new FooException() }
+ 1 * delegate.receive() >> "first"
+ delegate.receive() >> { throw failure }
when:
connection.receive()
+ connection.receive()
then:
- def ex = thrown(GradleException)
- ex.cause instanceof FooException
- 1 * onFailure.run()
+ def ex = thrown(DaemonConnectionException)
+ ex.class == DaemonConnectionException
+ ex.cause == failure
+ 0 * staleAddressDetector._
}
class FooException extends RuntimeException {}
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/client/DaemonClientServicesTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/client/DaemonClientServicesTest.groovy
index 101a226..b693af5 100644
--- a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/client/DaemonClientServicesTest.groovy
+++ b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/client/DaemonClientServicesTest.groovy
@@ -22,10 +22,11 @@ import org.gradle.logging.LoggingServiceRegistry
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
import org.junit.Rule
import spock.lang.Specification
+import org.gradle.initialization.BuildLayoutParameters
class DaemonClientServicesTest extends Specification {
@Rule TestNameTestDirectoryProvider tmp = new TestNameTestDirectoryProvider()
- final DaemonParameters parameters = new DaemonParameters(baseDir: tmp.testDirectory)
+ final DaemonParameters parameters = new DaemonParameters(new BuildLayoutParameters()).setBaseDir(tmp.testDirectory)
final DaemonClientServices services = new DaemonClientServices(LoggingServiceRegistry.newEmbeddableLogging(), parameters, System.in)
def "makes a DaemonRegistry available"() {
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/client/DaemonClientTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/client/DaemonClientTest.groovy
index 2536cd7..256437c 100644
--- a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/client/DaemonClientTest.groovy
+++ b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/client/DaemonClientTest.groovy
@@ -15,7 +15,7 @@
*/
package org.gradle.launcher.daemon.client
-import org.gradle.initialization.GradleLauncherAction
+import org.gradle.initialization.BuildAction
import org.gradle.internal.id.IdGenerator
import org.gradle.launcher.daemon.context.DaemonCompatibilitySpec
import org.gradle.launcher.exec.BuildActionParameters
@@ -91,7 +91,7 @@ class DaemonClientTest extends ConcurrentSpecification {
def executesAction() {
when:
- def result = client.execute(Stub(GradleLauncherAction), Stub(BuildActionParameters))
+ def result = client.execute(Stub(BuildAction), Stub(BuildActionParameters))
then:
result == '[result]'
@@ -108,7 +108,7 @@ class DaemonClientTest extends ConcurrentSpecification {
RuntimeException failure = new RuntimeException()
when:
- client.execute(Stub(GradleLauncherAction), Stub(BuildActionParameters))
+ client.execute(Stub(BuildAction), Stub(BuildActionParameters))
then:
RuntimeException e = thrown()
@@ -122,15 +122,15 @@ class DaemonClientTest extends ConcurrentSpecification {
0 * _
}
- def "tries to find a different daemon if getting the first result from the daemon fails"() {
+ def "tries to find a different daemon if connected to a stale daemon address"() {
DaemonClientConnection connection2 = Mock()
when:
- client.execute(Stub(GradleLauncherAction), Stub(BuildActionParameters))
+ client.execute(Stub(BuildAction), Stub(BuildActionParameters))
then:
2 * connector.connect(compatibilitySpec) >>> [connection, connection2]
- 1 * connection.dispatch({it instanceof Build}) >> { throw new RuntimeException("Boo!")}
+ 1 * connection.dispatch({it instanceof Build}) >> { throw new StaleDaemonAddressException("broken", new RuntimeException())}
1 * connection.stop()
2 * connection2.receive() >>> [Stub(BuildStarted), new Success('')]
0 * connection._
@@ -140,7 +140,7 @@ class DaemonClientTest extends ConcurrentSpecification {
DaemonClientConnection connection2 = Mock()
when:
- client.execute(Stub(GradleLauncherAction), Stub(BuildActionParameters))
+ client.execute(Stub(BuildAction), Stub(BuildActionParameters))
then:
2 * connector.connect(compatibilitySpec) >>> [connection, connection2]
@@ -156,7 +156,7 @@ class DaemonClientTest extends ConcurrentSpecification {
DaemonClientConnection connection2 = Mock()
when:
- client.execute(Stub(GradleLauncherAction), Stub(BuildActionParameters))
+ client.execute(Stub(BuildAction), Stub(BuildActionParameters))
then:
2 * connector.connect(compatibilitySpec) >>> [connection, connection2]
@@ -173,7 +173,7 @@ class DaemonClientTest extends ConcurrentSpecification {
connection.receive() >> Mock(DaemonUnavailable)
when:
- client.execute(Stub(GradleLauncherAction), Stub(BuildActionParameters))
+ client.execute(Stub(BuildAction), Stub(BuildActionParameters))
then:
thrown(NoUsableDaemonFoundException)
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/client/DefaultDaemonConnectorTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/client/DefaultDaemonConnectorTest.groovy
index 708e958..66edd06 100644
--- a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/client/DefaultDaemonConnectorTest.groovy
+++ b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/client/DefaultDaemonConnectorTest.groovy
@@ -15,7 +15,6 @@
*/
package org.gradle.launcher.daemon.client
-import org.gradle.api.GradleException
import org.gradle.api.internal.specs.ExplainingSpec
import org.gradle.api.internal.specs.ExplainingSpecs
import org.gradle.launcher.daemon.context.DaemonContext
@@ -84,7 +83,7 @@ class DefaultDaemonConnectorTest extends Specification {
def theConnector
- def getConnector() {
+ def DefaultDaemonConnector getConnector() {
if (theConnector == null) {
theConnector = createConnector()
}
@@ -115,22 +114,6 @@ class DefaultDaemonConnectorTest extends Specification {
connection && connection.connection.num < 12
}
- def "suspect address is removed from the registry on connect failure"() {
- given:
- startIdleDaemon()
- assert !registry.all.empty
-
- connector.connector.connect(_ as Address, _) >> { throw new ConnectException("Problem!", new RuntimeException("foo")) }
-
- when:
- def connection = connector.maybeConnect( { true } as ExplainingSpec)
-
- then:
- !connection
-
- registry.all.empty
- }
-
def "maybeConnect() returns null when no daemon matches spec"() {
given:
startIdleDaemon()
@@ -192,6 +175,22 @@ class DefaultDaemonConnectorTest extends Specification {
connector.connect(ExplainingSpecs.satisfyNone())
then:
- thrown(GradleException)
+ thrown(DaemonConnectionException)
+ }
+
+ def "suspect address is removed from the registry on connect failure"() {
+ given:
+ startIdleDaemon()
+ assert !registry.all.empty
+
+ connector.connector.connect(_ as Address, _) >> { throw new ConnectException("Problem!", new RuntimeException("foo")) }
+
+ when:
+ def connection = connector.maybeConnect( { true } as ExplainingSpec)
+
+ then:
+ !connection
+
+ registry.all.empty
}
}
\ No newline at end of file
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/client/StopDispatcherTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/client/StopDispatcherTest.groovy
index 86e9412..180e0cd 100644
--- a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/client/StopDispatcherTest.groovy
+++ b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/client/StopDispatcherTest.groovy
@@ -16,13 +16,10 @@
package org.gradle.launcher.daemon.client
-import org.gradle.messaging.remote.internal.Connection
import org.gradle.internal.id.IdGenerator
+import org.gradle.messaging.remote.internal.Connection
import spock.lang.Specification
-/**
- * @author: Szczepan Faber, created at: 9/13/11
- */
public class StopDispatcherTest extends Specification {
def dispatcher = new StopDispatcher({12} as IdGenerator)
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/configuration/CurrentProcessTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/configuration/CurrentProcessTest.groovy
index 3e6089e..8f8f529 100644
--- a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/configuration/CurrentProcessTest.groovy
+++ b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/configuration/CurrentProcessTest.groovy
@@ -22,6 +22,7 @@ import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
import org.gradle.util.SetSystemProperties
import org.junit.Rule
import spock.lang.Specification
+import org.gradle.initialization.BuildLayoutParameters
public class CurrentProcessTest extends Specification {
@Rule final TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider()
@@ -29,7 +30,7 @@ public class CurrentProcessTest extends Specification {
private FileResolver fileResolver = Mock()
private def currentJavaHome = tmpDir.file('java_home')
private JvmOptions currentJvmOptions = new JvmOptions(fileResolver)
- private DaemonParameters parameters = new DaemonParameters()
+ private DaemonParameters parameters = new DaemonParameters(new BuildLayoutParameters())
def "can only run build with identical java home"() {
when:
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/configuration/DaemonParametersTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/configuration/DaemonParametersTest.groovy
index e89cc05..be8f20b 100644
--- a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/configuration/DaemonParametersTest.groovy
+++ b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/configuration/DaemonParametersTest.groovy
@@ -16,13 +16,13 @@
package org.gradle.launcher.daemon.configuration
import org.gradle.StartParameter
-import org.gradle.internal.jvm.Jvm
+import org.gradle.initialization.BuildLayoutParameters
import spock.lang.Specification
import static java.lang.Boolean.parseBoolean
class DaemonParametersTest extends Specification {
- final DaemonParameters parameters = new DaemonParameters()
+ final DaemonParameters parameters = new DaemonParameters(new BuildLayoutParameters())
def "has reasonable default values"() {
expect:
@@ -31,7 +31,6 @@ class DaemonParametersTest extends Specification {
def "uses default values when no specific gradle properties provided"() {
expect:
- parameters.configureFrom(new GradleProperties()) //empty gradle properties
assertDefaultValues()
}
@@ -49,38 +48,13 @@ class DaemonParametersTest extends Specification {
def "configuring jvmargs replaces the defaults"() {
when:
- parameters.configureFrom(Stub(GradleProperties) {
- getJvmArgs() >> "-Xmx17m"
- })
+ parameters.setJvmArgs(["-Xmx17m"])
then:
parameters.effectiveJvmArgs.each { assert !parameters.defaultJvmArgs.contains(it) }
}
- def "can configure jvm args combined with a system property"() {
- when:
- parameters.configureFrom(Stub(GradleProperties) {
- getJvmArgs() >> '-Xmx1024m -Dprop=value'
- })
-
- then:
- parameters.effectiveJvmArgs.contains('-Xmx1024m')
- !parameters.effectiveJvmArgs.contains('-Dprop=value')
-
- parameters.systemProperties == [prop: 'value']
- }
-
- def "supports 'empty' system properties"() {
- when:
- parameters.configureFrom(Stub(GradleProperties) {
- getJvmArgs() >> "-Dfoo= -Dbar"
- })
-
- then:
- parameters.getSystemProperties() == [foo: '', bar: '']
- }
-
- def "knows if not using default jvm args"() {
+ def "knows if uses default jvm args"() {
given:
assert parameters.usingDefaultJvmArgs
@@ -91,35 +65,9 @@ class DaemonParametersTest extends Specification {
!parameters.usingDefaultJvmArgs
}
- def "knows if not using default jvm args when configured"() {
- given:
- assert parameters.usingDefaultJvmArgs
-
- when:
- parameters.configureFrom(Stub(GradleProperties) {
- getJvmArgs() >> "-Dfoo= -Dbar"
- })
-
- then:
- !parameters.usingDefaultJvmArgs
- }
-
- def "knows if using default jvm args"() {
- when:
- parameters.configureFrom(Stub(GradleProperties) {
- getJavaHome() >> Jvm.current().getJavaHome()
- getJvmArgs() >> null
- })
-
- then:
- parameters.usingDefaultJvmArgs
- }
-
def "can configure debug mode"() {
when:
- parameters.configureFrom(Stub (GradleProperties) {
- isDebugMode() >> parseBoolean(flag)
- })
+ parameters.setDebug(parseBoolean(flag))
then:
parameters.effectiveJvmArgs.contains("-Xdebug") == parseBoolean(flag)
@@ -128,24 +76,4 @@ class DaemonParametersTest extends Specification {
where:
flag << ["true", "false"]
}
-
- def "configures from gradle properties"() {
- def props = Stub (GradleProperties) {
- getJvmArgs() >> '-Xmx256m'
- getJavaHome() >> new File("javaHome")
- isDaemonEnabled() >> true
- getDaemonBaseDir() >> new File("baseDir")
- getIdleTimeout() >> 115
- }
-
- when:
- parameters.configureFrom(props)
-
- then:
- parameters.effectiveJvmArgs.contains("-Xmx256m")
- parameters.javaHome == new File("javaHome")
- parameters.enabled
- parameters.baseDir == new File("baseDir")
- parameters.idleTimeout == 115
- }
}
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/configuration/GradlePropertiesConfigurerTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/configuration/GradlePropertiesConfigurerTest.groovy
deleted file mode 100644
index 51d4892..0000000
--- a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/configuration/GradlePropertiesConfigurerTest.groovy
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright 2013 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.launcher.daemon.configuration
-
-import org.gradle.StartParameter
-import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
-import org.junit.Rule
-import spock.lang.Specification
-
-import static java.util.Collections.singletonMap
-
-/**
- * by Szczepan Faber, created at: 1/22/13
- */
-class GradlePropertiesConfigurerTest extends Specification {
-
- @Rule private TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider()
- private configurer = Spy(GradlePropertiesConfigurer)
-
- def "prepares properties and configures parameters"() {
- def param = Mock(StartParameter)
- def properties = Mock(GradleProperties)
-
- configurer.prepareProperties(_, false, _, _) >> properties
-
- when:
- def daemonParams = configurer.configureParameters(param);
-
- then:
- //daemon params created
- daemonParams
- //start parameter updated
- 1 * properties.updateStartParameter(param)
- //daemon params configured from properties
- properties.getIdleTimeout() >> 123
- daemonParams.idleTimeout == 123
- }
-
- def "gradle home properties take precedence over project dir properties"() {
- def projectDir = tmpDir.createDir("project")
- projectDir.file("gradle.properties") << "$GradleProperties.IDLE_TIMEOUT_PROPERTY=100"
- def gradleHome = tmpDir.createDir("gradleHome")
- gradleHome.file("gradle.properties") << "$GradleProperties.IDLE_TIMEOUT_PROPERTY=200"
-
- when:
- def props = configurer.prepareProperties(projectDir, false, gradleHome, [:])
-
- then:
- props.idleTimeout == 200
- }
-
- def "system property takes precedence over gradle home"() {
- def projectDir = tmpDir.createDir("project")
- def gradleHome = tmpDir.createDir("gradleHome")
- gradleHome.file("gradle.properties") << "$GradleProperties.IDLE_TIMEOUT_PROPERTY=200"
-
- when:
- def props = configurer.prepareProperties(projectDir, false, gradleHome, singletonMap(GradleProperties.IDLE_TIMEOUT_PROPERTY, '300'))
-
- then:
- props.idleTimeout == 300
- }
-}
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/configuration/GradlePropertiesTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/configuration/GradlePropertiesTest.groovy
deleted file mode 100644
index 0b8b1aa..0000000
--- a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/configuration/GradlePropertiesTest.groovy
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright 2013 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.launcher.daemon.configuration
-
-import org.gradle.api.GradleException
-import org.gradle.internal.jvm.Jvm
-import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
-import org.junit.Rule
-import spock.lang.Specification
-import org.gradle.StartParameter
-
-/**
- * by Szczepan Faber, created at: 1/22/13
- */
-class GradlePropertiesTest extends Specification {
-
- @Rule final TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider()
- private properties = new GradleProperties()
-
- def "configures from gradle home dir (using jvm args as example)"() {
- given:
- tmpDir.file("gradle.properties").withOutputStream { outstr ->
- new Properties((GradleProperties.JVM_ARGS_PROPERTY): '-Xmx1024m -Dprop=value').store(outstr, "HEADER")
- }
-
- when:
- properties.configureFromGradleUserHome(tmpDir.testDirectory)
-
- then:
- properties.jvmArgs == '-Xmx1024m -Dprop=value'
- }
-
- def "configures from project dir (using jvm args as example)"() {
- given:
- tmpDir.createFile("settings.gradle")
- tmpDir.file("gradle.properties").withOutputStream { outstr ->
- new Properties((GradleProperties.JVM_ARGS_PROPERTY): '-Xmx1024m -Dprop=value').store(outstr, "HEADER")
- }
-
- when:
- properties.configureFromBuildDir(tmpDir.testDirectory, true)
-
- then:
- properties.jvmArgs == '-Xmx1024m -Dprop=value'
- }
-
- def "configures from system properties (using jvm args as example)"() {
- when:
- properties.configureFromSystemProperties((GradleProperties.JVM_ARGS_PROPERTY): '-Xmx1024m -Dprop=value')
-
- then:
- properties.jvmArgs == '-Xmx1024m -Dprop=value'
- }
-
- def "sets default daemon base dir when configuring from gradle user home"() {
- def userHome = new File("some-dir")
-
- when:
- properties.configureFromGradleUserHome(userHome)
-
- then:
- properties.daemonBaseDir == new File(userHome, "daemon").canonicalFile
- }
-
- def "configures daemon base dir when configuring from system properties"() {
- when:
- properties.configureFromSystemProperties((GradleProperties.BASE_DIR_PROPERTY): 'some-dir')
-
- then:
- properties.daemonBaseDir == new File('some-dir').canonicalFile
- }
-
- def "configures idle timeout"() {
- when:
- properties.configureFrom((GradleProperties.IDLE_TIMEOUT_PROPERTY): '4000')
-
- then:
- properties.idleTimeout == 4000
- }
-
- def "shows nice message for invalid idle timeout"() {
- when:
- properties.configureFrom((GradleProperties.IDLE_TIMEOUT_PROPERTY): 'asdf')
-
- then:
- def ex = thrown(GradleException)
- ex.message.contains 'org.gradle.daemon.idletimeout'
- ex.message.contains 'asdf'
- }
-
- def "configures daemon mode"() {
- when:
- properties.configureFrom((GradleProperties.DAEMON_ENABLED_PROPERTY): flag)
-
- then:
- properties.daemonEnabled.toString() == flag
-
- where:
- flag << ["true", "false"]
- }
-
- def "configures java home"() {
- File jdk = Jvm.current().getJavaHome()
-
- when:
- properties.configureFrom([(GradleProperties.JAVA_HOME_PROPERTY) : jdk.toString()])
-
- then:
- properties.javaHome == jdk.canonicalFile
- }
-
- def "shows nice message for dummy java home"() {
- when:
- properties.configureFrom([(GradleProperties.JAVA_HOME_PROPERTY) : "/invalid/path"])
-
- then:
- def ex = thrown(GradleException)
- ex.message.contains 'org.gradle.java.home'
- ex.message.contains '/invalid/path'
- }
-
- def "shows nice message for invalid java home"() {
- def dummyDir = tmpDir.createDir("foobar")
- when:
- properties.configureFrom([(GradleProperties.JAVA_HOME_PROPERTY) : dummyDir.absolutePath])
-
- then:
- def ex = thrown(GradleException)
- ex.message.contains 'org.gradle.java.home'
- ex.message.contains 'foobar'
- }
-
- def "configures debug mode"() {
- when:
- properties.configureFrom((GradleProperties.DEBUG_MODE_PROPERTY): flag)
-
- then:
- properties.debugMode.toString() == flag
-
- where:
- flag << ["true", "false"]
- }
-
- def "configures parallel mode"() {
- when:
- properties.configureFrom((GradleProperties.PARALLEL_PROPERTY): flag)
-
- then:
- properties.parallelMode.toString() == flag
-
- where:
- flag << ["true", "false"]
- }
-
- def "informs start parameter about configure on demand"() {
- def param = Mock(StartParameter)
-
- when:
- properties.updateStartParameter(param)
-
- then:
- 0 * param._
-
- when:
- properties.configureOnDemand = true
- properties.updateStartParameter(param)
-
- then:
- 1 * param.setConfigureOnDemand(true)
- 0 * _
- }
-
- def "informs start parameter about parallel mode"() {
- def param = Mock(StartParameter)
-
- when:
- properties.updateStartParameter(param)
-
- then:
- 0 * param._
-
- when:
- properties.parallelMode = true
- properties.updateStartParameter(param)
-
- then:
- 1 * param.setParallelThreadCount(-1)
- }
-
- def "does not set parallel mode when it was already configured even parallel mode is requested"() {
- def param = Mock(StartParameter) {
- isParallelThreadCountConfigured() >> true
- }
-
- when:
- properties.parallelMode = true //requested
- properties.updateStartParameter(param)
-
- then:
- 0 * param.setParallelThreadCount(_)
- }
-}
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/diagnostics/DaemonDiagnosticsTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/diagnostics/DaemonDiagnosticsTest.groovy
index 1a9c3a3..9346c82 100644
--- a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/diagnostics/DaemonDiagnosticsTest.groovy
+++ b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/diagnostics/DaemonDiagnosticsTest.groovy
@@ -20,9 +20,6 @@ import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
import org.junit.Rule
import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 4/10/12
- */
class DaemonDiagnosticsTest extends Specification {
@Rule TestNameTestDirectoryProvider temp
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/registry/DomainRegistryUpdaterTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/registry/DomainRegistryUpdaterTest.groovy
index 0e7be47..63cf3a9 100644
--- a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/registry/DomainRegistryUpdaterTest.groovy
+++ b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/registry/DomainRegistryUpdaterTest.groovy
@@ -22,9 +22,6 @@ import org.gradle.launcher.daemon.server.DomainRegistryUpdater
import org.gradle.messaging.remote.Address
import spock.lang.Specification
-/**
- * @author: Szczepan Faber, created at: 9/12/11
- */
public class DomainRegistryUpdaterTest extends Specification {
final DaemonRegistry registry = Mock()
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/registry/PersistentDaemonRegistryTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/registry/PersistentDaemonRegistryTest.groovy
index 449e3dd..49d0d25 100644
--- a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/registry/PersistentDaemonRegistryTest.groovy
+++ b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/registry/PersistentDaemonRegistryTest.groovy
@@ -29,17 +29,15 @@ import static org.gradle.cache.internal.DefaultFileLockManagerTestHelper.unlockU
class PersistentDaemonRegistryTest extends Specification {
- @Rule TestNameTestDirectoryProvider tmp
+ @Rule TestNameTestDirectoryProvider tmp = new TestNameTestDirectoryProvider()
int addressCounter = 0
def lockManager = createDefaultFileLockManager()
+ def file = tmp.file("registry")
+ def registry = new PersistentDaemonRegistry(file, lockManager)
def "corrupt registry file is ignored"() {
given:
- def file = tmp.file("registry")
- def registry = new PersistentDaemonRegistry(file, lockManager)
-
- and:
registry.store(address(), daemonContext(), "password", true)
expect:
@@ -54,7 +52,6 @@ class PersistentDaemonRegistryTest extends Specification {
def "safely removes from registry file"() {
given:
- def registry = new PersistentDaemonRegistry(tmp.file("registry"), lockManager)
def address = address()
and:
@@ -72,7 +69,6 @@ class PersistentDaemonRegistryTest extends Specification {
def "safely removes if registry empty"() {
given:
- def registry = new PersistentDaemonRegistry(tmp.file("registry"), lockManager)
def address = address()
when:
@@ -81,7 +77,29 @@ class PersistentDaemonRegistryTest extends Specification {
then:
registry.all.empty
}
-
+
+ def "mark busy ignores entry that has been removed"() {
+ given:
+ def address = address()
+
+ when:
+ registry.markBusy(address)
+
+ then:
+ registry.all.empty
+ }
+
+ def "mark idle ignores entry that has been removed"() {
+ given:
+ def address = address()
+
+ when:
+ registry.markIdle(address)
+
+ then:
+ registry.all.empty
+ }
+
DaemonContext daemonContext() {
new DaemonContextBuilder([maybeGetPid: {null}] as ProcessEnvironment).with {
daemonRegistryDir = tmp.createDir("daemons")
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/DaemonServerExceptionHandlingTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/DaemonServerExceptionHandlingTest.groovy
index 924b9e1..bd18874 100644
--- a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/DaemonServerExceptionHandlingTest.groovy
+++ b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/DaemonServerExceptionHandlingTest.groovy
@@ -16,12 +16,11 @@
package org.gradle.launcher.daemon.server
-import org.gradle.BuildResult
-import org.gradle.GradleLauncher
import org.gradle.api.logging.LogLevel
import org.gradle.configuration.GradleLauncherMetaData
-import org.gradle.initialization.DefaultGradleLauncherFactory
-import org.gradle.initialization.GradleLauncherAction
+import org.gradle.initialization.BuildAction
+import org.gradle.initialization.BuildController
+import org.gradle.initialization.GradleLauncherFactory
import org.gradle.internal.nativeplatform.ProcessEnvironment
import org.gradle.launcher.daemon.client.DaemonClient
import org.gradle.launcher.daemon.client.EmbeddedDaemonClientServices
@@ -36,18 +35,14 @@ import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
import org.junit.Rule
import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 12/21/11
- */
class DaemonServerExceptionHandlingTest extends Specification {
@Rule TestNameTestDirectoryProvider temp = new TestNameTestDirectoryProvider()
def parameters = new DefaultBuildActionParameters(new GradleLauncherMetaData(), 0, new HashMap(System.properties), [:], temp.testDirectory, LogLevel.ERROR)
- static class DummyLauncherAction implements GradleLauncherAction, Serializable {
+ static class DummyLauncherAction implements BuildAction, Serializable {
Object someState
- Object getResult() { null }
- BuildResult run(GradleLauncher launcher) { null }
+ Object run(BuildController buildController) { null }
}
def "sends back failure when the daemon cannot receive the first command"() {
@@ -73,7 +68,7 @@ class DaemonServerExceptionHandlingTest extends Specification {
//we need to override some methods to inject a failure action into the sequence
def services = new EmbeddedDaemonClientServices() {
DaemonCommandExecuter createDaemonCommandExecuter() {
- return new DefaultDaemonCommandExecuter(new DefaultGradleLauncherFactory(loggingServices),
+ return new DefaultDaemonCommandExecuter(get(GradleLauncherFactory),
get(ProcessEnvironment), loggingServices.getFactory(LoggingManagerInternal.class).create(), new File("dummy")) {
List<DaemonCommandAction> createActions(DaemonContext daemonContext) {
def actions = new LinkedList(super.createActions(daemonContext));
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/DaemonStateCoordinatorTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/DaemonStateCoordinatorTest.groovy
index 1c92c0d..bf0b2db 100644
--- a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/DaemonStateCoordinatorTest.groovy
+++ b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/DaemonStateCoordinatorTest.groovy
@@ -19,9 +19,6 @@ import org.gradle.launcher.daemon.server.exec.DaemonUnavailableException
import spock.lang.Specification
import java.util.concurrent.TimeUnit
-/**
- * by Szczepan Faber, created at: 2/6/12
- */
class DaemonStateCoordinatorTest extends Specification {
final Runnable onStartCommand = Mock(Runnable)
final Runnable onFinishCommand = Mock(Runnable)
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/launcher/exec/DefaultBuildActionParametersTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/launcher/exec/DefaultBuildActionParametersTest.groovy
index aba09df..6d55dca 100644
--- a/subprojects/launcher/src/test/groovy/org/gradle/launcher/exec/DefaultBuildActionParametersTest.groovy
+++ b/subprojects/launcher/src/test/groovy/org/gradle/launcher/exec/DefaultBuildActionParametersTest.groovy
@@ -14,16 +14,12 @@
* limitations under the License.
*/
-package org.gradle.launcher.exec;
-
+package org.gradle.launcher.exec
+import org.gradle.api.logging.LogLevel
import org.gradle.configuration.GradleLauncherMetaData
import spock.lang.Specification
-import org.gradle.api.logging.LogLevel
-/**
- * @author: Szczepan Faber, created at: 9/6/11
- */
public class DefaultBuildActionParametersTest extends Specification {
def "is serializable"() {
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/launcher/exec/InProcessBuildActionExecuterTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/launcher/exec/InProcessBuildActionExecuterTest.groovy
new file mode 100644
index 0000000..a3768a3
--- /dev/null
+++ b/subprojects/launcher/src/test/groovy/org/gradle/launcher/exec/InProcessBuildActionExecuterTest.groovy
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.launcher.exec
+
+import org.gradle.initialization.BuildController
+import spock.lang.Specification
+import org.gradle.initialization.GradleLauncherFactory
+import org.gradle.initialization.BuildAction
+
+import org.gradle.initialization.BuildRequestMetaData
+import org.gradle.GradleLauncher
+import org.gradle.BuildResult
+
+import org.gradle.StartParameter
+
+class InProcessBuildActionExecuterTest extends Specification {
+ final GradleLauncherFactory factory = Mock()
+ final GradleLauncher launcher = Mock()
+ final BuildActionParameters param = Mock()
+ final BuildRequestMetaData metaData = Mock()
+ final BuildResult buildResult = Mock()
+ final InProcessBuildActionExecuter executer = new InProcessBuildActionExecuter(factory)
+
+ def setup() {
+ _ * param.buildRequestMetaData >> metaData
+ }
+
+ def "creates a launcher using a default StartParameter when the action does not specify any"() {
+ BuildAction<String> action = Mock()
+
+ when:
+ def result = executer.execute(action, param)
+
+ then:
+ result == '<result>'
+
+ and:
+ 1 * factory.newInstance(!null, metaData) >> launcher
+ 1 * action.run(!null) >> { BuildController controller ->
+ assert controller.launcher == launcher
+ return '<result>'
+ }
+ }
+
+ def "creates a launcher using StartParameter specified by the action"() {
+ BuildAction<String> action = Mock()
+ def startParam = new StartParameter()
+
+ when:
+ def result = executer.execute(action, param)
+
+ then:
+ result == '<result>'
+
+ and:
+ 1 * factory.newInstance(startParam, metaData) >> launcher
+ 1 * action.run(!null) >> { BuildController controller ->
+ controller.startParameter = startParam
+ assert controller.launcher == launcher
+ return '<result>'
+ }
+ }
+
+ def "cannot set start parameters after launcher created"() {
+ BuildAction<String> action = Mock()
+ def startParam = new StartParameter()
+
+ given:
+ _ * action.run(!null) >> { BuildController controller ->
+ controller.launcher
+ controller.startParameter = startParam
+ }
+ _ * factory.newInstance(!null, metaData) >> launcher
+
+ when:
+ executer.execute(action, param)
+
+ then:
+ IllegalStateException e = thrown()
+ e.message == 'Cannot change start parameter after launcher has been created.'
+ }
+
+ def "runs build when requested by action"() {
+ BuildAction<String> action = Mock()
+
+ when:
+ def result = executer.execute(action, param)
+
+ then:
+ result == '<result>'
+
+ and:
+ 1 * factory.newInstance(!null, metaData) >> launcher
+ 1 * launcher.run() >> buildResult
+ _ * buildResult.failure >> null
+ 1 * action.run(!null) >> { BuildController controller ->
+ controller.run()
+ return '<result>'
+ }
+ }
+
+ def "configures build when requested by action"() {
+ BuildAction<String> action = Mock()
+
+ when:
+ def result = executer.execute(action, param)
+
+ then:
+ result == '<result>'
+
+ and:
+ 1 * factory.newInstance(!null, metaData) >> launcher
+ 1 * launcher.getBuildAnalysis() >> buildResult
+ _ * buildResult.failure >> null
+ 1 * action.run(!null) >> { BuildController controller ->
+ controller.configure()
+ return '<result>'
+ }
+ }
+
+ def "wraps build failure"() {
+ def failure = new RuntimeException()
+ BuildAction<String> action = Mock()
+
+ given:
+ buildResult.failure >> failure
+
+ when:
+ executer.execute(action, param)
+
+ then:
+ ReportedException e = thrown()
+ e.cause == failure
+
+ and:
+ 1 * factory.newInstance(!null, metaData) >> launcher
+ 1 * launcher.run() >> buildResult
+ 1 * action.run(!null) >> { BuildController controller ->
+ controller.run()
+ }
+ }
+}
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/launcher/exec/InProcessGradleLauncherActionExecuterTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/launcher/exec/InProcessGradleLauncherActionExecuterTest.groovy
deleted file mode 100644
index 3193438..0000000
--- a/subprojects/launcher/src/test/groovy/org/gradle/launcher/exec/InProcessGradleLauncherActionExecuterTest.groovy
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.launcher.exec
-
-import spock.lang.Specification
-import org.gradle.initialization.GradleLauncherFactory
-import org.gradle.initialization.GradleLauncherAction
-
-import org.gradle.initialization.BuildRequestMetaData
-import org.gradle.GradleLauncher
-import org.gradle.BuildResult
-
-import org.gradle.StartParameter
-
-class InProcessGradleLauncherActionExecuterTest extends Specification {
- final GradleLauncherFactory factory = Mock()
- final GradleLauncher launcher = Mock()
- final BuildActionParameters param = Mock()
- final BuildRequestMetaData metaData = Mock()
- final BuildResult buildResult = Mock()
- final InProcessGradleLauncherActionExecuter executer = new InProcessGradleLauncherActionExecuter(factory)
-
- def setup() {
- _ * param.buildRequestMetaData >> metaData
- }
-
- def "executes the provided action using a default StartParameter"() {
- GradleLauncherAction<String> action = Mock()
-
- given:
- buildResult.failure >> null
- action.result >> '<result>'
-
- when:
- def result = executer.execute(action, param)
-
- then:
- result == '<result>'
-
- and:
- 1 * factory.newInstance(!null, metaData) >> launcher
- 1 * action.run(launcher) >> buildResult
- }
-
- def "executes the provided action using the provided StartParameter"() {
- TestAction action = Mock()
- def startParam = new StartParameter()
-
- given:
- action.configureStartParameter() >> startParam
- buildResult.failure >> null
- action.result >> '<result>'
-
- when:
- def result = executer.execute(action, param)
-
- then:
- result == '<result>'
-
- and:
- 1 * factory.newInstance(startParam, metaData) >> launcher
- 1 * action.run(launcher) >> buildResult
- }
-
- def "wraps build failure"() {
- def failure = new RuntimeException()
- GradleLauncherAction<String> action = Mock()
-
- given:
- buildResult.failure >> failure
-
- when:
- executer.execute(action, param)
-
- then:
- ReportedException e = thrown()
- e.cause == failure
-
- and:
- 1 * factory.newInstance(!null, metaData) >> launcher
- 1 * action.run(launcher) >> buildResult
- }
-}
-
-interface TestAction extends GradleLauncherAction<String>, InitializationAware {
-}
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/AbstractClassGraphSpec.groovy b/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/AbstractClassGraphSpec.groovy
new file mode 100644
index 0000000..246d80b
--- /dev/null
+++ b/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/AbstractClassGraphSpec.groovy
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.provider
+
+import org.gradle.internal.classloader.ClasspathUtil
+import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
+import org.gradle.util.TestClassLoader
+import org.junit.Rule
+import spock.lang.Specification
+
+abstract class AbstractClassGraphSpec extends Specification {
+ @Rule TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider()
+
+ /**
+ * Returns the classpath for the given classes.
+ */
+ List<File> originalClassPath(Class<?>... classes) {
+ return classes.collect { ClasspathUtil.getClasspathForClass(it) }
+ }
+
+ /**
+ * Makes a copy of the given classes and returns the classpath for these copies. Each class is added to its own classpath root.
+ */
+ List<File> isolatedClasses(Class<?>... classes) {
+ return classes.collect {
+ def name = it.name.replace('.', '/') + '.class'
+ def classPathRoot = tmpDir.file(it.name)
+ def classFile = classPathRoot.file(name)
+ def resource = it.classLoader.getResource(name)
+ classFile.parentFile.mkdirs()
+ classFile.bytes = resource.bytes
+ classPathRoot
+ }
+ }
+
+ /**
+ * Returns a URLClassLoader with the given classpath and parent. Parent defaults to system ClassLoader.
+ */
+ URLClassLoader urlClassLoader(ClassLoader parent = ClassLoader.systemClassLoader.parent, List<File> classpath) {
+ return new URLClassLoader(classpath.collect { it.toURI().toURL() } as URL[], parent)
+ }
+
+ /**
+ * Returns a custom ClassLoader with the given classpath and parent. Parent defaults to system ClassLoader.
+ */
+ ClassLoader customClassLoader(ClassLoader parent = ClassLoader.systemClassLoader.parent, List<File> classpath) {
+ return new TestClassLoader(parent, classpath)
+ }
+}
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/ClasspathInfererTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/ClasspathInfererTest.groovy
new file mode 100644
index 0000000..fcd2cc3
--- /dev/null
+++ b/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/ClasspathInfererTest.groovy
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.provider
+
+import org.gradle.internal.classloader.MutableURLClassLoader
+import org.gradle.tooling.BuildAction
+
+class ClasspathInfererTest extends AbstractClassGraphSpec {
+ def factory = new ClasspathInferer()
+
+ def "determines action and tooling API classpath when loaded via a URLClassLoader"() {
+ def cl = urlClassLoader(toolingApiClassPath + isolatedClasses(CustomAction, CustomModel))
+ def actionClass = cl.loadClass(CustomAction.name)
+
+ expect:
+ def classpath = []
+ factory.getClassPathFor(actionClass, classpath)
+ def loader = new MutableURLClassLoader(ClassLoader.systemClassLoader.parent, classpath)
+ def action = loader.loadClass(CustomAction.name).newInstance()
+ action.execute(null)
+ }
+
+ def "determines action and tooling API classpath when loaded via custom ClassLoader implementation"() {
+ def cl = customClassLoader(toolingApiClassPath + isolatedClasses(CustomAction, CustomModel))
+ def actionClass = cl.loadClass(CustomAction.name)
+
+ expect:
+ def classpath = []
+ factory.getClassPathFor(actionClass, classpath)
+ def loader = new MutableURLClassLoader(ClassLoader.systemClassLoader.parent, classpath)
+ def action = loader.loadClass(CustomAction.name).newInstance()
+ action.execute(null)
+ }
+
+ def "determines action and tooling API classpath when loaded via multiple custom ClassLoader implementations"() {
+ def toolingCl = customClassLoader(toolingApiClassPath)
+ def cl = customClassLoader(toolingCl, isolatedClasses(CustomAction, CustomModel))
+ def actionClass = cl.loadClass(CustomAction.name)
+
+ expect:
+ def classpath = []
+ factory.getClassPathFor(actionClass, classpath)
+ def loader = new MutableURLClassLoader(ClassLoader.systemClassLoader.parent, classpath)
+ def action = loader.loadClass(CustomAction.name).newInstance()
+ action.execute(null)
+ }
+
+ private List<File> getToolingApiClassPath() {
+ originalClassPath(BuildAction)
+ }
+
+}
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/ConfiguringBuildActionTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/ConfiguringBuildActionTest.groovy
index 5e8b6fc..74b4b2c 100644
--- a/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/ConfiguringBuildActionTest.groovy
+++ b/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/ConfiguringBuildActionTest.groovy
@@ -18,13 +18,15 @@
package org.gradle.tooling.internal.provider
+import org.gradle.launcher.cli.converter.PropertiesToStartParameterConverter
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
+import org.gradle.tooling.internal.provider.connection.ProviderOperationParameters
import org.junit.Rule
import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 3/6/12
- */
+import static org.gradle.util.Matchers.isSerializable
+import static org.hamcrest.MatcherAssert.assertThat
+
class ConfiguringBuildActionTest extends Specification {
@Rule TestNameTestDirectoryProvider temp
@@ -70,18 +72,32 @@ class ConfiguringBuildActionTest extends Specification {
def start = action.configureStartParameter()
then:
- !start.isSearchUpwards()
+ !start.searchUpwards
}
- def "can overwrite configure on demand via build arguments"() {
- expect:
- !new ConfiguringBuildAction().configureStartParameter().configureOnDemand
-
+ def "searchUpwards configured directly on the action wins over the command line setting"() {
when:
- def action = new ConfiguringBuildAction(arguments: ['--configure-on-demand'])
+ def action = new ConfiguringBuildAction(arguments: ['-u'], searchUpwards: true)
def start = action.configureStartParameter()
then:
- start.configureOnDemand
+ start.searchUpwards
+ }
+
+ def "the start parameter is configured from properties"() {
+ given:
+ def converter = Mock(PropertiesToStartParameterConverter)
+ def action = new ConfiguringBuildAction(properties: [foo: 'bar'])
+
+ when:
+ action.configureStartParameter(converter)
+
+ then:
+ 1 * converter.convert([foo: 'bar'], _)
+ }
+
+ def "is serializable"() {
+ expect:
+ assertThat(new ConfiguringBuildAction({} as ProviderOperationParameters, null, [foo: 'bar']), isSerializable())
}
}
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/ConnectionScopeServicesTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/ConnectionScopeServicesTest.groovy
new file mode 100644
index 0000000..e07804c
--- /dev/null
+++ b/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/ConnectionScopeServicesTest.groovy
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.provider
+
+import org.gradle.tooling.internal.adapter.ProtocolToModelAdapter
+import spock.lang.Specification
+
+class ConnectionScopeServicesTest extends Specification {
+ def services = new ConnectionScopeServices()
+
+ def "provides a ProviderConnection implementation"() {
+ expect:
+ services.get(ProviderConnection) instanceof ProviderConnection
+ }
+
+ def "provides a ProtocolToModelAdapter implementation"() {
+ expect:
+ services.get(ProtocolToModelAdapter) instanceof ProtocolToModelAdapter
+ }
+}
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/CustomAction.java b/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/CustomAction.java
new file mode 100644
index 0000000..207b77e
--- /dev/null
+++ b/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/CustomAction.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.provider;
+
+import org.gradle.tooling.BuildAction;
+import org.gradle.tooling.BuildController;
+import org.gradle.tooling.GradleConnectionException;
+
+import java.util.List;
+
+public class CustomAction implements BuildAction<Object> {
+ // Some interesting type references
+ byte[][][] buffers;
+ BuildController[][] controllers;
+ List<String> values;
+
+ public Object execute(BuildController controller) throws GradleConnectionException {
+ return new CustomModel(this);
+ }
+}
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/CustomModel.java b/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/CustomModel.java
new file mode 100644
index 0000000..3dd4345
--- /dev/null
+++ b/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/CustomModel.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.provider;
+
+import java.io.Serializable;
+
+public class CustomModel implements Serializable {
+ public CustomModel(CustomAction customAction) {
+ }
+}
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/CustomPayload.java b/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/CustomPayload.java
new file mode 100644
index 0000000..ac5f931
--- /dev/null
+++ b/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/CustomPayload.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.provider;
+
+import java.io.Serializable;
+
+public class CustomPayload implements Serializable, PayloadInterface {
+ Object value;
+ boolean ok;
+ Integer[] anArray = new Integer[0];
+
+ public String getValue() {
+ return value.toString();
+ }
+}
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/DaemonBuildActionExecuterTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/DaemonBuildActionExecuterTest.groovy
new file mode 100644
index 0000000..0f6c1ca
--- /dev/null
+++ b/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/DaemonBuildActionExecuterTest.groovy
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.provider
+
+import org.gradle.initialization.BuildAction
+import org.gradle.launcher.daemon.client.DaemonClient
+import org.gradle.launcher.daemon.configuration.DaemonParameters
+import org.gradle.launcher.exec.ReportedException
+import org.gradle.tooling.internal.protocol.BuildExceptionVersion1
+import org.gradle.tooling.internal.provider.connection.ProviderOperationParameters
+import spock.lang.Specification
+
+class DaemonBuildActionExecuterTest extends Specification {
+ final DaemonClient client = Mock()
+ final BuildAction<String> action = Mock()
+ final ProviderOperationParameters parameters = Mock()
+ final DaemonParameters daemonParameters = Mock()
+ final DaemonBuildActionExecuter executer = new DaemonBuildActionExecuter(client, daemonParameters)
+
+ def unpacksReportedException() {
+ def failure = new RuntimeException()
+
+ when:
+ executer.execute(action, parameters)
+
+ then:
+ BuildExceptionVersion1 e = thrown()
+ e.cause == failure
+ 1 * client.execute(action, !null) >> { throw new ReportedException(failure) }
+ _ * daemonParameters.effectiveSystemProperties >> [:]
+ }
+}
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/DaemonGradleLauncherActionExecuterTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/DaemonGradleLauncherActionExecuterTest.groovy
deleted file mode 100644
index dc380e1..0000000
--- a/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/DaemonGradleLauncherActionExecuterTest.groovy
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.provider
-
-import org.gradle.initialization.GradleLauncherAction
-import org.gradle.launcher.daemon.client.DaemonClient
-import org.gradle.launcher.daemon.configuration.DaemonParameters
-import org.gradle.launcher.exec.ReportedException
-import org.gradle.tooling.internal.protocol.BuildExceptionVersion1
-import org.gradle.tooling.internal.provider.connection.ProviderOperationParameters
-import spock.lang.Specification
-
-class DaemonGradleLauncherActionExecuterTest extends Specification {
- final DaemonClient client = Mock()
- final GradleLauncherAction<String> action = Mock()
- final ProviderOperationParameters parameters = Mock()
- final DaemonParameters daemonParameters = Mock()
- final DaemonGradleLauncherActionExecuter executer = new DaemonGradleLauncherActionExecuter(client, daemonParameters)
-
- def unpacksReportedException() {
- def failure = new RuntimeException()
-
- when:
- executer.execute(action, parameters)
-
- then:
- BuildExceptionVersion1 e = thrown()
- e.cause == failure
- 1 * client.execute(action, !null) >> { throw new ReportedException(failure) }
- _ * daemonParameters.effectiveSystemProperties >> [:]
- }
-}
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/DefaultBuildControllerTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/DefaultBuildControllerTest.groovy
new file mode 100644
index 0000000..f33d921
--- /dev/null
+++ b/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/DefaultBuildControllerTest.groovy
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.provider
+
+import org.gradle.api.internal.GradleInternal
+import org.gradle.api.internal.project.ProjectInternal
+import org.gradle.internal.service.scopes.ServiceRegistryFactory
+import org.gradle.tooling.internal.gradle.GradleProjectIdentity
+import org.gradle.tooling.internal.protocol.InternalUnsupportedModelException
+import org.gradle.tooling.internal.protocol.ModelIdentifier
+import org.gradle.tooling.provider.model.ToolingModelBuilder
+import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry
+import org.gradle.tooling.provider.model.UnknownModelException
+import spock.lang.Specification
+
+class DefaultBuildControllerTest extends Specification {
+ def gradle = Stub(GradleInternal)
+ def registry = Stub(ToolingModelBuilderRegistry)
+ def project = Stub(ProjectInternal) {
+ getServices() >> Stub(ServiceRegistryFactory) {
+ get(ToolingModelBuilderRegistry) >> registry
+ }
+ }
+ def modelId = Stub(ModelIdentifier) {
+ getName() >> 'some.model'
+ }
+ def modelBuilder = Stub(ToolingModelBuilder)
+ def controller = new DefaultBuildController(gradle)
+
+ def "adapts model not found exception to protocol exception"() {
+ def failure = new UnknownModelException("not found")
+
+ given:
+ _ * gradle.defaultProject >> project
+ _ * registry.getBuilder('some.model') >> { throw failure }
+
+ when:
+ controller.getModel(null, modelId)
+
+ then:
+ InternalUnsupportedModelException e = thrown()
+ e.cause == failure
+ }
+
+ def "uses builder for specified project"() {
+ def target = Stub(GradleProjectIdentity)
+ def rootProject = Stub(ProjectInternal)
+ def model = new Object()
+
+ given:
+ _ * target.path >> ":some:path"
+ _ * gradle.rootProject >> rootProject
+ _ * rootProject.project(":some:path") >> project
+ _ * registry.getBuilder("some.model") >> modelBuilder
+ _ * modelBuilder.buildAll("some.model", project) >> model
+
+ when:
+ def result = controller.getModel(target, modelId)
+
+ then:
+ result.getModel() == model
+ }
+
+ def "uses builder for default project when none specified"() {
+ def model = new Object()
+
+ given:
+ _ * gradle.defaultProject >> project
+ _ * registry.getBuilder("some.model") >> modelBuilder
+ _ * modelBuilder.buildAll("some.model", project) >> model
+
+ when:
+ def result = controller.getModel(null, modelId)
+
+ then:
+ result.getModel() == model
+ }
+}
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/ExecuteBuildActionTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/ExecuteBuildActionTest.groovy
deleted file mode 100644
index b960551..0000000
--- a/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/ExecuteBuildActionTest.groovy
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.provider
-
-import org.gradle.BuildResult
-import org.gradle.GradleLauncher
-import spock.lang.Specification
-
-class ExecuteBuildActionTest extends Specification {
- final ExecuteBuildAction action = new ExecuteBuildAction()
-
- def runsBuild() {
- GradleLauncher launcher = Mock()
- BuildResult buildResult = Mock()
-
- when:
- def result = action.run(launcher)
-
- then:
- result == buildResult
- 1 * launcher.run() >> buildResult
- 0 * _._
- }
-}
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/LoggingBridgingBuildActionExecuterTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/LoggingBridgingBuildActionExecuterTest.groovy
new file mode 100644
index 0000000..09beacb
--- /dev/null
+++ b/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/LoggingBridgingBuildActionExecuterTest.groovy
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.provider
+
+import org.gradle.api.logging.LogLevel
+import org.gradle.initialization.BuildAction
+import org.gradle.internal.Factory
+import org.gradle.launcher.exec.BuildActionExecuter
+import org.gradle.logging.LoggingManagerInternal
+import org.gradle.tooling.internal.provider.connection.ProviderOperationParameters
+import spock.lang.Specification
+
+class LoggingBridgingBuildActionExecuterTest extends Specification {
+ final BuildActionExecuter<ProviderOperationParameters> target = Mock()
+ final Factory<LoggingManagerInternal> loggingManagerFactory = Mock()
+ final LoggingManagerInternal loggingManager = Mock()
+ final BuildAction<String> action = Mock()
+ final ProviderOperationParameters parameters = Mock()
+
+ //declared type-lessly to work around groovy eclipse plugin bug
+ final executer = new LoggingBridgingBuildActionExecuter(target, loggingManagerFactory)
+
+ def configuresLoggingWhileActionIsExecuting() {
+ when:
+ executer.execute(action, parameters)
+
+ then:
+ 1 * loggingManagerFactory.create() >> loggingManager
+ 1 * loggingManager.addOutputEventListener(!null)
+ 1 * loggingManager.start()
+ 1 * target.execute(action, parameters)
+ 1 * loggingManager.stop()
+ }
+
+ def restoresLoggingWhenActionFails() {
+ def failure = new RuntimeException()
+
+ when:
+ executer.execute(action, parameters)
+
+ then:
+ RuntimeException e = thrown()
+ e == failure
+ 1 * loggingManagerFactory.create() >> loggingManager
+ 1 * loggingManager.start()
+ 1 * target.execute(action, parameters) >> {throw failure}
+ 1 * loggingManager.stop()
+ }
+
+ def "sets log level accordingly"() {
+ given:
+ loggingManagerFactory.create() >> loggingManager
+ parameters.getBuildLogLevel() >> LogLevel.QUIET
+
+ when:
+ executer.execute(action, parameters)
+
+ then:
+ 1 * loggingManager.setLevel(LogLevel.QUIET)
+ }
+}
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/LoggingBridgingGradleLauncherActionExecuterTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/LoggingBridgingGradleLauncherActionExecuterTest.groovy
deleted file mode 100644
index dd15ebb..0000000
--- a/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/LoggingBridgingGradleLauncherActionExecuterTest.groovy
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.provider
-
-import org.gradle.api.logging.LogLevel
-import org.gradle.initialization.GradleLauncherAction
-import org.gradle.internal.Factory
-import org.gradle.launcher.exec.GradleLauncherActionExecuter
-import org.gradle.logging.LoggingManagerInternal
-import org.gradle.tooling.internal.provider.connection.ProviderOperationParameters
-import spock.lang.Specification
-
-class LoggingBridgingGradleLauncherActionExecuterTest extends Specification {
- final GradleLauncherActionExecuter<ProviderOperationParameters> target = Mock()
- final Factory<LoggingManagerInternal> loggingManagerFactory = Mock()
- final LoggingManagerInternal loggingManager = Mock()
- final GradleLauncherAction<String> action = Mock()
- final ProviderOperationParameters parameters = Mock()
-
- //declared type-lessly to work around groovy eclipse plugin bug
- final executer = new LoggingBridgingGradleLauncherActionExecuter(target, loggingManagerFactory)
-
- def configuresLoggingWhileActionIsExecuting() {
- when:
- executer.execute(action, parameters)
-
- then:
- 1 * loggingManagerFactory.create() >> loggingManager
- 1 * loggingManager.addOutputEventListener(!null)
- 1 * loggingManager.start()
- 1 * target.execute(action, parameters)
- 1 * loggingManager.stop()
- }
-
- def restoresLoggingWhenActionFails() {
- def failure = new RuntimeException()
-
- when:
- executer.execute(action, parameters)
-
- then:
- RuntimeException e = thrown()
- e == failure
- 1 * loggingManagerFactory.create() >> loggingManager
- 1 * loggingManager.start()
- 1 * target.execute(action, parameters) >> {throw failure}
- 1 * loggingManager.stop()
- }
-
- def "sets log level accordingly"() {
- given:
- loggingManagerFactory.create() >> loggingManager
- parameters.getBuildLogLevel() >> LogLevel.QUIET
-
- when:
- executer.execute(action, parameters)
-
- then:
- 1 * loggingManager.setLevel(LogLevel.QUIET)
- }
-}
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/ModelClassLoaderFactoryTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/ModelClassLoaderFactoryTest.groovy
new file mode 100644
index 0000000..6be72e1
--- /dev/null
+++ b/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/ModelClassLoaderFactoryTest.groovy
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.provider
+
+import org.gradle.internal.classloader.MutableURLClassLoader
+import spock.lang.Specification
+
+class ModelClassLoaderFactoryTest extends Specification {
+ final ModelClassLoaderFactory registry = new ModelClassLoaderFactory()
+
+ def "creates ClassLoader for classpath"() {
+ def url1 = new URL("http://localhost/file1.jar")
+ def url2 = new URL("http://localhost/file2.jar")
+
+ when:
+ def cl = registry.getClassLoaderFor(new MutableURLClassLoader.Spec([url1, url2]), [null])
+
+ then:
+ cl instanceof MutableURLClassLoader
+ cl.URLs == [url1, url2] as URL[]
+ }
+}
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/PayloadInterface.java b/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/PayloadInterface.java
new file mode 100644
index 0000000..5fd22fc
--- /dev/null
+++ b/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/PayloadInterface.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.provider;
+
+public interface PayloadInterface {
+ String getValue();
+}
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/PayloadSerializerTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/PayloadSerializerTest.groovy
new file mode 100644
index 0000000..9d21b53
--- /dev/null
+++ b/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/PayloadSerializerTest.groovy
@@ -0,0 +1,204 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.provider
+
+import org.gradle.internal.classloader.FilteringClassLoader
+import org.junit.Assert
+import spock.lang.Ignore
+
+import java.lang.reflect.InvocationHandler
+import java.lang.reflect.Method
+import java.lang.reflect.Proxy
+
+class PayloadSerializerTest extends AbstractClassGraphSpec {
+ final PayloadSerializer originator = new PayloadSerializer(new DefaultPayloadClassLoaderRegistry(new ModelClassLoaderFactory()))
+ final PayloadSerializer receiver = new PayloadSerializer(new DefaultPayloadClassLoaderRegistry(new ModelClassLoaderFactory()))
+
+ def "can send an object between two parties"() {
+ expect:
+ def serialized = originator.serialize(source)
+ receiver.deserialize(serialized) == source
+
+ where:
+ source | _
+ null | _
+ "some value" | _
+ }
+
+ def "implementation classpath travels with object"() {
+ def payloadClass = isolated(CustomPayload, PayloadInterface).loadClass(CustomPayload.name)
+ def original = payloadClass.newInstance(value: 'value')
+
+ when:
+ def serialized = originator.serialize(original)
+ def received = receiver.deserialize(serialized)
+
+ then:
+ received.class != payloadClass
+ received.class != CustomPayload
+ received.class.name == CustomPayload.class.name
+ received.value == 'value'
+ }
+
+ def "uses system ClassLoader when original object is loaded by system ClassLoader"() {
+ when:
+ def serialized = originator.serialize(new StringBuilder('value'))
+ def received = receiver.deserialize(serialized)
+
+ then:
+ received.class == StringBuilder.class
+ received.toString() == 'value'
+ }
+
+ def "uses original ClassLoader when receiving a reply"() {
+ def payloadClass = isolated(CustomPayload, PayloadInterface).loadClass(CustomPayload.name)
+ def original = payloadClass.newInstance(value: 'value')
+
+ when:
+ def serialized = originator.serialize(original)
+ def received = receiver.deserialize(serialized)
+ def reply = originator.deserialize(receiver.serialize(received))
+
+ then:
+ received.class != CustomPayload.class
+ received.class != payloadClass
+ reply.class == payloadClass
+ }
+
+ def "handles nested objects which are not visible from root object ClassLoader"() {
+ def parent = isolated(WrapperPayload, PayloadInterface)
+ def wrapperClass = parent.loadClass(WrapperPayload.name)
+ def payloadClass = isolated(parent, CustomPayload).loadClass(CustomPayload.name)
+ assertNotVisible(wrapperClass, payloadClass)
+ def original = wrapperClass.newInstance(payload: payloadClass.newInstance(value: 'value'))
+
+ when:
+ def serialized = originator.serialize(original)
+ def received = receiver.deserialize(serialized)
+
+ then:
+ received.class != wrapperClass
+ received.class.name == WrapperPayload.name
+ received.payload.class != payloadClass
+ received.payload.class.name == CustomPayload.name
+ received.class.classLoader != received.payload.class.classLoader
+ }
+
+ @Ignore("work in progress")
+ def "handles objects in separate ClassLoaders with shared parent"() {
+ def filter = filter(PayloadInterface)
+ def wrapperClass = isolated(filter, WrapperPayload).loadClass(WrapperPayload.name)
+ def payloadClass = isolated(filter, CustomPayload).loadClass(CustomPayload.name)
+ assertNotVisible(wrapperClass, payloadClass)
+ assertNotVisible(payloadClass, wrapperClass)
+ def original = wrapperClass.newInstance(payload: payloadClass.newInstance(value: 'value'))
+
+ when:
+ def received = receiver.deserialize(originator.serialize(original))
+ def reply = originator.deserialize(receiver.serialize(received))
+
+ then:
+ received.class.classLoader.loadClass(PayloadInterface.name) == received.payload.class.classLoader.loadClass(PayloadInterface.name)
+ reply instanceof PayloadInterface
+ reply.value instanceof PayloadInterface
+ reply.class == wrapperClass
+ reply.payload.class == payloadClass
+ }
+
+ def "can send a dynamic proxy"() {
+ def cl = isolated(PayloadInterface)
+ def payloadClass = cl.loadClass(PayloadInterface.name)
+ def original = Proxy.newProxyInstance(cl, [payloadClass] as Class[], new GroovyInvocationHandler())
+
+ when:
+ def received = receiver.deserialize(originator.serialize(original))
+ def reply = originator.deserialize(receiver.serialize(received))
+
+ then:
+ received.class != original.class
+ !payloadClass.isInstance(received)
+ Proxy.getInvocationHandler(received).class != GroovyInvocationHandler.class
+ received.value == "result!"
+
+ payloadClass.isInstance(reply)
+ Proxy.getInvocationHandler(reply).class == GroovyInvocationHandler.class
+ reply.value == "result!"
+ }
+
+ def "can send a Class instance"() {
+ def cl = isolated(PayloadInterface).loadClass(PayloadInterface.name)
+
+ when:
+ def serialized = originator.serialize(cl)
+ def received = receiver.deserialize(serialized)
+
+ then:
+ received != cl
+ received.name == cl.name
+ }
+
+ def "reuses ClassLoaders for multiple invocations"() {
+ def cl = isolated(WrapperPayload, CustomPayload, PayloadInterface)
+ def wrapperClass = cl.loadClass(WrapperPayload.name)
+ def payloadClass = cl.loadClass(CustomPayload.name)
+ def original = wrapperClass.newInstance(payload: payloadClass.newInstance(value: 'value'))
+
+ when:
+ def received1 = receiver.deserialize(originator.serialize(original))
+ def reply1 = originator.deserialize(receiver.serialize(received1))
+ def received2 = receiver.deserialize(originator.serialize(original))
+ def reply2 = originator.deserialize(receiver.serialize(received2))
+
+ then:
+ received1.class.classLoader == received2.class.classLoader
+ received1.payload.class.classLoader == received2.payload.class.classLoader
+ reply1.class == wrapperClass
+ reply1.payload.class == payloadClass
+ reply2.class == wrapperClass
+ reply2.payload.class == payloadClass
+ }
+
+ void assertNotVisible(Class<?> from, Class<?> to) {
+ try {
+ from.classLoader.loadClass(to.name)
+ Assert.fail()
+ } catch (ClassNotFoundException) {
+ // expected
+ }
+ }
+
+ ClassLoader filter(Class<?> aClass) {
+ def filter = new FilteringClassLoader(aClass.classLoader)
+ filter.allowClass(aClass)
+ return filter
+ }
+
+ ClassLoader isolated(ClassLoader parent = ClassLoader.systemClassLoader.parent, Class<?>... classes) {
+ def classpath = isolatedClasses(classes)
+ def loader = urlClassLoader(parent, classpath)
+ for (Class<?> aClass : classes) {
+ assert loader.loadClass(aClass.name) != aClass
+ }
+ return loader
+ }
+
+ private static class GroovyInvocationHandler implements InvocationHandler, Serializable {
+ Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ return "result!"
+ }
+ }
+}
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/ToolingGlobalScopeServicesTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/ToolingGlobalScopeServicesTest.groovy
new file mode 100644
index 0000000..5b24a16
--- /dev/null
+++ b/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/ToolingGlobalScopeServicesTest.groovy
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.provider
+
+import spock.lang.Specification
+
+class ToolingGlobalScopeServicesTest extends Specification {
+ def services = new ToolingGlobalScopeServices()
+
+ def "provides a PayloadSerializer"() {
+ expect:
+ services.get(PayloadSerializer) instanceof PayloadSerializer
+ }
+}
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/WrapperPayload.java b/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/WrapperPayload.java
new file mode 100644
index 0000000..d7b13e9
--- /dev/null
+++ b/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/WrapperPayload.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.provider;
+
+import java.io.Serializable;
+
+public class WrapperPayload implements Serializable, PayloadInterface {
+ PayloadInterface payload;
+
+ public String getValue() {
+ return payload.getValue();
+ }
+}
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/connection/AdaptedOperationParametersTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/connection/AdaptedOperationParametersTest.groovy
index 7f73ec7..aa9da02 100644
--- a/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/connection/AdaptedOperationParametersTest.groovy
+++ b/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/connection/AdaptedOperationParametersTest.groovy
@@ -20,9 +20,6 @@ import org.gradle.api.logging.LogLevel
import org.gradle.tooling.internal.protocol.BuildOperationParametersVersion1
import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 3/6/12
- */
class AdaptedOperationParametersTest extends Specification {
interface BuildOperationParametersStub extends BuildOperationParametersVersion1 {
diff --git a/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/connection/BuildLogLevelMixInTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/connection/BuildLogLevelMixInTest.groovy
index 105d527..4677732 100644
--- a/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/connection/BuildLogLevelMixInTest.groovy
+++ b/subprojects/launcher/src/test/groovy/org/gradle/tooling/internal/provider/connection/BuildLogLevelMixInTest.groovy
@@ -19,9 +19,6 @@ package org.gradle.tooling.internal.provider.connection
import org.gradle.api.logging.LogLevel
import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 1/18/13
- */
class BuildLogLevelMixInTest extends Specification {
final parameters = Mock(ProviderOperationParameters)
diff --git a/subprojects/maven/maven.gradle b/subprojects/maven/maven.gradle
index 5aed01a..9d3649c 100644
--- a/subprojects/maven/maven.gradle
+++ b/subprojects/maven/maven.gradle
@@ -15,7 +15,7 @@
*/
dependencies {
- groovy libraries.groovy
+ compile libraries.groovy
compile project(':core')
compile project(':coreImpl')
diff --git a/subprojects/maven/src/integTest/groovy/org/gradle/api/plugins/maven/MavenConversionIntegrationTest.groovy b/subprojects/maven/src/integTest/groovy/org/gradle/api/plugins/maven/MavenConversionIntegrationTest.groovy
deleted file mode 100644
index 8233c72..0000000
--- a/subprojects/maven/src/integTest/groovy/org/gradle/api/plugins/maven/MavenConversionIntegrationTest.groovy
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.plugins.maven
-
-import org.gradle.integtests.fixtures.AbstractIntegrationSpec
-import org.gradle.integtests.fixtures.JUnitXmlTestExecutionResult
-import org.gradle.integtests.fixtures.TestResources
-import org.junit.Rule
-
-import static org.gradle.util.TextUtil.toPlatformLineSeparators
-
-/**
- * by Szczepan Faber, created at: 9/4/12
- */
-class MavenConversionIntegrationTest extends AbstractIntegrationSpec {
-
- @Rule public final TestResources resources = new TestResources(temporaryFolder)
-
- def "multiModule"() {
- given:
- file("build.gradle") << "apply plugin: 'maven2Gradle'"
-
- when:
- run 'maven2Gradle'
-
- then:
- file("settings.gradle").exists()
-
- when:
- run '-i', 'clean', 'build'
-
- then: //smoke test the build artifacts
- file("webinar-api/build/libs/webinar-api-1.0-SNAPSHOT.jar").exists()
- file("webinar-impl/build/libs/webinar-impl-1.0-SNAPSHOT.jar").exists()
- file("webinar-war/build/libs/webinar-war-1.0-SNAPSHOT.war").exists()
- file('webinar-impl/build/reports/tests/index.html').exists()
-
- new JUnitXmlTestExecutionResult(file("webinar-impl")).assertTestClassesExecuted('webinar.WebinarTest')
-
- when:
- run 'projects'
-
- then:
- output.contains(toPlatformLineSeparators("""
-Root project 'webinar-parent'
-+--- Project ':webinar-api' - Webinar APIs
-+--- Project ':webinar-impl' - Webinar implementation
-\\--- Project ':webinar-war' - Webinar web application
-"""))
- }
-
- def "flatmultimodule"() {
- given:
- file("webinar-parent/build.gradle") << "apply plugin: 'maven2Gradle'"
-
- when:
- executer.inDirectory(file("webinar-parent"))
- run 'maven2Gradle'
-
- then:
- file("webinar-parent/settings.gradle").exists()
-
- when:
- executer.inDirectory(file("webinar-parent"))
- run '-i', 'clean', 'build'
-
- then: //smoke test the build artifacts
- file("webinar-api/build/libs/webinar-api-1.0-SNAPSHOT.jar").exists()
- file("webinar-impl/build/libs/webinar-impl-1.0-SNAPSHOT.jar").exists()
- file("webinar-war/build/libs/webinar-war-1.0-SNAPSHOT.war").exists()
- file('webinar-impl/build/reports/tests/index.html').exists()
-
- new JUnitXmlTestExecutionResult(file("webinar-impl")).assertTestClassesExecuted('webinar.WebinarTest')
-
- when:
- executer.inDirectory(file("webinar-parent"))
- run 'projects'
-
- then:
- output.contains(toPlatformLineSeparators("""
-Root project 'webinar-parent'
-+--- Project ':webinar-api' - Webinar APIs
-+--- Project ':webinar-impl' - Webinar implementation
-\\--- Project ':webinar-war' - Webinar web application
-"""))
- }
-
- def "singleModule"() {
- given:
- file("build.gradle") << "apply plugin: 'maven2Gradle'"
-
- when:
- run 'maven2Gradle'
-
- then:
- noExceptionThrown()
-
- when:
- //TODO SF this build should fail because the TestNG test is failing
- //however the plugin does not generate testNG for single module project atm (bug)
- //def failure = runAndFail('clean', 'build') //assert if fails for the right reason
- run 'clean', 'build'
-
- then:
- file("build/libs/util-2.5.jar").exists()
- }
-
- def "testjar"() {
- given:
- file("build.gradle") << "apply plugin: 'maven2Gradle'"
-
- when:
- run 'maven2Gradle'
-
- then:
- noExceptionThrown()
-
- when:
- run 'clean', 'build'
-
- then:
- file("build/libs/testjar-2.5.jar").exists()
- file("build/libs/testjar-2.5-tests.jar").exists()
- }
-
- def "enforcerplugin"() {
- given:
- file("build.gradle") << "apply plugin: 'maven2Gradle'"
-
- when:
- run 'maven2Gradle'
-
- then:
- noExceptionThrown()
- and:
- buildFile.text.contains("""configurations.all {
-it.exclude group: 'org.apache.maven'
-it.exclude group: 'org.apache.maven', module: 'badArtifact'
-it.exclude group: '*', module: 'badArtifact'
-}""")
- when:
- run 'clean', 'build'
-
- then:
- file("build/libs/enforcerExample-1.0.jar").exists()
- }
-}
\ No newline at end of file
diff --git a/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/AbstractMavenPublishIntegTest.groovy b/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/AbstractMavenPublishIntegTest.groovy
index ab9f75b..16c3321 100644
--- a/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/AbstractMavenPublishIntegTest.groovy
+++ b/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/AbstractMavenPublishIntegTest.groovy
@@ -13,22 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-
-
package org.gradle.api.publish.maven
+
import org.gradle.integtests.fixtures.AbstractIntegrationSpec
import org.gradle.test.fixtures.maven.MavenFileModule
class AbstractMavenPublishIntegTest extends AbstractIntegrationSpec {
- protected def resolveArtifact(MavenFileModule module, def extension) {
- doResolveArtifacts("""
- dependencies {
- resolve group: '${sq(module.groupId)}', name: '${sq(module.artifactId)}', version: '${sq(module.version)}', ext: '${sq(extension)}'
- }
-""")
- }
protected def resolveArtifact(MavenFileModule module, def extension, def classifier) {
doResolveArtifacts("""
dependencies {
diff --git a/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishArtifactCustomisationIntegTest.groovy b/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishArtifactCustomisationIntegTest.groovy
deleted file mode 100644
index 317f542..0000000
--- a/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishArtifactCustomisationIntegTest.groovy
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.publish.maven
-
-class MavenPublishArtifactCustomisationIntegTest extends AbstractMavenPublishIntegTest {
-
- def "can attach custom artifacts"() {
- given:
- createBuildScripts("""
- publications {
- mavenCustom(MavenPublication) {
- artifact "customFile.txt"
- artifact customJar
- }
- }
-""")
- when:
- succeeds 'publish'
-
- then:
- def module = mavenRepo.module("group", "projectText", "1.0")
- module.assertPublished()
- module.parsedPom.packaging == "txt"
- module.assertArtifactsPublished("projectText-1.0.pom", "projectText-1.0.txt", "projectText-1.0-customjar.jar")
-
- and:
- resolveArtifacts(module, [classifier: 'customjar']) == ["projectText-1.0-customjar.jar", "projectText-1.0.txt"]
- }
-
- def "can set custom artifacts to override component artifacts"() {
- given:
- createBuildScripts("""
- publications {
- mavenCustom(MavenPublication) {
- from components.java
- artifacts = ["customFile.txt", customJar]
- }
- }
-
-""")
- when:
- succeeds 'publish'
-
- then:
- def module = mavenRepo.module("group", "projectText", "1.0")
- module.assertPublished()
- module.parsedPom.packaging == "txt"
- module.assertArtifactsPublished("projectText-1.0.pom", "projectText-1.0.txt", "projectText-1.0-customjar.jar")
-
- and:
- resolveArtifacts(module, [classifier: 'customjar']) == ["projectText-1.0-customjar.jar", "projectText-1.0.txt"]
- }
-
- def "can configure custom artifacts when creating"() {
- given:
- createBuildScripts("""
- publications {
- mavenCustom(MavenPublication) {
- artifact("customFile.txt") {
- classifier "output"
- }
- artifact(customFileTask.outputFile) {
- extension "htm"
- classifier "documentation"
- builtBy customFileTask
- }
- artifact customJar {
- classifier null
- extension "war"
- }
- }
- }
-""")
- when:
- succeeds 'publish'
-
- then:
- def module = mavenRepo.module("group", "projectText", "1.0")
- module.assertPublished()
- module.parsedPom.packaging == "war"
- module.assertArtifactsPublished("projectText-1.0.pom", "projectText-1.0.war", "projectText-1.0-documentation.htm", "projectText-1.0-output.txt")
-
- and:
- resolveArtifacts(module, [classifier: 'documentation', type: 'htm'], [classifier: 'output', type: 'txt']) == ["projectText-1.0-documentation.htm", "projectText-1.0-output.txt", "projectText-1.0.war"]
- }
-
- def "can attach custom file artifacts with map notation"() {
- given:
- createBuildScripts("""
- publications {
- mavenCustom(MavenPublication) {
- artifact source: "customFile.txt", classifier: "output"
- artifact source: customFileTask.outputFile, extension: "htm", classifier: "documentation", builtBy: customFileTask
- artifact source: customJar, extension: "war", classifier: null
- }
- }
-""")
- when:
- succeeds 'publish'
-
- then:
- def module = mavenRepo.module("group", "projectText", "1.0")
- module.assertPublished()
- module.parsedPom.packaging == "war"
- module.assertArtifactsPublished("projectText-1.0.pom", "projectText-1.0.war", "projectText-1.0-documentation.htm", "projectText-1.0-output.txt")
-
- and:
- resolveArtifacts(module, [classifier: 'documentation', type: 'htm'], [classifier: 'output', type: 'txt']) == ["projectText-1.0-documentation.htm", "projectText-1.0-output.txt", "projectText-1.0.war"]
- }
-
- def "can configure custom artifacts post creation"() {
- given:
- createBuildScripts("""
- publications {
- mavenCustom(MavenPublication) {
- artifact "customFile.txt"
- artifact customFileTask.outputFile
- artifact customJar
- }
- }
-""", """
- publishing.publications.mavenCustom.artifacts.each {
- if (it.extension == "html") {
- it.classifier = "docs"
- it.builtBy customFileTask
- }
- }
-""")
- when:
- succeeds 'publish'
-
- then:
- def module = mavenRepo.module("group", "projectText", "1.0")
- module.assertPublished()
- module.assertArtifactsPublished("projectText-1.0.pom", "projectText-1.0.txt", "projectText-1.0-docs.html", "projectText-1.0-customjar.jar")
- }
-
- def "can attach artifact with no extension"() {
- given:
- createBuildScripts("""
- publications {
- mavenCustom(MavenPublication) {
- from components.java
- artifact source: "customFile.txt", extension: "", classifier: "classified"
- }
- }
-""")
- when:
- succeeds 'publish'
-
- then:
- def module = mavenRepo.module("group", "projectText", "1.0")
- module.assertPublished()
- module.assertArtifactsPublished("projectText-1.0.pom", "projectText-1.0.jar", "projectText-1.0-classified")
-
- // TODO:DAZ Find a way to resolve Maven artifact with no extension
-// and:
-// resolveArtifact(module, '', 'classified') == ["projectText-1.0-classifier"]
- }
-
- def "reports failure publishing when validation fails"() {
- given:
- file("a-directory.dir").createDir()
-
- createBuildScripts("""
- publications {
- mavenCustom(MavenPublication) {
- artifact "a-directory.dir"
- }
- }
-""")
- when:
- fails 'publish'
-
- then:
- failure.assertHasDescription("Execution failed for task ':publishMavenCustomPublicationToMavenRepository'.")
- failure.assertHasCause("Failed to publish publication 'mavenCustom' to repository 'maven'")
- failure.assertHasCause("Invalid publication 'mavenCustom': artifact file is a directory")
- }
-
- private createBuildScripts(def publications, def append = "") {
- settingsFile << "rootProject.name = 'projectText'"
- buildFile << """
- apply plugin: 'java'
- apply plugin: 'maven-publish'
-
- group = 'group'
- version = '1.0'
-
- file("customFile.txt") << 'some content'
-
- task customFileTask {
- ext.outputFile = file('customFile-1.0-docs.html')
- doLast {
- outputFile << '<html/>'
- }
- }
-
- task customJar(type: Jar) {
- from file("customFile.txt")
- classifier "customjar"
- }
-
- publishing {
- repositories {
- maven { url "${mavenRepo.uri}" }
- }
- $publications
- }
-
- $append
- """
- }
-}
diff --git a/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishArtifactCustomizationIntegTest.groovy b/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishArtifactCustomizationIntegTest.groovy
new file mode 100644
index 0000000..9bad371
--- /dev/null
+++ b/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishArtifactCustomizationIntegTest.groovy
@@ -0,0 +1,255 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.publish.maven
+
+class MavenPublishArtifactCustomizationIntegTest extends AbstractMavenPublishIntegTest {
+
+ def "can attach custom artifacts"() {
+ given:
+ createBuildScripts("""
+ publications {
+ mavenCustom(MavenPublication) {
+ artifact "customFile.txt"
+ artifact customJar
+ }
+ }
+""")
+ when:
+ succeeds 'publish'
+
+ then:
+ def module = mavenRepo.module("group", "projectText", "1.0")
+ module.assertPublished()
+ module.parsedPom.packaging == "txt"
+ module.assertArtifactsPublished("projectText-1.0.pom", "projectText-1.0.txt", "projectText-1.0-customjar.jar")
+
+ and:
+ resolveArtifacts(module, [classifier: 'customjar']) == ["projectText-1.0-customjar.jar", "projectText-1.0.txt"]
+ }
+
+ public void "can configure artifacts added from component"() {
+ given:
+ createBuildScripts("""
+ publications {
+ maven(MavenPublication) {
+ from components.java
+ }
+ }
+ publications.maven.artifacts.each {
+ if (it.extension == 'jar') {
+ it.classifier = 'classified'
+ }
+ }
+""")
+
+ when:
+ run "publish"
+
+ then:
+ def module = mavenRepo.module("group", "projectText", "1.0")
+ module.assertPublished()
+ module.assertArtifactsPublished("projectText-1.0-classified.jar", "projectText-1.0.pom")
+
+ and:
+ resolveArtifact(module, 'jar', 'classified') == ["projectText-1.0-classified.jar"]
+ }
+
+ def "can set custom artifacts to override component artifacts"() {
+ given:
+ createBuildScripts("""
+ publications {
+ mavenCustom(MavenPublication) {
+ from components.java
+ artifacts = ["customFile.txt", customJar]
+ }
+ }
+
+""")
+ when:
+ succeeds 'publish'
+
+ then:
+ def module = mavenRepo.module("group", "projectText", "1.0")
+ module.assertPublished()
+ module.parsedPom.packaging == "txt"
+ module.assertArtifactsPublished("projectText-1.0.pom", "projectText-1.0.txt", "projectText-1.0-customjar.jar")
+
+ and:
+ resolveArtifacts(module, [classifier: 'customjar']) == ["projectText-1.0-customjar.jar", "projectText-1.0.txt"]
+ }
+
+ def "can configure custom artifacts when creating"() {
+ given:
+ createBuildScripts("""
+ publications {
+ mavenCustom(MavenPublication) {
+ artifact("customFile.txt") {
+ classifier "output"
+ }
+ artifact(customFileTask.outputFile) {
+ extension "htm"
+ classifier "documentation"
+ builtBy customFileTask
+ }
+ artifact customJar {
+ classifier null
+ extension "war"
+ }
+ }
+ }
+""")
+ when:
+ succeeds 'publish'
+
+ then:
+ def module = mavenRepo.module("group", "projectText", "1.0")
+ module.assertPublished()
+ module.parsedPom.packaging == "war"
+ module.assertArtifactsPublished("projectText-1.0.pom", "projectText-1.0.war", "projectText-1.0-documentation.htm", "projectText-1.0-output.txt")
+
+ and:
+ resolveArtifacts(module, [classifier: 'documentation', type: 'htm'], [classifier: 'output', type: 'txt']) == ["projectText-1.0-documentation.htm", "projectText-1.0-output.txt", "projectText-1.0.war"]
+ }
+
+ def "can attach custom file artifacts with map notation"() {
+ given:
+ createBuildScripts("""
+ publications {
+ mavenCustom(MavenPublication) {
+ artifact source: "customFile.txt", classifier: "output"
+ artifact source: customFileTask.outputFile, extension: "htm", classifier: "documentation", builtBy: customFileTask
+ artifact source: customJar, extension: "war", classifier: null
+ }
+ }
+""")
+ when:
+ succeeds 'publish'
+
+ then:
+ def module = mavenRepo.module("group", "projectText", "1.0")
+ module.assertPublished()
+ module.parsedPom.packaging == "war"
+ module.assertArtifactsPublished("projectText-1.0.pom", "projectText-1.0.war", "projectText-1.0-documentation.htm", "projectText-1.0-output.txt")
+
+ and:
+ resolveArtifacts(module, [classifier: 'documentation', type: 'htm'], [classifier: 'output', type: 'txt']) == ["projectText-1.0-documentation.htm", "projectText-1.0-output.txt", "projectText-1.0.war"]
+ }
+
+ def "can configure custom artifacts post creation"() {
+ given:
+ createBuildScripts("""
+ publications {
+ mavenCustom(MavenPublication) {
+ artifact "customFile.txt"
+ artifact customFileTask.outputFile
+ artifact customJar
+ }
+ }
+""", """
+ publishing.publications.mavenCustom.artifacts.each {
+ if (it.extension == "html") {
+ it.classifier = "docs"
+ it.builtBy customFileTask
+ }
+ }
+""")
+ when:
+ succeeds 'publish'
+
+ then:
+ def module = mavenRepo.module("group", "projectText", "1.0")
+ module.assertPublished()
+ module.assertArtifactsPublished("projectText-1.0.pom", "projectText-1.0.txt", "projectText-1.0-docs.html", "projectText-1.0-customjar.jar")
+ }
+
+ def "can attach artifact with no extension"() {
+ given:
+ createBuildScripts("""
+ publications {
+ mavenCustom(MavenPublication) {
+ from components.java
+ artifact source: "customFile.txt", extension: "", classifier: "classified"
+ }
+ }
+""")
+ when:
+ succeeds 'publish'
+
+ then:
+ def module = mavenRepo.module("group", "projectText", "1.0")
+ module.assertPublished()
+ module.assertArtifactsPublished("projectText-1.0.pom", "projectText-1.0.jar", "projectText-1.0-classified")
+
+ // TODO:DAZ Find a way to resolve Maven artifact with no extension
+// and:
+// resolveArtifact(module, '', 'classified') == ["projectText-1.0-classifier"]
+ }
+
+ def "reports failure publishing when validation fails"() {
+ given:
+ file("a-directory.dir").createDir()
+
+ createBuildScripts("""
+ publications {
+ mavenCustom(MavenPublication) {
+ artifact "a-directory.dir"
+ }
+ }
+""")
+ when:
+ fails 'publish'
+
+ then:
+ failure.assertHasDescription("Execution failed for task ':publishMavenCustomPublicationToMavenRepository'.")
+ failure.assertHasCause("Failed to publish publication 'mavenCustom' to repository 'maven'")
+ failure.assertHasCause("Invalid publication 'mavenCustom': artifact file is a directory")
+ }
+
+ private createBuildScripts(def publications, def append = "") {
+ settingsFile << "rootProject.name = 'projectText'"
+ buildFile << """
+ apply plugin: 'java'
+ apply plugin: 'maven-publish'
+
+ group = 'group'
+ version = '1.0'
+
+ file("customFile.txt") << 'some content'
+
+ task customFileTask {
+ ext.outputFile = file('customFile-1.0-docs.html')
+ doLast {
+ outputFile << '<html/>'
+ }
+ }
+
+ task customJar(type: Jar) {
+ from file("customFile.txt")
+ classifier "customjar"
+ }
+
+ publishing {
+ repositories {
+ maven { url "${mavenRepo.uri}" }
+ }
+ $publications
+ }
+
+ $append
+ """
+ }
+}
diff --git a/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishBasicIntegTest.groovy b/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishBasicIntegTest.groovy
index 2c12e43..298018f 100644
--- a/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishBasicIntegTest.groovy
+++ b/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishBasicIntegTest.groovy
@@ -80,7 +80,7 @@ class MavenPublishBasicIntegTest extends AbstractMavenPublishIntegTest {
then:
def module = mavenRepo.module('org.gradle.test', 'empty-project', '1.0')
- module.assertPublished()
+ module.assertPublishedAsPomModule()
module.parsedPom.scopes.isEmpty()
and:
@@ -196,11 +196,11 @@ class MavenPublishBasicIntegTest extends AbstractMavenPublishIntegTest {
fails 'publish'
then:
- failure.assertHasDescription("A problem occurred configuring the 'publishing' extension")
+ failure.assertHasDescription("A problem occurred configuring root project 'bad-project'.")
failure.assertHasCause("Maven publication 'maven' cannot include multiple components")
}
- @Ignore("Not yet implemented - currently the second publication will overwrite") // TODO:DAZ fix in validation story
+ @Ignore("Not yet implemented - currently the second publication will overwrite")
def "cannot publish multiple maven publications with the same identity"() {
given:
settingsFile << "rootProject.name = 'bad-project'"
@@ -229,7 +229,7 @@ class MavenPublishBasicIntegTest extends AbstractMavenPublishIntegTest {
fails 'publish'
then:
- failure.assertHasDescription("A problem occurred evaluating root project 'bad-project'")
+ failure.assertHasDescription("A problem occurred configuring root project 'bad-project'.")
failure.assertHasCause("Publication with name 'mavenJava' already exists")
}
}
diff --git a/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishCoordinatesIntegTest.groovy b/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishCoordinatesIntegTest.groovy
new file mode 100644
index 0000000..5f3c98a
--- /dev/null
+++ b/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishCoordinatesIntegTest.groovy
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.publish.maven
+
+import org.gradle.test.fixtures.maven.M2Installation
+import org.gradle.test.fixtures.maven.MavenFileRepository
+
+class MavenPublishCoordinatesIntegTest extends AbstractMavenPublishIntegTest {
+ MavenFileRepository m2Repo
+
+ def "setup"() {
+ def m2Installation = new M2Installation(testDirectory)
+ m2Repo = m2Installation.mavenRepo()
+ executer.beforeExecute m2Installation
+ }
+
+ def "can publish single jar with specified coordinates"() {
+ given:
+ def repoModule = mavenRepo.module('org.custom', 'custom', '2.2')
+ def localModule = m2Repo.module('org.custom', 'custom', '2.2')
+
+ and:
+ settingsFile << "rootProject.name = 'root'"
+ buildFile << """
+ apply plugin: 'maven-publish'
+ apply plugin: 'java'
+
+ group = 'group'
+ version = '1.0'
+
+ publishing {
+ repositories {
+ maven { url "${mavenRepo.uri}" }
+ }
+ publications {
+ maven(MavenPublication) {
+ from components.java
+ groupId 'org.custom'
+ artifactId 'custom'
+ version '2.2'
+ }
+ }
+ }
+ """
+
+ when:
+ succeeds 'publishToMavenLocal'
+
+ then: "jar is published to maven local repository"
+ repoModule.assertNotPublished()
+ localModule.assertPublishedAsJavaModule()
+
+ when:
+ succeeds 'publish'
+
+ then: "jar is published to defined maven repository"
+ file('build/libs/root-1.0.jar').assertExists()
+
+ and:
+ repoModule.assertPublishedAsJavaModule()
+
+ and:
+ resolveArtifacts(repoModule) == ['custom-2.2.jar']
+ }
+
+ def "can produce multiple separate publications for single project"() {
+ given:
+ def module = mavenRepo.module('org.custom', 'custom', '2.2')
+ def apiModule = mavenRepo.module('org.custom', 'custom-api', '2')
+
+ and:
+ settingsFile << "rootProject.name = 'root'"
+ buildFile << """
+ apply plugin: 'maven-publish'
+ apply plugin: 'java'
+
+ group = 'group'
+ version = '1.0'
+
+ task apiJar(type: Jar) {
+ from sourceSets.main.output
+ baseName "root-api"
+ exclude "**/impl/**"
+ }
+
+ publishing {
+ repositories {
+ maven { url "${mavenRepo.uri}" }
+ }
+ publications {
+ impl(MavenPublication) {
+ groupId "org.custom"
+ artifactId "custom"
+ version "2.2"
+ from components.java
+ }
+ api(MavenPublication) {
+ groupId "org.custom"
+ artifactId "custom-api"
+ version "2"
+ artifact(apiJar)
+ }
+ }
+ }
+ """
+
+ when:
+ succeeds 'publish'
+
+ then:
+ file('build/libs').assertHasDescendants("root-1.0.jar", "root-api-1.0.jar")
+
+ and:
+ module.assertPublishedAsJavaModule()
+ module.moduleDir.file('custom-2.2.jar').assertIsCopyOf(file('build/libs/root-1.0.jar'))
+
+ and:
+ apiModule.assertPublishedAsJavaModule()
+ apiModule.moduleDir.file('custom-api-2.jar').assertIsCopyOf(file('build/libs/root-api-1.0.jar'))
+
+ and:
+ resolveArtifacts(module) == ['custom-2.2.jar']
+ resolveArtifacts(apiModule) == ['custom-api-2.jar']
+ }
+
+}
diff --git a/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishCrossVersionIntegrationTest.groovy b/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishCrossVersionIntegrationTest.groovy
index cafeb28..6c3cc88 100644
--- a/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishCrossVersionIntegrationTest.groovy
+++ b/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishCrossVersionIntegrationTest.groovy
@@ -29,9 +29,9 @@ class MavenPublishCrossVersionIntegrationTest extends CrossVersionIntegrationSpe
projectPublishedUsingMavenPublishPlugin('java')
expect:
- consumePublicationWithPreviousVersion('')
+ consumePublicationWithPreviousVersion()
- file('build/resolved').assertHasDescendants('published-1.9.jar', 'commons-collections-3.0.jar')
+ file('build/resolved').assertHasDescendants('published-1.9.jar', 'test-project-1.2.jar')
}
def "maven war publication generated by maven-publish plugin can be consumed by previous versions of Gradle"() {
@@ -39,12 +39,14 @@ class MavenPublishCrossVersionIntegrationTest extends CrossVersionIntegrationSpe
projectPublishedUsingMavenPublishPlugin('web')
expect:
- consumePublicationWithPreviousVersion('@war')
+ consumePublicationWithPreviousVersion()
file('build/resolved').assertHasDescendants('published-1.9.war')
}
def projectPublishedUsingMavenPublishPlugin(def componentToPublish) {
+ repo.module("org.gradle", "test-project", "1.2").publish()
+
settingsFile.text = "rootProject.name = 'published'"
buildFile.text = """
@@ -55,10 +57,10 @@ group = 'org.gradle.crossversion'
version = '1.9'
repositories {
- mavenCentral()
+ maven { url "${repo.uri}" }
}
dependencies {
- compile "commons-collections:commons-collections:3.0"
+ compile "org.gradle:test-project:1.2"
}
publishing {
repositories {
@@ -66,7 +68,7 @@ publishing {
}
publications {
maven(MavenPublication) {
- from components['${componentToPublish}']
+ from components.${componentToPublish}
}
}
}
@@ -75,7 +77,7 @@ publishing {
version current withTasks 'publish' run()
}
- def consumePublicationWithPreviousVersion(def artifact) {
+ def consumePublicationWithPreviousVersion() {
settingsFile.text = "rootProject.name = 'consumer'"
buildFile.text = """
@@ -83,11 +85,10 @@ configurations {
lib
}
repositories {
- mavenCentral()
mavenRepo(urls: ['${repo.uri}'])
}
dependencies {
- lib 'org.gradle.crossversion:published:1.9$artifact'
+ lib 'org.gradle.crossversion:published:1.9'
}
task retrieve(type: Sync) {
into 'build/resolved'
@@ -95,6 +96,6 @@ task retrieve(type: Sync) {
}
"""
- version previous withDeprecationChecksDisabled() withTasks 'retrieve' run()
+ version previous requireOwnGradleUserHomeDir() withDeprecationChecksDisabled() withTasks 'retrieve' run()
}
}
diff --git a/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishIdentifierValidationIntegTest.groovy b/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishIdentifierValidationIntegTest.groovy
index 808a064..4fcca2f 100644
--- a/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishIdentifierValidationIntegTest.groovy
+++ b/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishIdentifierValidationIntegTest.groovy
@@ -15,7 +15,7 @@
*/
package org.gradle.api.publish.maven
-import org.gradle.test.fixtures.publish.Identifier
+import org.gradle.test.fixtures.encoding.Identifier
import spock.lang.Unroll
class MavenPublishIdentifierValidationIntegTest extends AbstractMavenPublishIntegTest {
@@ -142,7 +142,7 @@ class MavenPublishIdentifierValidationIntegTest extends AbstractMavenPublishInte
fails 'publish'
then:
- failure.assertHasDescription "Execution failed for task ':publishMavenPublicationToMavenRepository'"
+ failure.assertHasDescription "Execution failed for task ':publishMavenPublicationToMavenRepository'."
failure.assertHasCause "Failed to publish publication 'maven' to repository 'maven'"
failure.assertHasCause "Invalid publication 'maven': groupId cannot be empty"
}
diff --git a/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishIssuesIntegTest.groovy b/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishIssuesIntegTest.groovy
index 192f69f..2c25eae 100644
--- a/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishIssuesIntegTest.groovy
+++ b/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishIssuesIntegTest.groovy
@@ -108,4 +108,55 @@ publishing {
succeeds "publish"
}
+ @Issue("GRADLE-2837")
+ def "project is properly configured when it is the target of a project dependency"() {
+ given:
+ mavenRepo.module("org.gradle", "dep", "1.1").publish()
+
+ and:
+ settingsFile << "include ':main', ':util'"
+
+ buildFile << """
+subprojects {
+ apply plugin: 'java'
+ apply plugin: 'maven-publish'
+ group = 'my.org'
+ version = '1.0'
+ repositories {
+ maven { url "${mavenRepo.uri}" }
+ }
+ publishing {
+ repositories {
+ maven { url "${mavenRepo.uri}" }
+ }
+ publications {
+ mavenJava(MavenPublication) {
+ from components.java
+ }
+ }
+ }
+}
+"""
+ file("main", "build.gradle") << """
+ dependencies {
+ compile project(':util')
+ }
+"""
+
+ file("util", "build.gradle") << """
+ dependencies {
+ compile 'org.gradle:dep:1.1'
+ }
+"""
+
+ when:
+ succeeds "publish"
+
+ then:
+ def mainPom = mavenRepo.module('my.org', 'main', '1.0').parsedPom
+ mainPom.scopes.runtime.expectDependency('my.org:util:1.0')
+
+ def utilPom = mavenRepo.module('my.org', 'util', '1.0').parsedPom
+ utilPom.scopes.runtime.expectDependency('org.gradle:dep:1.1')
+ }
}
diff --git a/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishJavaIntegTest.groovy b/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishJavaIntegTest.groovy
index 498b7a9..14ea632 100644
--- a/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishJavaIntegTest.groovy
+++ b/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishJavaIntegTest.groovy
@@ -70,38 +70,10 @@ class MavenPublishJavaIntegTest extends AbstractMavenPublishIntegTest {
mavenModule.assertArtifactsPublished("publishTest-1.9.jar", "publishTest-1.9.pom", "publishTest-1.9-source.jar")
and:
+ resolveArtifacts(mavenModule) == ["commons-collections-3.2.1.jar", "commons-io-1.4.jar", "publishTest-1.9.jar"]
resolveArtifacts(mavenModule, [classifier: 'source']) == ["commons-collections-3.2.1.jar", "commons-io-1.4.jar", "publishTest-1.9-source.jar", "publishTest-1.9.jar"]
}
- public void "can configure artifacts added from component"() {
- given:
- createBuildScripts("""
- publishing {
- publications {
- maven(MavenPublication) {
- from components.java
- }
- }
- publications.maven.artifacts.each {
- if (it.extension == 'jar') {
- it.classifier = 'classified'
- }
- }
- }
-""")
-
- when:
- run "publish"
-
- then:
- def mavenModule = mavenRepo.module("org.gradle.test", "publishTest", "1.9")
- mavenModule.assertPublished()
- mavenModule.assertArtifactsPublished("publishTest-1.9-classified.jar", "publishTest-1.9.pom")
-
- and:
- resolveArtifact(mavenModule, 'jar', 'classified') == ["publishTest-1.9-classified.jar"]
- }
-
def createBuildScripts(def append) {
settingsFile << "rootProject.name = 'publishTest' "
diff --git a/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishMultiProjectIntegTest.groovy b/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishMultiProjectIntegTest.groovy
index 1488ff4..10cfcc9 100644
--- a/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishMultiProjectIntegTest.groovy
+++ b/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishMultiProjectIntegTest.groovy
@@ -16,8 +16,6 @@
package org.gradle.api.publish.maven
-import spock.lang.Ignore
-
class MavenPublishMultiProjectIntegTest extends AbstractMavenPublishIntegTest {
def project1 = mavenRepo.module("org.gradle.test", "project1", "1.0")
def project2 = mavenRepo.module("org.gradle.test", "project2", "2.0")
@@ -33,6 +31,62 @@ class MavenPublishMultiProjectIntegTest extends AbstractMavenPublishIntegTest {
projectsCorrectlyPublished()
}
+ def "project dependencies reference publication identity of dependent project"() {
+ def project3 = mavenRepo.module("changed.group", "changed-artifact-id", "changed")
+
+ createBuildScripts("""
+project(":project3") {
+ publishing {
+ publications.maven {
+ groupId "changed.group"
+ artifactId "changed-artifact-id"
+ version "changed"
+ }
+ }
+}
+""")
+
+ when:
+ run "publish"
+
+ then:
+ project1.assertPublishedAsJavaModule()
+ project1.parsedPom.scopes.runtime.assertDependsOn("changed.group:changed-artifact-id:changed", "org.gradle.test:project2:2.0")
+
+ project2.assertPublishedAsJavaModule()
+ project2.parsedPom.scopes.runtime.assertDependsOn("changed.group:changed-artifact-id:changed")
+
+ project3.assertPublishedAsJavaModule()
+ project3.parsedPom.scopes.runtime == null
+
+ and:
+ resolveArtifacts(project1) == ['changed-artifact-id-changed.jar', 'project1-1.0.jar', 'project2-2.0.jar']
+ }
+
+ def "reports failure when project dependency references a project with multiple publications"() {
+ createBuildScripts("""
+project(":project3") {
+ publishing {
+ publications {
+ extraMaven(MavenPublication) {
+ from components.java
+ groupId "extra.group"
+ artifactId "extra-artifact"
+ version "extra"
+ }
+ }
+ }
+}
+""")
+
+ when:
+ fails "publish"
+
+ then:
+ failure.assertHasDescription "A problem occurred configuring project ':project1'."
+ failure.assertHasCause "Publishing is not yet able to resolve a dependency on a project with multiple different publications."
+ }
+
def "maven-publish plugin does not take archivesBaseName into account when publishing"() {
createBuildScripts("""
project(":project2") {
@@ -132,36 +186,6 @@ project(":project2") {
project1.parsedPom.scopes.runtime.assertDependsOn("org.gradle.test:project2:2.0")
}
- @Ignore("This does not work: fix this as part of making the project coordinates customisable via DSL (using new mechanism to set artifactId")
- def "project dependency correctly reflected in POM if dependency publication pom is changed"() {
- createBuildScripts("""
-project(":project1") {
- dependencies {
- compile project(":project2")
- }
-}
-
-project(":project2") {
- publishing {
- publications {
- maven {
- pom.withXml {
- asNode().artifactId[0].value = "changed"
- }
- }
- }
- }
-}
- """)
-
- when:
- run ":project1:publish"
-
- then:
- def pom = project1.parsedPom
- pom.scopes.runtime.assertDependsOn("org.gradle.test:changed:1.9")
- }
-
private void createBuildScripts(String append = "") {
settingsFile << """
include "project1", "project2", "project3"
diff --git a/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishPomCustomisationIntegTest.groovy b/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishPomCustomisationIntegTest.groovy
deleted file mode 100644
index a167328..0000000
--- a/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishPomCustomisationIntegTest.groovy
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.publish.maven
-
-import org.gradle.integtests.fixtures.AbstractIntegrationSpec
-import org.gradle.util.SetSystemProperties
-import org.junit.Rule
-
-/**
- * Tests maven POM customisation
- */
-class MavenPublishPomCustomisationIntegTest extends AbstractIntegrationSpec {
- @Rule SetSystemProperties sysProp = new SetSystemProperties()
-
- def "can customise pom xml"() {
- given:
- settingsFile << "rootProject.name = 'customisePom'"
- buildFile << """
- apply plugin: 'maven-publish'
-
- group = 'org.gradle.test'
- version = '1.0'
-
- publishing {
- repositories {
- maven { url "${mavenRepo.uri}" }
- }
- publications {
- mavenCustom(MavenPublication) {
- pom.withXml {
- asNode().appendNode('description', "custom-description")
-
- def dependency = asNode().appendNode('dependencies').appendNode('dependency')
- dependency.appendNode('groupId', 'junit')
- dependency.appendNode('artifactId', 'junit')
- dependency.appendNode('version', '4.11')
- dependency.appendNode('scope', 'runtime')
- }
- }
- }
- }
- """
- when:
- succeeds 'publish'
-
- then:
- def module = mavenRepo.module('org.gradle.test', 'customisePom', '1.0')
- module.assertPublished()
- module.parsedPom.description == 'custom-description'
- module.parsedPom.scopes.runtime.assertDependsOn("junit:junit:4.11")
- }
-
- def "can generate pom file without publishing"() {
- given:
- settingsFile << "rootProject.name = 'generatePom'"
- buildFile << """
- apply plugin: 'maven-publish'
-
- group = 'org.gradle.test'
- version = '1.0'
-
- publishing {
- repositories {
- maven { url "${mavenRepo.uri}" }
- }
- publications {
- emptyMaven(MavenPublication) {
- pom.withXml {
- asNode().appendNode('description', "Test for pom generation")
- }
- }
- }
- generatePomFileForEmptyMavenPublication {
- destination = 'build/generated-pom.xml'
- }
- }
- """
-
- when:
- run "generatePomFileForEmptyMavenPublication"
-
- then:
- def mavenModule = mavenRepo.module("org.gradle.test", "generatePom", "1.0")
- mavenModule.assertNotPublished()
-
- and:
- file('build/generated-pom.xml').assertIsFile()
- def pom = new org.gradle.test.fixtures.maven.MavenPom(file('build/generated-pom.xml'))
- pom.groupId == "org.gradle.test"
- pom.artifactId == "generatePom"
- pom.version == "1.0"
- pom.description == "Test for pom generation"
- }
-
- def "has reasonable error message when withXml fails"() {
- given:
- settingsFile << "rootProject.name = 'root'"
- buildFile << """
- apply plugin: 'maven-publish'
- apply plugin: 'java'
-
- group = 'group'
- version = '1.0'
-
- publishing {
- repositories {
- maven { url "${mavenRepo.uri}" }
- }
- publications {
- maven(MavenPublication) {
- pom.withXml {
- asNode().foo = 'this is not a real element'
- }
- }
- }
- }
- """
- when:
- fails 'publish'
-
- then:
- failure.assertHasDescription("Execution failed for task ':generatePomFileForMavenPublication'")
- failure.assertHasCause("Could not apply withXml() to generated POM")
- failure.assertHasCause("No such property: foo for class: groovy.util.Node")
- }
-
- def "has reasonable error message when withXml produces invalid POM file"() {
- given:
- settingsFile << "rootProject.name = 'root'"
- buildFile << """
- apply plugin: 'maven-publish'
- apply plugin: 'java'
-
- group = 'group'
- version = '1.0'
-
- publishing {
- repositories {
- maven { url "${mavenRepo.uri}" }
- }
- publications {
- maven(MavenPublication) {
- pom.withXml {
- asNode().appendNode('invalid-node', "This is not a valid node for a Maven POM")
- }
- }
- }
- }
- """
- when:
- fails 'publish'
-
- then:
- failure.assertHasDescription("Execution failed for task ':publishMavenPublicationToMavenRepository'")
- failure.assertHasCause("Failed to publish publication 'maven' to repository 'maven'")
- failure.assertHasCause("Invalid publication 'maven': POM file is invalid. Check any modifications you have made to the POM file.")
- }
-}
diff --git a/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishPomCustomizationIntegTest.groovy b/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishPomCustomizationIntegTest.groovy
new file mode 100644
index 0000000..8ea7e27
--- /dev/null
+++ b/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishPomCustomizationIntegTest.groovy
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.publish.maven
+
+import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+import org.gradle.util.SetSystemProperties
+import org.junit.Rule
+
+/**
+ * Tests maven POM customization
+ */
+class MavenPublishPomCustomizationIntegTest extends AbstractIntegrationSpec {
+ @Rule SetSystemProperties sysProp = new SetSystemProperties()
+
+ def "can customize pom xml"() {
+ given:
+ settingsFile << "rootProject.name = 'customizePom'"
+ buildFile << """
+ apply plugin: 'maven-publish'
+
+ group = 'org.gradle.test'
+ version = '1.0'
+
+ publishing {
+ repositories {
+ maven { url "${mavenRepo.uri}" }
+ }
+ publications {
+ mavenCustom(MavenPublication) {
+ pom.packaging "custom-packaging"
+ pom.withXml {
+ asNode().appendNode('description', "custom-description")
+
+ def dependency = asNode().appendNode('dependencies').appendNode('dependency')
+ dependency.appendNode('groupId', 'junit')
+ dependency.appendNode('artifactId', 'junit')
+ dependency.appendNode('version', '4.11')
+ dependency.appendNode('scope', 'runtime')
+ }
+ }
+ }
+ }
+ """
+ when:
+ succeeds 'publish'
+
+ then:
+ def module = mavenRepo.module('org.gradle.test', 'customizePom', '1.0')
+ module.assertPublished()
+ module.parsedPom.description == 'custom-description'
+ module.parsedPom.packaging == 'custom-packaging'
+ module.parsedPom.scopes.runtime.assertDependsOn("junit:junit:4.11")
+ }
+
+ def "can generate pom file without publishing"() {
+ given:
+ settingsFile << "rootProject.name = 'generatePom'"
+ buildFile << """
+ apply plugin: 'maven-publish'
+
+ group = 'org.gradle.test'
+ version = '1.0'
+
+ publishing {
+ repositories {
+ maven { url "${mavenRepo.uri}" }
+ }
+ publications {
+ emptyMaven(MavenPublication) {
+ pom.withXml {
+ asNode().appendNode('description', "Test for pom generation")
+ }
+ }
+ }
+ generatePomFileForEmptyMavenPublication {
+ destination = 'build/generated-pom.xml'
+ }
+ }
+ """
+
+ when:
+ run "generatePomFileForEmptyMavenPublication"
+
+ then:
+ def mavenModule = mavenRepo.module("org.gradle.test", "generatePom", "1.0")
+ mavenModule.assertNotPublished()
+
+ and:
+ file('build/generated-pom.xml').assertIsFile()
+ def pom = new org.gradle.test.fixtures.maven.MavenPom(file('build/generated-pom.xml'))
+ pom.groupId == "org.gradle.test"
+ pom.artifactId == "generatePom"
+ pom.version == "1.0"
+ pom.description == "Test for pom generation"
+ }
+
+ def "has reasonable error message when withXml fails"() {
+ given:
+ settingsFile << "rootProject.name = 'root'"
+ buildFile << """
+ apply plugin: 'maven-publish'
+ apply plugin: 'java'
+
+ group = 'group'
+ version = '1.0'
+
+ publishing {
+ repositories {
+ maven { url "${mavenRepo.uri}" }
+ }
+ publications {
+ maven(MavenPublication) {
+ pom.withXml {
+ asNode().foo = 'this is not a real element'
+ }
+ }
+ }
+ }
+ """
+ when:
+ fails 'publish'
+
+ then:
+ failure.assertHasDescription("Execution failed for task ':generatePomFileForMavenPublication'.")
+ failure.assertHasCause("Could not apply withXml() to generated POM")
+ failure.assertHasCause("No such property: foo for class: groovy.util.Node")
+ }
+
+ def "has reasonable error message when withXml produces invalid POM file"() {
+ given:
+ settingsFile << "rootProject.name = 'root'"
+ buildFile << """
+ apply plugin: 'maven-publish'
+ apply plugin: 'java'
+
+ group = 'group'
+ version = '1.0'
+
+ publishing {
+ repositories {
+ maven { url "${mavenRepo.uri}" }
+ }
+ publications {
+ maven(MavenPublication) {
+ pom.withXml {
+ asNode().appendNode('invalid-node', "This is not a valid node for a Maven POM")
+ }
+ }
+ }
+ }
+ """
+ when:
+ fails 'publish'
+
+ then:
+ failure.assertHasDescription("Execution failed for task ':publishMavenPublicationToMavenRepository'.")
+ failure.assertHasCause("Failed to publish publication 'maven' to repository 'maven'")
+ failure.assertHasCause("Invalid publication 'maven': POM file is invalid. Check any modifications you have made to the POM file.")
+ }
+
+ def "has reasonable error message when withXML modifies publication coordinates"() {
+ when:
+ settingsFile << "rootProject.name = 'root'"
+ buildFile << """
+ apply plugin: 'maven-publish'
+ apply plugin: 'java'
+
+ publishing {
+ repositories {
+ maven { url "${mavenRepo.uri}" }
+ }
+ publications {
+ maven(MavenPublication) {
+ groupId "group"
+ artifactId "artifact"
+ version "1.0"
+
+ pom.withXml {
+ asNode().version[0].value = "2.0"
+ }
+ }
+ }
+ }
+ """
+ fails 'publish'
+
+ then:
+ failure.assertHasDescription("Execution failed for task ':publishMavenPublicationToMavenRepository'.")
+ failure.assertHasCause("Failed to publish publication 'maven' to repository 'maven'")
+ failure.assertHasCause("Invalid publication 'maven': supplied version does not match POM file (cannot edit version directly in the POM file).")
+ }
+}
diff --git a/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/SamplesMavenPublishIntegrationTest.groovy b/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/SamplesMavenPublishIntegrationTest.groovy
index cc8ec70..21ca57e 100644
--- a/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/SamplesMavenPublishIntegrationTest.groovy
+++ b/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/SamplesMavenPublishIntegrationTest.groovy
@@ -16,15 +16,19 @@
package org.gradle.api.publish.maven
+
import org.gradle.integtests.fixtures.AbstractIntegrationSpec
import org.gradle.integtests.fixtures.Sample
import org.gradle.test.fixtures.maven.M2Installation
+import org.gradle.test.fixtures.maven.MavenFileModule
+import org.gradle.util.TextUtil
import org.junit.Rule
public class SamplesMavenPublishIntegrationTest extends AbstractIntegrationSpec {
@Rule public final Sample quickstart = new Sample(temporaryFolder, "maven-publish/quickstart")
@Rule public final Sample javaProject = new Sample(temporaryFolder, "maven-publish/javaProject")
@Rule public final Sample pomCustomization = new Sample(temporaryFolder, "maven-publish/pomCustomization")
+ @Rule public final Sample multiPublish = new Sample(temporaryFolder, "maven-publish/multiple-publications")
def quickstartPublish() {
given:
@@ -95,6 +99,42 @@ public class SamplesMavenPublishIntegrationTest extends AbstractIntegrationSpec
then:
module.assertPublishedAsPomModule()
- module.parsedPom.description == "A demonstration of maven pom customisation"
+ module.parsedPom.description == "A demonstration of maven POM customization"
+ }
+
+ def multiplePublications() {
+ given:
+ sample multiPublish
+
+ and:
+ def fileRepo = maven(multiPublish.dir.file("build/repo"))
+ def project1sample = fileRepo.module("org.gradle.sample", "project1-sample", "1.1")
+ def project2api = fileRepo.module("org.gradle.sample", "project2-api", "2")
+ def project2impl = fileRepo.module("org.gradle.sample.impl", "project2-impl", "2.3")
+
+ when:
+ succeeds "publish"
+
+ then:
+ project1sample.assertPublishedAsJavaModule()
+ verifyPomFile(project1sample, "output/project1.pom.xml")
+
+ and:
+ project2api.assertPublishedAsJavaModule()
+ verifyPomFile(project2api, "output/project2-api.pom.xml")
+
+ and:
+ project2impl.assertPublishedAsJavaModule()
+ verifyPomFile(project2impl, "output/project2-impl.pom.xml")
+ }
+
+ private void verifyPomFile(MavenFileModule module, String outputFileName) {
+ def actualIvyXmlText = module.pomFile.text.replaceFirst('publication="\\d+"', 'publication="«PUBLICATION-TIME-STAMP»"').trim()
+ assert actualIvyXmlText == getExpectedIvyOutput(multiPublish.dir.file(outputFileName))
+ }
+
+ String getExpectedIvyOutput(File outputFile) {
+ assert outputFile.file
+ outputFile.readLines()[1..-1].join(TextUtil.getPlatformLineSeparator()).trim()
}
}
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/artifacts/maven/Conf2ScopeMapping.java b/subprojects/maven/src/main/groovy/org/gradle/api/artifacts/maven/Conf2ScopeMapping.java
index 566aaf4..300dd0b 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/artifacts/maven/Conf2ScopeMapping.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/artifacts/maven/Conf2ScopeMapping.java
@@ -20,8 +20,6 @@ import org.gradle.api.artifacts.Configuration;
/**
* An immutable mapping to map a dependency configuration to a Maven scope. This class has implemented equality and
* hashcode based on its values not on object identity.
- *
- * @author Hans Dockter
* @see org.gradle.api.artifacts.maven.Conf2ScopeMappingContainer
*/
public class Conf2ScopeMapping {
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/artifacts/maven/Conf2ScopeMappingContainer.java b/subprojects/maven/src/main/groovy/org/gradle/api/artifacts/maven/Conf2ScopeMappingContainer.java
index 5171b9a..8859781 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/artifacts/maven/Conf2ScopeMappingContainer.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/artifacts/maven/Conf2ScopeMappingContainer.java
@@ -21,10 +21,8 @@ import java.util.Collection;
import java.util.Map;
/**
- * Defines a set of rules for how to map the Gradle dependencies to a pom. This mapping is based
+ * Defines a set of rules for how to map the Gradle dependencies to a POM. This mapping is based
* on the configuration the dependencies belong to.
- *
- * @author Hans Dockter
*/
public interface Conf2ScopeMappingContainer {
String PROVIDED = "provided";
@@ -49,8 +47,8 @@ public interface Conf2ScopeMappingContainer {
/**
* Returns a scope that corresponds to the given configurations. Dependencies of different configurations can
- * be equal. But only one of those equals dependencies (which might differ in content) can be mapped to a pom
- * (due to the the nature of a Maven pom).
+ * be equal. But only one of those equals dependencies (which might differ in content) can be mapped to a POM
+ * (due to the the nature of a Maven POM).
*
* <p>Which scope is returned depends on the existing mappings. See {@link #addMapping(int, Configuration, String)}. If
* only one configuration is mapped, this mapping is used to choose the scope. If more than one configuration of a
@@ -81,7 +79,7 @@ public interface Conf2ScopeMappingContainer {
/**
* Sets, whether unmapped configuration should be skipped or not. If this is set to
- * false, dependencies belonging to unmapped configurations will be added to the Maven pom with no
+ * false, dependencies belonging to unmapped configurations will be added to the Maven POM with no
* scope specified. This means they belong to the Maven default scope, which is 'compile'.
*/
void setSkipUnmappedConfs(boolean skipDependenciesWithUnmappedConfiguration);
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/artifacts/maven/GroovyMavenDeployer.java b/subprojects/maven/src/main/groovy/org/gradle/api/artifacts/maven/GroovyMavenDeployer.java
index b04edfe..f027ba8 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/artifacts/maven/GroovyMavenDeployer.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/artifacts/maven/GroovyMavenDeployer.java
@@ -30,8 +30,6 @@ package org.gradle.api.artifacts.maven;
*
* This call set the repository object and also returns an instance of this object. If you use 'snapshotRepository'
* instead of repository, the snapshot repository is build.
- *
- * @author Hans Dockter
* @see MavenDeployer
*/
public interface GroovyMavenDeployer extends MavenDeployer {
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/artifacts/maven/MavenDeployer.java b/subprojects/maven/src/main/groovy/org/gradle/api/artifacts/maven/MavenDeployer.java
index 0c7a609..f9cdd38 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/artifacts/maven/MavenDeployer.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/artifacts/maven/MavenDeployer.java
@@ -24,15 +24,13 @@ import java.util.Collection;
* deployment, including snapshot deployment and metadata.xml manipulation.</p>
*
* <p>You have to specify at least one repository. Otherwise, if there is only one artifact, usually there is not more
- * to do. If there is more than one artifact you have to decide what to do about this, as a Maven pom can only deal with
+ * to do. If there is more than one artifact you have to decide what to do about this, as a Maven POM can only deal with
* one artifact. There are two strategies. If you want to deploy only one artifact you have to specify a filter to
* select this artifact. If you want to deploy more than one artifact, you have to specify filters which select each
- * artifact. Associated with each filter is a separate configurable pom.</p>
+ * artifact. Associated with each filter is a separate configurable POM.</p>
*
* <p>You can create an instance of this type via the {@link org.gradle.api.tasks.Upload#getRepositories()}
* container</p>
- *
- * @author Hans Dockter
*/
public interface MavenDeployer extends MavenResolver {
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/artifacts/maven/MavenDeployment.java b/subprojects/maven/src/main/groovy/org/gradle/api/artifacts/maven/MavenDeployment.java
index 8bddc3c..356dcef 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/artifacts/maven/MavenDeployment.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/artifacts/maven/MavenDeployment.java
@@ -20,7 +20,7 @@ import org.gradle.api.artifacts.PublishArtifact;
import java.util.Set;
/**
- * Represents the artifacts which will be deployed to a maven repository. You can use this interface to modify the set
+ * Represents the artifacts which will be deployed to a Maven repository. You can use this interface to modify the set
* of artifacts.
*/
public interface MavenDeployment {
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/artifacts/maven/MavenPom.java b/subprojects/maven/src/main/groovy/org/gradle/api/artifacts/maven/MavenPom.java
index 95e4829..df10201 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/artifacts/maven/MavenPom.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/artifacts/maven/MavenPom.java
@@ -24,22 +24,20 @@ import java.io.Writer;
import java.util.List;
/**
- * Is used for generating a Maven pom file and customizing the generation.
- * To learn about the Maven pom see: <a href="http://maven.apache.org/pom.html">http://maven.apache.org/pom.html</a>
- *
- * @author Hans Dockter
+ * Is used for generating a Maven POM file and customizing the generation.
+ * To learn about the Maven POM see: <a href="http://maven.apache.org/pom.html">http://maven.apache.org/pom.html</a>
*/
public interface MavenPom {
String POM_FILE_ENCODING = "UTF-8";
/**
- * Returns the scope mappings used for generating this pom.
+ * Returns the scope mappings used for generating this POM.
*/
Conf2ScopeMappingContainer getScopeMappings();
/**
- * Provides a builder for the Maven pom for adding or modifying properties of the Maven {@link #getModel()}.
+ * Provides a builder for the Maven POM for adding or modifying properties of the Maven {@link #getModel()}.
* The syntax is exactly the same as used by polyglot Maven. For example:
*
* <pre>
@@ -155,38 +153,38 @@ public interface MavenPom {
MavenPom setModel(Object model);
/**
- * Writes the {@link #getEffectivePom()} xml to a writer while applying the {@link #withXml(org.gradle.api.Action)} actions. Closes the supplied
+ * Writes the {@link #getEffectivePom()} XML to a writer while applying the {@link #withXml(org.gradle.api.Action)} actions. Closes the supplied
* Writer when finished.
*
- * @param writer The writer to write the pom xml.
+ * @param writer The writer to write the POM to.
* @return this
*/
MavenPom writeTo(Writer writer);
/**
- * Writes the {@link #getEffectivePom()} xml to a file while applying the {@link #withXml(org.gradle.api.Action)} actions.
+ * Writes the {@link #getEffectivePom()} XML to a file while applying the {@link #withXml(org.gradle.api.Action)} actions.
* The path is resolved as defined by {@link org.gradle.api.Project#files(Object...)}
* The file will be encoded as UTF-8.
*
- * @param path The path of the file to write the pom xml into.
+ * @param path The path of the file to write the POM into.
* @return this
*/
MavenPom writeTo(Object path);
/**
- * <p>Adds a closure to be called when the pom has been configured. The pom is passed to the closure as a
+ * <p>Adds a closure to be called when the POM has been configured. The POM is passed to the closure as a
* parameter.</p>
*
- * @param closure The closure to execute when the pom has been configured.
+ * @param closure The closure to execute when the POM has been configured.
* @return this
*/
MavenPom whenConfigured(Closure closure);
/**
- * <p>Adds an action to be called when the pom has been configured. The pom is passed to the action as a
+ * <p>Adds an action to be called when the POM has been configured. The POM is passed to the action as a
* parameter.</p>
*
- * @param action The action to execute when the pom has been configured.
+ * @param action The action to execute when the POM has been configured.
* @return this
*/
MavenPom whenConfigured(Action<MavenPom> action);
@@ -210,20 +208,20 @@ public interface MavenPom {
MavenPom withXml(Action<XmlProvider> action);
/**
- * Returns the configuration container used for mapping configurations to maven scopes.
+ * Returns the configuration container used for mapping configurations to Maven scopes.
*/
ConfigurationContainer getConfigurations();
/**
- * Sets the configuration container used for mapping configurations to maven scopes.
+ * Sets the configuration container used for mapping configurations to Maven scopes.
* @return this
*/
MavenPom setConfigurations(ConfigurationContainer configurations);
/**
- * Returns a pom with the generated dependencies and the {@link #whenConfigured(org.gradle.api.Action)} actions applied.
+ * Returns a POM with the generated dependencies and the {@link #whenConfigured(org.gradle.api.Action)} actions applied.
*
- * @return the effective pom
+ * @return the effective POM
*/
MavenPom getEffectivePom();
}
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/artifacts/maven/MavenResolver.java b/subprojects/maven/src/main/groovy/org/gradle/api/artifacts/maven/MavenResolver.java
index 0cd890a..2816660 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/artifacts/maven/MavenResolver.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/artifacts/maven/MavenResolver.java
@@ -21,12 +21,10 @@ import org.gradle.api.artifacts.repositories.ArtifactRepository;
/**
* An {@link ArtifactRepository} which can be used to publish artifacts to Maven repositories.
- *
- * @author Hans Dockter
*/
public interface MavenResolver extends ArtifactRepository, PomFilterContainer {
/**
- * Returns a maven settings object. This can be used for example to figure out where the local repository is
+ * Returns a Maven settings object. This can be used for example to figure out where the local repository is
* located. This property is filled after publishing. Before this property is null.
*/
Object getSettings();
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/artifacts/maven/PomFilterContainer.java b/subprojects/maven/src/main/groovy/org/gradle/api/artifacts/maven/PomFilterContainer.java
index 263e57e..2051337 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/artifacts/maven/PomFilterContainer.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/artifacts/maven/PomFilterContainer.java
@@ -20,8 +20,6 @@ import org.gradle.api.publication.maven.internal.PomFilter;
/**
* Manages a set of {@link MavenPom} instances and their associated {@link PublishFilter} instances.
- *
- * @author Hans Dockter
*/
public interface PomFilterContainer {
String DEFAULT_ARTIFACT_POM_NAME = "default";
@@ -38,7 +36,7 @@ public interface PomFilterContainer {
* If at least one custom filter has been added the default filter is not used any longer.</p>
* <p>The default for this property is {@link PublishFilter#ALWAYS_ACCEPT}.
* If there is only one artifact you are fine with this filter. If there is more than one artifact, deployment will lead to
- * an exception, if you don't specify a filter that selects the artifact to deploy. If you want to deploy more than one artiact you have
+ * an exception, if you don't specify a filter that selects the artifact to deploy. If you want to deploy more than one artifact you have
* to use the (see {@link #addFilter(String, org.gradle.api.artifacts.maven.PublishFilter)} method.</p>
*
* @param defaultFilter
@@ -47,22 +45,22 @@ public interface PomFilterContainer {
void setFilter(PublishFilter defaultFilter);
/**
- * Returns the pom property of the custom filter.
- * The pom property can be used to customize the pom generation. By default the properties of such a pom object are all null.
- * Null means that Gradle will use default values for generating the Maven pom. Those default values are derived from the deployable artifact
- * and from the project type (e.g. java, war, ...). If you explicitly set a pom property, Gradle will use those instead.
+ * Returns the POM property of the custom filter.
+ * The POM property can be used to customize the POM generation. By default the properties of such a POM object are all null.
+ * Null means that Gradle will use default values for generating the Maven POM. Those default values are derived from the deployable artifact
+ * and from the project type (e.g. java, war, ...). If you explicitly set a POM property, Gradle will use those instead.
*
* @return The Maven Pom
*/
MavenPom getPom();
/**
- * <p>Sets the default pom to be used. This pom is active if no custom filters have been added (see {@link #addFilter(String, org.gradle.api.artifacts.maven.PublishFilter)}).
- * If at least one custom filter has been added the default pom is not used any longer.</p>
- * <p>Usually you don't need to set this property as the default value provides you a pom object you might use for configuration.
- * By default the properties of such a pom object are all null.
- * If they are null, Gradle will use default values for generating the Maven pom. Those default values are derived from the deployable artifact
- * and from the project type (e.g. java, war, ...). If you explicitly set a pom property, Gradle will use this instead.</p>
+ * <p>Sets the default POM to be used. This POM is active if no custom filters have been added (see {@link #addFilter(String, org.gradle.api.artifacts.maven.PublishFilter)}).
+ * If at least one custom filter has been added the default POM is not used any longer.</p>
+ * <p>Usually you don't need to set this property as the default value provides you a POM object you might use for configuration.
+ * By default the properties of such a POM object are all null.
+ * If they are null, Gradle will use default values for generating the Maven POM. Those default values are derived from the deployable artifact
+ * and from the project type (e.g. java, war, ...). If you explicitly set a POM property, Gradle will use this instead.</p>
*
* @param defaultPom
*/
@@ -70,12 +68,12 @@ public interface PomFilterContainer {
/**
* If you want to deploy more than one artifact you need to define filters to select each of those artifacts. The method
- * returns a pom object associated with this filter, that allows you to customize the pom generation for the artifact selected
+ * returns a POM object associated with this filter, that allows you to customize the POM generation for the artifact selected
* by the filter.
*
* @param name The name of the filter
* @param publishFilter The filter to use
- * @return The pom associated with the filter
+ * @return The POM associated with the filter
*/
MavenPom addFilter(String name, PublishFilter publishFilter);
@@ -84,7 +82,7 @@ public interface PomFilterContainer {
*
* @param name The name of the filter
* @param filter The filter
- * @return The Maven pom associated with the closure
+ * @return The Maven POM associated with the closure
* @see PublishFilter
* @see PomFilterContainer#addFilter(String, org.gradle.api.artifacts.maven.PublishFilter)
*/
@@ -107,27 +105,27 @@ public interface PomFilterContainer {
void filter(Closure filter);
/**
- * Returns the pom associated with a filter added with {@link #addFilter(String, org.gradle.api.artifacts.maven.PublishFilter)}.
+ * Returns the POM associated with a filter added with {@link #addFilter(String, org.gradle.api.artifacts.maven.PublishFilter)}.
*
* @param name The name of the filter.
*/
MavenPom pom(String name);
/**
- * Configures a pom by a closure. The closure statements are delegated to the pom object associated with the given name.
+ * Configures a POM by a closure. The closure statements are delegated to the POM object associated with the given name.
*
* @param name
* @param configureClosure
- * @return The pom object associated with the given name.
+ * @return The POM object associated with the given name.
* @see PomFilterContainer#pom(String)
*/
MavenPom pom(String name, Closure configureClosure);
/**
- * Configures the default pom by a closure. The closure statements are delegated to the default pom.
+ * Configures the default POM by a closure. The closure statements are delegated to the default POM.
*
* @param configureClosure
- * @return The default pom.
+ * @return The default POM.
* @see PomFilterContainer#getPom()
*/
MavenPom pom(Closure configureClosure);
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/artifacts/maven/PublishFilter.java b/subprojects/maven/src/main/groovy/org/gradle/api/artifacts/maven/PublishFilter.java
index 2461e95..eb2a03c 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/artifacts/maven/PublishFilter.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/artifacts/maven/PublishFilter.java
@@ -22,8 +22,6 @@ import java.io.File;
/**
* A filter for artifacts to be published.
- *
- * @author Hans Dockter
*/
public interface PublishFilter {
PublishFilter ALWAYS_ACCEPT = new PublishFilter() {
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/plugins/MavenPlugin.java b/subprojects/maven/src/main/groovy/org/gradle/api/plugins/MavenPlugin.java
index 6fdaee1..f418676 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/plugins/MavenPlugin.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/plugins/MavenPlugin.java
@@ -40,8 +40,6 @@ import javax.inject.Inject;
/**
* <p>A {@link org.gradle.api.Plugin} which allows project artifacts to be deployed to a Maven repository, or installed
* to the local Maven cache.</p>
- *
- * @author Hans Dockter
*/
public class MavenPlugin implements Plugin<ProjectInternal> {
public static final int COMPILE_PRIORITY = 300;
@@ -124,11 +122,11 @@ public class MavenPlugin implements Plugin<ProjectInternal> {
}
private void configureInstall(Project project) {
- Upload installUpload = project.getTasks().add(INSTALL_TASK_NAME, Upload.class);
+ Upload installUpload = project.getTasks().create(INSTALL_TASK_NAME, Upload.class);
Configuration configuration = project.getConfigurations().getByName(Dependency.ARCHIVES_CONFIGURATION);
installUpload.setConfiguration(configuration);
MavenRepositoryHandlerConvention repositories = new DslObject(installUpload.getRepositories()).getConvention().getPlugin(MavenRepositoryHandlerConvention.class);
repositories.mavenInstaller();
- installUpload.setDescription("Does a maven install of the archives artifacts into the local .m2 cache.");
+ installUpload.setDescription("Installs the 'archives' artifacts into the local Maven repository.");
}
}
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/plugins/MavenPluginConvention.java b/subprojects/maven/src/main/groovy/org/gradle/api/plugins/MavenPluginConvention.java
index 60fe1a3..5eff207 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/plugins/MavenPluginConvention.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/plugins/MavenPluginConvention.java
@@ -31,8 +31,6 @@ import java.util.Collections;
/**
* Properties and methods added by the {@link org.gradle.api.plugins.MavenPlugin}.
- *
- * @author Hans Dockter
*/
public class MavenPluginConvention implements MavenPomMetaInfoProvider {
private final ProjectInternal project;
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/plugins/MavenRepositoryHandlerConvention.java b/subprojects/maven/src/main/groovy/org/gradle/api/plugins/MavenRepositoryHandlerConvention.java
index 40076e6..fc02fe4 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/plugins/MavenRepositoryHandlerConvention.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/plugins/MavenRepositoryHandlerConvention.java
@@ -22,7 +22,7 @@ import org.gradle.api.artifacts.maven.MavenResolver;
import java.util.Map;
/**
- * Allows maven repositories for publishing artifacts to be defined. The maven plugin mixes-in this interface to the {@link org.gradle.api.artifacts.dsl.RepositoryHandler} associated with each
+ * Allows Maven repositories for publishing artifacts to be defined. The Maven plugin mixes-in this interface to the {@link org.gradle.api.artifacts.dsl.RepositoryHandler} associated with each
* task of type {@link org.gradle.api.tasks.Upload}.
*/
public interface MavenRepositoryHandlerConvention {
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/plugins/maven/ConvertMaven2Gradle.groovy b/subprojects/maven/src/main/groovy/org/gradle/api/plugins/maven/ConvertMaven2Gradle.groovy
deleted file mode 100644
index 9697af0..0000000
--- a/subprojects/maven/src/main/groovy/org/gradle/api/plugins/maven/ConvertMaven2Gradle.groovy
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.plugins.maven
-
-import org.gradle.api.DefaultTask
-import org.gradle.api.Incubating
-import org.gradle.api.internal.artifacts.DependencyManagementServices
-import org.gradle.api.internal.artifacts.mvnsettings.MavenSettingsProvider
-import org.gradle.api.plugins.maven.internal.Maven2Gradle
-import org.gradle.api.plugins.maven.internal.MavenProjectsCreator
-import org.gradle.api.tasks.TaskAction
-import org.gradle.util.SingleMessageLogger
-
-import javax.inject.Inject
-
-/**
- * by Szczepan Faber, created at: 8/1/12
- */
- at Incubating
-class ConvertMaven2Gradle extends DefaultTask {
- private final MavenSettingsProvider settingsProvider
-
- @Inject
- ConvertMaven2Gradle(DependencyManagementServices managementServices) {
- this.settingsProvider = managementServices.get(MavenSettingsProvider)
- }
-
- @TaskAction
- void convertNow() {
- SingleMessageLogger.informAboutIncubating("Maven to Gradle conversion")
-
- def settings = settingsProvider.buildSettings()
-
- def mavenProjects = new MavenProjectsCreator().create(settings, project.file("pom.xml"))
-
- new Maven2Gradle(mavenProjects).convert()
- }
-}
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/plugins/maven/Maven2GradlePlugin.groovy b/subprojects/maven/src/main/groovy/org/gradle/api/plugins/maven/Maven2GradlePlugin.groovy
deleted file mode 100644
index cb89b74..0000000
--- a/subprojects/maven/src/main/groovy/org/gradle/api/plugins/maven/Maven2GradlePlugin.groovy
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.plugins.maven
-
-import org.gradle.api.Incubating
-import org.gradle.api.Plugin
-import org.gradle.api.Project
-
-/**
- * by Szczepan Faber, created at: 8/1/12
- */
- at Incubating
-class Maven2GradlePlugin implements Plugin<Project>{
- void apply(Project project) {
- project.task("maven2Gradle", type: ConvertMaven2Gradle) {
- group = 'Bootstrap experimental'
- description = '[incubating] Attempts to generate gradle builds from maven project.'
- }
- }
-}
\ No newline at end of file
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/plugins/maven/internal/Maven2Gradle.groovy b/subprojects/maven/src/main/groovy/org/gradle/api/plugins/maven/internal/Maven2Gradle.groovy
deleted file mode 100644
index 7c67fe2..0000000
--- a/subprojects/maven/src/main/groovy/org/gradle/api/plugins/maven/internal/Maven2Gradle.groovy
+++ /dev/null
@@ -1,552 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.plugins.maven.internal
-
-import org.gradle.mvn3.org.apache.maven.project.MavenProject
-import org.gradle.util.GFileUtils
-
-/**
- * This script obtains the effective pom of the current project, reads its dependencies
- * and generates build.gradle scripts. It also generates settings.gradle for multimodule builds. <br/>
- *
- * It currently supports both single-module and multi-module POMs, inheritance, dependency management, properties - everything.
- *
- * @author Antony Stubbs <antony.stubbs at gmail.com>
- * @author Baruch Sadogursky <jbaruch at sadogursky.com>
- * */
-class Maven2Gradle {
-
- def dependentWars = []
- def qualifiedNames
- def workingDir
- def effectivePom
-
- private Set<MavenProject> mavenProjects
-
- Maven2Gradle(Set<MavenProject> mavenProjects) {
- assert !mavenProjects.empty : "No maven projects provided."
- this.mavenProjects = mavenProjects
- }
-
- def convert() {
- workingDir = new File('.').canonicalFile
- println "Working path:" + workingDir.absolutePath + "\n"
-
- //For now we're building the effective pom xml from the model
- //and then we parse the xml using slurper.
- //This way we don't have to rewrite the Maven2Gradle just yet.
- //Maven2Gradle should be rewritten (with coverage) so that feeds of the maven object model, not xml.
- def effectivePom = new MavenProjectXmlWriter().toXml(mavenProjects)
- //use the Groovy XmlSlurper library to parse the text string
- this.effectivePom = new XmlSlurper().parseText(effectivePom)
-
- String build
- def multimodule = this.effectivePom.name() == "projects"
-
- if (multimodule) {
- println "This is multi-module project.\n"
- def allProjects = this.effectivePom.project
- print "Generating settings.gradle... "
- qualifiedNames = generateSettings(workingDir.getName(), allProjects[0].artifactId, allProjects);
- println "Done."
- print "Configuring Dependencies... "
- def dependencies = [:];
- allProjects.each { project ->
- dependencies[project.artifactId.text()] = getDependencies(project, allProjects)
- }
- println "Done."
-
-
- def commonDeps = dependencies.get(allProjects[0].artifactId.text())
- build = """allprojects {
- apply plugin: 'maven'
-
- ${getArtifactData(allProjects[0])}
-}
-
-subprojects {
- apply plugin: 'java'
- ${compilerSettings(allProjects[0], " ")}
- ${packageSources(allProjects[0])}
- ${getRepositoriesForProjects(allProjects)}
- ${globalExclusions(allProjects[0])}
- ${commonDeps}
- ${testNg(commonDeps)}
-}
-"""
- modules(allProjects, false).each { module ->
- def id = module.artifactId.text()
- String moduleDependencies = dependencies.get(id)
- boolean warPack = module.packaging.text().equals("war")
- def hasDependencies = !(moduleDependencies == null || moduleDependencies.length() == 0)
- print "Generating build.gradle for module ${id}... "
- File submoduleBuildFile = new File(projectDir(module), 'build.gradle')
- def group = ''
- if (module.groupId != allProjects[0].groupId) {
- group = "group = '${module.groupId}'"
- }
- String moduleBuild = """
-${group}
-description = '${module.name}'
-
-"""
- if (warPack) {
- moduleBuild += """apply plugin: 'war'
-
-"""
- if (dependentWars.any {project ->
- project.groupId.text() == module.groupId.text() &&
- project.artifactId.text() == id
- }) {
- moduleBuild += """jar.enabled = true
-"""
- }
- }
- if (hasDependencies) {
- moduleBuild += moduleDependencies
- }
-
- moduleBuild += testNg(moduleDependencies)
-
- if (submoduleBuildFile.exists()) {
- print "(backing up existing one)... "
- submoduleBuildFile.renameTo(new File("build.gradle.bak"))
- }
- def packageTests = packageTests(module);
- if (packageTests) {
- moduleBuild += packageTests;
- }
- submoduleBuildFile.text = moduleBuild
- println "Done."
- }
- //TODO deployment
- def uploadArchives = {
- """
-
-
-uploadArchives {
- group = 'Maven'
- description = "Does a maven deploy of archives artifacts."
-
- repositories.mavenDeployer {
- name = 'sshDeployer' // optional
- repository(url: "http://repos.mycompany.com/releases") {
- authentication(userName: "me", password: "myPassword")
- }
- configurePom(pom)
- }
-}
-
-
-"""
- }
- } else {//simple
- println "This is single module project."
- build = """apply plugin: 'java'
-apply plugin: 'maven'
-
-${getArtifactData(this.effectivePom)}
-
-description = \"""${this.effectivePom.name}\"""
-
-${compilerSettings(this.effectivePom, "")}
-${globalExclusions(this.effectivePom)}
-
-"""
-
- print "Configuring Maven repositories... "
- Set<String> repoSet = new LinkedHashSet<String>();
- getRepositoriesForModule(this.effectivePom, repoSet)
- String repos = """repositories {
- $localRepoUri
-"""
- repoSet.each {
- repos = "${repos} ${it}\n"
- }
- build += "${repos}}\n"
- println "Done."
- print "Configuring Dependencies... "
- String dependencies = getDependencies(this.effectivePom, null)
- build += dependencies
- println "Done."
-
- String packageTests = packageTests(this.effectivePom);
- if (packageTests) {
- build += '//packaging tests'
- build += packageTests;
- }
- print "Generating settings.gradle if needed... "
- generateSettings(workingDir.getName(), this.effectivePom.artifactId, null);
- println "Done."
-
- }
- print "Generating main build.gradle... "
- def buildFile = new File("build.gradle")
- if (buildFile.exists()) {
- print "(backing up existing one)... "
- buildFile.renameTo(new File("build.gradle.bak"))
- }
- buildFile.text = build
- println "Done."
- }
-
- def globalExclusions = {project ->
- def exclusions = ''
- def enforcerPlugin = plugin('maven-enforcer-plugin', project)
- def enforceGoal = pluginGoal('enforce', enforcerPlugin)
- if (enforceGoal) {
- exclusions += 'configurations.all {\n'
- enforceGoal.configuration.rules.bannedDependencies.excludes.childNodes().each {
- def tokens = it.text().tokenize(':')
- exclusions += "it.exclude group: '${tokens[0]}'"
- if (tokens.size() > 1 && tokens[1] != '*') {
- exclusions += ", module: '${tokens[1]}'"
- }
- exclusions += '\n'
- }
- }
- exclusions = exclusions ? exclusions += '}' : exclusions
- exclusions
- }
-
- def testNg = {moduleDependencies ->
- if (moduleDependencies.contains('testng')) {
- """test.useTestNG()
-"""
- } else {
- ''
- }
- }
-
- def modules = {allProjects, incReactors ->
- return allProjects.findAll { project ->
- project.parent.text().length() > 0 && (incReactors || project.packaging.text() != 'pom')
- }
- }
-
- def fqn = {project, allProjects ->
- def buffer = new StringBuilder()
- generateFqn(project, allProjects, buffer)
- return buffer.toString()
- }
-
- private generateFqn(def project, def allProjects, StringBuilder buffer) {
- def artifactId = project.artifactId.text()
- buffer.insert(0, ":${artifactId}")
- //we don't need the top-level parent in gradle, so we stop on it
- if (project.parent.artifactId.text() != allProjects[0].artifactId.text()) {
- generateFqn(allProjects.find {fullProject ->
- fullProject.artifactId.text() == project.parent.artifactId.text()
- }, allProjects, buffer)
- }
- }
-
-
- def localRepoUri = {
- """mavenLocal()
- """
- }
-
- private String getArtifactData(project) {
- return """group = '$project.groupId'
- version = '$project.version'
- """;
- }
-
- private String getRepositoriesForProjects(projects) {
- print 'Configuring Repositories... '
- String repos = """repositories {
- ${localRepoUri()}
-"""
- def repoSet = new LinkedHashSet<String>();
- projects.each {
- getRepositoriesForModule(it, repoSet)
- }
- repoSet.each {
- repos = "${repos}${it}\n"
- }
- repos = "${repos} }\n"
- println "Done."
- return repos
- }
-
- private void getRepositoriesForModule(module, repoSet) {
- module.repositories.repository.each {
- repoSet.add(" mavenRepo url: \"${it.url}\"")
- }
- //No need to include plugin repos - who cares about maven plugins?
- }
-
- private String getDependencies(project, allProjects) {
-// use GPath to navigate the object hierarchy and retrieve the collection of dependency nodes.
- def dependencies = project.dependencies.dependency
- def war = project.packaging == "war"
-
- def compileTimeScope = []
- def runTimeScope = []
- def testScope = []
- def providedScope = []
- def systemScope = []
-
- //cleanup duplicates from parent
-
-// using Groovy Looping and mapping a Groovy Closure to each element, we collect together all
-// the dependency nodes into corresponding collections depending on their scope value.
- dependencies.each() {
- if (!duplicateDependency(it, project, allProjects)) {
- def scope = (elementHasText(it.scope)) ? it.scope : "compile"
- switch (scope) {
- case "compile":
- compileTimeScope.add(it)
- break
- case "test":
- testScope.add(it)
- break
- case "provided":
- providedScope.add(it)
- break
- case "runtime":
- runTimeScope.add(it)
- break
- case "system":
- systemScope.add(it)
- break
- }
- }
- }
-
- /**
- * print function then checks the exclusions node to see if it exists, if
- * so it branches off, otherwise we call our simple print function
- */
- def createGradleDep = {String scope, StringBuilder sb, mavenDependency ->
- def projectDep = allProjects.find { prj ->
- return prj.artifactId.text() == mavenDependency.artifactId.text() && prj.groupId.text() == mavenDependency.groupId.text()
- }
- if (projectDep) {
- createProjectDependency(projectDep, sb, scope, allProjects)
- } else {
- def dependencyProperties = null;
- if (!war && scope == 'providedCompile') {
- scope = 'compile'
- dependencyProperties = [provided: true]
- }
- def exclusions = mavenDependency.exclusions.exclusion
- if (exclusions.size() > 0 || dependencyProperties) {
- createComplexDependency(mavenDependency, sb, scope, dependencyProperties)
- } else {
- createBasicDependency(mavenDependency, sb, scope)
- }
- }
- }
-
-
- StringBuilder build = new StringBuilder()
- if (!compileTimeScope.isEmpty() || !runTimeScope.isEmpty() || !testScope.isEmpty() || !providedScope.isEmpty() || !systemScope.isEmpty()) {
- build.append("dependencies {").append("\n")
-// for each collection, one at a time, we take each element and call our print function
- if (!compileTimeScope.isEmpty()) { compileTimeScope.each() { createGradleDep("compile", build, it) } }
- if (!runTimeScope.isEmpty()) { runTimeScope.each() { createGradleDep("runtime", build, it) } }
- if (!testScope.isEmpty()) { testScope.each() { createGradleDep("testCompile", build, it) } }
- if (!providedScope.isEmpty()) { providedScope.each() { createGradleDep("providedCompile", build, it) } }
- if (!systemScope.isEmpty()) { systemScope.each() { createGradleDep("system", build, it) } }
- build.append(" }\n")
- }
- return build.toString();
- }
-
- def compilerSettings = {project, indent ->
- def configuration = plugin('maven-compiler-plugin', project).configuration
- return "sourceCompatibility = ${configuration.source.text() ?: '1.5'}\n${indent}targetCompatibility = ${configuration.target.text() ?: '1.5'}\n"
- }
-
- def plugin = {artifactId, project ->
- project.build.plugins.plugin.find {pluginTag ->
- pluginTag.artifactId.text() == artifactId
- }
- }
-
- def pluginGoal = { goalName, plugin ->
- plugin.executions.execution.find { exec ->
- exec.goals.goal.find {gl ->
- gl.text().startsWith(goalName)
- }
- }
- }
-
- def packSources = {sourceSets ->
- def sourceSetStr = ''
- if (!sourceSets.empty) {
- sourceSetStr = """task packageSources(type: Jar) {
-classifier = 'sources'
-"""
- sourceSets.each { sourceSet ->
- sourceSetStr += """from sourceSets.${sourceSet}.allSource
-"""
- }
- sourceSetStr += """
-}
-artifacts.archives packageSources"""
- }
- println 'Done.'
- sourceSetStr
- }
-
-
- def packageTests = {project ->
- print 'Adding tests packaging...'
- def jarPlugin = plugin('maven-jar-plugin', project)
- pluginGoal('test-jar', jarPlugin) ? """
-task packageTests(type: Jar) {
- from sourceSets.test.output
- classifier = 'tests'
-}
-artifacts.archives packageTests
-""" : ''
- }
-
- def packageSources = { project ->
- def sourcePlugin = plugin('maven-source-plugin', project)
- def sourceSets = []
- if (sourcePlugin) {
- println 'Adding sources packaging...'
- if (pluginGoal('jar', sourcePlugin)) {
- sourceSets += 'main'
- } else if (pluginGoal('test-jar', sourcePlugin)) {
- sourceSets += 'test'
- }
- }
- packSources(sourceSets)
- }
-
- private boolean duplicateDependency(dependency, project, allProjects) {
- def parentTag = project.parent
- if (allProjects == null || parentTag.isEmpty()) {//simple project or no parent
- return false;
- } else {
- def parent = allProjects.find {
- it.groupId.equals(parentTag.groupId) && it.artifactId.equals(parentTag.artifactId)
- }
- def duplicate = parent.dependencies.dependency.any {
- it.groupId.equals(dependency.groupId) && it.artifactId.equals(dependency.artifactId)
- }
- if (duplicate) {
- return true;
- } else {
- duplicateDependency(dependency, parent, allProjects)
- }
- }
- }
-
- def artifactId = {File dir ->
- return new XmlSlurper().parse(new File(dir, 'pom.xml')).artifactId.text()
- }
-
- def projectDir = {project ->
- return new File(project.build.directory.text()).parentFile
- }
-
- private def generateSettings(def dirName, def mvnProjectName, def projects) {
- def qualifiedNames = [:]
- def projectName = "";
- if (dirName != mvnProjectName) {
- projectName = """rootProject.name = '${mvnProjectName}'
-"""
- }
- def modulePoms = modules(projects, true)
-
- def modules = new StringBuilder();
- def artifactIdToDir = [:]
- if (projects) {
- modulePoms.each { project ->
- def fqn = fqn(project, projects)
- artifactIdToDir[fqn] = GFileUtils.relativePath(workingDir, projectDir(project))
- modules.append("'${fqn}', ")
- }
- def strLength = modules.length()
- if (strLength > 2) {
- modules.delete(strLength - 2, strLength)
- }
- }
- File settingsFile = new File("settings.gradle")
- if (settingsFile.exists()) {
- print "(backing up existing one)... "
- settingsFile.renameTo(new File("settings.gradle.bak"))
- }
- def settingsText = "${projectName}${modules.length() > 0 ? "include ${modules.toString()}" : ''}\n"
- artifactIdToDir.each {entry ->
- settingsText += """
-project('$entry.key').projectDir = """ + '"$rootDir/' + "${entry.value}" + '" as File'
- }
- settingsFile.text = settingsText
- return qualifiedNames
- }
-
-/**
- * complex print statement does one extra task which is
- * iterate over each <exclusion> node and print out the artifact id.
- * It also tackles the properties attached to dependencies
- */
- private def createComplexDependency(it, build, scope, Map dependencyProperties) {
- build.append(" ${scope}(${contructSignature(it)}) {\n")
- it.exclusions.exclusion.each() {
- build.append("exclude(module: '${it.artifactId}')\n")
- }
- if (dependencyProperties) {
- dependencyProperties.keySet().each { key ->
- build.append("$key : ${dependencyProperties.get(key)}\n")
- }
- }
- build.append("}\n")
- }
-
-/**
- * Print out the basic form og gradle dependency
- */
- private def createBasicDependency(mavenDependency, build, String scope) {
- def classifier = contructSignature(mavenDependency)
- build.append(" ${scope} ${classifier}\n")
- }
-/**
- * Print out the basic form of gradle dependency
- */
- private def createProjectDependency(projectDep, build, String scope, allProjects) {
- if (projectDep.packaging.text() == 'war') {
- dependentWars += projectDep
- }
- build.append(" ${scope} project('${fqn(projectDep, allProjects)}')\n")
- }
-
-/**
- * Construct and return the signature of a dependency, including it's version and
- * classifier if it exists
- */
- private def contructSignature(mavenDependency) {
- def gradelDep = "group: '${mavenDependency.groupId.text()}', name: '${mavenDependency.artifactId.text()}', version:'${mavenDependency?.version?.text()}'"
- def classifier = elementHasText(mavenDependency.classifier) ? gradelDep + ", classifier:'" + mavenDependency.classifier.text().trim() + "'": gradelDep
- return classifier
- }
-
-/**
- * Check to see if the selected node has content
- */
- private boolean elementHasText(it) {
- return it.text().length() != 0
- }
-}
\ No newline at end of file
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/plugins/maven/internal/MavenProjectXmlWriter.java b/subprojects/maven/src/main/groovy/org/gradle/api/plugins/maven/internal/MavenProjectXmlWriter.java
deleted file mode 100644
index 5cce743..0000000
--- a/subprojects/maven/src/main/groovy/org/gradle/api/plugins/maven/internal/MavenProjectXmlWriter.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.plugins.maven.internal;
-
-import org.gradle.mvn3.org.apache.maven.model.io.xpp3.MavenXpp3Writer;
-import org.gradle.mvn3.org.apache.maven.project.MavenProject;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.Set;
-
-/**
- * by Szczepan Faber, created at: 9/14/12
- */
-public class MavenProjectXmlWriter {
-
- //TODO this class attempts to mimic the behavior of the output of mvn help:effective-pom
- //instead of this class we should walk the maven project object model (instead of parsing the xml!)
-
- String toXml(Set<MavenProject> projects) {
- assert !projects.isEmpty() : "Cannot prepare the maven projects effective xml because provided projects set is empty.";
-
- if (projects.size() == 1) {
- return toXml(projects.iterator().next());
- }
-
- StringBuilder out = new StringBuilder("<projects>");
- for (MavenProject project : projects) {
- out.append(toXml(project));
- }
- return out.append("</projects>").toString();
- }
-
- private String toXml(MavenProject project) {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- try {
- new MavenXpp3Writer().write(out, project.getModel());
- } catch (IOException e) {
- throw new RuntimeException("Unable to serialize maven model to xml. Maven project: " + project, e);
- }
- return prepareXml(out.toString());
- }
-
- String prepareXml(String xml) {
- return xml.replaceFirst("^<\\?xml.+?\\?>", "");
- }
-}
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/plugins/maven/internal/MavenProjectsCreator.java b/subprojects/maven/src/main/groovy/org/gradle/api/plugins/maven/internal/MavenProjectsCreator.java
deleted file mode 100644
index 214efa0..0000000
--- a/subprojects/maven/src/main/groovy/org/gradle/api/plugins/maven/internal/MavenProjectsCreator.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.plugins.maven.internal;
-
-import com.google.common.collect.ImmutableList;
-import org.gradle.mvn3.org.apache.maven.execution.*;
-import org.gradle.mvn3.org.apache.maven.model.building.ModelBuildingRequest;
-import org.gradle.mvn3.org.apache.maven.project.*;
-import org.gradle.mvn3.org.apache.maven.settings.Settings;
-import org.gradle.mvn3.org.codehaus.plexus.ContainerConfiguration;
-import org.gradle.mvn3.org.codehaus.plexus.DefaultContainerConfiguration;
-import org.gradle.mvn3.org.codehaus.plexus.DefaultPlexusContainer;
-import org.gradle.mvn3.org.codehaus.plexus.PlexusContainerException;
-import org.gradle.mvn3.org.codehaus.plexus.classworlds.ClassWorld;
-import org.gradle.mvn3.org.codehaus.plexus.component.repository.exception.ComponentLookupException;
-import org.gradle.mvn3.org.codehaus.plexus.configuration.PlexusConfigurationException;
-import org.gradle.mvn3.org.sonatype.aether.RepositorySystemSession;
-import org.gradle.mvn3.org.sonatype.aether.util.DefaultRepositorySystemSession;
-import org.gradle.api.GradleException;
-import org.gradle.api.Transformer;
-import org.gradle.util.CollectionUtils;
-
-import java.io.File;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * by Szczepan Faber, created at: 9/11/12
- */
-public class MavenProjectsCreator {
-
- public Set<MavenProject> create(Settings mavenSettings, File pomFile) {
- if (!pomFile.exists()) {
- throw new GradleException("Unable to create maven project model. The input pom file does not exist: " + pomFile);
- }
- try {
- return createNow(mavenSettings, pomFile);
- } catch (Exception e) {
- throw new GradleException("Unable to create maven project model using pom file: " + pomFile.getAbsolutePath(), e);
- }
- }
-
- private Set<MavenProject> createNow(Settings settings, File pomFile) throws PlexusContainerException, PlexusConfigurationException, ComponentLookupException, MavenExecutionRequestPopulationException, ProjectBuildingException {
- //using jarjar for maven3 classes affects the contents of the effective pom
- //references to certain maven standard plugins contain jarjar in the fqn
- //not sure if this is a problem.
- ContainerConfiguration containerConfiguration = new DefaultContainerConfiguration()
- .setClassWorld(new ClassWorld("plexus.core", ClassWorld.class.getClassLoader()))
- .setName("mavenCore");
-
- DefaultPlexusContainer container = new DefaultPlexusContainer(containerConfiguration);
- ProjectBuilder builder = container.lookup(ProjectBuilder.class);
- MavenExecutionRequest executionRequest = new DefaultMavenExecutionRequest();
- MavenExecutionRequestPopulator populator = container.lookup(MavenExecutionRequestPopulator.class);
- populator.populateFromSettings(executionRequest, settings);
- populator.populateDefaults(executionRequest);
- ProjectBuildingRequest buildingRequest = executionRequest.getProjectBuildingRequest();
- buildingRequest.setValidationLevel(ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL);
- MavenProject mavenProject = builder.build(pomFile, buildingRequest).getProject();
-
- Set<MavenProject> reactorProjects = new LinkedHashSet<MavenProject>();
-
- //TODO adding the parent project first because the converter needs it this way ATM. This is oversimplified.
- //the converter should not depend on the order of reactor projects.
- //we should add coverage for nested multi-project builds with multiple parents.
- reactorProjects.add(mavenProject);
-
- List<ProjectBuildingResult> allProjects = builder.build(ImmutableList.of(pomFile), true, buildingRequest);
- CollectionUtils.collect(allProjects, reactorProjects, new Transformer<MavenProject, ProjectBuildingResult>() {
- public MavenProject transform(ProjectBuildingResult original) {
- return original.getProject();
- }
- });
-
- MavenExecutionResult result = new DefaultMavenExecutionResult();
- result.setProject(mavenProject);
- RepositorySystemSession repoSession = new DefaultRepositorySystemSession();
- MavenSession session = new MavenSession(container, repoSession, executionRequest, result);
- session.setCurrentProject(mavenProject);
-
- return reactorProjects;
- }
-}
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ArtifactPom.java b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ArtifactPom.java
index 710a6f4..df4e600 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ArtifactPom.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ArtifactPom.java
@@ -22,9 +22,6 @@ import org.gradle.api.artifacts.maven.MavenPom;
import java.io.File;
import java.util.Set;
-/**
- * @author Hans Dockter
- */
public interface ArtifactPom {
/**
* @return The main artifact, may be null.
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ArtifactPomContainer.java b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ArtifactPomContainer.java
index 92a11fe..4b615b1 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ArtifactPomContainer.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ArtifactPomContainer.java
@@ -21,9 +21,6 @@ import org.gradle.api.artifacts.maven.MavenDeployment;
import java.io.File;
import java.util.Set;
-/**
- * @author Hans Dockter
- */
public interface ArtifactPomContainer {
void addArtifact(Artifact artifact, File src);
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ArtifactPomFactory.java b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ArtifactPomFactory.java
index c3761ac..e7ea210 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ArtifactPomFactory.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ArtifactPomFactory.java
@@ -17,9 +17,6 @@ package org.gradle.api.publication.maven.internal;
import org.gradle.api.artifacts.maven.MavenPom;
-/**
- * @author Hans Dockter
- */
public interface ArtifactPomFactory {
ArtifactPom createArtifactPom(MavenPom pom);
}
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/BasePomFilterContainer.java b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/BasePomFilterContainer.java
index 4c631ef..f477259 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/BasePomFilterContainer.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/BasePomFilterContainer.java
@@ -28,9 +28,6 @@ import org.gradle.util.WrapUtil;
import java.util.HashMap;
import java.util.Map;
-/**
- * @author Hans Dockter
- */
public class BasePomFilterContainer implements PomFilterContainer {
private Map<String, PomFilter> pomFilters = new HashMap<String, PomFilter>();
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/DefaultArtifactPom.java b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/DefaultArtifactPom.java
index 6ed01b0..9626631 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/DefaultArtifactPom.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/DefaultArtifactPom.java
@@ -28,9 +28,6 @@ import org.gradle.api.internal.artifacts.publish.AbstractPublishArtifact;
import java.io.File;
import java.util.*;
-/**
- * @author Hans Dockter
- */
public class DefaultArtifactPom implements ArtifactPom {
private static final Set<String> PACKAGING_TYPES = Sets.newHashSet("war", "jar", "ear");
private final MavenPom pom;
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/DefaultArtifactPomContainer.java b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/DefaultArtifactPomContainer.java
index 66b6383..987d16e 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/DefaultArtifactPomContainer.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/DefaultArtifactPomContainer.java
@@ -27,9 +27,6 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Set;
-/**
- * @author Hans Dockter
- */
public class DefaultArtifactPomContainer implements ArtifactPomContainer {
private Map<String, ArtifactPom> artifactPoms = new HashMap<String, ArtifactPom>();
private final MavenPomMetaInfoProvider pomMetaInfoProvider;
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/DefaultArtifactPomFactory.java b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/DefaultArtifactPomFactory.java
index b9eb510..1667ce3 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/DefaultArtifactPomFactory.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/DefaultArtifactPomFactory.java
@@ -17,9 +17,6 @@ package org.gradle.api.publication.maven.internal;
import org.gradle.api.artifacts.maven.MavenPom;
-/**
- * @author Hans Dockter
- */
public class DefaultArtifactPomFactory implements ArtifactPomFactory {
public ArtifactPom createArtifactPom(MavenPom pom) {
return new DefaultArtifactPom(pom);
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/DefaultConf2ScopeMappingContainer.java b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/DefaultConf2ScopeMappingContainer.java
index c766fd1..71db496 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/DefaultConf2ScopeMappingContainer.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/DefaultConf2ScopeMappingContainer.java
@@ -16,16 +16,13 @@
package org.gradle.api.publication.maven.internal;
import org.gradle.api.InvalidUserDataException;
+import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.maven.Conf2ScopeMapping;
import org.gradle.api.artifacts.maven.Conf2ScopeMappingContainer;
-import org.gradle.api.artifacts.Configuration;
import org.gradle.util.WrapUtil;
import java.util.*;
-/**
- * @author Hans Dockter
- */
public class DefaultConf2ScopeMappingContainer implements Conf2ScopeMappingContainer {
private Map<Configuration, Conf2ScopeMapping> mappings = new HashMap<Configuration, Conf2ScopeMapping>();
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/DefaultMavenDeployment.java b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/DefaultMavenDeployment.java
index 09ec43d..b109bbd 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/DefaultMavenDeployment.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/DefaultMavenDeployment.java
@@ -22,9 +22,6 @@ import org.gradle.api.artifacts.maven.MavenDeployment;
import java.util.HashSet;
import java.util.Set;
-/**
- * @author Hans Dockter
-*/
public class DefaultMavenDeployment implements MavenDeployment {
private Set<PublishArtifact> attachedArtifacts;
private final PublishArtifact pomArtifact;
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/DefaultMavenPom.java b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/DefaultMavenPom.java
index 31e5f1c..26e22de 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/DefaultMavenPom.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/DefaultMavenPom.java
@@ -29,8 +29,8 @@ import org.gradle.api.artifacts.maven.MavenPom;
import org.gradle.api.internal.ClosureBackedAction;
import org.gradle.api.internal.ErroringAction;
import org.gradle.api.internal.IoActions;
-import org.gradle.api.internal.xml.XmlTransformer;
import org.gradle.api.internal.file.FileResolver;
+import org.gradle.api.internal.xml.XmlTransformer;
import org.gradle.listener.ActionBroadcast;
import java.io.BufferedWriter;
@@ -39,9 +39,6 @@ import java.io.Writer;
import java.util.Collections;
import java.util.List;
-/**
- * @author Hans Dockter
- */
public class DefaultMavenPom implements MavenPom {
private PomDependenciesConverter pomDependenciesConverter;
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/DefaultMavenPomFactory.java b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/DefaultMavenPomFactory.java
index 4df4826..146f9b1 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/DefaultMavenPomFactory.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/DefaultMavenPomFactory.java
@@ -18,12 +18,9 @@ package org.gradle.api.publication.maven.internal;
import org.gradle.api.artifacts.ConfigurationContainer;
import org.gradle.api.artifacts.maven.Conf2ScopeMappingContainer;
import org.gradle.api.artifacts.maven.MavenPom;
-import org.gradle.internal.Factory;
import org.gradle.api.internal.file.FileResolver;
+import org.gradle.internal.Factory;
-/**
- * @author Hans Dockter
- */
public class DefaultMavenPomFactory implements Factory<MavenPom> {
private ConfigurationContainer configurationContainer;
private Conf2ScopeMappingContainer conf2ScopeMappingContainer;
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/DefaultPomFilter.java b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/DefaultPomFilter.java
index 3f44c82..2194182 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/DefaultPomFilter.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/DefaultPomFilter.java
@@ -18,9 +18,6 @@ package org.gradle.api.publication.maven.internal;
import org.gradle.api.artifacts.maven.MavenPom;
import org.gradle.api.artifacts.maven.PublishFilter;
-/**
- * @author Hans Dockter
- */
public class DefaultPomFilter implements PomFilter {
private String name;
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ExcludeRuleConverter.java b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ExcludeRuleConverter.java
index cc5743d..1702005 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ExcludeRuleConverter.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ExcludeRuleConverter.java
@@ -18,9 +18,6 @@ package org.gradle.api.publication.maven.internal;
import org.gradle.api.artifacts.ExcludeRule;
-/**
- * @author Hans Dockter
- */
public interface ExcludeRuleConverter {
Object convert(ExcludeRule excludeRule);
}
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/PomDependenciesConverter.java b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/PomDependenciesConverter.java
index 735fb9a..04c38b3 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/PomDependenciesConverter.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/PomDependenciesConverter.java
@@ -21,9 +21,6 @@ import org.gradle.api.artifacts.maven.Conf2ScopeMappingContainer;
import java.util.List;
import java.util.Set;
-/**
- * @author Hans Dockter
- */
public interface PomDependenciesConverter {
public List<?> convert(Conf2ScopeMappingContainer conf2ScopeMappingContainer, Set<Configuration> configurations);
}
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/PomFilter.java b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/PomFilter.java
index 84f8010..96a6aaa 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/PomFilter.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/PomFilter.java
@@ -18,9 +18,6 @@ package org.gradle.api.publication.maven.internal;
import org.gradle.api.artifacts.maven.MavenPom;
import org.gradle.api.artifacts.maven.PublishFilter;
-/**
- * @author Hans Dockter
- */
public interface PomFilter {
String getName();
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/AbstractMavenResolver.java b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/AbstractMavenResolver.java
index 9bd93e4..1b2692a 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/AbstractMavenResolver.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/AbstractMavenResolver.java
@@ -42,7 +42,9 @@ import org.gradle.api.Action;
import org.gradle.api.artifacts.PublishArtifact;
import org.gradle.api.artifacts.maven.*;
import org.gradle.api.internal.ClosureBackedAction;
-import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.IvyAwareModuleVersionRepository;
+import org.gradle.api.internal.artifacts.ModuleVersionPublisher;
+import org.gradle.api.internal.artifacts.ivyservice.IvyResolverBackedModuleVersionPublisher;
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ConfiguredModuleVersionRepository;
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.NoOpRepositoryCacheManager;
import org.gradle.api.internal.artifacts.repositories.AbstractArtifactRepository;
import org.gradle.api.logging.LogLevel;
@@ -58,9 +60,6 @@ import java.text.ParseException;
import java.util.Map;
import java.util.Set;
-/**
- * @author Hans Dockter
- */
public abstract class AbstractMavenResolver extends AbstractArtifactRepository implements MavenResolver, DependencyResolver {
private ArtifactPomContainer artifactPomContainer;
@@ -81,12 +80,12 @@ public abstract class AbstractMavenResolver extends AbstractArtifactRepository i
this.loggingManager = loggingManager;
}
- public IvyAwareModuleVersionRepository createResolver() {
+ public ConfiguredModuleVersionRepository createResolver() {
throw new UnsupportedOperationException("A Maven deployer cannot be used to resolve dependencies. It can only be used to publish artifacts.");
}
- public DependencyResolver createPublisher() {
- return this;
+ public ModuleVersionPublisher createPublisher() {
+ return new IvyResolverBackedModuleVersionPublisher(this);
}
public DependencyResolver createLegacyDslObject() {
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/BaseMavenDeployer.java b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/BaseMavenDeployer.java
index bac0525..afbffa8 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/BaseMavenDeployer.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/BaseMavenDeployer.java
@@ -24,8 +24,8 @@ import org.codehaus.plexus.PlexusContainerException;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.maven.MavenDeployer;
import org.gradle.api.artifacts.maven.PomFilterContainer;
-import org.gradle.internal.Factory;
import org.gradle.api.publication.maven.internal.ArtifactPomContainer;
+import org.gradle.internal.Factory;
import org.gradle.logging.LoggingManagerInternal;
import java.io.File;
@@ -33,9 +33,6 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
-/**
- * @author Hans Dockter
- */
public class BaseMavenDeployer extends AbstractMavenResolver implements MavenDeployer {
private RemoteRepository remoteRepository;
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/BaseMavenInstaller.java b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/BaseMavenInstaller.java
index df93aac..02101ae 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/BaseMavenInstaller.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/BaseMavenInstaller.java
@@ -19,13 +19,10 @@ import org.apache.maven.artifact.ant.InstallDeployTaskSupport;
import org.apache.maven.artifact.ant.InstallTask;
import org.apache.tools.ant.Project;
import org.gradle.api.artifacts.maven.PomFilterContainer;
-import org.gradle.internal.Factory;
import org.gradle.api.publication.maven.internal.ArtifactPomContainer;
+import org.gradle.internal.Factory;
import org.gradle.logging.LoggingManagerInternal;
-/**
- * @author Hans Dockter
- */
public class BaseMavenInstaller extends AbstractMavenResolver {
private Factory<CustomInstallTask> installTaskFactory = new DefaultInstallTaskFactory();
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/CustomDeployTask.java b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/CustomDeployTask.java
index bd9499d..85521bf 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/CustomDeployTask.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/CustomDeployTask.java
@@ -21,8 +21,6 @@ import org.codehaus.plexus.PlexusContainer;
/**
* We could also use reflection to get hold of the container property. But this would make it harder to use a Mock for this class.
- *
- * @author Hans Dockter
*/
public class CustomDeployTask extends DeployTask implements CustomInstallDeployTaskSupport {
@Override
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/CustomInstallDeployTaskSupport.java b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/CustomInstallDeployTaskSupport.java
index afd72d8..40c3ea9 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/CustomInstallDeployTaskSupport.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/CustomInstallDeployTaskSupport.java
@@ -15,13 +15,10 @@
*/
package org.gradle.api.publication.maven.internal.ant;
-import org.apache.maven.settings.Settings;
import org.apache.maven.artifact.ant.AttachedArtifact;
+import org.apache.maven.settings.Settings;
import org.apache.tools.ant.Project;
-/**
- * @author Hans Dockter
- */
public interface CustomInstallDeployTaskSupport {
Settings getSettings();
Project getProject();
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/CustomInstallTask.java b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/CustomInstallTask.java
index 9a87b04..15079c4 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/CustomInstallTask.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/CustomInstallTask.java
@@ -18,9 +18,6 @@ package org.gradle.api.publication.maven.internal.ant;
import org.apache.maven.artifact.ant.InstallTask;
import org.apache.maven.settings.Settings;
-/**
- * @author Hans Dockter
- */
public class CustomInstallTask extends InstallTask implements CustomInstallDeployTaskSupport {
@Override
public synchronized Settings getSettings() {
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/DefaultDeployTaskFactory.java b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/DefaultDeployTaskFactory.java
index 6ae4016..a8f4d6d 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/DefaultDeployTaskFactory.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/DefaultDeployTaskFactory.java
@@ -17,9 +17,6 @@ package org.gradle.api.publication.maven.internal.ant;
import org.gradle.internal.Factory;
-/**
- * @author Hans Dockter
- */
public class DefaultDeployTaskFactory implements Factory<CustomDeployTask> {
public CustomDeployTask create() {
return new CustomDeployTask();
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/DefaultExcludeRuleConverter.java b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/DefaultExcludeRuleConverter.java
index 93160b5..2f0efef 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/DefaultExcludeRuleConverter.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/DefaultExcludeRuleConverter.java
@@ -20,9 +20,6 @@ import org.gradle.api.artifacts.ExcludeRule;
import org.gradle.api.publication.maven.internal.ExcludeRuleConverter;
-/**
- * @author Hans Dockter
- */
public class DefaultExcludeRuleConverter implements ExcludeRuleConverter {
public Exclusion convert(ExcludeRule excludeRule) {
if (isConvertable(excludeRule)) {
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/DefaultGroovyMavenDeployer.groovy b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/DefaultGroovyMavenDeployer.groovy
index 3fafaa0..819de15 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/DefaultGroovyMavenDeployer.groovy
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/DefaultGroovyMavenDeployer.groovy
@@ -19,12 +19,8 @@ import org.codehaus.groovy.runtime.InvokerHelper
import org.gradle.api.artifacts.maven.GroovyMavenDeployer
import org.gradle.api.artifacts.maven.PomFilterContainer
import org.gradle.api.publication.maven.internal.ArtifactPomContainer
-
import org.gradle.logging.LoggingManagerInternal
-/**
- * @author Hans Dockter
- */
class DefaultGroovyMavenDeployer extends BaseMavenDeployer implements GroovyMavenDeployer, PomFilterContainer {
public static final String REPOSITORY_BUILDER = "repository"
public static final String SNAPSHOT_REPOSITORY_BUILDER = 'snapshotRepository'
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/DefaultInstallTaskFactory.java b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/DefaultInstallTaskFactory.java
index ade162e..f27bcf5 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/DefaultInstallTaskFactory.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/DefaultInstallTaskFactory.java
@@ -17,9 +17,6 @@ package org.gradle.api.publication.maven.internal.ant;
import org.gradle.internal.Factory;
-/**
- * @author Hans Dockter
- */
public class DefaultInstallTaskFactory implements Factory<CustomInstallTask> {
public CustomInstallTask create() {
return new CustomInstallTask();
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/DefaultPomDependenciesConverter.java b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/DefaultPomDependenciesConverter.java
index aa8f6e9..e1a00b7 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/DefaultPomDependenciesConverter.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/DefaultPomDependenciesConverter.java
@@ -26,9 +26,6 @@ import org.gradle.api.publication.maven.internal.PomDependenciesConverter;
import java.util.*;
-/**
- * @author Hans Dockter
- */
public class DefaultPomDependenciesConverter implements PomDependenciesConverter {
private ExcludeRuleConverter excludeRuleConverter;
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/EmptyMavenSettingsSupplier.java b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/EmptyMavenSettingsSupplier.java
index 2f7b1ac..5549dcb 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/EmptyMavenSettingsSupplier.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/EmptyMavenSettingsSupplier.java
@@ -25,9 +25,6 @@ import org.gradle.api.internal.file.TmpDirTemporaryFileProvider;
import java.io.File;
import java.io.IOException;
-/**
- * @author Szczepan Faber, created at: 3/29/11
- */
public class EmptyMavenSettingsSupplier implements MavenSettingsSupplier {
private final TemporaryFileProvider temporaryFileProvider = new TmpDirTemporaryFileProvider();
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/LoggingHelper.java b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/LoggingHelper.java
index 759a5b0..248f839 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/LoggingHelper.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/LoggingHelper.java
@@ -24,9 +24,6 @@ import org.codehaus.plexus.component.repository.exception.ComponentLookupExcepti
import java.lang.reflect.Field;
-/**
- * @author Hans Dockter
- */
public class LoggingHelper {
public static void injectLogger(PlexusContainer container, Project project) {
try {
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/MavenSettingsSupplier.java b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/MavenSettingsSupplier.java
index 8efe218..a8fb1c2 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/MavenSettingsSupplier.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/MavenSettingsSupplier.java
@@ -18,9 +18,6 @@ package org.gradle.api.publication.maven.internal.ant;
import org.apache.maven.artifact.ant.InstallDeployTaskSupport;
-/**
- * @author Szczepan Faber, created at: 3/29/11
- */
public interface MavenSettingsSupplier {
void done();
void supply(InstallDeployTaskSupport installDeployTaskSupport);
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/MaybeUserMavenSettingsSupplier.java b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/MaybeUserMavenSettingsSupplier.java
index 01fef7e..af4020b 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/MaybeUserMavenSettingsSupplier.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/MaybeUserMavenSettingsSupplier.java
@@ -22,9 +22,6 @@ import org.gradle.api.internal.artifacts.mvnsettings.MavenFileLocations;
import java.io.File;
-/**
- * @author Szczepan Faber, created at: 3/29/11
- */
public class MaybeUserMavenSettingsSupplier implements MavenSettingsSupplier {
MavenSettingsSupplier emptySettingsSupplier = new EmptyMavenSettingsSupplier();
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/RepositoryBuilder.java b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/RepositoryBuilder.java
index 110fc10..bff4576 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/RepositoryBuilder.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/RepositoryBuilder.java
@@ -21,9 +21,6 @@ import org.apache.maven.artifact.ant.Proxy;
import org.apache.maven.artifact.ant.RemoteRepository;
import org.apache.maven.artifact.ant.RepositoryPolicy;
-/**
- * @author Hans Dockter
- */
public class RepositoryBuilder extends FactoryBuilderSupport {
public RepositoryBuilder() {
registerFactory("repository", new RepositoryFactory(RemoteRepository.class));
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/RepositoryFactory.java b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/RepositoryFactory.java
index 7bf1586..e3517aa 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/RepositoryFactory.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/ant/RepositoryFactory.java
@@ -22,9 +22,6 @@ import org.apache.maven.artifact.ant.Proxy;
import org.apache.maven.artifact.ant.RemoteRepository;
import org.apache.maven.artifact.ant.RepositoryPolicy;
-/**
- * @author Hans Dockter
- */
public class RepositoryFactory extends BeanFactory {
public RepositoryFactory(Class klass) {
super(klass);
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/MavenArtifactSet.java b/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/MavenArtifactSet.java
index db2b46f..d04f5d5 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/MavenArtifactSet.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/MavenArtifactSet.java
@@ -27,7 +27,7 @@ import org.gradle.api.Incubating;
* <pre autoTested="true">
* apply plugin: 'maven-publish'
*
- * def publication = publishing.publications.add("name", MavenPublication)
+ * def publication = publishing.publications.create("name", MavenPublication)
* def artifacts = publication.artifacts
*
* artifacts.matching({
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/MavenDependency.java b/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/MavenDependency.java
new file mode 100644
index 0000000..84290be
--- /dev/null
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/MavenDependency.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.publish.maven;
+
+import org.gradle.api.Incubating;
+import org.gradle.api.internal.HasInternalProtocol;
+
+/**
+ * A dependency declared as part of an {@link MavenPublication}.
+ */
+ at Incubating
+ at HasInternalProtocol
+public interface MavenDependency {
+ /**
+ * The groupId value for this dependency.
+ */
+ String getGroupId();
+
+ /**
+ * The artifactId value for this dependency.
+ */
+ String getArtifactId();
+
+ /**
+ * The version value for this dependency.
+ */
+ String getVersion();
+}
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/MavenPom.java b/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/MavenPom.java
index 9a711d3..8609c00 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/MavenPom.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/MavenPom.java
@@ -42,7 +42,7 @@ public interface MavenPom {
* publications {
* maven(MavenPublication) {
* pom.withXml {
- * asNode().appendNode('description', 'A demonstration of maven pom customisation')
+ * asNode().appendNode('description', 'A demonstration of Maven POM customization')
* }
* }
* }
@@ -63,4 +63,15 @@ public interface MavenPom {
*/
void withXml(Action<? super XmlProvider> action);
+ /**
+ * Returns the packaging for this publication.
+ */
+ String getPackaging();
+
+ /**
+ * Sets the packaging for this publication.
+ */
+ void setPackaging(String packaging);
+
+
}
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/MavenPublication.java b/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/MavenPublication.java
index 900f2dc..8a91485 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/MavenPublication.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/MavenPublication.java
@@ -29,7 +29,9 @@ import org.gradle.api.publish.Publication;
* <pre>
* publishing {
* publications {
- * myPublicationName(MavenPublication)
+ * myPublicationName(MavenPublication) {
+ * // Configure the publication here
+ * }
* }
* }
* </pre>
@@ -69,7 +71,7 @@ import org.gradle.api.publish.Publication;
* classifier "source"
* }
* pom.withXml {
- * asNode().appendNode('description', 'A demonstration of maven pom customisation')
+ * asNode().appendNode('description', 'A demonstration of Maven POM customization')
* }
* }
* }
@@ -109,7 +111,7 @@ public interface MavenPublication extends Publication {
* Currently 2 types of component are supported: 'components.java' (added by the JavaPlugin) and 'components.web' (added by the WarPlugin).
* For any individual MavenPublication, only a single component can be provided in this way.
*
- * The following example demonstrates how to publish the 'java' component to a maven repository.
+ * The following example demonstrates how to publish the 'java' component to a Maven repository.
* <pre autoTested="true">
* apply plugin: "java"
* apply plugin: "maven-publish"
@@ -232,4 +234,34 @@ public interface MavenPublication extends Publication {
*/
MavenArtifactSet getArtifacts();
+ /**
+ * Returns the groupId for this publication.
+ */
+ String getGroupId();
+
+ /**
+ * Sets the groupId for this publication.
+ */
+ void setGroupId(String groupId);
+
+ /**
+ * Returns the artifactId for this publication.
+ */
+ String getArtifactId();
+
+ /**
+ * Sets the artifactId for this publication.
+ */
+ void setArtifactId(String artifactId);
+
+ /**
+ * Returns the version for this publication.
+ */
+ String getVersion();
+
+ /**
+ * Sets the version for this publication.
+ */
+ void setVersion(String version);
+
}
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/artifact/DefaultMavenArtifact.java b/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/artifact/DefaultMavenArtifact.java
index db4a67f..27ef454 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/artifact/DefaultMavenArtifact.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/artifact/DefaultMavenArtifact.java
@@ -63,4 +63,9 @@ public class DefaultMavenArtifact implements MavenArtifact {
public TaskDependency getBuildDependencies() {
return buildDependencies;
}
+
+ @Override
+ public String toString() {
+ return String.format("%s %s:%s", getClass().getSimpleName(), getExtension(), getClassifier());
+ }
}
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/dependencies/DefaultMavenDependency.java b/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/dependencies/DefaultMavenDependency.java
new file mode 100644
index 0000000..8327c1a
--- /dev/null
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/dependencies/DefaultMavenDependency.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.publish.maven.internal.dependencies;
+
+import org.gradle.api.artifacts.DependencyArtifact;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+public class DefaultMavenDependency implements MavenDependencyInternal {
+ private final String groupId;
+ private final String artifactId;
+ private final String version;
+ private final List<DependencyArtifact> artifacts = new ArrayList<DependencyArtifact>();
+
+ public DefaultMavenDependency(String groupId, String artifactId, String version) {
+ this.groupId = groupId;
+ this.artifactId = artifactId;
+ this.version = version;
+ }
+
+ public DefaultMavenDependency(String groupId, String artifactId, String version, Collection<DependencyArtifact> artifacts) {
+ this(groupId, artifactId, version);
+ this.artifacts.addAll(artifacts);
+ }
+
+ public String getGroupId() {
+ return groupId;
+ }
+
+ public String getArtifactId() {
+ return artifactId;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public Collection<DependencyArtifact> getArtifacts() {
+ return artifacts;
+ }
+}
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/dependencies/MavenDependencyInternal.java b/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/dependencies/MavenDependencyInternal.java
new file mode 100644
index 0000000..5153941
--- /dev/null
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/dependencies/MavenDependencyInternal.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.publish.maven.internal.dependencies;
+
+import org.gradle.api.artifacts.DependencyArtifact;
+import org.gradle.api.publish.maven.MavenDependency;
+
+import java.util.Collection;
+
+public interface MavenDependencyInternal extends MavenDependency {
+ Collection<DependencyArtifact> getArtifacts();
+}
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/plugins/GeneratePomTaskCreator.java b/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/plugins/GeneratePomTaskCreator.java
index 3fa99c5..9c75949 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/plugins/GeneratePomTaskCreator.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/plugins/GeneratePomTaskCreator.java
@@ -23,6 +23,7 @@ import org.gradle.api.internal.plugins.DslObject;
import org.gradle.api.publish.PublicationContainer;
import org.gradle.api.publish.maven.internal.publication.MavenPublicationInternal;
import org.gradle.api.publish.maven.tasks.GenerateMavenPom;
+import org.gradle.api.publish.plugins.PublishingPlugin;
import java.io.File;
import java.util.concurrent.Callable;
@@ -49,8 +50,9 @@ public class GeneratePomTaskCreator {
String publicationName = publication.getName();
String descriptorTaskName = calculateDescriptorTaskName(publicationName);
- GenerateMavenPom generatePomTask = project.getTasks().add(descriptorTaskName, GenerateMavenPom.class);
+ GenerateMavenPom generatePomTask = project.getTasks().create(descriptorTaskName, GenerateMavenPom.class);
generatePomTask.setDescription(String.format("Generates the Maven POM file for publication '%s'.", publication.getName()));
+ generatePomTask.setGroup(PublishingPlugin.PUBLISH_TASK_GROUP);
generatePomTask.setPom(publication.getPom());
ConventionMapping descriptorTaskConventionMapping = new DslObject(generatePomTask).getConventionMapping();
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/plugins/MavenPublishDynamicTaskCreator.java b/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/plugins/MavenPublishDynamicTaskCreator.java
index d5b88a7..73f2922 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/plugins/MavenPublishDynamicTaskCreator.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/plugins/MavenPublishDynamicTaskCreator.java
@@ -25,6 +25,7 @@ import org.gradle.api.artifacts.repositories.MavenArtifactRepository;
import org.gradle.api.publish.PublicationContainer;
import org.gradle.api.publish.maven.internal.publication.MavenPublicationInternal;
import org.gradle.api.publish.maven.tasks.PublishToMavenRepository;
+import org.gradle.api.publish.plugins.PublishingPlugin;
import org.gradle.api.tasks.TaskContainer;
import static org.apache.commons.lang.StringUtils.capitalize;
@@ -70,10 +71,10 @@ public class MavenPublishDynamicTaskCreator {
String publishTaskName = calculatePublishTaskName(publicationName, repositoryName);
if (tasks.findByName(publishTaskName) == null) {
- PublishToMavenRepository publishTask = tasks.add(publishTaskName, PublishToMavenRepository.class);
+ PublishToMavenRepository publishTask = tasks.create(publishTaskName, PublishToMavenRepository.class);
publishTask.setPublication(publication);
publishTask.setRepository(repository);
- publishTask.setGroup("publishing");
+ publishTask.setGroup(PublishingPlugin.PUBLISH_TASK_GROUP);
publishTask.setDescription(String.format("Publishes Maven publication '%s' to Maven repository '%s'.", publicationName, repositoryName));
publishLifecycleTask.dependsOn(publishTask);
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/plugins/MavenPublishLocalDynamicTaskCreator.java b/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/plugins/MavenPublishLocalDynamicTaskCreator.java
index 3709bc3..89e31a6 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/plugins/MavenPublishLocalDynamicTaskCreator.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/plugins/MavenPublishLocalDynamicTaskCreator.java
@@ -22,6 +22,7 @@ import org.gradle.api.Task;
import org.gradle.api.publish.PublicationContainer;
import org.gradle.api.publish.maven.internal.publication.MavenPublicationInternal;
import org.gradle.api.publish.maven.tasks.PublishToMavenLocal;
+import org.gradle.api.publish.plugins.PublishingPlugin;
import org.gradle.api.tasks.TaskContainer;
import static org.apache.commons.lang.StringUtils.capitalize;
@@ -51,10 +52,10 @@ public class MavenPublishLocalDynamicTaskCreator {
String publicationName = publication.getName();
String installTaskName = calculatePublishLocalTaskName(publicationName);
- PublishToMavenLocal publishTask = tasks.add(installTaskName, PublishToMavenLocal.class);
+ PublishToMavenLocal publishTask = tasks.create(installTaskName, PublishToMavenLocal.class);
publishTask.setPublication(publication);
- publishTask.setGroup("publishing");
- publishTask.setDescription(String.format("Publishes Maven publication '%s' to the local Maven cache.", publicationName));
+ publishTask.setGroup(PublishingPlugin.PUBLISH_TASK_GROUP);
+ publishTask.setDescription(String.format("Publishes Maven publication '%s' to the local Maven repository.", publicationName));
publishToMavenLocalLifecycleTask.dependsOn(publishTask);
}
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/publication/DefaultMavenPom.java b/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/publication/DefaultMavenPom.java
index 9c692f0..0beb2e9 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/publication/DefaultMavenPom.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/publication/DefaultMavenPom.java
@@ -17,11 +17,12 @@
package org.gradle.api.publish.maven.internal.publication;
import org.gradle.api.Action;
-import org.gradle.api.artifacts.Dependency;
-import org.gradle.api.internal.UserCodeAction;
import org.gradle.api.XmlProvider;
+import org.gradle.api.internal.UserCodeAction;
+import org.gradle.api.publish.maven.internal.dependencies.MavenDependencyInternal;
import org.gradle.api.publish.maven.internal.publisher.MavenProjectIdentity;
import org.gradle.listener.ActionBroadcast;
+import org.gradle.util.GUtil;
import java.util.Set;
@@ -29,6 +30,7 @@ public class DefaultMavenPom implements MavenPomInternal {
private final ActionBroadcast<XmlProvider> xmlAction = new ActionBroadcast<XmlProvider>();
private final MavenPublicationInternal mavenPublication;
+ private String packaging;
public DefaultMavenPom(MavenPublicationInternal mavenPublication) {
this.mavenPublication = mavenPublication;
@@ -43,14 +45,18 @@ public class DefaultMavenPom implements MavenPomInternal {
}
public String getPackaging() {
- return mavenPublication.determinePackagingFromArtifacts();
+ return GUtil.elvis(packaging, mavenPublication.determinePackagingFromArtifacts());
+ }
+
+ public void setPackaging(String packaging) {
+ this.packaging = packaging;
}
public MavenProjectIdentity getProjectIdentity() {
return mavenPublication.getMavenProjectIdentity();
}
- public Set<Dependency> getRuntimeDependencies() {
+ public Set<MavenDependencyInternal> getRuntimeDependencies() {
return mavenPublication.getRuntimeDependencies();
}
}
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/publication/DefaultMavenPublication.java b/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/publication/DefaultMavenPublication.java
index 42d1638..2befa12 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/publication/DefaultMavenPublication.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/publication/DefaultMavenPublication.java
@@ -18,18 +18,24 @@ package org.gradle.api.publish.maven.internal.publication;
import org.gradle.api.Action;
import org.gradle.api.InvalidUserDataException;
-import org.gradle.api.artifacts.Dependency;
+import org.gradle.api.artifacts.ModuleDependency;
+import org.gradle.api.artifacts.ModuleVersionIdentifier;
+import org.gradle.api.artifacts.ProjectDependency;
import org.gradle.api.artifacts.PublishArtifact;
import org.gradle.api.component.SoftwareComponent;
import org.gradle.api.file.FileCollection;
+import org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier;
import org.gradle.api.internal.component.SoftwareComponentInternal;
import org.gradle.api.internal.component.Usage;
import org.gradle.api.internal.file.UnionFileCollection;
import org.gradle.api.internal.notations.api.NotationParser;
+import org.gradle.api.publish.internal.ProjectDependencyPublicationResolver;
import org.gradle.api.publish.maven.MavenArtifact;
import org.gradle.api.publish.maven.MavenArtifactSet;
import org.gradle.api.publish.maven.MavenPom;
import org.gradle.api.publish.maven.internal.artifact.DefaultMavenArtifactSet;
+import org.gradle.api.publish.maven.internal.dependencies.DefaultMavenDependency;
+import org.gradle.api.publish.maven.internal.dependencies.MavenDependencyInternal;
import org.gradle.api.publish.maven.internal.publisher.MavenNormalizedPublication;
import org.gradle.api.publish.maven.internal.publisher.MavenProjectIdentity;
import org.gradle.internal.reflect.Instantiator;
@@ -45,7 +51,7 @@ public class DefaultMavenPublication implements MavenPublicationInternal {
private final MavenPomInternal pom;
private final MavenProjectIdentity projectIdentity;
private final DefaultMavenArtifactSet mavenArtifacts;
- private final Set<Dependency> runtimeDependencies = new LinkedHashSet<Dependency>();
+ private final Set<MavenDependencyInternal> runtimeDependencies = new LinkedHashSet<MavenDependencyInternal>();
private FileCollection pomFile;
private SoftwareComponentInternal component;
@@ -53,7 +59,7 @@ public class DefaultMavenPublication implements MavenPublicationInternal {
String name, MavenProjectIdentity projectIdentity, NotationParser<MavenArtifact> mavenArtifactParser, Instantiator instantiator
) {
this.name = name;
- this.projectIdentity = projectIdentity;
+ this.projectIdentity = new DefaultMavenProjectIdentity(projectIdentity.getGroupId(), projectIdentity.getArtifactId(), projectIdentity.getVersion());
mavenArtifacts = instantiator.newInstance(DefaultMavenArtifactSet.class, name, mavenArtifactParser);
pom = instantiator.newInstance(DefaultMavenPom.class, this);
}
@@ -82,16 +88,31 @@ public class DefaultMavenPublication implements MavenPublicationInternal {
this.component = (SoftwareComponentInternal) component;
for (Usage usage : this.component.getUsages()) {
- // TODO:DAZ Need a smarter way to map usage to artifact classifier
+ // TODO Need a smarter way to map usage to artifact classifier
for (PublishArtifact publishArtifact : usage.getArtifacts()) {
artifact(publishArtifact);
}
- // TODO:DAZ Need a smarter way to map usage to scope
- runtimeDependencies.addAll(usage.getDependencies());
+ // TODO Need a smarter way to map usage to scope
+ for (ModuleDependency dependency : usage.getDependencies()) {
+ if (dependency instanceof ProjectDependency) {
+ addProjectDependency((ProjectDependency) dependency);
+ } else {
+ addModuleDependency(dependency);
+ }
+ }
}
}
+ private void addProjectDependency(ProjectDependency dependency) {
+ ModuleVersionIdentifier identifier = new ProjectDependencyPublicationResolver().resolve(dependency);
+ runtimeDependencies.add(new DefaultMavenDependency(identifier.getGroup(), identifier.getName(), identifier.getVersion()));
+ }
+
+ private void addModuleDependency(ModuleDependency dependency) {
+ runtimeDependencies.add(new DefaultMavenDependency(dependency.getGroup(), dependency.getName(), dependency.getVersion(), dependency.getArtifacts()));
+ }
+
public MavenArtifact artifact(Object source) {
return mavenArtifacts.artifact(source);
}
@@ -111,6 +132,30 @@ public class DefaultMavenPublication implements MavenPublicationInternal {
}
}
+ public String getGroupId() {
+ return projectIdentity.getGroupId();
+ }
+
+ public void setGroupId(String groupId) {
+ projectIdentity.setGroupId(groupId);
+ }
+
+ public String getArtifactId() {
+ return projectIdentity.getArtifactId();
+ }
+
+ public void setArtifactId(String artifactId) {
+ projectIdentity.setArtifactId(artifactId);
+ }
+
+ public String getVersion() {
+ return projectIdentity.getVersion();
+ }
+
+ public void setVersion(String version) {
+ projectIdentity.setVersion(version);
+ }
+
public FileCollection getPublishableFiles() {
return new UnionFileCollection(mavenArtifacts.getFiles(), pomFile);
}
@@ -119,7 +164,7 @@ public class DefaultMavenPublication implements MavenPublicationInternal {
return projectIdentity;
}
- public Set<Dependency> getRuntimeDependencies() {
+ public Set<MavenDependencyInternal> getRuntimeDependencies() {
return runtimeDependencies;
}
@@ -142,4 +187,8 @@ public class DefaultMavenPublication implements MavenPublicationInternal {
}
return "pom";
}
+
+ public ModuleVersionIdentifier getCoordinates() {
+ return new DefaultModuleVersionIdentifier(getGroupId(), getArtifactId(), getVersion());
+ }
}
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/publication/MavenPomInternal.java b/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/publication/MavenPomInternal.java
index 09f4013..848061f 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/publication/MavenPomInternal.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/publication/MavenPomInternal.java
@@ -18,8 +18,8 @@ package org.gradle.api.publish.maven.internal.publication;
import org.gradle.api.Action;
import org.gradle.api.XmlProvider;
-import org.gradle.api.artifacts.Dependency;
import org.gradle.api.publish.maven.MavenPom;
+import org.gradle.api.publish.maven.internal.dependencies.MavenDependencyInternal;
import org.gradle.api.publish.maven.internal.publisher.MavenProjectIdentity;
import java.util.Set;
@@ -28,9 +28,7 @@ public interface MavenPomInternal extends MavenPom {
MavenProjectIdentity getProjectIdentity();
- String getPackaging();
-
- Set<Dependency> getRuntimeDependencies();
+ Set<MavenDependencyInternal> getRuntimeDependencies();
Action<XmlProvider> getXmlAction();
}
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/publication/MavenPublicationInternal.java b/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/publication/MavenPublicationInternal.java
index fb3db51..7d30dee 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/publication/MavenPublicationInternal.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/publication/MavenPublicationInternal.java
@@ -16,15 +16,16 @@
package org.gradle.api.publish.maven.internal.publication;
-import org.gradle.api.artifacts.Dependency;
import org.gradle.api.file.FileCollection;
+import org.gradle.api.publish.internal.PublicationInternal;
import org.gradle.api.publish.maven.MavenPublication;
+import org.gradle.api.publish.maven.internal.dependencies.MavenDependencyInternal;
import org.gradle.api.publish.maven.internal.publisher.MavenNormalizedPublication;
import org.gradle.api.publish.maven.internal.publisher.MavenProjectIdentity;
import java.util.Set;
-public interface MavenPublicationInternal extends MavenPublication {
+public interface MavenPublicationInternal extends MavenPublication, PublicationInternal {
MavenPomInternal getPom();
@@ -34,7 +35,7 @@ public interface MavenPublicationInternal extends MavenPublication {
MavenProjectIdentity getMavenProjectIdentity();
- Set<Dependency> getRuntimeDependencies();
+ Set<MavenDependencyInternal> getRuntimeDependencies();
MavenNormalizedPublication asNormalisedPublication();
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/publisher/AntTaskBackedMavenPublisher.java b/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/publisher/AntTaskBackedMavenPublisher.java
index 6ef2a0b..7922539 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/publisher/AntTaskBackedMavenPublisher.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/publisher/AntTaskBackedMavenPublisher.java
@@ -74,7 +74,7 @@ public class AntTaskBackedMavenPublisher implements MavenPublisher {
}
private void addRepository(CustomDeployTask deployTask, MavenArtifactRepository artifactRepository) {
- RemoteRepository mavenRepository = new MavenDeployerConfigurer(artifactRepository).createRepository();
+ RemoteRepository mavenRepository = new MavenRemoteRepositoryFactory(artifactRepository).create();
deployTask.addRemoteRepository(mavenRepository);
}
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/publisher/MavenDeployerConfigurer.java b/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/publisher/MavenDeployerConfigurer.java
deleted file mode 100644
index a57c03f..0000000
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/publisher/MavenDeployerConfigurer.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.publish.maven.internal.publisher;
-
-import org.apache.maven.artifact.ant.Authentication;
-import org.apache.maven.artifact.ant.RemoteRepository;
-import org.gradle.api.Action;
-import org.gradle.api.artifacts.maven.MavenDeployer;
-import org.gradle.api.artifacts.repositories.MavenArtifactRepository;
-import org.gradle.api.artifacts.repositories.PasswordCredentials;
-
-class MavenDeployerConfigurer implements Action<MavenDeployer> {
-
- private final MavenArtifactRepository artifactRepository;
-
- public MavenDeployerConfigurer(MavenArtifactRepository artifactRepository) {
- this.artifactRepository = artifactRepository;
- }
-
- public void execute(MavenDeployer deployer) {
- deployer.setRepository(createRepository());
- }
-
- public RemoteRepository createRepository() {
- RemoteRepository remoteRepository = new RemoteRepository();
- remoteRepository.setUrl(artifactRepository.getUrl().toString());
-
- PasswordCredentials credentials = artifactRepository.getCredentials();
- String username = credentials.getUsername();
- String password = credentials.getPassword();
-
- if (username != null || password != null) {
- Authentication authentication = new Authentication();
- authentication.setUserName(username);
- authentication.setPassword(password);
- remoteRepository.addAuthentication(authentication);
- }
-
- return remoteRepository;
- }
-}
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/publisher/MavenRemoteRepositoryFactory.java b/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/publisher/MavenRemoteRepositoryFactory.java
new file mode 100644
index 0000000..1f07241
--- /dev/null
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/publisher/MavenRemoteRepositoryFactory.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.publish.maven.internal.publisher;
+
+import org.apache.maven.artifact.ant.Authentication;
+import org.apache.maven.artifact.ant.RemoteRepository;
+import org.gradle.api.artifacts.repositories.MavenArtifactRepository;
+import org.gradle.api.artifacts.repositories.PasswordCredentials;
+import org.gradle.internal.Factory;
+
+class MavenRemoteRepositoryFactory implements Factory<RemoteRepository> {
+
+ private final MavenArtifactRepository artifactRepository;
+
+ public MavenRemoteRepositoryFactory(MavenArtifactRepository artifactRepository) {
+ this.artifactRepository = artifactRepository;
+ }
+
+ public RemoteRepository create() {
+ RemoteRepository remoteRepository = new RemoteRepository();
+ remoteRepository.setUrl(artifactRepository.getUrl().toString());
+
+ PasswordCredentials credentials = artifactRepository.getCredentials();
+ String username = credentials.getUsername();
+ String password = credentials.getPassword();
+
+ if (username != null || password != null) {
+ Authentication authentication = new Authentication();
+ authentication.setUserName(username);
+ authentication.setPassword(password);
+ remoteRepository.addAuthentication(authentication);
+ }
+
+ return remoteRepository;
+ }
+}
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/publisher/ValidatingMavenPublisher.java b/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/publisher/ValidatingMavenPublisher.java
index 5a263d1..36a60c5 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/publisher/ValidatingMavenPublisher.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/publisher/ValidatingMavenPublisher.java
@@ -17,17 +17,18 @@
package org.gradle.api.publish.maven.internal.publisher;
import org.apache.commons.lang.ObjectUtils;
+import org.gradle.api.UncheckedIOException;
import org.gradle.api.artifacts.repositories.MavenArtifactRepository;
import org.gradle.api.publish.internal.PublicationFieldValidator;
import org.gradle.api.publish.maven.InvalidMavenPublicationException;
import org.gradle.api.publish.maven.MavenArtifact;
-import org.gradle.internal.UncheckedException;
import org.gradle.mvn3.org.apache.maven.model.Model;
import org.gradle.mvn3.org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.gradle.mvn3.org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import java.io.File;
import java.io.FileReader;
+import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
@@ -63,17 +64,26 @@ public class ValidatingMavenPublisher implements MavenPublisher {
}
private Model parsePomFileIntoMavenModel(MavenNormalizedPublication publication) {
+ File pomFile = publication.getPomFile();
try {
- FileReader reader = new FileReader(publication.getPomFile());
- Model model = new MavenXpp3Reader().read(reader);
- model.setPomFile(publication.getPomFile());
+ Model model = readModelFromPom(pomFile);
+ model.setPomFile(pomFile);
return model;
} catch (XmlPullParserException parseException) {
throw new InvalidMavenPublicationException(publication.getName(),
"POM file is invalid. Check any modifications you have made to the POM file.",
parseException);
- } catch (Exception ex) {
- throw UncheckedException.throwAsUncheckedException(ex);
+ } catch (IOException ex) {
+ throw new UncheckedIOException(ex);
+ }
+ }
+
+ private Model readModelFromPom(File pomFile) throws IOException, XmlPullParserException {
+ FileReader reader = new FileReader(pomFile);
+ try {
+ return new MavenXpp3Reader().read(reader);
+ } finally {
+ reader.close();
}
}
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/tasks/MavenPomFileGenerator.java b/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/tasks/MavenPomFileGenerator.java
index 4de704a..fc1a786 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/tasks/MavenPomFileGenerator.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/internal/tasks/MavenPomFileGenerator.java
@@ -23,9 +23,9 @@ import org.gradle.api.Action;
import org.gradle.api.UncheckedIOException;
import org.gradle.api.XmlProvider;
import org.gradle.api.artifacts.DependencyArtifact;
-import org.gradle.api.artifacts.ModuleDependency;
-import org.gradle.api.artifacts.ProjectDependency;
import org.gradle.api.internal.xml.XmlTransformer;
+import org.gradle.api.publish.maven.internal.dependencies.MavenDependencyInternal;
+import org.gradle.api.publish.maven.internal.publisher.MavenProjectIdentity;
import java.io.File;
import java.io.IOException;
@@ -39,28 +39,47 @@ public class MavenPomFileGenerator {
private MavenProject mavenProject = new MavenProject();
private XmlTransformer xmlTransformer = new XmlTransformer();
- public MavenPomFileGenerator() {
+ public MavenPomFileGenerator(MavenProjectIdentity identity) {
mavenProject.setModelVersion(POM_VERSION);
+ Model model = getModel();
+ model.setGroupId(identity.getGroupId());
+ model.setArtifactId(identity.getArtifactId());
+ model.setVersion(identity.getVersion());
}
- public MavenPomFileGenerator setGroupId(String groupId) {
- getModel().setGroupId(groupId);
+ public MavenPomFileGenerator setPackaging(String packaging) {
+ getModel().setPackaging(packaging);
return this;
}
- public MavenPomFileGenerator setArtifactId(String artifactId) {
- getModel().setArtifactId(artifactId);
- return this;
+ private Model getModel() {
+ return mavenProject.getModel();
}
- public MavenPomFileGenerator setVersion(String version) {
- getModel().setVersion(version);
- return this;
+ public void addRuntimeDependency(MavenDependencyInternal dependency) {
+ addDependency(dependency, "runtime");
}
- public MavenPomFileGenerator setPackaging(String packaging) {
- getModel().setPackaging(packaging);
- return this;
+ private void addDependency(MavenDependencyInternal mavenDependency, String scope) {
+ if (mavenDependency.getArtifacts().size() == 0) {
+ addDependency(mavenDependency, mavenDependency.getArtifactId(), scope, null, null);
+ } else {
+ for (DependencyArtifact artifact : mavenDependency.getArtifacts()) {
+ addDependency(mavenDependency, artifact.getName(), scope, artifact.getType(), artifact.getClassifier());
+ }
+ }
+ }
+
+ private void addDependency(MavenDependencyInternal dependency, String artifactId, String scope, String type, String classifier) {
+ Dependency mavenDependency = new Dependency();
+ mavenDependency.setGroupId(dependency.getGroupId());
+ mavenDependency.setArtifactId(artifactId);
+ mavenDependency.setVersion(dependency.getVersion());
+ mavenDependency.setType(type);
+ mavenDependency.setScope(scope);
+ mavenDependency.setClassifier(classifier);
+
+ getModel().addDependency(mavenDependency);
}
public MavenPomFileGenerator withXml(final Action<XmlProvider> action) {
@@ -68,10 +87,6 @@ public class MavenPomFileGenerator {
return this;
}
- private Model getModel() {
- return mavenProject.getModel();
- }
-
public MavenPomFileGenerator writeTo(File file) {
xmlTransformer.transform(file, POM_FILE_ENCODING, new Action<Writer>() {
public void execute(Writer writer) {
@@ -85,40 +100,4 @@ public class MavenPomFileGenerator {
return this;
}
- public void addRuntimeDependency(org.gradle.api.artifacts.Dependency dependency) {
- if (dependency instanceof ModuleDependency) {
- addDependency((ModuleDependency) dependency, "runtime");
- }
- }
-
- private void addDependency(ModuleDependency moduleDependency, String scope) {
- if (moduleDependency.getArtifacts().size() == 0) {
- getModel().addDependency(createMavenDependency(moduleDependency, moduleDependency.getName(), null, scope, null));
- } else {
- for (DependencyArtifact artifact : moduleDependency.getArtifacts()) {
- getModel().addDependency(createMavenDependency(moduleDependency, artifact.getName(), artifact.getType(), scope, artifact.getClassifier()));
- }
- }
- }
-
- private Dependency createMavenDependency(ModuleDependency dependency, String name, String type, String scope, String classifier) {
- Dependency mavenDependency = new Dependency();
- mavenDependency.setGroupId(dependency.getGroup());
- if (dependency instanceof ProjectDependency) {
- mavenDependency.setArtifactId(determineProjectDependencyArtifactId((ProjectDependency) dependency));
- } else {
- mavenDependency.setArtifactId(name);
- }
- mavenDependency.setVersion(dependency.getVersion());
- mavenDependency.setType(type);
- mavenDependency.setScope(scope);
- mavenDependency.setOptional(false);
- mavenDependency.setClassifier(classifier);
- return mavenDependency;
- }
-
- private String determineProjectDependencyArtifactId(ProjectDependency dependency) {
- return dependency.getDependencyProject().getName();
- }
-
}
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/plugins/MavenPublishPlugin.java b/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/plugins/MavenPublishPlugin.java
index 3ebb01f..bf66231 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/plugins/MavenPublishPlugin.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/plugins/MavenPublishPlugin.java
@@ -22,8 +22,6 @@ import org.gradle.api.internal.artifacts.configurations.DependencyMetaDataProvid
import org.gradle.api.internal.file.FileResolver;
import org.gradle.api.internal.notations.api.NotationParser;
import org.gradle.api.publish.PublishingExtension;
-import org.gradle.api.publish.internal.PublicationContainerInternal;
-import org.gradle.api.publish.internal.PublicationFactory;
import org.gradle.api.publish.maven.MavenArtifact;
import org.gradle.api.publish.maven.MavenPublication;
import org.gradle.api.publish.maven.internal.artifact.MavenArtifactNotationParserFactory;
@@ -65,14 +63,14 @@ public class MavenPublishPlugin implements Plugin<Project> {
final TaskContainer tasks = project.getTasks();
final Task publishLifecycleTask = tasks.getByName(PublishingPlugin.PUBLISH_LIFECYCLE_TASK_NAME);
- final Task publishLocalLifecycleTask = tasks.add(PUBLISH_LOCAL_LIFECYCLE_TASK_NAME);
+ final Task publishLocalLifecycleTask = tasks.create(PUBLISH_LOCAL_LIFECYCLE_TASK_NAME);
publishLocalLifecycleTask.setDescription("Publishes all Maven publications produced by this project to the local Maven cache.");
- publishLocalLifecycleTask.setGroup("publishing");
+ publishLocalLifecycleTask.setGroup(PublishingPlugin.PUBLISH_TASK_GROUP);
project.getExtensions().configure(PublishingExtension.class, new Action<PublishingExtension>() {
public void execute(PublishingExtension extension) {
- final PublicationContainerInternal publicationContainer = (PublicationContainerInternal) extension.getPublications();
- publicationContainer.registerFactory(MavenPublication.class, new MavenPublicationFactory(dependencyMetaDataProvider, instantiator, fileResolver));
+ // Register factory for MavenPublication
+ extension.getPublications().registerFactory(MavenPublication.class, new MavenPublicationFactory(dependencyMetaDataProvider, instantiator, fileResolver));
// Create generatePom tasks for any Maven publication
GeneratePomTaskCreator descriptorGenerationTaskCreator = new GeneratePomTaskCreator(project);
@@ -89,7 +87,7 @@ public class MavenPublishPlugin implements Plugin<Project> {
});
}
- private class MavenPublicationFactory implements PublicationFactory {
+ private class MavenPublicationFactory implements NamedDomainObjectFactory<MavenPublication> {
private final Instantiator instantiator;
private final DependencyMetaDataProvider dependencyMetaDataProvider;
private final FileResolver fileResolver;
diff --git a/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/tasks/GenerateMavenPom.java b/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/tasks/GenerateMavenPom.java
index 280fc47..3cb165d 100644
--- a/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/tasks/GenerateMavenPom.java
+++ b/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/tasks/GenerateMavenPom.java
@@ -18,19 +18,17 @@ package org.gradle.api.publish.maven.tasks;
import org.gradle.api.DefaultTask;
import org.gradle.api.Incubating;
-import org.gradle.api.artifacts.Dependency;
import org.gradle.api.internal.file.FileResolver;
import org.gradle.api.publish.maven.MavenPom;
-import org.gradle.api.publish.maven.internal.tasks.MavenPomFileGenerator;
+import org.gradle.api.publish.maven.internal.dependencies.MavenDependencyInternal;
import org.gradle.api.publish.maven.internal.publication.MavenPomInternal;
-import org.gradle.api.publish.maven.internal.publisher.MavenProjectIdentity;
+import org.gradle.api.publish.maven.internal.tasks.MavenPomFileGenerator;
import org.gradle.api.specs.Specs;
import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.TaskAction;
import javax.inject.Inject;
import java.io.File;
-import java.util.Set;
/**
* Generates an Ivy XML Module Descriptor file.
@@ -53,9 +51,9 @@ public class GenerateMavenPom extends DefaultTask {
}
/**
- * The Maven pom.
+ * The Maven POM.
*
- * @return The Maven pom.
+ * @return The Maven POM.
*/
public MavenPom getPom() {
return pom;
@@ -66,9 +64,9 @@ public class GenerateMavenPom extends DefaultTask {
}
/**
- * The file the pom will be written to.
+ * The file the POM will be written to.
*
- * @return The file the pom will be written to
+ * @return The file the POM will be written to
*/
@OutputFile
public File getDestination() {
@@ -90,25 +88,16 @@ public class GenerateMavenPom extends DefaultTask {
public void doGenerate() {
MavenPomInternal pomInternal = (MavenPomInternal) getPom();
- MavenPomFileGenerator pomGenerator = new MavenPomFileGenerator();
- copyIdentity(pomInternal, pomGenerator);
- copyDependencies(pomInternal.getRuntimeDependencies(), pomGenerator);
+ MavenPomFileGenerator pomGenerator = new MavenPomFileGenerator(pomInternal.getProjectIdentity());
+ pomGenerator.setPackaging(pomInternal.getPackaging());
+
+ for (MavenDependencyInternal runtimeDependency : pomInternal.getRuntimeDependencies()) {
+ pomGenerator.addRuntimeDependency(runtimeDependency);
+ }
+
pomGenerator.withXml(pomInternal.getXmlAction());
pomGenerator.writeTo(getDestination());
}
- private void copyIdentity(MavenPomInternal pomInternal, MavenPomFileGenerator pom) {
- MavenProjectIdentity projectIdentity = pomInternal.getProjectIdentity();
- pom.setArtifactId(projectIdentity.getArtifactId());
- pom.setGroupId(projectIdentity.getGroupId());
- pom.setVersion(projectIdentity.getVersion());
- pom.setPackaging(pomInternal.getPackaging());
- }
-
- private void copyDependencies(Set<Dependency> runtimeDependencies, MavenPomFileGenerator pom) {
- for (Dependency runtimeDependency : runtimeDependencies) {
- pom.addRuntimeDependency(runtimeDependency);
- }
- }
}
diff --git a/subprojects/maven/src/main/resources/META-INF/gradle-plugins/maven2Gradle.properties b/subprojects/maven/src/main/resources/META-INF/gradle-plugins/maven2Gradle.properties
deleted file mode 100644
index a4ac47a..0000000
--- a/subprojects/maven/src/main/resources/META-INF/gradle-plugins/maven2Gradle.properties
+++ /dev/null
@@ -1 +0,0 @@
-implementation-class=org.gradle.api.plugins.maven.Maven2GradlePlugin
diff --git a/subprojects/maven/src/test/groovy/org/gradle/api/artifacts/maven/Conf2ScopeMappingTest.java b/subprojects/maven/src/test/groovy/org/gradle/api/artifacts/maven/Conf2ScopeMappingTest.java
index 43cbe4c..c1872a6 100644
--- a/subprojects/maven/src/test/groovy/org/gradle/api/artifacts/maven/Conf2ScopeMappingTest.java
+++ b/subprojects/maven/src/test/groovy/org/gradle/api/artifacts/maven/Conf2ScopeMappingTest.java
@@ -25,9 +25,6 @@ import org.junit.runners.JUnit4;
import static org.junit.Assert.*;
-/**
- * @author Hans Dockter
- */
@RunWith(JUnit4.class)
public class Conf2ScopeMappingTest {
private final JUnit4Mockery context = new JUnit4GroovyMockery();
diff --git a/subprojects/maven/src/test/groovy/org/gradle/api/plugins/MavenPluginConventionTest.groovy b/subprojects/maven/src/test/groovy/org/gradle/api/plugins/MavenPluginConventionTest.groovy
index 1e9a54d..cab7d04 100644
--- a/subprojects/maven/src/test/groovy/org/gradle/api/plugins/MavenPluginConventionTest.groovy
+++ b/subprojects/maven/src/test/groovy/org/gradle/api/plugins/MavenPluginConventionTest.groovy
@@ -15,19 +15,15 @@
*/
package org.gradle.api.plugins
-import org.gradle.api.internal.project.DefaultProject
-import org.gradle.util.HelperUtil
import org.gradle.api.artifacts.maven.MavenPom
-
-import spock.lang.Specification
-import org.gradle.api.publication.maven.internal.MavenFactory
+import org.gradle.api.internal.project.DefaultProject
import org.gradle.api.publication.maven.internal.DefaultMavenFactory
+import org.gradle.api.publication.maven.internal.MavenFactory
+import org.gradle.util.TestUtil
+import spock.lang.Specification
-/**
- * @author Hans Dockter
- */
class MavenPluginConventionTest extends Specification {
- DefaultProject project = HelperUtil.createRootProject()
+ DefaultProject project = TestUtil.createRootProject()
MavenFactory mavenFactory = new DefaultMavenFactory()
MavenPluginConvention mavenPluginConvention = new MavenPluginConvention(project, mavenFactory)
diff --git a/subprojects/maven/src/test/groovy/org/gradle/api/plugins/MavenPluginTest.java b/subprojects/maven/src/test/groovy/org/gradle/api/plugins/MavenPluginTest.java
index 3f745d5..f2e03b1 100644
--- a/subprojects/maven/src/test/groovy/org/gradle/api/plugins/MavenPluginTest.java
+++ b/subprojects/maven/src/test/groovy/org/gradle/api/plugins/MavenPluginTest.java
@@ -23,7 +23,7 @@ import org.gradle.api.artifacts.maven.MavenResolver;
import org.gradle.api.internal.plugins.DslObject;
import org.gradle.api.internal.project.DefaultProject;
import org.gradle.api.tasks.Upload;
-import org.gradle.util.HelperUtil;
+import org.gradle.util.TestUtil;
import java.io.File;
import java.util.Set;
@@ -33,11 +33,8 @@ import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
-/**
- * @author Hans Dockter
- */
public class MavenPluginTest {
- private final DefaultProject project = HelperUtil.createRootProject();
+ private final DefaultProject project = TestUtil.createRootProject();
@org.junit.Test
public void addsConventionToProject() {
@@ -115,7 +112,7 @@ public class MavenPluginTest {
MavenRepositoryHandlerConvention convention = new DslObject(task.getRepositories()).getConvention().getPlugin(MavenRepositoryHandlerConvention.class);
assertThat(convention, notNullValue());
- task = project.getTasks().add("customUpload", Upload.class);
+ task = project.getTasks().create("customUpload", Upload.class);
convention = new DslObject(task.getRepositories()).getConvention().getPlugin(MavenRepositoryHandlerConvention.class);
assertThat(convention, notNullValue());
}
diff --git a/subprojects/maven/src/test/groovy/org/gradle/api/plugins/maven/Maven2GradlePluginSpec.groovy b/subprojects/maven/src/test/groovy/org/gradle/api/plugins/maven/Maven2GradlePluginSpec.groovy
deleted file mode 100644
index b94e43a..0000000
--- a/subprojects/maven/src/test/groovy/org/gradle/api/plugins/maven/Maven2GradlePluginSpec.groovy
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.plugins.maven
-
-import org.gradle.testfixtures.ProjectBuilder
-import spock.lang.Specification
-
-/**
- * by Szczepan Faber, created at: 8/1/12
- */
-class Maven2GradlePluginSpec extends Specification {
-
- def project = new ProjectBuilder().build()
-
- def "applies plugin"() {
- when:
- project.plugins.apply Maven2GradlePlugin
-
- then:
- project.tasks.maven2Gradle instanceof ConvertMaven2Gradle
- }
-}
diff --git a/subprojects/maven/src/test/groovy/org/gradle/api/plugins/maven/internal/MavenProjectXmlWriterTest.groovy b/subprojects/maven/src/test/groovy/org/gradle/api/plugins/maven/internal/MavenProjectXmlWriterTest.groovy
deleted file mode 100644
index 3af2c89..0000000
--- a/subprojects/maven/src/test/groovy/org/gradle/api/plugins/maven/internal/MavenProjectXmlWriterTest.groovy
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2013 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.plugins.maven.internal
-
-import spock.lang.Specification
-
-/**
- * by Szczepan Faber, created at: 1/21/13
- */
-class MavenProjectXmlWriterTest extends Specification {
-
- def writer = new MavenProjectXmlWriter()
-
- def "removes xml element"() {
- expect:
- writer.prepareXml('<?xml encoding="UTF-8"?><project/>') == "<project/>"
- writer.prepareXml('<?xml version="1.0" encoding="UTF-8"?><project/>') == "<project/>"
- writer.prepareXml('<?xml version="1.0" encoding="UTF-8" ?><project/>') == "<project/>"
- }
-}
diff --git a/subprojects/maven/src/test/groovy/org/gradle/api/plugins/maven/internal/MavenProjectsCreatorSpec.groovy b/subprojects/maven/src/test/groovy/org/gradle/api/plugins/maven/internal/MavenProjectsCreatorSpec.groovy
deleted file mode 100644
index 457a6c7..0000000
--- a/subprojects/maven/src/test/groovy/org/gradle/api/plugins/maven/internal/MavenProjectsCreatorSpec.groovy
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.plugins.maven.internal
-
-import org.gradle.api.GradleException
-import org.gradle.api.internal.artifacts.mvnsettings.DefaultMavenSettingsProvider
-import org.gradle.api.internal.artifacts.mvnsettings.MavenFileLocations
-import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
-import org.junit.Rule
-import spock.lang.Specification
-
-/**
- * by Szczepan Faber, created at: 10/15/12
- */
-class MavenProjectsCreatorSpec extends Specification {
-
- @Rule TestNameTestDirectoryProvider temp
- private settings = new DefaultMavenSettingsProvider({} as MavenFileLocations)
- private creator = new MavenProjectsCreator()
-
- def "creates single module project"() {
- given:
- def pom = temp.file("pom.xml")
- pom.text = """<project>
- <modelVersion>4.0.0</modelVersion>
- <groupId>util</groupId>
- <artifactId>util</artifactId>
- <version>2.5</version>
- <packaging>jar</packaging>
-</project>"""
-
- when:
- def mavenProjects = creator.create(settings.buildSettings(), pom) as List
-
- then:
- mavenProjects.size() == 1
- mavenProjects[0].name == 'util'
- }
-
- def "creates multi module project"() {
- given:
- def parentPom = temp.file("pom.xml")
- parentPom.text = """<project>
- <modelVersion>4.0.0</modelVersion>
- <groupId>org.gradle.webinar</groupId>
- <artifactId>webinar-parent</artifactId>
- <version>1.0-SNAPSHOT</version>
- <packaging>pom</packaging>
-
- <modules>
- <module>webinar-api</module>
- </modules>
-</project>
-"""
-
- temp.createDir("webinar-api")
- temp.file("webinar-api/pom.xml").text = """<project>
- <modelVersion>4.0.0</modelVersion>
- <artifactId>webinar-api</artifactId>
- <packaging>jar</packaging>
-
- <parent>
- <groupId>org.gradle.webinar</groupId>
- <artifactId>webinar-parent</artifactId>
- <version>1.0-SNAPSHOT</version>
- </parent>
-</project>
-"""
-
- when:
- def mavenProjects = creator.create(settings.buildSettings(), parentPom) as List
-
- then:
- mavenProjects.size() == 2
- mavenProjects[0].name == 'webinar-parent'
- mavenProjects[1].name == 'webinar-api'
- }
-
- def "fails with decent exception if pom is incorrect"() {
- given:
- def pom = temp.file("pom.xml")
- pom.text = """<project>
- <modelVersion>4.0.0</modelVersion>
- <artifactId>util</artifactId>
- <version>2.5</version>
- <packaging>jar</packaging>
-</project>"""
-
- when:
- creator.create(settings.buildSettings(), pom) as List
-
- then:
- def ex = thrown(GradleException)
- ex.message.contains(pom.getAbsolutePath())
- }
-
- def "fails with decent exception if pom does not exist"() {
- when:
- creator.create(settings.buildSettings(), temp.file("pom.xml")) as List
-
- then:
- thrown(GradleException)
- }
-}
diff --git a/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/BasePomFilterContainerTest.java b/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/BasePomFilterContainerTest.java
index 46241cf..5561a61 100644
--- a/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/BasePomFilterContainerTest.java
+++ b/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/BasePomFilterContainerTest.java
@@ -32,9 +32,6 @@ import java.util.Set;
import static org.junit.Assert.*;
-/**
- * @author Hans Dockter
- */
@RunWith(JMock.class)
public class BasePomFilterContainerTest {
private static final String TEST_NAME = "testName";
diff --git a/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/DefaultArtifactPomTest.java b/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/DefaultArtifactPomTest.java
index b903870..8974d10 100644
--- a/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/DefaultArtifactPomTest.java
+++ b/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/DefaultArtifactPomTest.java
@@ -44,9 +44,6 @@ import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
-/**
- * @author Hans Dockter
- */
public class DefaultArtifactPomTest {
private DefaultArtifactPom artifactPom;
private MavenPom testPom;
diff --git a/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/DefaultConf2ScopeMappingContainerTest.java b/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/DefaultConf2ScopeMappingContainerTest.java
index d27e17b..aed0e20 100644
--- a/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/DefaultConf2ScopeMappingContainerTest.java
+++ b/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/DefaultConf2ScopeMappingContainerTest.java
@@ -32,9 +32,6 @@ import static java.util.Arrays.asList;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.*;
-/**
- * @author Hans Dockter
- */
@RunWith(JUnit4.class)
public class DefaultConf2ScopeMappingContainerTest {
private final JUnit4Mockery context = new JUnit4GroovyMockery();
diff --git a/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/DefaultMavenPomFactoryTest.groovy b/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/DefaultMavenPomFactoryTest.groovy
index 406909a..74b7278 100644
--- a/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/DefaultMavenPomFactoryTest.groovy
+++ b/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/DefaultMavenPomFactoryTest.groovy
@@ -13,17 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.gradle.api.publication.maven.internal;
-
+package org.gradle.api.publication.maven.internal
import org.gradle.api.artifacts.ConfigurationContainer
-
import org.gradle.api.internal.file.FileResolver
import spock.lang.Specification
-/**
- * @author Hans Dockter
- */
public class DefaultMavenPomFactoryTest extends Specification {
def createMavenPom() {
DefaultConf2ScopeMappingContainer scopeMappings = new DefaultConf2ScopeMappingContainer();
diff --git a/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/DefaultPomFilterTest.java b/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/DefaultPomFilterTest.java
index b99e204..d85d793 100644
--- a/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/DefaultPomFilterTest.java
+++ b/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/DefaultPomFilterTest.java
@@ -26,9 +26,6 @@ import org.junit.runner.RunWith;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
-/**
- * @author Hans Dockter
- */
@RunWith(JMock.class)
public class DefaultPomFilterTest {
private static final String TEST_NAME = "TEST_NAME";
diff --git a/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/AbstractMavenResolverTest.java b/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/AbstractMavenResolverTest.java
index 734c43b..832d8e5 100644
--- a/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/AbstractMavenResolverTest.java
+++ b/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/AbstractMavenResolverTest.java
@@ -31,9 +31,9 @@ import org.gradle.api.artifacts.maven.MavenPom;
import org.gradle.api.artifacts.maven.PomFilterContainer;
import org.gradle.api.artifacts.maven.PublishFilter;
import org.gradle.api.internal.artifacts.publish.DefaultPublishArtifact;
+import org.gradle.api.logging.LogLevel;
import org.gradle.api.publication.maven.internal.ArtifactPomContainer;
import org.gradle.api.publication.maven.internal.DefaultMavenDeployment;
-import org.gradle.api.logging.LogLevel;
import org.gradle.logging.LoggingManagerInternal;
import org.gradle.util.AntUtil;
import org.gradle.util.JUnit4GroovyMockery;
@@ -55,9 +55,6 @@ import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
-/**
- * @author Hans Dockter
- */
public abstract class AbstractMavenResolverTest {
public static final String TEST_NAME = "name";
private static final Artifact TEST_IVY_ARTIFACT = DefaultArtifact.newIvyArtifact(ModuleRevisionId.newInstance("org", TEST_NAME, "1.0"), null);
diff --git a/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/BaseMavenDeployerTest.java b/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/BaseMavenDeployerTest.java
index 1c0a32b..a40e6a1 100644
--- a/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/BaseMavenDeployerTest.java
+++ b/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/BaseMavenDeployerTest.java
@@ -23,8 +23,8 @@ import org.codehaus.plexus.PlexusContainerException;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.PublishArtifact;
import org.gradle.api.artifacts.maven.PomFilterContainer;
-import org.gradle.internal.Factory;
import org.gradle.api.publication.maven.internal.DefaultMavenDeployment;
+import org.gradle.internal.Factory;
import org.gradle.util.WrapUtil;
import org.jmock.Expectations;
import org.junit.Test;
@@ -36,9 +36,6 @@ import java.util.Set;
import static org.junit.Assert.assertTrue;
-/**
- * @author Hans Dockter
- */
@RunWith(org.jmock.integration.junit4.JMock.class)
public class BaseMavenDeployerTest extends AbstractMavenResolverTest {
diff --git a/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/BaseMavenInstallerTest.java b/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/BaseMavenInstallerTest.java
index 4db25cb..2acec39 100644
--- a/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/BaseMavenInstallerTest.java
+++ b/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/BaseMavenInstallerTest.java
@@ -20,16 +20,13 @@ import org.apache.maven.artifact.ant.InstallDeployTaskSupport;
import org.codehaus.plexus.PlexusContainerException;
import org.gradle.api.artifacts.PublishArtifact;
import org.gradle.api.artifacts.maven.PomFilterContainer;
-import org.gradle.internal.Factory;
import org.gradle.api.publication.maven.internal.DefaultMavenDeployment;
+import org.gradle.internal.Factory;
import org.jmock.Expectations;
import java.io.IOException;
import java.util.Set;
-/**
- * @author Hans Dockter
- */
public class BaseMavenInstallerTest extends AbstractMavenResolverTest {
private BaseMavenInstaller mavenInstaller;
diff --git a/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/DefaultDeployTaskFactoryTest.java b/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/DefaultDeployTaskFactoryTest.java
index fc35ae1..9064f54 100644
--- a/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/DefaultDeployTaskFactoryTest.java
+++ b/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/DefaultDeployTaskFactoryTest.java
@@ -15,13 +15,10 @@
*/
package org.gradle.api.publication.maven.internal.ant;
-import static org.junit.Assert.assertTrue;
-
import org.junit.Test;
-/**
- * @author Hans Dockter
- */
+import static org.junit.Assert.assertTrue;
+
public class DefaultDeployTaskFactoryTest {
@Test
public void create() {
diff --git a/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/DefaultExcludeRuleConverterTest.java b/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/DefaultExcludeRuleConverterTest.java
index fe1f57b..8746c9f 100644
--- a/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/DefaultExcludeRuleConverterTest.java
+++ b/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/DefaultExcludeRuleConverterTest.java
@@ -23,9 +23,6 @@ import org.junit.Test;
import static junit.framework.Assert.assertEquals;
import static org.junit.Assert.assertNull;
-/**
- * @author Hans Dockter
- */
public class DefaultExcludeRuleConverterTest {
private static final String TEST_ORG = "org";
private static final String TEST_MODULE = "module";
diff --git a/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/DefaultGroovyMavenDeployerTest.groovy b/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/DefaultGroovyMavenDeployerTest.groovy
index bf9d6a8..e11857a 100644
--- a/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/DefaultGroovyMavenDeployerTest.groovy
+++ b/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/DefaultGroovyMavenDeployerTest.groovy
@@ -17,15 +17,12 @@
package org.gradle.api.publication.maven.internal.ant
import org.gradle.api.artifacts.maven.PomFilterContainer
-
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+
import static org.junit.Assert.assertEquals
-/**
- * @author Hans Dockter
- */
@RunWith (org.jmock.integration.junit4.JMock.class)
class DefaultGroovyMavenDeployerTest extends BaseMavenDeployerTest {
private DefaultGroovyMavenDeployer groovyMavenDeployer;
diff --git a/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/DefaultGroovyPomFilterContainerTest.groovy b/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/DefaultGroovyPomFilterContainerTest.groovy
index be6ce92..117fd73 100644
--- a/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/DefaultGroovyPomFilterContainerTest.groovy
+++ b/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/DefaultGroovyPomFilterContainerTest.groovy
@@ -15,7 +15,6 @@
*/
package org.gradle.api.publication.maven.internal.ant
-import java.lang.reflect.Proxy
import org.gradle.api.artifacts.maven.MavenPom
import org.gradle.api.artifacts.maven.PomFilterContainer
import org.gradle.api.artifacts.maven.PublishFilter
@@ -29,11 +28,11 @@ import org.jmock.integration.junit4.JMock
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+
+import java.lang.reflect.Proxy
+
import static org.junit.Assert.assertSame
-/**
- * @author Hans Dockter
- */
@RunWith(JMock)
class DefaultGroovyPomFilterContainerTest extends BasePomFilterContainerTest {
static final String TEST_NAME = "somename"
diff --git a/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/DefaultPomDependenciesConverterTest.java b/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/DefaultPomDependenciesConverterTest.java
index 6afac33..9a668fa 100644
--- a/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/DefaultPomDependenciesConverterTest.java
+++ b/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/DefaultPomDependenciesConverterTest.java
@@ -41,9 +41,6 @@ import static org.gradle.util.WrapUtil.*;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.*;
-/**
- * @author Hans Dockter
- */
@RunWith(JMock.class)
public class DefaultPomDependenciesConverterTest {
private JUnit4Mockery context = new JUnit4GroovyMockery();
diff --git a/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/EmptyMavenSettingsSupplierTest.groovy b/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/EmptyMavenSettingsSupplierTest.groovy
index eafd010..6c92ac7 100644
--- a/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/EmptyMavenSettingsSupplierTest.groovy
+++ b/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/EmptyMavenSettingsSupplierTest.groovy
@@ -19,9 +19,6 @@ package org.gradle.api.publication.maven.internal.ant
import org.apache.maven.artifact.ant.InstallDeployTaskSupport
import spock.lang.Specification
-/**
- * @author Szczepan Faber, created at: 3/29/11
- */
class EmptyMavenSettingsSupplierTest extends Specification {
def EmptyMavenSettingsSupplier supplier = new EmptyMavenSettingsSupplier()
diff --git a/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/MaybeUserMavenSettingsSupplierTest.groovy b/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/MaybeUserMavenSettingsSupplierTest.groovy
index 9906e0a..eb24887 100644
--- a/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/MaybeUserMavenSettingsSupplierTest.groovy
+++ b/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/MaybeUserMavenSettingsSupplierTest.groovy
@@ -18,12 +18,8 @@ package org.gradle.api.publication.maven.internal.ant
import org.apache.maven.artifact.ant.InstallDeployTaskSupport
import org.gradle.api.internal.artifacts.mvnsettings.DefaultMavenFileLocations
-
import spock.lang.Specification
-/**
- * @author Szczepan Faber, created at: 3/29/11
- */
class MaybeUserMavenSettingsSupplierTest extends Specification {
InstallDeployTaskSupport support = Mock()
diff --git a/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/ProjectDependencyArtifactIdExtractorHackTest.groovy b/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/ProjectDependencyArtifactIdExtractorHackTest.groovy
index d3701ec..0f3a272 100644
--- a/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/ProjectDependencyArtifactIdExtractorHackTest.groovy
+++ b/subprojects/maven/src/test/groovy/org/gradle/api/publication/maven/internal/ant/ProjectDependencyArtifactIdExtractorHackTest.groovy
@@ -16,17 +16,16 @@
package org.gradle.api.publication.maven.internal.ant
-import org.gradle.util.HelperUtil
import org.gradle.api.internal.artifacts.dependencies.DefaultProjectDependency
import org.gradle.api.plugins.BasePlugin
import org.gradle.api.plugins.MavenPlugin
-
+import org.gradle.util.TestUtil
import spock.lang.Specification
import spock.lang.Issue
@Issue("GRADLE-443")
class ProjectDependencyArtifactIdExtractorHackTest extends Specification {
- def project = HelperUtil.createRootProject()
+ def project = TestUtil.createRootProject()
def extractor = new ProjectDependencyArtifactIdExtractorHack(new DefaultProjectDependency(project, null, true))
def "artifact ID defaults to project name if neither archivesBaseName nor mavenDeployer.pom.artifactId is configured"() {
diff --git a/subprojects/maven/src/test/groovy/org/gradle/api/publish/maven/internal/artifact/MavenArtifactNotationParserFactoryTest.groovy b/subprojects/maven/src/test/groovy/org/gradle/api/publish/maven/internal/artifact/MavenArtifactNotationParserFactoryTest.groovy
index 1161a7e..b6d1fd2 100644
--- a/subprojects/maven/src/test/groovy/org/gradle/api/publish/maven/internal/artifact/MavenArtifactNotationParserFactoryTest.groovy
+++ b/subprojects/maven/src/test/groovy/org/gradle/api/publish/maven/internal/artifact/MavenArtifactNotationParserFactoryTest.groovy
@@ -25,7 +25,7 @@ import org.gradle.api.tasks.TaskDependency
import org.gradle.api.tasks.bundling.Jar
import org.gradle.internal.reflect.DirectInstantiator
import org.gradle.internal.reflect.Instantiator
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import spock.lang.Specification
public class MavenArtifactNotationParserFactoryTest extends Specification {
@@ -119,7 +119,7 @@ public class MavenArtifactNotationParserFactoryTest extends Specification {
def "creates MavenArtifact for ArchivePublishArtifact"() {
when:
- def rootProject = HelperUtil.createRootProject()
+ def rootProject = TestUtil.createRootProject()
def archive = rootProject.task(type: Jar, {})
archive.setBaseName("baseName")
archive.setExtension(archiveExtension)
diff --git a/subprojects/maven/src/test/groovy/org/gradle/api/publish/maven/internal/publication/DefaultMavenPublicationTest.groovy b/subprojects/maven/src/test/groovy/org/gradle/api/publish/maven/internal/publication/DefaultMavenPublicationTest.groovy
index 06a9c32..0273af8 100644
--- a/subprojects/maven/src/test/groovy/org/gradle/api/publish/maven/internal/publication/DefaultMavenPublicationTest.groovy
+++ b/subprojects/maven/src/test/groovy/org/gradle/api/publish/maven/internal/publication/DefaultMavenPublicationTest.groovy
@@ -14,17 +14,24 @@
* limitations under the License.
*/
package org.gradle.api.publish.maven.internal.publication
+
import org.gradle.api.Action
import org.gradle.api.InvalidUserDataException
import org.gradle.api.Task
-import org.gradle.api.artifacts.DependencySet
+import org.gradle.api.artifacts.DependencyArtifact
import org.gradle.api.artifacts.ModuleDependency
+import org.gradle.api.artifacts.ProjectDependency
import org.gradle.api.artifacts.PublishArtifact
-import org.gradle.api.artifacts.PublishArtifactSet
+import org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier
import org.gradle.api.internal.component.SoftwareComponentInternal
import org.gradle.api.internal.component.Usage
import org.gradle.api.internal.file.collections.SimpleFileCollection
import org.gradle.api.internal.notations.api.NotationParser
+import org.gradle.api.internal.plugins.ExtensionContainerInternal
+import org.gradle.api.internal.project.ProjectInternal
+import org.gradle.api.publish.PublishingExtension
+import org.gradle.api.publish.internal.DefaultPublicationContainer
+import org.gradle.api.publish.internal.PublicationInternal
import org.gradle.api.publish.maven.MavenArtifact
import org.gradle.api.publish.maven.internal.publisher.MavenProjectIdentity
import org.gradle.api.tasks.TaskDependency
@@ -61,7 +68,40 @@ public class DefaultMavenPublicationTest extends Specification {
then:
publication.name == "pub-name"
- publication.mavenProjectIdentity == module
+ publication.mavenProjectIdentity.groupId == "group"
+ publication.mavenProjectIdentity.artifactId == "name"
+ publication.mavenProjectIdentity.version == "version"
+ }
+
+ def "changing publication coordinates does not effect those provided"() {
+ when:
+ module.artifactId >> "name"
+ module.groupId >> "group"
+ module.version >> "version"
+
+ and:
+ def publication = createPublication()
+
+ and:
+ publication.groupId = "group2"
+ publication.artifactId = "name2"
+ publication.version = "version2"
+
+ then:
+ module.groupId == "group"
+ module.artifactId == "name"
+ module.version == "version"
+
+ and:
+ publication.groupId == "group2"
+ publication.artifactId == "name2"
+ publication.version == "version2"
+
+ and:
+ publication.mavenProjectIdentity.groupId == "group2"
+ publication.mavenProjectIdentity.artifactId == "name2"
+ publication.mavenProjectIdentity.version == "version2"
+
}
def "packaging is taken from first added artifact without extension"() {
@@ -88,32 +128,25 @@ public class DefaultMavenPublicationTest extends Specification {
publication.runtimeDependencies.empty
}
- def "artifacts and dependencies are taken from added component"() {
+ def "artifacts are taken from added component"() {
given:
def publication = createPublication()
- def component = Mock(SoftwareComponentInternal)
- def usage = Mock(Usage)
def artifact = Mock(PublishArtifact)
- def dependency = Mock(ModuleDependency)
def publishArtifactDependencies = Mock(TaskDependency)
def mavenArtifact = Mock(MavenArtifact)
when:
- component.usages >> [usage]
- usage.artifacts >> [artifact]
- usage.dependencies >> [dependency]
-
notationParser.parseNotation(artifact) >> mavenArtifact
mavenArtifact.file >> artifactFile
and:
- publication.from(component)
+ publication.from(componentWithArtifact(artifact))
then:
publication.publishableFiles.files == [pomFile, artifactFile] as Set
publication.artifacts == [mavenArtifact] as Set
- publication.runtimeDependencies == [dependency] as Set
+ publication.runtimeDependencies.empty
when:
def task = Mock(Task)
@@ -124,25 +157,96 @@ public class DefaultMavenPublicationTest extends Specification {
publication.publishableFiles.buildDependencies.getDependencies(task) == [task] as Set
}
- def "cannot add multiple components"() {
+ def "adopts module dependency from added component"() {
given:
def publication = createPublication()
- def component = Mock(SoftwareComponentInternal)
- def usage = Mock(Usage)
- def publishArtifactSet = Mock(PublishArtifactSet)
- def dependencySet = Mock(DependencySet)
+ def moduleDependency = Mock(ModuleDependency)
+ def artifact = Mock(DependencyArtifact)
when:
- publication.from(component)
+ moduleDependency.group >> "group"
+ moduleDependency.name >> "name"
+ moduleDependency.version >> "version"
+ moduleDependency.artifacts >> [artifact]
+
+ and:
+ publication.from(componentWithDependency(moduleDependency))
then:
- component.usages >> [usage]
- usage.artifacts >> publishArtifactSet
- publishArtifactSet.iterator() >> [].iterator()
- usage.dependencies >> dependencySet
- dependencySet.iterator() >> [].iterator()
+ publication.runtimeDependencies.size() == 1
+ with (publication.runtimeDependencies.asList().first()) {
+ groupId == "group"
+ artifactId == "name"
+ version == "version"
+ artifacts == [artifact]
+ }
+ }
+
+ def "adopts dependency on project with single publications"() {
+ given:
+ def publication = createPublication()
+ def projectDependency = Mock(ProjectDependency)
+ def extensionContainer = Mock(ExtensionContainerInternal)
+ def publishingExtension = Mock(PublishingExtension)
+ def publications = new DefaultPublicationContainer(new DirectInstantiator())
+ publications.add(otherPublication("otherPub1", "pub-group", "pub-name", "pub-version"))
when:
+ projectDependency.artifacts >> []
+ projectDependency.dependencyProject >> Stub(ProjectInternal) {
+ getExtensions() >> extensionContainer
+ }
+ extensionContainer.findByType(PublishingExtension) >> publishingExtension
+ publishingExtension.publications >> publications
+
+ and:
+ publication.from(componentWithDependency(projectDependency))
+
+ then:
+ publication.runtimeDependencies.size() == 1
+ with (publication.runtimeDependencies.asList().first()) {
+ groupId == "pub-group"
+ artifactId == "pub-name"
+ version == "pub-version"
+ artifacts == []
+ }
+ }
+
+ def "adopts dependency on project without publishing extension"() {
+ given:
+ def publication = createPublication()
+ def projectDependency = Mock(ProjectDependency)
+ def extensionContainer = Mock(ExtensionContainerInternal)
+
+ when:
+ projectDependency.group >> "dep-group"
+ projectDependency.name >> "dep-name-1"
+ projectDependency.version >> "dep-version"
+ projectDependency.dependencyProject >> Stub(ProjectInternal) {
+ getExtensions() >> extensionContainer
+ getName() >> "project-name"
+ }
+ projectDependency.artifacts >> []
+ extensionContainer.findByType(PublishingExtension) >> null
+
+ and:
+ publication.from(componentWithDependency(projectDependency))
+
+ then:
+ publication.runtimeDependencies.size() == 1
+ with (publication.runtimeDependencies.asList().first()) {
+ groupId == "dep-group"
+ artifactId == "project-name"
+ version == "dep-version"
+ artifacts == []
+ }
+ }
+ def "cannot add multiple components"() {
+ given:
+ def publication = createPublication()
+
+ when:
+ publication.from(createComponent([], []))
publication.from(Mock(SoftwareComponentInternal))
then:
@@ -230,4 +334,31 @@ public class DefaultMavenPublicationTest extends Specification {
}
return artifact
}
+
+ def componentWithDependency(ModuleDependency dependency) {
+ return createComponent([], [dependency])
+ }
+
+ def componentWithArtifact(def artifact) {
+ return createComponent([artifact], [])
+ }
+
+ def createComponent(def artifacts, def dependencies) {
+ def usage = Stub(Usage) {
+ getName() >> "runtime"
+ getArtifacts() >> artifacts
+ getDependencies() >> dependencies
+ }
+ def component = Stub(SoftwareComponentInternal) {
+ getUsages() >> [usage]
+ }
+ return component
+ }
+
+ def otherPublication(String name, String group, String artifactId, String version) {
+ def pub = Mock(PublicationInternal)
+ pub.name >> name
+ pub.coordinates >> new DefaultModuleVersionIdentifier(group, artifactId, version)
+ return pub
+ }
}
diff --git a/subprojects/maven/src/test/groovy/org/gradle/api/publish/maven/internal/publisher/ValidatingMavenPublisherTest.groovy b/subprojects/maven/src/test/groovy/org/gradle/api/publish/maven/internal/publisher/ValidatingMavenPublisherTest.groovy
index 9d3831a..092c4bf 100644
--- a/subprojects/maven/src/test/groovy/org/gradle/api/publish/maven/internal/publisher/ValidatingMavenPublisherTest.groovy
+++ b/subprojects/maven/src/test/groovy/org/gradle/api/publish/maven/internal/publisher/ValidatingMavenPublisherTest.groovy
@@ -37,8 +37,8 @@ public class ValidatingMavenPublisherTest extends Specification {
def "delegates when publication is valid"() {
when:
- def projectIdentity = projectIdentity("the-group", "the-artifact", "the-version")
- def publication = new MavenNormalizedPublication("pub-name", createPomFile("the-group", "the-artifact", "the-version"), projectIdentity, emptySet())
+ def projectIdentity = makeProjectIdentity("the-group", "the-artifact", "the-version")
+ def publication = new MavenNormalizedPublication("pub-name", createPomFile(projectIdentity), projectIdentity, emptySet())
def repository = Mock(MavenArtifactRepository)
and:
@@ -50,8 +50,8 @@ public class ValidatingMavenPublisherTest extends Specification {
def "validates project coordinates"() {
given:
- def projectIdentity = projectIdentity(groupId, artifactId, version)
- def publication = new MavenNormalizedPublication("pub-name", createPomFile(groupId, artifactId, version), projectIdentity, emptySet())
+ def projectIdentity = makeProjectIdentity(groupId, artifactId, version)
+ def publication = new MavenNormalizedPublication("pub-name", createPomFile(projectIdentity), projectIdentity, emptySet())
def repository = Mock(MavenArtifactRepository)
@@ -78,8 +78,8 @@ public class ValidatingMavenPublisherTest extends Specification {
def "project coordinates must match POM file"() {
given:
- def projectIdentity = projectIdentity("group", "artifact", "version")
- def pomFile = createPomFile(groupId, artifactId, version)
+ def projectIdentity = makeProjectIdentity("group", "artifact", "version")
+ def pomFile = createPomFile(makeProjectIdentity(groupId, artifactId, version))
def publication = new MavenNormalizedPublication("pub-name", pomFile, projectIdentity, emptySet())
def repository = Mock(MavenArtifactRepository)
@@ -99,8 +99,8 @@ public class ValidatingMavenPublisherTest extends Specification {
}
def "validates artifact attributes"() {
- def projectIdentity = projectIdentity("group", "artifact", "version")
- def pomFile = createPomFile("group", "artifact", "version")
+ def projectIdentity = makeProjectIdentity("group", "artifact", "version")
+ def pomFile = createPomFile(projectIdentity)
def mavenArtifact = Stub(MavenArtifact) {
getExtension() >> extension
getClassifier() >> classifier
@@ -126,8 +126,8 @@ public class ValidatingMavenPublisherTest extends Specification {
@Unroll
def "cannot publish with file that #message"() {
- def projectIdentity = projectIdentity("group", "artifact", "version")
- def pomFile = createPomFile("group", "artifact", "version")
+ def projectIdentity = makeProjectIdentity("group", "artifact", "version")
+ def pomFile = createPomFile(projectIdentity)
def mavenArtifact = Mock(MavenArtifact)
def publication = new MavenNormalizedPublication("pub-name", pomFile, projectIdentity, toSet([mavenArtifact]))
@@ -160,8 +160,8 @@ public class ValidatingMavenPublisherTest extends Specification {
getClassifier() >> "classified"
getFile() >> testDir.createFile('artifact2')
}
- def projectIdentity = projectIdentity("group", "artifact", "version")
- def pomFile = createPomFile("group", "artifact", "version")
+ def projectIdentity = makeProjectIdentity("group", "artifact", "version")
+ def pomFile = createPomFile(projectIdentity)
def publication = new MavenNormalizedPublication("pub-name", pomFile, projectIdentity, toSet([artifact1, artifact2]))
when:
@@ -179,8 +179,8 @@ public class ValidatingMavenPublisherTest extends Specification {
getClassifier() >> null
getFile() >> testDir.createFile('artifact1')
}
- def projectIdentity = projectIdentity("group", "artifact", "version")
- def pomFile = createPomFile("group", "artifact", "version")
+ def projectIdentity = makeProjectIdentity("group", "artifact", "version")
+ def pomFile = createPomFile(projectIdentity)
def publication = new MavenNormalizedPublication("pub-name", pomFile, projectIdentity, toSet([artifact1]))
when:
@@ -193,8 +193,8 @@ public class ValidatingMavenPublisherTest extends Specification {
def "supplied POM file must be valid"() {
given:
- def projectIdentity = projectIdentity("group", "artifact", "version")
- def pomFile = createPomFile("group", "artifact", "version", new Action<XmlProvider>() {
+ def projectIdentity = makeProjectIdentity("group", "artifact", "version")
+ def pomFile = createPomFile(projectIdentity, new Action<XmlProvider>() {
void execute(XmlProvider xml) {
xml.asNode().appendNode("invalid", "This is not a valid pomFile element")
}
@@ -213,7 +213,7 @@ public class ValidatingMavenPublisherTest extends Specification {
e.cause.message =~ "Unrecognised tag: 'invalid' .*"
}
- private def projectIdentity(def groupId, def artifactId, def version) {
+ private def makeProjectIdentity(def groupId, def artifactId, def version) {
return Stub(MavenProjectIdentity) {
getGroupId() >> groupId
getArtifactId() >> artifactId
@@ -221,12 +221,9 @@ public class ValidatingMavenPublisherTest extends Specification {
}
}
- private def createPomFile(def groupId, def artifactId, def version, Action<XmlProvider> withXmlAction = null) {
+ private def createPomFile(MavenProjectIdentity projectIdentity, Action<XmlProvider> withXmlAction = null) {
def pomFile = testDir.file("pom")
- MavenPomFileGenerator pomFileGenerator = new MavenPomFileGenerator();
- pomFileGenerator.groupId = groupId
- pomFileGenerator.artifactId = artifactId
- pomFileGenerator.version = version
+ MavenPomFileGenerator pomFileGenerator = new MavenPomFileGenerator(projectIdentity);
if (withXmlAction != null) {
pomFileGenerator.withXml(withXmlAction)
}
diff --git a/subprojects/maven/src/test/groovy/org/gradle/api/publish/maven/internal/tasks/MavenPomFileGeneratorTest.groovy b/subprojects/maven/src/test/groovy/org/gradle/api/publish/maven/internal/tasks/MavenPomFileGeneratorTest.groovy
index 4f9de23..baf67ab 100644
--- a/subprojects/maven/src/test/groovy/org/gradle/api/publish/maven/internal/tasks/MavenPomFileGeneratorTest.groovy
+++ b/subprojects/maven/src/test/groovy/org/gradle/api/publish/maven/internal/tasks/MavenPomFileGeneratorTest.groovy
@@ -15,13 +15,11 @@
*/
package org.gradle.api.publish.maven.internal.tasks
-
import org.gradle.api.Action
-import org.gradle.api.Project
import org.gradle.api.XmlProvider
import org.gradle.api.artifacts.DependencyArtifact
-import org.gradle.api.artifacts.ModuleDependency
-import org.gradle.api.artifacts.ProjectDependency
+import org.gradle.api.publish.maven.internal.dependencies.MavenDependencyInternal
+import org.gradle.api.publish.maven.internal.publication.DefaultMavenProjectIdentity
import org.gradle.test.fixtures.file.TestDirectoryProvider
import org.gradle.test.fixtures.file.TestFile
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
@@ -31,7 +29,8 @@ import spock.lang.Specification
class MavenPomFileGeneratorTest extends Specification {
TestDirectoryProvider testDirectoryProvider = new TestNameTestDirectoryProvider()
- MavenPomFileGenerator generator = new MavenPomFileGenerator()
+ def projectIdentity = new DefaultMavenProjectIdentity("group-id", "artifact-id", "1.0")
+ MavenPomFileGenerator generator = new MavenPomFileGenerator(projectIdentity)
def "writes correct prologue and schema declarations"() {
expect:
@@ -42,38 +41,32 @@ class MavenPomFileGeneratorTest extends Specification {
"""))
}
- def "writes empty pom with default values"() {
+ def "writes configured coordinates"() {
expect:
with (pom) {
- modelVersion == "4.0.0"
- groupId == "unknown"
- artifactId == "empty-project"
- version == "0"
- dependencies.empty
+ groupId == "group-id"
+ artifactId == "artifact-id"
+ version == "1.0"
+ packaging.empty
}
}
- def "writes configured coordinates"() {
+ def "writes packaging"() {
when:
- generator.groupId = "group-id"
- generator.artifactId = "artifact-id"
- generator.version = "1.0"
generator.packaging = "pom"
then:
with (pom) {
- groupId == "group-id"
- artifactId == "artifact-id"
- version == "1.0"
packaging == "pom"
}
}
def "encodes coordinates for XML and unicode"() {
when:
- generator.groupId = 'group-ぴ₦ガき∆ç√∫'
- generator.artifactId = 'artifact-<tag attrib="value"/>-markup'
- generator.version = 'version-&"'
+ def groupId = 'group-ぴ₦ガき∆ç√∫'
+ def artifactId = 'artifact-<tag attrib="value"/>-markup'
+ def version = 'version-&"'
+ generator = new MavenPomFileGenerator(new DefaultMavenProjectIdentity(groupId, artifactId, version))
then:
with (pom) {
@@ -84,14 +77,14 @@ class MavenPomFileGeneratorTest extends Specification {
}
def "writes regular dependency"() {
- def dependency = Mock(ModuleDependency)
+ def dependency = Mock(MavenDependencyInternal)
when:
generator.addRuntimeDependency(dependency)
then:
dependency.artifacts >> new HashSet<DependencyArtifact>()
- dependency.group >> "dep-group"
- dependency.name >> "dep-name"
+ dependency.groupId >> "dep-group"
+ dependency.artifactId >> "dep-name"
dependency.version >> "dep-version"
and:
@@ -106,33 +99,8 @@ class MavenPomFileGeneratorTest extends Specification {
}
}
- def "writes project dependency"() {
- def dependency = Mock(ProjectDependency)
- when:
- generator.addRuntimeDependency(dependency)
-
- then:
- dependency.artifacts >> new HashSet<DependencyArtifact>()
- dependency.group >> "dep-group"
- dependency.version >> "dep-version"
- dependency.dependencyProject >> Stub(Project) {
- getName() >> "project-name"
- }
-
- and:
- with (pom) {
- dependencies.dependency.size() == 1
- with (dependencies[0].dependency[0]) {
- groupId == "dep-group"
- artifactId == "project-name"
- version == "dep-version"
- scope == "runtime"
- }
- }
- }
-
def "writes dependency with artifacts"() {
- def dependency = Mock(ModuleDependency)
+ def dependency = Mock(MavenDependencyInternal)
def artifact1 = Mock(DependencyArtifact)
def artifact2 = Mock(DependencyArtifact)
@@ -141,7 +109,7 @@ class MavenPomFileGeneratorTest extends Specification {
then:
dependency.artifacts >> CollectionUtils.toSet([artifact1, artifact2])
- dependency.group >> "dep-group"
+ dependency.groupId >> "dep-group"
dependency.version >> "dep-version"
artifact1.name >> "artifact-1"
artifact1.type >> "type-1"
diff --git a/subprojects/maven/src/test/groovy/org/gradle/api/publish/maven/plugins/MavenPublishPluginTest.groovy b/subprojects/maven/src/test/groovy/org/gradle/api/publish/maven/plugins/MavenPublishPluginTest.groovy
index 46a1c02..c77d010 100644
--- a/subprojects/maven/src/test/groovy/org/gradle/api/publish/maven/plugins/MavenPublishPluginTest.groovy
+++ b/subprojects/maven/src/test/groovy/org/gradle/api/publish/maven/plugins/MavenPublishPluginTest.groovy
@@ -25,12 +25,12 @@ import org.gradle.api.publish.maven.MavenPublication
import org.gradle.api.publish.maven.internal.publication.DefaultMavenPublication
import org.gradle.api.publish.maven.tasks.PublishToMavenLocal
import org.gradle.api.publish.maven.tasks.PublishToMavenRepository
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import spock.lang.Specification
class MavenPublishPluginTest extends Specification {
- def project = HelperUtil.createRootProject()
+ def project = TestUtil.createRootProject()
PublishingExtension publishing
def componentArtifacts = Mock(FileCollection)
def component = Stub(SoftwareComponentInternal)
@@ -55,7 +55,7 @@ class MavenPublishPluginTest extends Specification {
def "publication can be added"() {
when:
- publishing.publications.add("test", MavenPublication)
+ publishing.publications.create("test", MavenPublication)
then:
publishing.publications.size() == 1
@@ -64,7 +64,7 @@ class MavenPublishPluginTest extends Specification {
def "creates publish tasks for publication and repository"() {
when:
- publishing.publications.add("test", MavenPublication)
+ publishing.publications.create("test", MavenPublication)
publishing.repositories { maven { url = "http://foo.com" } }
then:
@@ -75,7 +75,7 @@ class MavenPublishPluginTest extends Specification {
def "task is created for publishing to mavenLocal"() {
given:
- publishing.publications.add("test", MavenPublication)
+ publishing.publications.create("test", MavenPublication)
expect:
publishLocalTasks.size() == 1
@@ -86,7 +86,7 @@ class MavenPublishPluginTest extends Specification {
def "can explicitly add mavenLocal as a publishing repository"() {
given:
- publishing.publications.add("test", MavenPublication)
+ publishing.publications.create("test", MavenPublication)
when:
def mavenLocal = publishing.repositories.mavenLocal()
@@ -101,7 +101,7 @@ class MavenPublishPluginTest extends Specification {
def "tasks are created for compatible publication / repo"() {
given:
- publishing.publications.add("test", MavenPublication)
+ publishing.publications.create("test", MavenPublication)
expect:
publishTasks.size() == 0
@@ -145,7 +145,7 @@ class MavenPublishPluginTest extends Specification {
project.version = "version"
and:
- publishing.publications.add("test", MavenPublication)
+ publishing.publications.create("test", MavenPublication)
then:
with(publishing.publications.test.mavenProjectIdentity) {
@@ -166,7 +166,7 @@ class MavenPublishPluginTest extends Specification {
def "pom dir moves with build dir"() {
when:
- publishing.publications.add("test", MavenPublication)
+ publishing.publications.create("test", MavenPublication)
then:
project.tasks["generatePomFileForTestPublication"].destination == new File(project.buildDir, "publications/test/pom-default.xml")
diff --git a/subprojects/maven/src/test/groovy/org/gradle/api/publish/maven/tasks/PublishToMavenRepositoryTest.groovy b/subprojects/maven/src/test/groovy/org/gradle/api/publish/maven/tasks/PublishToMavenRepositoryTest.groovy
index 0167cfb..b673d71 100644
--- a/subprojects/maven/src/test/groovy/org/gradle/api/publish/maven/tasks/PublishToMavenRepositoryTest.groovy
+++ b/subprojects/maven/src/test/groovy/org/gradle/api/publish/maven/tasks/PublishToMavenRepositoryTest.groovy
@@ -16,16 +16,16 @@
package org.gradle.api.publish.maven.tasks
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import spock.lang.Specification
class PublishToMavenRepositoryTest extends Specification {
- def project = HelperUtil.createRootProject()
+ def project = TestUtil.createRootProject()
def "can instantiate"() {
when:
- project.tasks.add("task", PublishToMavenRepository)
+ project.tasks.create("task", PublishToMavenRepository)
then:
true
diff --git a/subprojects/messaging/messaging.gradle b/subprojects/messaging/messaging.gradle
index 48123b4..6e40f2e 100644
--- a/subprojects/messaging/messaging.gradle
+++ b/subprojects/messaging/messaging.gradle
@@ -1,9 +1,9 @@
dependencies {
- groovy libraries.groovy
publishCompile project(':baseServices')
publishCompile libraries.slf4j_api
publishCompile libraries.guava
publishCompile 'com.esotericsoftware.kryo:kryo:2.20'
+ testCompile libraries.groovy
}
useTestFixtures()
diff --git a/subprojects/messaging/src/main/java/org/gradle/messaging/serialize/AbstractDecoder.java b/subprojects/messaging/src/main/java/org/gradle/messaging/serialize/AbstractDecoder.java
new file mode 100644
index 0000000..1afd5fd
--- /dev/null
+++ b/subprojects/messaging/src/main/java/org/gradle/messaging/serialize/AbstractDecoder.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.messaging.serialize;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+public abstract class AbstractDecoder implements Decoder {
+ private DecoderStream stream;
+
+ public InputStream getInputStream() {
+ if (stream == null) {
+ stream = new DecoderStream();
+ }
+ return stream;
+ }
+
+ public void readBytes(byte[] buffer) throws IOException {
+ readBytes(buffer, 0, buffer.length);
+ }
+
+ protected abstract int maybeReadBytes(byte[] buffer, int offset, int count) throws IOException;
+
+ private class DecoderStream extends InputStream {
+ byte[] buffer = new byte[1];
+
+ @Override
+ public int read() throws IOException {
+ int read = maybeReadBytes(buffer, 0, 1);
+ if (read <= 0) {
+ return read;
+ }
+ return buffer[0] & 0xff;
+ }
+
+ @Override
+ public int read(byte[] buffer) throws IOException {
+ return maybeReadBytes(buffer, 0, buffer.length);
+ }
+
+ @Override
+ public int read(byte[] buffer, int offset, int count) throws IOException {
+ return maybeReadBytes(buffer, offset, count);
+ }
+ }
+}
diff --git a/subprojects/messaging/src/main/java/org/gradle/messaging/serialize/AbstractEncoder.java b/subprojects/messaging/src/main/java/org/gradle/messaging/serialize/AbstractEncoder.java
new file mode 100644
index 0000000..a3bb3db
--- /dev/null
+++ b/subprojects/messaging/src/main/java/org/gradle/messaging/serialize/AbstractEncoder.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.messaging.serialize;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+public abstract class AbstractEncoder implements Encoder {
+ private EncoderStream stream;
+
+ public OutputStream getOutputStream() {
+ if (stream == null) {
+ stream = new EncoderStream();
+ }
+ return stream;
+ }
+
+ public void writeBytes(byte[] bytes) throws IOException {
+ writeBytes(bytes, 0, bytes.length);
+ }
+
+ public void writeBinary(byte[] bytes) throws IOException {
+ writeBinary(bytes, 0, bytes.length);
+ }
+
+ private class EncoderStream extends OutputStream {
+ @Override
+ public void write(byte[] buffer) throws IOException {
+ writeBytes(buffer);
+ }
+
+ @Override
+ public void write(byte[] buffer, int offset, int length) throws IOException {
+ writeBytes(buffer, offset, length);
+ }
+
+ @Override
+ public void write(int b) throws IOException {
+ writeByte((byte)b);
+ }
+ }
+}
diff --git a/subprojects/messaging/src/main/java/org/gradle/messaging/serialize/DataStreamBackedSerializer.java b/subprojects/messaging/src/main/java/org/gradle/messaging/serialize/DataStreamBackedSerializer.java
deleted file mode 100644
index 9b40ce6..0000000
--- a/subprojects/messaging/src/main/java/org/gradle/messaging/serialize/DataStreamBackedSerializer.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.messaging.serialize;
-
-import java.io.*;
-
-public abstract class DataStreamBackedSerializer<T> implements Serializer<T> {
- public T read(InputStream instr) throws Exception {
- DataInputStream dataInputStream = new DataInputStream(instr);
- return read((DataInput) dataInputStream);
- }
-
- public void write(OutputStream outstr, T value) throws Exception {
- DataOutputStream output = new DataOutputStream(outstr);
- write((DataOutput) output, value);
- output.flush();
- }
-
- public abstract T read(DataInput dataInput) throws Exception;
-
- public abstract void write(DataOutput dataOutput, T value) throws IOException;
-}
diff --git a/subprojects/messaging/src/main/java/org/gradle/messaging/serialize/Decoder.java b/subprojects/messaging/src/main/java/org/gradle/messaging/serialize/Decoder.java
new file mode 100644
index 0000000..6b4d3ac
--- /dev/null
+++ b/subprojects/messaging/src/main/java/org/gradle/messaging/serialize/Decoder.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.messaging.serialize;
+
+import org.gradle.api.Nullable;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Provides a way to decode structured data from a backing byte stream.
+ */
+public interface Decoder {
+ /**
+ * Returns an InputStream which can be used to read raw bytes.
+ */
+ InputStream getInputStream();
+
+ /**
+ * Reads a signed 64 bit long value. Can read any value that was written using {@link Encoder#writeLong(long)}.
+ *
+ * @throws EOFException when the end of the byte stream is reached before the long value can be fully read.
+ */
+ long readLong() throws EOFException, IOException;
+
+ /**
+ * Reads a signed 32 bit int value. Can read any value that was written using {@link Encoder#writeInt(int)}.
+ *
+ * @throws EOFException when the end of the byte stream is reached before the int value can be fully read.
+ */
+ int readInt() throws EOFException, IOException;
+
+ /**
+ * Reads a signed 32 bit int value. Can read any value that was written using {@link Encoder#writeSizeInt(int)}.
+ *
+ * @throws EOFException when the end of the byte stream is reached before the int value can be fully read.
+ */
+ int readSizeInt() throws EOFException, IOException;
+
+ /**
+ * Reads a boolean value. Can read any value that was written using {@link Encoder#writeBoolean(boolean)}.
+ *
+ * @throws EOFException when the end of the byte stream is reached before the boolean value can be fully read.
+ */
+ boolean readBoolean() throws EOFException, IOException;
+
+ /**
+ * Reads a non-null string value. Can read any value that was written using {@link Encoder#writeString(CharSequence)}.
+ *
+ * @throws EOFException when the end of the byte stream is reached before the string can be fully read.
+ */
+ String readString() throws EOFException, IOException;
+
+ /**
+ * Reads a nullable string value. Can reads any value that was written using {@link Encoder#writeNullableString(CharSequence)}.
+ *
+ * @throws EOFException when the end of the byte stream is reached before the string can be fully read.
+ */
+ @Nullable
+ String readNullableString() throws EOFException, IOException;
+
+ /**
+ * Reads a byte value. Can read any byte value that was written using one of the raw byte methods on {@link Encoder}, such as {@link Encoder#writeByte(byte)} or {@link Encoder#getOutputStream()}
+ *
+ * @throws EOFException when the end of the byte stream is reached.
+ */
+ byte readByte() throws EOFException, IOException;
+
+ /**
+ * Reads bytes into the given buffer, filling the buffer. Can read any byte values that were written using one of the raw byte methods on {@link Encoder}, such as {@link
+ * Encoder#writeBytes(byte[])} or {@link Encoder#getOutputStream()}
+ *
+ * @throws EOFException when the end of the byte stream is reached before the buffer is full.
+ */
+ void readBytes(byte[] buffer) throws EOFException, IOException;
+
+ /**
+ * Reads the specified number of bytes into the given buffer. Can read any byte values that were written using one of the raw byte methods on {@link Encoder}, such as {@link
+ * Encoder#writeBytes(byte[])} or {@link Encoder#getOutputStream()}
+ *
+ * @throws EOFException when the end of the byte stream is reached before the specified number of bytes were read.
+ */
+ void readBytes(byte[] buffer, int offset, int count) throws EOFException, IOException;
+
+ /**
+ * Reads a byte array. Can read any byte array written using {@link Encoder#writeBinary(byte[])} or {@link Encoder#writeBinary(byte[], int, int)}.
+ *
+ * @throws EOFException when the end of the byte stream is reached before the byte array was fully read.
+ */
+ byte[] readBinary() throws EOFException, IOException;
+}
diff --git a/subprojects/messaging/src/main/java/org/gradle/messaging/serialize/DefaultSerializer.java b/subprojects/messaging/src/main/java/org/gradle/messaging/serialize/DefaultSerializer.java
index cf9a115..2a3c7ef 100644
--- a/subprojects/messaging/src/main/java/org/gradle/messaging/serialize/DefaultSerializer.java
+++ b/subprojects/messaging/src/main/java/org/gradle/messaging/serialize/DefaultSerializer.java
@@ -17,7 +17,9 @@ package org.gradle.messaging.serialize;
import org.gradle.internal.io.ClassLoaderObjectInputStream;
-import java.io.*;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.io.StreamCorruptedException;
public class DefaultSerializer<T> implements Serializer<T> {
private ClassLoader classLoader;
@@ -38,16 +40,16 @@ public class DefaultSerializer<T> implements Serializer<T> {
this.classLoader = classLoader;
}
- public T read(InputStream instr) throws Exception {
+ public T read(Decoder decoder) throws Exception {
try {
- return (T) new ClassLoaderObjectInputStream(instr, classLoader).readObject();
+ return (T) new ClassLoaderObjectInputStream(decoder.getInputStream(), classLoader).readObject();
} catch (StreamCorruptedException e) {
return null;
}
}
- public void write(OutputStream outstr, T value) throws IOException {
- ObjectOutputStream objectStr = new ObjectOutputStream(outstr);
+ public void write(Encoder encoder, T value) throws IOException {
+ ObjectOutputStream objectStr = new ObjectOutputStream(encoder.getOutputStream());
objectStr.writeObject(value);
objectStr.flush();
}
diff --git a/subprojects/messaging/src/main/java/org/gradle/messaging/serialize/Encoder.java b/subprojects/messaging/src/main/java/org/gradle/messaging/serialize/Encoder.java
new file mode 100644
index 0000000..de288ac
--- /dev/null
+++ b/subprojects/messaging/src/main/java/org/gradle/messaging/serialize/Encoder.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.messaging.serialize;
+
+import org.gradle.api.Nullable;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+public interface Encoder {
+ /**
+ * Returns an OutputStream that can be used to write byte content to the stream.
+ */
+ OutputStream getOutputStream();
+
+ /**
+ * Writes a byte value to the stream.
+ */
+ void writeByte(byte value) throws IOException;
+
+ /**
+ * Writes the given bytes to the stream. Does not encode any length information.
+ */
+ void writeBytes(byte[] bytes) throws IOException;
+
+ /**
+ * Writes the given bytes to the stream. Does not encode any length information.
+ */
+ void writeBytes(byte[] bytes, int offset, int count) throws IOException;
+
+ /**
+ * Writes the given byte array to the stream. Encodes the bytes and some length information.
+ */
+ void writeBinary(byte[] bytes) throws IOException;
+
+ /**
+ * Writes the given byte array to the stream. Encodes the bytes and some length information.
+ */
+ void writeBinary(byte[] bytes, int offset, int count) throws IOException;
+
+ /**
+ * Writes a signed 64 bit long value. The implementation may encode the value as a variable number of bytes, not necessarily as 8 bytes.
+ */
+ void writeLong(long value) throws IOException;
+
+ /**
+ * Writes a signed 32 bit int value. The implementation may encode the value as a variable number of bytes, not necessarily as 4 bytes.
+ */
+ void writeInt(int value) throws IOException;
+
+ /**
+ * Writes a signed 32 bit int value whose value is likely to be small and positive but may not be. The implementation may encode the value as a variable number of bytes, not necessarily as 4
+ * bytes.
+ */
+ void writeSizeInt(int value) throws IOException;
+
+ /**
+ * Writes a boolean value.
+ */
+ void writeBoolean(boolean value) throws IOException;
+
+ /**
+ * Writes a non-null string value.
+ */
+ void writeString(CharSequence value) throws IOException;
+
+ /**
+ * Writes a nullable string value.
+ */
+ void writeNullableString(@Nullable CharSequence value) throws IOException;
+}
diff --git a/subprojects/messaging/src/main/java/org/gradle/messaging/serialize/FlushableEncoder.java b/subprojects/messaging/src/main/java/org/gradle/messaging/serialize/FlushableEncoder.java
new file mode 100644
index 0000000..ce0e7a7
--- /dev/null
+++ b/subprojects/messaging/src/main/java/org/gradle/messaging/serialize/FlushableEncoder.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.messaging.serialize;
+
+import java.io.Flushable;
+import java.io.IOException;
+
+public interface FlushableEncoder extends Encoder, Flushable {
+ void flush() throws IOException;
+}
diff --git a/subprojects/messaging/src/main/java/org/gradle/messaging/serialize/InputStreamBackedDecoder.java b/subprojects/messaging/src/main/java/org/gradle/messaging/serialize/InputStreamBackedDecoder.java
new file mode 100644
index 0000000..a8d0e35
--- /dev/null
+++ b/subprojects/messaging/src/main/java/org/gradle/messaging/serialize/InputStreamBackedDecoder.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.messaging.serialize;
+
+import java.io.*;
+
+public class InputStreamBackedDecoder extends AbstractDecoder implements Decoder, Closeable {
+ private final DataInputStream inputStream;
+
+ public InputStreamBackedDecoder(InputStream inputStream) {
+ this.inputStream = new DataInputStream(inputStream);
+ }
+
+ @Override
+ protected int maybeReadBytes(byte[] buffer, int offset, int count) throws IOException {
+ return inputStream.read(buffer, offset, count);
+ }
+
+ public long readLong() throws IOException {
+ return inputStream.readLong();
+ }
+
+ public int readInt() throws EOFException, IOException {
+ return inputStream.readInt();
+ }
+
+ public int readSizeInt() throws EOFException, IOException {
+ return inputStream.readInt();
+ }
+
+ public boolean readBoolean() throws EOFException, IOException {
+ return inputStream.readBoolean();
+ }
+
+ public String readString() throws EOFException, IOException {
+ return inputStream.readUTF();
+ }
+
+ public String readNullableString() throws EOFException, IOException {
+ if (inputStream.readBoolean()) {
+ return inputStream.readUTF();
+ } else {
+ return null;
+ }
+ }
+
+ public byte[] readBinary() throws IOException {
+ int length = inputStream.readInt();
+ byte[] result = new byte[length];
+ inputStream.readFully(result);
+ return result;
+ }
+
+ public byte readByte() throws IOException {
+ return (byte)(inputStream.readByte() & 0xff);
+ }
+
+ public void readBytes(byte[] buffer, int offset, int count) throws IOException {
+ inputStream.readFully(buffer, offset, count);
+ }
+
+ public void close() throws IOException {
+ inputStream.close();
+ }
+}
diff --git a/subprojects/messaging/src/main/java/org/gradle/messaging/serialize/LongSerializer.java b/subprojects/messaging/src/main/java/org/gradle/messaging/serialize/LongSerializer.java
new file mode 100644
index 0000000..48a8a1d
--- /dev/null
+++ b/subprojects/messaging/src/main/java/org/gradle/messaging/serialize/LongSerializer.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.messaging.serialize;
+
+public class LongSerializer implements Serializer<Long> {
+ public Long read(Decoder decoder) throws Exception {
+ return decoder.readLong();
+ }
+
+ public void write(Encoder encoder, Long value) throws Exception {
+ if (value == null) {
+ throw new IllegalArgumentException("This serializer does not serialize null values.");
+ }
+ encoder.writeLong(value);
+ }
+}
diff --git a/subprojects/messaging/src/main/java/org/gradle/messaging/serialize/OutputStreamBackedEncoder.java b/subprojects/messaging/src/main/java/org/gradle/messaging/serialize/OutputStreamBackedEncoder.java
new file mode 100644
index 0000000..5982861
--- /dev/null
+++ b/subprojects/messaging/src/main/java/org/gradle/messaging/serialize/OutputStreamBackedEncoder.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.messaging.serialize;
+
+import org.gradle.api.Nullable;
+
+import java.io.Closeable;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class OutputStreamBackedEncoder extends AbstractEncoder implements Closeable, FlushableEncoder {
+ private final DataOutputStream outputStream;
+
+ public OutputStreamBackedEncoder(OutputStream outputStream) {
+ this.outputStream = new DataOutputStream(outputStream);
+ }
+
+ public void writeLong(long value) throws IOException {
+ outputStream.writeLong(value);
+ }
+
+ public void writeInt(int value) throws IOException {
+ outputStream.writeInt(value);
+ }
+
+ public void writeSizeInt(int value) throws IOException {
+ outputStream.writeInt(value);
+ }
+
+ public void writeBoolean(boolean value) throws IOException {
+ outputStream.writeBoolean(value);
+ }
+
+ public void writeString(CharSequence value) throws IOException {
+ if (value == null) {
+ throw new IllegalArgumentException("Cannot encode a null string.");
+ }
+ outputStream.writeUTF(value.toString());
+ }
+
+ public void writeNullableString(@Nullable CharSequence value) throws IOException {
+ if (value == null) {
+ outputStream.writeBoolean(false);
+ } else {
+ outputStream.writeBoolean(true);
+ outputStream.writeUTF(value.toString());
+ }
+ }
+
+ public void writeBinary(byte[] bytes, int offset, int count) throws IOException {
+ outputStream.writeInt(count);
+ outputStream.write(bytes, offset, count);
+ }
+
+ public void writeByte(byte value) throws IOException {
+ outputStream.writeByte(value);
+ }
+
+ public void writeBytes(byte[] bytes, int offset, int count) throws IOException {
+ outputStream.write(bytes, offset, count);
+ }
+
+ public void flush() throws IOException {
+ outputStream.flush();
+ }
+
+ public void close() throws IOException {
+ outputStream.close();
+ }
+}
diff --git a/subprojects/messaging/src/main/java/org/gradle/messaging/serialize/Serializer.java b/subprojects/messaging/src/main/java/org/gradle/messaging/serialize/Serializer.java
index 9388801..9dbf770 100644
--- a/subprojects/messaging/src/main/java/org/gradle/messaging/serialize/Serializer.java
+++ b/subprojects/messaging/src/main/java/org/gradle/messaging/serialize/Serializer.java
@@ -15,18 +15,15 @@
*/
package org.gradle.messaging.serialize;
-import java.io.InputStream;
-import java.io.OutputStream;
-
public interface Serializer<T> {
/**
* Reads the next object from the given stream. The implementation must not perform any buffering, so that it reads only those bytes from the input stream that are
* required to deserialize the next object.
*/
- T read(InputStream instr) throws Exception;
+ T read(Decoder decoder) throws Exception;
/**
* Writes the given object to the given stream. The implementation must not perform any buffering.
*/
- void write(OutputStream outstr, T value) throws Exception;
+ void write(Encoder encoder, T value) throws Exception;
}
diff --git a/subprojects/messaging/src/main/java/org/gradle/messaging/serialize/kryo/KryoBackedDecoder.java b/subprojects/messaging/src/main/java/org/gradle/messaging/serialize/kryo/KryoBackedDecoder.java
new file mode 100644
index 0000000..ca95d0a
--- /dev/null
+++ b/subprojects/messaging/src/main/java/org/gradle/messaging/serialize/kryo/KryoBackedDecoder.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.messaging.serialize.kryo;
+
+import com.esotericsoftware.kryo.KryoException;
+import com.esotericsoftware.kryo.io.Input;
+import org.gradle.messaging.serialize.AbstractDecoder;
+import org.gradle.messaging.serialize.Decoder;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+
+public class KryoBackedDecoder extends AbstractDecoder implements Decoder {
+ private final Input input;
+
+ /**
+ * Note that this decoder uses buffering, so will attempt to read beyond the end of the encoded data. This means you should use this type only when this decoder will be used to decode the entire
+ * stream.
+ */
+ public KryoBackedDecoder(InputStream inputStream) {
+ input = new Input(inputStream);
+ }
+
+ @Override
+ protected int maybeReadBytes(byte[] buffer, int offset, int count) {
+ return input.read(buffer, offset, count);
+ }
+
+ private RuntimeException maybeEndOfStream(KryoException e) throws EOFException {
+ if (e.getMessage().equals("Buffer underflow.")) {
+ throw (EOFException) (new EOFException().initCause(e));
+ }
+ throw e;
+ }
+
+ public byte readByte() throws EOFException {
+ try {
+ return input.readByte();
+ } catch (KryoException e) {
+ throw maybeEndOfStream(e);
+ }
+ }
+
+ public void readBytes(byte[] buffer, int offset, int count) throws EOFException {
+ try {
+ input.readBytes(buffer, offset, count);
+ } catch (KryoException e) {
+ throw maybeEndOfStream(e);
+ }
+ }
+
+ public long readLong() throws EOFException {
+ try {
+ return input.readLong();
+ } catch (KryoException e) {
+ throw maybeEndOfStream(e);
+ }
+ }
+
+ public int readInt() throws EOFException {
+ try {
+ return input.readInt();
+ } catch (KryoException e) {
+ throw maybeEndOfStream(e);
+ }
+ }
+
+ public int readSizeInt() throws EOFException {
+ try {
+ return input.readInt(true);
+ } catch (KryoException e) {
+ throw maybeEndOfStream(e);
+ }
+ }
+
+ public boolean readBoolean() throws EOFException {
+ try {
+ return input.readBoolean();
+ } catch (KryoException e) {
+ throw maybeEndOfStream(e);
+ }
+ }
+
+ public String readString() throws EOFException {
+ return readNullableString();
+ }
+
+ public String readNullableString() throws EOFException {
+ try {
+ return input.readString();
+ } catch (KryoException e) {
+ throw maybeEndOfStream(e);
+ }
+ }
+
+ public byte[] readBinary() throws IOException {
+ try {
+ int length = input.readInt(true);
+ byte[] result = new byte[length];
+ input.readBytes(result);
+ return result;
+ } catch (KryoException e) {
+ throw maybeEndOfStream(e);
+ }
+ }
+}
diff --git a/subprojects/messaging/src/main/java/org/gradle/messaging/serialize/kryo/KryoBackedEncoder.java b/subprojects/messaging/src/main/java/org/gradle/messaging/serialize/kryo/KryoBackedEncoder.java
new file mode 100644
index 0000000..c9d6bab
--- /dev/null
+++ b/subprojects/messaging/src/main/java/org/gradle/messaging/serialize/kryo/KryoBackedEncoder.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.messaging.serialize.kryo;
+
+import com.esotericsoftware.kryo.io.Output;
+import org.gradle.api.Nullable;
+import org.gradle.messaging.serialize.AbstractEncoder;
+import org.gradle.messaging.serialize.Encoder;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class KryoBackedEncoder extends AbstractEncoder implements Encoder {
+ private final Output output;
+
+ public KryoBackedEncoder(OutputStream outputStream) {
+ output = new Output(outputStream);
+ }
+
+ public void writeByte(byte value) {
+ output.writeByte(value);
+ }
+
+ public void writeBytes(byte[] bytes, int offset, int count) {
+ output.writeBytes(bytes, offset, count);
+ }
+
+ public void writeLong(long value) {
+ output.writeLong(value);
+ }
+
+ public void writeInt(int value) throws IOException {
+ output.writeInt(value);
+ }
+
+ public void writeSizeInt(int value) throws IOException {
+ output.writeInt(value, true);
+ }
+
+ public void writeBoolean(boolean value) throws IOException {
+ output.writeBoolean(value);
+ }
+
+ public void writeString(CharSequence value) {
+ if (value == null) {
+ throw new IllegalArgumentException("Cannot encode a null string.");
+ }
+ output.writeString(value);
+ }
+
+ public void writeNullableString(@Nullable CharSequence value) {
+ output.writeString(value);
+ }
+
+ public void writeBinary(byte[] bytes, int offset, int count) throws IOException {
+ output.writeInt(count, true);
+ output.writeBytes(bytes, offset, count);
+ }
+
+ public void flush() {
+ output.flush();
+ }
+}
diff --git a/subprojects/messaging/src/test/groovy/org/gradle/messaging/serialize/AbstractCodecTest.groovy b/subprojects/messaging/src/test/groovy/org/gradle/messaging/serialize/AbstractCodecTest.groovy
new file mode 100644
index 0000000..e9cae47
--- /dev/null
+++ b/subprojects/messaging/src/test/groovy/org/gradle/messaging/serialize/AbstractCodecTest.groovy
@@ -0,0 +1,387 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.messaging.serialize
+
+import spock.lang.Specification
+
+abstract class AbstractCodecTest extends Specification {
+ def "can encode and decode raw bytes using Stream view"() {
+ expect:
+ def bytes = encode { Encoder encoder ->
+ encoder.outputStream.write(Byte.MIN_VALUE)
+ encoder.outputStream.write(Byte.MAX_VALUE)
+ encoder.outputStream.write(-1)
+ encoder.outputStream.write([1, 2, 3, 4] as byte[])
+ encoder.outputStream.write([0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7] as byte[], 2, 4)
+ }
+ decode(bytes) { Decoder decoder ->
+ def buffer = new byte[3]
+ assert decoder.inputStream.read(buffer) == 3
+ assert buffer == [Byte.MIN_VALUE, Byte.MAX_VALUE, -1] as byte[]
+ assert decoder.inputStream.read(buffer, 1, 2) == 2
+ assert buffer[1] == 1
+ assert buffer[2] == 2
+ assert decoder.inputStream.read() == 3
+ assert decoder.inputStream.read() == 4
+ assert decoder.inputStream.read() == 0xc3
+ def content = decoder.inputStream.bytes
+ assert content == [0xc4, 0xc5, 0xc6] as byte[]
+
+ assert decoder.inputStream.read() == -1
+ assert decoder.inputStream.read(buffer) == -1
+ assert decoder.inputStream.read(buffer, 0, 1) == -1
+ }
+ }
+
+ def "ignores close on InputStream"() {
+ def inputStream = Mock(InputStream)
+
+ when:
+ decodeFrom(inputStream) { Decoder decoder ->
+ decoder.inputStream.close()
+ }
+
+ then:
+ 0 * inputStream.close()
+ }
+
+ def "ignores close or flush on OutputStream"() {
+ def outputStream = Mock(OutputStream)
+
+ when:
+ encodeTo(outputStream) { Encoder encoder ->
+ encoder.outputStream.flush()
+ encoder.outputStream.close()
+ }
+
+ then:
+ 0 * outputStream.close()
+ 0 * outputStream.flush()
+ }
+
+ def "can encode and decode raw bytes"() {
+ expect:
+ def bytes = encode { Encoder encoder ->
+ encoder.writeByte(Byte.MIN_VALUE)
+ encoder.writeByte(Byte.MAX_VALUE)
+ encoder.writeByte(-1 as byte)
+ encoder.writeBytes([1, 2, 3, 4] as byte[])
+ encoder.writeBytes([0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7] as byte[], 2, 1)
+ }
+ decode(bytes) { Decoder decoder ->
+ def buffer = new byte[2]
+ decoder.readBytes(buffer)
+ assert buffer == [Byte.MIN_VALUE, Byte.MAX_VALUE] as byte[]
+ assert decoder.readByte() == -1 as byte
+ decoder.readBytes(buffer, 0, 2)
+ assert buffer[0] == 1
+ assert buffer[1] == 2
+ assert decoder.readByte() == 3
+ assert decoder.readByte() == 4
+ assert decoder.readByte() == 0xc3 as byte
+ }
+ }
+
+ def "decode fails when requested number of raw bytes are not available"() {
+ given:
+ def bytes = encode { Encoder encoder ->
+ encoder.writeBytes([0xc1, 0xc2, 0xc3] as byte[])
+ }
+
+ when:
+ decode(bytes) { Decoder decoder ->
+ decoder.readBytes(new byte[4])
+ }
+
+ then:
+ thrown(EOFException)
+
+ when:
+ decode(bytes) { Decoder decoder ->
+ decoder.readBytes(new byte[10], 0, 5)
+ }
+
+ then:
+ thrown(EOFException)
+
+ when:
+ decode(bytes) { Decoder decoder ->
+ decoder.readBytes(new byte[3], 0, 3)
+ decoder.readByte()
+ }
+
+ then:
+ thrown(EOFException)
+ }
+
+ def "can encode and decode byte array"() {
+ expect:
+ def bytes = encode { Encoder encoder ->
+ encoder.writeBinary([] as byte[])
+ encoder.writeBinary([1, 2, 3, 4] as byte[])
+ encoder.writeBinary([0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7] as byte[], 2, 3)
+ }
+ decode(bytes) { Decoder decoder ->
+ assert decoder.readBinary() == [] as byte[]
+ assert decoder.readBinary() == [1, 2, 3, 4] as byte[]
+ assert decoder.readBinary() == [0xc3, 0xc4, 0xc5] as byte[]
+ }
+ }
+
+ def "decode fails when byte array cannot be fully read"() {
+ given:
+ def bytes = truncate { Encoder encoder ->
+ encoder.writeBinary([1, 2, 3, 4] as byte[])
+ }
+
+ when:
+ decode(bytes) { Decoder decoder ->
+ decoder.readBinary()
+ }
+
+ then:
+ thrown(EOFException)
+
+ when:
+ decode([] as byte[]) { Decoder decoder ->
+ decoder.readBinary()
+ }
+
+ then:
+ thrown(EOFException)
+ }
+
+ def "can encode and decode a long"() {
+ expect:
+ def bytes = encode { Encoder encoder ->
+ encoder.writeLong(value)
+ }
+ decode(bytes) { Decoder decoder ->
+ assert decoder.readLong() == value
+ }
+
+ where:
+ value | _
+ 0 | _
+ 12 | _
+ -1 | _
+ Long.MAX_VALUE | _
+ Long.MIN_VALUE | _
+ }
+
+ def "decode fails when long cannot be fully read"() {
+ given:
+ def bytes = truncate { Encoder encoder ->
+ encoder.writeLong(0xa40745f3L)
+ }
+
+ when:
+ decode(bytes) { Decoder decoder ->
+ decoder.readLong()
+ }
+
+ then:
+ thrown(EOFException)
+ }
+
+ def "can encode and decode an int"() {
+ expect:
+ def bytes = encode { Encoder encoder ->
+ encoder.writeInt(value as int)
+ }
+ decode(bytes) { Decoder decoder ->
+ assert decoder.readInt() == value
+ }
+
+ where:
+ value | _
+ 0 | _
+ 12 | _
+ -1 | _
+ Integer.MAX_VALUE | _
+ Integer.MIN_VALUE | _
+ }
+
+ def "decode fails when int cannot be fully read"() {
+ given:
+ def bytes = truncate { Encoder encoder ->
+ encoder.writeInt(0xa40745f)
+ }
+
+ when:
+ decode(bytes) { Decoder decoder ->
+ decoder.readInt()
+ }
+
+ then:
+ thrown(EOFException)
+ }
+
+ def "can encode and decode a size int"() {
+ expect:
+ def bytesA = encode { Encoder encoder ->
+ encoder.writeSizeInt(a as int)
+ }
+ def bytesB = encode { Encoder encoder ->
+ encoder.writeSizeInt(b as int)
+ }
+ decode(bytesA) { Decoder decoder ->
+ assert decoder.readSizeInt() == a
+ }
+ decode(bytesB) { Decoder decoder ->
+ assert decoder.readSizeInt() == b
+ }
+ bytesA.length <= bytesB.length
+
+ where:
+ a | b
+ 0 | 0x1ff
+ 0x2ff | 0x1000
+ 0x1000 | -1
+ Integer.MAX_VALUE | -1
+ Integer.MAX_VALUE | -0xc3412
+ Integer.MAX_VALUE | Integer.MIN_VALUE
+ }
+
+ def "decode fails when size int cannot be fully read"() {
+ given:
+ def bytes = truncate { Encoder encoder ->
+ encoder.writeSizeInt(0xa40745f)
+ }
+
+ when:
+ decode(bytes) { Decoder decoder ->
+ decoder.readSizeInt()
+ }
+
+ then:
+ thrown(EOFException)
+ }
+
+ def "can encode and decode a boolean"() {
+ expect:
+ def bytes = encode { Encoder encoder ->
+ encoder.writeBoolean(true)
+ encoder.writeBoolean(false)
+ }
+ decode(bytes) { Decoder decoder ->
+ assert decoder.readBoolean()
+ assert !decoder.readBoolean()
+ }
+ }
+
+ def "decode fails when boolean cannot be fully read"() {
+ given:
+ def bytes = truncate { Encoder encoder ->
+ encoder.writeBoolean(true)
+ }
+
+ when:
+ decode(bytes) { Decoder decoder ->
+ decoder.readBoolean()
+ }
+
+ then:
+ thrown(EOFException)
+ }
+
+ def "can encode and decode a string"() {
+ expect:
+ def bytes = encode { Encoder encoder ->
+ encoder.writeString(value)
+ }
+ decode(bytes) { Decoder decoder ->
+ assert decoder.readString() == value.toString()
+ }
+
+ where:
+ value | _
+ "" | _
+ "all ascii" | _
+ "\u0000\u0101\u3100" | _
+ "${1 + 2}" | _
+ new StringBuilder("some string") | _
+ }
+
+ def "decode fails when string cannot be fully read"() {
+ given:
+ def bytes = truncate { Encoder encoder ->
+ encoder.writeString("hi")
+ }
+
+ when:
+ decode(bytes) { Decoder decoder ->
+ decoder.readString()
+ }
+
+ then:
+ thrown(EOFException)
+ }
+
+ def "cannot encode a null string"() {
+ when:
+ encode { Encoder encoder ->
+ encoder.writeString(null)
+ }
+
+ then:
+ thrown(IllegalArgumentException)
+ }
+
+ def "can encode and decode a nullable string"() {
+ expect:
+ def bytes = encode { Encoder encoder ->
+ encoder.writeNullableString(value)
+ }
+ decode(bytes) { Decoder decoder ->
+ assert decoder.readNullableString() == value?.toString()
+ }
+
+ where:
+ value | _
+ null | _
+ "" | _
+ "all ascii" | _
+ "\u0000\u0101\u3100" | _
+ "${1 + 2}" | _
+ new StringBuilder("some string") | _
+ }
+
+ abstract void encodeTo(OutputStream outputStream, Closure<Encoder> closure)
+
+ byte[] encode(Closure<Encoder> closure) {
+ def bytes = new ByteArrayOutputStream()
+ encodeTo(bytes, closure)
+ return bytes.toByteArray()
+ }
+
+ byte[] truncate(Closure<Encoder> closure) {
+ def bytes = new ByteArrayOutputStream()
+ encodeTo(bytes, closure)
+ def result = bytes.toByteArray()
+ if (result.length < 2) {
+ return [] as byte[]
+ }
+ return result[0..result.length - 2] as byte[]
+ }
+
+ abstract void decodeFrom(InputStream inputStream, Closure<Decoder> closure)
+
+ void decode(byte[] bytes, Closure<Decoder> closure) {
+ decodeFrom(new ByteArrayInputStream(bytes), closure)
+ }
+}
diff --git a/subprojects/messaging/src/test/groovy/org/gradle/messaging/serialize/DefaultSerializerTest.groovy b/subprojects/messaging/src/test/groovy/org/gradle/messaging/serialize/DefaultSerializerTest.groovy
index 5215f06..69eee88 100644
--- a/subprojects/messaging/src/test/groovy/org/gradle/messaging/serialize/DefaultSerializerTest.groovy
+++ b/subprojects/messaging/src/test/groovy/org/gradle/messaging/serialize/DefaultSerializerTest.groovy
@@ -15,9 +15,7 @@
*/
package org.gradle.messaging.serialize
-import spock.lang.Specification
-
-class DefaultSerializerTest extends Specification {
+class DefaultSerializerTest extends SerializerSpec {
def canSerializeAndDeserializeObject() {
GroovyClassLoader classLoader = new GroovyClassLoader(getClass().classLoader)
DefaultSerializer serializer = new DefaultSerializer(classLoader)
@@ -26,9 +24,7 @@ class DefaultSerializerTest extends Specification {
Object o = cl.newInstance()
when:
- ByteArrayOutputStream outputStream = new ByteArrayOutputStream()
- serializer.write(outputStream, o)
- Object r = serializer.read(new ByteArrayInputStream(outputStream.toByteArray()))
+ def r = serialize(o, serializer)
then:
cl.isInstance(r)
diff --git a/subprojects/messaging/src/test/groovy/org/gradle/messaging/serialize/LongSerializerTest.groovy b/subprojects/messaging/src/test/groovy/org/gradle/messaging/serialize/LongSerializerTest.groovy
new file mode 100644
index 0000000..6701422
--- /dev/null
+++ b/subprojects/messaging/src/test/groovy/org/gradle/messaging/serialize/LongSerializerTest.groovy
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.messaging.serialize
+
+class LongSerializerTest extends SerializerSpec {
+
+ def serializer = new LongSerializer()
+
+ def "writes and reads Longs"() {
+ expect:
+ serialize(144L, serializer) == 144L
+ }
+
+ def "does not permit null"() {
+ when:
+ serializer.write(new OutputStreamBackedEncoder(new ByteArrayOutputStream()), null)
+
+ then:
+ thrown(IllegalArgumentException)
+ }
+}
diff --git a/subprojects/messaging/src/test/groovy/org/gradle/messaging/serialize/StreamBackedCodecTest.groovy b/subprojects/messaging/src/test/groovy/org/gradle/messaging/serialize/StreamBackedCodecTest.groovy
new file mode 100644
index 0000000..c86b54d
--- /dev/null
+++ b/subprojects/messaging/src/test/groovy/org/gradle/messaging/serialize/StreamBackedCodecTest.groovy
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.messaging.serialize
+
+class StreamBackedCodecTest extends AbstractCodecTest {
+ @Override
+ void encodeTo(OutputStream outputStream, Closure<Encoder> closure) {
+ def encoder = new OutputStreamBackedEncoder(outputStream)
+ closure.call(encoder)
+ }
+
+ @Override
+ void decodeFrom(InputStream inputStream, Closure<Decoder> closure) {
+ def decoder = new InputStreamBackedDecoder(inputStream)
+ closure.call(decoder)
+ }
+}
diff --git a/subprojects/messaging/src/test/groovy/org/gradle/messaging/serialize/kryo/KryoBackedCodecTest.groovy b/subprojects/messaging/src/test/groovy/org/gradle/messaging/serialize/kryo/KryoBackedCodecTest.groovy
new file mode 100644
index 0000000..3b30f37
--- /dev/null
+++ b/subprojects/messaging/src/test/groovy/org/gradle/messaging/serialize/kryo/KryoBackedCodecTest.groovy
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.messaging.serialize.kryo
+
+import org.gradle.messaging.serialize.AbstractCodecTest
+import org.gradle.messaging.serialize.Decoder
+import org.gradle.messaging.serialize.Encoder
+
+class KryoBackedCodecTest extends AbstractCodecTest {
+ @Override
+ void encodeTo(OutputStream outputStream, Closure<Encoder> closure) {
+ def encoder = new KryoBackedEncoder(outputStream)
+ closure.call(encoder)
+ encoder.flush()
+ }
+
+ @Override
+ void decodeFrom(InputStream inputStream, Closure<Decoder> closure) {
+ def decoder = new KryoBackedDecoder(inputStream)
+ closure.call(decoder)
+ }
+}
diff --git a/subprojects/messaging/src/testFixtures/groovy/org/gradle/messaging/serialize/SerializerSpec.groovy b/subprojects/messaging/src/testFixtures/groovy/org/gradle/messaging/serialize/SerializerSpec.groovy
new file mode 100644
index 0000000..f012ef3
--- /dev/null
+++ b/subprojects/messaging/src/testFixtures/groovy/org/gradle/messaging/serialize/SerializerSpec.groovy
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.messaging.serialize
+
+import spock.lang.Specification
+
+class SerializerSpec extends Specification {
+ def serialize(def value, Serializer serializer) {
+ def bytes = new ByteArrayOutputStream()
+ def encoder = new OutputStreamBackedEncoder(bytes)
+ serializer.write(encoder, value)
+ encoder.flush()
+
+ return serializer.read(new InputStreamBackedDecoder(new ByteArrayInputStream(bytes.toByteArray())))
+ }
+}
diff --git a/subprojects/native/native.gradle b/subprojects/native/native.gradle
index 04f1ac8..fcf7f75 100755
--- a/subprojects/native/native.gradle
+++ b/subprojects/native/native.gradle
@@ -2,8 +2,6 @@
This project contains various native operating system integration utilities.
*/
dependencies {
- groovy libraries.groovy
-
compile project(':baseServices')
compile libraries.commons_io
compile libraries.slf4j_api
@@ -17,6 +15,7 @@ dependencies {
}
compile libraries.guava
compile libraries.jcip
+ testCompile libraries.groovy
}
if (!javaVersion.java7) {
diff --git a/subprojects/native/src/main/java/org/gradle/internal/nativeplatform/ReflectiveEnvironment.java b/subprojects/native/src/main/java/org/gradle/internal/nativeplatform/ReflectiveEnvironment.java
index b853340..242da0b 100644
--- a/subprojects/native/src/main/java/org/gradle/internal/nativeplatform/ReflectiveEnvironment.java
+++ b/subprojects/native/src/main/java/org/gradle/internal/nativeplatform/ReflectiveEnvironment.java
@@ -23,8 +23,6 @@ import java.util.Map;
/**
* Uses reflection to update private environment state
- *
- * @author: Szczepan Faber, created at: 9/7/11
*/
public class ReflectiveEnvironment {
diff --git a/subprojects/native/src/main/java/org/gradle/internal/nativeplatform/filesystem/FileSystemServices.java b/subprojects/native/src/main/java/org/gradle/internal/nativeplatform/filesystem/FileSystemServices.java
index 40e36d8..15686bb 100644
--- a/subprojects/native/src/main/java/org/gradle/internal/nativeplatform/filesystem/FileSystemServices.java
+++ b/subprojects/native/src/main/java/org/gradle/internal/nativeplatform/filesystem/FileSystemServices.java
@@ -58,10 +58,11 @@ public class FileSystemServices {
serviceRegistry.add(Symlink.class, createSymlink(libC));
// Use libc backed implementations on Linux and Mac, if libc available
- if (libC != null && (operatingSystem.isLinux() || operatingSystem.isMacOsX())) {
+ POSIX posix = PosixUtil.current();
+ if ((libC != null && (operatingSystem.isLinux() || operatingSystem.isMacOsX())) && posix instanceof BaseNativePOSIX) {
FilePathEncoder filePathEncoder = createEncoder(libC);
serviceRegistry.add(Chmod.class, new LibcChmod(libC, filePathEncoder));
- serviceRegistry.add(Stat.class, new LibCStat(libC, operatingSystem, (BaseNativePOSIX) PosixUtil.current(), filePathEncoder));
+ serviceRegistry.add(Stat.class, new LibCStat(libC, operatingSystem, (BaseNativePOSIX) posix, filePathEncoder));
return;
}
diff --git a/subprojects/native/src/main/java/org/gradle/internal/nativeplatform/jna/JnaBootPathConfigurer.java b/subprojects/native/src/main/java/org/gradle/internal/nativeplatform/jna/JnaBootPathConfigurer.java
index 8b486f4..75035b2 100644
--- a/subprojects/native/src/main/java/org/gradle/internal/nativeplatform/jna/JnaBootPathConfigurer.java
+++ b/subprojects/native/src/main/java/org/gradle/internal/nativeplatform/jna/JnaBootPathConfigurer.java
@@ -25,9 +25,6 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
-/**
- * @author: Szczepan Faber, created at: 9/12/11
- */
public class JnaBootPathConfigurer {
/**
* Attempts to find the jna library and copies it to a specified folder.
diff --git a/subprojects/open-api/open-api.gradle b/subprojects/open-api/open-api.gradle
index 154ff39..dff3fbd 100644
--- a/subprojects/open-api/open-api.gradle
+++ b/subprojects/open-api/open-api.gradle
@@ -1,5 +1,5 @@
dependencies {
- groovy libraries.groovy
+ testCompile libraries.groovy
integTestCompile libraries.slf4j_api
integTestCompile libraries.commons_lang
diff --git a/subprojects/open-api/src/integTest/groovy/org/gradle/integtests/openapi/CrossVersionCompatibilityIntegrationTest.groovy b/subprojects/open-api/src/integTest/groovy/org/gradle/integtests/openapi/CrossVersionCompatibilityIntegrationTest.groovy
index 4fec1b2..72e4707 100644
--- a/subprojects/open-api/src/integTest/groovy/org/gradle/integtests/openapi/CrossVersionCompatibilityIntegrationTest.groovy
+++ b/subprojects/open-api/src/integTest/groovy/org/gradle/integtests/openapi/CrossVersionCompatibilityIntegrationTest.groovy
@@ -18,8 +18,8 @@ package org.gradle.integtests.openapi
import org.gradle.integtests.fixtures.CrossVersionIntegrationSpec
import org.gradle.integtests.fixtures.TestResources
import org.gradle.integtests.fixtures.executer.GradleDistribution
-import org.gradle.util.ClasspathUtil
-import org.gradle.util.DefaultClassLoaderFactory
+import org.gradle.internal.classloader.ClasspathUtil
+import org.gradle.internal.classloader.DefaultClassLoaderFactory
import org.gradle.util.Requires
import org.gradle.util.TestPrecondition
import org.junit.Assert
diff --git a/subprojects/open-api/src/integTest/groovy/org/gradle/integtests/openapi/OutputUILordTest.groovy b/subprojects/open-api/src/integTest/groovy/org/gradle/integtests/openapi/OutputUILordTest.groovy
index d3c6aeb..a6d9cf0 100644
--- a/subprojects/open-api/src/integTest/groovy/org/gradle/integtests/openapi/OutputUILordTest.groovy
+++ b/subprojects/open-api/src/integTest/groovy/org/gradle/integtests/openapi/OutputUILordTest.groovy
@@ -35,8 +35,6 @@ import static org.hamcrest.Matchers.startsWith
/**
* Tests aspects of the OutputUILord in OpenAPI
- *
- * @author mhunsicker
*/
@Requires(TestPrecondition.SWING)
class OutputUILordTest {
diff --git a/subprojects/open-api/src/integTest/groovy/org/gradle/integtests/openapi/TestAlternateUIInteractionVersion1.java b/subprojects/open-api/src/integTest/groovy/org/gradle/integtests/openapi/TestAlternateUIInteractionVersion1.java
index f12e229..e6ea876 100644
--- a/subprojects/open-api/src/integTest/groovy/org/gradle/integtests/openapi/TestAlternateUIInteractionVersion1.java
+++ b/subprojects/open-api/src/integTest/groovy/org/gradle/integtests/openapi/TestAlternateUIInteractionVersion1.java
@@ -22,8 +22,6 @@ import java.io.File;
/**
* Implementation of AlternateUIInteractionVersion1 for testing purposes.
* This would lend itself well for mocking.
- *
- * @author mhunsicker
*/
public class TestAlternateUIInteractionVersion1 implements AlternateUIInteractionVersion1 {
diff --git a/subprojects/open-api/src/integTest/groovy/org/gradle/integtests/openapi/TestSettingsNodeVersion1.java b/subprojects/open-api/src/integTest/groovy/org/gradle/integtests/openapi/TestSettingsNodeVersion1.java
index 63cb847..9ba3cca 100644
--- a/subprojects/open-api/src/integTest/groovy/org/gradle/integtests/openapi/TestSettingsNodeVersion1.java
+++ b/subprojects/open-api/src/integTest/groovy/org/gradle/integtests/openapi/TestSettingsNodeVersion1.java
@@ -24,8 +24,6 @@ import java.util.List;
/**
* Implementation of settings node. It basically mirrors a DOM.
- *
- * @author mhunsicker
*/
public class TestSettingsNodeVersion1 implements SettingsNodeVersion1 {
diff --git a/subprojects/open-api/src/integTest/groovy/org/gradle/integtests/openapi/TestSingleDualPaneUIInteractionVersion1.java b/subprojects/open-api/src/integTest/groovy/org/gradle/integtests/openapi/TestSingleDualPaneUIInteractionVersion1.java
index 8871c29..96e8f82 100644
--- a/subprojects/open-api/src/integTest/groovy/org/gradle/integtests/openapi/TestSingleDualPaneUIInteractionVersion1.java
+++ b/subprojects/open-api/src/integTest/groovy/org/gradle/integtests/openapi/TestSingleDualPaneUIInteractionVersion1.java
@@ -23,7 +23,6 @@ import org.gradle.openapi.external.ui.SinglePaneUIInteractionVersion1;
/**
* This is a test implementation of both SinglePaneUIInteractionVersion1 and DualPaneUIInteractionVersion1.
* This is really just a container to hand off more complex interactions to the UI when asked for.
- * @author mhunsicker
*/
public class TestSingleDualPaneUIInteractionVersion1 implements SinglePaneUIInteractionVersion1, DualPaneUIInteractionVersion1 {
diff --git a/subprojects/open-api/src/main/groovy/org/gradle/foundation/BootstrapLoader.java b/subprojects/open-api/src/main/groovy/org/gradle/foundation/BootstrapLoader.java
deleted file mode 100644
index 1c30952..0000000
--- a/subprojects/open-api/src/main/groovy/org/gradle/foundation/BootstrapLoader.java
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.foundation;
-
-import java.io.File;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-/*
- This handles the work of loading gradle dynamically. Due to jar version issues,
- you can't just load all jar files.
-
- This does NOT require any system or environment variables to be set.
-
- To use this, instantiate this, then call one of the initialize functions.
- Now you can get the class loader to load whatever classes you like.
-
- @author mhunsicker
- */
-public class BootstrapLoader {
- private URLClassLoader libClassLoader;
-
- public void initialize(File gradleHome, boolean bootStrapDebug) throws Exception {
- initialize(ClassLoader.getSystemClassLoader().getParent(), gradleHome, false, true, bootStrapDebug);
- }
-
- /*
- Call this to initialize gradle.
- @param parentClassloader a parent class loader. Probably whatever class loader
- is used by the caller.
- @param gradleHome the root directory where gradle is installed. This
- directory should have a 'bin' child directory.
- @param useParentLastClassLoader true to use a class loader that will delegate
- to the parent only if it can't find it locally. This
- should only be true if you're trying to load gradle
- dynamically from another application.
- @param loadOpenAPI True to load the gradle open API, false not to.
- If you're calling this from a tool using the OpenAPI,
- then you've probably already loaded it, so pass in false
- here, otherwise, pass in true.
- @param bootStrapDebug true to output debug information about the loading
- process.
- @throws Exception if something goes wrong.
- @author mhunsicker
- */
- public void initialize(ClassLoader parentClassloader, File gradleHome, boolean useParentLastClassLoader, boolean loadOpenAPI, boolean bootStrapDebug) throws Exception {
- if (gradleHome == null || !gradleHome.exists()) {
- throw new RuntimeException("Gradle home not defined!");
- }
-
- if (bootStrapDebug) {
- System.out.println("Gradle Home is declared by system property gradle.home to: " + gradleHome.getAbsolutePath());
- }
-
- System.setProperty("gradle.home", gradleHome.getAbsolutePath());
-
- List<URL> loggingJars = toUrl(getLoggingJars());
-
- List<File> nonLoggingJarFiles = getNonLoggingJars();
- removeUnwantedJarFiles(nonLoggingJarFiles, loadOpenAPI);
- List<URL> nonLoggingJars = toUrl(nonLoggingJarFiles);
-
- if (bootStrapDebug) {
- System.out.println("Parent Classloader of new context classloader is: " + parentClassloader);
- System.out.println("Adding the following files to new logging classloader: " + loggingJars);
- System.out.println("Adding the following files to new lib classloader: " + nonLoggingJars);
- }
-
- URLClassLoader loggingClassLoader = new URLClassLoader(loggingJars.toArray(new URL[loggingJars.size()]), parentClassloader);
-
- if (useParentLastClassLoader) {
- libClassLoader = new ParentLastClassLoader(nonLoggingJars.toArray(new URL[nonLoggingJars.size()]), loggingClassLoader);
- } else {
- libClassLoader = new URLClassLoader(nonLoggingJars.toArray(new URL[nonLoggingJars.size()]), loggingClassLoader);
- }
-
- if (bootStrapDebug) {
- System.out.println("Logging class loader: " + loggingClassLoader);
- System.out.println("Lib class loader: " + libClassLoader);
- }
- }
-
- public static File[] getGradleHomeLibClasspath() {
- File gradleHomeLib = new File(System.getProperty("gradle.home") + "/lib");
- if (gradleHomeLib.isDirectory()) {
- return gradleHomeLib.listFiles();
- }
- return new File[0];
- }
-
- public static List<File> getNonLoggingJars() {
- List<File> pathElements = new ArrayList<File>();
- for (File file : getGradleClasspath()) {
- if (!isLogLib(file)) {
- pathElements.add(file);
- }
- }
- return pathElements;
- }
-
- public static List<File> getLoggingJars() {
- List<File> pathElements = new ArrayList<File>();
- for (File file : getGradleClasspath()) {
- if (isLogLib(file)) {
- pathElements.add(file);
- }
- }
- return pathElements;
- }
-
- private static boolean isLogLib(File file) {
- return file.getName().startsWith("logback") || file.getName().startsWith("slf4j");
- }
-
- public static List<File> getGradleClasspath() {
- File customGradleBin = null;
- List<File> pathElements = new ArrayList<File>();
- if (System.getProperty("gradle.bootstrap.gradleBin") != null) {
- customGradleBin = new File(System.getProperty("gradle.bootstrap.gradleBin"));
- pathElements.add(customGradleBin);
- }
- for (File homeLibFile : getGradleHomeLibClasspath()) {
- if (homeLibFile.isFile() && !(customGradleBin != null && homeLibFile.getName().startsWith("gradle-"))) {
- pathElements.add(homeLibFile);
- }
- }
- return pathElements;
- }
-
- /*
- This removes unwanted jar files. At the time of this writing, we're only
- interested in the open api jar.
-
- @param nonLoggingJarFiles a list of jar files
- @param loadOpenAPI true to keep the open api jar, false to remove it.
- @author mhunsicker
- */
- private void removeUnwantedJarFiles(List<File> nonLoggingJarFiles, boolean loadOpenAPI) {
- if (loadOpenAPI) {
- return;
- }
-
- Iterator<File> iterator = nonLoggingJarFiles.iterator();
- while (iterator.hasNext()) {
- File file = iterator.next();
- if (file.getName().startsWith("gradle-open-api-")) {
- iterator.remove();
- }
- }
- }
-
- /*
- Call this to get the class loader you can use to load gradle classes.
- @return a URLClassLoader
- @author mhunsicker
- */
- public URLClassLoader getClassLoader() {
- return libClassLoader;
- }
-
- public Class load(String classPath) throws Exception {
- return libClassLoader.loadClass(classPath);
- }
-
- private static List<URL> toUrl(List<File> files) throws MalformedURLException {
- List<URL> result = new ArrayList<URL>();
- for (File file : files) {
- result.add(file.toURI().toURL());
- }
- return result;
- }
-}
diff --git a/subprojects/open-api/src/main/groovy/org/gradle/foundation/ParentLastClassLoader.java b/subprojects/open-api/src/main/groovy/org/gradle/foundation/ParentLastClassLoader.java
deleted file mode 100644
index 2cbcb49..0000000
--- a/subprojects/open-api/src/main/groovy/org/gradle/foundation/ParentLastClassLoader.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.foundation;
-
-import java.net.URLClassLoader;
-import java.net.URL;
-import java.net.URLStreamHandlerFactory;
-
-/**
- * <p>This class loader delegates to the parent class loader ONLY if it cannot find it itself. This is meant to solve classloading issues when running something as, say, a plugin inside an application
- * that may have already loaded a different version of some required jars. This makes sure it looks locally first. This is the opposite of a ClassLoader's typical behavior, but it necessary when you
- * can't control the environment in which you're running.
- *
- * <p>Using this class can be very dangerous. You must carefully make sure you understand the ramifications of using this. You should also probably make this the first class loader between your plugin
- * and the plugin's owner.
- *
- * @author mhunsicker
- */
-public class ParentLastClassLoader extends URLClassLoader {
- public ParentLastClassLoader(URL[] urls, ClassLoader parent) {
- super(urls, parent);
- }
-
- public ParentLastClassLoader(URL[] urls) {
- super(urls);
- }
-
- public ParentLastClassLoader(URL[] urls, ClassLoader parent, URLStreamHandlerFactory factory) {
- super(urls, parent, factory);
- }
-
- /*
- This has been overridden to look at the parent class loader last.
- @author mhunsicker
- */
- @Override
- public Class<?> loadClass(String name) throws ClassNotFoundException {
- // First check whether it's already been loaded, if so use it
- Class loadedClass = findLoadedClass(name);
-
- // Not loaded, try to load it
- if (loadedClass == null) {
- try {
- // Ignore parent delegation and just try to load locally
- loadedClass = findClass(name);
- } catch (ClassNotFoundException e) {
- // Swallow exception - does not exist locally
- }
-
- // If not found locally, use normal parent delegation in URLClassloader
- if (loadedClass == null) {
- // throws ClassNotFoundException if not found in delegation hierarchy at all
- loadedClass = super.loadClass(name);
- }
- }
- // will never return null (ClassNotFoundException will be thrown)
- return loadedClass;
- }
-}
-
diff --git a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/ExternalUtility.java b/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/ExternalUtility.java
deleted file mode 100644
index a631e82..0000000
--- a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/ExternalUtility.java
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.openapi.external;
-
-import org.gradle.foundation.BootstrapLoader;
-
-import java.io.File;
-import java.io.FileFilter;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
-import java.util.regex.Pattern;
-
-/**
- * Utility functions required by the OpenAPI
- *
- * @author mhunsicker
- */
-public class ExternalUtility {
- private static final Pattern GRADLE_CORE_PATTERN = Pattern.compile("^gradle-core-\\d.*\\.jar$");
-
- /**
- * Call this to get a classloader that has loaded gradle.
- *
- * @param parentClassLoader Your classloader. Probably the classloader of whatever class is calling this.
- * @param gradleHomeDirectory the root directory of a gradle installation
- * @param showDebugInfo true to show some additional information that may be helpful diagnosing problems is this fails
- * @return a classloader that has loaded gradle and all of its dependencies.
- * @author mhunsicker
- */
-
- public static ClassLoader getGradleClassloader(ClassLoader parentClassLoader, File gradleHomeDirectory, boolean showDebugInfo) throws Exception {
- File gradleJarFile = getGradleJar(gradleHomeDirectory);
- if (gradleJarFile == null) {
- throw new RuntimeException("Not a valid gradle home directory '" + gradleHomeDirectory.getAbsolutePath() + "'");
- }
-
- System.setProperty("gradle.home", gradleHomeDirectory.getAbsolutePath());
-
- BootstrapLoader bootstrapLoader = new BootstrapLoader();
- bootstrapLoader.initialize(parentClassLoader, gradleHomeDirectory, true, false, showDebugInfo);
- return bootstrapLoader.getClassLoader();
- }
-
- /**
- * This locates the gradle jar. We do NOT want the gradle-wrapper jar.
- *
- * @param gradleHomeDirectory the root directory of a gradle installation. We're expecting this to have a child directory named 'lib'.
- * @return the gradle jar file. Null if we didn't find it.
- * @author mhunsicker
- */
- public static File getGradleJar(File gradleHomeDirectory) {
- File libDirectory = new File(gradleHomeDirectory, "lib");
- if (!libDirectory.exists()) {
- return null;
- }
-
- //try to get the gradle.jar. It'll be "gradle-[version].jar"
- File[] files = libDirectory.listFiles(new FileFilter() {
- public boolean accept(File file) {
- return GRADLE_CORE_PATTERN.matcher(file.getName()).matches();
- }
- });
-
- if (files == null || files.length == 0) {
- return null;
- }
-
- //if they've given us a directory with multiple gradle jars, tell them. We won't know which one to use.
- if (files.length > 1) {
- throw new RuntimeException("Installation has multiple gradle jars. Cannot determine which one to use. Found files: " + createFileNamesString(files));
- }
-
- return files[0];
- }
-
- private static StringBuilder createFileNamesString(File[] files) {
- StringBuilder fileNames = new StringBuilder();
- for (File f : files) {
- fileNames.append(f.getAbsolutePath() + ", ");
- }
- fileNames.delete(fileNames.length() - 2, fileNames.length()); // Remove the trailing ', '
- return fileNames;
- }
-
- //just a function to help debugging. If we can't find the constructor we want, this dumps out what is available.
-
- public static String dumpConstructors(Class classInQuestion) {
- StringBuilder builder = new StringBuilder();
- Constructor[] constructors = classInQuestion.getConstructors();
- for (int index = 0; index < constructors.length; index++) {
- Constructor constructor = constructors[index];
- builder.append(constructor).append('\n');
- }
-
- return builder.toString();
- }
-
- public static String dumpMethods(Class classInQuestion) {
- StringBuilder builder = new StringBuilder();
-
- Method[] methods = classInQuestion.getMethods();
- for (int index = 0; index < methods.length; index++) {
- Method method = methods[index];
- builder.append(method).append('\n');
- }
-
- return builder.toString();
- }
-
- /**
- * This attempts to load the a class from the specified gradle home directory.
- *
- * @param classToLoad the full path to the class to load
- * @param parentClassLoader Your classloader. Probably the classloader of whatever class is calling this.
- * @param gradleHomeDirectory the root directory of a gradle installation
- * @param showDebugInfo true to show some additional information that may be helpful diagnosing problems is this fails
- */
- public static Class loadGradleClass(String classToLoad, ClassLoader parentClassLoader, File gradleHomeDirectory, boolean showDebugInfo) throws Exception {
- ClassLoader bootStrapClassLoader = getGradleClassloader(parentClassLoader, gradleHomeDirectory, showDebugInfo);
- Thread.currentThread().setContextClassLoader(bootStrapClassLoader);
-
- //load the class in gradle that wraps our return interface and handles versioning issues.
- try {
- return bootStrapClassLoader.loadClass(classToLoad);
- } catch (NoClassDefFoundError e) { //might be a version mismatch
- e.printStackTrace();
- return null;
- } catch (Throwable e) { //might be a version mismatch
- e.printStackTrace();
- return null;
- }
- }
-
- /**
- * This wraps up invoking a static method into a single call.
- *
- * @param classToInvoke the class that has the method
- * @param methodName the name of the method to invoke
- * @param argumentsClasses the classes of the arguments (we can't determine this from the argumentValues because they can be of class A, but implement class B and B is be the argument type of the
- * method in question
- * @param argumentValues the values of the arguments.
- * @return the return value of invoking the method.
- */
- public static Object invokeStaticMethod(Class classToInvoke, String methodName, Class[] argumentsClasses, Object... argumentValues) throws Exception {
- Method method = null;
- try {
- method = classToInvoke.getDeclaredMethod(methodName, argumentsClasses);
- } catch (NoSuchMethodException e) {
- e.printStackTrace();
- System.out.println("Dumping available methods on " + classToInvoke.getName() + "\n" + ExternalUtility.dumpMethods(classToInvoke));
- throw e;
- }
- return method.invoke(null, argumentValues);
- }
-}
diff --git a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/foundation/GradleInterfaceVersion1.java b/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/foundation/GradleInterfaceVersion1.java
deleted file mode 100644
index 6142d85..0000000
--- a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/foundation/GradleInterfaceVersion1.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.openapi.external.foundation;
-
-import org.gradle.openapi.external.ui.CommandLineArgumentAlteringListenerVersion1;
-
-import java.io.File;
-import java.util.List;
-
-/**
- * This is an abstraction from Gradle that allows you to retrieve projects and views from it.
- *
- * This is a mirror of GradlePluginLord inside Gradle, but this is meant to aid backward and forward compatibility by shielding you from direct changes within gradle.
- *
- * @author mhunsicker
- */
-public interface GradleInterfaceVersion1 {
-
- /**
- * @return the root projects. It probably only has one.
- */
- public List<ProjectVersion1> getRootProjects();
-
- /**
- * This refreshes the projects and task list.
- */
- public void refreshTaskTree();
-
- /**
- * Determines if commands are currently being executed or not.
- *
- * @return true if we're busy, false if not.
- */
- public boolean isBusy();
-
- /**
- * Call this to execute the given gradle command.
- *
- * @param commandLineArguments the command line arguments to pass to gradle.
- * @param displayName the name displayed in the UI for this command
- */
- public void executeCommand(String commandLineArguments, String displayName);
-
- /**
- * @return the root directory of your gradle project.
- */
- public File getCurrentDirectory();
-
- /**
- * @param currentDirectory the new root directory of your gradle project.
- */
- public void setCurrentDirectory(File currentDirectory);
-
- /**
- * @return the gradle home directory. Where gradle is installed.
- */
- public File getGradleHomeDirectory();
-
- /**
- * This is called to get a custom gradle executable file. If you don't run gradle.bat or gradle shell script to run gradle, use this to specify what you do run. Note: we're going to pass it the
- * arguments that we would pass to gradle so if you don't like that, see alterCommandLineArguments. Normally, this should return null.
- *
- * @return the Executable to run gradle command or null to use the default
- */
- public File getCustomGradleExecutable();
-
- /**
- * This allows you to add a listener that can add additional command line arguments whenever gradle is executed. This is useful if you've customized your gradle build and need to specify, for
- * example, an init script.
- *
- * @param listener the listener that modifies the command line arguments.
- */
- public void addCommandLineArgumentAlteringListener(CommandLineArgumentAlteringListenerVersion1 listener);
-
- public void removeCommandLineArgumentAlteringListener(CommandLineArgumentAlteringListenerVersion1 listener);
-}
diff --git a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/foundation/GradleInterfaceVersion2.java b/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/foundation/GradleInterfaceVersion2.java
deleted file mode 100644
index dbc817e..0000000
--- a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/foundation/GradleInterfaceVersion2.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.openapi.external.foundation;
-
-import org.gradle.openapi.external.foundation.favorites.FavoriteTaskVersion1;
-
-import java.io.File;
-import java.util.List;
-
-/**
- * This is an abstraction from Gradle that allows you to retrieve projects and views from it.
- *
- * This is a mirror of GradlePluginLord inside Gradle, but this is meant to aid backward and forward compatibility by shielding you from direct changes within gradle.
- *
- * @author mhunsicker
- */
-public interface GradleInterfaceVersion2 extends GradleInterfaceVersion1 {
-
- /**
- * @return the version of gradle being run. This is basically the version from the jar file.
- */
- public String getVersion();
-
- /**
- * This refreshes the projects and task list.
- */
- public RequestVersion1 refreshTaskTree2();
-
- /**
- * This refreshes the task tree. Useful if you know you've changed something behind gradle's back or when first displaying this UI.
- *
- * @param additionalCommandLineArguments additional command line arguments to be passed to gradle when refreshing the task tree.
- * @return the request object. Useful if you want to track its completion via a RequestObserver
- */
- public RequestVersion1 refreshTaskTree2(String additionalCommandLineArguments);
-
- /**
- * Call this to execute the given gradle command.
- *
- * @param commandLineArguments the command line arguments to pass to gradle.
- * @param displayName the name displayed in the UI for this command
- * @return the request object. Useful if you want to track its completion via a RequestObserver
- * @author mhunsicker
- */
- public RequestVersion1 executeCommand2(String commandLineArguments, String displayName);
-
- /**
- * Executes several favorites commands at once as a single command. This has the affect of simply concatenating all the favorite command lines into a single line.
- *
- * @param favorites a list of favorites. If just one favorite, it executes it normally. If multiple favorites, it executes them all at once as a single command. This blindly concatenates them so
- * it may wind up with duplicate tasks on the command line.
- * @return the request object. Useful if you want to track its completion via a RequestObserver
- */
- public RequestVersion1 executeFavorites(List<FavoriteTaskVersion1> favorites);
-
- /**
- * Sets a custom gradle executable. See getCustomGradleExecutable
- *
- * @param customGradleExecutor the path to an executable (or script/batch file)
- */
- public void setCustomGradleExecutable(File customGradleExecutor);
-
- /**
- * Adds an observer that is notified when Gradle commands are executed and completed.
- *
- * @param observer the observer that is notified
- */
- public void addRequestObserver(RequestObserverVersion1 observer);
-
- /**
- * Removes a request observer when you no longer wish to receive notifications about Gradle command being executed.
- *
- * @param observer the observer to remove
- */
- public void removeRequestObserver(RequestObserverVersion1 observer);
-}
\ No newline at end of file
diff --git a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/foundation/ProjectVersion1.java b/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/foundation/ProjectVersion1.java
deleted file mode 100644
index 366fe5c..0000000
--- a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/foundation/ProjectVersion1.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.openapi.external.foundation;
-
-import java.io.File;
-import java.util.List;
-
-/**
- * This is an abstraction of a Gradle project
- *
- * This is a mirror of ProjectView inside Gradle, but this is meant to aid backward and forward compatibility by shielding you from direct changes within gradle.
- *
- * @author mhunsicker
- */
-public interface ProjectVersion1 {
-
- /**
- * @return the name of this project
- */
- public String getName();
-
- /**
- * @return The full project name. This is just the project name if its off of the root. Otherwise, its all of its ancestors separated by colons with this project being last.
- */
- public String getFullProjectName();
-
- /**
- * @return the TaskVersion1 objects associated with this project
- */
- public List<TaskVersion1> getTasks();
-
- /**
- * @return the .gradle file this project is defined in
- */
- public File getFile();
-
- /**
- * @return the sub projects of this project
- */
- public List<ProjectVersion1> getSubProjects();
-
- /**
- * @return the parent of this project if this is a sub project. Otherwise, null
- */
- public ProjectVersion1 getParentProject();
-
- /**
- * @return a list of projects that this project depends on.
- */
- public List<ProjectVersion1> getDependantProjects();
-
- public ProjectVersion1 getSubProject(String name);
-
- public ProjectVersion1 getSubProjectFromFullPath(String fullProjectName);
-
- public TaskVersion1 getTask(String name);
-
- /**
- * Builds a list of default tasks. These are defined by specifying
- *
- * defaultTasks 'task name'
- *
- * in the gradle file. There can be multiple default tasks. This only returns default tasks directly for this project and does not return them for subprojects.
- *
- * @return a list of default tasks or an empty list if none exist
- */
- public List<TaskVersion1> getDefaultTasks();
-
- public TaskVersion1 getTaskFromFullPath(String fullTaskName);
-}
diff --git a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/foundation/RequestObserverVersion1.java b/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/foundation/RequestObserverVersion1.java
deleted file mode 100644
index 97a7c30..0000000
--- a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/foundation/RequestObserverVersion1.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.openapi.external.foundation;
-
-/**
- * This allows you to observer when Gradle commands are executed/complete. It is an abstraction of a GradlePluginLord.RequestObserver.
- *
- * <p>This is a mirror of GradlePluginLord.RequestObserver inside Gradle, but this is meant to aid backward and forward compatibility by shielding you from direct changes within gradle.
- *
- * @author mhunsicker
- */
-public interface RequestObserverVersion1 {
-
- /**
- * Notification that an execution request was added to the queue. This is the normal request that initiates a gradle command.
- *
- * @param request the request that was added
- */
- public void executionRequestAdded(RequestVersion1 request);
-
- /**
- * Notification that a refresh request was added to the queue. This type of request updates the task tree.
- */
- public void refreshRequestAdded(RequestVersion1 request);
-
- /**
- * Notification that a command is about to be executed. This is mostly useful for IDE's that may need to save their files. This is always called after a request has been added to the queue.
- */
- public void aboutToExecuteRequest(RequestVersion1 request);
-
- /**
- * Notification that a request has completed execution.
- *
- * @param request the original request containing the command that was executed
- * @param result the result of the command
- * @param output the output from gradle executing the command
- */
- public void requestExecutionComplete(RequestVersion1 request, int result, String output);
-}
diff --git a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/foundation/RequestVersion1.java b/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/foundation/RequestVersion1.java
deleted file mode 100644
index 938e6d9..0000000
--- a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/foundation/RequestVersion1.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.openapi.external.foundation;
-
-/**
- * This represents an execution or refresh request sent to Gradle. Execution requests are
- * just Gradle commands (what would be the command line arguments). A refresh request is
- * what updates the task tree.
- *
- * This is a mirror of Request inside Gradle, but this is meant to aid backward and forward compatibility by shielding you
- * from direct changes within gradle.
- *
- * @author mhunsicker
- */
-public interface RequestVersion1 {
-
- /**
- * @return the full gradle command line of this request
- */
- public String getFullCommandLine();
-
- /**
- * @return the display name of this request. Often this is the same as the full
- * command line, but favorites may specify something more user-friendly.
- */
- public String getDisplayName();
-
- /**
- * @return whether or not output should always be shown. If false, only show it when
- * errors occur.
- */
- public boolean forceOutputToBeShown();
-
- /**
- * Cancels this request.
- */
- public boolean cancel();
-
- public static final String EXECUTION_TYPE = "execution";
- public static final String REFRESH_TYPE = "refresh";
- public static final String UNKNOWN_TYPE_PREFIX = "[unknown]:";
-
- /**
- * @return the type of the request. Either EXECUTION, REFRESH, or something that
- * starts with UNKNOWN_TYPE_PREFIX (followed by an internal identifier) if its not
- * listed above.
- */
- public String getType();
-}
diff --git a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/foundation/TaskVersion1.java b/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/foundation/TaskVersion1.java
deleted file mode 100644
index e430b51..0000000
--- a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/foundation/TaskVersion1.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.openapi.external.foundation;
-
-/**
- * This is an abstraction of a gradle task
- *
- * This is a mirror of TaskView inside Gradle, but this is meant
- * to aid backward and forward compatibility by shielding you from direct
- * changes within gradle.
- *
- * @author mhunsicker
- */
-public interface TaskVersion1 {
-
- /**
- * @return the project this task is associated with
- */
- public ProjectVersion1 getProject();
-
- /**
- * @return the name of this task
- */
- public String getName();
-
- /**
- * @return this tasks description
- */
- public String getDescription();
-
- /**
- * returns whether or not this is a default task for its parent project. These are defined by specifying
- *
- * defaultTasks 'task name'
- *
- * in the gradle file. There can be multiple default tasks.
- *
- * @return true if its a default task, false if not.
- */
- public boolean isDefault();
-
- /**
- * This generates this task's full name. This is a colon-separated string of this task and its parent projects.
- *
- * Example: root_project:sub_project:sub_sub_project:task.
- */
- public String getFullTaskName();
-}
diff --git a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/foundation/favorites/FavoriteTaskVersion1.java b/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/foundation/favorites/FavoriteTaskVersion1.java
deleted file mode 100644
index 5b086f3..0000000
--- a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/foundation/favorites/FavoriteTaskVersion1.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.openapi.external.foundation.favorites;
-
-/**
- * This is an abstraction from Gradle that allows you to work with a 'favorite' task.
- *
- * This is a mirror of FavoriteTask inside Gradle, but this is meant
- * to aid backward and forward compatibility by shielding you from direct
- * changes within gradle.
- *
- * You should not implement this yourself. Only use an implementation coming from Gradle.
- *
- * @author mhunsicker
- */
-public interface FavoriteTaskVersion1 {
- /**<!====== getFullCommandLine ============================================>
- @return the command line that is executed
- @author mhunsicker
- <!=======================================================================>*/
- public String getFullCommandLine();
-
- /**<!====== getDisplayName ================================================>
- @return a display name for this command
- @author mhunsicker
- <!=======================================================================>*/
- public String getDisplayName();
-
- /**<!====== alwaysShowOutput ==============================================>
- @return true if executing this command should always show the output, false
- to only show output if an error occurs.
- @author mhunsicker
- <!=======================================================================>*/
- public boolean alwaysShowOutput();
-}
diff --git a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/foundation/favorites/FavoritesEditorVersion1.java b/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/foundation/favorites/FavoritesEditorVersion1.java
deleted file mode 100644
index 3e45cde..0000000
--- a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/foundation/favorites/FavoritesEditorVersion1.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.openapi.external.foundation.favorites;
-
-import org.gradle.openapi.external.foundation.TaskVersion1;
-
-import java.awt.*;
-import java.util.List;
-
-/**
- * This is an abstraction from Gradle that allows you to obtain and edit favorites.
- *
- * <p>This is a mirror of FavoritesEditor inside Gradle, but this is meant to aid backward and forward compatibility by shielding you from direct changes within gradle.
- *
- * @author mhunsicker
- */
-public interface FavoritesEditorVersion1 {
-
- /**
- * Adds the specified favorite.
- *
- * @param fullCommandLine the command line that this favorite executes
- * @param displayName a more user-friendly name for the command
- * @param alwaysShowOutput true to always show output when this favorite is executed. False to only show output when errors occur.
- * @return the favorite added
- */
- public FavoriteTaskVersion1 addFavorite(String fullCommandLine, String displayName, boolean alwaysShowOutput);
-
- /**
- * Sets new values on the specified favorite task. This provides a simple way to programmatically edit favorite tasks.
- *
- * @param favoriteTask the favorite to edit
- * @param newFullCommandLine the new command line
- * @param newDisplayName the new display name
- * @param newAlwaysShowOutput the new value for whether or not to always show output (vs only showing it when an error occurs).
- * @returns null if successful otherwise, an error suitable for displaying to the user.
- */
- public String editFavorite(FavoriteTaskVersion1 favoriteTask, String newFullCommandLine, String newDisplayName, boolean newAlwaysShowOutput);
-
- /**
- * @return a list of all favorites in the system
- */
- public List<FavoriteTaskVersion1> getFavoriteTasks();
-
- /**
- * Returns the favorite with the specified command line
- *
- * @param fullCommandLine the command line of the sought favorite
- * @return the matching favorite or null if no match found.
- */
- public FavoriteTaskVersion1 getFavorite(String fullCommandLine);
-
- /**
- * Returns the favorite with the specified display name
- *
- * @param displayName the display name of the sought favorite
- * @return the matching favorite or null if no match found.
- */
- public FavoriteTaskVersion1 getFavoriteByDisplayName(String displayName);
-
- /**
- * Returns the favorite with the specified task
- *
- * @param task the task of the sought favorite
- * @return the matching favorite or null if no match found.
- */
- public FavoriteTaskVersion1 getFavorite(TaskVersion1 task);
-
- /**
- * Display a Swing dialog prompting the user to enter a favorite.
- *
- * @param parent the parent window of the dialog.
- * @return the favorite that was added or null if the user canceled
- */
- public FavoriteTaskVersion1 promptUserToAddFavorite(Window parent);
-
- /**
- * Display a Swing dialog prompting the user to edit the specified favorite
- *
- * @param parent the parent window of the dialog
- * @param favorite the favorite to edit
- * @return true if the user made changes and accepted them, false if the user canceled.
- */
- public boolean promptUserToEditFavorite(Window parent, FavoriteTaskVersion1 favorite);
-
- /**
- * Removes the specified favorites.
- *
- * @param favoritesToRemove the favorites to remove
- */
- public void removeFavorites(List<FavoriteTaskVersion1> favoritesToRemove);
-}
diff --git a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/runner/GradleRunnerFactory.java b/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/runner/GradleRunnerFactory.java
deleted file mode 100644
index b705c56..0000000
--- a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/runner/GradleRunnerFactory.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.openapi.external.runner;
-
-import org.gradle.openapi.external.ExternalUtility;
-
-import java.io.File;
-import java.lang.reflect.Constructor;
-
-/**
- * This provides a simple way to execute gradle commands from an external process. call createGradleRunner to instantiate a gradle runner. You can then use that to execute commands.
- *
- * @author mhunsicker
- */
-public class GradleRunnerFactory {
- /**
- * Call this to instantiate an object that you can use to execute gradle commands directly.
- *
- * Note: this function is meant to be backward and forward compatible. So this signature should not change at all, however, it may take and return objects that implement ADDITIONAL interfaces. That
- * is, it will always return a GradleRunnerVersion1, but it may also be an object that implements GradleRunnerVersion2 (notice the 2). The caller will need to dynamically determine that. The
- * GradleRunnerInteractionVersion1 may take an object that also implements GradleRunnerInteractionVersion2. If so, we'll dynamically determine that and handle it. Of course, this all depends on
- * what happens in the future.
- *
- * @param parentClassLoader Your classloader. Probably the classloader of whatever class is calling this.
- * @param gradleHomeDirectory the root directory of a gradle installation
- * @param interaction this is how we interact with the caller.
- * @param showDebugInfo true to show some additional information that may be helpful diagnosing problems is this fails
- * @return a gradle runner
- * @author mhunsicker
- * @deprecated Use the tooling API instead.
- */
- @Deprecated
- public static GradleRunnerVersion1 createGradleRunner(ClassLoader parentClassLoader, File gradleHomeDirectory, GradleRunnerInteractionVersion1 interaction, boolean showDebugInfo)
- throws Exception {
- //much of this function is exception handling so if we can't obtain it via the newer factory method, then
- //we'll try the old way, but we want to report the original exception if we can't do it either way.
- Exception viaFactoryException = null;
- GradleRunnerVersion1 gradleRunner = null;
-
- //first, try it the new way
- try {
- gradleRunner = createGradleRunnerViaFactory(parentClassLoader, gradleHomeDirectory, interaction, showDebugInfo);
- } catch (Exception e) {
- //we might ignore this. It means we're probably using an older version of gradle. That case is handled below.
- //If not, this exception will be thrown at the end.
- viaFactoryException = e;
- }
-
- //try it the old way
- if (gradleRunner == null) {
- gradleRunner = createGradleRunnerOldWay(parentClassLoader, gradleHomeDirectory, interaction, showDebugInfo);
- }
-
- //if we still don't have a gradle runner and we have an exception from using the factory, throw it. If we
- //got an exception using the 'old way', it would have been thrown already and we wouldn't be here.
- if (gradleRunner == null && viaFactoryException != null) {
- throw viaFactoryException;
- }
-
- return gradleRunner;
- }
-
- /**
- * This function uses a factory to instantiate a GradleRunner. The factory is located with the version of gradle pointed to by gradleHomeDirectory and thus allows the version of gradle being loaded
- * to make decisions about how to instantiate the runner. This is needed as multiple versions of the runner are being used.
- */
- private static GradleRunnerVersion1 createGradleRunnerViaFactory(ClassLoader parentClassLoader, File gradleHomeDirectory, GradleRunnerInteractionVersion1 interaction, boolean showDebugInfo)
- throws Exception {
- //load the class in gradle that wraps our return interface and handles versioning issues.
- Class soughtClass = ExternalUtility.loadGradleClass("org.gradle.openapi.wrappers.RunnerWrapperFactory", parentClassLoader, gradleHomeDirectory, showDebugInfo);
- if (soughtClass == null) {
- return null;
- }
-
- Class[] argumentClasses = new Class[]{File.class, GradleRunnerInteractionVersion1.class, boolean.class};
-
- Object gradleRunner = ExternalUtility.invokeStaticMethod(soughtClass, "createGradleRunner", argumentClasses, gradleHomeDirectory, interaction, showDebugInfo);
- return (GradleRunnerVersion1) gradleRunner;
- }
-
- /**
- * This function uses an early way (early 0.9 pre-release and sooner) of instantiating the GradleRunner and should no longer be used. It unfortunately is tied to a single wrapper class instance
- * (which it tries to directly instantiate). This doesn't allow the GradleRunner to adaptively determine what to instantiate.
- */
- private static GradleRunnerVersion1 createGradleRunnerOldWay(ClassLoader parentClassLoader, File gradleHomeDirectory, GradleRunnerInteractionVersion1 interaction, boolean showDebugInfo)
- throws Exception {
- ClassLoader bootStrapClassLoader = ExternalUtility.getGradleClassloader(parentClassLoader, gradleHomeDirectory, showDebugInfo);
- Thread.currentThread().setContextClassLoader(bootStrapClassLoader);
-
- //load the class in gradle that wraps our return interface and handles versioning issues.
- Class soughtClass = null;
- try {
- soughtClass = bootStrapClassLoader.loadClass("org.gradle.openapi.wrappers.runner.GradleRunnerWrapper");
- } catch (NoClassDefFoundError e) { //might be a version mismatch
- e.printStackTrace();
- return null;
- } catch (ClassNotFoundException e) { //might be a version mismatch
- e.printStackTrace();
- return null;
- }
-
- if (soughtClass == null) {
- return null;
- }
-
- //instantiate it.
- Constructor constructor = null;
- try {
- constructor = soughtClass.getDeclaredConstructor(File.class, GradleRunnerInteractionVersion1.class);
- } catch (NoSuchMethodException e) {
- e.printStackTrace();
- System.out.println("Dumping available constructors on " + soughtClass.getName() + "\n" + ExternalUtility.dumpConstructors(soughtClass));
-
- throw e;
- }
-
- Object gradleRunner = constructor.newInstance(gradleHomeDirectory, interaction);
-
- return (GradleRunnerVersion1) gradleRunner;
- }
-}
diff --git a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/runner/GradleRunnerInteractionVersion1.java b/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/runner/GradleRunnerInteractionVersion1.java
deleted file mode 100644
index 1931e83..0000000
--- a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/runner/GradleRunnerInteractionVersion1.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.openapi.external.runner;
-
-import java.io.File;
-
-/**
- * .
- *
- * @author mhunsicker
- */
-public interface GradleRunnerInteractionVersion1 {
- /**
- * @return The root directory of your gradle project. The same directory Where you would run gradle from the command.
- */
- public File getWorkingDirectory();
-
- public enum LogLevel {Quiet, Lifecycle, Debug}
-
- public enum StackTraceLevel {InternalExceptions, Always, AlwaysFull}
-
- /**
- * @return the log level. This determines the detail level of information reported via reportLiveOutput and reportExecutionFinished.
- */
- public LogLevel getLogLevel();
-
- /**
- * @return the stack trace level. This determines the detail level of any stack traces should an exception occur.
- */
- public StackTraceLevel getStackTraceLevel();
-
- /**
- * Notification that overall execution has been started. This is only called once at the end.
- */
- public void reportExecutionStarted();
-
- /**
- * Notification of the total number of tasks that will be executed. This is called after reportExecutionStarted and before any tasks are executed.
- *
- * @param size the total number of tasks.
- */
- public void reportNumberOfTasksToExecute(int size);
-
- /**
- * Notification that a single task has completed. Note: the task you kicked off probably executes other tasks and this notifies you of those tasks and provides completion progress.
- *
- * @param currentTaskName the task being executed
- * @param percentComplete the percent complete of all the tasks that make up the task you requested.
- */
- public void reportTaskStarted(String currentTaskName, float percentComplete);
-
- public void reportTaskComplete(String currentTaskName, float percentComplete);
-
- /**
- * Report real-time output from gradle and its subsystems (such as ant).
- *
- * @param output a single line of text to show.
- */
- public void reportLiveOutput(String output);
-
- public void reportExecutionFinished(boolean wasSuccessful, String message, Throwable throwable);
-
- /**
- * This is called to get a custom gradle executable file. If you don't run gradle.bat or gradle shell script to run gradle, use this to specify what you do run. Note: we're going to pass it the
- * arguments that we would pass to gradle so if you don't like that, see alterCommandLineArguments. Normaly, this should return null.
- *
- * @return the Executable to run gradle command or null to use the default
- */
- public File getCustomGradleExecutable();
-}
diff --git a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/runner/GradleRunnerVersion1.java b/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/runner/GradleRunnerVersion1.java
deleted file mode 100644
index 3e04b04..0000000
--- a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/runner/GradleRunnerVersion1.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.openapi.external.runner;
-
-/**
- * This executes gradle commands in an external process.
- *
- * @author mhunsicker
- */
-public interface GradleRunnerVersion1 {
- /**
- * Call this to execute the specified command line.
- *
- * @param commandLine the command to execute
- */
- public void executeCommand(String commandLine);
-
- /**
- * Call this to stop the gradle command. This is killing the process, not gracefully exiting.
- */
- public void killProcess();
-}
diff --git a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/ui/AlternateUIInteractionVersion1.java b/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/ui/AlternateUIInteractionVersion1.java
deleted file mode 100644
index daf64ea..0000000
--- a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/ui/AlternateUIInteractionVersion1.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.openapi.external.ui;
-
-import java.io.File;
-
-/**
- * This is how the gradle UI panel interacts with the UI that is holding it.
- *
- * This is a mirror of AlternateUIInteraction inside Gradle, but this is meant to aid backward and forward compatibility by shielding you from direct changes within gradle.
- *
- * @author mhunsicker
- */
-public interface AlternateUIInteractionVersion1 {
- /**
- * Notification that you should open the specified file and go to the specified line. Its up to the application to determine if this file should be opened for editing or simply displayed. The
- * difference comes into play for things like xml or html files where a user may want to open them in a browser vs a source code file where they may want to open it directly in an IDE.
- *
- * @param file the file to edit
- * @param line the line to go to. -1 if no line is specified.
- */
- public void openFile(File file, int line);
-
- /**
- * This is called when we should open the specified file for editing. This version explicitly wants them edited versus just opened.
- *
- * @param file the file to open
- * @param line the line to go to. -1 if no line is specified.
- */
- public void editFile(File file, int line);
-
- /**
- * Determines if we can call editFiles or openFile. This is not a dynamic answer and should always return either true of false. If you want to change the answer, return true and then handle the
- * files differently in editFiles.
- *
- * @return true if support editing files, false otherwise.
- */
- public boolean doesSupportEditingOpeningFiles();
-
- /**
- * Notification that a command is about to be executed. This is mostly useful for IDE's that may need to save their files.
- *
- * @param fullCommandLine the command that's about to be executed.
- */
- public void aboutToExecuteCommand(String fullCommandLine);
-}
diff --git a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/ui/BasicGradleUIVersion1.java b/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/ui/BasicGradleUIVersion1.java
deleted file mode 100644
index d251165..0000000
--- a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/ui/BasicGradleUIVersion1.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.openapi.external.ui;
-
-import org.gradle.openapi.external.foundation.GradleInterfaceVersion1;
-import org.gradle.openapi.external.foundation.favorites.FavoritesEditorVersion1;
-
-import javax.swing.*;
-import java.io.File;
-
-/**
- * This represents a basic gradle UI
- *
- * To use this, you'll want to get an instance of this from Gradle. Then setup your UI and add this to it via getComponent. Then call aboutToShow before you display your UI. Call close before you hide
- * your UI. You'll need to set the current directory (at any time) so gradle knows where your project is located.
- *
- * @author mhunsicker
- */
-public interface BasicGradleUIVersion1 {
- /**
- * Call this whenever you're about to show this panel. We'll do whatever initialization is necessary.
- */
- public void aboutToShow();
-
- //
- public interface CloseInteraction {
- /**
- * This is called if gradle tasks are being executed and you want to know if we can close. Ask the user.
- *
- * @return true if the user confirms cancelling the current tasks. False if not.
- */
- public boolean promptUserToConfirmClosingWhileBusy();
- }
-
- /**
- * Call this to determine if you can close this pane. if we're busy, we'll ask the user if they want to close.
- *
- * @param closeInteraction allows us to interact with the user
- * @return true if we can close, false if not.
- */
- public boolean canClose(CloseInteraction closeInteraction);
-
- /**
- * Call this before you close the pane. This gives it an opportunity to do cleanup. You probably should call canClose before this. It gives the app a chance to cancel if its busy.
- */
- public void close();
-
- /**
- * @return the root directory of your gradle project.
- */
- public File getCurrentDirectory();
-
- /**
- * @param currentDirectory the new root directory of your gradle project.
- */
- public void setCurrentDirectory(File currentDirectory);
-
- /**
- * @return the gradle home directory. Where gradle is installed.
- */
- public File getGradleHomeDirectory();
-
- /**
- * This is called to get a custom gradle executable file. If you don't run gradle.bat or gradle shell script to run gradle, use this to specify what you do run. Note: we're going to pass it the
- * arguments that we would pass to gradle so if you don't like that, see alterCommandLineArguments. Normally, this should return null.
- *
- * @return the Executable to run gradle command or null to use the default
- */
- public File getCustomGradleExecutable();
-
- /**
- * Call this to add an additional tab to the gradle UI. You can call this at any time.
- *
- * @param index the index of where to add the tab.
- * @param gradleTabVersion1 the tab to add.
- */
- public void addTab(int index, GradleTabVersion1 gradleTabVersion1);
-
- /**
- * Call this to remove one of your own tabs from this.
- *
- * @param gradleTabVersion1 the tab to remove
- */
- public void removeTab(GradleTabVersion1 gradleTabVersion1);
-
- /**
- * @return the total number of tabs.
- */
- public int getGradleTabCount();
-
- /**
- * @param index the index of the tab
- * @return the name of the tab at the specified index.
- */
- public String getGradleTabName(int index);
-
- /**
- * Returns the index of the gradle tab with the specified name.
- *
- * @param name the name of the tab
- * @return the index of the tab or -1 if not found
- */
- public int getGradleTabIndex(String name);
-
- /**
- * @return the currently selected tab
- */
- public int getCurrentGradleTab();
-
- /**
- * Makes the specified tab the current tab.
- *
- * @param index the index of the tab.
- */
- public void setCurrentGradleTab(int index);
-
- /**
- * This allows you to add a listener that can add additional command line arguments whenever gradle is executed. This is useful if you've customized your gradle build and need to specify, for
- * example, an init script.
- *
- * @param listener the listener that modifies the command line arguments.
- */
- public void addCommandLineArgumentAlteringListener(CommandLineArgumentAlteringListenerVersion1 listener);
-
- public void removeCommandLineArgumentAlteringListener(CommandLineArgumentAlteringListenerVersion1 listener);
-
- /**
- * Call this to execute the given gradle command.
- *
- * @param commandLineArguments the command line arguments to pass to gradle.
- * @param displayName the name displayed in the UI for this command
- */
- public void executeCommand(String commandLineArguments, String displayName);
-
- /**
- * This refreshes the task tree. Useful if you know you've changed something behind gradle's back or when first displaying this UI.
- */
- public void refreshTaskTree();
-
- /**
- * @return the output lord which shows the live output of all commands being executed. You can add observers to this as well as alter how it finds file links.
- */
- public OutputUILordVersion1 getOutputLord();
-
- //these were moved to OutputUILordVersion1, but remain here for backward compatibility
- public void addOutputObserver(OutputObserverVersion1 outputObserverVersion1);
-
- public void removeOutputObserver(OutputObserverVersion1 outputObserverVersion1);
-
- /**
- * Determines if commands are currently being executed or not.
- *
- * @return true if we're busy, false if not.
- */
- public boolean isBusy();
-
- /**
- * Determines whether output is shown only when errors occur or always
- *
- * @return true to only show output if errors occur, false to show it always.
- */
- public boolean getOnlyShowOutputOnErrors();
-
- /**
- * This adds the specified component to the setup panel. It is added below the last 'default' item. You can only add 1 component here, so if you need to add multiple things, you'll have to handle
- * adding that to yourself to the one component.
- *
- * @param component the component to add.
- */
- public void setCustomPanelToSetupTab(JComponent component);
-
- /**
- * This returns an object that works with lower level gradle and contains the current projects and tasks. You can also execute tasks from it and perform certain setup.
- *
- * @return a GradleInterfaceVersion1 object. It may also be GradleInterfaceVersion2 or a future version. You can check its type and then cast it as appropriate. This allows the caller to be
- * backward compatible.
- */
- public GradleInterfaceVersion1 getGradleInterfaceVersion1();
-
- /**
- * Returns a FavoritesEditor. This is useful for getting a list of all favorites or modifying them.
- *
- * @return a FavoritesEditorVersion1. Use this to interact with the favorites.
- */
- public FavoritesEditorVersion1 getFavoritesEditor();
-}
diff --git a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/ui/CommandLineArgumentAlteringListenerVersion1.java b/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/ui/CommandLineArgumentAlteringListenerVersion1.java
deleted file mode 100644
index 50a8ef0..0000000
--- a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/ui/CommandLineArgumentAlteringListenerVersion1.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.openapi.external.ui;
-
-/**
- * This allows you to add a listener that can add additional command line arguments whenever gradle is executed. This is useful if you've customized your gradle build and need to specify, for example,
- * an init script.
- *
- * @author mhunsicker
- */
-public interface CommandLineArgumentAlteringListenerVersion1 {
- /**
- * This is called when you can add additional command line arguments. Return any additional arguments to add. This doesn't modify the existing commands.
- *
- * @param commandLineArguments the command line to execute.
- * @return any command lines to add or null to leave it alone
- */
- public String getAdditionalCommandLineArguments(String commandLineArguments);
-}
diff --git a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/ui/DualPaneUIInteractionVersion1.java b/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/ui/DualPaneUIInteractionVersion1.java
deleted file mode 100644
index ff16c62..0000000
--- a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/ui/DualPaneUIInteractionVersion1.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.openapi.external.ui;
-
-/**
- This interface holds onto our options and allows us to interact with the
- caller. This is meant to interact with the Gradle UI across class loader
- and version boundaries. That is, the open API has a single entry point
- that shouldn't change across versions. New interfaces can be expected, but
- we'll always allow 'version1'. This is to provide backward/forward compatibility.
-
- @author mhunsicker
-*/
-public interface DualPaneUIInteractionVersion1 extends GradleUIInteractionVersion1
-{
-}
diff --git a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/ui/DualPaneUIVersion1.java b/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/ui/DualPaneUIVersion1.java
deleted file mode 100644
index 153cf1c..0000000
--- a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/ui/DualPaneUIVersion1.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.openapi.external.ui;
-
-import javax.swing.JComponent;
-import java.awt.Component;
-
-/**
-This is a gradle UI that is broken into two panels: one contains a tabbed pane
- of tasks, favorites, command line, etc. The other pane contains the output.
- This is meant to simplify how an IDE plugin can interact with gradle. Specifically,
- this allows the 'main' pane to be vertical and the output pane to be horizontal.
-
- To use this, you'll want to get an instance of this from Gradle. Then setup
- your UI and add this to it via getComponent. Then call aboutToShow before
- you display your UI. Call close before you hide your UI. You'll need to set
- the current directory (at any time) so gradle knows where your project is
- located.
- */
-public interface DualPaneUIVersion1 extends BasicGradleUIVersion1 {
- /**
- Returns a component that shows the task tree tab, favorites tab, etc.
- suitable for inserting in your UI.
- @return the main component
- */
- public JComponent getMainComponent();
-
- /**
- Returns a component that shows the output of the tasks being executed.
- This is suitable for inserting in your UI.
- @return the output component
- */
- public Component getOutputPanel();
-
- /**
- * This gets the number of opened output tabs. This is used by the Idea plugin
- * to determine if it should close the entire output pane when a tab is closed
- * This doesn't determine whether or not the tabs are busy. See
- * GradleInterfaceVersion1.isBusy for that
- * @return the number of opened output tabs.
- */
- public int getNumberOfOpenedOutputTabs();
-}
diff --git a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/ui/GradleTabVersion1.java b/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/ui/GradleTabVersion1.java
deleted file mode 100644
index 02a1cf5..0000000
--- a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/ui/GradleTabVersion1.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.openapi.external.ui;
-
-import java.awt.Component;
-
-/**
-
- This represents a tab that the caller can add to the gradle UI.
-
- This is a mirror of GradleTab inside Gradle, but this is meant to aid
- backward and forward compatibility by shielding you from direct changes
- within gradle.
-
- @author mhunsicker
- */
-public interface GradleTabVersion1 {
- /*
- @return the name of this tab
- @author mhunsicker
- */
- public String getName();
-
- /*
- This is where we should create your component.
-
- @return the component
- @author mhunsicker
- */
- public Component createComponent();
-
- /*
- Notification that this component is about to be shown. Do whatever
- initialization you choose.
- @author mhunsicker
- */
- public void aboutToShow();
-}
diff --git a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/ui/GradleUIInteractionVersion1.java b/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/ui/GradleUIInteractionVersion1.java
deleted file mode 100644
index b0ff6e7..0000000
--- a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/ui/GradleUIInteractionVersion1.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.openapi.external.ui;
-
-/**
- This interface holds onto our options and allows us to interact with the
- caller. This is meant to interact with the Gradle UI across class loader
- and version boundaries. That is, the open API has a single entry point
- that shouldn't change across versions. New interfaces can be expected, but
- we'll always allow 'version1'. This is to provide backward/forward compatibility.
-
- @author mhunsicker
-*/
-public interface GradleUIInteractionVersion1 {
- /*
- This is only called once and is how we get a hold of the AlternateUIInteraction.
- @return an AlternateUIInteraction object. This cannot be null.
- @author mhunsicker
- */
- public AlternateUIInteractionVersion1 instantiateAlternateUIInteraction();
-
- /*
- This is only called once and is how we get a hold of how the owner wants
- to store preferences.
- @return a settings object. This cannot be null.
- @author mhunsicker
- */
- public SettingsNodeVersion1 instantiateSettings();
-}
diff --git a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/ui/OutputObserverVersion1.java b/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/ui/OutputObserverVersion1.java
deleted file mode 100644
index 8d90b9d..0000000
--- a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/ui/OutputObserverVersion1.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.openapi.external.ui;
-
-/**
- * <p>This interface informs you when the output pane is displaying requests. This is NOT for general output of gradle commands.
- *
- * <p>This is a mirror of OutputUILord.OutputObserver inside Gradle, but this is meant to aid backward and forward compatibility by shielding you from direct changes within gradle.
- */
-public interface OutputObserverVersion1 {
- /**
- * Notification that a request was added to the output. This means we've got some output that is useful to display. <! Name Description>
- *
- * @param requestID an ID you can use to identify this request when it is complete.
- * @param fullCommandLine the command line for the request that was added
- * @param displayName the display name of this command (often the same as the full command line)
- * @param forceOutputToBeShown true if this request wants to force its output to be shown
- */
- public void executionRequestAdded(long requestID, String fullCommandLine, String displayName, boolean forceOutputToBeShown);
-
- /**
- * Notification that a refresh task list request was added to the output. This means we've got some output that is useful to display.
- *
- * @param requestID an ID you can use to identify this request when it is complete.
- * @param forceOutputToBeShown true if this request wants to force its output to be shown
- */
- public void refreshRequestAdded(long requestID, boolean forceOutputToBeShown);
-
- /**
- * Notification that a request is complete. Note: if its canceled, you'll just get an outputTabClosed notification.
- *
- * @param requestID the ID of the request that is complete. It is given to you in executionRequestAdded or refreshRequestAdded.
- * @param wasSuccessful true if was successful, false if not or was cancelled.
- */
- public void requestComplete(long requestID, boolean wasSuccessful);
-
- /**
- * Notification that an output tab was closed, possibly because it was canceled. You might want to know this if you want to close your IDE output window when all tabs are closed.
- *
- * @param requestID the ID of the request associated with this tab. It is given to you in executionRequestAdded or refreshRequestAdded.
- */
- public void outputTabClosed(long requestID);
-}
diff --git a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/ui/OutputUILordVersion1.java b/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/ui/OutputUILordVersion1.java
deleted file mode 100644
index 42522d6..0000000
--- a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/ui/OutputUILordVersion1.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.openapi.external.ui;
-
-import java.util.List;
-import java.awt.Font;
-
-/**
- * Provides access to aspects of gradle's output
- *
- * @author mhunsicker
- */
-public interface OutputUILordVersion1 {
-
- public void setOutputTextFont(Font font);
-
- public Font getOutputTextFont();
-
- /**
- * Call this to add file extensions to look for in the output. The files will be highlighted and are clickable by the user. This results in AlternateUIInteractionVersion1.editFile or openFile
- * being called. This assumes the file path is the first thing on the line.
- *
- * @param extension the file extension
- * @param lineNumberDelimiter optional delimiter text for line number. Whatever is after this will be assumed to be a line number. We'll only parse the numbers after this so there can be other
- * stuff after the line number. Pass in null to ignore.
- */
- public void addFileExtension(String extension, String lineNumberDelimiter);
-
- /**
- * Creates a file link definition to find file paths in the output that have a known prefix and extension. The files will be highlighted and are clickable by the user. This results in
- * AlternateUIInteractionVersion1.editFile or openFile being called. It also allows for an optional line number after a delimiter. This is useful if you know a certain message always precedes a
- * file path.
- *
- * @param name the name of this file link definition. Used by tests mostly.
- * @param prefix the text that is before the file path. It should be enough to make it fairly unique
- * @param extension the expected file extension. If we don't find this extension, we do not consider the text a file's path. If there are multiple extensions, you'll have to add multiples of
- * these.
- * @param lineNumberDelimiter optional delimiter text for line number. Whatever is after this will be assumed to be a line number. We'll only parse the numbers after this so there can be other
- * stuff after the line number. Pass in null to ignore.
- */
- public void addPrefixedFileLink(String name, String prefix, String extension, String lineNumberDelimiter);
-
- /**
- * @return a list of file extensions that are highlighted in the output
- */
- public List<String> getFileExtensions();
-
- public void addOutputObserver(OutputObserverVersion1 outputObserverVersion1);
-
- public void removeOutputObserver(OutputObserverVersion1 outputObserverVersion1);
-
- /*
- This re-executes the last execution command (ignores refresh commands).
- This is potentially useful for IDEs to hook into (hotkey to execute last command).
- */
- public void reExecuteLastCommand();
-}
diff --git a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/ui/SettingsNodeVersion1.java b/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/ui/SettingsNodeVersion1.java
deleted file mode 100644
index 5cbba26..0000000
--- a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/ui/SettingsNodeVersion1.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.openapi.external.ui;
-
-import java.util.List;
-
-/**
- * Abstraction of how settings are stored. If you're implementing this, see SettingsNode for more information.
- *
- * This is a mirror of SettingsNode inside Gradle, but this is meant to aid backward and forward compatibility by shielding you from direct changes within gradle.
- *
- * @author mhunsicker
- */
-public interface SettingsNodeVersion1 {
- public void setName(String name);
-
- public String getName();
-
- public void setValue(String value);
-
- public String getValue();
-
- public void setValueOfChild(String name, String value);
-
- public String getValueOfChild(String name, String defaultValue);
-
- public int getValueOfChildAsInt(String name, int defaultValue);
-
- public void setValueOfChildAsInt(String name, int value);
-
- public boolean getValueOfChildAsBoolean(String name, boolean defaultValue);
-
- public void setValueOfChildAsBoolean(String name, boolean value);
-
- public long getValueOfChildAsLong(String name, long defaultValue);
-
- public void setValueOfChildAsLong(String name, long value);
-
- public List<SettingsNodeVersion1> getChildNodes();
-
- public List<SettingsNodeVersion1> getChildNodes(String name);
-
- public SettingsNodeVersion1 addChild(String name);
-
- public SettingsNodeVersion1 addChildIfNotPresent(String name);
-
- public SettingsNodeVersion1 getChildNode(String name);
-
- public SettingsNodeVersion1 getNodeAtPath(String... pathPortions);
-
- public void removeFromParent();
-
- public void removeAllChildren();
-}
diff --git a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/ui/SinglePaneUIInteractionVersion1.java b/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/ui/SinglePaneUIInteractionVersion1.java
deleted file mode 100644
index 28eb3a0..0000000
--- a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/ui/SinglePaneUIInteractionVersion1.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.openapi.external.ui;
-
-/*
- This interface holds onto our options and allows us to interact with the
- caller. This is meant to interact with the Gradle UI across class loader
- and version boundaries. That is, the open API has a single entry point
- that shouldn't change across versions. New interfaces can be expected, but
- we'll always allow 'version1'. This is to provide backward/forward compatibility.
-
- @author mhunsicker
-*/
-public interface SinglePaneUIInteractionVersion1 extends GradleUIInteractionVersion1
-{
-}
diff --git a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/ui/SinglePaneUIVersion1.java b/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/ui/SinglePaneUIVersion1.java
deleted file mode 100644
index 4d452d7..0000000
--- a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/ui/SinglePaneUIVersion1.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.openapi.external.ui;
-
-import javax.swing.JComponent;
-
-/*
- This is a gradle UI that is entirely within a single panel (and only a panel;
- no dialog or frame). This is meant to simplify how a plugin can interact with
- gradle.
-
- To use this, you'll want to get an instance of this from Gradle. Then setup
- your UI and add this to it via getComponent. Then call aboutToShow before
- you display your UI. Call close before you hide your UI. You'll need to set
- the current directory (at any time) so gradle knows where your project is
- located.
-
- @author mhunsicker
- */
-public interface SinglePaneUIVersion1 extends BasicGradleUIVersion1 {
- /**
- Returns this panel as a Swing object suitable for inserting in your UI.
- @return the main component
- */
- public JComponent getComponent();
-}
diff --git a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/ui/UIFactory.java b/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/ui/UIFactory.java
deleted file mode 100644
index 8d97a88..0000000
--- a/subprojects/open-api/src/main/groovy/org/gradle/openapi/external/ui/UIFactory.java
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.openapi.external.ui;
-
-import org.gradle.openapi.external.ExternalUtility;
-
-import java.io.File;
-import java.lang.reflect.Constructor;
-
-/**
- * This loads up the main gradle UI. This is intended to be used as a plugin inside another application (like an IDE) in a dynamic fashion. If you're always going to ship the entire plugin with the
- * entire Gradle dist, you don't need to use this. This is meant to dynamically load Gradle from its dist. The idea is that you point your plugin to a Gradle dist and then can always load the latest
- * version.
- *
- * @author mhunsicker
- */
-public class UIFactory {
- private static final String UIWRAPPER_FACTORY_CLASS_NAME = "org.gradle.openapi.wrappers.UIWrapperFactory";
-
- /**
- * Call this to instantiate a self-contained gradle UI. That is, everything in the UI is in a single panel (versus 2 panels one for the tasks and one for the output). This will load gradle via
- * reflection, instantiate the UI and all required gradle-related classes.
- *
- * <p>Note: this function is meant to be backward and forward compatible. So this signature should not change at all, however, it may take and return objects that implement ADDITIONAL interfaces.
- * That is, it will always return SinglePaneUIVersion1, but it may also be an object that implements SinglePaneUIVersion2 (notice the 2). The caller will need to dynamically determine that. The
- * SinglePaneUIInteractionVersion1 may take an object that also implements SinglePaneUIInteractionVersion2. If so, we'll dynamically determine that and handle it. Of course, this all depends on
- * what happens in the future.
- *
- * @param parentClassLoader Your classloader. Probably the classloader of whatever class is calling this.
- * @param gradleHomeDirectory the root directory of a gradle installation
- * @param showDebugInfo true to show some additional information that may be helpful diagnosing problems is this fails
- * @return the UI object.
- * @deprecated Use the tooling API instead.
- */
- @Deprecated
- public static SinglePaneUIVersion1 createSinglePaneUI(ClassLoader parentClassLoader, File gradleHomeDirectory, final SinglePaneUIInteractionVersion1 interaction, boolean showDebugInfo)
- throws Exception {
- //much of this function is exception handling so if we can't obtain it via the newer factory method, then
- //we'll try the old way, but we want to report the original exception if we can't do it either way.
- Exception viaFactoryException = null;
- SinglePaneUIVersion1 gradleUI = null;
-
- //first, try it the new way
- try {
- gradleUI = createSinglePaneUIViaFactory(parentClassLoader, gradleHomeDirectory, interaction, showDebugInfo);
- } catch (Exception e) {
- //we might ignore this. It means we're probably using an older version of gradle. That case is handled below.
- //If not, this exception will be thrown at the end.
- viaFactoryException = e;
- }
-
- //try it the old way
- if (gradleUI == null) {
- gradleUI = createSinglePaneUIOldWay(parentClassLoader, gradleHomeDirectory, interaction, showDebugInfo);
- }
-
- //if we still don't have a gradle ui and we have an exception from using the factory, throw it. If we
- //got an exception using the 'old way', it would have been thrown already and we wouldn't be here.
- if (gradleUI == null && viaFactoryException != null) {
- throw viaFactoryException;
- }
-
- return gradleUI;
- }
-
- /**
- * This function uses a factory to instantiate the UI. The factory is located with the version of gradle pointed to by gradleHomeDirectory and thus allows the version of gradle being loaded to make
- * decisions about how to instantiate the UI. This is needed as multiple versions of the UI are being used.
- */
- private static SinglePaneUIVersion1 createSinglePaneUIViaFactory(ClassLoader parentClassLoader, File gradleHomeDirectory, final SinglePaneUIInteractionVersion1 interaction, boolean showDebugInfo)
- throws Exception {
- //load the class in gradle that wraps our return interface and handles versioning issues.
- Class soughtClass = ExternalUtility.loadGradleClass(UIWRAPPER_FACTORY_CLASS_NAME, parentClassLoader, gradleHomeDirectory, showDebugInfo);
- if (soughtClass == null) {
- return null;
- }
-
- Class[] argumentClasses = new Class[]{SinglePaneUIInteractionVersion1.class, boolean.class};
-
- Object gradleUI = ExternalUtility.invokeStaticMethod(soughtClass, "createSinglePaneUI", argumentClasses, interaction, showDebugInfo);
- return (SinglePaneUIVersion1) gradleUI;
- }
-
- /**
- * This function uses an early way (early 0.9 pre-release and sooner) of instantiating the UI and should no longer be used. It unfortunately is tied to a single wrapper class instance (which it
- * tries to directly instantiate). This doesn't allow the Gradle UI to adaptively determine what to instantiate.
- */
- private static SinglePaneUIVersion1 createSinglePaneUIOldWay(ClassLoader parentClassLoader, File gradleHomeDirectory, final SinglePaneUIInteractionVersion1 singlePaneUIArguments,
- boolean showDebugInfo) throws Exception {
- ClassLoader bootStrapClassLoader = ExternalUtility.getGradleClassloader(parentClassLoader, gradleHomeDirectory, showDebugInfo);
- Thread.currentThread().setContextClassLoader(bootStrapClassLoader);
-
- //load the class in gradle that wraps our return interface and handles versioning issues.
- Class soughtClass = null;
- try {
- soughtClass = bootStrapClassLoader.loadClass("org.gradle.openapi.wrappers.ui.SinglePaneUIWrapper");
- } catch (NoClassDefFoundError e) { //might be a version mismatch
- e.printStackTrace();
- return null;
- } catch (ClassNotFoundException e) { //might be a version mismatch
- e.printStackTrace();
- }
- if (soughtClass == null) {
- return null;
- }
-
- //instantiate it.
- Constructor constructor = null;
- try {
- constructor = soughtClass.getDeclaredConstructor(SinglePaneUIInteractionVersion1.class);
- } catch (NoSuchMethodException e) {
- e.printStackTrace();
- System.out.println("Dumping available constructors on " + soughtClass.getName() + "\n" + ExternalUtility.dumpConstructors(soughtClass));
-
- throw e;
- }
- Object singlePaneUI = constructor.newInstance(singlePaneUIArguments);
- return (SinglePaneUIVersion1) singlePaneUI;
- }
-
- /**
- * Call this to instantiate a gradle UI that contains the main tab control separate from the output panel. This allows you to position the output however you like. For example: you can place the
- * main pane along the side going vertically and you can place the output pane along the bottom going horizontally. This will load gradle via reflection, instantiate the UI and all required
- * gradle-related classes.
- *
- * <p>Note: this function is meant to be backward and forward compatible. So this signature should not change at all, however, it may take and return objects that implement ADDITIONAL interfaces.
- * That is, it will always return SinglePaneUIVersion1, but it may also be an object that implements SinglePaneUIVersion2 (notice the 2). The caller will need to dynamically determine that. The
- * SinglePaneUIInteractionVersion1 may take an object that also implements SinglePaneUIInteractionVersion2. If so, we'll dynamically determine that and handle it. Of course, this all depends on
- * what happens in the future.
- *
- * @param parentClassLoader Your classloader. Probably the classloader of whatever class is calling this.
- * @param gradleHomeDirectory the root directory of a gradle installation
- * @param interaction this is how we interact with the caller.
- * @param showDebugInfo true to show some additional information that may be helpful diagnosing problems is this fails
- * @return the UI object.
- * @author mhunsicker
- * @deprecated Use the tooling API instead.
- */
- @Deprecated
- public static DualPaneUIVersion1 createDualPaneUI(ClassLoader parentClassLoader, File gradleHomeDirectory, final DualPaneUIInteractionVersion1 interaction, boolean showDebugInfo)
- throws Exception {
- //much of this function is exception handling so if we can't obtain it via the newer factory method, then
- //we'll try the old way, but we want to report the original exception if we can't do it either way.
- Exception viaFactoryException = null;
- DualPaneUIVersion1 gradleUI = null;
-
- //first, try it the new way
- try {
- gradleUI = createDualPaneUIViaFactory(parentClassLoader, gradleHomeDirectory, interaction, showDebugInfo);
- } catch (Exception e) {
- //we might ignore this. It means we're probably using an older version of gradle. That case is handled below.
- //If not, this exception will be thrown at the end.
- viaFactoryException = e;
- }
-
- //try it the old way
- if (gradleUI == null) {
- gradleUI = createDualPaneUIOldWay(parentClassLoader, gradleHomeDirectory, interaction, showDebugInfo);
- }
-
- //if we still don't have a gradle ui and we have an exception from using the factory, throw it. If we
- //got an exception using the 'old way', it would have been thrown already and we wouldn't be here.
- if (gradleUI == null && viaFactoryException != null) {
- throw viaFactoryException;
- }
-
- return gradleUI;
- }
-
- /**
- * This function uses a factory to instantiate the UI. The factory is located with the version of gradle pointed to by gradleHomeDirectory and thus allows the version of gradle being loaded to make
- * decisions about how to instantiate the UI. This is needed as multiple versions of the UI are being used.
- * @deprecated Use the tooling API instead.
- */
- @Deprecated
- public static DualPaneUIVersion1 createDualPaneUIViaFactory(ClassLoader parentClassLoader, File gradleHomeDirectory, final DualPaneUIInteractionVersion1 interaction, boolean showDebugInfo)
- throws Exception {
- //load the class in gradle that wraps our return interface and handles versioning issues.
- Class soughtClass = ExternalUtility.loadGradleClass(UIWRAPPER_FACTORY_CLASS_NAME, parentClassLoader, gradleHomeDirectory, showDebugInfo);
- if (soughtClass == null) {
- return null;
- }
-
- Class[] argumentClasses = new Class[]{DualPaneUIInteractionVersion1.class, boolean.class};
-
- Object gradleUI = ExternalUtility.invokeStaticMethod(soughtClass, "createDualPaneUI", argumentClasses, interaction, showDebugInfo);
- return (DualPaneUIVersion1) gradleUI;
- }
-
- /**
- * This function uses an early way (early 0.9 pre-release and sooner) of instantiating the UI and should no longer be used. It unfortunately is tied to a single wrapper class instance (which it
- * tries to directly instantiate). This doesn't allow the Gradle UI to adaptively determine what to instantiate.
- */
- private static DualPaneUIVersion1 createDualPaneUIOldWay(ClassLoader parentClassLoader, File gradleHomeDirectory, final DualPaneUIInteractionVersion1 interaction, boolean showDebugInfo)
- throws Exception {
- ClassLoader bootStrapClassLoader = ExternalUtility.getGradleClassloader(parentClassLoader, gradleHomeDirectory, showDebugInfo);
- Thread.currentThread().setContextClassLoader(bootStrapClassLoader);
-
- //load the class in gradle that wraps our return interface and handles versioning issues.
- Class soughtClass = null;
- try {
- soughtClass = bootStrapClassLoader.loadClass("org.gradle.openapi.wrappers.ui.DualPaneUIWrapper");
- } catch (NoClassDefFoundError e) { //might be a version mismatch
- e.printStackTrace();
- return null;
- } catch (ClassNotFoundException e) { //might be a version mismatch
- e.printStackTrace();
- }
- if (soughtClass == null) {
- return null;
- }
-
- //instantiate it.
- Constructor constructor = null;
- try {
- constructor = soughtClass.getDeclaredConstructor(DualPaneUIInteractionVersion1.class);
- } catch (NoSuchMethodException e) {
- e.printStackTrace();
- System.out.println("Dumping available constructors on " + soughtClass.getName() + "\n" + ExternalUtility.dumpConstructors(soughtClass));
-
- throw e;
- }
- Object gradleUI = constructor.newInstance(interaction);
- return (DualPaneUIVersion1) gradleUI;
- }
-}
diff --git a/subprojects/open-api/src/main/java/org/gradle/foundation/BootstrapLoader.java b/subprojects/open-api/src/main/java/org/gradle/foundation/BootstrapLoader.java
new file mode 100644
index 0000000..7f02c5e
--- /dev/null
+++ b/subprojects/open-api/src/main/java/org/gradle/foundation/BootstrapLoader.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.foundation;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ This handles the work of loading gradle dynamically. Due to jar version issues,
+ you can't just load all jar files.
+
+ This does NOT require any system or environment variables to be set.
+
+ To use this, instantiate this, then call one of the initialize functions.
+ Now you can get the class loader to load whatever classes you like.
+
+ @deprecated No replacement
+ */
+ at Deprecated
+public class BootstrapLoader {
+ private URLClassLoader libClassLoader;
+
+ public void initialize(File gradleHome, boolean bootStrapDebug) throws Exception {
+ initialize(ClassLoader.getSystemClassLoader().getParent(), gradleHome, false, true, bootStrapDebug);
+ }
+
+ /*
+ Call this to initialize gradle.
+ @param parentClassloader a parent class loader. Probably whatever class loader
+ is used by the caller.
+ @param gradleHome the root directory where gradle is installed. This
+ directory should have a 'bin' child directory.
+ @param useParentLastClassLoader true to use a class loader that will delegate
+ to the parent only if it can't find it locally. This
+ should only be true if you're trying to load gradle
+ dynamically from another application.
+ @param loadOpenAPI True to load the gradle open API, false not to.
+ If you're calling this from a tool using the OpenAPI,
+ then you've probably already loaded it, so pass in false
+ here, otherwise, pass in true.
+ @param bootStrapDebug true to output debug information about the loading
+ process.
+ @throws Exception if something goes wrong.
+ */
+ public void initialize(ClassLoader parentClassloader, File gradleHome, boolean useParentLastClassLoader, boolean loadOpenAPI, boolean bootStrapDebug) throws Exception {
+ if (gradleHome == null || !gradleHome.exists()) {
+ throw new RuntimeException("Gradle home not defined!");
+ }
+
+ if (bootStrapDebug) {
+ System.out.println("Gradle Home is declared by system property gradle.home to: " + gradleHome.getAbsolutePath());
+ }
+
+ System.setProperty("gradle.home", gradleHome.getAbsolutePath());
+
+ List<URL> loggingJars = toUrl(getLoggingJars());
+
+ List<File> nonLoggingJarFiles = getNonLoggingJars();
+ removeUnwantedJarFiles(nonLoggingJarFiles, loadOpenAPI);
+ List<URL> nonLoggingJars = toUrl(nonLoggingJarFiles);
+
+ if (bootStrapDebug) {
+ System.out.println("Parent Classloader of new context classloader is: " + parentClassloader);
+ System.out.println("Adding the following files to new logging classloader: " + loggingJars);
+ System.out.println("Adding the following files to new lib classloader: " + nonLoggingJars);
+ }
+
+ URLClassLoader loggingClassLoader = new URLClassLoader(loggingJars.toArray(new URL[loggingJars.size()]), parentClassloader);
+
+ if (useParentLastClassLoader) {
+ libClassLoader = new ParentLastClassLoader(nonLoggingJars.toArray(new URL[nonLoggingJars.size()]), loggingClassLoader);
+ } else {
+ libClassLoader = new URLClassLoader(nonLoggingJars.toArray(new URL[nonLoggingJars.size()]), loggingClassLoader);
+ }
+
+ if (bootStrapDebug) {
+ System.out.println("Logging class loader: " + loggingClassLoader);
+ System.out.println("Lib class loader: " + libClassLoader);
+ }
+ }
+
+ public static File[] getGradleHomeLibClasspath() {
+ File gradleHomeLib = new File(System.getProperty("gradle.home") + "/lib");
+ if (gradleHomeLib.isDirectory()) {
+ return gradleHomeLib.listFiles();
+ }
+ return new File[0];
+ }
+
+ public static List<File> getNonLoggingJars() {
+ List<File> pathElements = new ArrayList<File>();
+ for (File file : getGradleClasspath()) {
+ if (!isLogLib(file)) {
+ pathElements.add(file);
+ }
+ }
+ return pathElements;
+ }
+
+ public static List<File> getLoggingJars() {
+ List<File> pathElements = new ArrayList<File>();
+ for (File file : getGradleClasspath()) {
+ if (isLogLib(file)) {
+ pathElements.add(file);
+ }
+ }
+ return pathElements;
+ }
+
+ private static boolean isLogLib(File file) {
+ return file.getName().startsWith("logback") || file.getName().startsWith("slf4j");
+ }
+
+ public static List<File> getGradleClasspath() {
+ File customGradleBin = null;
+ List<File> pathElements = new ArrayList<File>();
+ if (System.getProperty("gradle.bootstrap.gradleBin") != null) {
+ customGradleBin = new File(System.getProperty("gradle.bootstrap.gradleBin"));
+ pathElements.add(customGradleBin);
+ }
+ for (File homeLibFile : getGradleHomeLibClasspath()) {
+ if (homeLibFile.isFile() && !(customGradleBin != null && homeLibFile.getName().startsWith("gradle-"))) {
+ pathElements.add(homeLibFile);
+ }
+ }
+ return pathElements;
+ }
+
+ /*
+ This removes unwanted jar files. At the time of this writing, we're only
+ interested in the open api jar.
+
+ @param nonLoggingJarFiles a list of jar files
+ @param loadOpenAPI true to keep the open api jar, false to remove it.
+ */
+ private void removeUnwantedJarFiles(List<File> nonLoggingJarFiles, boolean loadOpenAPI) {
+ if (loadOpenAPI) {
+ return;
+ }
+
+ Iterator<File> iterator = nonLoggingJarFiles.iterator();
+ while (iterator.hasNext()) {
+ File file = iterator.next();
+ if (file.getName().startsWith("gradle-open-api-")) {
+ iterator.remove();
+ }
+ }
+ }
+
+ /*
+ Call this to get the class loader you can use to load gradle classes.
+ @return a URLClassLoader
+ */
+ public URLClassLoader getClassLoader() {
+ return libClassLoader;
+ }
+
+ public Class load(String classPath) throws Exception {
+ return libClassLoader.loadClass(classPath);
+ }
+
+ private static List<URL> toUrl(List<File> files) throws MalformedURLException {
+ List<URL> result = new ArrayList<URL>();
+ for (File file : files) {
+ result.add(file.toURI().toURL());
+ }
+ return result;
+ }
+}
diff --git a/subprojects/open-api/src/main/java/org/gradle/foundation/ParentLastClassLoader.java b/subprojects/open-api/src/main/java/org/gradle/foundation/ParentLastClassLoader.java
new file mode 100644
index 0000000..0d95db5
--- /dev/null
+++ b/subprojects/open-api/src/main/java/org/gradle/foundation/ParentLastClassLoader.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.foundation;
+
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.net.URLStreamHandlerFactory;
+
+/**
+ * <p>This class loader delegates to the parent class loader ONLY if it cannot find it itself. This is meant to solve classloading issues when running something as, say, a plugin inside an application
+ * that may have already loaded a different version of some required jars. This makes sure it looks locally first. This is the opposite of a ClassLoader's typical behavior, but it necessary when you
+ * can't control the environment in which you're running.
+ *
+ * <p>Using this class can be very dangerous. You must carefully make sure you understand the ramifications of using this. You should also probably make this the first class loader between your plugin
+ * and the plugin's owner.
+ * @deprecated No replacement
+ */
+ at Deprecated
+public class ParentLastClassLoader extends URLClassLoader {
+ public ParentLastClassLoader(URL[] urls, ClassLoader parent) {
+ super(urls, parent);
+ }
+
+ public ParentLastClassLoader(URL[] urls) {
+ super(urls);
+ }
+
+ public ParentLastClassLoader(URL[] urls, ClassLoader parent, URLStreamHandlerFactory factory) {
+ super(urls, parent, factory);
+ }
+
+ /*
+ This has been overridden to look at the parent class loader last.
+ */
+ @Override
+ public Class<?> loadClass(String name) throws ClassNotFoundException {
+ // First check whether it's already been loaded, if so use it
+ Class loadedClass = findLoadedClass(name);
+
+ // Not loaded, try to load it
+ if (loadedClass == null) {
+ try {
+ // Ignore parent delegation and just try to load locally
+ loadedClass = findClass(name);
+ } catch (ClassNotFoundException e) {
+ // Swallow exception - does not exist locally
+ }
+
+ // If not found locally, use normal parent delegation in URLClassloader
+ if (loadedClass == null) {
+ // throws ClassNotFoundException if not found in delegation hierarchy at all
+ loadedClass = super.loadClass(name);
+ }
+ }
+ // will never return null (ClassNotFoundException will be thrown)
+ return loadedClass;
+ }
+}
+
diff --git a/subprojects/open-api/src/main/java/org/gradle/openapi/external/ExternalUtility.java b/subprojects/open-api/src/main/java/org/gradle/openapi/external/ExternalUtility.java
new file mode 100644
index 0000000..b4743ba
--- /dev/null
+++ b/subprojects/open-api/src/main/java/org/gradle/openapi/external/ExternalUtility.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.openapi.external;
+
+import org.gradle.foundation.BootstrapLoader;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.util.regex.Pattern;
+
+/**
+ * Utility functions required by the OpenAPI
+ * @deprecated No replacement
+ */
+ at Deprecated
+public class ExternalUtility {
+ private static final Pattern GRADLE_CORE_PATTERN = Pattern.compile("^gradle-core-\\d.*\\.jar$");
+
+ /**
+ * Call this to get a classloader that has loaded gradle.
+ *
+ * @param parentClassLoader Your classloader. Probably the classloader of whatever class is calling this.
+ * @param gradleHomeDirectory the root directory of a gradle installation
+ * @param showDebugInfo true to show some additional information that may be helpful diagnosing problems is this fails
+ * @return a classloader that has loaded gradle and all of its dependencies.
+ */
+
+ public static ClassLoader getGradleClassloader(ClassLoader parentClassLoader, File gradleHomeDirectory, boolean showDebugInfo) throws Exception {
+ File gradleJarFile = getGradleJar(gradleHomeDirectory);
+ if (gradleJarFile == null) {
+ throw new RuntimeException("Not a valid gradle home directory '" + gradleHomeDirectory.getAbsolutePath() + "'");
+ }
+
+ System.setProperty("gradle.home", gradleHomeDirectory.getAbsolutePath());
+
+ BootstrapLoader bootstrapLoader = new BootstrapLoader();
+ bootstrapLoader.initialize(parentClassLoader, gradleHomeDirectory, true, false, showDebugInfo);
+ return bootstrapLoader.getClassLoader();
+ }
+
+ /**
+ * This locates the gradle jar. We do NOT want the gradle-wrapper jar.
+ *
+ * @param gradleHomeDirectory the root directory of a gradle installation. We're expecting this to have a child directory named 'lib'.
+ * @return the gradle jar file. Null if we didn't find it.
+ */
+ public static File getGradleJar(File gradleHomeDirectory) {
+ File libDirectory = new File(gradleHomeDirectory, "lib");
+ if (!libDirectory.exists()) {
+ return null;
+ }
+
+ //try to get the gradle.jar. It'll be "gradle-[version].jar"
+ File[] files = libDirectory.listFiles(new FileFilter() {
+ public boolean accept(File file) {
+ return GRADLE_CORE_PATTERN.matcher(file.getName()).matches();
+ }
+ });
+
+ if (files == null || files.length == 0) {
+ return null;
+ }
+
+ //if they've given us a directory with multiple gradle jars, tell them. We won't know which one to use.
+ if (files.length > 1) {
+ throw new RuntimeException("Installation has multiple gradle jars. Cannot determine which one to use. Found files: " + createFileNamesString(files));
+ }
+
+ return files[0];
+ }
+
+ private static StringBuilder createFileNamesString(File[] files) {
+ StringBuilder fileNames = new StringBuilder();
+ for (File f : files) {
+ fileNames.append(f.getAbsolutePath() + ", ");
+ }
+ fileNames.delete(fileNames.length() - 2, fileNames.length()); // Remove the trailing ', '
+ return fileNames;
+ }
+
+ //just a function to help debugging. If we can't find the constructor we want, this dumps out what is available.
+
+ public static String dumpConstructors(Class classInQuestion) {
+ StringBuilder builder = new StringBuilder();
+ Constructor[] constructors = classInQuestion.getConstructors();
+ for (int index = 0; index < constructors.length; index++) {
+ Constructor constructor = constructors[index];
+ builder.append(constructor).append('\n');
+ }
+
+ return builder.toString();
+ }
+
+ public static String dumpMethods(Class classInQuestion) {
+ StringBuilder builder = new StringBuilder();
+
+ Method[] methods = classInQuestion.getMethods();
+ for (int index = 0; index < methods.length; index++) {
+ Method method = methods[index];
+ builder.append(method).append('\n');
+ }
+
+ return builder.toString();
+ }
+
+ /**
+ * This attempts to load the a class from the specified gradle home directory.
+ *
+ * @param classToLoad the full path to the class to load
+ * @param parentClassLoader Your classloader. Probably the classloader of whatever class is calling this.
+ * @param gradleHomeDirectory the root directory of a gradle installation
+ * @param showDebugInfo true to show some additional information that may be helpful diagnosing problems is this fails
+ */
+ public static Class loadGradleClass(String classToLoad, ClassLoader parentClassLoader, File gradleHomeDirectory, boolean showDebugInfo) throws Exception {
+ ClassLoader bootStrapClassLoader = getGradleClassloader(parentClassLoader, gradleHomeDirectory, showDebugInfo);
+ Thread.currentThread().setContextClassLoader(bootStrapClassLoader);
+
+ //load the class in gradle that wraps our return interface and handles versioning issues.
+ try {
+ return bootStrapClassLoader.loadClass(classToLoad);
+ } catch (NoClassDefFoundError e) { //might be a version mismatch
+ e.printStackTrace();
+ return null;
+ } catch (Throwable e) { //might be a version mismatch
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ /**
+ * This wraps up invoking a static method into a single call.
+ *
+ * @param classToInvoke the class that has the method
+ * @param methodName the name of the method to invoke
+ * @param argumentsClasses the classes of the arguments (we can't determine this from the argumentValues because they can be of class A, but implement class B and B is be the argument type of the
+ * method in question
+ * @param argumentValues the values of the arguments.
+ * @return the return value of invoking the method.
+ */
+ public static Object invokeStaticMethod(Class classToInvoke, String methodName, Class[] argumentsClasses, Object... argumentValues) throws Exception {
+ Method method = null;
+ try {
+ method = classToInvoke.getDeclaredMethod(methodName, argumentsClasses);
+ } catch (NoSuchMethodException e) {
+ e.printStackTrace();
+ System.out.println("Dumping available methods on " + classToInvoke.getName() + "\n" + ExternalUtility.dumpMethods(classToInvoke));
+ throw e;
+ }
+ return method.invoke(null, argumentValues);
+ }
+}
diff --git a/subprojects/open-api/src/main/java/org/gradle/openapi/external/foundation/GradleInterfaceVersion1.java b/subprojects/open-api/src/main/java/org/gradle/openapi/external/foundation/GradleInterfaceVersion1.java
new file mode 100644
index 0000000..5d1d827
--- /dev/null
+++ b/subprojects/open-api/src/main/java/org/gradle/openapi/external/foundation/GradleInterfaceVersion1.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.openapi.external.foundation;
+
+import org.gradle.openapi.external.ui.CommandLineArgumentAlteringListenerVersion1;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ * This is an abstraction from Gradle that allows you to retrieve projects and views from it.
+ *
+ * This is a mirror of GradlePluginLord inside Gradle, but this is meant to aid backward and forward compatibility by shielding you from direct changes within gradle.
+ * @deprecated No replacement
+ */
+ at Deprecated
+public interface GradleInterfaceVersion1 {
+
+ /**
+ * @return the root projects. It probably only has one.
+ */
+ public List<ProjectVersion1> getRootProjects();
+
+ /**
+ * This refreshes the projects and task list.
+ */
+ public void refreshTaskTree();
+
+ /**
+ * Determines if commands are currently being executed or not.
+ *
+ * @return true if we're busy, false if not.
+ */
+ public boolean isBusy();
+
+ /**
+ * Call this to execute the given gradle command.
+ *
+ * @param commandLineArguments the command line arguments to pass to gradle.
+ * @param displayName the name displayed in the UI for this command
+ */
+ public void executeCommand(String commandLineArguments, String displayName);
+
+ /**
+ * @return the root directory of your gradle project.
+ */
+ public File getCurrentDirectory();
+
+ /**
+ * @param currentDirectory the new root directory of your gradle project.
+ */
+ public void setCurrentDirectory(File currentDirectory);
+
+ /**
+ * @return the gradle home directory. Where gradle is installed.
+ */
+ public File getGradleHomeDirectory();
+
+ /**
+ * This is called to get a custom gradle executable file. If you don't run gradle.bat or gradle shell script to run gradle, use this to specify what you do run. Note: we're going to pass it the
+ * arguments that we would pass to gradle so if you don't like that, see alterCommandLineArguments. Normally, this should return null.
+ *
+ * @return the Executable to run gradle command or null to use the default
+ */
+ public File getCustomGradleExecutable();
+
+ /**
+ * This allows you to add a listener that can add additional command line arguments whenever gradle is executed. This is useful if you've customized your gradle build and need to specify, for
+ * example, an init script.
+ *
+ * @param listener the listener that modifies the command line arguments.
+ */
+ public void addCommandLineArgumentAlteringListener(CommandLineArgumentAlteringListenerVersion1 listener);
+
+ public void removeCommandLineArgumentAlteringListener(CommandLineArgumentAlteringListenerVersion1 listener);
+}
diff --git a/subprojects/open-api/src/main/java/org/gradle/openapi/external/foundation/GradleInterfaceVersion2.java b/subprojects/open-api/src/main/java/org/gradle/openapi/external/foundation/GradleInterfaceVersion2.java
new file mode 100644
index 0000000..6250aab
--- /dev/null
+++ b/subprojects/open-api/src/main/java/org/gradle/openapi/external/foundation/GradleInterfaceVersion2.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.openapi.external.foundation;
+
+import org.gradle.openapi.external.foundation.favorites.FavoriteTaskVersion1;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ * This is an abstraction from Gradle that allows you to retrieve projects and views from it.
+ *
+ * This is a mirror of GradlePluginLord inside Gradle, but this is meant to aid backward and forward compatibility by shielding you from direct changes within gradle.
+ * @deprecated No replacement
+ */
+ at Deprecated
+public interface GradleInterfaceVersion2 extends GradleInterfaceVersion1 {
+
+ /**
+ * @return the version of gradle being run. This is basically the version from the jar file.
+ */
+ public String getVersion();
+
+ /**
+ * This refreshes the projects and task list.
+ */
+ public RequestVersion1 refreshTaskTree2();
+
+ /**
+ * This refreshes the task tree. Useful if you know you've changed something behind gradle's back or when first displaying this UI.
+ *
+ * @param additionalCommandLineArguments additional command line arguments to be passed to gradle when refreshing the task tree.
+ * @return the request object. Useful if you want to track its completion via a RequestObserver
+ */
+ public RequestVersion1 refreshTaskTree2(String additionalCommandLineArguments);
+
+ /**
+ * Call this to execute the given gradle command.
+ *
+ * @param commandLineArguments the command line arguments to pass to gradle.
+ * @param displayName the name displayed in the UI for this command
+ * @return the request object. Useful if you want to track its completion via a RequestObserver
+ */
+ public RequestVersion1 executeCommand2(String commandLineArguments, String displayName);
+
+ /**
+ * Executes several favorites commands at once as a single command. This has the affect of simply concatenating all the favorite command lines into a single line.
+ *
+ * @param favorites a list of favorites. If just one favorite, it executes it normally. If multiple favorites, it executes them all at once as a single command. This blindly concatenates them so
+ * it may wind up with duplicate tasks on the command line.
+ * @return the request object. Useful if you want to track its completion via a RequestObserver
+ */
+ public RequestVersion1 executeFavorites(List<FavoriteTaskVersion1> favorites);
+
+ /**
+ * Sets a custom gradle executable. See getCustomGradleExecutable
+ *
+ * @param customGradleExecutor the path to an executable (or script/batch file)
+ */
+ public void setCustomGradleExecutable(File customGradleExecutor);
+
+ /**
+ * Adds an observer that is notified when Gradle commands are executed and completed.
+ *
+ * @param observer the observer that is notified
+ */
+ public void addRequestObserver(RequestObserverVersion1 observer);
+
+ /**
+ * Removes a request observer when you no longer wish to receive notifications about Gradle command being executed.
+ *
+ * @param observer the observer to remove
+ */
+ public void removeRequestObserver(RequestObserverVersion1 observer);
+}
\ No newline at end of file
diff --git a/subprojects/open-api/src/main/java/org/gradle/openapi/external/foundation/ProjectVersion1.java b/subprojects/open-api/src/main/java/org/gradle/openapi/external/foundation/ProjectVersion1.java
new file mode 100644
index 0000000..16f00fb
--- /dev/null
+++ b/subprojects/open-api/src/main/java/org/gradle/openapi/external/foundation/ProjectVersion1.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.openapi.external.foundation;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ * This is an abstraction of a Gradle project
+ *
+ * This is a mirror of ProjectView inside Gradle, but this is meant to aid backward and forward compatibility by shielding you from direct changes within gradle.
+ * @deprecated No replacement
+ */
+ at Deprecated
+public interface ProjectVersion1 {
+
+ /**
+ * @return the name of this project
+ */
+ public String getName();
+
+ /**
+ * @return The full project name. This is just the project name if its off of the root. Otherwise, its all of its ancestors separated by colons with this project being last.
+ */
+ public String getFullProjectName();
+
+ /**
+ * @return the TaskVersion1 objects associated with this project
+ */
+ public List<TaskVersion1> getTasks();
+
+ /**
+ * @return the .gradle file this project is defined in
+ */
+ public File getFile();
+
+ /**
+ * @return the sub projects of this project
+ */
+ public List<ProjectVersion1> getSubProjects();
+
+ /**
+ * @return the parent of this project if this is a sub project. Otherwise, null
+ */
+ public ProjectVersion1 getParentProject();
+
+ /**
+ * @return a list of projects that this project depends on.
+ */
+ public List<ProjectVersion1> getDependantProjects();
+
+ public ProjectVersion1 getSubProject(String name);
+
+ public ProjectVersion1 getSubProjectFromFullPath(String fullProjectName);
+
+ public TaskVersion1 getTask(String name);
+
+ /**
+ * Builds a list of default tasks. These are defined by specifying
+ *
+ * defaultTasks 'task name'
+ *
+ * in the gradle file. There can be multiple default tasks. This only returns default tasks directly for this project and does not return them for subprojects.
+ *
+ * @return a list of default tasks or an empty list if none exist
+ */
+ public List<TaskVersion1> getDefaultTasks();
+
+ public TaskVersion1 getTaskFromFullPath(String fullTaskName);
+}
diff --git a/subprojects/open-api/src/main/java/org/gradle/openapi/external/foundation/RequestObserverVersion1.java b/subprojects/open-api/src/main/java/org/gradle/openapi/external/foundation/RequestObserverVersion1.java
new file mode 100644
index 0000000..da6a2aa
--- /dev/null
+++ b/subprojects/open-api/src/main/java/org/gradle/openapi/external/foundation/RequestObserverVersion1.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.openapi.external.foundation;
+
+/**
+ * This allows you to observer when Gradle commands are executed/complete. It is an abstraction of a GradlePluginLord.RequestObserver.
+ *
+ * <p>This is a mirror of GradlePluginLord.RequestObserver inside Gradle, but this is meant to aid backward and forward compatibility by shielding you from direct changes within gradle.
+ * @deprecated No replacement
+ */
+ at Deprecated
+public interface RequestObserverVersion1 {
+
+ /**
+ * Notification that an execution request was added to the queue. This is the normal request that initiates a gradle command.
+ *
+ * @param request the request that was added
+ */
+ public void executionRequestAdded(RequestVersion1 request);
+
+ /**
+ * Notification that a refresh request was added to the queue. This type of request updates the task tree.
+ */
+ public void refreshRequestAdded(RequestVersion1 request);
+
+ /**
+ * Notification that a command is about to be executed. This is mostly useful for IDE's that may need to save their files. This is always called after a request has been added to the queue.
+ */
+ public void aboutToExecuteRequest(RequestVersion1 request);
+
+ /**
+ * Notification that a request has completed execution.
+ *
+ * @param request the original request containing the command that was executed
+ * @param result the result of the command
+ * @param output the output from gradle executing the command
+ */
+ public void requestExecutionComplete(RequestVersion1 request, int result, String output);
+}
diff --git a/subprojects/open-api/src/main/java/org/gradle/openapi/external/foundation/RequestVersion1.java b/subprojects/open-api/src/main/java/org/gradle/openapi/external/foundation/RequestVersion1.java
new file mode 100644
index 0000000..27678d4
--- /dev/null
+++ b/subprojects/open-api/src/main/java/org/gradle/openapi/external/foundation/RequestVersion1.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.openapi.external.foundation;
+
+/**
+ * This represents an execution or refresh request sent to Gradle. Execution requests are
+ * just Gradle commands (what would be the command line arguments). A refresh request is
+ * what updates the task tree.
+ *
+ * This is a mirror of Request inside Gradle, but this is meant to aid backward and forward compatibility by shielding you
+ * from direct changes within gradle.
+ * @deprecated No replacement
+ */
+ at Deprecated
+public interface RequestVersion1 {
+
+ /**
+ * @return the full gradle command line of this request
+ */
+ public String getFullCommandLine();
+
+ /**
+ * @return the display name of this request. Often this is the same as the full
+ * command line, but favorites may specify something more user-friendly.
+ */
+ public String getDisplayName();
+
+ /**
+ * @return whether or not output should always be shown. If false, only show it when
+ * errors occur.
+ */
+ public boolean forceOutputToBeShown();
+
+ /**
+ * Cancels this request.
+ */
+ public boolean cancel();
+
+ public static final String EXECUTION_TYPE = "execution";
+ public static final String REFRESH_TYPE = "refresh";
+ public static final String UNKNOWN_TYPE_PREFIX = "[unknown]:";
+
+ /**
+ * @return the type of the request. Either EXECUTION, REFRESH, or something that
+ * starts with UNKNOWN_TYPE_PREFIX (followed by an internal identifier) if its not
+ * listed above.
+ */
+ public String getType();
+}
diff --git a/subprojects/open-api/src/main/java/org/gradle/openapi/external/foundation/TaskVersion1.java b/subprojects/open-api/src/main/java/org/gradle/openapi/external/foundation/TaskVersion1.java
new file mode 100644
index 0000000..2934052
--- /dev/null
+++ b/subprojects/open-api/src/main/java/org/gradle/openapi/external/foundation/TaskVersion1.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.openapi.external.foundation;
+
+/**
+ * This is an abstraction of a gradle task
+ *
+ * This is a mirror of TaskView inside Gradle, but this is meant
+ * to aid backward and forward compatibility by shielding you from direct
+ * changes within gradle.
+ * @deprecated No replacement
+ */
+ at Deprecated
+public interface TaskVersion1 {
+
+ /**
+ * @return the project this task is associated with
+ */
+ public ProjectVersion1 getProject();
+
+ /**
+ * @return the name of this task
+ */
+ public String getName();
+
+ /**
+ * @return this tasks description
+ */
+ public String getDescription();
+
+ /**
+ * returns whether or not this is a default task for its parent project. These are defined by specifying
+ *
+ * defaultTasks 'task name'
+ *
+ * in the gradle file. There can be multiple default tasks.
+ *
+ * @return true if its a default task, false if not.
+ */
+ public boolean isDefault();
+
+ /**
+ * This generates this task's full name. This is a colon-separated string of this task and its parent projects.
+ *
+ * Example: root_project:sub_project:sub_sub_project:task.
+ */
+ public String getFullTaskName();
+}
diff --git a/subprojects/open-api/src/main/java/org/gradle/openapi/external/foundation/favorites/FavoriteTaskVersion1.java b/subprojects/open-api/src/main/java/org/gradle/openapi/external/foundation/favorites/FavoriteTaskVersion1.java
new file mode 100644
index 0000000..c5e3415
--- /dev/null
+++ b/subprojects/open-api/src/main/java/org/gradle/openapi/external/foundation/favorites/FavoriteTaskVersion1.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.openapi.external.foundation.favorites;
+
+/**
+ * This is an abstraction from Gradle that allows you to work with a 'favorite' task.
+ *
+ * This is a mirror of FavoriteTask inside Gradle, but this is meant
+ * to aid backward and forward compatibility by shielding you from direct
+ * changes within gradle.
+ *
+ * You should not implement this yourself. Only use an implementation coming from Gradle.
+ * @deprecated No replacement
+ */
+ at Deprecated
+public interface FavoriteTaskVersion1 {
+ /**<!====== getFullCommandLine ============================================>
+ @return the command line that is executed
+ <!=======================================================================>*/
+ public String getFullCommandLine();
+
+ /**<!====== getDisplayName ================================================>
+ @return a display name for this command
+ <!=======================================================================>*/
+ public String getDisplayName();
+
+ /**<!====== alwaysShowOutput ==============================================>
+ @return true if executing this command should always show the output, false
+ to only show output if an error occurs.
+ <!=======================================================================>*/
+ public boolean alwaysShowOutput();
+}
diff --git a/subprojects/open-api/src/main/java/org/gradle/openapi/external/foundation/favorites/FavoritesEditorVersion1.java b/subprojects/open-api/src/main/java/org/gradle/openapi/external/foundation/favorites/FavoritesEditorVersion1.java
new file mode 100644
index 0000000..2e646d0
--- /dev/null
+++ b/subprojects/open-api/src/main/java/org/gradle/openapi/external/foundation/favorites/FavoritesEditorVersion1.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.openapi.external.foundation.favorites;
+
+import org.gradle.openapi.external.foundation.TaskVersion1;
+
+import java.awt.*;
+import java.util.List;
+
+/**
+ * This is an abstraction from Gradle that allows you to obtain and edit favorites.
+ *
+ * <p>This is a mirror of FavoritesEditor inside Gradle, but this is meant to aid backward and forward compatibility by shielding you from direct changes within gradle.
+ * @deprecated No replacement
+ */
+ at Deprecated
+public interface FavoritesEditorVersion1 {
+
+ /**
+ * Adds the specified favorite.
+ *
+ * @param fullCommandLine the command line that this favorite executes
+ * @param displayName a more user-friendly name for the command
+ * @param alwaysShowOutput true to always show output when this favorite is executed. False to only show output when errors occur.
+ * @return the favorite added
+ */
+ public FavoriteTaskVersion1 addFavorite(String fullCommandLine, String displayName, boolean alwaysShowOutput);
+
+ /**
+ * Sets new values on the specified favorite task. This provides a simple way to programmatically edit favorite tasks.
+ *
+ * @param favoriteTask the favorite to edit
+ * @param newFullCommandLine the new command line
+ * @param newDisplayName the new display name
+ * @param newAlwaysShowOutput the new value for whether or not to always show output (vs only showing it when an error occurs).
+ * @returns null if successful otherwise, an error suitable for displaying to the user.
+ */
+ public String editFavorite(FavoriteTaskVersion1 favoriteTask, String newFullCommandLine, String newDisplayName, boolean newAlwaysShowOutput);
+
+ /**
+ * @return a list of all favorites in the system
+ */
+ public List<FavoriteTaskVersion1> getFavoriteTasks();
+
+ /**
+ * Returns the favorite with the specified command line
+ *
+ * @param fullCommandLine the command line of the sought favorite
+ * @return the matching favorite or null if no match found.
+ */
+ public FavoriteTaskVersion1 getFavorite(String fullCommandLine);
+
+ /**
+ * Returns the favorite with the specified display name
+ *
+ * @param displayName the display name of the sought favorite
+ * @return the matching favorite or null if no match found.
+ */
+ public FavoriteTaskVersion1 getFavoriteByDisplayName(String displayName);
+
+ /**
+ * Returns the favorite with the specified task
+ *
+ * @param task the task of the sought favorite
+ * @return the matching favorite or null if no match found.
+ */
+ public FavoriteTaskVersion1 getFavorite(TaskVersion1 task);
+
+ /**
+ * Display a Swing dialog prompting the user to enter a favorite.
+ *
+ * @param parent the parent window of the dialog.
+ * @return the favorite that was added or null if the user canceled
+ */
+ public FavoriteTaskVersion1 promptUserToAddFavorite(Window parent);
+
+ /**
+ * Display a Swing dialog prompting the user to edit the specified favorite
+ *
+ * @param parent the parent window of the dialog
+ * @param favorite the favorite to edit
+ * @return true if the user made changes and accepted them, false if the user canceled.
+ */
+ public boolean promptUserToEditFavorite(Window parent, FavoriteTaskVersion1 favorite);
+
+ /**
+ * Removes the specified favorites.
+ *
+ * @param favoritesToRemove the favorites to remove
+ */
+ public void removeFavorites(List<FavoriteTaskVersion1> favoritesToRemove);
+}
diff --git a/subprojects/open-api/src/main/java/org/gradle/openapi/external/runner/GradleRunnerFactory.java b/subprojects/open-api/src/main/java/org/gradle/openapi/external/runner/GradleRunnerFactory.java
new file mode 100644
index 0000000..02bad4e
--- /dev/null
+++ b/subprojects/open-api/src/main/java/org/gradle/openapi/external/runner/GradleRunnerFactory.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.openapi.external.runner;
+
+import org.gradle.openapi.external.ExternalUtility;
+
+import java.io.File;
+import java.lang.reflect.Constructor;
+
+/**
+ * This provides a simple way to execute gradle commands from an external process. call createGradleRunner to instantiate a gradle runner. You can then use that to execute commands.
+ * @deprecated Use the tooling API instead.
+ */
+ at Deprecated
+public class GradleRunnerFactory {
+ /**
+ * Call this to instantiate an object that you can use to execute gradle commands directly.
+ *
+ * Note: this function is meant to be backward and forward compatible. So this signature should not change at all, however, it may take and return objects that implement ADDITIONAL interfaces. That
+ * is, it will always return a GradleRunnerVersion1, but it may also be an object that implements GradleRunnerVersion2 (notice the 2). The caller will need to dynamically determine that. The
+ * GradleRunnerInteractionVersion1 may take an object that also implements GradleRunnerInteractionVersion2. If so, we'll dynamically determine that and handle it. Of course, this all depends on
+ * what happens in the future.
+ *
+ * @param parentClassLoader Your classloader. Probably the classloader of whatever class is calling this.
+ * @param gradleHomeDirectory the root directory of a gradle installation
+ * @param interaction this is how we interact with the caller.
+ * @param showDebugInfo true to show some additional information that may be helpful diagnosing problems is this fails
+ * @return a gradle runner
+ * @deprecated Use the tooling API instead.
+ */
+ @Deprecated
+ public static GradleRunnerVersion1 createGradleRunner(ClassLoader parentClassLoader, File gradleHomeDirectory, GradleRunnerInteractionVersion1 interaction, boolean showDebugInfo)
+ throws Exception {
+ //much of this function is exception handling so if we can't obtain it via the newer factory method, then
+ //we'll try the old way, but we want to report the original exception if we can't do it either way.
+ Exception viaFactoryException = null;
+ GradleRunnerVersion1 gradleRunner = null;
+
+ //first, try it the new way
+ try {
+ gradleRunner = createGradleRunnerViaFactory(parentClassLoader, gradleHomeDirectory, interaction, showDebugInfo);
+ } catch (Exception e) {
+ //we might ignore this. It means we're probably using an older version of gradle. That case is handled below.
+ //If not, this exception will be thrown at the end.
+ viaFactoryException = e;
+ }
+
+ //try it the old way
+ if (gradleRunner == null) {
+ gradleRunner = createGradleRunnerOldWay(parentClassLoader, gradleHomeDirectory, interaction, showDebugInfo);
+ }
+
+ //if we still don't have a gradle runner and we have an exception from using the factory, throw it. If we
+ //got an exception using the 'old way', it would have been thrown already and we wouldn't be here.
+ if (gradleRunner == null && viaFactoryException != null) {
+ throw viaFactoryException;
+ }
+
+ return gradleRunner;
+ }
+
+ /**
+ * This function uses a factory to instantiate a GradleRunner. The factory is located with the version of gradle pointed to by gradleHomeDirectory and thus allows the version of gradle being loaded
+ * to make decisions about how to instantiate the runner. This is needed as multiple versions of the runner are being used.
+ */
+ private static GradleRunnerVersion1 createGradleRunnerViaFactory(ClassLoader parentClassLoader, File gradleHomeDirectory, GradleRunnerInteractionVersion1 interaction, boolean showDebugInfo)
+ throws Exception {
+ //load the class in gradle that wraps our return interface and handles versioning issues.
+ Class soughtClass = ExternalUtility.loadGradleClass("org.gradle.openapi.wrappers.RunnerWrapperFactory", parentClassLoader, gradleHomeDirectory, showDebugInfo);
+ if (soughtClass == null) {
+ return null;
+ }
+
+ Class[] argumentClasses = new Class[]{File.class, GradleRunnerInteractionVersion1.class, boolean.class};
+
+ Object gradleRunner = ExternalUtility.invokeStaticMethod(soughtClass, "createGradleRunner", argumentClasses, gradleHomeDirectory, interaction, showDebugInfo);
+ return (GradleRunnerVersion1) gradleRunner;
+ }
+
+ /**
+ * This function uses an early way (early 0.9 pre-release and sooner) of instantiating the GradleRunner and should no longer be used. It unfortunately is tied to a single wrapper class instance
+ * (which it tries to directly instantiate). This doesn't allow the GradleRunner to adaptively determine what to instantiate.
+ */
+ private static GradleRunnerVersion1 createGradleRunnerOldWay(ClassLoader parentClassLoader, File gradleHomeDirectory, GradleRunnerInteractionVersion1 interaction, boolean showDebugInfo)
+ throws Exception {
+ ClassLoader bootStrapClassLoader = ExternalUtility.getGradleClassloader(parentClassLoader, gradleHomeDirectory, showDebugInfo);
+ Thread.currentThread().setContextClassLoader(bootStrapClassLoader);
+
+ //load the class in gradle that wraps our return interface and handles versioning issues.
+ Class soughtClass = null;
+ try {
+ soughtClass = bootStrapClassLoader.loadClass("org.gradle.openapi.wrappers.runner.GradleRunnerWrapper");
+ } catch (NoClassDefFoundError e) { //might be a version mismatch
+ e.printStackTrace();
+ return null;
+ } catch (ClassNotFoundException e) { //might be a version mismatch
+ e.printStackTrace();
+ return null;
+ }
+
+ if (soughtClass == null) {
+ return null;
+ }
+
+ //instantiate it.
+ Constructor constructor = null;
+ try {
+ constructor = soughtClass.getDeclaredConstructor(File.class, GradleRunnerInteractionVersion1.class);
+ } catch (NoSuchMethodException e) {
+ e.printStackTrace();
+ System.out.println("Dumping available constructors on " + soughtClass.getName() + "\n" + ExternalUtility.dumpConstructors(soughtClass));
+
+ throw e;
+ }
+
+ Object gradleRunner = constructor.newInstance(gradleHomeDirectory, interaction);
+
+ return (GradleRunnerVersion1) gradleRunner;
+ }
+}
diff --git a/subprojects/open-api/src/main/java/org/gradle/openapi/external/runner/GradleRunnerInteractionVersion1.java b/subprojects/open-api/src/main/java/org/gradle/openapi/external/runner/GradleRunnerInteractionVersion1.java
new file mode 100644
index 0000000..f06ddd3
--- /dev/null
+++ b/subprojects/open-api/src/main/java/org/gradle/openapi/external/runner/GradleRunnerInteractionVersion1.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.openapi.external.runner;
+
+import java.io.File;
+
+/**
+ * .
+ * @deprecated Use the tooling API instead.
+ */
+ at Deprecated
+public interface GradleRunnerInteractionVersion1 {
+ /**
+ * @return The root directory of your gradle project. The same directory Where you would run gradle from the command.
+ */
+ public File getWorkingDirectory();
+
+ @Deprecated
+ public enum LogLevel {Quiet, Lifecycle, Debug}
+
+ @Deprecated
+ public enum StackTraceLevel {InternalExceptions, Always, AlwaysFull}
+
+ /**
+ * @return the log level. This determines the detail level of information reported via reportLiveOutput and reportExecutionFinished.
+ */
+ public LogLevel getLogLevel();
+
+ /**
+ * @return the stack trace level. This determines the detail level of any stack traces should an exception occur.
+ */
+ public StackTraceLevel getStackTraceLevel();
+
+ /**
+ * Notification that overall execution has been started. This is only called once at the end.
+ */
+ public void reportExecutionStarted();
+
+ /**
+ * Notification of the total number of tasks that will be executed. This is called after reportExecutionStarted and before any tasks are executed.
+ *
+ * @param size the total number of tasks.
+ */
+ public void reportNumberOfTasksToExecute(int size);
+
+ /**
+ * Notification that a single task has completed. Note: the task you kicked off probably executes other tasks and this notifies you of those tasks and provides completion progress.
+ *
+ * @param currentTaskName the task being executed
+ * @param percentComplete the percent complete of all the tasks that make up the task you requested.
+ */
+ public void reportTaskStarted(String currentTaskName, float percentComplete);
+
+ public void reportTaskComplete(String currentTaskName, float percentComplete);
+
+ /**
+ * Report real-time output from gradle and its subsystems (such as ant).
+ *
+ * @param output a single line of text to show.
+ */
+ public void reportLiveOutput(String output);
+
+ public void reportExecutionFinished(boolean wasSuccessful, String message, Throwable throwable);
+
+ /**
+ * This is called to get a custom gradle executable file. If you don't run gradle.bat or gradle shell script to run gradle, use this to specify what you do run. Note: we're going to pass it the
+ * arguments that we would pass to gradle so if you don't like that, see alterCommandLineArguments. Normaly, this should return null.
+ *
+ * @return the Executable to run gradle command or null to use the default
+ */
+ public File getCustomGradleExecutable();
+}
diff --git a/subprojects/open-api/src/main/java/org/gradle/openapi/external/runner/GradleRunnerVersion1.java b/subprojects/open-api/src/main/java/org/gradle/openapi/external/runner/GradleRunnerVersion1.java
new file mode 100644
index 0000000..3397af8
--- /dev/null
+++ b/subprojects/open-api/src/main/java/org/gradle/openapi/external/runner/GradleRunnerVersion1.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.openapi.external.runner;
+
+/**
+ * This executes gradle commands in an external process.
+ * @deprecated Use the tooling API instead
+ */
+ at Deprecated
+public interface GradleRunnerVersion1 {
+ /**
+ * Call this to execute the specified command line.
+ *
+ * @param commandLine the command to execute
+ */
+ public void executeCommand(String commandLine);
+
+ /**
+ * Call this to stop the gradle command. This is killing the process, not gracefully exiting.
+ */
+ public void killProcess();
+}
diff --git a/subprojects/open-api/src/main/java/org/gradle/openapi/external/ui/AlternateUIInteractionVersion1.java b/subprojects/open-api/src/main/java/org/gradle/openapi/external/ui/AlternateUIInteractionVersion1.java
new file mode 100644
index 0000000..6defe7b
--- /dev/null
+++ b/subprojects/open-api/src/main/java/org/gradle/openapi/external/ui/AlternateUIInteractionVersion1.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.openapi.external.ui;
+
+import java.io.File;
+
+/**
+ * This is how the gradle UI panel interacts with the UI that is holding it.
+ *
+ * This is a mirror of AlternateUIInteraction inside Gradle, but this is meant to aid backward and forward compatibility by shielding you from direct changes within gradle.
+ * @deprecated No replacement
+ */
+ at Deprecated
+public interface AlternateUIInteractionVersion1 {
+ /**
+ * Notification that you should open the specified file and go to the specified line. Its up to the application to determine if this file should be opened for editing or simply displayed. The
+ * difference comes into play for things like xml or html files where a user may want to open them in a browser vs a source code file where they may want to open it directly in an IDE.
+ *
+ * @param file the file to edit
+ * @param line the line to go to. -1 if no line is specified.
+ */
+ public void openFile(File file, int line);
+
+ /**
+ * This is called when we should open the specified file for editing. This version explicitly wants them edited versus just opened.
+ *
+ * @param file the file to open
+ * @param line the line to go to. -1 if no line is specified.
+ */
+ public void editFile(File file, int line);
+
+ /**
+ * Determines if we can call editFiles or openFile. This is not a dynamic answer and should always return either true of false. If you want to change the answer, return true and then handle the
+ * files differently in editFiles.
+ *
+ * @return true if support editing files, false otherwise.
+ */
+ public boolean doesSupportEditingOpeningFiles();
+
+ /**
+ * Notification that a command is about to be executed. This is mostly useful for IDE's that may need to save their files.
+ *
+ * @param fullCommandLine the command that's about to be executed.
+ */
+ public void aboutToExecuteCommand(String fullCommandLine);
+}
diff --git a/subprojects/open-api/src/main/java/org/gradle/openapi/external/ui/BasicGradleUIVersion1.java b/subprojects/open-api/src/main/java/org/gradle/openapi/external/ui/BasicGradleUIVersion1.java
new file mode 100644
index 0000000..127dd38
--- /dev/null
+++ b/subprojects/open-api/src/main/java/org/gradle/openapi/external/ui/BasicGradleUIVersion1.java
@@ -0,0 +1,199 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.openapi.external.ui;
+
+import org.gradle.openapi.external.foundation.GradleInterfaceVersion1;
+import org.gradle.openapi.external.foundation.favorites.FavoritesEditorVersion1;
+
+import javax.swing.*;
+import java.io.File;
+
+/**
+ * This represents a basic gradle UI
+ *
+ * To use this, you'll want to get an instance of this from Gradle. Then setup your UI and add this to it via getComponent. Then call aboutToShow before you display your UI. Call close before you hide
+ * your UI. You'll need to set the current directory (at any time) so gradle knows where your project is located.
+ * @deprecated No replacement
+ */
+ at Deprecated
+public interface BasicGradleUIVersion1 {
+ /**
+ * Call this whenever you're about to show this panel. We'll do whatever initialization is necessary.
+ */
+ public void aboutToShow();
+
+ //
+ public interface CloseInteraction {
+ /**
+ * This is called if gradle tasks are being executed and you want to know if we can close. Ask the user.
+ *
+ * @return true if the user confirms cancelling the current tasks. False if not.
+ */
+ public boolean promptUserToConfirmClosingWhileBusy();
+ }
+
+ /**
+ * Call this to determine if you can close this pane. if we're busy, we'll ask the user if they want to close.
+ *
+ * @param closeInteraction allows us to interact with the user
+ * @return true if we can close, false if not.
+ */
+ public boolean canClose(CloseInteraction closeInteraction);
+
+ /**
+ * Call this before you close the pane. This gives it an opportunity to do cleanup. You probably should call canClose before this. It gives the app a chance to cancel if its busy.
+ */
+ public void close();
+
+ /**
+ * @return the root directory of your gradle project.
+ */
+ public File getCurrentDirectory();
+
+ /**
+ * @param currentDirectory the new root directory of your gradle project.
+ */
+ public void setCurrentDirectory(File currentDirectory);
+
+ /**
+ * @return the gradle home directory. Where gradle is installed.
+ */
+ public File getGradleHomeDirectory();
+
+ /**
+ * This is called to get a custom gradle executable file. If you don't run gradle.bat or gradle shell script to run gradle, use this to specify what you do run. Note: we're going to pass it the
+ * arguments that we would pass to gradle so if you don't like that, see alterCommandLineArguments. Normally, this should return null.
+ *
+ * @return the Executable to run gradle command or null to use the default
+ */
+ public File getCustomGradleExecutable();
+
+ /**
+ * Call this to add an additional tab to the gradle UI. You can call this at any time.
+ *
+ * @param index the index of where to add the tab.
+ * @param gradleTabVersion1 the tab to add.
+ */
+ public void addTab(int index, GradleTabVersion1 gradleTabVersion1);
+
+ /**
+ * Call this to remove one of your own tabs from this.
+ *
+ * @param gradleTabVersion1 the tab to remove
+ */
+ public void removeTab(GradleTabVersion1 gradleTabVersion1);
+
+ /**
+ * @return the total number of tabs.
+ */
+ public int getGradleTabCount();
+
+ /**
+ * @param index the index of the tab
+ * @return the name of the tab at the specified index.
+ */
+ public String getGradleTabName(int index);
+
+ /**
+ * Returns the index of the gradle tab with the specified name.
+ *
+ * @param name the name of the tab
+ * @return the index of the tab or -1 if not found
+ */
+ public int getGradleTabIndex(String name);
+
+ /**
+ * @return the currently selected tab
+ */
+ public int getCurrentGradleTab();
+
+ /**
+ * Makes the specified tab the current tab.
+ *
+ * @param index the index of the tab.
+ */
+ public void setCurrentGradleTab(int index);
+
+ /**
+ * This allows you to add a listener that can add additional command line arguments whenever gradle is executed. This is useful if you've customized your gradle build and need to specify, for
+ * example, an init script.
+ *
+ * @param listener the listener that modifies the command line arguments.
+ */
+ public void addCommandLineArgumentAlteringListener(CommandLineArgumentAlteringListenerVersion1 listener);
+
+ public void removeCommandLineArgumentAlteringListener(CommandLineArgumentAlteringListenerVersion1 listener);
+
+ /**
+ * Call this to execute the given gradle command.
+ *
+ * @param commandLineArguments the command line arguments to pass to gradle.
+ * @param displayName the name displayed in the UI for this command
+ */
+ public void executeCommand(String commandLineArguments, String displayName);
+
+ /**
+ * This refreshes the task tree. Useful if you know you've changed something behind gradle's back or when first displaying this UI.
+ */
+ public void refreshTaskTree();
+
+ /**
+ * @return the output lord which shows the live output of all commands being executed. You can add observers to this as well as alter how it finds file links.
+ */
+ public OutputUILordVersion1 getOutputLord();
+
+ //these were moved to OutputUILordVersion1, but remain here for backward compatibility
+ public void addOutputObserver(OutputObserverVersion1 outputObserverVersion1);
+
+ public void removeOutputObserver(OutputObserverVersion1 outputObserverVersion1);
+
+ /**
+ * Determines if commands are currently being executed or not.
+ *
+ * @return true if we're busy, false if not.
+ */
+ public boolean isBusy();
+
+ /**
+ * Determines whether output is shown only when errors occur or always
+ *
+ * @return true to only show output if errors occur, false to show it always.
+ */
+ public boolean getOnlyShowOutputOnErrors();
+
+ /**
+ * This adds the specified component to the setup panel. It is added below the last 'default' item. You can only add 1 component here, so if you need to add multiple things, you'll have to handle
+ * adding that to yourself to the one component.
+ *
+ * @param component the component to add.
+ */
+ public void setCustomPanelToSetupTab(JComponent component);
+
+ /**
+ * This returns an object that works with lower level gradle and contains the current projects and tasks. You can also execute tasks from it and perform certain setup.
+ *
+ * @return a GradleInterfaceVersion1 object. It may also be GradleInterfaceVersion2 or a future version. You can check its type and then cast it as appropriate. This allows the caller to be
+ * backward compatible.
+ */
+ public GradleInterfaceVersion1 getGradleInterfaceVersion1();
+
+ /**
+ * Returns a FavoritesEditor. This is useful for getting a list of all favorites or modifying them.
+ *
+ * @return a FavoritesEditorVersion1. Use this to interact with the favorites.
+ */
+ public FavoritesEditorVersion1 getFavoritesEditor();
+}
diff --git a/subprojects/open-api/src/main/java/org/gradle/openapi/external/ui/CommandLineArgumentAlteringListenerVersion1.java b/subprojects/open-api/src/main/java/org/gradle/openapi/external/ui/CommandLineArgumentAlteringListenerVersion1.java
new file mode 100644
index 0000000..0a25472
--- /dev/null
+++ b/subprojects/open-api/src/main/java/org/gradle/openapi/external/ui/CommandLineArgumentAlteringListenerVersion1.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.openapi.external.ui;
+
+/**
+ * This allows you to add a listener that can add additional command line arguments whenever gradle is executed. This is useful if you've customized your gradle build and need to specify, for example,
+ * an init script.
+ * @deprecated No replacement
+ */
+ at Deprecated
+public interface CommandLineArgumentAlteringListenerVersion1 {
+ /**
+ * This is called when you can add additional command line arguments. Return any additional arguments to add. This doesn't modify the existing commands.
+ *
+ * @param commandLineArguments the command line to execute.
+ * @return any command lines to add or null to leave it alone
+ */
+ public String getAdditionalCommandLineArguments(String commandLineArguments);
+}
diff --git a/subprojects/open-api/src/main/java/org/gradle/openapi/external/ui/DualPaneUIInteractionVersion1.java b/subprojects/open-api/src/main/java/org/gradle/openapi/external/ui/DualPaneUIInteractionVersion1.java
new file mode 100644
index 0000000..609ff09
--- /dev/null
+++ b/subprojects/open-api/src/main/java/org/gradle/openapi/external/ui/DualPaneUIInteractionVersion1.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.openapi.external.ui;
+
+/**
+ This interface holds onto our options and allows us to interact with the
+ caller. This is meant to interact with the Gradle UI across class loader
+ and version boundaries. That is, the open API has a single entry point
+ that shouldn't change across versions. New interfaces can be expected, but
+ we'll always allow 'version1'. This is to provide backward/forward compatibility.
+
+ @deprecated No replacement
+*/
+ at Deprecated
+public interface DualPaneUIInteractionVersion1 extends GradleUIInteractionVersion1
+{
+}
diff --git a/subprojects/open-api/src/main/java/org/gradle/openapi/external/ui/DualPaneUIVersion1.java b/subprojects/open-api/src/main/java/org/gradle/openapi/external/ui/DualPaneUIVersion1.java
new file mode 100644
index 0000000..dec3f66
--- /dev/null
+++ b/subprojects/open-api/src/main/java/org/gradle/openapi/external/ui/DualPaneUIVersion1.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.openapi.external.ui;
+
+import javax.swing.JComponent;
+import java.awt.Component;
+
+/**
+This is a gradle UI that is broken into two panels: one contains a tabbed pane
+ of tasks, favorites, command line, etc. The other pane contains the output.
+ This is meant to simplify how an IDE plugin can interact with gradle. Specifically,
+ this allows the 'main' pane to be vertical and the output pane to be horizontal.
+
+ To use this, you'll want to get an instance of this from Gradle. Then setup
+ your UI and add this to it via getComponent. Then call aboutToShow before
+ you display your UI. Call close before you hide your UI. You'll need to set
+ the current directory (at any time) so gradle knows where your project is
+ located.
+
+ @deprecated No replacement
+ */
+ at Deprecated
+public interface DualPaneUIVersion1 extends BasicGradleUIVersion1 {
+ /**
+ Returns a component that shows the task tree tab, favorites tab, etc.
+ suitable for inserting in your UI.
+ @return the main component
+ */
+ public JComponent getMainComponent();
+
+ /**
+ Returns a component that shows the output of the tasks being executed.
+ This is suitable for inserting in your UI.
+ @return the output component
+ */
+ public Component getOutputPanel();
+
+ /**
+ * This gets the number of opened output tabs. This is used by the Idea plugin
+ * to determine if it should close the entire output pane when a tab is closed
+ * This doesn't determine whether or not the tabs are busy. See
+ * GradleInterfaceVersion1.isBusy for that
+ * @return the number of opened output tabs.
+ */
+ public int getNumberOfOpenedOutputTabs();
+}
diff --git a/subprojects/open-api/src/main/java/org/gradle/openapi/external/ui/GradleTabVersion1.java b/subprojects/open-api/src/main/java/org/gradle/openapi/external/ui/GradleTabVersion1.java
new file mode 100644
index 0000000..64435de
--- /dev/null
+++ b/subprojects/open-api/src/main/java/org/gradle/openapi/external/ui/GradleTabVersion1.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.openapi.external.ui;
+
+import java.awt.*;
+
+/**
+
+ This represents a tab that the caller can add to the gradle UI.
+
+ This is a mirror of GradleTab inside Gradle, but this is meant to aid
+ backward and forward compatibility by shielding you from direct changes
+ within gradle.
+ @deprecated No replacement
+ */
+ at Deprecated
+public interface GradleTabVersion1 {
+ /*
+ @return the name of this tab
+ */
+ public String getName();
+
+ /*
+ This is where we should create your component.
+
+ @return the component
+ */
+ public Component createComponent();
+
+ /*
+ Notification that this component is about to be shown. Do whatever
+ initialization you choose.
+ */
+ public void aboutToShow();
+}
diff --git a/subprojects/open-api/src/main/java/org/gradle/openapi/external/ui/GradleUIInteractionVersion1.java b/subprojects/open-api/src/main/java/org/gradle/openapi/external/ui/GradleUIInteractionVersion1.java
new file mode 100644
index 0000000..154ae7c
--- /dev/null
+++ b/subprojects/open-api/src/main/java/org/gradle/openapi/external/ui/GradleUIInteractionVersion1.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.openapi.external.ui;
+
+/**
+ This interface holds onto our options and allows us to interact with the
+ caller. This is meant to interact with the Gradle UI across class loader
+ and version boundaries. That is, the open API has a single entry point
+ that shouldn't change across versions. New interfaces can be expected, but
+ we'll always allow 'version1'. This is to provide backward/forward compatibility.
+
+ @deprecated No replacement
+*/
+ at Deprecated
+public interface GradleUIInteractionVersion1 {
+ /*
+ This is only called once and is how we get a hold of the AlternateUIInteraction.
+ @return an AlternateUIInteraction object. This cannot be null.
+ */
+ public AlternateUIInteractionVersion1 instantiateAlternateUIInteraction();
+
+ /*
+ This is only called once and is how we get a hold of how the owner wants
+ to store preferences.
+ @return a settings object. This cannot be null.
+ */
+ public SettingsNodeVersion1 instantiateSettings();
+}
diff --git a/subprojects/open-api/src/main/java/org/gradle/openapi/external/ui/OutputObserverVersion1.java b/subprojects/open-api/src/main/java/org/gradle/openapi/external/ui/OutputObserverVersion1.java
new file mode 100644
index 0000000..a9d81da
--- /dev/null
+++ b/subprojects/open-api/src/main/java/org/gradle/openapi/external/ui/OutputObserverVersion1.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.openapi.external.ui;
+
+/**
+ * <p>This interface informs you when the output pane is displaying requests. This is NOT for general output of gradle commands.
+ *
+ * <p>This is a mirror of OutputUILord.OutputObserver inside Gradle, but this is meant to aid backward and forward compatibility by shielding you from direct changes within gradle.
+ *
+ * @deprecated No replacement
+ */
+ at Deprecated
+public interface OutputObserverVersion1 {
+ /**
+ * Notification that a request was added to the output. This means we've got some output that is useful to display. <! Name Description>
+ *
+ * @param requestID an ID you can use to identify this request when it is complete.
+ * @param fullCommandLine the command line for the request that was added
+ * @param displayName the display name of this command (often the same as the full command line)
+ * @param forceOutputToBeShown true if this request wants to force its output to be shown
+ */
+ public void executionRequestAdded(long requestID, String fullCommandLine, String displayName, boolean forceOutputToBeShown);
+
+ /**
+ * Notification that a refresh task list request was added to the output. This means we've got some output that is useful to display.
+ *
+ * @param requestID an ID you can use to identify this request when it is complete.
+ * @param forceOutputToBeShown true if this request wants to force its output to be shown
+ */
+ public void refreshRequestAdded(long requestID, boolean forceOutputToBeShown);
+
+ /**
+ * Notification that a request is complete. Note: if its canceled, you'll just get an outputTabClosed notification.
+ *
+ * @param requestID the ID of the request that is complete. It is given to you in executionRequestAdded or refreshRequestAdded.
+ * @param wasSuccessful true if was successful, false if not or was cancelled.
+ */
+ public void requestComplete(long requestID, boolean wasSuccessful);
+
+ /**
+ * Notification that an output tab was closed, possibly because it was canceled. You might want to know this if you want to close your IDE output window when all tabs are closed.
+ *
+ * @param requestID the ID of the request associated with this tab. It is given to you in executionRequestAdded or refreshRequestAdded.
+ */
+ public void outputTabClosed(long requestID);
+}
diff --git a/subprojects/open-api/src/main/java/org/gradle/openapi/external/ui/OutputUILordVersion1.java b/subprojects/open-api/src/main/java/org/gradle/openapi/external/ui/OutputUILordVersion1.java
new file mode 100644
index 0000000..3123d73
--- /dev/null
+++ b/subprojects/open-api/src/main/java/org/gradle/openapi/external/ui/OutputUILordVersion1.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.openapi.external.ui;
+
+import java.awt.*;
+import java.util.List;
+
+/**
+ * Provides access to aspects of gradle's output
+ * @deprecated No replacement
+ */
+ at Deprecated
+public interface OutputUILordVersion1 {
+
+ public void setOutputTextFont(Font font);
+
+ public Font getOutputTextFont();
+
+ /**
+ * Call this to add file extensions to look for in the output. The files will be highlighted and are clickable by the user. This results in AlternateUIInteractionVersion1.editFile or openFile
+ * being called. This assumes the file path is the first thing on the line.
+ *
+ * @param extension the file extension
+ * @param lineNumberDelimiter optional delimiter text for line number. Whatever is after this will be assumed to be a line number. We'll only parse the numbers after this so there can be other
+ * stuff after the line number. Pass in null to ignore.
+ */
+ public void addFileExtension(String extension, String lineNumberDelimiter);
+
+ /**
+ * Creates a file link definition to find file paths in the output that have a known prefix and extension. The files will be highlighted and are clickable by the user. This results in
+ * AlternateUIInteractionVersion1.editFile or openFile being called. It also allows for an optional line number after a delimiter. This is useful if you know a certain message always precedes a
+ * file path.
+ *
+ * @param name the name of this file link definition. Used by tests mostly.
+ * @param prefix the text that is before the file path. It should be enough to make it fairly unique
+ * @param extension the expected file extension. If we don't find this extension, we do not consider the text a file's path. If there are multiple extensions, you'll have to add multiples of
+ * these.
+ * @param lineNumberDelimiter optional delimiter text for line number. Whatever is after this will be assumed to be a line number. We'll only parse the numbers after this so there can be other
+ * stuff after the line number. Pass in null to ignore.
+ */
+ public void addPrefixedFileLink(String name, String prefix, String extension, String lineNumberDelimiter);
+
+ /**
+ * @return a list of file extensions that are highlighted in the output
+ */
+ public List<String> getFileExtensions();
+
+ public void addOutputObserver(OutputObserverVersion1 outputObserverVersion1);
+
+ public void removeOutputObserver(OutputObserverVersion1 outputObserverVersion1);
+
+ /*
+ This re-executes the last execution command (ignores refresh commands).
+ This is potentially useful for IDEs to hook into (hotkey to execute last command).
+ */
+ public void reExecuteLastCommand();
+}
diff --git a/subprojects/open-api/src/main/java/org/gradle/openapi/external/ui/SettingsNodeVersion1.java b/subprojects/open-api/src/main/java/org/gradle/openapi/external/ui/SettingsNodeVersion1.java
new file mode 100644
index 0000000..c2f1532
--- /dev/null
+++ b/subprojects/open-api/src/main/java/org/gradle/openapi/external/ui/SettingsNodeVersion1.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.openapi.external.ui;
+
+import java.util.List;
+
+/**
+ * Abstraction of how settings are stored. If you're implementing this, see SettingsNode for more information.
+ *
+ * This is a mirror of SettingsNode inside Gradle, but this is meant to aid backward and forward compatibility by shielding you from direct changes within gradle.
+ * @deprecated No replacement
+ */
+ at Deprecated
+public interface SettingsNodeVersion1 {
+ public void setName(String name);
+
+ public String getName();
+
+ public void setValue(String value);
+
+ public String getValue();
+
+ public void setValueOfChild(String name, String value);
+
+ public String getValueOfChild(String name, String defaultValue);
+
+ public int getValueOfChildAsInt(String name, int defaultValue);
+
+ public void setValueOfChildAsInt(String name, int value);
+
+ public boolean getValueOfChildAsBoolean(String name, boolean defaultValue);
+
+ public void setValueOfChildAsBoolean(String name, boolean value);
+
+ public long getValueOfChildAsLong(String name, long defaultValue);
+
+ public void setValueOfChildAsLong(String name, long value);
+
+ public List<SettingsNodeVersion1> getChildNodes();
+
+ public List<SettingsNodeVersion1> getChildNodes(String name);
+
+ public SettingsNodeVersion1 addChild(String name);
+
+ public SettingsNodeVersion1 addChildIfNotPresent(String name);
+
+ public SettingsNodeVersion1 getChildNode(String name);
+
+ public SettingsNodeVersion1 getNodeAtPath(String... pathPortions);
+
+ public void removeFromParent();
+
+ public void removeAllChildren();
+}
diff --git a/subprojects/open-api/src/main/java/org/gradle/openapi/external/ui/SinglePaneUIInteractionVersion1.java b/subprojects/open-api/src/main/java/org/gradle/openapi/external/ui/SinglePaneUIInteractionVersion1.java
new file mode 100644
index 0000000..a047bd1
--- /dev/null
+++ b/subprojects/open-api/src/main/java/org/gradle/openapi/external/ui/SinglePaneUIInteractionVersion1.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.openapi.external.ui;
+
+/*
+ This interface holds onto our options and allows us to interact with the
+ caller. This is meant to interact with the Gradle UI across class loader
+ and version boundaries. That is, the open API has a single entry point
+ that shouldn't change across versions. New interfaces can be expected, but
+ we'll always allow 'version1'. This is to provide backward/forward compatibility.
+
+ @deprecated No replacement
+*/
+ at Deprecated
+public interface SinglePaneUIInteractionVersion1 extends GradleUIInteractionVersion1
+{
+}
diff --git a/subprojects/open-api/src/main/java/org/gradle/openapi/external/ui/SinglePaneUIVersion1.java b/subprojects/open-api/src/main/java/org/gradle/openapi/external/ui/SinglePaneUIVersion1.java
new file mode 100644
index 0000000..83b0967
--- /dev/null
+++ b/subprojects/open-api/src/main/java/org/gradle/openapi/external/ui/SinglePaneUIVersion1.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.openapi.external.ui;
+
+import javax.swing.*;
+
+/*
+ This is a gradle UI that is entirely within a single panel (and only a panel;
+ no dialog or frame). This is meant to simplify how a plugin can interact with
+ gradle.
+
+ To use this, you'll want to get an instance of this from Gradle. Then setup
+ your UI and add this to it via getComponent. Then call aboutToShow before
+ you display your UI. Call close before you hide your UI. You'll need to set
+ the current directory (at any time) so gradle knows where your project is
+ located.
+
+ @deprecated No replacement
+ */
+ at Deprecated
+public interface SinglePaneUIVersion1 extends BasicGradleUIVersion1 {
+ /**
+ Returns this panel as a Swing object suitable for inserting in your UI.
+ @return the main component
+ */
+ public JComponent getComponent();
+}
diff --git a/subprojects/open-api/src/main/java/org/gradle/openapi/external/ui/UIFactory.java b/subprojects/open-api/src/main/java/org/gradle/openapi/external/ui/UIFactory.java
new file mode 100644
index 0000000..8b80bf4
--- /dev/null
+++ b/subprojects/open-api/src/main/java/org/gradle/openapi/external/ui/UIFactory.java
@@ -0,0 +1,238 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.openapi.external.ui;
+
+import org.gradle.openapi.external.ExternalUtility;
+
+import java.io.File;
+import java.lang.reflect.Constructor;
+
+/**
+ * This loads up the main gradle UI. This is intended to be used as a plugin inside another application (like an IDE) in a dynamic fashion. If you're always going to ship the entire plugin with the
+ * entire Gradle dist, you don't need to use this. This is meant to dynamically load Gradle from its dist. The idea is that you point your plugin to a Gradle dist and then can always load the latest
+ * version.
+ * @deprecated No replacement
+ */
+ at Deprecated
+public class UIFactory {
+ private static final String UIWRAPPER_FACTORY_CLASS_NAME = "org.gradle.openapi.wrappers.UIWrapperFactory";
+
+ /**
+ * Call this to instantiate a self-contained gradle UI. That is, everything in the UI is in a single panel (versus 2 panels one for the tasks and one for the output). This will load gradle via
+ * reflection, instantiate the UI and all required gradle-related classes.
+ *
+ * <p>Note: this function is meant to be backward and forward compatible. So this signature should not change at all, however, it may take and return objects that implement ADDITIONAL interfaces.
+ * That is, it will always return SinglePaneUIVersion1, but it may also be an object that implements SinglePaneUIVersion2 (notice the 2). The caller will need to dynamically determine that. The
+ * SinglePaneUIInteractionVersion1 may take an object that also implements SinglePaneUIInteractionVersion2. If so, we'll dynamically determine that and handle it. Of course, this all depends on
+ * what happens in the future.
+ *
+ * @param parentClassLoader Your classloader. Probably the classloader of whatever class is calling this.
+ * @param gradleHomeDirectory the root directory of a gradle installation
+ * @param showDebugInfo true to show some additional information that may be helpful diagnosing problems is this fails
+ * @return the UI object.
+ * @deprecated Use the tooling API instead.
+ */
+ @Deprecated
+ public static SinglePaneUIVersion1 createSinglePaneUI(ClassLoader parentClassLoader, File gradleHomeDirectory, final SinglePaneUIInteractionVersion1 interaction, boolean showDebugInfo)
+ throws Exception {
+ //much of this function is exception handling so if we can't obtain it via the newer factory method, then
+ //we'll try the old way, but we want to report the original exception if we can't do it either way.
+ Exception viaFactoryException = null;
+ SinglePaneUIVersion1 gradleUI = null;
+
+ //first, try it the new way
+ try {
+ gradleUI = createSinglePaneUIViaFactory(parentClassLoader, gradleHomeDirectory, interaction, showDebugInfo);
+ } catch (Exception e) {
+ //we might ignore this. It means we're probably using an older version of gradle. That case is handled below.
+ //If not, this exception will be thrown at the end.
+ viaFactoryException = e;
+ }
+
+ //try it the old way
+ if (gradleUI == null) {
+ gradleUI = createSinglePaneUIOldWay(parentClassLoader, gradleHomeDirectory, interaction, showDebugInfo);
+ }
+
+ //if we still don't have a gradle ui and we have an exception from using the factory, throw it. If we
+ //got an exception using the 'old way', it would have been thrown already and we wouldn't be here.
+ if (gradleUI == null && viaFactoryException != null) {
+ throw viaFactoryException;
+ }
+
+ return gradleUI;
+ }
+
+ /**
+ * This function uses a factory to instantiate the UI. The factory is located with the version of gradle pointed to by gradleHomeDirectory and thus allows the version of gradle being loaded to make
+ * decisions about how to instantiate the UI. This is needed as multiple versions of the UI are being used.
+ */
+ private static SinglePaneUIVersion1 createSinglePaneUIViaFactory(ClassLoader parentClassLoader, File gradleHomeDirectory, final SinglePaneUIInteractionVersion1 interaction, boolean showDebugInfo)
+ throws Exception {
+ //load the class in gradle that wraps our return interface and handles versioning issues.
+ Class soughtClass = ExternalUtility.loadGradleClass(UIWRAPPER_FACTORY_CLASS_NAME, parentClassLoader, gradleHomeDirectory, showDebugInfo);
+ if (soughtClass == null) {
+ return null;
+ }
+
+ Class[] argumentClasses = new Class[]{SinglePaneUIInteractionVersion1.class, boolean.class};
+
+ Object gradleUI = ExternalUtility.invokeStaticMethod(soughtClass, "createSinglePaneUI", argumentClasses, interaction, showDebugInfo);
+ return (SinglePaneUIVersion1) gradleUI;
+ }
+
+ /**
+ * This function uses an early way (early 0.9 pre-release and sooner) of instantiating the UI and should no longer be used. It unfortunately is tied to a single wrapper class instance (which it
+ * tries to directly instantiate). This doesn't allow the Gradle UI to adaptively determine what to instantiate.
+ */
+ private static SinglePaneUIVersion1 createSinglePaneUIOldWay(ClassLoader parentClassLoader, File gradleHomeDirectory, final SinglePaneUIInteractionVersion1 singlePaneUIArguments,
+ boolean showDebugInfo) throws Exception {
+ ClassLoader bootStrapClassLoader = ExternalUtility.getGradleClassloader(parentClassLoader, gradleHomeDirectory, showDebugInfo);
+ Thread.currentThread().setContextClassLoader(bootStrapClassLoader);
+
+ //load the class in gradle that wraps our return interface and handles versioning issues.
+ Class soughtClass = null;
+ try {
+ soughtClass = bootStrapClassLoader.loadClass("org.gradle.openapi.wrappers.ui.SinglePaneUIWrapper");
+ } catch (NoClassDefFoundError e) { //might be a version mismatch
+ e.printStackTrace();
+ return null;
+ } catch (ClassNotFoundException e) { //might be a version mismatch
+ e.printStackTrace();
+ }
+ if (soughtClass == null) {
+ return null;
+ }
+
+ //instantiate it.
+ Constructor constructor = null;
+ try {
+ constructor = soughtClass.getDeclaredConstructor(SinglePaneUIInteractionVersion1.class);
+ } catch (NoSuchMethodException e) {
+ e.printStackTrace();
+ System.out.println("Dumping available constructors on " + soughtClass.getName() + "\n" + ExternalUtility.dumpConstructors(soughtClass));
+
+ throw e;
+ }
+ Object singlePaneUI = constructor.newInstance(singlePaneUIArguments);
+ return (SinglePaneUIVersion1) singlePaneUI;
+ }
+
+ /**
+ * Call this to instantiate a gradle UI that contains the main tab control separate from the output panel. This allows you to position the output however you like. For example: you can place the
+ * main pane along the side going vertically and you can place the output pane along the bottom going horizontally. This will load gradle via reflection, instantiate the UI and all required
+ * gradle-related classes.
+ *
+ * <p>Note: this function is meant to be backward and forward compatible. So this signature should not change at all, however, it may take and return objects that implement ADDITIONAL interfaces.
+ * That is, it will always return SinglePaneUIVersion1, but it may also be an object that implements SinglePaneUIVersion2 (notice the 2). The caller will need to dynamically determine that. The
+ * SinglePaneUIInteractionVersion1 may take an object that also implements SinglePaneUIInteractionVersion2. If so, we'll dynamically determine that and handle it. Of course, this all depends on
+ * what happens in the future.
+ *
+ * @param parentClassLoader Your classloader. Probably the classloader of whatever class is calling this.
+ * @param gradleHomeDirectory the root directory of a gradle installation
+ * @param interaction this is how we interact with the caller.
+ * @param showDebugInfo true to show some additional information that may be helpful diagnosing problems is this fails
+ * @return the UI object.
+ * @deprecated Use the tooling API instead.
+ */
+ @Deprecated
+ public static DualPaneUIVersion1 createDualPaneUI(ClassLoader parentClassLoader, File gradleHomeDirectory, final DualPaneUIInteractionVersion1 interaction, boolean showDebugInfo)
+ throws Exception {
+ //much of this function is exception handling so if we can't obtain it via the newer factory method, then
+ //we'll try the old way, but we want to report the original exception if we can't do it either way.
+ Exception viaFactoryException = null;
+ DualPaneUIVersion1 gradleUI = null;
+
+ //first, try it the new way
+ try {
+ gradleUI = createDualPaneUIViaFactory(parentClassLoader, gradleHomeDirectory, interaction, showDebugInfo);
+ } catch (Exception e) {
+ //we might ignore this. It means we're probably using an older version of gradle. That case is handled below.
+ //If not, this exception will be thrown at the end.
+ viaFactoryException = e;
+ }
+
+ //try it the old way
+ if (gradleUI == null) {
+ gradleUI = createDualPaneUIOldWay(parentClassLoader, gradleHomeDirectory, interaction, showDebugInfo);
+ }
+
+ //if we still don't have a gradle ui and we have an exception from using the factory, throw it. If we
+ //got an exception using the 'old way', it would have been thrown already and we wouldn't be here.
+ if (gradleUI == null && viaFactoryException != null) {
+ throw viaFactoryException;
+ }
+
+ return gradleUI;
+ }
+
+ /**
+ * This function uses a factory to instantiate the UI. The factory is located with the version of gradle pointed to by gradleHomeDirectory and thus allows the version of gradle being loaded to make
+ * decisions about how to instantiate the UI. This is needed as multiple versions of the UI are being used.
+ * @deprecated Use the tooling API instead.
+ */
+ @Deprecated
+ public static DualPaneUIVersion1 createDualPaneUIViaFactory(ClassLoader parentClassLoader, File gradleHomeDirectory, final DualPaneUIInteractionVersion1 interaction, boolean showDebugInfo)
+ throws Exception {
+ //load the class in gradle that wraps our return interface and handles versioning issues.
+ Class soughtClass = ExternalUtility.loadGradleClass(UIWRAPPER_FACTORY_CLASS_NAME, parentClassLoader, gradleHomeDirectory, showDebugInfo);
+ if (soughtClass == null) {
+ return null;
+ }
+
+ Class[] argumentClasses = new Class[]{DualPaneUIInteractionVersion1.class, boolean.class};
+
+ Object gradleUI = ExternalUtility.invokeStaticMethod(soughtClass, "createDualPaneUI", argumentClasses, interaction, showDebugInfo);
+ return (DualPaneUIVersion1) gradleUI;
+ }
+
+ /**
+ * This function uses an early way (early 0.9 pre-release and sooner) of instantiating the UI and should no longer be used. It unfortunately is tied to a single wrapper class instance (which it
+ * tries to directly instantiate). This doesn't allow the Gradle UI to adaptively determine what to instantiate.
+ */
+ private static DualPaneUIVersion1 createDualPaneUIOldWay(ClassLoader parentClassLoader, File gradleHomeDirectory, final DualPaneUIInteractionVersion1 interaction, boolean showDebugInfo)
+ throws Exception {
+ ClassLoader bootStrapClassLoader = ExternalUtility.getGradleClassloader(parentClassLoader, gradleHomeDirectory, showDebugInfo);
+ Thread.currentThread().setContextClassLoader(bootStrapClassLoader);
+
+ //load the class in gradle that wraps our return interface and handles versioning issues.
+ Class soughtClass = null;
+ try {
+ soughtClass = bootStrapClassLoader.loadClass("org.gradle.openapi.wrappers.ui.DualPaneUIWrapper");
+ } catch (NoClassDefFoundError e) { //might be a version mismatch
+ e.printStackTrace();
+ return null;
+ } catch (ClassNotFoundException e) { //might be a version mismatch
+ e.printStackTrace();
+ }
+ if (soughtClass == null) {
+ return null;
+ }
+
+ //instantiate it.
+ Constructor constructor = null;
+ try {
+ constructor = soughtClass.getDeclaredConstructor(DualPaneUIInteractionVersion1.class);
+ } catch (NoSuchMethodException e) {
+ e.printStackTrace();
+ System.out.println("Dumping available constructors on " + soughtClass.getName() + "\n" + ExternalUtility.dumpConstructors(soughtClass));
+
+ throw e;
+ }
+ Object gradleUI = constructor.newInstance(interaction);
+ return (DualPaneUIVersion1) gradleUI;
+ }
+}
diff --git a/subprojects/osgi/osgi.gradle b/subprojects/osgi/osgi.gradle
index 57d7c1f..2e5d501 100644
--- a/subprojects/osgi/osgi.gradle
+++ b/subprojects/osgi/osgi.gradle
@@ -15,13 +15,13 @@
*/
dependencies {
- groovy libraries.groovy
+ compile libraries.groovy
compile project(':core')
compile project(':plugins')
compile libraries.slf4j_api
- compile module('biz.aQute:bndlib:1.50.0')
+ compile module('biz.aQute.bnd:bndlib:2.1.0')
}
useTestFixtures()
diff --git a/subprojects/osgi/src/main/groovy/org/gradle/api/internal/plugins/osgi/ContainedVersionAnalyzer.java b/subprojects/osgi/src/main/groovy/org/gradle/api/internal/plugins/osgi/ContainedVersionAnalyzer.java
index 55746c9..18e4ce6 100644
--- a/subprojects/osgi/src/main/groovy/org/gradle/api/internal/plugins/osgi/ContainedVersionAnalyzer.java
+++ b/subprojects/osgi/src/main/groovy/org/gradle/api/internal/plugins/osgi/ContainedVersionAnalyzer.java
@@ -16,7 +16,7 @@
package org.gradle.api.internal.plugins.osgi;
-import aQute.lib.osgi.Analyzer;
+import aQute.bnd.osgi.Analyzer;
public class ContainedVersionAnalyzer extends Analyzer {
}
\ No newline at end of file
diff --git a/subprojects/osgi/src/main/groovy/org/gradle/api/internal/plugins/osgi/DefaultAnalyzerFactory.java b/subprojects/osgi/src/main/groovy/org/gradle/api/internal/plugins/osgi/DefaultAnalyzerFactory.java
index 2ad3486..2054a8a 100644
--- a/subprojects/osgi/src/main/groovy/org/gradle/api/internal/plugins/osgi/DefaultAnalyzerFactory.java
+++ b/subprojects/osgi/src/main/groovy/org/gradle/api/internal/plugins/osgi/DefaultAnalyzerFactory.java
@@ -17,9 +17,6 @@ package org.gradle.api.internal.plugins.osgi;
import org.gradle.internal.Factory;
-/**
- * @author Hans Dockter
- */
public class DefaultAnalyzerFactory implements Factory<ContainedVersionAnalyzer> {
public ContainedVersionAnalyzer create() {
return new ContainedVersionAnalyzer();
diff --git a/subprojects/osgi/src/main/groovy/org/gradle/api/internal/plugins/osgi/DefaultOsgiManifest.java b/subprojects/osgi/src/main/groovy/org/gradle/api/internal/plugins/osgi/DefaultOsgiManifest.java
index 4f01491..d18554c 100644
--- a/subprojects/osgi/src/main/groovy/org/gradle/api/internal/plugins/osgi/DefaultOsgiManifest.java
+++ b/subprojects/osgi/src/main/groovy/org/gradle/api/internal/plugins/osgi/DefaultOsgiManifest.java
@@ -15,7 +15,7 @@
*/
package org.gradle.api.internal.plugins.osgi;
-import aQute.lib.osgi.Analyzer;
+import aQute.bnd.osgi.Analyzer;
import org.gradle.api.file.FileCollection;
import org.gradle.api.internal.file.FileResolver;
import org.gradle.api.java.archives.Attributes;
@@ -32,9 +32,6 @@ import java.io.IOException;
import java.util.*;
import java.util.jar.Manifest;
-/**
- * @author Hans Dockter
- */
public class DefaultOsgiManifest extends DefaultManifest implements OsgiManifest {
// Because these properties can be convention mapped we need special handling in here.
diff --git a/subprojects/osgi/src/main/groovy/org/gradle/api/internal/plugins/osgi/OsgiHelper.java b/subprojects/osgi/src/main/groovy/org/gradle/api/internal/plugins/osgi/OsgiHelper.java
index 9830064..8fccc6e 100644
--- a/subprojects/osgi/src/main/groovy/org/gradle/api/internal/plugins/osgi/OsgiHelper.java
+++ b/subprojects/osgi/src/main/groovy/org/gradle/api/internal/plugins/osgi/OsgiHelper.java
@@ -23,9 +23,6 @@ import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-/**
- * @author Hans Dockter
- */
public class OsgiHelper {
/**
* Bundle-Version must match this pattern
diff --git a/subprojects/osgi/src/main/groovy/org/gradle/api/plugins/osgi/OsgiManifest.java b/subprojects/osgi/src/main/groovy/org/gradle/api/plugins/osgi/OsgiManifest.java
index d593706..879669b 100644
--- a/subprojects/osgi/src/main/groovy/org/gradle/api/plugins/osgi/OsgiManifest.java
+++ b/subprojects/osgi/src/main/groovy/org/gradle/api/plugins/osgi/OsgiManifest.java
@@ -23,8 +23,6 @@ import java.util.Map;
/**
* Represents a manifest file for a JAR containing an OSGi bundle.
- *
- * @author Hans Dockter
*/
public interface OsgiManifest extends org.gradle.api.java.archives.Manifest {
/**
@@ -73,7 +71,7 @@ public interface OsgiManifest extends org.gradle.api.java.archives.Manifest {
OsgiManifest instructionReplace(String name, String... values);
/**
- * Returns all exisiting instruction.
+ * Returns all existing instruction.
*
* @return A map with instructions. The key of the map is the instruction name, the value a list of arguments.
*/
diff --git a/subprojects/osgi/src/main/groovy/org/gradle/api/plugins/osgi/OsgiPlugin.groovy b/subprojects/osgi/src/main/groovy/org/gradle/api/plugins/osgi/OsgiPlugin.groovy
index 8da3158..53bb103 100644
--- a/subprojects/osgi/src/main/groovy/org/gradle/api/plugins/osgi/OsgiPlugin.groovy
+++ b/subprojects/osgi/src/main/groovy/org/gradle/api/plugins/osgi/OsgiPlugin.groovy
@@ -23,8 +23,6 @@ import org.gradle.api.plugins.JavaPlugin
/**
* A {@link Plugin} which extends the {@link JavaPlugin} to add OSGi meta-information to the project Jars.
- *
- * @author Hans Dockter
*/
public class OsgiPlugin implements Plugin<Project> {
public void apply(Project project) {
diff --git a/subprojects/osgi/src/main/groovy/org/gradle/api/plugins/osgi/OsgiPluginConvention.java b/subprojects/osgi/src/main/groovy/org/gradle/api/plugins/osgi/OsgiPluginConvention.java
index d69aa58..37fc647 100644
--- a/subprojects/osgi/src/main/groovy/org/gradle/api/plugins/osgi/OsgiPluginConvention.java
+++ b/subprojects/osgi/src/main/groovy/org/gradle/api/plugins/osgi/OsgiPluginConvention.java
@@ -29,8 +29,6 @@ import java.util.concurrent.Callable;
/**
* Is mixed in into the project when applying the {@link org.gradle.api.plugins.osgi.OsgiPlugin} .
- *
- * @author Hans Dockter
*/
public class OsgiPluginConvention {
private ProjectInternal project;
diff --git a/subprojects/osgi/src/test/groovy/org/gradle/api/internal/plugins/osgi/DefaultAnalyzerFactoryTest.java b/subprojects/osgi/src/test/groovy/org/gradle/api/internal/plugins/osgi/DefaultAnalyzerFactoryTest.java
index 64258a8..5ee2789 100644
--- a/subprojects/osgi/src/test/groovy/org/gradle/api/internal/plugins/osgi/DefaultAnalyzerFactoryTest.java
+++ b/subprojects/osgi/src/test/groovy/org/gradle/api/internal/plugins/osgi/DefaultAnalyzerFactoryTest.java
@@ -16,11 +16,9 @@
package org.gradle.api.internal.plugins.osgi;
import org.junit.Test;
+
import static org.junit.Assert.assertNotNull;
-/**
- * @author Hans Dockter
- */
public class DefaultAnalyzerFactoryTest {
@Test
public void create() {
diff --git a/subprojects/osgi/src/test/groovy/org/gradle/api/internal/plugins/osgi/DefaultOsgiManifestTest.groovy b/subprojects/osgi/src/test/groovy/org/gradle/api/internal/plugins/osgi/DefaultOsgiManifestTest.groovy
index a394af1..3e3024d 100644
--- a/subprojects/osgi/src/test/groovy/org/gradle/api/internal/plugins/osgi/DefaultOsgiManifestTest.groovy
+++ b/subprojects/osgi/src/test/groovy/org/gradle/api/internal/plugins/osgi/DefaultOsgiManifestTest.groovy
@@ -15,8 +15,7 @@
*/
package org.gradle.api.internal.plugins.osgi
-import aQute.lib.osgi.Analyzer
-import java.util.jar.Manifest
+import aQute.bnd.osgi.Analyzer
import org.gradle.api.file.FileCollection
import org.gradle.api.internal.file.FileResolver
import org.gradle.api.java.archives.Attributes
@@ -27,9 +26,8 @@ import spock.lang.Shared
import spock.lang.Specification
import spock.lang.Unroll
-/**
- * @author Hans Dockter
- */
+import java.util.jar.Manifest
+
class DefaultOsgiManifestTest extends Specification {
private static final String ARBITRARY_SECTION = "A-Different-Section"
private static final String ARBITRARY_ATTRIBUTE = "Silly-Attribute"
diff --git a/subprojects/osgi/src/test/groovy/org/gradle/api/plugins/osgi/OsgiPluginConventionTest.groovy b/subprojects/osgi/src/test/groovy/org/gradle/api/plugins/osgi/OsgiPluginConventionTest.groovy
index 59f5483..727f7f8 100644
--- a/subprojects/osgi/src/test/groovy/org/gradle/api/plugins/osgi/OsgiPluginConventionTest.groovy
+++ b/subprojects/osgi/src/test/groovy/org/gradle/api/plugins/osgi/OsgiPluginConventionTest.groovy
@@ -15,20 +15,16 @@
*/
package org.gradle.api.plugins.osgi
-import org.gradle.util.HelperUtil
-import org.gradle.api.internal.project.DefaultProject
import org.gradle.api.internal.plugins.osgi.DefaultOsgiManifest
import org.gradle.api.internal.plugins.osgi.OsgiHelper
+import org.gradle.api.internal.project.DefaultProject
import org.gradle.api.plugins.JavaBasePlugin
-
-import spock.lang.Specification
+import org.gradle.util.TestUtil
import spock.lang.Issue
+import spock.lang.Specification
-/**
- * @author Hans Dockter
- */
class OsgiPluginConventionTest extends Specification {
- DefaultProject project = HelperUtil.createRootProject()
+ DefaultProject project = TestUtil.createRootProject()
OsgiPluginConvention osgiPluginConvention = new OsgiPluginConvention(project)
def setup() {
diff --git a/subprojects/osgi/src/test/groovy/org/gradle/api/plugins/osgi/OsgiPluginTest.groovy b/subprojects/osgi/src/test/groovy/org/gradle/api/plugins/osgi/OsgiPluginTest.groovy
index f1c9201..4cd64a5 100644
--- a/subprojects/osgi/src/test/groovy/org/gradle/api/plugins/osgi/OsgiPluginTest.groovy
+++ b/subprojects/osgi/src/test/groovy/org/gradle/api/plugins/osgi/OsgiPluginTest.groovy
@@ -18,12 +18,12 @@ package org.gradle.api.plugins.osgi;
import org.gradle.api.Project
import org.gradle.api.plugins.JavaPlugin
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import spock.lang.Specification
import org.gradle.api.tasks.SourceSet
public class OsgiPluginTest extends Specification {
- private final Project project = HelperUtil.createRootProject();
+ private final Project project = TestUtil.createRootProject();
private final OsgiPlugin osgiPlugin = new OsgiPlugin();
public void appliesTheJavaPlugin() {
diff --git a/subprojects/performance/performance.gradle b/subprojects/performance/performance.gradle
index e954b00..6fd3911 100644
--- a/subprojects/performance/performance.gradle
+++ b/subprojects/performance/performance.gradle
@@ -1,18 +1,39 @@
apply from: 'src/generator.groovy'
+apply plugin: 'javascript-base'
configurations {
junit
- plugin
+ reports
+}
+
+repositories {
+ javaScript.googleApis()
}
dependencies {
junit 'junit:junit:4.11'
- groovy libraries.groovy
+ reports "jquery:jquery.min:1.8.0 at js"
+ reports "flot:flot:0.8.1:min at js"
+
+ compile libraries.groovy
+ testFixturesCompile libraries.slf4j_api
testFixturesCompile project(':internalIntegTesting')
- plugin gradleApi()
+ testFixturesCompile 'com.googlecode.jatl:jatl:0.2.2'
+ testFixturesCompile 'org.eclipse.jgit:org.eclipse.jgit:3.0.0.201306101825-r'
+
+ testFixturesRuntime 'com.h2database:h2:1.3.171'
+
+ testCompile libraries.jsoup
}
useTestFixtures()
+useClassycle()
+
+task reportResources(type: Copy) {
+ from configurations.reports
+ into "$generatedResourcesDir/org/gradle/reporting"
+}
+sourceSets.main.output.dir generatedResourcesDir, builtBy: reportResources
task small(type: ProjectGeneratorTask, description: 'Generates a small project') {
}
@@ -91,74 +112,40 @@ task lotDependencies(type: ProjectGeneratorTask, description: 'Generates a small
}
task manyProjects(type: ProjectGeneratorTask) {
- projects = 500
- sourceFiles = 0
-}
-
-task singleProjectNoBuildScript(type: ProjectGeneratorTask) {
- projects = 1
- sourceFiles = 0
- rootProjectTemplates = []
- subProjectTemplates = []
-}
-
-task manyProjectNoBuildScript(type: ProjectGeneratorTask) {
- projects = 500
- sourceFiles = 0
- rootProjectTemplates = []
- subProjectTemplates = []
-}
-
-task manyProjectMinimalBuildScript(type: ProjectGeneratorTask) {
- projects = 500
+ projects = 100
sourceFiles = 0
- rootProjectTemplates = ['minimal']
- subProjectTemplates = ['minimal']
}
-task manyProjectConfigInject(type: ProjectGeneratorTask) {
- projects = 500
- sourceFiles = 0
- rootProjectTemplates = ['config-inject']
- subProjectTemplates = []
-}
-
-task compilePlugin(type: JavaCompile) {
- source 'src/configPlugin'
- destinationDir file("$buildDir/configPlugin")
- classpath = configurations.plugin
-}
-
-task manyProjectJavaConfig(type: ProjectGeneratorTask, dependsOn: compilePlugin) {
- projects = 500
- sourceFiles = 0
- rootProjectTemplates = ['java-config']
- subProjectTemplates = []
-}
-
-def generators = tasks.withType(ProjectGeneratorTask)
-generators.all {
+def generators = tasks.withType(ProjectGeneratorTask) {
group = 'Project setup'
testDependencies = configurations.junit
}
-task all(dependsOn: generators)
-task prepareSamples(dependsOn: [small, multi, lotDependencies, withJUnit, withTestNG, withVerboseTestNG, withVerboseJUnit])
+task all(dependsOn: generators)
-integTestTasks.all {
- if (buildTypes.isActive('performanceTest') || buildTypes.isActive('localPerformanceTest')) {
- dependsOn prepareSamples
- } else {
- gradle.startParameter.excludedTaskNames << it.path
+task prepareSamples(dependsOn: [small, multi, lotDependencies, withJUnit, withTestNG, withVerboseTestNG, withVerboseJUnit, manyProjects])
+
+task report {
+ def reportDir = new File(buildDir, "performance-tests/report")
+ inputs.files sourceSets.testFixtures.runtimeClasspath
+ outputs.dir reportDir
+
+ doLast {
+ def cl = new URLClassLoader(sourceSets.testFixtures.runtimeClasspath.collect { it.toURI().toURL()} as URL[], ClassLoader.systemClassLoader.parent)
+ def store = cl.loadClass("org.gradle.performance.results.ResultsStore").newInstance()
+ try {
+ def generator = cl.loadClass("org.gradle.performance.results.ReportGenerator").newInstance()
+ generator.generate(store, reportDir)
+ } finally {
+ store.close()
+ }
}
- maxParallelForks = 1
}
-tasks.integTest.testLogging {
- showStandardStreams = true
- lifecycle {
- exceptionFormat 'full'
- }
+integTestTasks.all {
+ dependsOn prepareSamples
+ finalizedBy report
+ maxParallelForks = 1
}
eclipse {
diff --git a/subprojects/performance/src/integTest/groovy/org/gradle/performance/CleanBuildPerformanceTest.groovy b/subprojects/performance/src/integTest/groovy/org/gradle/performance/CleanBuildPerformanceTest.groovy
index 6863035..892f74c 100644
--- a/subprojects/performance/src/integTest/groovy/org/gradle/performance/CleanBuildPerformanceTest.groovy
+++ b/subprojects/performance/src/integTest/groovy/org/gradle/performance/CleanBuildPerformanceTest.groovy
@@ -19,20 +19,16 @@ package org.gradle.performance
import org.gradle.performance.fixture.AbstractPerformanceTest
import spock.lang.Unroll
-import static org.gradle.performance.fixture.DataAmount.kbytes
-import static org.gradle.performance.fixture.Duration.millis
+import static org.gradle.performance.measure.Duration.millis
-/**
- * by Szczepan Faber, created at: 2/9/12
- */
class CleanBuildPerformanceTest extends AbstractPerformanceTest {
@Unroll("Project '#testProject' clean build")
def "clean build"() {
given:
+ runner.testId = "clean build $testProject"
runner.testProject = testProject
runner.tasksToRun = ['clean', 'build']
runner.maxExecutionTimeRegression = maxExecutionTimeRegression
- runner.maxMemoryRegression = kbytes(3000)
when:
def result = runner.run()
diff --git a/subprojects/performance/src/integTest/groovy/org/gradle/performance/DependencyReportPerformanceTest.groovy b/subprojects/performance/src/integTest/groovy/org/gradle/performance/DependencyReportPerformanceTest.groovy
index 5b8aaff..c9fb4d1 100644
--- a/subprojects/performance/src/integTest/groovy/org/gradle/performance/DependencyReportPerformanceTest.groovy
+++ b/subprojects/performance/src/integTest/groovy/org/gradle/performance/DependencyReportPerformanceTest.groovy
@@ -19,20 +19,16 @@ package org.gradle.performance
import org.gradle.performance.fixture.AbstractPerformanceTest
import spock.lang.Unroll
-import static org.gradle.performance.fixture.DataAmount.kbytes
-import static org.gradle.performance.fixture.Duration.millis
+import static org.gradle.performance.measure.Duration.millis
-/**
- * by Szczepan Faber, created at: 2/9/12
- */
class DependencyReportPerformanceTest extends AbstractPerformanceTest {
@Unroll("Project '#testProject' dependency report")
def "dependency report"() {
given:
+ runner.testId = "dependencyReport $testProject"
runner.testProject = testProject
runner.tasksToRun = ['dependencyReport']
runner.maxExecutionTimeRegression = maxExecutionTimeRegression
- runner.maxMemoryRegression = maxMemoryRegression
when:
def result = runner.run()
@@ -41,7 +37,7 @@ class DependencyReportPerformanceTest extends AbstractPerformanceTest {
result.assertCurrentVersionHasNotRegressed()
where:
- testProject | maxExecutionTimeRegression | maxMemoryRegression
- "lotDependencies" | millis(7000) | kbytes(3000)
+ testProject | maxExecutionTimeRegression
+ "lotDependencies" | millis(500)
}
}
\ No newline at end of file
diff --git a/subprojects/performance/src/integTest/groovy/org/gradle/performance/DependencyResolutionStressTest.groovy b/subprojects/performance/src/integTest/groovy/org/gradle/performance/DependencyResolutionStressTest.groovy
index ab5f057..98fec2a 100644
--- a/subprojects/performance/src/integTest/groovy/org/gradle/performance/DependencyResolutionStressTest.groovy
+++ b/subprojects/performance/src/integTest/groovy/org/gradle/performance/DependencyResolutionStressTest.groovy
@@ -78,8 +78,9 @@ task check << {
}
"""
- GradleExecuter executer = distribution.executer(workspace)
- executer.requireGradleHome().requireOwnGradleUserHomeDir()
+ GradleExecuter executer = distribution.executer(workspace).
+ requireGradleHome().
+ withGradleUserHomeDir(workspace.file("user-home"))
10.times {
executer.inDirectory(buildDir).withArgument("--refresh-dependencies").withTasks('check').run()
}
diff --git a/subprojects/performance/src/integTest/groovy/org/gradle/performance/FirstBuildPerformanceTest.groovy b/subprojects/performance/src/integTest/groovy/org/gradle/performance/FirstBuildPerformanceTest.groovy
new file mode 100644
index 0000000..59086df
--- /dev/null
+++ b/subprojects/performance/src/integTest/groovy/org/gradle/performance/FirstBuildPerformanceTest.groovy
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.performance
+
+import org.gradle.performance.fixture.AbstractPerformanceTest
+import spock.lang.Unroll
+
+import static org.gradle.performance.measure.DataAmount.mbytes
+import static org.gradle.performance.measure.Duration.millis
+
+class FirstBuildPerformanceTest extends AbstractPerformanceTest {
+ @Unroll("Project '#testProject' first use")
+ def "build"() {
+ // This is just an approximation of first use. We simply recompile the scripts
+ given:
+ runner.testId = "first use $testProject"
+ runner.testProject = testProject
+ runner.tasksToRun = ['help']
+ runner.args = ['--recompile-scripts']
+ runner.maxExecutionTimeRegression = maxExecutionTimeRegression
+ runner.maxMemoryRegression = maxMemoryRegression
+
+ when:
+ def result = runner.run()
+
+ then:
+ result.assertCurrentVersionHasNotRegressed()
+
+ where:
+ testProject | maxExecutionTimeRegression | maxMemoryRegression
+ "manyProjects" | millis(500) | mbytes(10)
+ }
+}
\ No newline at end of file
diff --git a/subprojects/performance/src/integTest/groovy/org/gradle/performance/IdeIntegrationPerformanceTest.groovy b/subprojects/performance/src/integTest/groovy/org/gradle/performance/IdeIntegrationPerformanceTest.groovy
index 1a8b65f..147458c 100644
--- a/subprojects/performance/src/integTest/groovy/org/gradle/performance/IdeIntegrationPerformanceTest.groovy
+++ b/subprojects/performance/src/integTest/groovy/org/gradle/performance/IdeIntegrationPerformanceTest.groovy
@@ -19,20 +19,16 @@ package org.gradle.performance
import org.gradle.performance.fixture.AbstractPerformanceTest
import spock.lang.Unroll
-import static org.gradle.performance.fixture.DataAmount.kbytes
-import static org.gradle.performance.fixture.Duration.millis
+import static org.gradle.performance.measure.Duration.millis
-/**
- * by Szczepan Faber, created at: 2/9/12
- */
class IdeIntegrationPerformanceTest extends AbstractPerformanceTest {
@Unroll("Project '#testProject' eclipse")
def "eclipse"() {
given:
+ runner.testId = "eclipse $testProject"
runner.testProject = testProject
runner.tasksToRun = ['eclipse']
runner.maxExecutionTimeRegression = maxExecutionTimeRegression
- runner.maxMemoryRegression = kbytes(3000)
when:
def result = runner.run()
@@ -42,7 +38,7 @@ class IdeIntegrationPerformanceTest extends AbstractPerformanceTest {
where:
testProject | maxExecutionTimeRegression
- "small" | millis(500)
+ "small" | millis(700)
"multi" | millis(1500)
"lotDependencies" | millis(3000)
}
@@ -50,10 +46,10 @@ class IdeIntegrationPerformanceTest extends AbstractPerformanceTest {
@Unroll("Project '#testProject' idea")
def "idea"() {
given:
+ runner.testId = "idea $testProject"
runner.testProject = testProject
runner.tasksToRun = ['idea']
runner.maxExecutionTimeRegression = maxExecutionTimeRegression
- runner.maxMemoryRegression = kbytes(3000)
when:
def result = runner.run()
@@ -63,7 +59,7 @@ class IdeIntegrationPerformanceTest extends AbstractPerformanceTest {
where:
testProject | maxExecutionTimeRegression
- "small" | millis(500)
+ "small" | millis(700)
"multi" | millis(1500)
"lotDependencies" | millis(3000)
}
diff --git a/subprojects/performance/src/integTest/groovy/org/gradle/performance/TestExecutionPerformanceTest.groovy b/subprojects/performance/src/integTest/groovy/org/gradle/performance/TestExecutionPerformanceTest.groovy
index 6676d3a..02d90ef 100644
--- a/subprojects/performance/src/integTest/groovy/org/gradle/performance/TestExecutionPerformanceTest.groovy
+++ b/subprojects/performance/src/integTest/groovy/org/gradle/performance/TestExecutionPerformanceTest.groovy
@@ -19,21 +19,17 @@ package org.gradle.performance
import org.gradle.performance.fixture.AbstractPerformanceTest
import spock.lang.Unroll
-import static org.gradle.performance.fixture.DataAmount.kbytes
-import static org.gradle.performance.fixture.Duration.millis
+import static org.gradle.performance.measure.Duration.millis
-/**
- * by Szczepan Faber, created at: 2/9/12
- */
class TestExecutionPerformanceTest extends AbstractPerformanceTest {
- @Unroll("Project '#testProject'")
+ @Unroll("Project '#testProject' test execution")
def "test execution"() {
given:
+ runner.testId = "test $testProject"
runner.testProject = testProject
runner.tasksToRun = ['cleanTest', 'test']
runner.args = ['-q']
runner.maxExecutionTimeRegression = maxExecutionTimeRegression
- runner.maxMemoryRegression = kbytes(3000)
when:
def result = runner.run()
diff --git a/subprojects/performance/src/integTest/groovy/org/gradle/performance/UpToDateBuildPerformanceTest.groovy b/subprojects/performance/src/integTest/groovy/org/gradle/performance/UpToDateBuildPerformanceTest.groovy
index 2441900..efa6832 100644
--- a/subprojects/performance/src/integTest/groovy/org/gradle/performance/UpToDateBuildPerformanceTest.groovy
+++ b/subprojects/performance/src/integTest/groovy/org/gradle/performance/UpToDateBuildPerformanceTest.groovy
@@ -19,20 +19,16 @@ package org.gradle.performance
import org.gradle.performance.fixture.AbstractPerformanceTest
import spock.lang.Unroll
-import static org.gradle.performance.fixture.DataAmount.kbytes
-import static org.gradle.performance.fixture.Duration.millis
+import static org.gradle.performance.measure.Duration.millis
-/**
- * by Szczepan Faber, created at: 2/9/12
- */
class UpToDateBuildPerformanceTest extends AbstractPerformanceTest {
@Unroll("Project '#testProject' up-to-date build")
def "build"() {
given:
+ runner.testId = "up-to-date build $testProject"
runner.testProject = testProject
runner.tasksToRun = ['build']
runner.maxExecutionTimeRegression = maxExecutionTimeRegression
- runner.maxMemoryRegression = kbytes(3000)
when:
def result = runner.run()
diff --git a/subprojects/performance/src/templates/project-with-source/build.gradle b/subprojects/performance/src/templates/project-with-source/build.gradle
index 29561d0..4e8421f 100644
--- a/subprojects/performance/src/templates/project-with-source/build.gradle
+++ b/subprojects/performance/src/templates/project-with-source/build.gradle
@@ -53,5 +53,6 @@ tasks.withType(ScalaCompile) {
<% } %>
task dependencyReport(type: DependencyReportTask) {
+ outputs.upToDateWhen { false }
outputFile = new File(buildDir, "dependencies.txt")
}
diff --git a/subprojects/performance/src/test/groovy/org/gradle/performance/ResultSpecification.groovy b/subprojects/performance/src/test/groovy/org/gradle/performance/ResultSpecification.groovy
new file mode 100644
index 0000000..dd2f9fa
--- /dev/null
+++ b/subprojects/performance/src/test/groovy/org/gradle/performance/ResultSpecification.groovy
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.performance
+
+import org.gradle.performance.fixture.PerformanceResults
+import org.gradle.performance.measure.Amount
+import org.gradle.performance.measure.DataAmount
+import org.gradle.performance.measure.Duration
+import org.gradle.performance.measure.MeasuredOperation
+import spock.lang.Specification
+
+class ResultSpecification extends Specification {
+ PerformanceResults results(Map<String, ?> options = [:]) {
+ def results = new PerformanceResults()
+ results.testId = "test-id"
+ results.testProject = "test-project"
+ results.tasks = ["clean", "build"]
+ results.args = []
+ results.operatingSystem = "some os"
+ results.jvm = "java 6"
+ results.versionUnderTest = "1.7-rc-1"
+ results.vcsBranch = "master"
+ options.each { key, value -> results."$key" = value }
+ return results
+ }
+
+ MeasuredOperation operation(Map<String, Object> args = [:]) {
+ def operation = new MeasuredOperation()
+ operation.executionTime = args.executionTime instanceof Amount ? args.executionTime : Duration.millis(args?.executionTime ?: 120)
+ operation.totalMemoryUsed = args.heapUsed instanceof Amount ? args.heapUsed : DataAmount.bytes(args?.heapUsed ?: 1024)
+ operation.exception = args?.failure
+ return operation
+ }
+}
diff --git a/subprojects/performance/src/test/groovy/org/gradle/performance/fixture/AmountTest.groovy b/subprojects/performance/src/test/groovy/org/gradle/performance/fixture/AmountTest.groovy
deleted file mode 100644
index 5aa2e86..0000000
--- a/subprojects/performance/src/test/groovy/org/gradle/performance/fixture/AmountTest.groovy
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.performance.fixture
-
-import spock.lang.Specification
-
-class AmountTest extends Specification {
-
- def "toString() retains original measurement"() {
- expect:
- Amount.valueOf(value, units).toString() == str
-
- where:
- value | units | str
- 0 | Fruit.apples | "0 apples"
- 1 | Fruit.apples | "1 apple"
- 1000 | Fruit.apples | "1000 apples"
- 0.123 | Fruit.apples | "0.123 apples"
- 0.333333 | Fruit.apples | "0.333333 apples"
- 0.5555 | Fruit.apples | "0.5555 apples"
- -12 | Fruit.apples | "-12 apples"
- 145 | Fruit.oranges | "145 oranges"
- 0.23 | Fruit.grapefruit | "0.23 grapefruit"
- }
-
- def "format() displays amount in highest possible units with rounded value"() {
- expect:
- Amount.valueOf(value, units).format() == str
-
- where:
- value | units | str
- 0 | Fruit.apples | "0 apples"
- 1 | Fruit.apples | "1 apple"
- 0.032 | Fruit.apples | "0.032 apples"
- 2.367722 | Fruit.apples | "2.368 apples"
- 3 | Fruit.apples | "1 orange"
- 5 | Fruit.apples | "1 grapefruit"
- 4 | Fruit.apples | "1.333 oranges"
- 1000 | Fruit.oranges | "600 grapefruit"
- 42 | Fruit.oranges | "25.2 grapefruit"
- 0.45 | Fruit.oranges | "1.35 apples"
- -12 | Fruit.apples | "-2.4 grapefruit"
- }
-
- def "can convert to specific units"() {
- expect:
- Amount.valueOf(value, fromUnits).toUnits(toUnits) == Amount.valueOf(converted, toUnits)
- Amount.valueOf(value, fromUnits).toUnits(toUnits).toString() == Amount.valueOf(converted, toUnits).toString()
-
- where:
- value | fromUnits | toUnits | converted
- 21 | Fruit.apples | Fruit.apples | 21
- 2.1 | Fruit.oranges | Fruit.apples | 6.3
- 1024 | Fruit.grapefruit | Fruit.apples | 1024 * 5
- 1 | Fruit.apples | Fruit.grapefruit | 0.2
- 1 | Fruit.apples | Fruit.oranges | 0.333333
- }
-
- def "amounts are equal when normalised values are the same"() {
- expect:
- def a = Amount.valueOf(valueA, unitsA)
- def b = Amount.valueOf(valueB, unitsB)
- a.equals(b)
- b.equals(a)
- a.hashCode() == b.hashCode()
- a.compareTo(b) == 0
- b.compareTo(a) == 0
-
- where:
- valueA | unitsA | valueB | unitsB
- 0 | Fruit.apples | 0 | Fruit.apples
- 0 | Fruit.apples | 0 | Fruit.oranges
- 9 | Fruit.apples | 3 | Fruit.oranges
- 5 | Fruit.oranges | 3 | Fruit.grapefruit
- 6.3399 | Fruit.apples | 2.1133 | Fruit.oranges
- 0.333 | Fruit.apples | 0.333 | Fruit.apples
- 0.55667 | Fruit.apples | 0.55667 | Fruit.apples
- }
-
- def "amounts are not equal when normalised values are different"() {
- expect:
- def a = Amount.valueOf(valueA, unitsA)
- def b = Amount.valueOf(valueB, unitsB)
- !a.equals(b)
- !b.equals(a)
- a.hashCode() != b.hashCode()
- a.compareTo(b) != 0
- b.compareTo(a) != 0
-
- where:
- valueA | unitsA | valueB | unitsB
- 0 | Fruit.apples | 1 | Fruit.apples
- 0.334 | Fruit.apples | 0.333 | Fruit.apples
- 0.334 | Fruit.apples | 0.33433 | Fruit.apples
- 1 | Fruit.apples | 1 | Fruit.oranges
- 1 | Fruit.grapefruit | 1 | Fruit.oranges
- }
-
- def "can compare values"() {
- expect:
- def a = Amount.valueOf(valueA, unitsA)
- def b = Amount.valueOf(valueB, unitsB)
- a < b
- b > a
- a != b
- b != a
-
- where:
- valueA | unitsA | valueB | unitsB
- 0.1 | Fruit.oranges | 0.101 | Fruit.oranges
- 0.33333 | Fruit.oranges | 1 | Fruit.apples
- 1 | Fruit.apples | 1 | Fruit.oranges
- 1 | Fruit.oranges | 1 | Fruit.grapefruit
- -1 | Fruit.apples | 0 | Fruit.oranges
- 5.9 | Fruit.apples | 2 | Fruit.oranges
- }
-
- def "can add amounts with same units"() {
- expect:
- Amount.valueOf(a, units) + Amount.valueOf(b, units) == Amount.valueOf(c, units)
-
- where:
- a | b | c | units
- 0 | 0 | 0 | Fruit.apples
- 1 | 2 | 3 | Fruit.apples
- 1 | 2 | 3 | Fruit.oranges
- 23.4 | 0.567 | 23.967 | Fruit.apples
- }
-
- def "can add amounts with different units of same quantity"() {
- def sum = Amount.valueOf(valueA, unitsA) + Amount.valueOf(valueB, unitsB)
- expect:
- sum == Amount.valueOf(valueC, unitsC)
- sum.toString() == Amount.valueOf(valueC, unitsC).toString()
-
- where:
- valueA | unitsA | valueB | unitsB | valueC | unitsC
- 0 | Fruit.apples | 0 | Fruit.oranges | 0 | Fruit.apples
- 0 | Fruit.apples | 12 | Fruit.oranges | 12 | Fruit.oranges
- 0.7 | Fruit.apples | 0 | Fruit.oranges | 0.7 | Fruit.apples
- 1 | Fruit.apples | 2 | Fruit.oranges | 7 | Fruit.apples
- 3 | Fruit.oranges | 4 | Fruit.oranges | 7 | Fruit.oranges
- 12.45 | Fruit.apples | 0.2222 | Fruit.oranges | 13.1166 | Fruit.apples
- }
-
- def "can subtract amounts with same units"() {
- expect:
- Amount.valueOf(a, units) - Amount.valueOf(b, units) == Amount.valueOf(c, units)
-
- where:
- a | b | c | units
- 0 | 0 | 0 | Fruit.apples
- 2 | 1 | 1 | Fruit.apples
- 123 | 12 | 111 | Fruit.oranges
- 10 | 56 | -46 | Fruit.apples
- 23.4 | 0.567 | 22.833 | Fruit.apples
- }
-
- def "can subtract amounts with different units of same quantity"() {
- def difference = Amount.valueOf(valueA, unitsA) - Amount.valueOf(valueB, unitsB)
- expect:
- difference == Amount.valueOf(valueC, unitsC)
- difference.toString() == Amount.valueOf(valueC, unitsC).toString()
-
- where:
- valueA | unitsA | valueB | unitsB | valueC | unitsC
- 0 | Fruit.apples | 0 | Fruit.oranges | 0 | Fruit.apples
- 1 | Fruit.oranges | 0 | Fruit.apples | 1 | Fruit.oranges
- 4 | Fruit.apples | 1 | Fruit.oranges | 1 | Fruit.apples
- 2 | Fruit.apples | 1 | Fruit.oranges | -1 | Fruit.apples
- 0 | Fruit.apples | 12 | Fruit.oranges | -36 | Fruit.apples
- 0.7 | Fruit.apples | 0 | Fruit.oranges | 0.7 | Fruit.apples
- 0.7 | Fruit.oranges | 1 | Fruit.apples | 1.1 | Fruit.apples
- 12.45 | Fruit.apples | 0.2222 | Fruit.oranges | 11.7834 | Fruit.apples
- }
-
- def "can divide amount by a unitless value"() {
- expect:
- Amount.valueOf(a, Fruit.apples) / b == Amount.valueOf(c, Fruit.apples)
-
- where:
- a | b | c
- 0 | 200 | 0
- 2 | 1 | 2
- 5 | 10 | 0.5
- 10 | -2 | -5
- 1 | 3 | 0.333333
- 2 | 3 | 0.666667
- }
-
- def "can divide amount by another amount of same quantity"() {
- expect:
- Amount.valueOf(valueA, unitsA) / Amount.valueOf(valueB, unitsB) == result
-
- where:
- valueA | unitsA | valueB | unitsB | result
- 0 | Fruit.apples | 200 | Fruit.apples | 0
- 2 | Fruit.apples | 1 | Fruit.apples | 2
- 5 | Fruit.apples | 10 | Fruit.apples | 0.5
- 10 | Fruit.apples | -2 | Fruit.apples | -5
- 1 | Fruit.apples | 3 | Fruit.apples | 0.333333
- 2 | Fruit.apples | 3 | Fruit.apples | 0.666667
- 4 | Fruit.apples | 1.2 | Fruit.oranges | 1.111111
- 125 | Fruit.oranges | 23.4 | Fruit.grapefruit | 3.205128
- }
-
- def "can convert to absolute value"() {
- expect:
- Amount.valueOf(12, Fruit.grapefruit).abs() == Amount.valueOf(12, Fruit.grapefruit)
- Amount.valueOf(-34, Fruit.grapefruit).abs() == Amount.valueOf(34, Fruit.grapefruit)
- }
-
- public static class Fruit {
- static def apples = Units.base(Fruit.class, "apple", "apples")
- static def oranges = apples.times(3, "orange", "oranges")
- static def grapefruit = apples.times(5, "grapefruit")
- }
-}
diff --git a/subprojects/performance/src/test/groovy/org/gradle/performance/fixture/DurationTest.groovy b/subprojects/performance/src/test/groovy/org/gradle/performance/fixture/DurationTest.groovy
deleted file mode 100644
index f6e7b99..0000000
--- a/subprojects/performance/src/test/groovy/org/gradle/performance/fixture/DurationTest.groovy
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.performance.fixture
-
-import spock.lang.Specification
-
-class DurationTest extends Specification {
- def "millisecond durations have useful string formats"() {
- expect:
- Duration.millis(millis).toString() == str
- Duration.millis(millis).format() == formatted
-
- where:
- millis | str | formatted
- 0 | "0 ms" | "0 ms"
- 1 | "1 ms" | "1 ms"
- 0.123 | "0.123 ms" | "0.123 ms"
- -12 | "-12 ms" | "-12 ms"
- 1000 | "1000 ms" | "1 s"
- 123456 | "123456 ms" | "2.058 m"
- 3607000 | "3607000 ms" | "1.002 h"
- }
-
- def "second durations have useful string formats"() {
- expect:
- Duration.seconds(millis).toString() == str
-
- where:
- millis | str | format
- 0 | "0 s" | "0 ms"
- 1 | "1 s" | "1 s"
- 1000 | "1000 s" | "16.667 m"
- 0.123 | "0.123 s" | "123 ms"
- 0.1234567 | "0.1234567 s" | "123.457 ms"
- -12 | "-12 s" | "-12 s"
- }
-
- def "can convert between units"() {
- expect:
- Duration.millis(45000) == Duration.seconds(45)
- Duration.seconds(0.98) == Duration.millis(980)
- Duration.seconds(120) == Duration.minutes(2)
- Duration.seconds(30) == Duration.minutes(0.5)
- Duration.hours(30) == Duration.millis(30 * 60 * 60 * 1000)
- }
-}
diff --git a/subprojects/performance/src/test/groovy/org/gradle/performance/fixture/PerformanceResultsTest.groovy b/subprojects/performance/src/test/groovy/org/gradle/performance/fixture/PerformanceResultsTest.groovy
index 30bf52d..b16584e 100644
--- a/subprojects/performance/src/test/groovy/org/gradle/performance/fixture/PerformanceResultsTest.groovy
+++ b/subprojects/performance/src/test/groovy/org/gradle/performance/fixture/PerformanceResultsTest.groovy
@@ -16,18 +16,18 @@
package org.gradle.performance.fixture
-import spock.lang.Specification
+import org.gradle.performance.ResultSpecification
+import org.gradle.performance.measure.DataAmount
+import org.gradle.performance.measure.Duration
-import static org.gradle.performance.fixture.BaselineVersion.baseline
-
-class PerformanceResultsTest extends Specification {
- def PerformanceResults result = new PerformanceResults()
+class PerformanceResultsTest extends ResultSpecification {
+ def PerformanceResults result = new PerformanceResults(testProject: "some-project", tasks: [])
def "passes when average execution time for current release is smaller than average execution time for previous releases"() {
given:
- result.baselineVersions[0].results.add(operation(executionTime: 110))
- result.baselineVersions[0].results.add(operation(executionTime: 100))
- result.baselineVersions[0].results.add(operation(executionTime: 90))
+ result.baseline("1.0").results.add(operation(executionTime: 110))
+ result.baseline("1.0").results.add(operation(executionTime: 100))
+ result.baseline("1.0").results.add(operation(executionTime: 90))
and:
result.current.add(operation(executionTime: 90))
@@ -40,15 +40,14 @@ class PerformanceResultsTest extends Specification {
def "passes when average execution time for current release is within specified range of average execution time for previous releases"() {
given:
- result.baselineVersions[0].maxExecutionTimeRegression = Duration.millis(10)
- result.baselineVersions[0].results << operation(executionTime: 100)
- result.baselineVersions[0].results << operation(executionTime: 100)
- result.baselineVersions[0].results << operation(executionTime: 100)
+ result.baseline("1.0").maxExecutionTimeRegression = Duration.millis(10)
+ result.baseline("1.0").results << operation(executionTime: 100)
+ result.baseline("1.0").results << operation(executionTime: 100)
+ result.baseline("1.0").results << operation(executionTime: 100)
- result.baselineVersions << baseline("1.3")
- result.baselineVersions[1].results << operation(executionTime: 115)
- result.baselineVersions[1].results << operation(executionTime: 105)
- result.baselineVersions[1].results << operation(executionTime: 110)
+ result.baseline("1.3").results << operation(executionTime: 115)
+ result.baseline("1.3").results << operation(executionTime: 105)
+ result.baseline("1.3").results << operation(executionTime: 110)
and:
result.current << operation(executionTime: 110)
@@ -61,19 +60,15 @@ class PerformanceResultsTest extends Specification {
def "fails when average execution time for current release is larger than average execution time for previous releases"() {
given:
- result.displayName = '<test>'
-
- result.baselineVersions[0].version = '1.2' //fail
- result.baselineVersions[0].maxExecutionTimeRegression = Duration.millis(10)
- result.baselineVersions[0].results << operation(executionTime: 100)
- result.baselineVersions[0].results << operation(executionTime: 100)
- result.baselineVersions[0].results << operation(executionTime: 100)
+ result.baseline("1.0").maxExecutionTimeRegression = Duration.millis(10)
+ result.baseline("1.0").results << operation(executionTime: 100)
+ result.baseline("1.0").results << operation(executionTime: 100)
+ result.baseline("1.0").results << operation(executionTime: 100)
- result.baselineVersions << baseline("1.3") //pass
- result.baselineVersions[1].maxExecutionTimeRegression = Duration.millis(10)
- result.baselineVersions[1].results << operation(executionTime: 101)
- result.baselineVersions[1].results << operation(executionTime: 100)
- result.baselineVersions[1].results << operation(executionTime: 100)
+ result.baseline("1.3").maxExecutionTimeRegression = Duration.millis(10)
+ result.baseline("1.3").results << operation(executionTime: 101)
+ result.baseline("1.3").results << operation(executionTime: 100)
+ result.baseline("1.3").results << operation(executionTime: 100)
and:
result.current << operation(executionTime: 110)
@@ -85,21 +80,20 @@ class PerformanceResultsTest extends Specification {
then:
AssertionError e = thrown()
- e.message.startsWith("Speed <test>: we're slower than 1.2.")
+ e.message.startsWith("Speed ${result.displayName}: we're slower than 1.0.")
e.message.contains('Difference: 10.333 ms slower (10.333 ms), 10.33%')
!e.message.contains('1.3')
}
def "passes when average heap usage for current release is smaller than average heap usage for previous releases"() {
given:
- result.baselineVersions[0].results << operation(heapUsed: 1000)
- result.baselineVersions[0].results << operation(heapUsed: 1000)
- result.baselineVersions[0].results << operation(heapUsed: 1000)
+ result.baseline("1.0").results << operation(heapUsed: 1000)
+ result.baseline("1.0").results << operation(heapUsed: 1000)
+ result.baseline("1.0").results << operation(heapUsed: 1000)
- result.baselineVersions << baseline("1.3")
- result.baselineVersions[1].results << operation(heapUsed: 800)
- result.baselineVersions[1].results << operation(heapUsed: 1000)
- result.baselineVersions[1].results << operation(heapUsed: 1200)
+ result.baseline("1.3").results << operation(heapUsed: 800)
+ result.baseline("1.3").results << operation(heapUsed: 1000)
+ result.baseline("1.3").results << operation(heapUsed: 1200)
and:
result.current << operation(heapUsed: 1000)
@@ -112,16 +106,15 @@ class PerformanceResultsTest extends Specification {
def "passes when average heap usage for current release is slightly larger than average heap usage for previous releases"() {
given:
- result.baselineVersions[0].maxMemoryRegression = DataAmount.bytes(100)
- result.baselineVersions[0].results << operation(heapUsed: 1000)
- result.baselineVersions[0].results << operation(heapUsed: 1000)
- result.baselineVersions[0].results << operation(heapUsed: 1000)
+ result.baseline("1.0").maxMemoryRegression = DataAmount.bytes(100)
+ result.baseline("1.0").results << operation(heapUsed: 1000)
+ result.baseline("1.0").results << operation(heapUsed: 1000)
+ result.baseline("1.0").results << operation(heapUsed: 1000)
- result.baselineVersions << baseline("1.3")
- result.baselineVersions[1].maxMemoryRegression = DataAmount.bytes(100)
- result.baselineVersions[1].results << operation(heapUsed: 900)
- result.baselineVersions[1].results << operation(heapUsed: 1000)
- result.baselineVersions[1].results << operation(heapUsed: 1100)
+ result.baseline("1.3").maxMemoryRegression = DataAmount.bytes(100)
+ result.baseline("1.3").results << operation(heapUsed: 900)
+ result.baseline("1.3").results << operation(heapUsed: 1000)
+ result.baseline("1.3").results << operation(heapUsed: 1100)
and:
result.current << operation(heapUsed: 1100)
@@ -134,19 +127,15 @@ class PerformanceResultsTest extends Specification {
def "fails when average heap usage for current release is larger than average heap usage for previous releases"() {
given:
- result.displayName = '<test>'
-
- result.baselineVersions[0].version = "1.1" //pass
- result.baselineVersions[0].maxMemoryRegression = DataAmount.bytes(100)
- result.baselineVersions[0].results << operation(heapUsed: 1001)
- result.baselineVersions[0].results << operation(heapUsed: 1001)
- result.baselineVersions[0].results << operation(heapUsed: 1001)
+ result.baseline("1.0").maxMemoryRegression = DataAmount.bytes(100)
+ result.baseline("1.0").results << operation(heapUsed: 1001)
+ result.baseline("1.0").results << operation(heapUsed: 1001)
+ result.baseline("1.0").results << operation(heapUsed: 1001)
- result.baselineVersions << baseline("1.2") //fail
- result.baselineVersions[1].maxMemoryRegression = DataAmount.bytes(100)
- result.baselineVersions[1].results << operation(heapUsed: 1000)
- result.baselineVersions[1].results << operation(heapUsed: 1000)
- result.baselineVersions[1].results << operation(heapUsed: 1000)
+ result.baseline("1.2").maxMemoryRegression = DataAmount.bytes(100)
+ result.baseline("1.2").results << operation(heapUsed: 1000)
+ result.baseline("1.2").results << operation(heapUsed: 1000)
+ result.baseline("1.2").results << operation(heapUsed: 1000)
and:
result.current << operation(heapUsed: 1100)
@@ -158,23 +147,20 @@ class PerformanceResultsTest extends Specification {
then:
AssertionError e = thrown()
- e.message.startsWith('Memory <test>: we need more memory than 1.2.')
+ e.message.startsWith("Memory ${result.displayName}: we need more memory than 1.2.")
e.message.contains('Difference: 100.333 B more (100.333 B), 10.03%')
- !e.message.contains('1.1')
+ !e.message.contains('than 1.0')
}
def "fails when both heap usage and execution time have regressed"() {
given:
- result.displayName = '<test>'
- result.baselineVersions[0].version = '1.1' //pass
- result.baselineVersions[0].results << operation(heapUsed: 1200, executionTime: 150)
- result.baselineVersions[0].results << operation(heapUsed: 1000, executionTime: 100)
- result.baselineVersions[0].results << operation(heapUsed: 1200, executionTime: 150)
+ result.baseline("1.0").results << operation(heapUsed: 1200, executionTime: 150)
+ result.baseline("1.0").results << operation(heapUsed: 1000, executionTime: 100)
+ result.baseline("1.0").results << operation(heapUsed: 1200, executionTime: 150)
- result.baselineVersions << baseline("1.2") //fail
- result.baselineVersions[1].results << operation(heapUsed: 1000, executionTime: 100)
- result.baselineVersions[1].results << operation(heapUsed: 1000, executionTime: 100)
- result.baselineVersions[1].results << operation(heapUsed: 1000, executionTime: 100)
+ result.baseline("1.2").results << operation(heapUsed: 1000, executionTime: 100)
+ result.baseline("1.2").results << operation(heapUsed: 1000, executionTime: 100)
+ result.baseline("1.2").results << operation(heapUsed: 1000, executionTime: 100)
and:
result.current << operation(heapUsed: 1100, executionTime: 110)
@@ -186,16 +172,16 @@ class PerformanceResultsTest extends Specification {
then:
AssertionError e = thrown()
- e.message.contains("Speed <test>: we're slower than 1.2.")
+ e.message.contains("Speed ${result.displayName}: we're slower than 1.2.")
e.message.contains('Difference: 10.333 ms slower (10.333 ms)')
- e.message.contains('Memory <test>: we need more memory than 1.2.')
+ e.message.contains("Memory ${result.displayName}: we need more memory than 1.2.")
e.message.contains('Difference: 100.333 B more (100.333 B)')
- !e.message.contains('1.1')
+ !e.message.contains('than 1.0')
}
def "fails when a previous operation fails"() {
given:
- result.baselineVersions[0].results << operation(failure: new RuntimeException())
+ result.baseline("1.0").results << operation(failure: new RuntimeException())
result.current.add(operation())
when:
@@ -208,7 +194,7 @@ class PerformanceResultsTest extends Specification {
def "fails when a current operation fails"() {
given:
- result.baselineVersions[0].results << operation()
+ result.baseline("1.0").results << operation()
result.current.add(operation(failure: new RuntimeException()))
when:
@@ -222,9 +208,8 @@ class PerformanceResultsTest extends Specification {
def "fails when an operation fails"() {
given:
result.current.add(operation())
- result.baselineVersions << baseline('oldVersion')
- result.baselineVersions[0].results << operation()
- result.baselineVersions[1].results << operation(failure: new RuntimeException())
+ result.baseline("1.0").results << operation()
+ result.baseline("oldVersion").results << operation(failure: new RuntimeException())
when:
result.assertCurrentVersionHasNotRegressed()
@@ -236,14 +221,11 @@ class PerformanceResultsTest extends Specification {
def "fails if one of the baseline version is faster and the other needs less memory"() {
given:
- result.displayName = '<test>'
- result.baselineVersions[0].version = '1.1' //fast
- result.baselineVersions[0].results << operation(heapUsed: 1200, executionTime: 100)
- result.baselineVersions[0].results << operation(heapUsed: 1200, executionTime: 100)
+ result.baseline("1.0").results << operation(heapUsed: 1200, executionTime: 100)
+ result.baseline("1.0").results << operation(heapUsed: 1200, executionTime: 100)
- result.baselineVersions << baseline("1.2") //needs less memory
- result.baselineVersions[1].results << operation(heapUsed: 1000, executionTime: 150)
- result.baselineVersions[1].results << operation(heapUsed: 1000, executionTime: 150)
+ result.baseline("1.2").results << operation(heapUsed: 1000, executionTime: 150)
+ result.baseline("1.2").results << operation(heapUsed: 1000, executionTime: 150)
and:
result.current << operation(heapUsed: 1100, executionTime: 125)
@@ -254,23 +236,20 @@ class PerformanceResultsTest extends Specification {
then:
AssertionError e = thrown()
- e.message.contains("Speed <test>: we're slower than 1.1.")
+ e.message.contains("Speed ${result.displayName}: we're slower than 1.0.")
e.message.contains('Difference: 25 ms slower')
- e.message.contains('Memory <test>: we need more memory than 1.2.')
+ e.message.contains("Memory ${result.displayName}: we need more memory than 1.2.")
e.message.contains('Difference: 100 B more')
- e.message.count('<test>') == 2
+ e.message.count(result.displayName) == 2
}
def "fails if all of the baseline versions are better in every respect"() {
given:
- result.displayName = '<test>'
- result.baselineVersions[0].version = '1.1' //fast
- result.baselineVersions[0].results << operation(heapUsed: 1200, executionTime: 120)
- result.baselineVersions[0].results << operation(heapUsed: 1200, executionTime: 120)
+ result.baseline("1.0").results << operation(heapUsed: 1200, executionTime: 120)
+ result.baseline("1.0").results << operation(heapUsed: 1200, executionTime: 120)
- result.baselineVersions << baseline("1.2") //needs less memory
- result.baselineVersions[1].results << operation(heapUsed: 1100, executionTime: 150)
- result.baselineVersions[1].results << operation(heapUsed: 1100, executionTime: 150)
+ result.baseline("1.2").results << operation(heapUsed: 1100, executionTime: 150)
+ result.baseline("1.2").results << operation(heapUsed: 1100, executionTime: 150)
and:
result.current << operation(heapUsed: 1300, executionTime: 200)
@@ -281,17 +260,9 @@ class PerformanceResultsTest extends Specification {
then:
AssertionError e = thrown()
- e.message.contains("Speed <test>: we're slower than 1.1.")
- e.message.contains("Speed <test>: we're slower than 1.2.")
- e.message.contains('Memory <test>: we need more memory than 1.1.')
- e.message.contains('Memory <test>: we need more memory than 1.2.')
- }
-
- private MeasuredOperation operation(Map<String, Object> args) {
- def operation = new MeasuredOperation()
- operation.executionTime = Duration.millis(args?.executionTime ?: 120)
- operation.totalMemoryUsed = DataAmount.bytes(args?.heapUsed ?: 1024)
- operation.exception = args?.failure
- return operation
+ e.message.contains("Speed ${result.displayName}: we're slower than 1.0.")
+ e.message.contains("Speed ${result.displayName}: we're slower than 1.2.")
+ e.message.contains("Memory ${result.displayName}: we need more memory than 1.0.")
+ e.message.contains("Memory ${result.displayName}: we need more memory than 1.2.")
}
}
diff --git a/subprojects/performance/src/test/groovy/org/gradle/performance/fixture/PerformanceTestRunnerTest.groovy b/subprojects/performance/src/test/groovy/org/gradle/performance/fixture/PerformanceTestRunnerTest.groovy
new file mode 100644
index 0000000..4985b79
--- /dev/null
+++ b/subprojects/performance/src/test/groovy/org/gradle/performance/fixture/PerformanceTestRunnerTest.groovy
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.performance.fixture
+
+import org.gradle.integtests.fixtures.executer.GradleDistribution
+import org.gradle.integtests.fixtures.versions.ReleasedVersionDistributions
+import org.gradle.performance.ResultSpecification
+import org.gradle.performance.measure.DataAmount
+import org.gradle.performance.measure.Duration
+import org.gradle.util.GradleVersion
+
+class PerformanceTestRunnerTest extends ResultSpecification {
+ final timer = Mock(OperationTimer)
+ final reporter = Mock(DataReporter)
+ final testProjectLocator = Stub(TestProjectLocator)
+ final dataCollector = Stub(DataCollector)
+ final currentGradle = Stub(GradleDistribution)
+ final mostRecentRelease = new ReleasedVersionDistributions().mostRecentFinalRelease.version.version
+ final currentVersionBase = GradleVersion.current().baseVersion.version
+
+ def "runs test and builds results"() {
+ given:
+ def runner = runner()
+ runner.testId = 'some-test'
+ runner.testProject = 'test1'
+ runner.targetVersions = ['1.0', '1.1']
+ runner.tasksToRun = ['clean', 'build']
+ runner.args = ['--arg1', '--arg2']
+ runner.warmUpRuns = 1
+ runner.runs = 4
+ runner.maxExecutionTimeRegression = Duration.millis(100)
+ runner.maxMemoryRegression = DataAmount.bytes(10)
+
+ when:
+ def results = runner.run()
+
+ then:
+ results.testId == 'some-test'
+ results.testProject == 'test1'
+ results.tasks == ['clean', 'build']
+ results.args == ['--arg1', '--arg2']
+ results.versionUnderTest
+ results.jvm
+ results.operatingSystem
+ results.current.size() == 4
+ results.current.avgTime() == Duration.seconds(10)
+ results.current.avgMemory() == DataAmount.kbytes(10)
+ results.baselineVersions*.version == ['1.0', '1.1']
+ results.baseline('1.0').results.size() == 4
+ results.baseline('1.1').results.size() == 4
+ results.baselineVersions.every { it.maxExecutionTimeRegression == runner.maxExecutionTimeRegression }
+ results.baselineVersions.every { it.maxMemoryRegression == runner.maxMemoryRegression }
+
+ and:
+ // warmup runs are discarded
+ 3 * timer.measure(_) >> operation(executionTime: Duration.seconds(100), heapUsed: DataAmount.kbytes(100))
+ 12 * timer.measure(_) >> operation(executionTime: Duration.seconds(10), heapUsed: DataAmount.kbytes(10))
+ 1 * reporter.report(_)
+ 0 * timer._
+ 0 * reporter._
+ }
+
+ def "can use 'last' baseline version to refer to most recently released version"() {
+ given:
+ def runner = runner()
+ runner.targetVersions = ['1.0', 'last']
+
+ when:
+ def results = runner.run()
+
+ then:
+ results.baselineVersions*.version == ['1.0', mostRecentRelease]
+ }
+
+ def "ignores baseline version if it has the same base as the version under test"() {
+ given:
+ def runner = runner()
+ runner.targetVersions = ['1.0', currentVersionBase, mostRecentRelease, 'last']
+
+ when:
+ def results = runner.run()
+
+ then:
+ results.baselineVersions*.version == ['1.0', mostRecentRelease]
+ }
+
+ def runner() {
+ return new PerformanceTestRunner(testId: 'some-test',
+ timer: timer, testProjectLocator: testProjectLocator, dataCollector: dataCollector, current: currentGradle, reporter: reporter)
+ }
+}
diff --git a/subprojects/performance/src/test/groovy/org/gradle/performance/fixture/PrettyCalculatorSpec.groovy b/subprojects/performance/src/test/groovy/org/gradle/performance/fixture/PrettyCalculatorSpec.groovy
index a7b3b23..64783c1 100644
--- a/subprojects/performance/src/test/groovy/org/gradle/performance/fixture/PrettyCalculatorSpec.groovy
+++ b/subprojects/performance/src/test/groovy/org/gradle/performance/fixture/PrettyCalculatorSpec.groovy
@@ -16,13 +16,12 @@
package org.gradle.performance.fixture
+import org.gradle.performance.measure.Amount
+import org.gradle.performance.measure.Duration
import spock.lang.Specification
import static org.gradle.performance.fixture.PrettyCalculator.percentChange
-/**
- * by Szczepan Faber, created at: 10/30/12
- */
class PrettyCalculatorSpec extends Specification {
def "knows percentage change"() {
diff --git a/subprojects/performance/src/test/groovy/org/gradle/performance/fixture/UnitsTest.groovy b/subprojects/performance/src/test/groovy/org/gradle/performance/fixture/UnitsTest.groovy
deleted file mode 100644
index ccd0b47..0000000
--- a/subprojects/performance/src/test/groovy/org/gradle/performance/fixture/UnitsTest.groovy
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.performance.fixture
-
-import spock.lang.Specification
-
-class UnitsTest extends Specification {
- def "can compare units of same quantity"() {
- def base = Units.base(Void.class, "base")
- def units1 = base.times(12, "units1")
- def units2 = base.times(33, "units2")
-
- expect:
- base < units1
- base < units2
- units1 > base
- units1 < units2
- units2 > base
- units2 > units1
- }
-}
diff --git a/subprojects/performance/src/test/groovy/org/gradle/performance/measure/AmountTest.groovy b/subprojects/performance/src/test/groovy/org/gradle/performance/measure/AmountTest.groovy
new file mode 100644
index 0000000..7f20c06
--- /dev/null
+++ b/subprojects/performance/src/test/groovy/org/gradle/performance/measure/AmountTest.groovy
@@ -0,0 +1,231 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.performance.measure
+
+import spock.lang.Specification
+
+class AmountTest extends Specification {
+
+ def "toString() retains original measurement"() {
+ expect:
+ Amount.valueOf(value, units).toString() == str
+
+ where:
+ value | units | str
+ 0 | Fruit.apples | "0 apples"
+ 1 | Fruit.apples | "1 apple"
+ 1000 | Fruit.apples | "1000 apples"
+ 0.123 | Fruit.apples | "0.123 apples"
+ 0.333333 | Fruit.apples | "0.333333 apples"
+ 0.5555 | Fruit.apples | "0.5555 apples"
+ -12 | Fruit.apples | "-12 apples"
+ 145 | Fruit.oranges | "145 oranges"
+ 0.23 | Fruit.grapefruit | "0.23 grapefruit"
+ }
+
+ def "format() displays amount in highest possible units with rounded value"() {
+ expect:
+ Amount.valueOf(value, units).format() == str
+
+ where:
+ value | units | str
+ 0 | Fruit.apples | "0 apples"
+ 1 | Fruit.apples | "1 apple"
+ 0.032 | Fruit.apples | "0.032 apples"
+ 2.367722 | Fruit.apples | "2.368 apples"
+ 3 | Fruit.apples | "1 orange"
+ 5 | Fruit.apples | "1 grapefruit"
+ 4 | Fruit.apples | "1.333 oranges"
+ 1000 | Fruit.oranges | "600 grapefruit"
+ 42 | Fruit.oranges | "25.2 grapefruit"
+ 0.45 | Fruit.oranges | "1.35 apples"
+ -12 | Fruit.apples | "-2.4 grapefruit"
+ }
+
+ def "can convert to specific units"() {
+ expect:
+ Amount.valueOf(value, fromUnits).toUnits(toUnits) == Amount.valueOf(converted, toUnits)
+ Amount.valueOf(value, fromUnits).toUnits(toUnits).toString() == Amount.valueOf(converted, toUnits).toString()
+
+ where:
+ value | fromUnits | toUnits | converted
+ 21 | Fruit.apples | Fruit.apples | 21
+ 2.1 | Fruit.oranges | Fruit.apples | 6.3
+ 1024 | Fruit.grapefruit | Fruit.apples | 1024 * 5
+ 1 | Fruit.apples | Fruit.grapefruit | 0.2
+ 1 | Fruit.apples | Fruit.oranges | 0.333333
+ }
+
+ def "amounts are equal when normalised values are the same"() {
+ expect:
+ def a = Amount.valueOf(valueA, unitsA)
+ def b = Amount.valueOf(valueB, unitsB)
+ a.equals(b)
+ b.equals(a)
+ a.hashCode() == b.hashCode()
+ a.compareTo(b) == 0
+ b.compareTo(a) == 0
+
+ where:
+ valueA | unitsA | valueB | unitsB
+ 0 | Fruit.apples | 0 | Fruit.apples
+ 0 | Fruit.apples | 0 | Fruit.oranges
+ 9 | Fruit.apples | 3 | Fruit.oranges
+ 5 | Fruit.oranges | 3 | Fruit.grapefruit
+ 6.3399 | Fruit.apples | 2.1133 | Fruit.oranges
+ 0.333 | Fruit.apples | 0.333 | Fruit.apples
+ 0.55667 | Fruit.apples | 0.55667 | Fruit.apples
+ }
+
+ def "amounts are not equal when normalised values are different"() {
+ expect:
+ def a = Amount.valueOf(valueA, unitsA)
+ def b = Amount.valueOf(valueB, unitsB)
+ !a.equals(b)
+ !b.equals(a)
+ a.hashCode() != b.hashCode()
+ a.compareTo(b) != 0
+ b.compareTo(a) != 0
+
+ where:
+ valueA | unitsA | valueB | unitsB
+ 0 | Fruit.apples | 1 | Fruit.apples
+ 0.334 | Fruit.apples | 0.333 | Fruit.apples
+ 0.334 | Fruit.apples | 0.33433 | Fruit.apples
+ 1 | Fruit.apples | 1 | Fruit.oranges
+ 1 | Fruit.grapefruit | 1 | Fruit.oranges
+ }
+
+ def "can compare values"() {
+ expect:
+ def a = Amount.valueOf(valueA, unitsA)
+ def b = Amount.valueOf(valueB, unitsB)
+ a < b
+ b > a
+ a != b
+ b != a
+
+ where:
+ valueA | unitsA | valueB | unitsB
+ 0.1 | Fruit.oranges | 0.101 | Fruit.oranges
+ 0.33333 | Fruit.oranges | 1 | Fruit.apples
+ 1 | Fruit.apples | 1 | Fruit.oranges
+ 1 | Fruit.oranges | 1 | Fruit.grapefruit
+ -1 | Fruit.apples | 0 | Fruit.oranges
+ 5.9 | Fruit.apples | 2 | Fruit.oranges
+ }
+
+ def "can add amounts with same units"() {
+ expect:
+ Amount.valueOf(a, units) + Amount.valueOf(b, units) == Amount.valueOf(c, units)
+
+ where:
+ a | b | c | units
+ 0 | 0 | 0 | Fruit.apples
+ 1 | 2 | 3 | Fruit.apples
+ 1 | 2 | 3 | Fruit.oranges
+ 23.4 | 0.567 | 23.967 | Fruit.apples
+ }
+
+ def "can add amounts with different units of same quantity"() {
+ def sum = Amount.valueOf(valueA, unitsA) + Amount.valueOf(valueB, unitsB)
+ expect:
+ sum == Amount.valueOf(valueC, unitsC)
+ sum.toString() == Amount.valueOf(valueC, unitsC).toString()
+
+ where:
+ valueA | unitsA | valueB | unitsB | valueC | unitsC
+ 0 | Fruit.apples | 0 | Fruit.oranges | 0 | Fruit.apples
+ 0 | Fruit.apples | 12 | Fruit.oranges | 12 | Fruit.oranges
+ 0.7 | Fruit.apples | 0 | Fruit.oranges | 0.7 | Fruit.apples
+ 1 | Fruit.apples | 2 | Fruit.oranges | 7 | Fruit.apples
+ 3 | Fruit.oranges | 4 | Fruit.oranges | 7 | Fruit.oranges
+ 12.45 | Fruit.apples | 0.2222 | Fruit.oranges | 13.1166 | Fruit.apples
+ }
+
+ def "can subtract amounts with same units"() {
+ expect:
+ Amount.valueOf(a, units) - Amount.valueOf(b, units) == Amount.valueOf(c, units)
+
+ where:
+ a | b | c | units
+ 0 | 0 | 0 | Fruit.apples
+ 2 | 1 | 1 | Fruit.apples
+ 123 | 12 | 111 | Fruit.oranges
+ 10 | 56 | -46 | Fruit.apples
+ 23.4 | 0.567 | 22.833 | Fruit.apples
+ }
+
+ def "can subtract amounts with different units of same quantity"() {
+ def difference = Amount.valueOf(valueA, unitsA) - Amount.valueOf(valueB, unitsB)
+ expect:
+ difference == Amount.valueOf(valueC, unitsC)
+ difference.toString() == Amount.valueOf(valueC, unitsC).toString()
+
+ where:
+ valueA | unitsA | valueB | unitsB | valueC | unitsC
+ 0 | Fruit.apples | 0 | Fruit.oranges | 0 | Fruit.apples
+ 1 | Fruit.oranges | 0 | Fruit.apples | 1 | Fruit.oranges
+ 4 | Fruit.apples | 1 | Fruit.oranges | 1 | Fruit.apples
+ 2 | Fruit.apples | 1 | Fruit.oranges | -1 | Fruit.apples
+ 0 | Fruit.apples | 12 | Fruit.oranges | -36 | Fruit.apples
+ 0.7 | Fruit.apples | 0 | Fruit.oranges | 0.7 | Fruit.apples
+ 0.7 | Fruit.oranges | 1 | Fruit.apples | 1.1 | Fruit.apples
+ 12.45 | Fruit.apples | 0.2222 | Fruit.oranges | 11.7834 | Fruit.apples
+ }
+
+ def "can divide amount by a unitless value"() {
+ expect:
+ Amount.valueOf(a, Fruit.apples) / b == Amount.valueOf(c, Fruit.apples)
+
+ where:
+ a | b | c
+ 0 | 200 | 0
+ 2 | 1 | 2
+ 5 | 10 | 0.5
+ 10 | -2 | -5
+ 1 | 3 | 0.333333
+ 2 | 3 | 0.666667
+ }
+
+ def "can divide amount by another amount of same quantity"() {
+ expect:
+ Amount.valueOf(valueA, unitsA) / Amount.valueOf(valueB, unitsB) == result
+
+ where:
+ valueA | unitsA | valueB | unitsB | result
+ 0 | Fruit.apples | 200 | Fruit.apples | 0
+ 2 | Fruit.apples | 1 | Fruit.apples | 2
+ 5 | Fruit.apples | 10 | Fruit.apples | 0.5
+ 10 | Fruit.apples | -2 | Fruit.apples | -5
+ 1 | Fruit.apples | 3 | Fruit.apples | 0.333333
+ 2 | Fruit.apples | 3 | Fruit.apples | 0.666667
+ 4 | Fruit.apples | 1.2 | Fruit.oranges | 1.111111
+ 125 | Fruit.oranges | 23.4 | Fruit.grapefruit | 3.205128
+ }
+
+ def "can convert to absolute value"() {
+ expect:
+ Amount.valueOf(12, Fruit.grapefruit).abs() == Amount.valueOf(12, Fruit.grapefruit)
+ Amount.valueOf(-34, Fruit.grapefruit).abs() == Amount.valueOf(34, Fruit.grapefruit)
+ }
+
+ public static class Fruit {
+ static def apples = Units.base(Fruit.class, "apple", "apples")
+ static def oranges = apples.times(3, "orange", "oranges")
+ static def grapefruit = apples.times(5, "grapefruit")
+ }
+}
diff --git a/subprojects/performance/src/test/groovy/org/gradle/performance/measure/DurationTest.groovy b/subprojects/performance/src/test/groovy/org/gradle/performance/measure/DurationTest.groovy
new file mode 100644
index 0000000..04b68c2
--- /dev/null
+++ b/subprojects/performance/src/test/groovy/org/gradle/performance/measure/DurationTest.groovy
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.performance.measure
+
+import spock.lang.Specification
+
+class DurationTest extends Specification {
+ def "millisecond durations have useful string formats"() {
+ expect:
+ Duration.millis(millis).toString() == str
+ Duration.millis(millis).format() == formatted
+
+ where:
+ millis | str | formatted
+ 0 | "0 ms" | "0 ms"
+ 1 | "1 ms" | "1 ms"
+ 0.123 | "0.123 ms" | "0.123 ms"
+ -12 | "-12 ms" | "-12 ms"
+ 1000 | "1000 ms" | "1 s"
+ 123456 | "123456 ms" | "2.058 m"
+ 3607000 | "3607000 ms" | "1.002 h"
+ }
+
+ def "second durations have useful string formats"() {
+ expect:
+ Duration.seconds(millis).toString() == str
+
+ where:
+ millis | str | format
+ 0 | "0 s" | "0 ms"
+ 1 | "1 s" | "1 s"
+ 1000 | "1000 s" | "16.667 m"
+ 0.123 | "0.123 s" | "123 ms"
+ 0.1234567 | "0.1234567 s" | "123.457 ms"
+ -12 | "-12 s" | "-12 s"
+ }
+
+ def "can convert between units"() {
+ expect:
+ Duration.millis(45000) == Duration.seconds(45)
+ Duration.seconds(0.98) == Duration.millis(980)
+ Duration.seconds(120) == Duration.minutes(2)
+ Duration.seconds(30) == Duration.minutes(0.5)
+ Duration.hours(30) == Duration.millis(30 * 60 * 60 * 1000)
+ }
+}
diff --git a/subprojects/performance/src/test/groovy/org/gradle/performance/measure/UnitsTest.groovy b/subprojects/performance/src/test/groovy/org/gradle/performance/measure/UnitsTest.groovy
new file mode 100644
index 0000000..3bb901f
--- /dev/null
+++ b/subprojects/performance/src/test/groovy/org/gradle/performance/measure/UnitsTest.groovy
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.performance.measure
+
+import spock.lang.Specification
+
+class UnitsTest extends Specification {
+ def "can compare units of same quantity"() {
+ def base = Units.base(Void.class, "base")
+ def units1 = base.times(12, "units1")
+ def units2 = base.times(33, "units2")
+
+ expect:
+ base < units1
+ base < units2
+ units1 > base
+ units1 < units2
+ units2 > base
+ units2 > units1
+ }
+}
diff --git a/subprojects/performance/src/test/groovy/org/gradle/performance/results/ReportGeneratorTest.groovy b/subprojects/performance/src/test/groovy/org/gradle/performance/results/ReportGeneratorTest.groovy
new file mode 100644
index 0000000..8b8953c
--- /dev/null
+++ b/subprojects/performance/src/test/groovy/org/gradle/performance/results/ReportGeneratorTest.groovy
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.performance.results
+
+import org.gradle.performance.ResultSpecification
+import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
+import org.junit.Rule
+
+class ReportGeneratorTest extends ResultSpecification {
+ @Rule TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider()
+ final ReportGenerator generator = new ReportGenerator()
+ final dbFile = tmpDir.file("results")
+ final reportDir = tmpDir.file("report")
+
+ def "generates report"() {
+ setup:
+ def store = new ResultsStore(dbFile)
+ def result2 = results()
+ result2.current << operation()
+ result2.current << operation()
+ store.report(result2)
+ store.close()
+
+ when:
+ generator.generate(store, reportDir)
+
+ then:
+ reportDir.file("index.html").isFile()
+ }
+}
diff --git a/subprojects/performance/src/test/groovy/org/gradle/performance/results/ResultsStoreTest.groovy b/subprojects/performance/src/test/groovy/org/gradle/performance/results/ResultsStoreTest.groovy
new file mode 100644
index 0000000..c05edd6
--- /dev/null
+++ b/subprojects/performance/src/test/groovy/org/gradle/performance/results/ResultsStoreTest.groovy
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.performance.results
+
+import org.gradle.performance.ResultSpecification
+import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
+import org.junit.Rule
+
+import static org.gradle.performance.measure.DataAmount.kbytes
+import static org.gradle.performance.measure.Duration.minutes
+
+class ResultsStoreTest extends ResultSpecification {
+ @Rule TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider()
+ final dbFile = tmpDir.file("results")
+
+ def "persists results"() {
+ def result1 = results(testId: "test1",
+ testProject: "test-project",
+ tasks: ["clean", "build"],
+ args: ["--arg1"],
+ operatingSystem: "some-os",
+ jvm: "java 6",
+ testTime: 10000,
+ versionUnderTest: "1.7-rc-1",
+ vcsBranch: "master",
+ vcsCommit: "1234")
+ def baseline1 = result1.baseline("1.0")
+ def baseline2 = result1.baseline("1.5")
+ result1.current << operation(executionTime: minutes(12), heapUsed: kbytes(12.33))
+ baseline1.results << operation()
+ baseline2.results << operation()
+ baseline2.results << operation()
+ baseline2.results << operation()
+
+ def result2 = results(testId: "test2", testTime: 20000, versionUnderTest: "1.7-rc-2")
+ result2.current << operation()
+ result2.current << operation()
+ def baseline3 = result2.baseline("1.0")
+ baseline3.results << operation()
+
+ when:
+ def writeStore = new ResultsStore(dbFile)
+ writeStore.report(result1)
+ writeStore.report(result2)
+ writeStore.close()
+
+ then:
+ tmpDir.file("results.h2.db").exists()
+
+ when:
+ def readStore = new ResultsStore(dbFile)
+ def tests = readStore.testNames
+
+ then:
+ tests == ["test1", "test2"]
+
+ when:
+ def history = readStore.getTestResults("test1")
+
+ then:
+ history.baselineVersions == ["1.0", "1.5"]
+
+ and:
+ def results = history.results
+ results.size() == 1
+ results[0].testId == "test1"
+ results[0].displayName == "Results for test project 'test-project' with tasks clean, build"
+ results[0].testProject == "test-project"
+ results[0].tasks == ["clean", "build"]
+ results[0].args == ["--arg1"]
+ results[0].operatingSystem == "some-os"
+ results[0].jvm == "java 6"
+ results[0].testTime == 10000
+ results[0].versionUnderTest == '1.7-rc-1'
+ results[0].vcsBranch == 'master'
+ results[0].vcsCommit == '1234'
+ results[0].current.size() == 1
+ results[0].current[0].executionTime == minutes(12)
+ results[0].current[0].totalMemoryUsed == kbytes(12.33)
+ results[0].baselineVersions*.version == ["1.0", "1.5"]
+ results[0].baseline("1.0").results.size() == 1
+ results[0].baseline("1.5").results.size() == 3
+
+ when:
+ history = readStore.getTestResults("test2")
+ results = history.results
+ readStore.close()
+
+ then:
+ history.baselineVersions == ["1.0"]
+
+ and:
+ results.size() == 1
+ results[0].testId == "test2"
+ results[0].testTime == 20000
+ results[0].versionUnderTest == '1.7-rc-2'
+ results[0].current.size() == 2
+ results[0].baselineVersions*.version == ["1.0"]
+ results[0].baseline("1.0").results.size() == 1
+
+ cleanup:
+ writeStore?.close()
+ readStore?.close()
+ }
+
+ def "returns test names in ascending order"() {
+ def result1 = results(testId: "test1", testTime: 30000, versionUnderTest: "1.7-rc-1")
+ def result2 = results(testId: "test2", testTime: 20000, versionUnderTest: "1.7-rc-2")
+ def result3 = results(testId: "test3", testTime: 10000, versionUnderTest: "1.7-rc-3")
+
+ given:
+ def writeStore = new ResultsStore(dbFile)
+ writeStore.report(result3)
+ writeStore.report(result1)
+ writeStore.report(result2)
+ writeStore.close()
+
+ when:
+ def readStore = new ResultsStore(dbFile)
+ def tests = readStore.testNames
+
+ then:
+ tests == ["test1", "test2", "test3"]
+
+ cleanup:
+ writeStore?.close()
+ readStore?.close()
+ }
+
+ def "returns test executions in descending date order"() {
+ def result1 = results(testId: "some test", testTime: 10000, versionUnderTest: "1.7-rc-1")
+ def result2 = results(testId: "some test", testTime: 20000, versionUnderTest: "1.7-rc-2")
+ def result3 = results(testId: "some test", testTime: 30000, versionUnderTest: "1.7-rc-3")
+
+ given:
+ def writeStore = new ResultsStore(dbFile)
+ writeStore.report(result3)
+ writeStore.report(result1)
+ writeStore.report(result2)
+ writeStore.close()
+
+ when:
+ def readStore = new ResultsStore(dbFile)
+ def results = readStore.getTestResults("some test")
+
+ then:
+ results.results.size() == 3
+ results.results*.versionUnderTest == ["1.7-rc-3", "1.7-rc-2", "1.7-rc-1"]
+ results.resultsOldestFirst*.versionUnderTest == ["1.7-rc-1", "1.7-rc-2", "1.7-rc-3"]
+
+ cleanup:
+ writeStore?.close()
+ readStore?.close()
+ }
+
+ def "returns empty results for unknown id"() {
+ given:
+ def store = new ResultsStore(dbFile)
+
+ expect:
+ store.getTestResults("unknown").baselineVersions.empty
+ store.getTestResults("unknown").results.empty
+
+ cleanup:
+ store?.close()
+ }
+}
diff --git a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/AbstractPerformanceTest.groovy b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/AbstractPerformanceTest.groovy
index 6abbd60..f9b6053 100644
--- a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/AbstractPerformanceTest.groovy
+++ b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/AbstractPerformanceTest.groovy
@@ -16,12 +16,40 @@
package org.gradle.performance.fixture
+import org.gradle.integtests.fixtures.executer.UnderDevelopmentGradleDistribution
+import org.gradle.internal.os.OperatingSystem
+import org.gradle.performance.measure.DataAmount
+import org.gradle.performance.measure.Duration
+import org.gradle.performance.results.ResultsStore
+import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
+import org.junit.Rule
import spock.lang.Specification
class AbstractPerformanceTest extends Specification {
+ @Rule TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider()
+ static def resultStore = new ResultsStore()
+ static def textReporter = new TextFileDataReporter(new File("build/performance-tests/results.txt"))
+
final def runner = new PerformanceTestRunner(
+ testDirectoryProvider: tmpDir,
+ current: new UnderDevelopmentGradleDistribution(),
runs: 5,
warmUpRuns: 1,
- targetVersions: ['1.0', '1.4', 'last']
+ targetVersions: ['1.0', '1.4', '1.7', 'last'],
+ maxExecutionTimeRegression: Duration.millis(500),
+ // Our performance tests on Windows seem to need more heap
+ // TODO - find out if this is a real problem
+ maxMemoryRegression: OperatingSystem.current().isWindows() ? DataAmount.mbytes(10) : DataAmount.mbytes(3)
)
+
+ def setup() {
+ runner.reporter = new CompositeDataReporter([textReporter, resultStore])
+ }
+
+ static {
+ // TODO - find a better way to cleanup
+ System.addShutdownHook {
+ resultStore.close()
+ }
+ }
}
diff --git a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/Amount.java b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/Amount.java
deleted file mode 100644
index 7984ff8..0000000
--- a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/Amount.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.performance.fixture;
-
-import java.math.BigDecimal;
-import java.math.RoundingMode;
-import java.text.DecimalFormat;
-import java.text.DecimalFormatSymbols;
-import java.util.List;
-import java.util.Locale;
-
-/**
- * An amount is an immutable value of some quantity, such as duration or length. Each amount has a decimal value and associated units.
- *
- * TODO - need to sort out scaling when dividing or converting between units.
- */
-public class Amount<Q> implements Comparable<Amount<Q>> {
- private final BigDecimal value;
- private final Units<Q> units;
- private final BigDecimal normalised;
-
- private Amount(BigDecimal value, Units<Q> units) {
- this.value = value;
- this.units = units;
- normalised = units.scaleTo(value, units.getBaseUnits());
- }
-
- public static <Q> Amount<Q> valueOf(long value, Units<Q> units) {
- return valueOf(BigDecimal.valueOf(value), units);
- }
-
- public static <Q> Amount<Q> valueOf(BigDecimal value, Units<Q> units) {
- return new Amount<Q>(value, units);
- }
-
- /**
- * Returns a string representation of this amount. Uses the original value and units of this amount.
- */
- @Override
- public String toString() {
- return String.format("%s %s", value, units.format(value));
- }
-
- public Units<Q> getUnits() {
- return units;
- }
-
- public BigDecimal getValue() {
- return value;
- }
-
- /**
- * Returns a human consumable string representation of this amount.
- */
- public String format() {
- List<Units<Q>> allUnits = units.getUnitsForQuantity();
- BigDecimal base = normalised.abs();
- for (int i = allUnits.size()-1; i >= 0; i--) {
- Units<Q> candidate = allUnits.get(i);
- if (base.compareTo(candidate.getFactor()) >= 0) {
- BigDecimal scaled = units.scaleTo(value, candidate);
- return String.format("%s %s", new DecimalFormat("#.###", new DecimalFormatSymbols(Locale.US)).format(scaled), candidate.format(scaled));
- }
- }
- return String.format("%s %s", new DecimalFormat("#.###", new DecimalFormatSymbols(Locale.US)).format(value), units.format(value));
- }
-
- /**
- * Converts this amount to an equivalent amount in the specified units.
- *
- * @return The converted amount.
- */
- public Amount<Q> toUnits(Units<Q> units) {
- if (units.equals(this.units)) {
- return this;
- }
- return new Amount<Q>(this.units.scaleTo(value, units), units);
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj == this) {
- return true;
- }
- if (obj == null || obj.getClass() != getClass()) {
- return false;
- }
- Amount<Q> other = (Amount<Q>) obj;
- return compareTo(other) == 0;
- }
-
- @Override
- public int hashCode() {
- return normalised.hashCode();
- }
-
- public int compareTo(Amount<Q> o) {
- if (o.units.getType() != units.getType()) {
- throw new IllegalArgumentException(String.format("Cannot compare amount with units %s.", o.units));
- }
- return normalised.compareTo(o.normalised);
- }
-
- public Amount<Q> plus(Amount<Q> other) {
- if (other.value.equals(BigDecimal.ZERO)) {
- return this;
- }
- if (value.equals(BigDecimal.ZERO)) {
- return other;
- }
- int diff = units.compareTo(other.units);
- if (diff == 0) {
- return new Amount<Q>(value.add(other.value), units);
- }
- if (diff < 0) {
- return new Amount<Q>(value.add(other.units.scaleTo(other.value, units)), units);
- }
- return new Amount<Q>(units.scaleTo(value, other.units).add(other.value), other.units);
- }
-
- public Amount<Q> minus(Amount<Q> other) {
- if (other.value.equals(BigDecimal.ZERO)) {
- return this;
- }
- int diff = units.compareTo(other.units);
- if (diff == 0) {
- return new Amount<Q>(value.subtract(other.value), units);
- }
- if (diff < 0) {
- return new Amount<Q>(value.subtract(other.units.scaleTo(other.value, units)), units);
- }
- return new Amount<Q>(units.scaleTo(value, other.units).subtract(other.value), other.units);
- }
-
- public Amount<Q> div(long other) {
- return new Amount<Q>(value.divide(BigDecimal.valueOf(other), 6, RoundingMode.HALF_UP), units);
- }
-
- public BigDecimal div(Amount<Q> other) {
- return normalised.divide(other.normalised, 6, RoundingMode.HALF_UP);
- }
-
- public Amount<Q> abs() {
- if (value.compareTo(BigDecimal.ZERO) >= 0) {
- return this;
- }
- return new Amount<Q>(value.abs(), units);
- }
-}
diff --git a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/BaselineVersion.groovy b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/BaselineVersion.groovy
index 93a7bb5..8e6be0e 100644
--- a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/BaselineVersion.groovy
+++ b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/BaselineVersion.groovy
@@ -16,27 +16,27 @@
package org.gradle.performance.fixture
+import org.gradle.performance.measure.Amount
+import org.gradle.performance.measure.DataAmount
+import org.gradle.performance.measure.Duration
+
import static org.gradle.performance.fixture.PrettyCalculator.*
-/**
- * by Szczepan Faber, created at: 11/20/12
- */
class BaselineVersion {
-
- String version
+ final String version
+ final MeasuredOperationList results = new MeasuredOperationList()
Amount<Duration> maxExecutionTimeRegression = Duration.millis(0)
Amount<DataAmount> maxMemoryRegression = DataAmount.bytes(0)
- MeasuredOperationList results
+ BaselineVersion(String version) {
+ this.version = version
+ results.name = "Gradle $version"
+ }
void clearResults() {
results.clear()
}
- static BaselineVersion baseline(String version) {
- new BaselineVersion(version: version, results: new MeasuredOperationList(name: "Gradle $version"))
- }
-
String getSpeedStatsAgainst(String displayName, MeasuredOperationList current) {
def sb = new StringBuilder()
if (current.avgTime() > results.avgTime()) {
diff --git a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/CompositeDataReporter.java b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/CompositeDataReporter.java
new file mode 100644
index 0000000..053ef1a
--- /dev/null
+++ b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/CompositeDataReporter.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.performance.fixture;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class CompositeDataReporter implements DataReporter {
+ private final List<DataReporter> reporters;
+ private final Set<String> testIds = new HashSet<String>();
+
+ public CompositeDataReporter(List<DataReporter> reporters) {
+ this.reporters = reporters;
+ }
+
+ public void report(PerformanceResults results) {
+ if (!testIds.add(results.getTestId())) {
+ throw new IllegalArgumentException(String.format("Multiple performance test executions with id '%s' found.", results.getTestId()));
+ }
+ for (DataReporter reporter : reporters) {
+ reporter.report(results);
+ }
+ }
+}
diff --git a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/DataAmount.java b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/DataAmount.java
deleted file mode 100644
index 7d0707d..0000000
--- a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/DataAmount.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.performance.fixture;
-
-import java.math.BigDecimal;
-
-public class DataAmount {
- public static final Units<DataAmount> BYTES = Units.base(DataAmount.class, "B");
- public static final Units<DataAmount> KILO_BYTES = BYTES.times(1024, "kB");
- public static final Units<DataAmount> MEGA_BYTES = KILO_BYTES.times(1024, "MB");
- public static final Units<DataAmount> GIGA_BYTES = MEGA_BYTES.times(1024, "GB");
-
- public static Amount<DataAmount> bytes(long value) {
- return Amount.valueOf(value, BYTES);
- }
-
- public static Amount<DataAmount> bytes(BigDecimal value) {
- return Amount.valueOf(value, BYTES);
- }
-
- public static Amount<DataAmount> kbytes(BigDecimal value) {
- return Amount.valueOf(value, KILO_BYTES);
- }
-}
diff --git a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/DataCollector.java b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/DataCollector.java
index 2b387d8..d71e958 100644
--- a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/DataCollector.java
+++ b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/DataCollector.java
@@ -16,11 +16,10 @@
package org.gradle.performance.fixture;
+import org.gradle.performance.measure.MeasuredOperation;
+
import java.io.File;
-/**
- * by Szczepan Faber, created at: 8/14/12
- */
public interface DataCollector {
void collect(File testProjectDir, MeasuredOperation operation);
diff --git a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/Duration.java b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/Duration.java
deleted file mode 100644
index 90803c8..0000000
--- a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/Duration.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.performance.fixture;
-
-import java.math.BigDecimal;
-
-public class Duration {
- public static final Units<Duration> MILLI_SECONDS = Units.base(Duration.class, "ms");
- public static final Units<Duration> SECONDS = MILLI_SECONDS.times(1000, "s");
- public static final Units<Duration> MINUTES = SECONDS.times(60, "m");
- public static final Units<Duration> HOURS = MINUTES.times(60, "h");
-
- public static Amount<Duration> millis(long millis) {
- return Amount.valueOf(millis, MILLI_SECONDS);
- }
-
- public static Amount<Duration> millis(BigDecimal millis) {
- return Amount.valueOf(millis, MILLI_SECONDS);
- }
-
- public static Amount<Duration> seconds(BigDecimal seconds) {
- return Amount.valueOf(seconds, SECONDS);
- }
-
- public static Amount<Duration> minutes(BigDecimal minutes) {
- return Amount.valueOf(minutes, MINUTES);
- }
-
- public static Amount<Duration> hours(BigDecimal hours) {
- return Amount.valueOf(hours, HOURS);
- }
-}
diff --git a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/Git.groovy b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/Git.groovy
new file mode 100644
index 0000000..7fd66c5
--- /dev/null
+++ b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/Git.groovy
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.performance.fixture
+
+import org.eclipse.jgit.storage.file.FileRepositoryBuilder
+
+class Git {
+ private static Git git
+ final String commitId
+ final String branchName
+
+ public static Git current() {
+ if (git == null) {
+ git = new Git()
+ }
+ return git
+ }
+
+ private Git() {
+ def repository = new FileRepositoryBuilder().findGitDir().build()
+ try {
+ branchName = repository.branch
+ commitId = repository.getRef(repository.fullBranch).objectId.name
+ } finally {
+ repository.close()
+ }
+ }
+}
diff --git a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/MeasuredOperation.groovy b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/MeasuredOperation.groovy
deleted file mode 100644
index f9da914..0000000
--- a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/MeasuredOperation.groovy
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.performance.fixture
-
-import org.gradle.util.Clock
-
-/**
- * by Szczepan Faber, created at: 2/10/12
- */
-public class MeasuredOperation {
- Amount<Duration> executionTime
- Exception exception
- Amount<DataAmount> totalMemoryUsed
-
- static MeasuredOperation measure(Closure operation) {
- def out = new MeasuredOperation()
- def clock = new Clock()
- clock.reset()
- try {
- operation(out)
- } catch (Exception e) {
- out.exception = e
- }
- out.executionTime = Duration.millis(clock.timeInMs)
- return out
- }
-}
diff --git a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/MeasuredOperationList.groovy b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/MeasuredOperationList.groovy
index f49079b..3938f6e 100644
--- a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/MeasuredOperationList.groovy
+++ b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/MeasuredOperationList.groovy
@@ -16,12 +16,14 @@
package org.gradle.performance.fixture
+import org.gradle.performance.measure.Amount
+import org.gradle.performance.measure.DataAmount
+import org.gradle.performance.measure.Duration
+import org.gradle.performance.measure.MeasuredOperation
+
import static org.gradle.performance.fixture.PrettyCalculator.prettyBytes
import static org.gradle.performance.fixture.PrettyCalculator.prettyTime
-/**
- * by Szczepan Faber, created at: 2/10/12
- */
public class MeasuredOperationList extends LinkedList<MeasuredOperation> {
String name
diff --git a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/MemoryInfoCollector.groovy b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/MemoryInfoCollector.groovy
index 107794b..7329285 100644
--- a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/MemoryInfoCollector.groovy
+++ b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/MemoryInfoCollector.groovy
@@ -16,9 +16,9 @@
package org.gradle.performance.fixture
-/**
- * by Szczepan Faber, created at: 8/14/12
- */
+import org.gradle.performance.measure.DataAmount
+import org.gradle.performance.measure.MeasuredOperation
+
public class MemoryInfoCollector implements DataCollector {
String outputFileName
diff --git a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/OperationTimer.java b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/OperationTimer.java
new file mode 100644
index 0000000..52e466f
--- /dev/null
+++ b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/OperationTimer.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.performance.fixture;
+
+import groovy.lang.Closure;
+import org.gradle.performance.measure.Duration;
+import org.gradle.performance.measure.MeasuredOperation;
+
+public class OperationTimer {
+ public MeasuredOperation measure(Closure operation) {
+ MeasuredOperation result = new MeasuredOperation();
+ long start = System.currentTimeMillis();
+ try {
+ operation.call(result);
+ } catch (Exception e) {
+ result.setException(e);
+ }
+ long end = System.currentTimeMillis();
+ result.setExecutionTime(Duration.millis(end - start));
+ return result;
+ }
+}
diff --git a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/PerformanceResults.groovy b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/PerformanceResults.groovy
index 10e36fa..0389bf4 100644
--- a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/PerformanceResults.groovy
+++ b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/PerformanceResults.groovy
@@ -18,26 +18,57 @@ package org.gradle.performance.fixture
import org.gradle.api.logging.Logging
-import static org.gradle.performance.fixture.BaselineVersion.baseline
-
public class PerformanceResults {
+ private final static LOGGER = Logging.getLogger(PerformanceResults.class)
- private final static LOGGER = Logging.getLogger(PerformanceTestRunner.class)
-
- List<BaselineVersion> baselineVersions = [ baseline("1.x")]
- String displayName
+ String testId
+ String testProject
+ String[] args
+ String[] tasks
+ String jvm
+ String operatingSystem
+ long testTime
+ String versionUnderTest
+ String vcsBranch
+ String vcsCommit
- final MeasuredOperationList current = new MeasuredOperationList(name: "Current G.")
+ private final Map<String, BaselineVersion> baselineVersions = new LinkedHashMap<>()
+ final MeasuredOperationList current = new MeasuredOperationList(name: "Current Gradle")
def clear() {
- baselineVersions.each { it.clearResults() }
+ baselineVersions.values()each { it.clearResults() }
current.clear()
}
+ @Override
+ String toString() {
+ return displayName
+ }
+
+ String getDisplayName() {
+ return "Results for test project '$testProject' with tasks ${tasks.join(', ')}"
+ }
+
+ Collection<BaselineVersion> getBaselineVersions() {
+ return baselineVersions.values()
+ }
+
+ /**
+ * Locates the given baseline version, adding it if not present.
+ */
+ BaselineVersion baseline(String version) {
+ def baselineVersion = baselineVersions[version]
+ if (baselineVersion == null) {
+ baselineVersion = new BaselineVersion(version)
+ baselineVersions[version] = baselineVersion
+ }
+ return baselineVersion
+ }
+
void assertEveryBuildSucceeds() {
LOGGER.info("Asserting all builds have succeeded...");
def failures = []
- baselineVersions.each {
+ baselineVersions.values().each {
failures.addAll it.results.findAll { it.exception }
}
failures.addAll current.findAll { it.exception }
@@ -63,7 +94,7 @@ public class PerformanceResults {
private String checkBaselineVersion(Closure fails, Closure provideMessage) {
def failed = false
def failure = new StringBuilder()
- baselineVersions.each {
+ baselineVersions.values().each {
String message = provideMessage(it)
if (fails(it)) {
failed = true
diff --git a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/PerformanceTestRunner.groovy b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/PerformanceTestRunner.groovy
index 4dca19b..be88aff 100644
--- a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/PerformanceTestRunner.groovy
+++ b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/PerformanceTestRunner.groovy
@@ -19,22 +19,31 @@ package org.gradle.performance.fixture
import org.gradle.integtests.fixtures.executer.GradleDistribution
import org.gradle.integtests.fixtures.executer.GradleExecuter
import org.gradle.integtests.fixtures.executer.IntegrationTestBuildContext
-import org.gradle.integtests.fixtures.executer.UnderDevelopmentGradleDistribution
import org.gradle.integtests.fixtures.versions.ReleasedVersionDistributions
-import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
+import org.gradle.internal.jvm.Jvm
+import org.gradle.internal.os.OperatingSystem
+import org.gradle.performance.measure.Amount
+import org.gradle.performance.measure.DataAmount
+import org.gradle.performance.measure.Duration
+import org.gradle.performance.measure.MeasuredOperation
+import org.gradle.test.fixtures.file.TestDirectoryProvider
+import org.gradle.util.GradleVersion
public class PerformanceTestRunner {
- def testDirectoryProvider = new TestNameTestDirectoryProvider()
- def current = new UnderDevelopmentGradleDistribution()
- def buildContext = new IntegrationTestBuildContext()
+ TestDirectoryProvider testDirectoryProvider
+ GradleDistribution current
+ IntegrationTestBuildContext buildContext = new IntegrationTestBuildContext()
+ DataReporter reporter
+ OperationTimer timer = new OperationTimer()
+ TestProjectLocator testProjectLocator = new TestProjectLocator()
+ String testId
String testProject
int runs
int warmUpRuns
List<String> tasksToRun = []
DataCollector dataCollector = new MemoryInfoCollector(outputFileName: "build/totalMemoryUsed.txt")
- DataReporter reporter = new TextFileDataReporter()
List<String> args = []
List<String> targetVersions = []
@@ -45,22 +54,38 @@ public class PerformanceTestRunner {
PerformanceResults run() {
assert !targetVersions.empty
+ assert testId
- def mostRecentFinalRelease = new ReleasedVersionDistributions().mostRecentFinalRelease.version.version
+ results = new PerformanceResults(
+ testId: testId,
+ testProject: testProject,
+ tasks: tasksToRun,
+ args: args,
+ jvm: Jvm.current().toString(),
+ operatingSystem: OperatingSystem.current().toString(),
+ versionUnderTest: GradleVersion.current().getVersion(),
+ vcsBranch: Git.current().branchName,
+ vcsCommit: Git.current().commitId,
+ testTime: System.currentTimeMillis())
+
+ def releasedDistributions = new ReleasedVersionDistributions()
+ def releasedVersions = releasedDistributions.all*.version.version
+ def mostRecentFinalRelease = releasedDistributions.mostRecentFinalRelease.version.version
+ def currentBaseVersion = GradleVersion.current().getBaseVersion().version
def allVersions = targetVersions.collect { (it == 'last') ? mostRecentFinalRelease : it }.unique()
- def baselineVersions = []
+ allVersions.remove(currentBaseVersion)
+
+ // A target version may be something that is yet unreleased, so filter that out
+ allVersions.removeAll { !releasedVersions.contains(it) }
+
+ assert !allVersions.isEmpty()
+
allVersions.each { it ->
- baselineVersions << new BaselineVersion(version: it,
- maxExecutionTimeRegression: maxExecutionTimeRegression,
- maxMemoryRegression: maxMemoryRegression,
- results: new MeasuredOperationList(name: "Gradle $it")
- )
+ def baselineVersion = results.baseline(it)
+ baselineVersion.maxExecutionTimeRegression = maxExecutionTimeRegression
+ baselineVersion.maxMemoryRegression = maxMemoryRegression
}
- results = new PerformanceResults(
- baselineVersions: baselineVersions,
- displayName: "Results for test project '$testProject' with tasks ${tasksToRun.join(', ')}")
-
println "Running performance tests for test project '$testProject', no. of runs: $runs"
warmUpRuns.times {
println "Executing warm-up run #${it + 1}"
@@ -76,8 +101,8 @@ public class PerformanceTestRunner {
}
void runOnce() {
- File projectDir = new TestProjectLocator().findProjectDir(testProject)
- results.baselineVersions.reverse().each {
+ File projectDir = testProjectLocator.findProjectDir(testProject)
+ results.baselineVersions.each {
println "Gradle ${it.version}..."
runOnce(buildContext.distribution(it.version), projectDir, it.results)
}
@@ -88,7 +113,7 @@ public class PerformanceTestRunner {
void runOnce(GradleDistribution dist, File projectDir, MeasuredOperationList results) {
def executer = this.executer(dist, projectDir)
- def operation = MeasuredOperation.measure { MeasuredOperation operation ->
+ def operation = timer.measure { MeasuredOperation operation ->
executer.run()
}
dataCollector.collect(projectDir, operation)
diff --git a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/PrettyCalculator.groovy b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/PrettyCalculator.groovy
index 10d19ff..062463f 100644
--- a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/PrettyCalculator.groovy
+++ b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/PrettyCalculator.groovy
@@ -16,11 +16,12 @@
package org.gradle.performance.fixture
+import org.gradle.performance.measure.Amount
+import org.gradle.performance.measure.DataAmount
+import org.gradle.performance.measure.Duration
+
import java.math.RoundingMode
-/**
- * by Szczepan Faber, created at: 10/30/12
- */
class PrettyCalculator {
static String prettyBytes(Amount<DataAmount> bytes) {
diff --git a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/TestProjectLocator.groovy b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/TestProjectLocator.groovy
index a109dca..9d45692 100644
--- a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/TestProjectLocator.groovy
+++ b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/TestProjectLocator.groovy
@@ -16,9 +16,6 @@
package org.gradle.performance.fixture
-/**
- * by Szczepan Faber, created at: 2/10/12
- */
class TestProjectLocator {
File findProjectDir(String name) {
diff --git a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/TextFileDataReporter.groovy b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/TextFileDataReporter.groovy
index ca16730..2b7141d 100644
--- a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/TextFileDataReporter.groovy
+++ b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/TextFileDataReporter.groovy
@@ -17,14 +17,19 @@
package org.gradle.performance.fixture
class TextFileDataReporter implements DataReporter {
+ private final File outputFile
+
+ TextFileDataReporter(File outputFile) {
+ this.outputFile = outputFile
+ }
+
void report(PerformanceResults results) {
- File outFile = new File("build/performance-tests/results.txt")
- outFile.parentFile.mkdirs()
+ outputFile.parentFile.mkdirs()
results.baselineVersions.each {
- outFile << it.getSpeedStatsAgainst(results.displayName, results.current)
+ outputFile << it.getSpeedStatsAgainst(results.displayName, results.current)
}
results.baselineVersions.each {
- outFile << it.getMemoryStatsAgainst(results.displayName, results.current)
+ outputFile << it.getMemoryStatsAgainst(results.displayName, results.current)
}
}
}
diff --git a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/Units.java b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/Units.java
deleted file mode 100644
index 0d787ad..0000000
--- a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/fixture/Units.java
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.performance.fixture;
-
-import java.math.BigDecimal;
-import java.math.RoundingMode;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-public abstract class Units<Q> implements Comparable<Units<Q>> {
- private final Class<Q> type;
- private final String displaySingular;
- private final String displayPlural;
-
- protected Units(Class<Q> type, String displaySingular, String displayPlural) {
- this.type = type;
- this.displaySingular = displaySingular;
- this.displayPlural = displayPlural;
- }
-
- /**
- * Creates the base units for a given quantity.
- */
- public static <Q> Units<Q> base(Class<Q> type, String displaySingular) {
- return new BaseUnits<Q>(type, displaySingular, displaySingular);
- }
-
- /**
- * Creates the base units for a given quantity.
- */
- public static <Q> Units<Q> base(Class<Q> type, String displaySingular, String displayPlural) {
- return new BaseUnits<Q>(type, displaySingular, displayPlural);
- }
-
- protected Class<Q> getType() {
- return type;
- }
-
- @Override
- public String toString() {
- return displayPlural;
- }
-
- /**
- * Creates units that are some multiple of this units.
- */
- public abstract Units<Q> times(long value, String displaySingular, String displayPlural);
-
- /**
- * Creates units that are some multiple of this units.
- */
- public Units<Q> times(long value, String displaySingular) {
- return times(value, displaySingular, displaySingular);
- }
-
- protected abstract Units<Q> getBaseUnits();
-
- protected abstract List<Units<Q>> getUnitsForQuantity();
-
- protected abstract BigDecimal getFactor();
-
- protected abstract BigDecimal scaleTo(BigDecimal value, Units<Q> units);
-
- protected String format(BigDecimal value) {
- return value.compareTo(BigDecimal.ONE) == 0 ? displaySingular : displayPlural;
- }
-
- private static class BaseUnits<Q> extends Units<Q> {
- private final List<Units<Q>> units = new ArrayList<Units<Q>>();
-
- protected BaseUnits(Class<Q> type, String displaySingular, String displayPlural) {
- super(type, displaySingular, displayPlural);
- units.add(this);
- }
-
- @Override
- public BigDecimal scaleTo(BigDecimal value, Units<Q> units) {
- if (units == this) {
- return value;
- }
- ScaledUnits<Q> scaledUnits = (ScaledUnits<Q>) units;
- return value.divide(scaledUnits.factor, 6, RoundingMode.HALF_UP).stripTrailingZeros();
- }
-
- @Override
- protected List<Units<Q>> getUnitsForQuantity() {
- return units;
- }
-
- @Override
- public Units<Q> times(long value, String displaySingular, String displayPlural) {
- return new ScaledUnits<Q>(this, displaySingular, displayPlural, BigDecimal.valueOf(value));
- }
-
- @Override
- protected Units<Q> getBaseUnits() {
- return this;
- }
-
- @Override
- protected BigDecimal getFactor() {
- return BigDecimal.ONE;
- }
-
- public int compareTo(Units<Q> o) {
- if (o == this) {
- return 0;
- }
- if (o.getType() != getType()) {
- throw new IllegalArgumentException(String.format("Cannot compare units of %s with units of %s.", getType(), o.getType()));
- }
- return -1;
- }
-
- public void add(ScaledUnits<Q> units) {
- this.units.add(units);
- Collections.sort(this.units);
- }
- }
-
- private static class ScaledUnits<Q> extends Units<Q> {
- private final BaseUnits<Q> baseUnits;
- private final BigDecimal factor;
-
- public ScaledUnits(BaseUnits<Q> baseUnits, String displaySingular, String displayPlural, BigDecimal factor) {
- super(baseUnits.getType(), displaySingular, displayPlural);
- assert factor.compareTo(BigDecimal.ONE) > 0;
- this.baseUnits = baseUnits;
- this.factor = factor;
- baseUnits.add(this);
- }
-
- @Override
- public Units<Q> times(long value, String displaySingular, String displayPlural) {
- return new ScaledUnits<Q>(baseUnits, displaySingular, displayPlural, factor.multiply(BigDecimal.valueOf(value)));
- }
-
- @Override
- public BigDecimal scaleTo(BigDecimal value, Units<Q> units) {
- if (units == this) {
- return value;
- }
- if (units.equals(baseUnits)) {
- return value.multiply(factor);
- }
- ScaledUnits<Q> other = (ScaledUnits<Q>) units;
- return value.multiply(factor).divide(other.factor, 6, RoundingMode.HALF_UP).stripTrailingZeros();
- }
-
- @Override
- protected List<Units<Q>> getUnitsForQuantity() {
- return baseUnits.getUnitsForQuantity();
- }
-
- @Override
- protected Units<Q> getBaseUnits() {
- return baseUnits;
- }
-
- @Override
- protected BigDecimal getFactor() {
- return factor;
- }
-
- public int compareTo(Units<Q> o) {
- if (o.getType() != getType()) {
- throw new IllegalArgumentException(String.format("Cannot compare units of %s with units of %s.", getType(), o.getType()));
- }
- if (o.equals(baseUnits)) {
- return 1;
- }
- ScaledUnits<Q> other = (ScaledUnits<Q>) o;
- if (!other.baseUnits.equals(baseUnits)) {
- throw new IllegalArgumentException("Cannot compare units with different base units.");
- }
- return factor.compareTo(other.factor);
- }
- }
-}
diff --git a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/measure/Amount.java b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/measure/Amount.java
new file mode 100644
index 0000000..1d1fe81
--- /dev/null
+++ b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/measure/Amount.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.performance.measure;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.util.List;
+import java.util.Locale;
+
+/**
+ * An amount is an immutable value of some quantity, such as duration or length. Each amount has a decimal value and associated units.
+ *
+ * TODO - need to sort out scaling when dividing or converting between units.
+ */
+public class Amount<Q> implements Comparable<Amount<Q>> {
+ private final BigDecimal value;
+ private final Units<Q> units;
+ private final BigDecimal normalised;
+
+ private Amount(BigDecimal value, Units<Q> units) {
+ this.value = value;
+ this.units = units;
+ normalised = units.scaleTo(value, units.getBaseUnits());
+ }
+
+ public static <Q> Amount<Q> valueOf(long value, Units<Q> units) {
+ return valueOf(BigDecimal.valueOf(value), units);
+ }
+
+ public static <Q> Amount<Q> valueOf(BigDecimal value, Units<Q> units) {
+ return new Amount<Q>(value, units);
+ }
+
+ /**
+ * Returns a string representation of this amount. Uses the original value and units of this amount.
+ */
+ @Override
+ public String toString() {
+ return String.format("%s %s", value, units.format(value));
+ }
+
+ public Units<Q> getUnits() {
+ return units;
+ }
+
+ public BigDecimal getValue() {
+ return value;
+ }
+
+ /**
+ * Returns a human consumable string representation of this amount.
+ */
+ public String format() {
+ List<Units<Q>> allUnits = units.getUnitsForQuantity();
+ BigDecimal base = normalised.abs();
+ for (int i = allUnits.size()-1; i >= 0; i--) {
+ Units<Q> candidate = allUnits.get(i);
+ if (base.compareTo(candidate.getFactor()) >= 0) {
+ BigDecimal scaled = units.scaleTo(value, candidate);
+ return String.format("%s %s", new DecimalFormat("#.###", new DecimalFormatSymbols(Locale.US)).format(scaled), candidate.format(scaled));
+ }
+ }
+ return String.format("%s %s", new DecimalFormat("#.###", new DecimalFormatSymbols(Locale.US)).format(value), units.format(value));
+ }
+
+ /**
+ * Converts this amount to an equivalent amount in the specified units.
+ *
+ * @return The converted amount.
+ */
+ public Amount<Q> toUnits(Units<Q> units) {
+ if (units.equals(this.units)) {
+ return this;
+ }
+ return new Amount<Q>(this.units.scaleTo(value, units), units);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (obj == null || obj.getClass() != getClass()) {
+ return false;
+ }
+ @SuppressWarnings("unchecked")
+ Amount<Q> other = (Amount) obj;
+ return compareTo(other) == 0;
+ }
+
+ @Override
+ public int hashCode() {
+ return normalised.hashCode();
+ }
+
+ public int compareTo(Amount<Q> o) {
+ if (o.units.getType() != units.getType()) {
+ throw new IllegalArgumentException(String.format("Cannot compare amount with units %s.", o.units));
+ }
+ return normalised.compareTo(o.normalised);
+ }
+
+ public Amount<Q> plus(Amount<Q> other) {
+ if (other.value.equals(BigDecimal.ZERO)) {
+ return this;
+ }
+ if (value.equals(BigDecimal.ZERO)) {
+ return other;
+ }
+ int diff = units.compareTo(other.units);
+ if (diff == 0) {
+ return new Amount<Q>(value.add(other.value), units);
+ }
+ if (diff < 0) {
+ return new Amount<Q>(value.add(other.units.scaleTo(other.value, units)), units);
+ }
+ return new Amount<Q>(units.scaleTo(value, other.units).add(other.value), other.units);
+ }
+
+ public Amount<Q> minus(Amount<Q> other) {
+ if (other.value.equals(BigDecimal.ZERO)) {
+ return this;
+ }
+ int diff = units.compareTo(other.units);
+ if (diff == 0) {
+ return new Amount<Q>(value.subtract(other.value), units);
+ }
+ if (diff < 0) {
+ return new Amount<Q>(value.subtract(other.units.scaleTo(other.value, units)), units);
+ }
+ return new Amount<Q>(units.scaleTo(value, other.units).subtract(other.value), other.units);
+ }
+
+ public Amount<Q> div(long other) {
+ return new Amount<Q>(value.divide(BigDecimal.valueOf(other), 6, RoundingMode.HALF_UP), units);
+ }
+
+ public BigDecimal div(Amount<Q> other) {
+ return normalised.divide(other.normalised, 6, RoundingMode.HALF_UP);
+ }
+
+ public Amount<Q> abs() {
+ if (value.compareTo(BigDecimal.ZERO) >= 0) {
+ return this;
+ }
+ return new Amount<Q>(value.abs(), units);
+ }
+}
diff --git a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/measure/DataAmount.java b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/measure/DataAmount.java
new file mode 100644
index 0000000..1716bbe
--- /dev/null
+++ b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/measure/DataAmount.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.performance.measure;
+
+import java.math.BigDecimal;
+
+public class DataAmount {
+ public static final Units<DataAmount> BYTES = Units.base(DataAmount.class, "B");
+ public static final Units<DataAmount> KILO_BYTES = BYTES.times(1024, "kB");
+ public static final Units<DataAmount> MEGA_BYTES = KILO_BYTES.times(1024, "MB");
+ public static final Units<DataAmount> GIGA_BYTES = MEGA_BYTES.times(1024, "GB");
+
+ public static Amount<DataAmount> bytes(long value) {
+ return Amount.valueOf(value, BYTES);
+ }
+
+ public static Amount<DataAmount> bytes(BigDecimal value) {
+ return Amount.valueOf(value, BYTES);
+ }
+
+ public static Amount<DataAmount> kbytes(BigDecimal value) {
+ return Amount.valueOf(value, KILO_BYTES);
+ }
+
+ public static Amount<DataAmount> mbytes(BigDecimal value) {
+ return Amount.valueOf(value, MEGA_BYTES);
+ }
+}
diff --git a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/measure/Duration.java b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/measure/Duration.java
new file mode 100644
index 0000000..9cd321d
--- /dev/null
+++ b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/measure/Duration.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.performance.measure;
+
+import java.math.BigDecimal;
+
+public class Duration {
+ public static final Units<Duration> MILLI_SECONDS = Units.base(Duration.class, "ms");
+ public static final Units<Duration> SECONDS = MILLI_SECONDS.times(1000, "s");
+ public static final Units<Duration> MINUTES = SECONDS.times(60, "m");
+ public static final Units<Duration> HOURS = MINUTES.times(60, "h");
+
+ public static Amount<Duration> millis(long millis) {
+ return Amount.valueOf(millis, MILLI_SECONDS);
+ }
+
+ public static Amount<Duration> millis(BigDecimal millis) {
+ return Amount.valueOf(millis, MILLI_SECONDS);
+ }
+
+ public static Amount<Duration> seconds(BigDecimal seconds) {
+ return Amount.valueOf(seconds, SECONDS);
+ }
+
+ public static Amount<Duration> minutes(BigDecimal minutes) {
+ return Amount.valueOf(minutes, MINUTES);
+ }
+
+ public static Amount<Duration> hours(BigDecimal hours) {
+ return Amount.valueOf(hours, HOURS);
+ }
+}
diff --git a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/measure/MeasuredOperation.groovy b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/measure/MeasuredOperation.groovy
new file mode 100644
index 0000000..e8c37ee
--- /dev/null
+++ b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/measure/MeasuredOperation.groovy
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.performance.measure
+public class MeasuredOperation {
+ Amount<Duration> executionTime
+ Exception exception
+ Amount<DataAmount> totalMemoryUsed
+}
diff --git a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/measure/Units.java b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/measure/Units.java
new file mode 100644
index 0000000..6e5a614
--- /dev/null
+++ b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/measure/Units.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.performance.measure;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public abstract class Units<Q> implements Comparable<Units<Q>> {
+ private final Class<Q> type;
+ private final String displaySingular;
+ private final String displayPlural;
+
+ protected Units(Class<Q> type, String displaySingular, String displayPlural) {
+ this.type = type;
+ this.displaySingular = displaySingular;
+ this.displayPlural = displayPlural;
+ }
+
+ /**
+ * Creates the base units for a given quantity.
+ */
+ public static <Q> Units<Q> base(Class<Q> type, String displaySingular) {
+ return new BaseUnits<Q>(type, displaySingular, displaySingular);
+ }
+
+ /**
+ * Creates the base units for a given quantity.
+ */
+ public static <Q> Units<Q> base(Class<Q> type, String displaySingular, String displayPlural) {
+ return new BaseUnits<Q>(type, displaySingular, displayPlural);
+ }
+
+ protected Class<Q> getType() {
+ return type;
+ }
+
+ @Override
+ public String toString() {
+ return displayPlural;
+ }
+
+ /**
+ * Creates units that are some multiple of this units.
+ */
+ public abstract Units<Q> times(long value, String displaySingular, String displayPlural);
+
+ /**
+ * Creates units that are some multiple of this units.
+ */
+ public Units<Q> times(long value, String displaySingular) {
+ return times(value, displaySingular, displaySingular);
+ }
+
+ protected abstract Units<Q> getBaseUnits();
+
+ protected abstract List<Units<Q>> getUnitsForQuantity();
+
+ protected abstract BigDecimal getFactor();
+
+ protected abstract BigDecimal scaleTo(BigDecimal value, Units<Q> units);
+
+ protected String format(BigDecimal value) {
+ return value.compareTo(BigDecimal.ONE) == 0 ? displaySingular : displayPlural;
+ }
+
+ private static class BaseUnits<Q> extends Units<Q> {
+ private final List<Units<Q>> units = new ArrayList<Units<Q>>();
+
+ protected BaseUnits(Class<Q> type, String displaySingular, String displayPlural) {
+ super(type, displaySingular, displayPlural);
+ units.add(this);
+ }
+
+ @Override
+ public BigDecimal scaleTo(BigDecimal value, Units<Q> units) {
+ if (units == this) {
+ return value;
+ }
+ ScaledUnits<Q> scaledUnits = (ScaledUnits<Q>) units;
+ return value.divide(scaledUnits.factor, 6, RoundingMode.HALF_UP).stripTrailingZeros();
+ }
+
+ @Override
+ protected List<Units<Q>> getUnitsForQuantity() {
+ return units;
+ }
+
+ @Override
+ public Units<Q> times(long value, String displaySingular, String displayPlural) {
+ return new ScaledUnits<Q>(this, displaySingular, displayPlural, BigDecimal.valueOf(value));
+ }
+
+ @Override
+ protected Units<Q> getBaseUnits() {
+ return this;
+ }
+
+ @Override
+ protected BigDecimal getFactor() {
+ return BigDecimal.ONE;
+ }
+
+ public int compareTo(Units<Q> o) {
+ if (o == this) {
+ return 0;
+ }
+ if (o.getType() != getType()) {
+ throw new IllegalArgumentException(String.format("Cannot compare units of %s with units of %s.", getType(), o.getType()));
+ }
+ return -1;
+ }
+
+ public void add(ScaledUnits<Q> units) {
+ this.units.add(units);
+ Collections.sort(this.units);
+ }
+ }
+
+ private static class ScaledUnits<Q> extends Units<Q> {
+ private final BaseUnits<Q> baseUnits;
+ private final BigDecimal factor;
+
+ public ScaledUnits(BaseUnits<Q> baseUnits, String displaySingular, String displayPlural, BigDecimal factor) {
+ super(baseUnits.getType(), displaySingular, displayPlural);
+ assert factor.compareTo(BigDecimal.ONE) > 0;
+ this.baseUnits = baseUnits;
+ this.factor = factor;
+ baseUnits.add(this);
+ }
+
+ @Override
+ public Units<Q> times(long value, String displaySingular, String displayPlural) {
+ return new ScaledUnits<Q>(baseUnits, displaySingular, displayPlural, factor.multiply(BigDecimal.valueOf(value)));
+ }
+
+ @Override
+ public BigDecimal scaleTo(BigDecimal value, Units<Q> units) {
+ if (units == this) {
+ return value;
+ }
+ if (units.equals(baseUnits)) {
+ return value.multiply(factor);
+ }
+ ScaledUnits<Q> other = (ScaledUnits<Q>) units;
+ return value.multiply(factor).divide(other.factor, 6, RoundingMode.HALF_UP).stripTrailingZeros();
+ }
+
+ @Override
+ protected List<Units<Q>> getUnitsForQuantity() {
+ return baseUnits.getUnitsForQuantity();
+ }
+
+ @Override
+ protected Units<Q> getBaseUnits() {
+ return baseUnits;
+ }
+
+ @Override
+ protected BigDecimal getFactor() {
+ return factor;
+ }
+
+ public int compareTo(Units<Q> o) {
+ if (o.getType() != getType()) {
+ throw new IllegalArgumentException(String.format("Cannot compare units of %s with units of %s.", getType(), o.getType()));
+ }
+ if (o.equals(baseUnits)) {
+ return 1;
+ }
+ ScaledUnits<Q> other = (ScaledUnits<Q>) o;
+ if (!other.baseUnits.equals(baseUnits)) {
+ throw new IllegalArgumentException("Cannot compare units with different base units.");
+ }
+ return factor.compareTo(other.factor);
+ }
+ }
+}
diff --git a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/results/FileRenderer.java b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/results/FileRenderer.java
new file mode 100644
index 0000000..423ac74
--- /dev/null
+++ b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/results/FileRenderer.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.performance.results;
+
+import org.gradle.reporting.ReportRenderer;
+import org.gradle.util.GFileUtils;
+
+import java.io.*;
+
+public class FileRenderer {
+ public <T> void render(T model, ReportRenderer<T, Writer> renderer, File outputFile) throws IOException {
+ GFileUtils.parentMkdirs(outputFile);
+ Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outputFile), "UTF-8"));
+ try {
+ renderer.render(model, writer);
+ } finally {
+ writer.close();
+ }
+ }
+}
diff --git a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/results/FormatSupport.java b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/results/FormatSupport.java
new file mode 100644
index 0000000..3761065
--- /dev/null
+++ b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/results/FormatSupport.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.performance.results;
+
+import org.gradle.performance.measure.Amount;
+import org.gradle.performance.measure.DataAmount;
+import org.gradle.performance.measure.Duration;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.TimeZone;
+
+public class FormatSupport {
+ private final DateFormat timeStampFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ private final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
+
+ public FormatSupport() {
+ timeStampFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+ dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+ }
+
+ public String executionTimestamp() {
+ return timeStampFormat.format(new Date());
+ }
+
+ public String timestamp(Date date) {
+ return timeStampFormat.format(date);
+ }
+
+ public String date(Date date) {
+ return dateFormat.format(date);
+ }
+
+ public String seconds(Amount<Duration> duration) {
+ return duration.toUnits(Duration.SECONDS).getValue().toString();
+ }
+
+ public String megabytes(Amount<DataAmount> amount) {
+ return amount.toUnits(DataAmount.MEGA_BYTES).getValue().toString();
+ }
+}
diff --git a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/results/HtmlPageGenerator.java b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/results/HtmlPageGenerator.java
new file mode 100644
index 0000000..b51354a
--- /dev/null
+++ b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/results/HtmlPageGenerator.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.performance.results;
+
+import com.googlecode.jatl.Html;
+import org.gradle.reporting.ReportRenderer;
+import org.gradle.util.GradleVersion;
+
+import java.io.Writer;
+
+public abstract class HtmlPageGenerator<T> extends ReportRenderer<T, Writer> {
+ protected final FormatSupport format = new FormatSupport();
+
+ protected void headSection(Html html) {
+ html.meta()
+ .httpEquiv("Content-Type")
+ .content("text/html; charset=utf-8");
+ html.link()
+ .rel("stylesheet")
+ .type("text/css")
+ .href("css/style.css")
+ .end();
+ html.script()
+ .src("js/jquery.min-1.8.0.js")
+ .end();
+ html.script()
+ .src("js/flot-0.8.1-min.js")
+ .end();
+ }
+
+ protected void footer(Html html) {
+ html.div()
+ .id("footer")
+ .text(String.format("Generated at %s by %s", format.executionTimestamp(), GradleVersion.current()))
+ .end();
+ }
+}
diff --git a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/results/IndexPageGenerator.java b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/results/IndexPageGenerator.java
new file mode 100644
index 0000000..076dc1a
--- /dev/null
+++ b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/results/IndexPageGenerator.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.performance.results;
+
+import com.googlecode.jatl.Html;
+import org.gradle.performance.fixture.BaselineVersion;
+import org.gradle.performance.fixture.PerformanceResults;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Date;
+import java.util.List;
+
+public class IndexPageGenerator extends HtmlPageGenerator<ResultsStore> {
+ @Override
+ public void render(final ResultsStore store, Writer writer) throws IOException {
+ new Html(writer) {{
+ html();
+ head();
+ headSection(this);
+ title().text("Profile report").end();
+ end();
+ body();
+ div().id("content");
+ h2().text("All tests").end();
+ List<String> testNames = store.getTestNames();
+ table().classAttr("history");
+ for (String testName : testNames) {
+ TestExecutionHistory testHistory = store.getTestResults(testName);
+ tr();
+ th().colspan("6").classAttr("test-execution");
+ text(testName);
+ end();
+ end();
+ tr();
+ th().colspan("3").end();
+ th().colspan(String.valueOf(testHistory.getBaselineVersions().size() + 1)).text("Average execution time").end();
+ th().colspan(String.valueOf(testHistory.getBaselineVersions().size() + 1)).text("Average heap usage").end();
+ end();
+ tr();
+ th().text("Date").end();
+ th().text("Test version").end();
+ th().text("Branch").end();
+ for (String version : testHistory.getBaselineVersions()) {
+ th().classAttr("numeric").text(version).end();
+ }
+ th().classAttr("numeric").text("Current").end();
+ for (String version : testHistory.getBaselineVersions()) {
+ th().classAttr("numeric").text(version).end();
+ }
+ th().classAttr("numeric").text("Current").end();
+ end();
+ for (int i = 0; i < testHistory.getResults().size() && i < 5; i++) {
+ PerformanceResults performanceResults = testHistory.getResults().get(i);
+ tr();
+ td().text(format.timestamp(new Date(performanceResults.getTestTime()))).end();
+ td().text(performanceResults.getVersionUnderTest()).end();
+ td().text(performanceResults.getVcsBranch()).end();
+ for (String version : testHistory.getBaselineVersions()) {
+ BaselineVersion baselineVersion = performanceResults.baseline(version);
+ if (baselineVersion.getResults().isEmpty()) {
+ td().text("").end();
+ } else {
+ td().classAttr("numeric").text(baselineVersion.getResults().avgTime().format()).end();
+ }
+ }
+ td().classAttr("numeric").text(performanceResults.getCurrent().avgTime().format()).end();
+ for (String version : testHistory.getBaselineVersions()) {
+ BaselineVersion baselineVersion = performanceResults.baseline(version);
+ if (baselineVersion.getResults().isEmpty()) {
+ td().text("").end();
+ } else {
+ td().classAttr("numeric").text(baselineVersion.getResults().avgMemory().format()).end();
+ }
+ }
+ td().classAttr("numeric").text(performanceResults.getCurrent().avgMemory().format()).end();
+ end();
+ }
+ tr();
+ td().colspan("6");
+ String url = testHistory.getId() + ".html";
+ a().href(url).text("details...").end();
+ end();
+ end();
+ }
+ end();
+ end();
+ footer(this);
+ endAll();
+ }};
+ }
+}
diff --git a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/results/ReportGenerator.java b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/results/ReportGenerator.java
new file mode 100644
index 0000000..9ba80d8
--- /dev/null
+++ b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/results/ReportGenerator.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.performance.results;
+
+import org.apache.commons.lang.StringUtils;
+import org.gradle.util.GFileUtils;
+
+import java.io.File;
+import java.net.URL;
+
+public class ReportGenerator {
+ void generate(final ResultsStore store, File outputDirectory) {
+ try {
+ FileRenderer fileRenderer = new FileRenderer();
+ TestPageGenerator testHtmlRenderer = new TestPageGenerator();
+ TestDataGenerator testDataRenderer = new TestDataGenerator();
+
+ fileRenderer.render(store, new IndexPageGenerator(), new File(outputDirectory, "index.html"));
+
+ for (String testName : store.getTestNames()) {
+ TestExecutionHistory testResults = store.getTestResults(testName);
+ fileRenderer.render(testResults, testHtmlRenderer, new File(outputDirectory, testResults.getId() + ".html"));
+ fileRenderer.render(testResults, testDataRenderer, new File(outputDirectory, testResults.getId() + ".json"));
+ }
+
+ copyResource("jquery.min-1.8.0.js", outputDirectory);
+ copyResource("flot-0.8.1-min.js", outputDirectory);
+ copyResource("style.css", outputDirectory);
+ } catch (Exception e) {
+ throw new RuntimeException(String.format("Could not generate performance test report to '%s'.", outputDirectory), e);
+ }
+ }
+
+ private void copyResource(String resourceName, File outputDirectory) {
+ URL resource = getClass().getClassLoader().getResource("org/gradle/reporting/" + resourceName);
+ String dir = StringUtils.substringAfterLast(resourceName, ".");
+ GFileUtils.copyURLToFile(resource, new File(outputDirectory, dir + "/" + resourceName));
+ }
+}
diff --git a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/results/ResultsStore.java b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/results/ResultsStore.java
new file mode 100644
index 0000000..c66b899
--- /dev/null
+++ b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/results/ResultsStore.java
@@ -0,0 +1,239 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.performance.results;
+
+import org.gradle.internal.UncheckedException;
+import org.gradle.performance.fixture.BaselineVersion;
+import org.gradle.performance.fixture.DataReporter;
+import org.gradle.performance.fixture.MeasuredOperationList;
+import org.gradle.performance.fixture.PerformanceResults;
+import org.gradle.performance.measure.DataAmount;
+import org.gradle.performance.measure.Duration;
+import org.gradle.performance.measure.MeasuredOperation;
+
+import java.io.File;
+import java.math.BigDecimal;
+import java.sql.*;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+/**
+ * A {@link DataReporter} implementation that stores results in an H2 relational database.
+ */
+public class ResultsStore implements DataReporter {
+ private final File dbFile;
+ private Connection connection;
+ private final long ignoreV17Before;
+
+ public ResultsStore() {
+ this(new File(System.getProperty("user.home"), ".gradle-performance-test-data/results"));
+ }
+
+ public ResultsStore(File dbFile) {
+ this.dbFile = dbFile;
+
+ // Ignore some broken samples before the given date
+ DateFormat timeStampFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ timeStampFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+ try {
+ ignoreV17Before = timeStampFormat.parse("2013-07-03 00:00:00").getTime();
+ } catch (ParseException e) {
+ throw UncheckedException.throwAsUncheckedException(e);
+ }
+ }
+
+ public void report(final PerformanceResults results) {
+ try {
+ withConnection(new ConnectionAction<Void>() {
+ public Void execute(Connection connection) throws Exception {
+ long testId;
+ PreparedStatement statement = connection.prepareStatement("insert into testExecution(testId, executionTime, targetVersion, testProject, tasks, args, operatingSystem, jvm, vcsBranch, vcsCommit) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
+ try {
+ statement.setString(1, results.getTestId());
+ statement.setTimestamp(2, new Timestamp(results.getTestTime()));
+ statement.setString(3, results.getVersionUnderTest());
+ statement.setString(4, results.getTestProject());
+ statement.setObject(5, results.getTasks());
+ statement.setObject(6, results.getArgs());
+ statement.setString(7, results.getOperatingSystem());
+ statement.setString(8, results.getJvm());
+ statement.setString(9, results.getVcsBranch());
+ statement.setString(10, results.getVcsCommit());
+ statement.execute();
+ ResultSet keys = statement.getGeneratedKeys();
+ keys.next();
+ testId = keys.getLong(1);
+ } finally {
+ statement.close();
+ }
+ statement = connection.prepareStatement("insert into testOperation(testExecution, version, executionTimeMs, heapUsageBytes) values (?, ?, ?, ?)");
+ try {
+ addOperations(statement, testId, null, results.getCurrent());
+ for (BaselineVersion baselineVersion : results.getBaselineVersions()) {
+ addOperations(statement, testId, baselineVersion.getVersion(), baselineVersion.getResults());
+ }
+ } finally {
+ statement.close();
+ }
+ return null;
+ }
+ });
+ } catch (Exception e) {
+ throw new RuntimeException(String.format("Could not open results datastore '%s'.", dbFile), e);
+ }
+ }
+
+ private void addOperations(PreparedStatement statement, long testId, String version, MeasuredOperationList operations) throws SQLException {
+ for (MeasuredOperation operation : operations) {
+ statement.setLong(1, testId);
+ statement.setString(2, version);
+ statement.setBigDecimal(3, operation.getExecutionTime().toUnits(Duration.MILLI_SECONDS).getValue());
+ statement.setBigDecimal(4, operation.getTotalMemoryUsed().toUnits(DataAmount.BYTES).getValue());
+ statement.execute();
+ }
+ }
+
+ public List<String> getTestNames() {
+ try {
+ return withConnection(new ConnectionAction<List<String>>() {
+ public List<String> execute(Connection connection) throws Exception {
+ List<String> testNames = new ArrayList<String>();
+ ResultSet testExecutions = connection.createStatement().executeQuery("select distinct testId from testExecution order by testId");
+ while (testExecutions.next()) {
+ testNames.add(testExecutions.getString(1));
+ }
+ return testNames;
+ }
+ });
+ } catch (Exception e) {
+ throw new RuntimeException(String.format("Could not load test history from datastore '%s'.", dbFile), e);
+ }
+ }
+
+ public TestExecutionHistory getTestResults(final String testName) {
+ try {
+ return withConnection(new ConnectionAction<TestExecutionHistory>() {
+ public TestExecutionHistory execute(Connection connection) throws Exception {
+ List<PerformanceResults> results = new ArrayList<PerformanceResults>();
+ Set<String> allVersions = new TreeSet<String>();
+ PreparedStatement executionsForName = connection.prepareStatement("select id, executionTime, targetVersion, testProject, tasks, args, operatingSystem, jvm, vcsBranch, vcsCommit from testExecution where testId = ? order by executionTime desc");
+ PreparedStatement buildsForTest = connection.prepareStatement("select version, executionTimeMs, heapUsageBytes from testOperation where testExecution = ?");
+ executionsForName.setString(1, testName);
+ ResultSet testExecutions = executionsForName.executeQuery();
+ while (testExecutions.next()) {
+ long id = testExecutions.getLong(1);
+ PerformanceResults performanceResults = new PerformanceResults();
+ performanceResults.setTestId(testName);
+ performanceResults.setTestTime(testExecutions.getTimestamp(2).getTime());
+ performanceResults.setVersionUnderTest(testExecutions.getString(3));
+ performanceResults.setTestProject(testExecutions.getString(4));
+ performanceResults.setTasks(toArray(testExecutions.getObject(5)));
+ performanceResults.setArgs(toArray(testExecutions.getObject(6)));
+ performanceResults.setOperatingSystem(testExecutions.getString(7));
+ performanceResults.setJvm(testExecutions.getString(8));
+ performanceResults.setVcsBranch(testExecutions.getString(9));
+ performanceResults.setVcsCommit(testExecutions.getString(10));
+
+ results.add(performanceResults);
+
+ buildsForTest.setLong(1, id);
+ ResultSet builds = buildsForTest.executeQuery();
+ while (builds.next()) {
+ String version = builds.getString(1);
+ if ("1.7".equals(version) && performanceResults.getTestTime() <= ignoreV17Before) {
+ // Ignore some broken samples
+ continue;
+ }
+ BigDecimal executionTimeMs = builds.getBigDecimal(2);
+ BigDecimal heapUsageBytes = builds.getBigDecimal(3);
+ MeasuredOperation operation = new MeasuredOperation();
+ operation.setExecutionTime(Duration.millis(executionTimeMs));
+ operation.setTotalMemoryUsed(DataAmount.bytes(heapUsageBytes));
+
+ if (version == null) {
+ performanceResults.getCurrent().add(operation);
+ } else {
+ BaselineVersion baselineVersion = performanceResults.baseline(version);
+ baselineVersion.getResults().add(operation);
+ allVersions.add(version);
+ }
+ }
+ }
+ testExecutions.close();
+ buildsForTest.close();
+ executionsForName.close();
+
+ return new TestExecutionHistory(testName, new ArrayList<String>(allVersions), results);
+ }
+ });
+ } catch (Exception e) {
+ throw new RuntimeException(String.format("Could not load results from datastore '%s'.", dbFile), e);
+ }
+ }
+
+ private String[] toArray(Object object) {
+ Object[] value = (Object[]) object;
+ String[] result = new String[value.length];
+ for (int i = 0; i < value.length; i++) {
+ result[i] = value[i].toString();
+ }
+ return result;
+ }
+
+ public void close() {
+ if (connection != null) {
+ try {
+ connection.close();
+ } catch (SQLException e) {
+ throw new RuntimeException(String.format("Could not close datastore '%s'.", dbFile), e);
+ } finally {
+ connection = null;
+ }
+ }
+ }
+
+ private <T> T withConnection(ConnectionAction<T> action) throws Exception {
+ if (connection == null) {
+ dbFile.getParentFile().mkdirs();
+ Class.forName("org.h2.Driver");
+ connection = DriverManager.getConnection(String.format("jdbc:h2:%s", dbFile.getAbsolutePath()), "sa", "");
+ try {
+ initSchema(connection);
+ } catch (Exception e) {
+ connection.close();
+ connection = null;
+ throw e;
+ }
+ }
+ return action.execute(connection);
+ }
+
+ private void initSchema(Connection connection) throws Exception {
+ Statement statement = connection.createStatement();
+ statement.execute("create table if not exists testExecution (id bigint identity not null, testId varchar not null, executionTime timestamp not null, targetVersion varchar not null, testProject varchar not null, tasks array not null, args array not null, operatingSystem varchar not null, jvm varchar not null)");
+ statement.execute("create table if not exists testOperation (testExecution bigint not null, version varchar, executionTimeMs decimal not null, heapUsageBytes decimal not null, foreign key(testExecution) references testExecution(id))");
+ statement.execute("alter table testExecution add column if not exists vcsBranch varchar not null default 'master'");
+ statement.execute("alter table testExecution add column if not exists vcsCommit varchar");
+ statement.close();
+ }
+
+ private interface ConnectionAction<T> {
+ T execute(Connection connection) throws Exception;
+ }
+}
diff --git a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/results/TestDataGenerator.java b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/results/TestDataGenerator.java
new file mode 100644
index 0000000..16ffa8a
--- /dev/null
+++ b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/results/TestDataGenerator.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.performance.results;
+
+import org.gradle.api.Transformer;
+import org.gradle.performance.fixture.MeasuredOperationList;
+import org.gradle.performance.fixture.PerformanceResults;
+import org.gradle.reporting.ReportRenderer;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.Writer;
+import java.util.Date;
+import java.util.List;
+
+public class TestDataGenerator extends ReportRenderer<TestExecutionHistory, Writer> {
+ protected final FormatSupport format = new FormatSupport();
+
+ @Override
+ public void render(TestExecutionHistory testHistory, Writer output) throws IOException {
+ PrintWriter out = new PrintWriter(output);
+ List<PerformanceResults> sortedResults = testHistory.getResultsOldestFirst();
+ out.println("{");
+ out.println("\"labels\": [");
+ for (int i = 0; i < sortedResults.size(); i++) {
+ PerformanceResults results = sortedResults.get(i);
+ if (i > 0) {
+ out.print(", ");
+ }
+ out.print("\"" + format.date(new Date(results.getTestTime())) + "\"");
+ }
+ out.println("],");
+ out.print("\"executionTime\":");
+ render(testHistory, new Transformer<String, MeasuredOperationList>() {
+ public String transform(MeasuredOperationList original) {
+ return format.seconds(original.avgTime());
+ }
+ }, out);
+ out.println(",");
+ out.print("\"heapUsage\":");
+ render(testHistory, new Transformer<String, MeasuredOperationList>() {
+ public String transform(MeasuredOperationList original) {
+ return format.megabytes(original.avgMemory());
+ }
+ }, out);
+ out.println("}");
+ out.flush();
+ }
+
+ void render(TestExecutionHistory testHistory, Transformer<String, MeasuredOperationList> valueRenderer, PrintWriter out) {
+ List<PerformanceResults> sortedResults = testHistory.getResultsOldestFirst();
+ out.println(" [{");
+ out.println(" \"label\": \"current\",");
+ out.print(" \"data\": [ ");
+ for (int j = 0; j < sortedResults.size(); j++) {
+ PerformanceResults results = sortedResults.get(j);
+ if (j > 0) {
+ out.print(", ");
+ }
+ out.print("[" + j + ", " + valueRenderer.transform(results.getCurrent()) + "]");
+ }
+ out.println("]");
+ out.print(" }");
+ for (int i = 0; i < testHistory.getBaselineVersions().size(); i++) {
+ String version = testHistory.getBaselineVersions().get(i);
+ out.println(",");
+ out.println(" {");
+ out.println(" \"label\": \"" + version + "\",");
+ out.print("\"data\": [");
+ boolean empty = true;
+ for (int j = 0; j < sortedResults.size(); j++) {
+ PerformanceResults results = sortedResults.get(j);
+ MeasuredOperationList measuredOperations = results.baseline(version).getResults();
+ if (!measuredOperations.isEmpty()) {
+ if (!empty) {
+ out.print(", ");
+ }
+ out.print("[" + j + ", " + valueRenderer.transform(measuredOperations) + "]");
+ empty = false;
+ }
+ }
+ out.println("]");
+ out.print(" }");
+ }
+ out.println();
+ out.println("]");
+ }
+}
diff --git a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/results/TestExecutionHistory.java b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/results/TestExecutionHistory.java
new file mode 100644
index 0000000..959c1ef
--- /dev/null
+++ b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/results/TestExecutionHistory.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.performance.results;
+
+import org.gradle.performance.fixture.PerformanceResults;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class TestExecutionHistory {
+ private final String name;
+ private final List<String> versions;
+ private final List<PerformanceResults> newestFirst;
+ private List<PerformanceResults> oldestFirst;
+
+ public TestExecutionHistory(String name, List<String> versions, List<PerformanceResults> newestFirst) {
+ this.name = name;
+ this.versions = versions;
+ this.newestFirst = newestFirst;
+ }
+
+ public String getId() {
+ return name.replaceAll("\\s+", "-");
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public List<String> getBaselineVersions() {
+ return versions;
+ }
+
+ /**
+ * Returns results from most recent to least recent.
+ */
+ public List<PerformanceResults> getResults() {
+ return newestFirst;
+ }
+
+ /**
+ * Returns results from least recent to most recent.
+ */
+ public List<PerformanceResults> getResultsOldestFirst() {
+ if (oldestFirst == null) {
+ oldestFirst = new ArrayList<PerformanceResults>(newestFirst);
+ Collections.reverse(oldestFirst);
+ }
+ return oldestFirst;
+ }
+}
diff --git a/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/results/TestPageGenerator.java b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/results/TestPageGenerator.java
new file mode 100644
index 0000000..2e89c33
--- /dev/null
+++ b/subprojects/performance/src/testFixtures/groovy/org/gradle/performance/results/TestPageGenerator.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.performance.results;
+
+import com.google.common.base.Joiner;
+import com.googlecode.jatl.Html;
+import org.gradle.performance.fixture.BaselineVersion;
+import org.gradle.performance.fixture.PerformanceResults;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Date;
+
+public class TestPageGenerator extends HtmlPageGenerator<TestExecutionHistory> {
+ @Override
+ public void render(final TestExecutionHistory testHistory, Writer writer) throws IOException {
+ new Html(writer) {{
+ html();
+ head();
+ headSection(this);
+ title().text(String.format("Profile test %s report", testHistory.getName())).end();
+ script();
+ text("$(function() {\n");
+ text("$.ajax({ url:'" + testHistory.getId() + ".json\', dataType: 'json',");
+ text(" success: function(data) {\n");
+ text(" var labels = data.labels;\n");
+ text(" var options = { series: { points: { show: true }, lines: { show: true } }, legend: { noColumns: 0, margin: 1 }, grid: { hoverable: true, clickable: true }, xaxis: { tickFormatter: function(index, value) { return labels[index]; } } };\n");
+ text(" $.plot('#executionTimeChart', data.executionTime, options);\n");
+ text(" $.plot('#heapUsageChart', data.heapUsage, options);\n");
+ text(" $('#executionTimeChart').bind('plothover', function (event, pos, item) {\n");
+ text(" if (!item) {\n");
+ text(" $('#tooltip').hide();\n");
+ text(" } else {\n");
+ text(" var text = 'Version: ' + item.series.label + ', date: ' + labels[item.dataIndex] + ', execution time: ' + item.datapoint[1] + 's';\n");
+ text(" $('#tooltip').html(text).css({top: item.pageY - 10, left: item.pageX + 10}).show();\n");
+ text(" }\n");
+ text(" });\n");
+ text(" $('#heapUsageChart').bind('plothover', function (event, pos, item) {\n");
+ text(" if (!item) {\n");
+ text(" $('#tooltip').hide();\n");
+ text(" } else {\n");
+ text(" var text = 'Version: ' + item.series.label + ', date: ' + labels[item.dataIndex] + ', heap usage: ' + item.datapoint[1] + 'mb';\n");
+ text(" $('#tooltip').html(text).css({top: item.pageY - 10, left: item.pageX + 10}).show();\n");
+ text(" }\n");
+ text(" });\n");
+ text(" }\n");
+ text("});\n");
+ text("});");
+ end();
+ end();
+ body();
+ div().id("content");
+ h2().text(String.format("Test %s", testHistory.getName())).end();
+ h3().text("Average execution time").end();
+ div().id("executionTimeChart").classAttr("chart");
+ p().text("Loading...").end();
+ end();
+ h3().text("Average heap usage").end();
+ div().id("heapUsageChart").classAttr("chart");
+ p().text("Loading...").end();
+ end();
+ div().id("tooltip").end();
+ h3().text("Test history").end();
+ table().classAttr("history");
+ tr();
+ th().colspan("3").end();
+ th().colspan(String.valueOf(testHistory.getBaselineVersions().size() + 1)).text("Average execution time").end();
+ th().colspan(String.valueOf(testHistory.getBaselineVersions().size() + 1)).text("Average heap usage").end();
+ th().colspan("5").text("Details").end();
+ end();
+ tr();
+ th().text("Date").end();
+ th().text("Test version").end();
+ th().text("Branch").end();
+ for (String version : testHistory.getBaselineVersions()) {
+ th().classAttr("numeric").text(version).end();
+ }
+ th().classAttr("numeric").text("Current").end();
+ for (String version : testHistory.getBaselineVersions()) {
+ th().classAttr("numeric").text(version).end();
+ }
+ th().classAttr("numeric").text("Current").end();
+ th().text("Test project").end();
+ th().text("Tasks").end();
+ th().text("Operating System").end();
+ th().text("JVM").end();
+ th().text("Commit Id").end();
+ end();
+ for (PerformanceResults performanceResults : testHistory.getResults()) {
+ tr();
+ td().text(format.timestamp(new Date(performanceResults.getTestTime()))).end();
+ td().text(performanceResults.getVersionUnderTest()).end();
+ td().text(performanceResults.getVcsBranch()).end();
+ for (String version : testHistory.getBaselineVersions()) {
+ BaselineVersion baselineVersion = performanceResults.baseline(version);
+ if (baselineVersion.getResults().isEmpty()) {
+ td().text("").end();
+ } else {
+ td().classAttr("numeric").text(baselineVersion.getResults().avgTime().format()).end();
+ }
+ }
+ td().classAttr("numeric").text(performanceResults.getCurrent().avgTime().format()).end();
+ for (String version : testHistory.getBaselineVersions()) {
+ BaselineVersion baselineVersion = performanceResults.baseline(version);
+ if (baselineVersion.getResults().isEmpty()) {
+ td().text("").end();
+ } else {
+ td().classAttr("numeric").text(baselineVersion.getResults().avgMemory().format()).end();
+ }
+ }
+ td().classAttr("numeric").text(performanceResults.getCurrent().avgMemory().format()).end();
+ td().text(performanceResults.getTestProject()).end();
+ td();
+ text(Joiner.on(", ").join(performanceResults.getArgs()));
+ text(" ");
+ text(Joiner.on(", ").join(performanceResults.getTasks()));
+ end();
+ td().text(performanceResults.getOperatingSystem()).end();
+ td().text(performanceResults.getJvm()).end();
+ td().text(performanceResults.getVcsCommit()).end();
+ end();
+ }
+ end();
+ end();
+ footer(this);
+ endAll();
+ }};
+ }
+}
diff --git a/subprojects/performance/src/testFixtures/resources/org/gradle/reporting/style.css b/subprojects/performance/src/testFixtures/resources/org/gradle/reporting/style.css
new file mode 100644
index 0000000..c3893cd
--- /dev/null
+++ b/subprojects/performance/src/testFixtures/resources/org/gradle/reporting/style.css
@@ -0,0 +1,59 @@
+body {
+ font-family: sans-serif;
+ font-size: 12pt;
+ margin: 3em;
+ color: #444;
+}
+
+h2 {
+ font-size: 14pt;
+ margin-top: 2em;
+}
+
+#footer {
+ margin-top: 4em;
+ font-size: 8pt;
+}
+
+table.history {
+ margin-top: 20px;
+ font-size: 10pt;
+}
+
+th, td {
+ white-space: nowrap;
+ padding-right: 8px;
+ text-align: left;
+}
+
+th.numeric, td.numeric {
+ text-align: right;
+}
+
+th.test-execution {
+ font-size: 14pt;
+ padding-top: 1em;
+}
+
+.chart {
+ width: 1000px;
+ height: 280px;
+ margin-top: 20px;
+ margin-bottom: 20px;
+}
+
+.chart p {
+ font-size: 8pt;
+ color: #a0a0a0;
+ text-align: center;
+}
+
+#tooltip {
+ position: absolute;
+ display: none;
+ font-size: 10pt;
+ background-color: #fee;
+ border: solid 1px #fdd;
+ opacity: 0.80;
+ padding: 3px;
+}
\ No newline at end of file
diff --git a/subprojects/plugins/plugins.gradle b/subprojects/plugins/plugins.gradle
index e1b00be..213dc4f 100644
--- a/subprojects/plugins/plugins.gradle
+++ b/subprojects/plugins/plugins.gradle
@@ -25,12 +25,13 @@ if (!javaVersion.java6Compatible) {
}
dependencies {
- groovy libraries.groovy
+ compile libraries.groovy
compile project(':core')
compile project(':coreImpl')
- compile project(':wrapper')
compile project(':reporting')
+ compile project(':languageBase')
+ compile project(':languageJvm')
compile libraries.ant
compile libraries.asm
diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/api/plugins/BuildSrcPluginTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/api/plugins/BuildSrcPluginTest.groovy
index 4df8b36..c50d179 100644
--- a/subprojects/plugins/src/integTest/groovy/org/gradle/api/plugins/BuildSrcPluginTest.groovy
+++ b/subprojects/plugins/src/integTest/groovy/org/gradle/api/plugins/BuildSrcPluginTest.groovy
@@ -41,7 +41,7 @@ class BuildSrcPluginTest extends AbstractIntegrationSpec {
apply plugin: "groovy"
dependencies {
- groovy localGroovy()
+ compile localGroovy()
compile gradleApi()
}
"""
diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/api/tasks/bundling/JarIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/api/tasks/bundling/JarIntegrationTest.groovy
index 2a7c872..fabd225 100644
--- a/subprojects/plugins/src/integTest/groovy/org/gradle/api/tasks/bundling/JarIntegrationTest.groovy
+++ b/subprojects/plugins/src/integTest/groovy/org/gradle/api/tasks/bundling/JarIntegrationTest.groovy
@@ -17,7 +17,9 @@
package org.gradle.api.tasks.bundling
import org.gradle.integtests.fixtures.AbstractIntegrationSpec
-import static org.hamcrest.Matchers.equalTo
+import org.gradle.test.fixtures.archive.JarTestFixture
+
+import static org.hamcrest.Matchers.*
class JarIntegrationTest extends AbstractIntegrationSpec {
@@ -160,4 +162,155 @@ class JarIntegrationTest extends AbstractIntegrationSpec {
jar.unzipTo(expandDir)
expandDir.assertHasDescendants('dir1/file1.txt', 'dir2/file2.txt', 'META-INF/MANIFEST.MF')
}
+
+ def excludeDuplicatesUseManifestOverMetaInf() {
+ createDir('meta-inf') {
+ file 'MANIFEST.MF'
+ }
+ buildFile << '''
+ task jar(type: Jar) {
+ duplicatesStrategy = 'exclude'
+ metaInf {
+ from 'meta-inf'
+ }
+ manifest {
+ attributes(attr: 'from manifest')
+ }
+ destinationDir = buildDir
+ archiveName = 'test.jar'
+ }
+
+ '''
+ when:
+ run 'jar'
+ then:
+ def jar = file('build/test.jar')
+ def manifest = jar.manifest
+ manifest.mainAttributes.getValue('attr') == 'from manifest'
+ }
+
+
+ def excludeDuplicatesUseMetaInfOverRegularFiles() {
+ createDir('meta-inf1') {
+ file 'file.txt'
+ }
+
+ createDir('meta-inf2') {
+ file 'file.txt'
+ }
+
+ file('meta-inf1/file.txt').text = 'good'
+ file('meta-inf2/file.txt').text = 'bad'
+
+
+ buildFile << '''
+ task jar(type: Jar) {
+ duplicatesStrategy = 'exclude'
+ // this should be excluded even though it comes first
+ into('META-INF') {
+ from 'meta-inf2'
+ }
+ metaInf {
+ from 'meta-inf1'
+ }
+ destinationDir = buildDir
+ archiveName = 'test.jar'
+ }
+
+ '''
+ when:
+ run 'jar'
+ then:
+ def jar = file('build/test.jar')
+ jar.unzipTo(file('expected'))
+ def target = file('expected/META-INF/file.txt')
+
+ then:
+ target.assertIsFile()
+ target.text == 'good'
+ }
+
+ def duplicateServicesIncludedOthersExcluded() {
+ createParallelDirsWithServices()
+
+ given:
+ buildFile << '''
+ task jar(type: Jar) {
+ archiveName = 'test.jar'
+ from 'dir1'
+ from 'dir2'
+ eachFile {
+ it.duplicatesStrategy = it.relativePath.toString().startsWith('META-INF/services/') ? 'include' : 'exclude'
+ }
+ }
+
+ '''
+ when:
+ run 'jar'
+ then:
+
+ confirmDuplicateServicesPreserved()
+ }
+
+ def duplicatesExcludedByDefaultWithExceptionForServices() {
+ createParallelDirsWithServices()
+
+ given:
+ buildFile << '''
+ task jar(type: Jar) {
+ archiveName = 'test.jar'
+ from 'dir1'
+ from 'dir2'
+ duplicatesStrategy = 'exclude'
+ filesMatching ('META-INF/services/**') {
+ duplicatesStrategy = 'include'
+ }
+ }
+
+ '''
+ when:
+ run 'jar'
+ then:
+ confirmDuplicateServicesPreserved()
+ }
+
+ private def createParallelDirsWithServices() {
+ createDir('dir1') {
+ 'META-INF' {
+ services {
+ file('org.gradle.Service')
+ }
+ }
+ path {
+ file 'test.txt'
+ }
+ }
+ createDir('dir2') {
+ 'META-INF' {
+ services {
+ file('org.gradle.Service')
+ }
+ }
+ file {
+ file 'test.txt'
+ }
+ }
+
+ file('dir1/META-INF/services/org.gradle.Service').write('org.gradle.DefaultServiceImpl')
+ file('dir2/META-INF/services/org.gradle.Service').write('org.gradle.BetterServiceImpl')
+ file('dir1/test.txt').write('Content of first file')
+ file('dir2/test.txt').write('Content of second file')
+ }
+
+ private def confirmDuplicateServicesPreserved() {
+ def jar = new JarTestFixture(file('test.jar'))
+
+ assert 2 == jar.countFiles('META-INF/services/org.gradle.Service')
+ assert 1 == jar.countFiles('path/test.txt')
+
+ jar.assertFileContent('test.txt', 'Content of first file')
+ jar.hasService('org.gradle.Service', 'org.gradle.BetterServiceImpl')
+ jar.hasService('org.gradle.Service', 'org.gradle.DefaultServiceImpl')
+ }
+
}
diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/api/tasks/bundling/WarTaskIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/api/tasks/bundling/WarTaskIntegrationTest.groovy
index 11354d7..ba14dc2 100644
--- a/subprojects/plugins/src/integTest/groovy/org/gradle/api/tasks/bundling/WarTaskIntegrationTest.groovy
+++ b/subprojects/plugins/src/integTest/groovy/org/gradle/api/tasks/bundling/WarTaskIntegrationTest.groovy
@@ -17,6 +17,7 @@
package org.gradle.api.tasks.bundling
import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+
import static org.hamcrest.Matchers.equalTo
class WarTaskIntegrationTest extends AbstractIntegrationSpec {
@@ -149,4 +150,105 @@ class WarTaskIntegrationTest extends AbstractIntegrationSpec {
'WEB-INF/webinf1/file1.txt',
'WEB-INF/dir2/file2.txt')
}
+
+ def "exclude duplicates: webXml precedence over webInf"() {
+ given:
+ createDir('bad') {
+ file('web.xml')
+ }
+ file('good.xml')
+
+ file('bad/web.xml').text = 'bad'
+ file('good.xml').text = 'good'
+
+ buildFile << '''
+ task war(type: War) {
+ webInf {
+ from 'bad'
+ }
+ webXml = file('good.xml')
+ destinationDir = buildDir
+ archiveName = 'test.war'
+ duplicatesStrategy = 'exclude'
+ }
+ '''
+ when:
+ run "war"
+ def war = file('build/test.war')
+ def expandDir = file('expanded')
+ war.unzipTo(expandDir)
+ then:
+ expandDir.assertHasDescendants('WEB-INF/web.xml', 'META-INF/MANIFEST.MF')
+ file('expanded/WEB-INF/web.xml').text == 'good'
+ }
+
+ def "exclude duplicates: classpath precedence over webInf"() {
+ given:
+ createDir('bad') {
+ lib {
+ file('file.txt')
+ }
+ }
+ createDir('good') {
+ file('file.txt')
+ }
+
+ file('bad/lib/file.txt').text = 'bad'
+ file('good/file.txt').text = 'good'
+
+ buildFile << '''
+ task war(type: War) {
+ webInf {
+ from 'bad'
+ }
+ classpath 'good/file.txt'
+ destinationDir = buildDir
+ archiveName = 'test.war'
+ duplicatesStrategy = 'exclude'
+ }
+ '''
+ when:
+ run "war"
+ def war = file('build/test.war')
+ def expandDir = file('expanded')
+ war.unzipTo(expandDir)
+ then:
+ expandDir.assertHasDescendants('WEB-INF/lib/file.txt', 'META-INF/MANIFEST.MF')
+ file('expanded/WEB-INF/lib/file.txt').text == 'good'
+ }
+
+ def "exclude duplicates: webInf over normal files"() {
+ given:
+ createDir('bad') {
+ file('file.txt')
+ }
+ createDir('good') {
+ file('file.txt')
+ }
+
+ file('bad/file.txt').text = 'bad'
+ file('good/file.txt').text = 'good'
+
+ buildFile << '''
+ task war(type: War) {
+ into('WEB-INF') {
+ from 'bad'
+ }
+ webInf {
+ from 'good'
+ }
+ destinationDir = buildDir
+ archiveName = 'test.war'
+ duplicatesStrategy = 'exclude'
+ }
+ '''
+ when:
+ run "war"
+ def war = file('build/test.war')
+ def expandDir = file('expanded')
+ war.unzipTo(expandDir)
+ then:
+ expandDir.assertHasDescendants('WEB-INF/file.txt', 'META-INF/MANIFEST.MF')
+ file('expanded/WEB-INF/file.txt').text == 'good'
+ }
}
diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/groovy/GroovyBasePluginIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/groovy/GroovyBasePluginIntegrationTest.groovy
index 629b864..63fb7d6 100644
--- a/subprojects/plugins/src/integTest/groovy/org/gradle/groovy/GroovyBasePluginIntegrationTest.groovy
+++ b/subprojects/plugins/src/integTest/groovy/org/gradle/groovy/GroovyBasePluginIntegrationTest.groovy
@@ -18,6 +18,35 @@ package org.gradle.groovy
import org.gradle.integtests.fixtures.AbstractIntegrationSpec
class GroovyBasePluginIntegrationTest extends AbstractIntegrationSpec {
+ def "defaults groovyClasspath to 'groovy' configuration if the latter is non-empty"() {
+ executer.withDeprecationChecksDisabled()
+ file("build.gradle") << """
+apply plugin: "groovy-base"
+
+sourceSets {
+ custom
+}
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ groovy "org.codehaus.groovy:groovy-all:2.1.2"
+}
+
+task groovydoc(type: Groovydoc)
+
+task verify << {
+ assert compileCustomGroovy.groovyClasspath.is(configurations.groovy)
+ assert groovydoc.groovyClasspath.is(configurations.groovy)
+}
+"""
+
+ expect:
+ succeeds("verify")
+ }
+
def "defaults Groovy class path to inferred Groovy dependency if Groovy configuration is empty"() {
file("build.gradle") << """
apply plugin: "groovy-base"
@@ -49,12 +78,12 @@ task verify << {
where:
dependency | jarFile
- "org.codehaus.groovy:groovy-all:2.0.5" | "groovy-all-2.0.5.jar"
- "org.codehaus.groovy:groovy:2.0.5" | "groovy-2.0.5.jar"
- "org.codehaus.groovy:groovy-all:2.0.5:indy" | "groovy-all-2.0.5-indy.jar"
+ "org.codehaus.groovy:groovy-all:2.1.2" | "groovy-all-2.1.2.jar"
+ "org.codehaus.groovy:groovy:2.1.2" | "groovy-2.1.2.jar"
+ "org.codehaus.groovy:groovy-all:2.1.2:indy" | "groovy-all-2.1.2-indy.jar"
}
- def "defaults groovyClasspath to (empty) Groovy configuration if Groovy library isn't found on class path"() {
+ def "only resolves source class path feeding into inferred Groovy class path if/when the latter is actually used (but not during autowiring)"() {
file("build.gradle") << """
apply plugin: "groovy-base"
@@ -66,15 +95,50 @@ repositories {
mavenCentral()
}
-task groovydoc(type: Groovydoc)
+dependencies {
+ customCompile "org.codehaus.groovy:groovy-all:2.1.2"
+}
+
+task groovydoc(type: Groovydoc) {
+ classpath = sourceSets.custom.runtimeClasspath
+}
task verify << {
- assert compileCustomGroovy.groovyClasspath.is(configurations.groovy)
- assert groovydoc.groovyClasspath.is(configurations.groovy)
+ assert configurations.customCompile.state.toString() == "UNRESOLVED"
+ assert configurations.customRuntime.state.toString() == "UNRESOLVED"
}
-"""
+ """
expect:
succeeds("verify")
}
+
+ def "not specifying a groovy runtime produces decent error message"() {
+ given:
+ buildFile << """
+ apply plugin: "groovy-base"
+
+ sourceSets {
+ main {}
+ }
+
+ repositories {
+ mavenCentral()
+ }
+
+ dependencies {
+ compile "com.google.guava:guava:11.0.2"
+ }
+ """
+
+ file("src/main/groovy/Thing.groovy") << """
+ class Thing {}
+ """
+
+ when:
+ fails "compileGroovy"
+
+ then:
+ failure.assertHasDescription "Cannot infer Groovy class path because no Groovy Jar was found on class path: configuration ':compile'"
+ }
}
diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/groovy/GroovyPluginIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/groovy/GroovyPluginIntegrationTest.groovy
new file mode 100644
index 0000000..118b8e2
--- /dev/null
+++ b/subprojects/plugins/src/integTest/groovy/org/gradle/groovy/GroovyPluginIntegrationTest.groovy
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.groovy
+
+import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+
+class GroovyPluginIntegrationTest extends AbstractIntegrationSpec {
+
+ def groovyConfigurationCanStillBeUsedButIsDeprecated() {
+ given:
+ buildFile << """
+ apply plugin: "groovy"
+
+ repositories {
+ mavenCentral()
+ }
+
+ dependencies {
+ groovy "org.codehaus.groovy:groovy-all:2.0.5"
+ compile "com.google.guava:guava:11.0.2"
+ }
+ """
+
+ file("src/main/groovy/Thing.groovy") << """
+ import com.google.common.base.Strings
+
+ class Thing {}
+ """
+
+ and:
+ executer.withDeprecationChecksDisabled()
+
+ when:
+ succeeds("build")
+
+ then:
+ output.contains("The groovy configuration has been deprecated")
+ }
+}
diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/groovy/compile/AntForkingGroovyCompilerIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/groovy/compile/AntForkingGroovyCompilerIntegrationTest.groovy
index fb9b4ac..4881ba8 100644
--- a/subprojects/plugins/src/integTest/groovy/org/gradle/groovy/compile/AntForkingGroovyCompilerIntegrationTest.groovy
+++ b/subprojects/plugins/src/integTest/groovy/org/gradle/groovy/compile/AntForkingGroovyCompilerIntegrationTest.groovy
@@ -18,7 +18,7 @@ package org.gradle.groovy.compile
import org.gradle.integtests.fixtures.TargetVersions
import org.gradle.util.VersionNumber
- at TargetVersions(['1.6.9', '1.7.11', '1.8.8', '2.0.5'])
+ at TargetVersions(['1.6.9', '1.7.11', '1.8.8', '2.0.5', '2.1.0'])
class AntForkingGroovyCompilerIntegrationTest extends GroovyCompilerIntegrationSpec {
@Override
diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/groovy/compile/BasicGroovyCompilerIntegrationSpec.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/groovy/compile/BasicGroovyCompilerIntegrationSpec.groovy
index 6ccc619..a9cb48d 100644
--- a/subprojects/plugins/src/integTest/groovy/org/gradle/groovy/compile/BasicGroovyCompilerIntegrationSpec.groovy
+++ b/subprojects/plugins/src/integTest/groovy/org/gradle/groovy/compile/BasicGroovyCompilerIntegrationSpec.groovy
@@ -24,7 +24,7 @@ import org.gradle.integtests.fixtures.executer.ExecutionResult
import org.gradle.util.VersionNumber
import org.junit.Rule
- at TargetVersions(['1.5.8', '1.6.9', '1.7.11', '1.8.8', '2.0.5'])
+ at TargetVersions(['1.5.8', '1.6.9', '1.7.11', '1.8.8', '2.0.5', '2.1.0'])
abstract class BasicGroovyCompilerIntegrationSpec extends MultiVersionIntegrationSpec {
@Rule TestResources resources = new TestResources(temporaryFolder)
diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/groovy/compile/GroovyCompilerIntegrationSpec.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/groovy/compile/GroovyCompilerIntegrationSpec.groovy
index dbd8630..3fef919 100644
--- a/subprojects/plugins/src/integTest/groovy/org/gradle/groovy/compile/GroovyCompilerIntegrationSpec.groovy
+++ b/subprojects/plugins/src/integTest/groovy/org/gradle/groovy/compile/GroovyCompilerIntegrationSpec.groovy
@@ -15,6 +15,7 @@
*/
package org.gradle.groovy.compile
+import org.gradle.internal.jvm.Jvm
import spock.lang.Issue
abstract class GroovyCompilerIntegrationSpec extends BasicGroovyCompilerIntegrationSpec {
@@ -68,4 +69,15 @@ abstract class GroovyCompilerIntegrationSpec extends BasicGroovyCompilerIntegrat
then:
noExceptionThrown()
}
+
+
+ def canJointCompileWithJavaCompilerExecutable() {
+ args("-PjdkHome=${Jvm.current().getExecutable('javac')}")
+
+ expect:
+ succeeds("compileGroovy")
+ !errorOutput
+ file("build/classes/main/GroovyCode.class").exists()
+ file("build/classes/main/JavaCode.class").exists()
+ }
}
diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/groovy/environment/JreJavaHomeGroovyIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/groovy/environment/JreJavaHomeGroovyIntegrationTest.groovy
index 591a545..78a0058 100644
--- a/subprojects/plugins/src/integTest/groovy/org/gradle/groovy/environment/JreJavaHomeGroovyIntegrationTest.groovy
+++ b/subprojects/plugins/src/integTest/groovy/org/gradle/groovy/environment/JreJavaHomeGroovyIntegrationTest.groovy
@@ -36,7 +36,7 @@ class JreJavaHomeGroovyIntegrationTest extends AbstractIntegrationSpec {
println "Used JRE: ${jreJavaHome.absolutePath.replace(File.separator, '/')}"
apply plugin:'groovy'
dependencies{
- groovy localGroovy()
+ compile localGroovy()
}
compileGroovy{
options.fork = ${forkMode}
@@ -50,8 +50,10 @@ class JreJavaHomeGroovyIntegrationTest extends AbstractIntegrationSpec {
file("build/classes/main/org/test/GroovyClazz.class").exists()
where:
- forkMode << [false, true, false]
- useAnt << [false, false, true]
+ forkMode | useAnt
+ false | false
+ false | true
+ true | false
}
@Requires(TestPrecondition.WINDOWS)
@@ -62,28 +64,29 @@ class JreJavaHomeGroovyIntegrationTest extends AbstractIntegrationSpec {
writeGroovyTestSource("src/main/groovy")
file('build.gradle') << """
apply plugin:'groovy'
- dependencies{
- groovy localGroovy()
+ dependencies {
+ compile localGroovy()
}
- compileGroovy{
+ compileGroovy {
options.fork = ${forkMode}
- DeprecationLogger.whileDisabled {
- options.useAnt = ${useAnt}
- groovyOptions.useAnt = ${useAnt}
- }
+ options.useAnt = ${useAnt}
+ groovyOptions.useAnt = ${useAnt}
}
"""
when:
def envVars = System.getenv().findAll { !(it.key in ['GRADLE_OPTS', 'JAVA_HOME', 'Path']) }
envVars.put("Path", "C:\\Windows\\System32")
- executer.withEnvironmentVars(envVars).withTasks("compileGroovy").run()
+ executer.withEnvironmentVars(envVars).withDeprecationChecksDisabled().withTasks("compileGroovy").run()
then:
file("build/classes/main/org/test/JavaClazz.class").exists()
file("build/classes/main/org/test/GroovyClazz.class").exists()
+
where:
- forkMode << [false, true, false]
- useAnt << [false, false, true]
+ forkMode | useAnt
+ false | false
+ false | true
+ true | false
}
private writeJavaTestSource(String srcDir, String clazzName = "JavaClazz") {
diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaPluginGoodBehaviourTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaPluginGoodBehaviourTest.groovy
index e004f1f..cad2d31 100644
--- a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaPluginGoodBehaviourTest.groovy
+++ b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaPluginGoodBehaviourTest.groovy
@@ -16,10 +16,32 @@
package org.gradle.java
import org.gradle.integtests.fixtures.WellBehavedPluginTest
+import spock.lang.Issue
class JavaPluginGoodBehaviourTest extends WellBehavedPluginTest {
@Override
String getMainTask() {
return "build"
}
+
+ @Issue("http://issues.gradle.org/browse/GRADLE-2851")
+ def "changing debug flag does not produce deprecation warning"() {
+ // We are testing here that Groovy prefers the is*() variant over the get one.
+ // If it prefers the get one we'll get a deprecation warning
+ given:
+ applyPlugin()
+
+ when:
+ buildFile << """
+ compileJava {
+ configure(options) {
+ def value = debug
+ value = failOnError
+ }
+ }
+ """
+
+ then:
+ succeeds "tasks"
+ }
}
\ No newline at end of file
diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/java/environment/JreJavaHomeJavaIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/java/environment/JreJavaHomeJavaIntegrationTest.groovy
index 7b5dba7..efe9017 100644
--- a/subprojects/plugins/src/integTest/groovy/org/gradle/java/environment/JreJavaHomeJavaIntegrationTest.groovy
+++ b/subprojects/plugins/src/integTest/groovy/org/gradle/java/environment/JreJavaHomeJavaIntegrationTest.groovy
@@ -25,7 +25,7 @@ import spock.lang.Unroll
class JreJavaHomeJavaIntegrationTest extends AbstractIntegrationSpec {
- @IgnoreIf({ AvailableJavaHomes.bestJre == null})
+ @IgnoreIf({ AvailableJavaHomes.bestJre == null })
@Unroll
def "java compilation works in forking mode = #forkMode and useAnt = #useAnt when JAVA_HOME is set to JRE"() {
given:
@@ -34,19 +34,21 @@ class JreJavaHomeJavaIntegrationTest extends AbstractIntegrationSpec {
file('build.gradle') << """
println "Used JRE: ${jreJavaHome.absolutePath.replace(File.separator, '/')}"
apply plugin:'java'
- compileJava{
+ compileJava {
options.fork = ${forkMode}
- DeprecationLogger.whileDisabled { options.useAnt = ${useAnt} }
+ options.useAnt = ${useAnt}
}
"""
when:
- executer.withEnvironmentVars("JAVA_HOME": jreJavaHome.absolutePath).withTasks("compileJava").run().output
+ executer.withEnvironmentVars("JAVA_HOME": jreJavaHome.absolutePath).withDeprecationChecksDisabled().withTasks("compileJava").run().output
then:
file("build/classes/main/org/test/JavaClazz.class").exists()
where:
- forkMode << [false, true, false]
- useAnt << [false, false, true]
+ forkMode | useAnt
+ false | false
+ false | true
+ true | false
}
@Requires(TestPrecondition.WINDOWS)
@@ -55,21 +57,23 @@ class JreJavaHomeJavaIntegrationTest extends AbstractIntegrationSpec {
given:
writeJavaTestSource("src/main/java");
file('build.gradle') << """
- apply plugin:'java'
- compileJava{
- options.fork = ${forkMode}
- DeprecationLogger.whileDisabled { options.useAnt = ${useAnt} }
+ apply plugin:'java'
+ compileJava {
+ options.fork = ${forkMode}
+ options.useAnt = ${useAnt}
}
"""
def envVars = System.getenv().findAll { !(it.key in ['GRADLE_OPTS', 'JAVA_HOME', 'Path']) }
envVars.put("Path", "C:\\Windows\\System32")
when:
- executer.withEnvironmentVars(envVars).withTasks("compileJava").run()
+ executer.withEnvironmentVars(envVars).withDeprecationChecksDisabled().withTasks("compileJava").run()
then:
file("build/classes/main/org/test/JavaClazz.class").exists()
where:
- forkMode << [false, true, false]
- useAnt << [false, false, true]
+ forkMode | useAnt
+ false | false
+ false | true
+ true | false
}
private writeJavaTestSource(String srcDir) {
diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/testing/IncrementalTestIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/testing/IncrementalTestIntegrationTest.groovy
new file mode 100644
index 0000000..eaf938b
--- /dev/null
+++ b/subprojects/plugins/src/integTest/groovy/org/gradle/testing/IncrementalTestIntegrationTest.groovy
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.testing
+
+import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+import org.gradle.integtests.fixtures.JUnitXmlTestExecutionResult
+import org.gradle.integtests.fixtures.TestResources
+import org.junit.Rule
+
+class IncrementalTestIntegrationTest extends AbstractIntegrationSpec {
+
+ @Rule public final TestResources resources = new TestResources(temporaryFolder)
+
+ def setup() {
+ executer.noExtraLogging()
+ }
+
+ def doesNotRunStaleTests() {
+ given:
+ fails('test').assertTestsFailed()
+
+ file('src/test/java/Broken.java').assertIsFile().delete()
+
+ expect:
+ succeeds('test')
+ }
+
+ def executesTestsWhenSourceChanges() {
+ given:
+ succeeds('test')
+
+ when:
+ // Change a production class
+ file('src/main/java/MainClass.java').assertIsFile().copyFrom(file('NewMainClass.java'))
+
+ then:
+ succeeds('test').assertTasksNotSkipped(':compileJava', ':classes', ':compileTestJava', ':testClasses', ':test')
+ succeeds('test').assertTasksNotSkipped()
+
+ when:
+ // Change a test class
+ file('src/test/java/Ok.java').assertIsFile().copyFrom(file('NewOk.java'))
+
+ then:
+ succeeds('test').assertTasksNotSkipped(':compileTestJava', ':testClasses', ':test')
+ succeeds('test').assertTasksNotSkipped()
+ }
+
+ def executesTestsWhenTestFrameworkChanges() {
+ given:
+ succeeds('test')
+
+ def result = new JUnitXmlTestExecutionResult(testDirectory)
+ result.assertTestClassesExecuted('JUnitTest')
+
+ when:
+ // Switch test framework
+ file('build.gradle').append 'test.useTestNG()\n'
+
+ then:
+ succeeds('test').assertTasksNotSkipped(':test')
+
+ result.assertTestClassesExecuted('TestNGTest', 'JUnitTest') //previous result still present in the dir
+
+ succeeds('test').assertTasksNotSkipped()
+ }
+
+ def "test up-to-date status respects test name patterns"() {
+ file("src/test/java/FooTest.java") << """
+import org.junit.*;
+public class FooTest {
+ @Test public void test() {}
+}
+"""
+ file("src/test/java/BarTest.java") << """
+import org.junit.*;
+public class BarTest {
+ @Test public void test() {}
+}
+"""
+
+ file("build.gradle") << """
+ apply plugin: 'java'
+ repositories { mavenCentral() }
+ dependencies { testCompile 'junit:junit:4.10' }
+ test.beforeTest { println "executed " + it }
+ """
+
+ when:
+ def result = executer.withTasks("test", "-Dtest.single=Foo").run()
+
+ then:
+ //asserting on output because test results are kept in between invocations
+ !result.output.contains("executed test test(BarTest)")
+ result.output.contains("executed test test(FooTest)")
+
+ when:
+ result = executer.withTasks("test", "-Dtest.single=Bar").run()
+
+ then:
+ result.output.contains("executed test test(BarTest)")
+ !result.output.contains("executed test test(FooTest)")
+
+ when:
+ result = executer.withTasks("test", "-Dtest.single=Bar").run()
+
+ then:
+ result.assertTaskSkipped(":test")
+ }
+}
diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/testing/TestReportIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/testing/TestReportIntegrationTest.groovy
index 7216d7e..3ab6030 100644
--- a/subprojects/plugins/src/integTest/groovy/org/gradle/testing/TestReportIntegrationTest.groovy
+++ b/subprojects/plugins/src/integTest/groovy/org/gradle/testing/TestReportIntegrationTest.groovy
@@ -16,14 +16,12 @@
package org.gradle.testing
-import org.gradle.integtests.fixtures.AbstractIntegrationSpec
-import org.gradle.integtests.fixtures.HtmlTestExecutionResult
-import org.gradle.integtests.fixtures.Sample
-import org.gradle.integtests.fixtures.UsesSample
+import org.gradle.integtests.fixtures.*
import org.junit.Rule
+import spock.lang.Issue
+import spock.lang.Unroll
-import static org.hamcrest.Matchers.contains
-import static org.hamcrest.Matchers.equalTo
+import static org.hamcrest.Matchers.*
class TestReportIntegrationTest extends AbstractIntegrationSpec {
@Rule Sample sample = new Sample(temporaryFolder)
@@ -31,9 +29,7 @@ class TestReportIntegrationTest extends AbstractIntegrationSpec {
def "report includes results of each invocation"() {
given:
buildFile << """
-apply plugin: 'java'
-repositories { mavenCentral() }
-dependencies { testCompile 'junit:junit:4.11' }
+$junitSetup
test { systemProperty 'LogLessStuff', System.getProperty('LogLessStuff') }
"""
@@ -83,4 +79,241 @@ public class LoggingTest {
htmlReport.testClass("org.gradle.sample.CoreTest").assertTestCount(1, 0, 0).assertTestPassed("ok").assertStdout(contains("hello from CoreTest."))
htmlReport.testClass("org.gradle.sample.UtilTest").assertTestCount(1, 0, 0).assertTestPassed("ok").assertStdout(contains("hello from UtilTest."))
}
+
+ @Issue("http://issues.gradle.org//browse/GRADLE-2821")
+ def "test report task can handle test tasks that did not run tests"() {
+ given:
+ buildScript """
+ apply plugin: 'java'
+
+ $junitSetup
+
+ task otherTests(type: Test) {
+ binResultsDir file("bin")
+ testSrcDirs = []
+ testClassesDir = file("blah")
+ }
+
+ task testReport(type: TestReport) {
+ reportOn test, otherTests
+ destinationDir reporting.file("tr")
+ }
+ """
+
+ and:
+ testClass("Thing")
+
+ when:
+ succeeds "testReport"
+
+ then:
+ ":otherTests" in skippedTasks
+ ":test" in nonSkippedTasks
+ new HtmlTestExecutionResult(testDirectory, "tr").assertTestClassesExecuted("Thing")
+ }
+
+ def "test report task is skipped when there are no results"() {
+ given:
+ buildScript """
+ apply plugin: 'java'
+
+ task testReport(type: TestReport) {
+ reportOn test
+ destinationDir reporting.file("tr")
+ }
+ """
+
+ when:
+ succeeds "testReport"
+
+ then:
+ ":test" in skippedTasks
+ ":testReport" in skippedTasks
+ }
+
+ @Unroll
+ "#type report files are considered outputs"() {
+ given:
+ buildScript """
+ $junitSetup
+ """
+
+ and:
+ testClass "SomeTest"
+
+ when:
+ run "test"
+
+ then:
+ ":test" in nonSkippedTasks
+ file(reportsDir).exists()
+
+ when:
+ run "test"
+
+ then:
+ ":test" in skippedTasks
+ file(reportsDir).exists()
+
+ when:
+ file(reportsDir).deleteDir()
+ run "test"
+
+ then:
+ ":test" in nonSkippedTasks
+ file(reportsDir).exists()
+
+ where:
+ type | reportsDir
+ "xml" | "build/test-results"
+ "html" | "build/reports/tests"
+ }
+
+ def "results or reports are linked to in error output"() {
+ given:
+ buildScript """
+ $junitSetup
+ test {
+ reports.all { it.enabled = true }
+ }
+ """
+
+ and:
+ failingTestClass "SomeTest"
+
+ when:
+ fails "test"
+
+ then:
+ ":test" in nonSkippedTasks
+ errorOutput.contains("See the report at: ")
+
+ when:
+ buildFile << "\ntest.reports.html.enabled = false\n"
+ fails "test"
+
+ then:
+ ":test" in nonSkippedTasks
+ errorOutput.contains("See the results at: ")
+
+ when:
+ buildFile << "\ntest.reports.junitXml.enabled = false\n"
+ fails "test"
+
+ then:
+ ":test" in nonSkippedTasks
+ errorOutput.contains("There were failing tests")
+ !errorOutput.contains("See the")
+ }
+
+
+ def "output per test case flag invalidates outputs"() {
+ when:
+ buildScript """
+ $junitSetup
+ test.reports.junitXml.outputPerTestCase = false
+ """
+ testClass "SomeTest"
+ succeeds "test"
+
+ then:
+ ":test" in nonSkippedTasks
+
+ when:
+ buildFile << "\ntest.reports.junitXml.outputPerTestCase = true\n"
+ succeeds "test"
+
+ then:
+ ":test" in nonSkippedTasks
+ }
+
+ def "outputs over lifecycle"() {
+ when:
+ buildScript """
+ $junitSetup
+ test.reports.junitXml.outputPerTestCase = true
+ """
+
+ file("src/test/java/OutputLifecycleTest.java") << """
+ import org.junit.*;
+
+ public class OutputLifecycleTest {
+
+ public OutputLifecycleTest() {
+ System.out.println("constructor out");
+ System.err.println("constructor err");
+ }
+
+ @BeforeClass
+ public static void beforeClass() {
+ System.out.println("beforeClass out");
+ System.err.println("beforeClass err");
+ }
+
+ @Before
+ public void beforeTest() {
+ System.out.println("beforeTest out");
+ System.err.println("beforeTest err");
+ }
+
+ @Test public void m1() {
+ System.out.println("m1 out");
+ System.err.println("m1 err");
+ }
+
+ @Test public void m2() {
+ System.out.println("m2 out");
+ System.err.println("m2 err");
+ }
+
+ @After
+ public void afterTest() {
+ System.out.println("afterTest out");
+ System.err.println("afterTest err");
+ }
+
+ @AfterClass
+ public static void afterClass() {
+ System.out.println("afterClass out");
+ System.err.println("afterClass err");
+ }
+ }
+ """
+
+ succeeds "test"
+
+ then:
+ def xmlReport = new JUnitXmlTestExecutionResult(testDirectory)
+ def clazz = xmlReport.testClass("OutputLifecycleTest")
+ clazz.assertTestCaseStderr("m1", is("beforeTest err\nm1 err\nafterTest err\n"))
+ clazz.assertTestCaseStderr("m2", is("beforeTest err\nm2 err\nafterTest err\n"))
+ clazz.assertTestCaseStdout("m1", is("beforeTest out\nm1 out\nafterTest out\n"))
+ clazz.assertTestCaseStdout("m2", is("beforeTest out\nm2 out\nafterTest out\n"))
+ clazz.assertStderr(is("beforeClass err\nconstructor err\nconstructor err\nafterClass err\n"))
+ clazz.assertStdout(is("beforeClass out\nconstructor out\nconstructor out\nafterClass out\n"))
+ }
+
+ String getJunitSetup() {
+ """
+ apply plugin: 'java'
+ repositories { mavenCentral() }
+ dependencies { testCompile 'junit:junit:4.11' }
+ """
+ }
+
+ void failingTestClass(String name) {
+ testClass(name, true)
+ }
+
+ void testClass(String name, boolean failing = false) {
+ file("src/test/java/${name}.java") << """
+ public class $name {
+ @org.junit.Test
+ public void test() {
+ assert false == ${failing};
+ }
+ }
+ """
+ }
+
}
diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/testing/TestTaskIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/testing/TestTaskIntegrationTest.groovy
new file mode 100644
index 0000000..4bcec9f
--- /dev/null
+++ b/subprojects/plugins/src/integTest/groovy/org/gradle/testing/TestTaskIntegrationTest.groovy
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.testing;
+
+import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+import spock.lang.Issue;
+
+public class TestTaskIntegrationTest extends AbstractIntegrationSpec {
+
+ @Issue("GRADLE-2702")
+ def "should not resolve configurations when there are no tests"() {
+ buildFile << """
+ apply plugin: 'java'
+
+ configure([configurations.testRuntime, configurations.testCompile]) {
+ incoming.beforeResolve { assert false : "should not be resolved" }
+ }
+ """
+
+ when:
+ run("build")
+
+ then:
+ noExceptionThrown()
+ }
+
+ def "test task is skipped when there are no tests"() {
+ buildFile << "apply plugin: 'java'"
+ file("src/test/java/not_a_test.txt")
+
+ when:
+ run("build")
+
+ then:
+ result.assertTaskSkipped(":test")
+ }
+}
diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/testing/TestingIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/testing/TestingIntegrationTest.groovy
index b32c75c..2f4a784 100644
--- a/subprojects/plugins/src/integTest/groovy/org/gradle/testing/TestingIntegrationTest.groovy
+++ b/subprojects/plugins/src/integTest/groovy/org/gradle/testing/TestingIntegrationTest.groovy
@@ -15,8 +15,11 @@
*/
package org.gradle.testing
+import org.apache.commons.lang.RandomStringUtils
import org.gradle.integtests.fixtures.AbstractIntegrationSpec
import org.gradle.integtests.fixtures.JUnitXmlTestExecutionResult
+import org.gradle.internal.os.OperatingSystem
+import spock.lang.IgnoreIf
import spock.lang.Issue
import spock.lang.Timeout
import spock.lang.Unroll
@@ -54,6 +57,37 @@ class TestingIntegrationTest extends AbstractIntegrationSpec {
":test" in nonSkippedTasks
}
+ @IgnoreIf({ OperatingSystem.current().isWindows() })
+ def "can use long paths for working directory"() {
+ given:
+ // windows can handle a path up to 260 characters
+ // we create a path that is 260 +1 (offset + "/" + randompath)
+ def pathoffset = 260 - testDirectory.getAbsolutePath().length()
+ def alphanumeric = RandomStringUtils.randomAlphanumeric(pathoffset)
+ def testWorkingDir = testDirectory.createDir("$alphanumeric")
+
+ buildFile << """
+ apply plugin: 'java'
+ repositories { mavenCentral() }
+ dependencies { testCompile "junit:junit:4.11" }
+ test.workingDir = "${testWorkingDir.toURI()}"
+ """
+
+ and:
+ file("src/test/java/SomeTest.java") << """
+ import org.junit.*;
+
+ public class SomeTest {
+ @Test public void foo() {
+ System.out.println(new java.io.File(".").getAbsolutePath());
+ }
+ }
+ """
+
+ expect:
+ succeeds "test"
+ }
+
@Issue("http://issues.gradle.org/browse/GRADLE-2313")
@Unroll
"can clean test after extracting class file with #framework"() {
diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/testing/junit/JUnitAssumptionsIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/testing/junit/JUnitAssumptionsIntegrationTest.groovy
new file mode 100644
index 0000000..55f956e
--- /dev/null
+++ b/subprojects/plugins/src/integTest/groovy/org/gradle/testing/junit/JUnitAssumptionsIntegrationTest.groovy
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.testing.junit
+
+import org.gradle.integtests.fixtures.DefaultTestExecutionResult
+import org.gradle.integtests.fixtures.MultiVersionIntegrationSpec
+import org.gradle.integtests.fixtures.TargetVersions
+import org.gradle.integtests.fixtures.TestResources
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+
+ at TargetVersions(['4.5', '4.11'])
+public class JUnitAssumptionsIntegrationTest extends MultiVersionIntegrationSpec {
+
+ @Rule
+ public final TestResources resources = new TestResources(temporaryFolder)
+
+ @Before
+ public void before() {
+ executer.noExtraLogging()
+ }
+
+ private void configureJUnit() {
+ buildFile << """
+ dependencies {
+ testCompile 'junit:junit:$version'
+ }"""
+ }
+
+ @Test
+ public void supportsAssumptions() {
+ setup:
+ configureJUnit()
+ when:
+ executer.withTasks('check').run()
+ then:
+ def result = new DefaultTestExecutionResult(testDirectory)
+ result.assertTestClassesExecuted('org.gradle.TestWithAssumptions')
+ result.testClass('org.gradle.TestWithAssumptions')
+ .assertTestCount(2, 0, 0)
+ .assertTestsExecuted('assumptionSucceeded')
+ .assertTestPassed('assumptionSucceeded')
+ .assertTestsSkipped('assumptionFailed')
+ }
+}
diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec.groovy
new file mode 100644
index 0000000..f38759f
--- /dev/null
+++ b/subprojects/plugins/src/integTest/groovy/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec.groovy
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.testing.junit
+
+import org.gradle.integtests.fixtures.DefaultTestExecutionResult
+import org.gradle.integtests.fixtures.MultiVersionIntegrationSpec
+import org.gradle.integtests.fixtures.TargetVersions
+import org.gradle.integtests.fixtures.TestResources
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+
+ at TargetVersions(['4.8', '4.11'])
+public class JUnitCategoriesCrossVersionIntegrationSpec extends MultiVersionIntegrationSpec {
+
+ @Rule
+ public final TestResources resources = new TestResources(temporaryFolder)
+
+ String junitDependency = "junit:junit:$version"
+
+ @Before
+ public void before() {
+ executer.noExtraLogging()
+ }
+
+ private void configureJUnit() {
+ buildFile << """
+ dependencies {
+ testCompile '${junitDependency.toString()}'
+ }"""
+ }
+
+ @Test
+ public void canSpecifyIncludeAndExcludeCategories() {
+ given:
+ configureJUnit();
+ when:
+ executer.withTasks('test').run();
+ then:
+ DefaultTestExecutionResult result = new DefaultTestExecutionResult(testDirectory)
+ result.assertTestClassesExecuted('org.gradle.CatATests', 'org.gradle.CatBTests', 'org.gradle.CatADTests', 'org.gradle.MixedTests')
+ result.testClass("org.gradle.CatATests").assertTestCount(4, 0, 0)
+ result.testClass("org.gradle.CatATests").assertTestsExecuted('catAOk1', 'catAOk2', 'catAOk3', 'catAOk4')
+ result.testClass("org.gradle.CatBTests").assertTestCount(4, 0, 0)
+ result.testClass("org.gradle.CatBTests").assertTestsExecuted('catBOk1', 'catBOk2', 'catBOk3', 'catBOk4')
+ result.testClass("org.gradle.CatADTests").assertTestCount(2, 0, 0)
+ result.testClass("org.gradle.CatADTests").assertTestsExecuted('catAOk1', 'catAOk2')
+ result.testClass("org.gradle.MixedTests").assertTestCount(3, 0, 0)
+ result.testClass("org.gradle.MixedTests").assertTestsExecuted('catAOk1', 'catBOk2')
+ result.testClass("org.gradle.MixedTests").assertTestsSkipped('someIgnoredTest')
+ }
+
+ @Test
+ public void canSpecifyExcludesOnly() {
+ given:
+ configureJUnit();
+ when:
+ executer.withTasks('test').run();
+ then:
+ DefaultTestExecutionResult result = new DefaultTestExecutionResult(testDirectory)
+ result.assertTestClassesExecuted('org.gradle.NoCatTests', 'org.gradle.SomeTests', 'org.gradle.SomeOtherCatTests')
+ result.testClass("org.gradle.SomeOtherCatTests").assertTestCount(2, 0, 0)
+ result.testClass("org.gradle.SomeOtherCatTests").assertTestsExecuted('someOtherOk1', 'someOtherOk2')
+ result.testClass("org.gradle.NoCatTests").assertTestCount(2, 0, 0)
+ result.testClass("org.gradle.NoCatTests").assertTestsExecuted('noCatOk1', 'noCatOk2')
+ result.testClass("org.gradle.SomeTests").assertTestCount(3, 0, 0)
+ result.testClass("org.gradle.SomeTests").assertTestsExecuted('noCatOk3', 'noCatOk4', 'someOtherCatOk2')
+ }
+
+ @Test
+ public void canCombineCategoriesWithCustomRunner() {
+ given:
+ configureJUnit();
+ when:
+ executer.withTasks('test').run();
+ then:
+ DefaultTestExecutionResult result = new DefaultTestExecutionResult(testDirectory)
+ result.assertTestClassesExecuted('org.gradle.SomeLocaleTests')
+ result.testClass("org.gradle.SomeLocaleTests").assertTestCount(3, 0, 0)
+ result.testClass("org.gradle.SomeLocaleTests").assertTestsExecuted('ok1 [de]', 'ok1 [en]', 'ok1 [fr]')
+ }
+}
diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/testing/junit/JUnitCategoriesIntegrationSpec.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/testing/junit/JUnitCategoriesIntegrationSpec.groovy
new file mode 100644
index 0000000..7264851
--- /dev/null
+++ b/subprojects/plugins/src/integTest/groovy/org/gradle/testing/junit/JUnitCategoriesIntegrationSpec.groovy
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.testing.junit
+
+import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+import org.gradle.integtests.fixtures.DefaultTestExecutionResult
+import org.gradle.integtests.fixtures.TestResources
+import org.gradle.integtests.fixtures.executer.ExecutionResult
+import org.gradle.test.fixtures.file.TestFile
+import org.junit.Rule
+import org.junit.Test
+import static org.hamcrest.Matchers.startsWith
+
+
+public class JUnitCategoriesIntegrationSpec extends AbstractIntegrationSpec {
+ @Rule
+ public final TestResources resources = new TestResources(temporaryFolder)
+
+ @Test
+ public void reportsUnloadableExcludeCategory() {
+ given:
+ resources.maybeCopy("JUnitCategoriesIntegrationSpec/reportsUnloadableCategories")
+ TestFile buildFile = testDirectory.file('build.gradle');
+ buildFile << '''test {
+ useJUnit {
+ excludeCategories 'org.gradle.CategoryA'
+ }
+ }
+ '''
+
+ when:
+ executer.withTasks('test').runWithFailure();
+ then:
+ DefaultTestExecutionResult result = new DefaultTestExecutionResult(testDirectory)
+ result.assertTestClassesExecuted('org.gradle.SomeTestClass')
+ result.testClass("org.gradle.SomeTestClass").assertTestCount(1, 1, 0)
+ result.testClass("org.gradle.SomeTestClass").assertTestFailed("initializationError", startsWith("org.gradle.api.InvalidUserDataException: Can't load category class [org.gradle.CategoryA]"))
+ }
+
+ @Test
+ public void reportsUnloadableIncludeCategory() {
+ given:
+ resources.maybeCopy("JUnitCategoriesIntegrationSpec/reportsUnloadableCategories")
+ TestFile buildFile = testDirectory.file('build.gradle');
+ buildFile << '''test {
+ useJUnit {
+ includeCategories 'org.gradle.CategoryA'
+ }
+ }
+ '''
+
+ when:
+ executer.withTasks('test').runWithFailure();
+ then:
+ DefaultTestExecutionResult result = new DefaultTestExecutionResult(testDirectory)
+ result.assertTestClassesExecuted('org.gradle.SomeTestClass')
+ result.testClass("org.gradle.SomeTestClass").assertTestCount(1, 1, 0)
+ result.testClass("org.gradle.SomeTestClass").assertTestFailed("initializationError", startsWith("org.gradle.api.InvalidUserDataException: Can't load category class [org.gradle.CategoryA]"))
+ }
+
+ @Test
+ public void testTaskFailsIfCategoriesNotSupported() {
+ when:
+ ExecutionResult failure = executer.withTasks('test').runWithFailure();
+ then:
+ failure.error.contains("JUnit Categories defined but declared JUnit version does not support Categories.")
+ }
+}
diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/testing/junit/JUnitCrossVersionIntegrationSpec.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/testing/junit/JUnitCrossVersionIntegrationSpec.groovy
index 2a5e8ae..ce849ff 100644
--- a/subprojects/plugins/src/integTest/groovy/org/gradle/testing/junit/JUnitCrossVersionIntegrationSpec.groovy
+++ b/subprojects/plugins/src/integTest/groovy/org/gradle/testing/junit/JUnitCrossVersionIntegrationSpec.groovy
@@ -16,19 +16,18 @@
package org.gradle.testing.junit
-import org.gradle.integtests.fixtures.JUnitXmlTestExecutionResult
+import org.gradle.integtests.fixtures.DefaultTestExecutionResult
import org.gradle.integtests.fixtures.MultiVersionIntegrationSpec
import org.gradle.integtests.fixtures.TargetVersions
import org.gradle.integtests.fixtures.TestResources
import org.junit.Rule
import org.junit.Test
- at TargetVersions(['4,0', '4.4', '4.8.2', '4.11'])
+ at TargetVersions(['4.0', '4.4', '4.8.2', '4.11'])
class JUnitCrossVersionIntegrationSpec extends MultiVersionIntegrationSpec {
@Rule
public final TestResources resources = new TestResources(temporaryFolder)
-
String junitDependency = "junit:junit:$version"
@Test
@@ -41,15 +40,17 @@ class JUnitCrossVersionIntegrationSpec extends MultiVersionIntegrationSpec {
when:
executer.withTasks('check').run()
then:
- def result = new JUnitXmlTestExecutionResult(testDirectory)
- result.assertTestClassesExecuted('org.gradle.Junit3Test', 'org.gradle.Junit4Test', 'org.gradle.IgnoredTest', 'org.gradle.CustomIgnoredTest')
- result.testClass('org.gradle.Junit3Test').assertTestsExecuted('testRenamesItself')
- result.testClass('org.gradle.Junit3Test').assertTestPassed('testRenamesItself')
- result.testClass('org.gradle.Junit4Test').assertTestsExecuted('ok')
- result.testClass('org.gradle.Junit4Test').assertTestPassed('ok')
- result.testClass('org.gradle.Junit4Test').assertTestsSkipped('broken', 'assumptionFailed')
- result.testClass('org.gradle.IgnoredTest').assertTestsSkipped('testIgnored')
- result.testClass('org.gradle.CustomIgnoredTest').assertTestCount(3, 0, 0).assertTestsSkipped("first test run", "second test run", "third test run")
+ def result = new DefaultTestExecutionResult(testDirectory)
+ result.assertTestClassesExecuted('org.gradle.Junit3Test', 'org.gradle.Junit4Test')
+ result.testClass('org.gradle.Junit3Test')
+ .assertTestCount(1, 0, 0)
+ .assertTestsExecuted('testRenamesItself')
+ .assertTestPassed('testRenamesItself')
+ result.testClass('org.gradle.Junit4Test')
+ .assertTestCount(2, 0, 0)
+ .assertTestsExecuted('ok')
+ .assertTestPassed('ok')
+ .assertTestsSkipped('broken')
}
private void configureJUnit() {
diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/testing/junit/JUnitIgnoreClassCrossVersionIntegrationSpec.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/testing/junit/JUnitIgnoreClassCrossVersionIntegrationSpec.groovy
new file mode 100644
index 0000000..79906ae
--- /dev/null
+++ b/subprojects/plugins/src/integTest/groovy/org/gradle/testing/junit/JUnitIgnoreClassCrossVersionIntegrationSpec.groovy
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.testing.junit
+
+import org.gradle.integtests.fixtures.DefaultTestExecutionResult
+import org.gradle.integtests.fixtures.MultiVersionIntegrationSpec
+import org.gradle.integtests.fixtures.TargetVersions
+import org.gradle.integtests.fixtures.TestResources
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+
+
+ at TargetVersions(['4.4', '4.8.2', '4.11'])
+class JUnitIgnoreClassCrossVersionIntegrationSpec extends MultiVersionIntegrationSpec {
+
+ @Rule
+ public final TestResources resources = new TestResources(temporaryFolder)
+
+ String junitDependency = "junit:junit:$version"
+
+ @Before
+ public void before() {
+ executer.noExtraLogging()
+ configureJUnit()
+ }
+
+ private void configureJUnit() {
+ buildFile << """
+ dependencies {
+ testCompile '${junitDependency.toString()}'
+ }"""
+ }
+
+ @Test
+ public void canHandleClassLevelIgnoredTests() {
+ resources.maybeCopy('JUnitIntegrationTest/ignoreTests')
+ executer.withTasks('check').run()
+ def result = new DefaultTestExecutionResult(testDirectory)
+ result.assertTestClassesExecuted('org.gradle.IgnoredTest', 'org.gradle.CustomIgnoredTest')
+ result.testClass('org.gradle.IgnoredTest').assertTestCount(1, 0, 0).assertTestsSkipped("testIgnored")
+ result.testClass('org.gradle.CustomIgnoredTest').assertTestCount(3, 0, 0).assertTestsSkipped("first test run", "second test run", "third test run")
+ }
+}
diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/testing/junit/JUnitIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/testing/junit/JUnitIntegrationTest.groovy
index 698e91d..7a52941 100755
--- a/subprojects/plugins/src/integTest/groovy/org/gradle/testing/junit/JUnitIntegrationTest.groovy
+++ b/subprojects/plugins/src/integTest/groovy/org/gradle/testing/junit/JUnitIntegrationTest.groovy
@@ -97,26 +97,7 @@ public class JUnitIntegrationTest extends AbstractIntegrationTest {
result.testClass("org.gradle.SomeTest").assertTestsExecuted("ok", "ok")
}
- @Test
- public void canRunMixOfJunit3And4Tests() {
- resources.maybeCopy('JUnitIntegrationTest/junit3Tests')
- resources.maybeCopy('JUnitIntegrationTest/junit4Tests')
- executer.withTasks('check').run()
- def result = new DefaultTestExecutionResult(testDirectory)
- result.assertTestClassesExecuted('org.gradle.Junit3Test', 'org.gradle.Junit4Test', 'org.gradle.IgnoredTest', 'org.gradle.CustomIgnoredTest')
- result.testClass('org.gradle.Junit3Test')
- .assertTestCount(1, 0, 0)
- .assertTestsExecuted('testRenamesItself')
- .assertTestPassed('testRenamesItself')
- result.testClass('org.gradle.Junit4Test')
- .assertTestCount(3, 0, 0)
- .assertTestsExecuted('ok')
- .assertTestPassed('ok')
- .assertTestsSkipped('broken', 'assumptionFailed')
- result.testClass('org.gradle.IgnoredTest').assertTestCount(1, 0, 0).assertTestsSkipped("testIgnored")
- result.testClass('org.gradle.CustomIgnoredTest').assertTestCount(3, 0, 0).assertTestsSkipped("first test run", "second test run", "third test run")
- }
@Test
public void canRunTestsUsingJUnit3() {
@@ -467,4 +448,6 @@ public class JUnitIntegrationTest extends AbstractIntegrationTest {
result.testClass("org.gradle.SomeSuite").assertStderr(containsString("stderr in TestSetup#setup"))
result.testClass("org.gradle.SomeSuite").assertStderr(containsString("stderr in TestSetup#teardown"))
}
+
+
}
diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/testing/testng/SampleTestNGIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/testing/testng/SampleTestNGIntegrationTest.groovy
index 2d40e17..621bfae 100644
--- a/subprojects/plugins/src/integTest/groovy/org/gradle/testing/testng/SampleTestNGIntegrationTest.groovy
+++ b/subprojects/plugins/src/integTest/groovy/org/gradle/testing/testng/SampleTestNGIntegrationTest.groovy
@@ -19,9 +19,6 @@ import org.gradle.integtests.fixtures.*
import org.junit.Rule
import org.junit.Test
-/**
- * @author Tom Eyckmans
- */
public class SampleTestNGIntegrationTest extends AbstractIntegrationTest {
@Rule public final Sample sample = new Sample(testDirectoryProvider)
diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/testing/testng/TestNGIntegrationProject.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/testing/testng/TestNGIntegrationProject.groovy
deleted file mode 100644
index e9d9a53..0000000
--- a/subprojects/plugins/src/integTest/groovy/org/gradle/testing/testng/TestNGIntegrationProject.groovy
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.testing.testng
-
-import org.gradle.integtests.fixtures.TestNGExecutionResult
-
-/**
- * @author Tom Eyckmans
- */
-
-public class TestNGIntegrationProject {
- String name
- boolean expectFailure
- Closure assertClosure
-
- static TestNGIntegrationProject failingIntegrationProject(String language, String jdk, assertClosure)
- {
- new TestNGIntegrationProject(language + "-" + jdk + "-failing", true, null, assertClosure)
- }
-
- static TestNGIntegrationProject failingIntegrationProject(String language, String jdk, String nameSuffix, assertClosure)
- {
- new TestNGIntegrationProject(language + "-" + jdk + "-failing", true, nameSuffix, assertClosure)
- }
-
- static TestNGIntegrationProject passingIntegrationProject(String language, String jdk, assertClosure)
- {
- new TestNGIntegrationProject(language + "-" + jdk + "-passing", false, null, assertClosure)
- }
-
- static TestNGIntegrationProject passingIntegrationProject(String language, String jdk, String nameSuffix, assertClosure)
- {
- new TestNGIntegrationProject(language + "-" + jdk + "-passing", false, nameSuffix, assertClosure)
- }
-
- public TestNGIntegrationProject(String name, boolean expectFailure, String nameSuffix, assertClosure)
- {
- if ( nameSuffix == null ) {
- this.name = name
- } else {
- this.name = name + nameSuffix
- }
- this.expectFailure = expectFailure
- this.assertClosure = assertClosure
- }
-
- void doAssert(projectDir, result) {
- if (assertClosure.maximumNumberOfParameters == 3) {
- assertClosure(name, projectDir, new TestNGExecutionResult(projectDir))
- } else {
- assertClosure(name, projectDir, new TestNGExecutionResult(projectDir), result)
- }
- }
-}
\ No newline at end of file
diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/testing/testng/TestNGIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/testing/testng/TestNGIntegrationTest.groovy
index 5b315f7..1d0f8fc 100644
--- a/subprojects/plugins/src/integTest/groovy/org/gradle/testing/testng/TestNGIntegrationTest.groovy
+++ b/subprojects/plugins/src/integTest/groovy/org/gradle/testing/testng/TestNGIntegrationTest.groovy
@@ -29,9 +29,6 @@ import static org.gradle.util.Matchers.containsLine
import static org.hamcrest.Matchers.*
import static org.junit.Assert.assertThat
-/**
- * @author Tom Eyckmans
- */
class TestNGIntegrationTest extends AbstractIntegrationTest {
@Rule public TestResources resources = new TestResources(testDirectoryProvider)
diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/testing/testng/TestNGLoggingIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/testing/testng/TestNGLoggingIntegrationTest.groovy
index 10246a1..4eee33c 100644
--- a/subprojects/plugins/src/integTest/groovy/org/gradle/testing/testng/TestNGLoggingIntegrationTest.groovy
+++ b/subprojects/plugins/src/integTest/groovy/org/gradle/testing/testng/TestNGLoggingIntegrationTest.groovy
@@ -17,19 +17,70 @@
package org.gradle.testing.testng
import org.gradle.integtests.fixtures.AbstractIntegrationSpec
-import org.gradle.integtests.fixtures.TestResources
-import org.gradle.integtests.fixtures.executer.ExecutionResult
import org.gradle.util.TextUtil
-import org.junit.Rule
// can make assumptions about order in which test methods of TestNGTest get executed
// because the methods are chained with 'methodDependsOn'
class TestNGLoggingIntegrationTest extends AbstractIntegrationSpec {
- @Rule TestResources resources = new TestResources(temporaryFolder)
- ExecutionResult result
def setup() {
executer.noExtraLogging().withStackTraceChecksDisabled().withTasks("test")
+
+ buildFile << """
+ apply plugin: "groovy"
+
+ repositories {
+ mavenCentral()
+ }
+
+ dependencies {
+ compile "org.codehaus.groovy:groovy-all:2.0.5"
+ testCompile "org.testng:testng:6.3.1"
+ }
+
+ test {
+ useTestNG()
+ testLogging {
+ quiet {
+ events "skipped", "failed"
+ minGranularity 2
+ maxGranularity -1
+ displayGranularity 3
+ exceptionFormat "full"
+ stackTraceFilters "truncate", "groovy"
+ }
+ }
+ }
+ """
+
+ file("src/test/groovy/org/gradle/TestNGTest.groovy") << """
+ package org.gradle
+
+ import org.testng.annotations.Test
+
+ class TestNGTest {
+ @Test
+ void goodTest() {}
+
+ @Test(dependsOnMethods = ["goodTest"])
+ void badTest() {
+ beBad()
+ }
+
+ @Test(dependsOnMethods = ["badTest"])
+ void ignoredTest() {}
+
+ @Test(dependsOnMethods = ["goodTest"])
+ void printTest() {
+ println "line 1\\nline 2"
+ println "line 3"
+ }
+
+ private beBad() {
+ throw new RuntimeException("bad")
+ }
+ }
+ """
}
def "defaultLifecycleLogging"() {
@@ -39,7 +90,7 @@ class TestNGLoggingIntegrationTest extends AbstractIntegrationSpec {
then:
outputContains("""
Gradle test > org.gradle.TestNGTest.badTest FAILED
- java.lang.RuntimeException at TestNGTest.groovy:40
+ java.lang.RuntimeException at TestNGTest.groovy:25
""")
}
@@ -51,8 +102,8 @@ Gradle test > org.gradle.TestNGTest.badTest FAILED
outputContains("""
org.gradle.TestNGTest.badTest FAILED
java.lang.RuntimeException: bad
- at org.gradle.TestNGTest.beBad(TestNGTest.groovy:40)
- at org.gradle.TestNGTest.badTest(TestNGTest.groovy:27)
+ at org.gradle.TestNGTest.beBad(TestNGTest.groovy:25)
+ at org.gradle.TestNGTest.badTest(TestNGTest.groovy:12)
org.gradle.TestNGTest.ignoredTest SKIPPED
@@ -61,6 +112,44 @@ Gradle test FAILED
}
def "standardOutputLogging"() {
+ given:
+ buildFile.text = """
+ apply plugin: "groovy"
+
+ repositories {
+ mavenCentral()
+ }
+
+ dependencies {
+ compile "org.codehaus.groovy:groovy-all:2.0.5"
+ testCompile "org.testng:testng:6.3.1"
+ }
+
+ test {
+ useTestNG()
+ testLogging {
+ quiet {
+ events "standardOut", "standardError"
+ }
+ }
+ }
+ """
+
+ and:
+ file("src/test/groovy/org/gradle/TestNGStandardOutputTest.groovy") << """
+ package org.gradle
+
+ import org.testng.annotations.Test
+
+ class TestNGStandardOutputTest {
+ @Test
+ void printTest() {
+ println "line 1\\nline 2"
+ println "line 3"
+ }
+ }
+ """
+
when:
result = executer.withArguments("-q").runWithFailure()
@@ -76,4 +165,6 @@ Gradle test > org.gradle.TestNGStandardOutputTest.printTest STANDARD_OUT
private void outputContains(String text) {
assert result.output.contains(TextUtil.toPlatformLineSeparators(text.trim()))
}
+
+
}
diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/testing/testng/TestNGProducesOldReportsIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/testing/testng/TestNGProducesOldReportsIntegrationTest.groovy
index dcd8ee0..f278e27 100644
--- a/subprojects/plugins/src/integTest/groovy/org/gradle/testing/testng/TestNGProducesOldReportsIntegrationTest.groovy
+++ b/subprojects/plugins/src/integTest/groovy/org/gradle/testing/testng/TestNGProducesOldReportsIntegrationTest.groovy
@@ -50,7 +50,7 @@ repositories { mavenCentral() }
dependencies { testCompile 'org.testng:testng:6.3.1' }
test {
- testReport = false
+ reports.html.enabled = false
useTestNG()
}
"""
@@ -77,7 +77,7 @@ apply plugin: 'java'
repositories { mavenCentral() }
dependencies { testCompile 'org.testng:testng:6.3.1' }
test {
- testReport = false
+ reports.html.enabled = false
useTestNG(){
useDefaultListeners = true
}
diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/testing/testng/TestNGXmlResultAndHtmlReportIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/testing/testng/TestNGXmlResultAndHtmlReportIntegrationTest.groovy
index 28e1974..04ebfc5 100644
--- a/subprojects/plugins/src/integTest/groovy/org/gradle/testing/testng/TestNGXmlResultAndHtmlReportIntegrationTest.groovy
+++ b/subprojects/plugins/src/integTest/groovy/org/gradle/testing/testng/TestNGXmlResultAndHtmlReportIntegrationTest.groovy
@@ -17,48 +17,75 @@
package org.gradle.testing.testng
-import org.gradle.integtests.fixtures.AbstractIntegrationSpec
-import org.gradle.integtests.fixtures.HtmlTestExecutionResult
-import org.gradle.integtests.fixtures.JUnitXmlTestExecutionResult
-import org.gradle.integtests.fixtures.TestExecutionResult
+import org.gradle.integtests.fixtures.*
+import spock.lang.Shared
+import spock.lang.Unroll
+import static org.gradle.integtests.fixtures.TestResultOutputAssociation.WITH_SUITE
+import static org.gradle.integtests.fixtures.TestResultOutputAssociation.WITH_TESTCASE
import static org.hamcrest.Matchers.*
+ at Unroll
public class TestNGXmlResultAndHtmlReportIntegrationTest extends
AbstractIntegrationSpec {
+ static class Mode {
+ String name
+ TestResultOutputAssociation outputAssociation
+ String config
+ }
+
+ @Shared Mode outputPerTestCase = new Mode(name: "output-per-testcase", outputAssociation: WITH_TESTCASE, config: "reports.junitXml.outputPerTestCase true")
+ @Shared Mode outputAtSuite = new Mode(name: "output-at-suite", outputAssociation: WITH_SUITE, config: "reports.junitXml.outputPerTestCase false")
+
+ @Shared List<Mode> modes = [outputAtSuite, outputPerTestCase]
+
def setup() {
executer.noExtraLogging()
setupTestCases()
}
- def "produces JUnit xml results"() {
+ def "produces JUnit xml results - #mode.name"() {
when:
- runWithTestConfig("useTestNG()")
+ runWithTestConfig("useTestNG(); $mode.config")
+
then:
- verifyTestResultWith(new JUnitXmlTestExecutionResult(file(".")))
- verifyTestResultWith(new HtmlTestExecutionResult(file(".")))
+ verify(mode)
+
+ where:
+ mode << modes
}
- def "produces JUnit xml results when running tests in parallel"() {
+ def "produces JUnit xml results when running tests in parallel - #mode.name"() {
when:
- runWithTestConfig("useTestNG(); maxParallelForks 2")
+ runWithTestConfig("useTestNG(); maxParallelForks 2; $mode.config")
+
then:
- verifyTestResultWith(new JUnitXmlTestExecutionResult(file(".")))
- verifyTestResultWith(new HtmlTestExecutionResult(file(".")))
+ verify(mode)
+
+ where:
+ mode << modes
}
- def "produces JUnit xml results with aggressive forking"() {
+ def "produces JUnit xml results with aggressive forking - #mode.name"() {
when:
- runWithTestConfig("useTestNG(); forkEvery 1")
+ runWithTestConfig("useTestNG(); forkEvery 1; $mode.config")
+
then:
- verifyTestResultWith(new JUnitXmlTestExecutionResult(file(".")))
- verifyTestResultWith(new HtmlTestExecutionResult(file(".")))
+ verify(mode)
+
+ where:
+ mode << modes
+ }
+
+ void verify(Mode mode) {
+ verifyTestResultWith(new JUnitXmlTestExecutionResult(file("."), mode.outputAssociation), mode.outputAssociation)
+ verifyTestResultWith(new HtmlTestExecutionResult(file(".")), mode.outputAssociation)
}
def runWithTestConfig(String testConfiguration) {
def buildFile = file('build.gradle')
- buildFile << """
+ buildFile.text = """
apply plugin: 'java'
repositories { mavenCentral() }
dependencies { testCompile 'org.testng:testng:6.3.1' }
@@ -71,10 +98,10 @@ public class TestNGXmlResultAndHtmlReportIntegrationTest extends
executer.withTasks('test').runWithFailure().assertTestsFailed()
}
- def verifyTestResultWith(TestExecutionResult executionResult) {
- executionResult.assertTestClassesExecuted("org.FailingTest", "org.PassingTest", "org.MixedMethodsTest", "org.NoOutputsTest", "org.EncodingTest")
+ def verifyTestResultWith(TestExecutionResult executionResult, TestResultOutputAssociation outputAssociation) {
+ executionResult.assertTestClassesExecuted("org.FailingTest", "org.PassingTest", "org.MixedMethodsTest", "org.NoOutputsTest", "org.EncodingTest", "org.ParameterizedTest", "org.OutputLifecycleTest")
- executionResult.testClass("org.MixedMethodsTest")
+ def mixedMethods = executionResult.testClass("org.MixedMethodsTest")
.assertTestCount(4, 2, 0)
.assertTestsExecuted("passing", "passing2", "failing", "failing2")
.assertTestFailed("failing", equalTo('java.lang.AssertionError: failing!'))
@@ -82,40 +109,140 @@ public class TestNGXmlResultAndHtmlReportIntegrationTest extends
.assertTestPassed("passing")
.assertTestPassed("passing2")
.assertTestsSkipped()
- .assertStderr(allOf(containsString("err.fail"), containsString("err.fail2"), containsString("err.pass"), containsString("err.pass2")))
- .assertStderr(not(containsString("out.")))
- .assertStdout(allOf(containsString("out.fail"), containsString("out.fail2"), containsString("out.pass"), containsString("out.pass2")))
- .assertStdout(not(containsString("err.")))
- executionResult.testClass("org.PassingTest")
+ if (executionResult instanceof HtmlTestExecutionResult || outputAssociation == WITH_SUITE) {
+ mixedMethods
+ .assertStderr(allOf(containsString("err.fail"), containsString("err.fail2"), containsString("err.pass"), containsString("err.pass2")))
+ .assertStderr(not(containsString("out.")))
+ .assertStdout(allOf(containsString("out.fail"), containsString("out.fail2"), containsString("out.pass"), containsString("out.pass2")))
+ .assertStdout(not(containsString("err.")))
+ } else {
+ mixedMethods
+ .assertTestCaseStdout("passing", equalTo("out.pass\n"))
+ .assertTestCaseStderr("passing", equalTo("err.pass\n"))
+ .assertTestCaseStdout("failing", equalTo("out.fail\n"))
+ .assertTestCaseStderr("failing", equalTo("err.fail\n"))
+ .assertTestCaseStdout("passing2", equalTo("out.pass2\n"))
+ .assertTestCaseStderr("passing2", equalTo("err.pass2\n"))
+ .assertTestCaseStdout("failing2", equalTo("out.fail2\n"))
+ .assertTestCaseStderr("failing2", equalTo("err.fail2\n"))
+ }
+
+ def passing = executionResult.testClass("org.PassingTest")
.assertTestCount(2, 0, 0)
.assertTestsExecuted("passing", "passing2")
.assertTestPassed("passing").assertTestPassed("passing2")
- .assertStdout(equalTo("out\n"))
- .assertStderr(equalTo(""))
+ if (executionResult instanceof HtmlTestExecutionResult || outputAssociation == WITH_SUITE) {
+ passing
+ .assertStdout(equalTo("out\n"))
+ .assertStderr(equalTo(""))
+ } else {
+ passing
+ .assertTestCaseStdout("passing", equalTo("out\n"))
+ .assertTestCaseStderr("passing", equalTo(""))
+ .assertTestCaseStdout("passing2", equalTo(""))
+ .assertTestCaseStderr("passing2", equalTo(""))
+ }
- executionResult.testClass("org.FailingTest")
+ def failing = executionResult.testClass("org.FailingTest")
.assertTestCount(2, 2, 0)
.assertTestsExecuted("failing", "failing2")
.assertTestFailed("failing", anything()).assertTestFailed("failing2", anything())
- .assertStdout(equalTo(""))
- .assertStderr(equalTo("err\n"))
- executionResult.testClass("org.NoOutputsTest")
+ if (executionResult instanceof HtmlTestExecutionResult || outputAssociation == WITH_SUITE) {
+ failing
+ .assertStdout(equalTo(""))
+ .assertStderr(equalTo("err\n"))
+ } else {
+ failing
+ .assertTestCaseStdout("failing", equalTo(""))
+ .assertTestCaseStderr("failing", equalTo("err\n"))
+ .assertTestCaseStdout("failing2", equalTo(""))
+ .assertTestCaseStderr("failing2", equalTo(""))
+
+ }
+
+ def noOutputs = executionResult.testClass("org.NoOutputsTest")
.assertTestCount(1, 0, 0)
.assertTestsExecuted("passing").assertTestPassed("passing")
- .assertStdout(equalTo(""))
- .assertStderr(equalTo(""))
- executionResult.testClass("org.EncodingTest")
+ if (executionResult instanceof HtmlTestExecutionResult || outputAssociation == WITH_SUITE) {
+ noOutputs
+ .assertStdout(equalTo(""))
+ .assertStderr(equalTo(""))
+ } else {
+ noOutputs
+ .assertTestCaseStdout("passing", equalTo(""))
+ .assertTestCaseStderr("passing", equalTo(""))
+ }
+
+ def encoding = executionResult.testClass("org.EncodingTest")
.assertTestCount(2, 1, 0)
.assertTestPassed("encodesCdata")
.assertTestFailed("encodesAttributeValues", equalTo('java.lang.RuntimeException: html: <> cdata: ]]> non-ascii: ż'))
- .assertStdout(equalTo("""< html allowed, cdata closing token ]]> encoded!
+
+ if (executionResult instanceof HtmlTestExecutionResult || outputAssociation == WITH_SUITE) {
+ encoding
+ .assertStdout(equalTo("""< html allowed, cdata closing token ]]> encoded!
+no EOL, non-ascii char: ż
+xml entity: &
+"""))
+ .assertStderr(equalTo("< html allowed, cdata closing token ]]> encoded!\n"))
+ } else {
+ encoding
+ .assertTestCaseStdout("encodesCdata", equalTo("""< html allowed, cdata closing token ]]> encoded!
no EOL, non-ascii char: ż
xml entity: &
"""))
- .assertStderr(equalTo("< html allowed, cdata closing token ]]> encoded!\n"))
+ .assertTestCaseStderr("encodesCdata", equalTo("< html allowed, cdata closing token ]]> encoded!\n"))
+ }
+
+ def parameterized = executionResult.testClass("org.ParameterizedTest")
+ .assertTestCount(6, 4, 0)
+ .assertTestsExecuted(
+ "p1[0](1, 2)", "p4[0](1, \">…Ú)", "p1[1](3, 4)", "p3[0]", "p3[1]", "p4[1](2, \">…Ú)"
+ )
+ .assertTestFailed("p1[1](3, 4)", anything())
+ .assertTestFailed("p3[0]", containsString("Parameter 2 of iteration 1 of method 'p3' toString() method threw exception"))
+ .assertTestFailed("p3[1]", containsString("Parameter 2 of iteration 2 of method 'p3' toString() method threw exception"))
+ .assertTestFailed("p4[1](2, \">…Ú)", anything())
+
+ if (executionResult instanceof HtmlTestExecutionResult || outputAssociation == WITH_SUITE) {
+ parameterized
+ .assertStdout(equalTo("var1 is: 1\nvar1 is: 3\n"))
+ .assertStderr(equalTo("var2 is: 2\nvar2 is: 4\n"))
+ } else {
+ parameterized
+ .assertTestCaseStdout("p1[0](1, 2)", equalTo("var1 is: 1\n"))
+ .assertTestCaseStdout("p1[1](3, 4)", equalTo("var1 is: 3\n"))
+ .assertTestCaseStderr("p1[0](1, 2)", equalTo("var2 is: 2\n"))
+ .assertTestCaseStderr("p1[1](3, 4)", equalTo("var2 is: 4\n"))
+ }
+
+ def outputLifecycle = executionResult.testClass("org.OutputLifecycleTest")
+ .assertTestCount(2, 0, 0)
+ .assertTestsExecuted("m1", "m2")
+ .assertTestPassed("m1")
+ .assertTestPassed("m1")
+ .assertTestsSkipped()
+
+ if (executionResult instanceof HtmlTestExecutionResult || outputAssociation == WITH_SUITE) {
+ outputLifecycle
+ .assertStdout(allOf(containsString("m1 out"), containsString("m2 out")))
+ .assertStderr(allOf(containsString("m1 err"), containsString("m2 err")))
+
+ // We don't capture anything outside of test methods for TestNG
+ .assertStdout(not(anyOf(containsString("before"), containsString("after"), containsString("constructor"))))
+ .assertStderr(not(anyOf(containsString("before"), containsString("after"), containsString("constructor"))))
+ } else {
+ outputLifecycle
+ .assertTestCaseStdout("m1", equalTo("m1 out\n"))
+ .assertTestCaseStderr("m1", equalTo("m1 err\n"))
+ .assertTestCaseStdout("m2", equalTo("m2 out\n"))
+ .assertTestCaseStderr("m2", equalTo("m2 err\n"))
+ }
+
+ true
}
@@ -195,5 +322,105 @@ public class EncodingTest {
}
}
"""
+
+ file("src/test/java/org/ParameterizedTest.java") << """package org;
+
+import org.testng.annotations.*;
+import static org.testng.Assert.*;
+
+public class ParameterizedTest {
+
+ @Test(dataProvider = "1")
+ public void p1(String var1, String var2) {
+ System.out.println("var1 is: " + var1);
+ System.err.println("var2 is: " + var2);
+ assertEquals(var1, "1");
+ }
+
+ @DataProvider(name = "1")
+ public Object[][] provider1() {
+ return new Object[][] {
+ {"1", "2"},
+ {"3", "4"}
+ };
+ }
+
+ @Test(dataProvider = "3")
+ public void p3(int i, Object obj) {
+ assertTrue(i == 1);
+ }
+
+ @DataProvider(name = "3")
+ public Object[][] provider3() {
+ return new Object[][] {
+ {1, new Object() { public String toString() { throw new RuntimeException("bang!"); } } },
+ {2, new Object() { public String toString() { throw new RuntimeException("bang!"); } } }
+ };
+ }
+
+ @Test(dataProvider = "4")
+ public void p4(int i, Object obj) {
+ assertTrue(i == 1);
+ }
+
+ @DataProvider(name = "4")
+ public Object[][] provider4() {
+ return new Object[][] {
+ {1, "\\">…Ú" },
+ {2, "\\">…Ú" }
+ };
+ }
+
+}
+"""
+
+ file("src/test/java/org/OutputLifecycleTest.java") << """package org;
+
+import org.testng.annotations.*;
+import static org.testng.Assert.*;
+
+public class OutputLifecycleTest {
+
+ public OutputLifecycleTest() {
+ System.out.println("constructor out");
+ System.err.println("constructor err");
+ }
+
+ @BeforeClass
+ public static void beforeClass() {
+ System.out.println("beforeClass out");
+ System.err.println("beforeClass err");
+ }
+
+ @BeforeTest
+ public void beforeTest() {
+ System.out.println("beforeTest out");
+ System.err.println("beforeTest err");
+ }
+
+ @Test public void m1() {
+ System.out.println("m1 out");
+ System.err.println("m1 err");
+ }
+
+ @Test public void m2() {
+ System.out.println("m2 out");
+ System.err.println("m2 err");
+ }
+
+ @AfterTest
+ public void afterTest() {
+ System.out.println("afterTest out");
+ System.err.println("afterTest err");
+ }
+
+ @AfterClass
+ public static void afterClass() {
+ System.out.println("afterClass out");
+ System.err.println("afterClass err");
+ }
+}
+"""
+
}
}
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/compile/daemon/ParallelCompilerDaemonIntegrationTest/shared/build.gradle b/subprojects/plugins/src/integTest/resources/org/gradle/compile/daemon/ParallelCompilerDaemonIntegrationTest/shared/build.gradle
index 0aebc65..1949e8a 100644
--- a/subprojects/plugins/src/integTest/resources/org/gradle/compile/daemon/ParallelCompilerDaemonIntegrationTest/shared/build.gradle
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/compile/daemon/ParallelCompilerDaemonIntegrationTest/shared/build.gradle
@@ -2,7 +2,7 @@ subprojects {
apply plugin: "groovy"
dependencies {
- groovy localGroovy()
+ compile localGroovy()
}
compileJava.options.fork = true
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/groovy/compile/GroovyCompilerIntegrationSpec/canJointCompileWithJavaCompilerExecutable/build.gradle b/subprojects/plugins/src/integTest/resources/org/gradle/groovy/compile/GroovyCompilerIntegrationSpec/canJointCompileWithJavaCompilerExecutable/build.gradle
new file mode 100644
index 0000000..694dadf
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/groovy/compile/GroovyCompilerIntegrationSpec/canJointCompileWithJavaCompilerExecutable/build.gradle
@@ -0,0 +1,10 @@
+apply plugin: "groovy"
+
+repositories {
+ mavenCentral()
+}
+
+compileGroovy {
+ options.fork = true
+ options.forkOptions.executable = jdkHome
+}
\ No newline at end of file
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/groovy/compile/GroovyCompilerIntegrationSpec/canJointCompileWithJavaCompilerExecutable/src/main/groovy/GroovyCode.groovy b/subprojects/plugins/src/integTest/resources/org/gradle/groovy/compile/GroovyCompilerIntegrationSpec/canJointCompileWithJavaCompilerExecutable/src/main/groovy/GroovyCode.groovy
new file mode 100644
index 0000000..d2378ad
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/groovy/compile/GroovyCompilerIntegrationSpec/canJointCompileWithJavaCompilerExecutable/src/main/groovy/GroovyCode.groovy
@@ -0,0 +1 @@
+class GroovyCode {}
\ No newline at end of file
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/groovy/compile/GroovyCompilerIntegrationSpec/canJointCompileWithJavaCompilerExecutable/src/main/groovy/JavaCode.java b/subprojects/plugins/src/integTest/resources/org/gradle/groovy/compile/GroovyCompilerIntegrationSpec/canJointCompileWithJavaCompilerExecutable/src/main/groovy/JavaCode.java
new file mode 100644
index 0000000..8bbb6ac
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/groovy/compile/GroovyCompilerIntegrationSpec/canJointCompileWithJavaCompilerExecutable/src/main/groovy/JavaCode.java
@@ -0,0 +1,3 @@
+public class JavaCode {
+ GroovyCode groovyCode;
+}
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/groovy/compile/GroovyCompilerIntegrationSpec/canUseAstTransformThatReferencesGroovyTestCase/build.gradle b/subprojects/plugins/src/integTest/resources/org/gradle/groovy/compile/GroovyCompilerIntegrationSpec/canUseAstTransformThatReferencesGroovyTestCase/build.gradle
index 669c8e9..4a687c9 100644
--- a/subprojects/plugins/src/integTest/resources/org/gradle/groovy/compile/GroovyCompilerIntegrationSpec/canUseAstTransformThatReferencesGroovyTestCase/build.gradle
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/groovy/compile/GroovyCompilerIntegrationSpec/canUseAstTransformThatReferencesGroovyTestCase/build.gradle
@@ -5,6 +5,6 @@ repositories {
}
dependencies {
- groovy localGroovy()
+ compile localGroovy()
testCompile "junit:junit:4.10"
}
\ No newline at end of file
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/groovy/compile/IncrementalGroovyCompileIntegrationTest/recompilesDependentClasses/build.gradle b/subprojects/plugins/src/integTest/resources/org/gradle/groovy/compile/IncrementalGroovyCompileIntegrationTest/recompilesDependentClasses/build.gradle
index 69928e4..6bfe32a 100644
--- a/subprojects/plugins/src/integTest/resources/org/gradle/groovy/compile/IncrementalGroovyCompileIntegrationTest/recompilesDependentClasses/build.gradle
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/groovy/compile/IncrementalGroovyCompileIntegrationTest/recompilesDependentClasses/build.gradle
@@ -1,5 +1,5 @@
apply plugin: 'groovy'
dependencies {
- groovy localGroovy()
+ compile localGroovy()
}
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/groovy/compile/IncrementalGroovyCompileIntegrationTest/recompilesSourceWhenPropertiesChange/build.gradle b/subprojects/plugins/src/integTest/resources/org/gradle/groovy/compile/IncrementalGroovyCompileIntegrationTest/recompilesSourceWhenPropertiesChange/build.gradle
index 58fd49e..b501216 100644
--- a/subprojects/plugins/src/integTest/resources/org/gradle/groovy/compile/IncrementalGroovyCompileIntegrationTest/recompilesSourceWhenPropertiesChange/build.gradle
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/groovy/compile/IncrementalGroovyCompileIntegrationTest/recompilesSourceWhenPropertiesChange/build.gradle
@@ -1,6 +1,6 @@
apply plugin: 'groovy'
dependencies {
- groovy localGroovy()
+ compile localGroovy()
}
diff --git a/subprojects/integ-test/src/integTest/resources/org/gradle/integtests/IncrementalTestIntegrationTest/doesNotRunStaleTests/src/test/java/Broken.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/IncrementalTestIntegrationTest/doesNotRunStaleTests/src/test/java/Broken.java
similarity index 100%
rename from subprojects/integ-test/src/integTest/resources/org/gradle/integtests/IncrementalTestIntegrationTest/doesNotRunStaleTests/src/test/java/Broken.java
rename to subprojects/plugins/src/integTest/resources/org/gradle/testing/IncrementalTestIntegrationTest/doesNotRunStaleTests/src/test/java/Broken.java
diff --git a/subprojects/integ-test/src/integTest/resources/org/gradle/integtests/IncrementalTestIntegrationTest/executesTestsWhenSourceChanges/NewMainClass.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/IncrementalTestIntegrationTest/executesTestsWhenSourceChanges/NewMainClass.java
similarity index 100%
rename from subprojects/integ-test/src/integTest/resources/org/gradle/integtests/IncrementalTestIntegrationTest/executesTestsWhenSourceChanges/NewMainClass.java
rename to subprojects/plugins/src/integTest/resources/org/gradle/testing/IncrementalTestIntegrationTest/executesTestsWhenSourceChanges/NewMainClass.java
diff --git a/subprojects/integ-test/src/integTest/resources/org/gradle/integtests/IncrementalTestIntegrationTest/executesTestsWhenSourceChanges/NewOk.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/IncrementalTestIntegrationTest/executesTestsWhenSourceChanges/NewOk.java
similarity index 100%
rename from subprojects/integ-test/src/integTest/resources/org/gradle/integtests/IncrementalTestIntegrationTest/executesTestsWhenSourceChanges/NewOk.java
rename to subprojects/plugins/src/integTest/resources/org/gradle/testing/IncrementalTestIntegrationTest/executesTestsWhenSourceChanges/NewOk.java
diff --git a/subprojects/integ-test/src/integTest/resources/org/gradle/integtests/IncrementalTestIntegrationTest/executesTestsWhenSourceChanges/src/main/java/MainClass.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/IncrementalTestIntegrationTest/executesTestsWhenSourceChanges/src/main/java/MainClass.java
similarity index 100%
rename from subprojects/integ-test/src/integTest/resources/org/gradle/integtests/IncrementalTestIntegrationTest/executesTestsWhenSourceChanges/src/main/java/MainClass.java
rename to subprojects/plugins/src/integTest/resources/org/gradle/testing/IncrementalTestIntegrationTest/executesTestsWhenSourceChanges/src/main/java/MainClass.java
diff --git a/subprojects/integ-test/src/integTest/resources/org/gradle/integtests/IncrementalTestIntegrationTest/executesTestsWhenSelectedTestsChange/build.gradle b/subprojects/plugins/src/integTest/resources/org/gradle/testing/IncrementalTestIntegrationTest/executesTestsWhenTestFrameworkChanges/build.gradle
similarity index 100%
rename from subprojects/integ-test/src/integTest/resources/org/gradle/integtests/IncrementalTestIntegrationTest/executesTestsWhenSelectedTestsChange/build.gradle
rename to subprojects/plugins/src/integTest/resources/org/gradle/testing/IncrementalTestIntegrationTest/executesTestsWhenTestFrameworkChanges/build.gradle
diff --git a/subprojects/integ-test/src/integTest/resources/org/gradle/integtests/IncrementalTestIntegrationTest/executesTestsWhenSelectedTestsChange/src/test/java/JUnitExtra.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/IncrementalTestIntegrationTest/executesTestsWhenTestFrameworkChanges/src/test/java/JUnitExtra.java
similarity index 100%
rename from subprojects/integ-test/src/integTest/resources/org/gradle/integtests/IncrementalTestIntegrationTest/executesTestsWhenSelectedTestsChange/src/test/java/JUnitExtra.java
rename to subprojects/plugins/src/integTest/resources/org/gradle/testing/IncrementalTestIntegrationTest/executesTestsWhenTestFrameworkChanges/src/test/java/JUnitExtra.java
diff --git a/subprojects/integ-test/src/integTest/resources/org/gradle/integtests/IncrementalTestIntegrationTest/executesTestsWhenSelectedTestsChange/src/test/java/JUnitTest.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/IncrementalTestIntegrationTest/executesTestsWhenTestFrameworkChanges/src/test/java/JUnitTest.java
similarity index 100%
rename from subprojects/integ-test/src/integTest/resources/org/gradle/integtests/IncrementalTestIntegrationTest/executesTestsWhenSelectedTestsChange/src/test/java/JUnitTest.java
rename to subprojects/plugins/src/integTest/resources/org/gradle/testing/IncrementalTestIntegrationTest/executesTestsWhenTestFrameworkChanges/src/test/java/JUnitTest.java
diff --git a/subprojects/integ-test/src/integTest/resources/org/gradle/integtests/IncrementalTestIntegrationTest/executesTestsWhenSelectedTestsChange/src/test/java/TestNGTest.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/IncrementalTestIntegrationTest/executesTestsWhenTestFrameworkChanges/src/test/java/TestNGTest.java
similarity index 100%
rename from subprojects/integ-test/src/integTest/resources/org/gradle/integtests/IncrementalTestIntegrationTest/executesTestsWhenSelectedTestsChange/src/test/java/TestNGTest.java
rename to subprojects/plugins/src/integTest/resources/org/gradle/testing/IncrementalTestIntegrationTest/executesTestsWhenTestFrameworkChanges/src/test/java/TestNGTest.java
diff --git a/subprojects/integ-test/src/integTest/resources/org/gradle/integtests/IncrementalTestIntegrationTest/shared/build.gradle b/subprojects/plugins/src/integTest/resources/org/gradle/testing/IncrementalTestIntegrationTest/shared/build.gradle
similarity index 100%
rename from subprojects/integ-test/src/integTest/resources/org/gradle/integtests/IncrementalTestIntegrationTest/shared/build.gradle
rename to subprojects/plugins/src/integTest/resources/org/gradle/testing/IncrementalTestIntegrationTest/shared/build.gradle
diff --git a/subprojects/integ-test/src/integTest/resources/org/gradle/integtests/IncrementalTestIntegrationTest/shared/src/test/java/Ok.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/IncrementalTestIntegrationTest/shared/src/test/java/Ok.java
similarity index 100%
rename from subprojects/integ-test/src/integTest/resources/org/gradle/integtests/IncrementalTestIntegrationTest/shared/src/test/java/Ok.java
rename to subprojects/plugins/src/integTest/resources/org/gradle/testing/IncrementalTestIntegrationTest/shared/src/test/java/Ok.java
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitAssumptionsIntegrationTest/supportsAssumptions/build.gradle b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitAssumptionsIntegrationTest/supportsAssumptions/build.gradle
new file mode 100644
index 0000000..1c9cc4d
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitAssumptionsIntegrationTest/supportsAssumptions/build.gradle
@@ -0,0 +1,18 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+apply plugin: 'java'
+repositories { mavenCentral() }
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitAssumptionsIntegrationTest/supportsAssumptions/src/test/java/org/gradle/TestWithAssumptions.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitAssumptionsIntegrationTest/supportsAssumptions/src/test/java/org/gradle/TestWithAssumptions.java
new file mode 100644
index 0000000..7fd3fc1
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitAssumptionsIntegrationTest/supportsAssumptions/src/test/java/org/gradle/TestWithAssumptions.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle;
+
+import org.junit.Assume;
+import org.junit.Test;
+
+public class TestWithAssumptions {
+ @Test
+ public void assumptionFailed() {
+ Assume.assumeTrue(false);
+ }
+
+ @Test
+ public void assumptionSucceeded() {
+ Assume.assumeTrue(true);
+ }
+}
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canCombineCategoriesWithCustomRunner/build.gradle b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canCombineCategoriesWithCustomRunner/build.gradle
new file mode 100644
index 0000000..6b5b248
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canCombineCategoriesWithCustomRunner/build.gradle
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+
+apply plugin: "java"
+
+repositories {
+ mavenCentral()
+}
+
+test {
+ useJUnit {
+ excludeCategories 'org.gradle.CategoryA'
+ }
+}
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canCombineCategoriesWithCustomRunner/src/test/java/org/gradle/CategoryA.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canCombineCategoriesWithCustomRunner/src/test/java/org/gradle/CategoryA.java
new file mode 100644
index 0000000..932dcf1
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canCombineCategoriesWithCustomRunner/src/test/java/org/gradle/CategoryA.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle;
+
+public interface CategoryA {
+}
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canCombineCategoriesWithCustomRunner/src/test/java/org/gradle/LocaleHolder.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canCombineCategoriesWithCustomRunner/src/test/java/org/gradle/LocaleHolder.java
new file mode 100644
index 0000000..b42b587
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canCombineCategoriesWithCustomRunner/src/test/java/org/gradle/LocaleHolder.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle;
+
+import java.util.Locale;
+
+class LocaleHolder {
+ private static Locale locale;
+
+ public static Locale set(Locale locale) {
+ Locale old = LocaleHolder.locale;
+ LocaleHolder.locale = locale;
+ return old;
+ }
+ public static Locale get() {
+ return locale;
+ }
+}
\ No newline at end of file
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canCombineCategoriesWithCustomRunner/src/test/java/org/gradle/Locales.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canCombineCategoriesWithCustomRunner/src/test/java/org/gradle/Locales.java
new file mode 100644
index 0000000..f2730b4
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canCombineCategoriesWithCustomRunner/src/test/java/org/gradle/Locales.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle;
+
+import org.junit.runner.Runner;
+import org.junit.runners.BlockJUnit4ClassRunner;
+import org.junit.runners.Suite;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.InitializationError;
+import org.junit.runners.model.Statement;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+
+public class Locales extends Suite {
+ private static final Iterable<Locale> localesToUse = Arrays.asList(Locale.FRENCH, Locale.GERMAN, Locale.ENGLISH);
+
+ public Locales(Class<?> klass) throws InitializationError {
+ super(klass, extracAndCreateRunners(klass));
+ }
+
+ private static List<Runner> extracAndCreateRunners(Class<?> klass) throws InitializationError {
+ List<Runner> runners = new ArrayList<Runner>();
+ for (Locale locale : localesToUse) {
+ runners.add(new LocalesRunner(locale, klass));
+ }
+ return runners;
+ }
+
+ private static class LocalesRunner extends BlockJUnit4ClassRunner {
+ private final Locale locale;
+
+ LocalesRunner(Locale locale, Class<?> klass) throws InitializationError {
+ super(klass);
+ this.locale = locale;
+ }
+
+ @Override
+ protected Statement methodBlock(final FrameworkMethod method) {
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ Locale oldLocale = LocaleHolder.set(locale);
+ try {
+ LocalesRunner.super.methodBlock(method).evaluate();
+ } finally {
+ LocaleHolder.set(oldLocale);
+ }
+ }
+ };
+ }
+
+ @Override// The name of the test class
+ protected String getName() {
+ return String.format("%s [%s]", super.getName(), locale);
+ }
+
+ @Override// The name of the test method
+ protected String testName(final FrameworkMethod method) {
+ return String.format("%s [%s]", method.getName(), locale);
+ }
+ }
+
+}
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canCombineCategoriesWithCustomRunner/src/test/java/org/gradle/SomeLocaleTests.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canCombineCategoriesWithCustomRunner/src/test/java/org/gradle/SomeLocaleTests.java
new file mode 100644
index 0000000..97b8122
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canCombineCategoriesWithCustomRunner/src/test/java/org/gradle/SomeLocaleTests.java
@@ -0,0 +1,19 @@
+package org.gradle;
+
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+
+ at RunWith(org.gradle.Locales.class)
+public class SomeLocaleTests {
+ @Test
+ public void ok1() {
+ System.out.println("Locale in use: " + LocaleHolder.get());
+ }
+
+ @Test
+ @Category(org.gradle.CategoryA.class)
+ public void ok2() {
+ System.out.println("Locale in use: " + LocaleHolder.get());
+ }
+}
\ No newline at end of file
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canCombineCategoriesWithCustomRunner/src/test/java/org/gradle/SomeMoreLocalTests.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canCombineCategoriesWithCustomRunner/src/test/java/org/gradle/SomeMoreLocalTests.java
new file mode 100644
index 0000000..e18620f
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canCombineCategoriesWithCustomRunner/src/test/java/org/gradle/SomeMoreLocalTests.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle;
+
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+
+ at RunWith(org.gradle.Locales.class)
+ at Category(org.gradle.CategoryA.class)
+public class SomeMoreLocalTests {
+ @Test
+ public void someMoreTest1() {
+ System.out.println("Locale in use: " + LocaleHolder.get());
+ }
+
+ @Test
+ public void someMoreTest2() {
+ System.out.println("Locale in use: " + LocaleHolder.get());
+ }
+}
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyExcludesOnly/build.gradle b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyExcludesOnly/build.gradle
new file mode 100644
index 0000000..72cfbd5
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyExcludesOnly/build.gradle
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+apply plugin: "java"
+
+repositories {
+ mavenCentral()
+}
+
+test {
+ useJUnit {
+ excludeCategories 'org.gradle.CategoryA'
+ }
+}
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyExcludesOnly/src/test/java/org/gradle/CatATests.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyExcludesOnly/src/test/java/org/gradle/CatATests.java
new file mode 100644
index 0000000..3abce2e
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyExcludesOnly/src/test/java/org/gradle/CatATests.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle;
+
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+
+ at Category(org.gradle.CategoryA.class)
+public class CatATests {
+
+ @Test
+ public void catAOk1() {
+ }
+
+ @Test
+ public void catAOk2() {
+ }
+
+ @Test
+ public void catAOk3() {
+ }
+
+ @Test
+ public void catAOk4() {
+ }
+}
+
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyExcludesOnly/src/test/java/org/gradle/CategoryA.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyExcludesOnly/src/test/java/org/gradle/CategoryA.java
new file mode 100644
index 0000000..fe86403
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyExcludesOnly/src/test/java/org/gradle/CategoryA.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle;
+
+public class CategoryA {
+}
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyExcludesOnly/src/test/java/org/gradle/NoCatTests.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyExcludesOnly/src/test/java/org/gradle/NoCatTests.java
new file mode 100644
index 0000000..31fe49e
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyExcludesOnly/src/test/java/org/gradle/NoCatTests.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle;
+
+import org.junit.Test;
+
+public class NoCatTests {
+
+ @Test
+ public void noCatOk1() {
+ }
+
+ @Test
+ public void noCatOk2() {
+ }
+}
\ No newline at end of file
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyExcludesOnly/src/test/java/org/gradle/SomeOtherCat.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyExcludesOnly/src/test/java/org/gradle/SomeOtherCat.java
new file mode 100644
index 0000000..f694f60
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyExcludesOnly/src/test/java/org/gradle/SomeOtherCat.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle;
+
+public interface SomeOtherCat {
+}
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyExcludesOnly/src/test/java/org/gradle/SomeOtherCatTests.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyExcludesOnly/src/test/java/org/gradle/SomeOtherCatTests.java
new file mode 100644
index 0000000..68266a5
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyExcludesOnly/src/test/java/org/gradle/SomeOtherCatTests.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle;
+
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+ at Category(org.gradle.SomeOtherCat.class)
+public class SomeOtherCatTests {
+
+ @Test
+ public void someOtherOk1() {
+ }
+
+ @Test
+ public void someOtherOk2() {
+ }
+}
\ No newline at end of file
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyExcludesOnly/src/test/java/org/gradle/SomeTests.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyExcludesOnly/src/test/java/org/gradle/SomeTests.java
new file mode 100644
index 0000000..dd69759
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyExcludesOnly/src/test/java/org/gradle/SomeTests.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle;
+
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+public class SomeTests {
+ @Category(org.gradle.CategoryA.class)
+ @Test
+ public void catAOk1() {
+ }
+
+ @Category(org.gradle.SomeOtherCat.class)
+ @Test
+ public void someOtherCatOk2() {
+ }
+
+ @Test
+ public void noCatOk3() {
+ }
+
+ @Test
+ public void noCatOk4() {
+ }
+}
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/build.gradle b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/build.gradle
new file mode 100644
index 0000000..34071d2
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/build.gradle
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+apply plugin: "java"
+
+repositories {
+ mavenCentral()
+}
+
+test {
+ useJUnit {
+ includeCategories 'org.gradle.CategoryA'
+ excludeCategories 'org.gradle.CategoryC'
+ }
+}
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/CatACTests.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/CatACTests.java
new file mode 100644
index 0000000..c026a15
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/CatACTests.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle;
+
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+ at Category({org.gradle.CategoryA.class, org.gradle.CategoryC.class})
+public class CatACTests {
+
+ @Test
+ public void catABOk1() {
+ }
+
+ @Test
+ public void catABOk2() {
+ }
+
+ @Test
+ public void catABOk3() {
+ }
+
+ @Test
+ public void catABOk4() {
+ }
+}
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/CatADTests.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/CatADTests.java
new file mode 100644
index 0000000..6650d3b
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/CatADTests.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle;
+
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+
+ at Category(org.gradle.CategoryA.class)
+public class CatADTests {
+
+ @Test
+ public void catAOk1() {
+ }
+
+ @Test
+ public void catAOk2() {
+ }
+
+ @Test
+ @Category(org.gradle.CategoryC.class)
+ public void catCOk3() {
+ }
+
+ @Test
+ @Category(org.gradle.CategoryD.class)
+ public void catDOk4() {
+ }
+}
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/CatATests.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/CatATests.java
new file mode 100644
index 0000000..a8966b4
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/CatATests.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle;
+
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+
+ at Category(org.gradle.CategoryA.class)
+public class CatATests {
+
+ @Test
+ public void catAOk1() {
+ }
+
+ @Test
+ public void catAOk2() {
+ }
+
+ @Test
+ public void catAOk3() {
+ }
+
+ @Test
+ public void catAOk4() {
+ }
+}
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/CatBTests.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/CatBTests.java
new file mode 100644
index 0000000..a6dccd4
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/CatBTests.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle;
+
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+ at Category(org.gradle.CategoryB.class)
+public class CatBTests {
+
+ @Test
+ public void catBOk1() {
+ }
+
+ @Test
+ public void catBOk2() {
+ }
+
+ @Test
+ public void catBOk3() {
+ }
+
+ @Test
+ public void catBOk4() {
+ }
+}
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/CatCBTests.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/CatCBTests.java
new file mode 100644
index 0000000..88617d4
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/CatCBTests.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle;
+
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+
+ at Category(org.gradle.CategoryC.class)
+public class CatCBTests {
+
+ @Test
+ public void catCOk1() {
+ }
+
+ @Test
+ public void catCOk2() {
+ }
+
+ @Test
+ @Category(org.gradle.CategoryA.class)
+ public void catAOk3() {
+ }
+
+ @Test
+ @Category(org.gradle.CategoryB.class)
+ public void catBOk4() {
+ }
+}
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/CatCTests.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/CatCTests.java
new file mode 100644
index 0000000..6ff66fe
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/CatCTests.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle;
+
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+ at Category(CategoryC.class)
+public class CatCTests {
+
+ @Test
+ public void catCOk1() {
+ }
+
+ @Test
+ public void catCOk2() {
+ }
+
+ @Test
+ public void catCOk3() {
+ }
+
+ @Test
+ public void catCOk4() {
+ }
+}
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/CatDTests.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/CatDTests.java
new file mode 100644
index 0000000..f755acc
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/CatDTests.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle;
+
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+ at Category(CategoryD.class)
+public class CatDTests {
+
+ @Test
+ public void catDOk1() {
+ }
+
+ @Test
+ public void catDOk2() {
+ }
+
+ @Test
+ public void catDOk3() {
+ }
+
+ @Test
+ public void catDOk4() {
+ }
+}
\ No newline at end of file
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/CatZTests.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/CatZTests.java
new file mode 100644
index 0000000..c95e596
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/CatZTests.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle;
+
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+ at Category(CategoryZ.class)
+public class CatZTests {
+
+ @Test
+ public void catZOk1() {
+ }
+
+ @Test
+ public void catZOk2() {
+ }
+
+ @Test
+ public void catZOk3() {
+ }
+
+ @Test
+ public void catZOk4() {
+ }
+}
\ No newline at end of file
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/CategoryA.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/CategoryA.java
new file mode 100644
index 0000000..87277ec
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/CategoryA.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle;
+
+public interface CategoryA{
+}
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/CategoryB.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/CategoryB.java
new file mode 100644
index 0000000..355b5f8
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/CategoryB.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle;
+
+public interface CategoryB extends org.gradle.CategoryA{
+}
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/CategoryC.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/CategoryC.java
new file mode 100644
index 0000000..ccee989
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/CategoryC.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle;
+
+public interface CategoryC{
+}
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/CategoryD.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/CategoryD.java
new file mode 100644
index 0000000..c8f7024
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/CategoryD.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle;
+
+public interface CategoryD extends org.gradle.CategoryC{
+}
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/CategoryZ.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/CategoryZ.java
new file mode 100644
index 0000000..a866cbc
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/CategoryZ.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle;
+
+public interface CategoryZ {
+}
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/MixedTests.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/MixedTests.java
new file mode 100644
index 0000000..fefb774
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/MixedTests.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+
+public class MixedTests {
+
+ @Category(org.gradle.CategoryA.class)
+ @Test
+ public void catAOk1() {
+ }
+
+ @Category(org.gradle.CategoryB.class)
+ @Test
+ public void catBOk2() {
+ }
+
+ @Category(org.gradle.CategoryA.class)
+ @Ignore
+ @Test
+ public void someIgnoredTest() {
+ }
+
+ @Test
+ public void noCatOk4() {
+ }
+}
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/NoCatTests.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/NoCatTests.java
new file mode 100644
index 0000000..a96e2c8
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCrossVersionIntegrationSpec/canSpecifyIncludeAndExcludeCategories/src/test/java/org/gradle/NoCatTests.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle;
+
+import org.junit.Test;
+
+public class NoCatTests {
+
+ @Test
+ public void noCatOk1() {
+ }
+
+ @Test
+ public void noCatOk2() {
+ }
+
+ @Test
+ public void noCatOk3() {
+ }
+
+ @Test
+ public void noCatOk4() {
+ }
+}
\ No newline at end of file
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesIntegrationSpec/reportsUnloadableCategories/build.gradle b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesIntegrationSpec/reportsUnloadableCategories/build.gradle
new file mode 100644
index 0000000..1c5f193
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesIntegrationSpec/reportsUnloadableCategories/build.gradle
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+
+
+apply plugin: "java"
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ testCompile 'junit:junit:4.11'
+}
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesIntegrationSpec/reportsUnloadableCategories/src/test/java/org/gradle/SomeTestClass.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesIntegrationSpec/reportsUnloadableCategories/src/test/java/org/gradle/SomeTestClass.java
new file mode 100644
index 0000000..dbb7f5f
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesIntegrationSpec/reportsUnloadableCategories/src/test/java/org/gradle/SomeTestClass.java
@@ -0,0 +1,13 @@
+package org.gradle;
+
+import org.junit.Test;
+
+public class SomeTestClass {
+ @Test
+ public void ok1() {
+ }
+
+ @Test
+ public void ok2() {
+ }
+}
\ No newline at end of file
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesIntegrationSpec/testTaskFailsIfCategoriesNotSupported/build.gradle b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesIntegrationSpec/testTaskFailsIfCategoriesNotSupported/build.gradle
new file mode 100644
index 0000000..9136c73
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesIntegrationSpec/testTaskFailsIfCategoriesNotSupported/build.gradle
@@ -0,0 +1,16 @@
+apply plugin: "java"
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ testCompile "junit:junit:4.4"
+}
+
+test {
+ useJUnit {
+ includeCategories 'org.gradle.CategoryA'
+ excludeCategories 'org.gradle.CategoryC'
+ }
+}
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesIntegrationSpec/testTaskFailsIfCategoriesNotSupported/src/test/java/org/gradle/SomeTest.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesIntegrationSpec/testTaskFailsIfCategoriesNotSupported/src/test/java/org/gradle/SomeTest.java
new file mode 100644
index 0000000..0c8904e
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesIntegrationSpec/testTaskFailsIfCategoriesNotSupported/src/test/java/org/gradle/SomeTest.java
@@ -0,0 +1,12 @@
+package org.gradle;
+
+import org.junit.Test;
+
+public class SomeTest {
+ @Test
+ public void ok() {
+ }
+
+ public void helpermethod() {
+ }
+}
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIgnoreClassCrossVersionIntegrationSpec/canHandleClassLevelIgnoredTests/build.gradle b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIgnoreClassCrossVersionIntegrationSpec/canHandleClassLevelIgnoredTests/build.gradle
new file mode 100644
index 0000000..f3986de
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIgnoreClassCrossVersionIntegrationSpec/canHandleClassLevelIgnoredTests/build.gradle
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+
+
+apply plugin: 'java'
+
+repositories {
+ mavenCentral()
+}
\ No newline at end of file
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIgnoreClassCrossVersionIntegrationSpec/canHandleClassLevelIgnoredTests/src/test/java/org/gradle/CustomIgnoredTest.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIgnoreClassCrossVersionIntegrationSpec/canHandleClassLevelIgnoredTests/src/test/java/org/gradle/CustomIgnoredTest.java
new file mode 100644
index 0000000..f3d2895
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIgnoreClassCrossVersionIntegrationSpec/canHandleClassLevelIgnoredTests/src/test/java/org/gradle/CustomIgnoredTest.java
@@ -0,0 +1,70 @@
+package org.gradle.testing.junit.JUnitIgnoreClassCrossVersionIntegrationSpec.canHandleClassLevelIgnoredTests.src.test.java.org.gradle;
+
+import org.junit.Ignore;
+import org.junit.runner.Description;
+import org.junit.runner.RunWith;
+import org.junit.runner.Runner;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunNotifier;
+
+import java.util.ArrayList;
+import java.util.List;
+
+ at Ignore
+ at RunWith(org.gradle.CustomIgnoredTest.TheRunner.class)
+public class CustomIgnoredTest {
+ static int count = 0;
+
+ public boolean doSomething() {
+ return true;
+ }
+
+ public static class TheRunner extends Runner {
+ List descriptions = new ArrayList();
+ private final Class<? extends org.gradle.CustomIgnoredTest> testClass;
+ private final org.gradle.CustomIgnoredTest testContainingInstance;
+ private Description testSuiteDescription;
+
+ public TheRunner(Class<? extends org.gradle.CustomIgnoredTest> testClass) {
+ this.testClass = testClass;
+ testContainingInstance = reflectMeATestContainingInstance(testClass);
+ testSuiteDescription = Description.createSuiteDescription("Custom Test with Suite ");
+ testSuiteDescription.addChild(createTestDescription("first test run"));
+ testSuiteDescription.addChild(createTestDescription("second test run"));
+ testSuiteDescription.addChild(createTestDescription("third test run"));
+ }
+
+ @Override
+ public Description getDescription() {
+ return testSuiteDescription;
+ }
+
+ @Override
+ public void run(RunNotifier notifier) {
+ for (Description description : testSuiteDescription.getChildren()) {
+ notifier.fireTestStarted(description);
+ try {
+ if (testContainingInstance.doSomething()) {
+ notifier.fireTestFinished(description);
+ } else {
+ notifier.fireTestIgnored(description);
+ }
+ } catch (Exception e) {
+ notifier.fireTestFailure(new Failure(description, e));
+ }
+ }
+ }
+
+ private org.gradle.CustomIgnoredTest reflectMeATestContainingInstance(Class<? extends org.gradle.CustomIgnoredTest> testClass) {
+ try {
+ return testClass.newInstance();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private Description createTestDescription(String description) {
+ return Description.createTestDescription(testClass, description);
+ }
+ }
+}
\ No newline at end of file
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIgnoreClassCrossVersionIntegrationSpec/canHandleClassLevelIgnoredTests/src/test/java/org/gradle/IgnoredTest.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIgnoreClassCrossVersionIntegrationSpec/canHandleClassLevelIgnoredTests/src/test/java/org/gradle/IgnoredTest.java
new file mode 100644
index 0000000..31c7395
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIgnoreClassCrossVersionIntegrationSpec/canHandleClassLevelIgnoredTests/src/test/java/org/gradle/IgnoredTest.java
@@ -0,0 +1,12 @@
+package org.gradle.testing.junit.JUnitIgnoreClassCrossVersionIntegrationSpec.canHandleClassLevelIgnoredTests.src.test.java.org.gradle;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+ at Ignore
+public class IgnoredTest {
+ @Test
+ public void testIgnored() {
+ throw new RuntimeException();
+ }
+}
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/canHandleMultipleThreadsWritingToSystemErr/build.gradle b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/canHandleMultipleThreadsWritingToSystemErr/build.gradle
index 76284da..ba9f816 100644
--- a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/canHandleMultipleThreadsWritingToSystemErr/build.gradle
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/canHandleMultipleThreadsWritingToSystemErr/build.gradle
@@ -1,7 +1,9 @@
apply plugin: 'groovy'
repositories { mavenCentral() }
-dependencies { groovy localGroovy() }
-dependencies { testCompile 'junit:junit:4.11'}
+dependencies {
+ testCompile localGroovy()
+ testCompile 'junit:junit:4.11'
+}
test {
testLogging {
showStandardStreams = true
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/canHandleMultipleThreadsWritingToSystemOut/build.gradle b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/canHandleMultipleThreadsWritingToSystemOut/build.gradle
index 76284da..ba9f816 100644
--- a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/canHandleMultipleThreadsWritingToSystemOut/build.gradle
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/canHandleMultipleThreadsWritingToSystemOut/build.gradle
@@ -1,7 +1,9 @@
apply plugin: 'groovy'
repositories { mavenCentral() }
-dependencies { groovy localGroovy() }
-dependencies { testCompile 'junit:junit:4.11'}
+dependencies {
+ testCompile localGroovy()
+ testCompile 'junit:junit:4.11'
+}
test {
testLogging {
showStandardStreams = true
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/canRunTestsUsingJUnit3/build.gradle b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/canRunTestsUsingJUnit3/build.gradle
new file mode 100644
index 0000000..464a61d
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/canRunTestsUsingJUnit3/build.gradle
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+apply plugin: 'java'
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ testCompile "junit:junit:3.8"
+}
\ No newline at end of file
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/junit3Tests/build.gradle b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/junit3Tests/build.gradle
deleted file mode 100644
index 0f93806..0000000
--- a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/junit3Tests/build.gradle
+++ /dev/null
@@ -1,9 +0,0 @@
-apply plugin: 'java'
-
-repositories {
- mavenCentral()
-}
-
-dependencies {
- testCompile "junit:junit:3.8"
-}
\ No newline at end of file
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/junit4Tests/build.gradle b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/junit4Tests/build.gradle
deleted file mode 100644
index 7da1b0e..0000000
--- a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/junit4Tests/build.gradle
+++ /dev/null
@@ -1,9 +0,0 @@
-apply plugin: 'java'
-
-repositories {
- mavenCentral()
-}
-
-dependencies {
- testCompile "junit:junit:4.11"
-}
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/junit4Tests/src/test/java/org/gradle/CustomIgnoredTest.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/junit4Tests/src/test/java/org/gradle/CustomIgnoredTest.java
deleted file mode 100644
index 435cc7b..0000000
--- a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/junit4Tests/src/test/java/org/gradle/CustomIgnoredTest.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package org.gradle;
-
-import org.junit.Ignore;
-import org.junit.runner.Description;
-import org.junit.runner.RunWith;
-import org.junit.runner.Runner;
-import org.junit.runner.notification.Failure;
-import org.junit.runner.notification.RunNotifier;
-
-import java.util.ArrayList;
-import java.util.List;
-
- at Ignore
- at RunWith(org.gradle.CustomIgnoredTest.TheRunner.class)
-public class CustomIgnoredTest {
- static int count = 0;
-
- public boolean doSomething() {
- return true;
- }
-
- public static class TheRunner extends Runner {
- List descriptions = new ArrayList();
- private final Class<? extends org.gradle.CustomIgnoredTest> testClass;
- private final org.gradle.CustomIgnoredTest testContainingInstance;
- private Description testSuiteDescription;
-
- public TheRunner(Class<? extends org.gradle.CustomIgnoredTest> testClass) {
- this.testClass = testClass;
- testContainingInstance = reflectMeATestContainingInstance(testClass);
- testSuiteDescription = Description.createSuiteDescription("Custom Test with Suite ");
- testSuiteDescription.addChild(createTestDescription("first test run"));
- testSuiteDescription.addChild(createTestDescription("second test run"));
- testSuiteDescription.addChild(createTestDescription("third test run"));
- }
-
- @Override
- public Description getDescription() {
- return testSuiteDescription;
- }
-
- @Override
- public void run(RunNotifier notifier) {
- for (Description description : testSuiteDescription.getChildren()) {
- notifier.fireTestStarted(description);
- try {
- if (testContainingInstance.doSomething()) {
- notifier.fireTestFinished(description);
- } else {
- notifier.fireTestIgnored(description);
- }
- } catch (Exception e) {
- notifier.fireTestFailure(new Failure(description, e));
- }
- }
-
- }
-
- private org.gradle.CustomIgnoredTest reflectMeATestContainingInstance(Class<? extends org.gradle.CustomIgnoredTest> testClass) {
- try {
- return testClass.newInstance();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
- private Description createTestDescription(String description) {
- return Description.createTestDescription(testClass, description);
- }
- }
-}
\ No newline at end of file
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/junit4Tests/src/test/java/org/gradle/IgnoredTest.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/junit4Tests/src/test/java/org/gradle/IgnoredTest.java
deleted file mode 100644
index ec02a29..0000000
--- a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/junit4Tests/src/test/java/org/gradle/IgnoredTest.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.gradle;
-
-import org.junit.Ignore;
-import org.junit.Test;
-
- at Ignore
-public class IgnoredTest {
- @Test
- public void testIgnored() {
- throw new RuntimeException();
- }
-}
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/junit4Tests/src/test/java/org/gradle/Junit4Test.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/junit4Tests/src/test/java/org/gradle/Junit4Test.java
index 857793d..9d0ba47 100644
--- a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/junit4Tests/src/test/java/org/gradle/Junit4Test.java
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/junit4Tests/src/test/java/org/gradle/Junit4Test.java
@@ -1,6 +1,5 @@
package org.gradle;
-import org.junit.Assume;
import org.junit.Ignore;
import org.junit.Test;
@@ -9,16 +8,12 @@ public class Junit4Test {
public void ok() {
}
- @Test @Ignore
+ @Test
+ @Ignore
public void broken() {
throw new RuntimeException();
}
- public void helpermethod(){
- }
-
- @Test
- public void assumptionFailed() {
- Assume.assumeTrue(false);
+ public void helpermethod() {
}
}
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/reportsAndBreaksBuildWhenTestFails/build.gradle b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/reportsAndBreaksBuildWhenTestFails/build.gradle
index 9d27852..0fc8356 100644
--- a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/reportsAndBreaksBuildWhenTestFails/build.gradle
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/reportsAndBreaksBuildWhenTestFails/build.gradle
@@ -1,3 +1,7 @@
apply plugin: 'java'
-repositories { mavenCentral() }
-dependencies { testCompile 'junit:junit:4.11' }
+repositories {
+ mavenCentral()
+}
+dependencies {
+ testCompile 'junit:junit:4.11'
+}
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/supportsTestCategories/build.gradle b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/supportsTestCategories/build.gradle
new file mode 100644
index 0000000..fd11e8d
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/supportsTestCategories/build.gradle
@@ -0,0 +1,16 @@
+apply plugin: "java"
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ testCompile "junit:junit:4.11"
+}
+
+test {
+ useJUnit {
+ includeCategories 'org.gradle.CategoryA'
+ excludeCategories 'org.gradle.CategoryC'
+ }
+}
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/supportsTestCategories/src/test/java/org/gradle/CategoryA.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/supportsTestCategories/src/test/java/org/gradle/CategoryA.java
new file mode 100644
index 0000000..d396068
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/supportsTestCategories/src/test/java/org/gradle/CategoryA.java
@@ -0,0 +1,4 @@
+package org.gradle;
+
+public interface CategoryA {
+}
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/supportsTestCategories/src/test/java/org/gradle/CategoryB.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/supportsTestCategories/src/test/java/org/gradle/CategoryB.java
new file mode 100644
index 0000000..00d73b6
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/supportsTestCategories/src/test/java/org/gradle/CategoryB.java
@@ -0,0 +1,4 @@
+package org.gradle;
+
+public interface CategoryB extends CategoryA{
+}
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/supportsTestCategories/src/test/java/org/gradle/CategoryC.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/supportsTestCategories/src/test/java/org/gradle/CategoryC.java
new file mode 100644
index 0000000..e70c77f
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/supportsTestCategories/src/test/java/org/gradle/CategoryC.java
@@ -0,0 +1,4 @@
+package org.gradle;
+
+public interface CategoryC {
+}
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/supportsTestCategories/src/test/java/org/gradle/SomeTest.java b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/supportsTestCategories/src/test/java/org/gradle/SomeTest.java
new file mode 100644
index 0000000..5e0ba2b
--- /dev/null
+++ b/subprojects/plugins/src/integTest/resources/org/gradle/testing/junit/JUnitIntegrationTest/supportsTestCategories/src/test/java/org/gradle/SomeTest.java
@@ -0,0 +1,27 @@
+package org.gradle;
+
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+ at Category(CategoryA.class)
+public class SomeTest {
+
+ @Test
+ public void testOk1() {
+ }
+
+ @Test
+ @Category(CategoryC.class)
+ public void testOk2() {
+ }
+
+ @Test
+ @Category(CategoryB.class)
+ public void testOk3() {
+ }
+
+ @Test
+ @Category({CategoryB.class, CategoryC.class})
+ public void testOk4() {
+ }
+}
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/testng/TestNGLoggingIntegrationTest/shared/build.gradle b/subprojects/plugins/src/integTest/resources/org/gradle/testing/testng/TestNGLoggingIntegrationTest/shared/build.gradle
deleted file mode 100644
index fcabda8..0000000
--- a/subprojects/plugins/src/integTest/resources/org/gradle/testing/testng/TestNGLoggingIntegrationTest/shared/build.gradle
+++ /dev/null
@@ -1,24 +0,0 @@
-apply plugin: "groovy"
-
-repositories {
- mavenCentral()
-}
-
-dependencies {
- compile "org.codehaus.groovy:groovy-all:2.0.5"
- testCompile "org.testng:testng:6.3.1"
-}
-
-test {
- useTestNG()
- testLogging {
- quiet {
- events "skipped", "failed"
- minGranularity 2
- maxGranularity -1
- displayGranularity 3
- exceptionFormat "full"
- stackTraceFilters "truncate", "groovy"
- }
- }
-}
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/testng/TestNGLoggingIntegrationTest/shared/src/test/groovy/org/gradle/TestNGTest.groovy b/subprojects/plugins/src/integTest/resources/org/gradle/testing/testng/TestNGLoggingIntegrationTest/shared/src/test/groovy/org/gradle/TestNGTest.groovy
deleted file mode 100644
index 6fa79fe..0000000
--- a/subprojects/plugins/src/integTest/resources/org/gradle/testing/testng/TestNGLoggingIntegrationTest/shared/src/test/groovy/org/gradle/TestNGTest.groovy
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle
-
-import org.testng.annotations.Test
-
-class TestNGTest {
- @Test
- void goodTest() {}
-
- @Test(dependsOnMethods = ["goodTest"])
- void badTest() {
- beBad()
- }
-
- @Test(dependsOnMethods = ["badTest"])
- void ignoredTest() {}
-
- @Test(dependsOnMethods = ["goodTest"])
- void printTest() {
- println "line 1\nline 2"
- println "line 3"
- }
-
- private beBad() {
- throw new RuntimeException("bad")
- }
-}
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/testng/TestNGLoggingIntegrationTest/standardOutputLogging/build.gradle b/subprojects/plugins/src/integTest/resources/org/gradle/testing/testng/TestNGLoggingIntegrationTest/standardOutputLogging/build.gradle
deleted file mode 100644
index c104119..0000000
--- a/subprojects/plugins/src/integTest/resources/org/gradle/testing/testng/TestNGLoggingIntegrationTest/standardOutputLogging/build.gradle
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.
- */
-
-apply plugin: "groovy"
-
-repositories {
- mavenCentral()
-}
-
-dependencies {
- compile "org.codehaus.groovy:groovy-all:2.0.5"
- testCompile "org.testng:testng:6.3.1"
-}
-
-test {
- useTestNG()
- testLogging {
- quiet {
- events "standardOut", "standardError"
- }
- }
-}
diff --git a/subprojects/plugins/src/integTest/resources/org/gradle/testing/testng/TestNGLoggingIntegrationTest/standardOutputLogging/src/test/groovy/org/gradle/TestNGStandardOutputTest.groovy b/subprojects/plugins/src/integTest/resources/org/gradle/testing/testng/TestNGLoggingIntegrationTest/standardOutputLogging/src/test/groovy/org/gradle/TestNGStandardOutputTest.groovy
deleted file mode 100644
index becc609..0000000
--- a/subprojects/plugins/src/integTest/resources/org/gradle/testing/testng/TestNGLoggingIntegrationTest/standardOutputLogging/src/test/groovy/org/gradle/TestNGStandardOutputTest.groovy
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle
-
-import org.testng.annotations.Test
-
-class TestNGStandardOutputTest {
- @Test
- void printTest() {
- println "line 1\nline 2"
- println "line 3"
- }
-}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/distribution/Distribution.java b/subprojects/plugins/src/main/groovy/org/gradle/api/distribution/Distribution.java
index 2b63d98..701b78a 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/distribution/Distribution.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/distribution/Distribution.java
@@ -17,29 +17,33 @@
package org.gradle.api.distribution;
import org.gradle.api.Action;
-import org.gradle.api.Named;
import org.gradle.api.Incubating;
+import org.gradle.api.Named;
import org.gradle.api.file.CopySpec;
/**
* A distribution allow to bundle an application or a library including dependencies,sources...
- *
- * @author scogneau
*/
@Incubating
public interface Distribution extends Named {
+
/**
* The name of this distribution.
*/
String getName();
/**
- * Returns the baseName of the distribution. This is used in file names for the distribution.
+ * The baseName of the distribution, used in naming the distribution archives.
+ * <p>
+ * If the {@link #getName()} of this distribution is "{@code main}" this defaults to the project's name.
+ * Otherwise it is "{@code $project.name-$this.name}".
*/
String getBaseName();
/**
- * Set the baseName of the distribution. This is used in file names for the distribution.
+ * The baseName of the distribution.
+ * <p>
+ * Set to change the name of the distribution archives.
*/
void setBaseName(String baseName);
@@ -50,6 +54,20 @@ public interface Distribution extends Named {
/**
* Configures the contents of the distribution.
+ * <p>
+ * Can be used to configure the contents of the distribution:
+ * <pre autoTested=''>
+ * apply plugin: "distribution"
+ *
+ * distributions {
+ * main {
+ * contents {
+ * from "src/readme"
+ * }
+ * }
+ * }
+ * </pre>
+ * The DSL inside the {@code contents\{} } block is the same DSL used for Copy tasks.
*/
CopySpec contents(Action<? super CopySpec> action);
}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/distribution/internal/DefaultDistribution.java b/subprojects/plugins/src/main/groovy/org/gradle/api/distribution/internal/DefaultDistribution.java
index ead3990..bb3b1c8 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/distribution/internal/DefaultDistribution.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/distribution/internal/DefaultDistribution.java
@@ -18,22 +18,18 @@ package org.gradle.api.distribution.internal;
import org.gradle.api.Action;
import org.gradle.api.distribution.Distribution;
import org.gradle.api.file.CopySpec;
-import org.gradle.api.internal.file.FileResolver;
-import org.gradle.api.internal.file.copy.CopySpecImpl;
/**
* Allow user to declare a distribution.
- *
- * @author scogneau
*/
public class DefaultDistribution implements Distribution {
private final String name;
private String baseName;
private final CopySpec contents;
- public DefaultDistribution(String name, FileResolver fileResolver) {
+ public DefaultDistribution(String name, CopySpec contents) {
this.name = name;
- this.contents = new CopySpecImpl(fileResolver);
+ this.contents = contents;
}
public String getName() {
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/distribution/internal/DefaultDistributionContainer.java b/subprojects/plugins/src/main/groovy/org/gradle/api/distribution/internal/DefaultDistributionContainer.java
index 182d10e..e64fd83 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/distribution/internal/DefaultDistributionContainer.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/distribution/internal/DefaultDistributionContainer.java
@@ -18,23 +18,22 @@ package org.gradle.api.distribution.internal;
import org.gradle.api.distribution.Distribution;
import org.gradle.api.distribution.DistributionContainer;
import org.gradle.api.internal.AbstractNamedDomainObjectContainer;
-import org.gradle.api.internal.file.FileResolver;
+import org.gradle.api.internal.Actions;
+import org.gradle.api.internal.file.FileOperations;
import org.gradle.internal.reflect.Instantiator;
/**
* Default implementation for {@link org.gradle.api.distribution.DistributionContainer}
- *
- * @author scogneau
*/
public class DefaultDistributionContainer extends AbstractNamedDomainObjectContainer<Distribution> implements DistributionContainer {
- private final FileResolver fileResolver;
+ private final FileOperations fileOperations;
- public DefaultDistributionContainer(Class<Distribution> type, Instantiator instantiator, FileResolver fileResolver) {
+ public DefaultDistributionContainer(Class<Distribution> type, Instantiator instantiator, FileOperations fileOperations) {
super(type, instantiator);
- this.fileResolver = fileResolver;
+ this.fileOperations = fileOperations;
}
protected Distribution doCreate(String name) {
- return getInstantiator().newInstance(DefaultDistribution.class, name, fileResolver);
+ return getInstantiator().newInstance(DefaultDistribution.class, name, fileOperations.copySpec(Actions.doNothing()));
}
}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/distribution/plugins/DistributionPlugin.groovy b/subprojects/plugins/src/main/groovy/org/gradle/api/distribution/plugins/DistributionPlugin.groovy
index 208d9ee..d8b504e 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/distribution/plugins/DistributionPlugin.groovy
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/distribution/plugins/DistributionPlugin.groovy
@@ -21,80 +21,74 @@ import org.gradle.api.Incubating
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.distribution.Distribution
-import org.gradle.api.distribution.DistributionContainer
import org.gradle.api.distribution.internal.DefaultDistributionContainer
+import org.gradle.api.internal.file.FileOperations
+import org.gradle.api.plugins.BasePlugin
import org.gradle.api.tasks.Sync
-import org.gradle.api.tasks.bundling.Zip
-import org.gradle.api.tasks.bundling.Tar
import org.gradle.api.tasks.bundling.AbstractArchiveTask
+import org.gradle.api.tasks.bundling.Tar
+import org.gradle.api.tasks.bundling.Zip
import org.gradle.internal.reflect.Instantiator
import javax.inject.Inject
-import org.gradle.api.plugins.BasePlugin
/**
- * <p>A {@link Plugin} to package project as a distribution.</p>
- *
- * @author scogneau
- *
+ * Adds the ability to create distributions of the project.
*/
@Incubating
class DistributionPlugin implements Plugin<Project> {
- /**
- * Name of the main distribution
- */
- static final String MAIN_DISTRIBUTION_NAME = "main"
- static final String DISTRIBUTION_GROUP = "distribution"
- static final String TASK_DIST_ZIP_NAME = "distZip"
- static final String TASK_DIST_TAR_NAME = "distTar"
- static final String TASK_INSTALL_NAME = "installDist"
+ private static final String MAIN_DISTRIBUTION_NAME = "main"
+ private static final String DISTRIBUTION_GROUP = "distribution"
+ private static final String TASK_DIST_ZIP_NAME = "distZip"
+ private static final String TASK_DIST_TAR_NAME = "distTar"
+ private static final String TASK_INSTALL_NAME = "installDist"
- private DistributionContainer extension
- private Project project
- private Instantiator instantiator
+ private final Instantiator instantiator
+ private final FileOperations fileOperations
@Inject
- public DistributionPlugin(Instantiator instantiator) {
- this.instantiator = instantiator;
+ DistributionPlugin(Instantiator instantiator, FileOperations fileOperations) {
+ this.fileOperations = fileOperations
+ this.instantiator = instantiator
}
- public void apply(Project project) {
- this.project = project
+ void apply(Project project) {
project.plugins.apply(BasePlugin)
- addPluginExtension()
- }
- void addPluginExtension() {
- extension = project.extensions.create("distributions", DefaultDistributionContainer.class, Distribution.class, instantiator, project.fileResolver)
- extension.all { dist ->
+ def distributions = project.extensions.create("distributions", DefaultDistributionContainer, Distribution, instantiator, fileOperations)
+
+ // TODO - refactor this action out so it can be unit tested
+ distributions.all { dist ->
dist.baseName = dist.name == MAIN_DISTRIBUTION_NAME ? project.name : String.format("%s-%s", project.name, dist.name)
- dist.contents.from("src/${dist.name}/dist")
- addZipTask(dist)
- addTarTask(dist)
- addInstallTask(dist)
+ dist.contents.from("src/$dist.name/dist")
+
+ addZipTask(project, dist)
+ addTarTask(project, dist)
+ addInstallTask(project, dist)
}
- extension.create(DistributionPlugin.MAIN_DISTRIBUTION_NAME)
+
+ distributions.create(MAIN_DISTRIBUTION_NAME)
}
- void addZipTask(Distribution distribution) {
+ void addZipTask(Project project, Distribution distribution) {
def taskName = TASK_DIST_ZIP_NAME
- if (!MAIN_DISTRIBUTION_NAME.equals(distribution.name)) {
+ if (MAIN_DISTRIBUTION_NAME != distribution.name) {
taskName = distribution.name + "DistZip"
}
- configureArchiveTask(taskName, distribution, Zip)
+ configureArchiveTask(project, taskName, distribution, Zip)
}
- void addTarTask(Distribution distribution) {
+ void addTarTask(Project project, Distribution distribution) {
def taskName = TASK_DIST_TAR_NAME
- if (!MAIN_DISTRIBUTION_NAME.equals(distribution.name)) {
+ if (MAIN_DISTRIBUTION_NAME != distribution.name) {
taskName = distribution.name + "DistTar"
}
- configureArchiveTask(taskName, distribution, Tar)
+ configureArchiveTask(project, taskName, distribution, Tar)
}
- private <T extends AbstractArchiveTask> void configureArchiveTask(String taskName, Distribution distribution, Class<T> type) {
- def archiveTask = project.tasks.add(taskName, type)
+ private <T extends AbstractArchiveTask> void configureArchiveTask(Project project, String taskName, Distribution distribution, Class<T> type) {
+ def archiveTask = project.tasks.create(taskName, type)
archiveTask.description = "Bundles the project as a distribution."
archiveTask.group = DISTRIBUTION_GROUP
archiveTask.conventionMapping.baseName = {
@@ -109,12 +103,12 @@ class DistributionPlugin implements Plugin<Project> {
}
}
- private void addInstallTask(Distribution distribution) {
+ private void addInstallTask(Project project, Distribution distribution) {
def taskName = TASK_INSTALL_NAME
- if (!MAIN_DISTRIBUTION_NAME.equals(distribution.name)) {
+ if (MAIN_DISTRIBUTION_NAME != distribution.name) {
taskName = "install"+ distribution.name.capitalize() + "Dist"
}
- def installTask = project.tasks.add(taskName, Sync)
+ def installTask = project.tasks.create(taskName, Sync)
installTask.description = "Installs the project as a JVM application along with libs and OS specific scripts."
installTask.group = DISTRIBUTION_GROUP
installTask.with distribution.contents
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/java/WebApplication.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/java/WebApplication.java
index 55d1647..80cc86a 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/java/WebApplication.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/java/WebApplication.java
@@ -43,7 +43,7 @@ public class WebApplication implements SoftwareComponentInternal {
private class WebArchiveUsage implements Usage {
public String getName() {
- return "master"; // TODO:DAZ Maybe come up with a better name
+ return "master";
}
public Set<PublishArtifact> getArtifacts() {
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/plugins/BuildConfigurationRule.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/plugins/BuildConfigurationRule.java
index 6d2096c..ea4f9d9 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/plugins/BuildConfigurationRule.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/plugins/BuildConfigurationRule.java
@@ -44,7 +44,7 @@ public class BuildConfigurationRule extends AbstractRule {
Configuration configuration = configurations.findByName(configurationName);
if (configuration != null) {
- Task task = tasks.add(taskName);
+ Task task = tasks.create(taskName);
task.dependsOn(configuration.getAllArtifacts());
task.setDescription(String.format("Builds the artifacts belonging to %s.", configuration));
}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/plugins/CleanRule.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/plugins/CleanRule.java
index 66fcc30..4266b35 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/plugins/CleanRule.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/plugins/CleanRule.java
@@ -50,7 +50,7 @@ public class CleanRule extends AbstractRule {
return;
}
- Delete clean = tasks.add(taskName, Delete.class);
+ Delete clean = tasks.create(taskName, Delete.class);
clean.delete(task.getOutputs().getFiles());
}
}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/plugins/ProcessResources.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/plugins/ProcessResources.java
index 3cb258e..231957a 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/plugins/ProcessResources.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/plugins/ProcessResources.java
@@ -15,16 +15,11 @@
*/
package org.gradle.api.internal.plugins;
-import org.gradle.api.internal.tasks.compile.SimpleStaleClassCleaner;
-import org.gradle.api.internal.tasks.compile.StaleClassCleaner;
-import org.gradle.api.tasks.Copy;
-
-public class ProcessResources extends Copy {
- @Override
- protected void copy() {
- StaleClassCleaner cleaner = new SimpleStaleClassCleaner(getOutputs());
- cleaner.setDestinationDir(getDestinationDir());
- cleaner.execute();
- super.copy();
- }
-}
+/**
+ * Copies resources from their source to their target directory, potentially processing them.
+ * Makes sure no stale resources remain in the target directory.
+ *
+ * @deprecated use {@link org.gradle.language.jvm.tasks.ProcessResources} instead
+ */
+ at Deprecated
+public class ProcessResources extends org.gradle.language.jvm.tasks.ProcessResources {}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/plugins/StartScriptGenerator.groovy b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/plugins/StartScriptGenerator.groovy
index be5601f..c92810c 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/plugins/StartScriptGenerator.groovy
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/plugins/StartScriptGenerator.groovy
@@ -39,6 +39,8 @@ class StartScriptGenerator {
String mainClassName
+ Iterable<String> defaultJvmOpts = []
+
/**
* The classpath, relative to the application home directory.
*/
@@ -64,9 +66,22 @@ class StartScriptGenerator {
String generateUnixScriptContent() {
def unixClassPath = classpath.collect { "\$APP_HOME/${it.replace('\\', '/')}" }.join(":")
+ def quotedDefaultJvmOpts = defaultJvmOpts.collect{
+ //quote ', ", \, $. Probably not perfect. TODO: identify non-working cases, fail-fast on them
+ it = it.replace('\\', '\\\\')
+ it = it.replace('"', '\\"')
+ it = it.replace(/'/, /'"'"'/)
+ it = it.replace(/`/, /'"`"'/)
+ it = it.replace('$', '\\$')
+ (/"${it}"/)
+ }
+ //put the whole arguments string in single quotes, unless defaultJvmOpts was empty,
+ // in which case we output "" to stay compatible with existing builds that scan the script for it
+ def defaultJvmOptsString = (quotedDefaultJvmOpts ? /'${quotedDefaultJvmOpts.join(' ')}'/ : '""')
def binding = [applicationName: applicationName,
optsEnvironmentVar: optsEnvironmentVar,
mainClassName: mainClassName,
+ defaultJvmOpts: defaultJvmOptsString,
appNameSystemProperty: appNameSystemProperty,
appHomeRelativePath: appHomeRelativePath,
classpath: unixClassPath]
@@ -81,10 +96,32 @@ class StartScriptGenerator {
String generateWindowsScriptContent() {
def windowsClassPath = classpath.collect { "%APP_HOME%\\${it.replace('/', '\\')}" }.join(";")
def appHome = appHomeRelativePath.replace('/', '\\')
+ //argument quoting:
+ // - " must be encoded as \"
+ // - % must be encoded as %%
+ // - pathological case: \" must be encoded as \\\", but other than that, \ MUST NOT be quoted
+ // - other characters (including ') will not be quoted
+ // - use a state machine rather than regexps
+ def quotedDefaultJvmOpts = defaultJvmOpts.collect {
+ def wasOnBackslash = false
+ it = it.collect { ch ->
+ def repl = ch
+ if (ch == '%') {
+ repl = '%%'
+ } else if (ch == '"') {
+ repl = (wasOnBackslash ? '\\' : '') + '\\"'
+ }
+ wasOnBackslash = (ch == '\\')
+ repl
+ }
+ (/"${it.join()}"/)
+ }
+ def defaultJvmOptsString = quotedDefaultJvmOpts.join(' ')
def binding = [applicationName: applicationName,
optsEnvironmentVar: optsEnvironmentVar,
exitEnvironmentVar: exitEnvironmentVar,
mainClassName: mainClassName,
+ defaultJvmOpts: defaultJvmOptsString,
appNameSystemProperty: appNameSystemProperty,
appHomeRelativePath: appHome,
classpath: windowsClassPath]
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/plugins/UploadRule.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/plugins/UploadRule.java
index 676b24e..242152a 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/plugins/UploadRule.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/plugins/UploadRule.java
@@ -47,7 +47,7 @@ public class UploadRule extends AbstractRule {
}
private Upload createUploadTask(String name, final Configuration configuration, final Project project) {
- Upload upload = project.getTasks().add(name, Upload.class);
+ Upload upload = project.getTasks().create(name, Upload.class);
upload.setDescription(String.format("Uploads all artifacts belonging to %s", configuration));
upload.setGroup(BasePlugin.UPLOAD_GROUP);
upload.setConfiguration(configuration);
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/DefaultBinariesContainer.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/DefaultBinariesContainer.java
deleted file mode 100644
index 45f690a..0000000
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/DefaultBinariesContainer.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2013 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.tasks;
-
-import org.gradle.api.Named;
-import org.gradle.api.internal.DefaultNamedDomainObjectSet;
-import org.gradle.api.tasks.BinariesContainer;
-import org.gradle.internal.reflect.Instantiator;
-
-public class DefaultBinariesContainer extends DefaultNamedDomainObjectSet<Named> implements BinariesContainer {
- public DefaultBinariesContainer(Instantiator instantiator) {
- super(Named.class, instantiator);
- }
-}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/DefaultClassDirectoryBinary.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/DefaultClassDirectoryBinary.java
deleted file mode 100644
index 6090b1c..0000000
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/DefaultClassDirectoryBinary.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright 2013 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.tasks;
-
-import org.apache.commons.lang.StringUtils;
-import org.gradle.api.DomainObjectCollection;
-import org.gradle.api.Nullable;
-import org.gradle.api.Task;
-import org.gradle.api.internal.DefaultDomainObjectSet;
-import org.gradle.api.tasks.*;
-import org.gradle.api.tasks.compile.AbstractCompile;
-import org.gradle.util.GUtil;
-
-import java.io.File;
-
-public class DefaultClassDirectoryBinary implements ClassDirectoryBinary {
- private final String name;
- private File classesDir;
- private File resourcesDir;
- private final DomainObjectCollection<LanguageSourceSet> source = new DefaultDomainObjectSet<LanguageSourceSet>(LanguageSourceSet.class);
- private Task classesTask;
- private Copy resourcesTask;
- private AbstractCompile compileTask;
-
- public DefaultClassDirectoryBinary(String name) {
- this.name = name;
- }
-
- public String getName() {
- return name;
- }
-
- public File getClassesDir() {
- return classesDir;
- }
-
- public void setClassesDir(File classesDir) {
- this.classesDir = classesDir;
- }
-
- public File getResourcesDir() {
- return resourcesDir;
- }
-
- public void setResourcesDir(File resourcesDir) {
- this.resourcesDir = resourcesDir;
- }
-
- public DomainObjectCollection<LanguageSourceSet> getSource() {
- return source;
- }
-
- public TaskDependency getBuildDependencies() {
- return null; //TODO
- }
-
- public Task getClassesTask() {
- return classesTask;
- }
-
- public void setClassesTask(Task classesTask) {
- this.classesTask = classesTask;
- }
-
- @Nullable
- public Copy getResourcesTask() {
- return resourcesTask;
- }
-
- public void setResourcesTask(Copy resourcesTask) {
- this.resourcesTask = resourcesTask;
- }
-
- @Nullable
- public AbstractCompile getCompileTask() {
- return compileTask;
- }
-
- public void setCompileTask(AbstractCompile compileTask) {
- this.compileTask = compileTask;
- }
-
- public String getTaskName(@Nullable String verb, @Nullable String target) {
- if (verb == null) {
- return StringUtils.uncapitalize(String.format("%s%s", getTaskBaseName(), StringUtils.capitalize(target)));
- }
- if (target == null) {
- return StringUtils.uncapitalize(String.format("%s%s", verb, GUtil.toCamelCase(name)));
- }
- return StringUtils.uncapitalize(String.format("%s%s%s", verb, getTaskBaseName(), StringUtils.capitalize(target)));
- }
-
- public String getTaskBaseName() {
- return name.equals("main") ? "" : GUtil.toCamelCase(name);
- }
-}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/DefaultClasspath.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/DefaultClasspath.java
deleted file mode 100644
index 44e0fb8..0000000
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/DefaultClasspath.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 2013 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.tasks;
-
-import org.gradle.api.file.FileCollection;
-import org.gradle.api.internal.file.FileResolver;
-import org.gradle.api.internal.file.collections.DefaultConfigurableFileCollection;
-import org.gradle.api.tasks.Classpath;
-import org.gradle.api.tasks.TaskDependency;
-
-public class DefaultClasspath implements Classpath {
- private final FileCollection files;
-
- public DefaultClasspath(FileResolver fileResolver, TaskResolver taskResolver) {
- files = new DefaultConfigurableFileCollection(fileResolver, taskResolver);
- }
-
- public FileCollection getFiles() {
- return files;
- }
-
- public TaskDependency getBuildDependencies() {
- return files.getBuildDependencies();
- }
-}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/DefaultFunctionalSourceSet.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/DefaultFunctionalSourceSet.java
deleted file mode 100644
index 08fcbbe..0000000
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/DefaultFunctionalSourceSet.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2013 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.tasks;
-
-import org.gradle.api.tasks.FunctionalSourceSet;
-import org.gradle.api.tasks.LanguageSourceSet;
-import org.gradle.api.internal.DefaultPolymorphicDomainObjectContainer;
-import org.gradle.internal.reflect.Instantiator;
-
-public class DefaultFunctionalSourceSet extends DefaultPolymorphicDomainObjectContainer<LanguageSourceSet> implements FunctionalSourceSet {
- private final String name;
-
- public DefaultFunctionalSourceSet(String name, Instantiator instantiator) {
- super(LanguageSourceSet.class, instantiator);
- this.name = name;
- }
-
- public String getName() {
- return name;
- }
-}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/DefaultJavaSourceSet.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/DefaultJavaSourceSet.java
deleted file mode 100644
index baf13a9..0000000
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/DefaultJavaSourceSet.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright 2013 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.tasks;
-
-import org.gradle.api.Task;
-import org.gradle.api.file.SourceDirectorySet;
-import org.gradle.api.tasks.Classpath;
-import org.gradle.api.tasks.FunctionalSourceSet;
-import org.gradle.api.tasks.JavaSourceSet;
-import org.gradle.api.tasks.TaskDependency;
-
-import java.util.HashSet;
-import java.util.Set;
-
-public class DefaultJavaSourceSet implements JavaSourceSet {
- private final String name;
- private final SourceDirectorySet source;
- private final Classpath compileClasspath;
- private final FunctionalSourceSet parent;
-
- public DefaultJavaSourceSet(String name, SourceDirectorySet source, Classpath compileClasspath, FunctionalSourceSet parent) {
- this.name = name;
- this.source = source;
- this.compileClasspath = compileClasspath;
- this.parent = parent;
- }
-
- public Classpath getCompileClasspath() {
- return compileClasspath;
- }
-
- public SourceDirectorySet getSource() {
- return source;
- }
-
- public FunctionalSourceSet getParent() {
- return parent;
- }
-
- public TaskDependency getBuildDependencies() {
- return new TaskDependency() {
- public Set<? extends Task> getDependencies(Task task) {
- Set<Task> dependencies = new HashSet<Task>();
- dependencies.addAll(compileClasspath.getBuildDependencies().getDependencies(task));
- dependencies.addAll(source.getBuildDependencies().getDependencies(task));
- return dependencies;
- }
- };
- }
-
- public String getName() {
- return name;
- }
-
-
- public String toString() {
- return String.format("%s/%s source set", parent.getName(), name);
- }
-}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/DefaultJvmBinaryContainer.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/DefaultJvmBinaryContainer.java
deleted file mode 100644
index bc51285..0000000
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/DefaultJvmBinaryContainer.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2013 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.tasks;
-
-import org.gradle.api.internal.DefaultPolymorphicDomainObjectContainer;
-import org.gradle.api.tasks.ClassDirectoryBinary;
-import org.gradle.api.tasks.JvmBinaryContainer;
-import org.gradle.internal.reflect.Instantiator;
-
-public class DefaultJvmBinaryContainer extends DefaultPolymorphicDomainObjectContainer<ClassDirectoryBinary> implements JvmBinaryContainer {
- public DefaultJvmBinaryContainer(Instantiator instantiator) {
- super(ClassDirectoryBinary.class, instantiator);
- }
-
- public String getName() {
- return "jvm";
- }
-
- @Override
- protected ClassDirectoryBinary doCreate(String name) {
- return getInstantiator().newInstance(DefaultClassDirectoryBinary.class, name);
- }
-}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/DefaultProjectSourceSet.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/DefaultProjectSourceSet.java
deleted file mode 100644
index a340827..0000000
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/DefaultProjectSourceSet.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2013 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.tasks;
-
-import org.gradle.api.internal.AbstractNamedDomainObjectContainer;
-import org.gradle.api.tasks.FunctionalSourceSet;
-import org.gradle.api.tasks.ProjectSourceSet;
-import org.gradle.internal.reflect.Instantiator;
-
-public class DefaultProjectSourceSet extends AbstractNamedDomainObjectContainer<FunctionalSourceSet> implements ProjectSourceSet {
- public DefaultProjectSourceSet(Instantiator instantiator) {
- super(FunctionalSourceSet.class, instantiator);
- }
-
- @Override
- protected FunctionalSourceSet doCreate(String name) {
- return getInstantiator().newInstance(DefaultFunctionalSourceSet.class, name, getInstantiator());
- }
-}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/DefaultResourceSet.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/DefaultResourceSet.java
deleted file mode 100644
index 912f623..0000000
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/DefaultResourceSet.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2013 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.tasks;
-
-import org.gradle.api.file.SourceDirectorySet;
-import org.gradle.api.tasks.FunctionalSourceSet;
-import org.gradle.api.tasks.ResourceSet;
-import org.gradle.api.tasks.TaskDependency;
-
-public class DefaultResourceSet implements ResourceSet {
- private final String name;
- private final SourceDirectorySet source;
- private final FunctionalSourceSet parent;
-
- public DefaultResourceSet(String name, SourceDirectorySet source, FunctionalSourceSet parent) {
- this.name = name;
- this.source = source;
- this.parent = parent;
- }
-
- public SourceDirectorySet getSource() {
- return source;
- }
-
- public FunctionalSourceSet getParent() {
- return parent;
- }
-
- public TaskDependency getBuildDependencies() {
- return source.getBuildDependencies();
- }
-
- public String getName() {
- return name;
- }
-
- public String toString() {
- return String.format("%s/%s source set", parent.getName(), name);
- }
-}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/DefaultSourceSet.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/DefaultSourceSet.java
index ef423c4..fcf78ed 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/DefaultSourceSet.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/DefaultSourceSet.java
@@ -73,7 +73,7 @@ public class DefaultSourceSet implements SourceSet {
@Override
public String toString() {
- return String.format("source set %s", getDisplayName());
+ return String.format("source set '%s'", getDisplayName());
}
public String getDisplayName() {
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/DefaultSourceSetContainer.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/DefaultSourceSetContainer.java
index 0c3b012..f120e1d 100755
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/DefaultSourceSetContainer.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/DefaultSourceSetContainer.java
@@ -22,6 +22,7 @@ import org.gradle.internal.reflect.Instantiator;
import org.gradle.api.internal.file.FileResolver;
import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.SourceSetContainer;
+import org.gradle.util.DeprecationLogger;
public class DefaultSourceSetContainer extends AbstractNamedDomainObjectContainer<SourceSet> implements SourceSetContainer {
private final FileResolver fileResolver;
@@ -44,10 +45,12 @@ public class DefaultSourceSetContainer extends AbstractNamedDomainObjectContaine
}
public SourceSet add(String name) {
+ DeprecationLogger.nagUserOfReplacedMethod("SourceSetContainer.add()", "create()");
return create(name);
}
public SourceSet add(String name, Closure closure) {
+ DeprecationLogger.nagUserOfReplacedMethod("SourceSetContainer.add()", "create()");
return create(name, closure);
}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/DefaultSourceSetOutput.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/DefaultSourceSetOutput.java
index 722326e..300947b 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/DefaultSourceSetOutput.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/DefaultSourceSetOutput.java
@@ -29,9 +29,6 @@ import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;
-/**
- * @author: Szczepan Faber, created at: 5/4/11
- */
public class DefaultSourceSetOutput extends CompositeFileCollection implements SourceSetOutput {
private DefaultConfigurableFileCollection outputDirectories;
private Object classesDir;
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/SourceSetCompileClasspath.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/SourceSetCompileClasspath.java
index 323f9c6..6f4176d 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/SourceSetCompileClasspath.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/SourceSetCompileClasspath.java
@@ -17,11 +17,12 @@ package org.gradle.api.internal.tasks;
import org.gradle.api.file.FileCollection;
import org.gradle.api.tasks.*;
+import org.gradle.language.jvm.Classpath;
public class SourceSetCompileClasspath implements Classpath {
- private final org.gradle.api.tasks.SourceSet sourceSet;
+ private final SourceSet sourceSet;
- public SourceSetCompileClasspath(org.gradle.api.tasks.SourceSet sourceSet) {
+ public SourceSetCompileClasspath(SourceSet sourceSet) {
this.sourceSet = sourceSet;
}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/AntDependsStaleClassCleaner.groovy b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/AntDependsStaleClassCleaner.groovy
index e71588e..562e407 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/AntDependsStaleClassCleaner.groovy
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/AntDependsStaleClassCleaner.groovy
@@ -17,15 +17,19 @@ package org.gradle.api.internal.tasks.compile
import org.gradle.api.AntBuilder
import org.gradle.api.file.FileCollection
+import org.gradle.api.tasks.compile.CompileOptions
import org.gradle.internal.Factory
+import org.gradle.language.jvm.internal.StaleClassCleaner
class AntDependsStaleClassCleaner extends StaleClassCleaner {
private final Factory<AntBuilder> antBuilderFactory
+ private final CompileOptions compileOptions
File dependencyCacheDir
- AntDependsStaleClassCleaner(Factory<AntBuilder> antBuilderFactory) {
+ AntDependsStaleClassCleaner(Factory<AntBuilder> antBuilderFactory, CompileOptions compileOptions) {
this.antBuilderFactory = antBuilderFactory;
+ this.compileOptions = compileOptions;
}
void execute() {
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/AntGroovyCompiler.groovy b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/AntGroovyCompiler.groovy
index 062e4c2..93a34f1 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/AntGroovyCompiler.groovy
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/AntGroovyCompiler.groovy
@@ -27,8 +27,6 @@ import org.gradle.util.VersionNumber
* Please note: includeAntRuntime=false is ignored if groovyc is used in non fork mode. In this case the runtime classpath is
* added to the compile classpath.
* See: http://jira.codehaus.org/browse/GROOVY-2717
- *
- * @author Hans Dockter
*/
class AntGroovyCompiler implements org.gradle.api.internal.tasks.compile.Compiler<GroovyJavaJointCompileSpec> {
private final IsolatedAntBuilder ant
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/AntJavaCompiler.groovy b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/AntJavaCompiler.groovy
index 213363d..0b02045 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/AntJavaCompiler.groovy
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/AntJavaCompiler.groovy
@@ -20,12 +20,10 @@ import org.gradle.api.AntBuilder
import org.gradle.api.file.FileCollection
import org.gradle.api.tasks.WorkResult
import org.gradle.internal.Factory
+import org.gradle.internal.jvm.Jvm
import org.slf4j.Logger
import org.slf4j.LoggerFactory
-/**
- * @author Hans Dockter
- */
class AntJavaCompiler implements org.gradle.api.internal.tasks.compile.Compiler<JavaCompileSpec> {
private static final Logger LOGGER = LoggerFactory.getLogger(AntJavaCompiler)
private static final String CLASSPATH_ID = 'compile.classpath'
@@ -48,6 +46,9 @@ class AntJavaCompiler implements org.gradle.api.internal.tasks.compile.Compiler<
target: spec.targetCompatibility,
source: spec.sourceCompatibility
]
+ if (spec.compileOptions.fork && !spec.compileOptions.forkOptions.executable) {
+ spec.compileOptions.forkOptions.executable = Jvm.current().javacExecutable
+ }
Map options = otherArgs + spec.compileOptions.optionMap()
LOGGER.info("Compiling with Ant javac task.")
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/ApiGroovyCompiler.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/ApiGroovyCompiler.java
index e91b72b..2ee42fd 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/ApiGroovyCompiler.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/ApiGroovyCompiler.java
@@ -23,10 +23,11 @@ import org.codehaus.groovy.control.CompilerConfiguration;
import org.codehaus.groovy.control.messages.SimpleMessage;
import org.codehaus.groovy.tools.javac.JavaAwareCompilationUnit;
import org.codehaus.groovy.tools.javac.JavaCompiler;
+import org.gradle.api.internal.tasks.SimpleWorkResult;
import org.gradle.api.specs.Spec;
import org.gradle.api.tasks.WorkResult;
import org.gradle.internal.classpath.DefaultClassPath;
-import org.gradle.util.FilteringClassLoader;
+import org.gradle.internal.classloader.FilteringClassLoader;
import java.io.File;
import java.io.Serializable;
@@ -65,7 +66,7 @@ public class ApiGroovyCompiler implements Compiler<GroovyJavaJointCompileSpec>,
// would end up on the compile class path of every compile task for that source set, which may not be desirable.
spec.setClasspath(Iterables.concat(spec.getClasspath(), Collections.singleton(spec.getDestinationDir())));
- URLClassLoader classPathLoader = new TransformingClassLoader(new DefaultClassPath(spec.getClasspath()));
+ URLClassLoader classPathLoader = new GroovyCompileTransformingClassLoader(new DefaultClassPath(spec.getClasspath()));
GroovyClassLoader compileClasspathClassLoader = new GroovyClassLoader(classPathLoader, null);
FilteringClassLoader groovyCompilerClassLoader = new FilteringClassLoader(GroovyClassLoader.class.getClassLoader());
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/ArgCollector.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/ArgCollector.java
index 47e0c3a..a630b63 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/ArgCollector.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/ArgCollector.java
@@ -20,4 +20,6 @@ public interface ArgCollector {
ArgCollector args(Object... args);
+ ArgCollector args(Iterable<?> args);
+
}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/ArgWriter.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/ArgWriter.java
index 6fb66a0..6d901cf 100755
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/ArgWriter.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/ArgWriter.java
@@ -79,4 +79,11 @@ public class ArgWriter implements ArgCollector {
writer.println();
return this;
}
+
+ public ArgCollector args(Iterable<?> args) {
+ for (Object arg : args) {
+ args(arg);
+ }
+ return this;
+ }
}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/CommandLineJavaCompiler.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/CommandLineJavaCompiler.java
index 5ee946e..a974bbb 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/CommandLineJavaCompiler.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/CommandLineJavaCompiler.java
@@ -17,6 +17,7 @@
package org.gradle.api.internal.tasks.compile;
import org.gradle.api.internal.file.TemporaryFileProvider;
+import org.gradle.api.internal.tasks.SimpleWorkResult;
import org.gradle.api.tasks.WorkResult;
import org.gradle.process.ExecResult;
import org.gradle.process.internal.ExecHandle;
@@ -25,11 +26,12 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
+import java.io.Serializable;
/**
* Executes the Java command line compiler specified in {@code JavaCompileSpec.forkOptions.getExecutable()}.
*/
-public class CommandLineJavaCompiler implements Compiler<JavaCompileSpec> {
+public class CommandLineJavaCompiler implements Compiler<JavaCompileSpec>, Serializable {
private static final Logger LOGGER = LoggerFactory.getLogger(CommandLineJavaCompiler.class);
private final CompileSpecToArguments<JavaCompileSpec> argumentsGenerator;
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/CommandLineJavaCompilerArgumentsGenerator.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/CommandLineJavaCompilerArgumentsGenerator.java
index 7146cf3..6b554fb 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/CommandLineJavaCompilerArgumentsGenerator.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/CommandLineJavaCompilerArgumentsGenerator.java
@@ -20,14 +20,11 @@ import com.google.common.collect.Iterables;
import org.gradle.api.UncheckedIOException;
import org.gradle.api.internal.file.TemporaryFileProvider;
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.PrintWriter;
+import java.io.*;
import java.util.Collections;
import java.util.List;
-public class CommandLineJavaCompilerArgumentsGenerator implements CompileSpecToArguments<JavaCompileSpec> {
+public class CommandLineJavaCompilerArgumentsGenerator implements CompileSpecToArguments<JavaCompileSpec>, Serializable {
private final TemporaryFileProvider tempFileProvider;
public CommandLineJavaCompilerArgumentsGenerator(TemporaryFileProvider tempFileProvider) {
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/DefaultJavaCompilerFactory.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/DefaultJavaCompilerFactory.java
index 4fc2368..5938f13 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/DefaultJavaCompilerFactory.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/DefaultJavaCompilerFactory.java
@@ -16,6 +16,7 @@
package org.gradle.api.internal.tasks.compile;
import org.gradle.api.AntBuilder;
+import org.gradle.api.internal.file.DefaultTemporaryFileProvider;
import org.gradle.api.internal.file.TemporaryFileProvider;
import org.gradle.api.internal.project.ProjectInternal;
import org.gradle.api.internal.tasks.compile.daemon.DaemonJavaCompiler;
@@ -24,18 +25,19 @@ import org.gradle.api.logging.Logging;
import org.gradle.api.tasks.compile.CompileOptions;
import org.gradle.internal.Factory;
+import java.io.File;
+import java.io.Serializable;
+
public class DefaultJavaCompilerFactory implements JavaCompilerFactory {
private final static Logger LOGGER = Logging.getLogger(DefaultJavaCompilerFactory.class);
private final ProjectInternal project;
- private final TemporaryFileProvider tempFileProvider;
private final Factory<AntBuilder> antBuilderFactory;
private final JavaCompilerFactory inProcessCompilerFactory;
private boolean jointCompilation;
- public DefaultJavaCompilerFactory(ProjectInternal project, TemporaryFileProvider tempFileProvider, Factory<AntBuilder> antBuilderFactory, JavaCompilerFactory inProcessCompilerFactory){
+ public DefaultJavaCompilerFactory(ProjectInternal project, Factory<AntBuilder> antBuilderFactory, JavaCompilerFactory inProcessCompilerFactory){
this.project = project;
- this.tempFileProvider = tempFileProvider;
this.antBuilderFactory = antBuilderFactory;
this.inProcessCompilerFactory = inProcessCompilerFactory;
}
@@ -74,7 +76,7 @@ public class DefaultJavaCompilerFactory implements JavaCompilerFactory {
private Compiler<JavaCompileSpec> createTargetCompiler(CompileOptions options) {
if (options.isFork() && options.getForkOptions().getExecutable() != null) {
- return new CommandLineJavaCompiler(tempFileProvider, project.getProjectDir());
+ return new CommandLineJavaCompiler(createSerializableTempFileProvider(), project.getProjectDir());
}
Compiler<JavaCompileSpec> compiler = inProcessCompilerFactory.create(options);
@@ -84,4 +86,20 @@ public class DefaultJavaCompilerFactory implements JavaCompilerFactory {
return compiler;
}
+
+ private TemporaryFileProvider createSerializableTempFileProvider() {
+ return new DefaultTemporaryFileProvider(new FileFactory(project.getBuildDir()));
+ }
+
+ private static class FileFactory implements Factory<File>, Serializable {
+ private final File file;
+
+ private FileFactory(File file) {
+ this.file = file;
+ }
+
+ public File create() {
+ return file;
+ }
+ }
}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/ExecSpecBackedArgCollector.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/ExecSpecBackedArgCollector.java
index c54832e..961f9ea 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/ExecSpecBackedArgCollector.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/ExecSpecBackedArgCollector.java
@@ -29,4 +29,9 @@ public class ExecSpecBackedArgCollector implements ArgCollector {
action.args(args);
return this;
}
+
+ public ArgCollector args(Iterable<?> args) {
+ action.args(args);
+ return this;
+ }
}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/GroovyCompileTransformingClassLoader.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/GroovyCompileTransformingClassLoader.java
new file mode 100644
index 0000000..8f9a13b
--- /dev/null
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/GroovyCompileTransformingClassLoader.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.tasks.compile;
+
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+import org.gradle.internal.classloader.TransformingClassLoader;
+import org.gradle.internal.classpath.ClassPath;
+import org.objectweb.asm.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Transforms @GroovyASTTransformationClass(classes = {classLiterals}) into @GroovyASTTransformationClass([classNames]),
+ * to work around GROOVY-5416.
+ */
+class GroovyCompileTransformingClassLoader extends TransformingClassLoader {
+ private static final String ANNOTATION_DESCRIPTOR = Type.getType(GroovyASTTransformationClass.class).getDescriptor();
+
+ public GroovyCompileTransformingClassLoader(ClassPath classpath) {
+ super(null, classpath);
+ }
+
+ @Override
+ protected byte[] transform(byte[] bytes) {
+ // First scan for annotation, and short circuit transformation if not present
+ ClassReader classReader = new ClassReader(bytes);
+
+ AnnotationDetector detector = new AnnotationDetector();
+ classReader.accept(detector, ClassReader.SKIP_DEBUG | ClassReader.SKIP_CODE);
+ if (!detector.found) {
+ return bytes;
+ }
+
+ ClassWriter classWriter = new ClassWriter(0);
+ classReader.accept(new TransformingAdapter(classWriter), 0);
+ bytes = classWriter.toByteArray();
+ return bytes;
+ }
+
+ private static class AnnotationDetector extends ClassVisitor {
+ private boolean found;
+
+ private AnnotationDetector() {
+ super(Opcodes.ASM4);
+ }
+
+ public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+ if (desc.equals(ANNOTATION_DESCRIPTOR)) {
+ found = true;
+ }
+ return null;
+ }
+ }
+
+ private static class TransformingAdapter extends ClassVisitor {
+ public TransformingAdapter(ClassWriter classWriter) {
+ super(Opcodes.ASM4, classWriter);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+ if (desc.equals(ANNOTATION_DESCRIPTOR)) {
+ return new AnnotationTransformingVisitor(super.visitAnnotation(desc, visible));
+ }
+ return super.visitAnnotation(desc, visible);
+ }
+
+ private static class AnnotationTransformingVisitor extends AnnotationVisitor {
+ private final List<String> names = new ArrayList<String>();
+
+ public AnnotationTransformingVisitor(AnnotationVisitor annotationVisitor) {
+ super(Opcodes.ASM4, annotationVisitor);
+ }
+
+ public AnnotationVisitor visitArray(String name) {
+ if (name.equals("classes")) {
+ return new AnnotationVisitor(Opcodes.ASM4){
+ @Override
+ public void visit(String name, Object value) {
+ Type type = (Type) value;
+ names.add(type.getClassName());
+ }
+ };
+ } else if (name.equals("value")) {
+ return new AnnotationVisitor(Opcodes.ASM4) {
+ @Override
+ public void visit(String name, Object value) {
+ String type = (String) value;
+ names.add(type);
+ }
+ };
+ } else {
+ return super.visitArray(name);
+ }
+ }
+
+ public void visitEnd() {
+ if (!names.isEmpty()) {
+ AnnotationVisitor visitor = super.visitArray("value");
+ for (String name : names) {
+ visitor.visit(null, name);
+ }
+ visitor.visitEnd();
+ }
+ super.visitEnd();
+ }
+ }
+ }
+}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/InProcessJavaCompilerFactory.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/InProcessJavaCompilerFactory.java
index 556e890..b91b6df 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/InProcessJavaCompilerFactory.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/InProcessJavaCompilerFactory.java
@@ -18,10 +18,10 @@ package org.gradle.api.internal.tasks.compile;
import org.gradle.api.GradleException;
import org.gradle.api.JavaVersion;
import org.gradle.api.tasks.compile.CompileOptions;
-import org.gradle.util.ReflectionUtil;
+import org.gradle.internal.reflect.JavaReflectionUtil;
public class InProcessJavaCompilerFactory implements JavaCompilerFactory {
- private static final boolean SUN_COMPILER_AVAILABLE = ReflectionUtil.isClassAvailable("com.sun.tools.javac.Main");
+ private static final boolean SUN_COMPILER_AVAILABLE = JavaReflectionUtil.isClassAvailable("com.sun.tools.javac.Main");
public Compiler<JavaCompileSpec> create(CompileOptions options) {
if (JavaVersion.current().isJava6Compatible()) {
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/IncrementalGroovyCompiler.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/IncrementalGroovyCompiler.java
index 01eafc9..42cb04b 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/IncrementalGroovyCompiler.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/IncrementalGroovyCompiler.java
@@ -16,6 +16,8 @@
package org.gradle.api.internal.tasks.compile;
import org.gradle.api.internal.TaskOutputsInternal;
+import org.gradle.language.jvm.internal.SimpleStaleClassCleaner;
+import org.gradle.language.jvm.internal.StaleClassCleaner;
public class IncrementalGroovyCompiler extends IncrementalJavaCompilerSupport<GroovyJavaJointCompileSpec> {
private final Compiler<GroovyJavaJointCompileSpec> compiler;
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/IncrementalJavaCompiler.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/IncrementalJavaCompiler.java
index 2e40c72..cefee79 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/IncrementalJavaCompiler.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/IncrementalJavaCompiler.java
@@ -18,6 +18,8 @@ package org.gradle.api.internal.tasks.compile;
import org.gradle.api.AntBuilder;
import org.gradle.internal.Factory;
import org.gradle.api.internal.TaskOutputsInternal;
+import org.gradle.language.jvm.internal.SimpleStaleClassCleaner;
+import org.gradle.language.jvm.internal.StaleClassCleaner;
public class IncrementalJavaCompiler extends IncrementalJavaCompilerSupport<JavaCompileSpec> implements Compiler<JavaCompileSpec> {
private final Compiler<JavaCompileSpec> compiler;
@@ -38,7 +40,7 @@ public class IncrementalJavaCompiler extends IncrementalJavaCompilerSupport<Java
protected StaleClassCleaner createCleaner(JavaCompileSpec spec) {
if (spec.getCompileOptions().isUseDepend()) {
- AntDependsStaleClassCleaner cleaner = new AntDependsStaleClassCleaner(antBuilderFactory);
+ AntDependsStaleClassCleaner cleaner = new AntDependsStaleClassCleaner(antBuilderFactory, spec.getCompileOptions());
cleaner.setDependencyCacheDir(spec.getDependencyCacheDir());
return cleaner;
} else {
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/IncrementalJavaCompilerSupport.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/IncrementalJavaCompilerSupport.java
index 90cecb3..ec5169a 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/IncrementalJavaCompilerSupport.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/IncrementalJavaCompilerSupport.java
@@ -16,6 +16,7 @@
package org.gradle.api.internal.tasks.compile;
import org.gradle.api.tasks.WorkResult;
+import org.gradle.language.jvm.internal.StaleClassCleaner;
/**
* A dumb incremental compiler. Deletes stale classes before invoking the actual compiler
@@ -26,7 +27,6 @@ public abstract class IncrementalJavaCompilerSupport<T extends JavaCompileSpec>
cleaner.setDestinationDir(spec.getDestinationDir());
cleaner.setSource(spec.getSource());
- cleaner.setCompileOptions(spec.getCompileOptions());
cleaner.execute();
Compiler<? super T> compiler = getCompiler();
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/NoOpStaleClassCleaner.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/NoOpStaleClassCleaner.java
index 0e91abd..d20b0b1 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/NoOpStaleClassCleaner.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/NoOpStaleClassCleaner.java
@@ -16,6 +16,8 @@
package org.gradle.api.internal.tasks.compile;
+import org.gradle.language.jvm.internal.StaleClassCleaner;
+
public class NoOpStaleClassCleaner extends StaleClassCleaner {
@Override
public void execute() {
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/NormalizingGroovyCompiler.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/NormalizingGroovyCompiler.java
index 57e5d6b..ab744b1 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/NormalizingGroovyCompiler.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/NormalizingGroovyCompiler.java
@@ -19,6 +19,7 @@ import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import org.gradle.api.file.FileCollection;
import org.gradle.api.internal.file.collections.SimpleFileCollection;
+import org.gradle.api.internal.tasks.SimpleWorkResult;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
import org.gradle.api.specs.Spec;
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/NormalizingJavaCompiler.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/NormalizingJavaCompiler.java
index 21fdb2b..cfcc8f9 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/NormalizingJavaCompiler.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/NormalizingJavaCompiler.java
@@ -19,6 +19,7 @@ import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import org.gradle.api.file.FileCollection;
import org.gradle.api.internal.file.collections.SimpleFileCollection;
+import org.gradle.api.internal.tasks.SimpleWorkResult;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
import org.gradle.api.specs.Spec;
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/SimpleStaleClassCleaner.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/SimpleStaleClassCleaner.java
deleted file mode 100644
index 82e3554..0000000
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/SimpleStaleClassCleaner.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.tasks.compile;
-
-import org.gradle.api.internal.TaskOutputsInternal;
-
-import java.io.File;
-
-public class SimpleStaleClassCleaner extends StaleClassCleaner {
- private final TaskOutputsInternal taskOutputs;
-
- public SimpleStaleClassCleaner(TaskOutputsInternal taskOutputs) {
- this.taskOutputs = taskOutputs;
- }
-
- @Override
- public void execute() {
- String prefix = getDestinationDir().getAbsolutePath() + File.separator;
- for (File f : taskOutputs.getPreviousFiles()) {
- if (f.getAbsolutePath().startsWith(prefix)) {
- f.delete();
- }
- }
- }
-}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/SimpleWorkResult.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/SimpleWorkResult.java
deleted file mode 100644
index c1a8993..0000000
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/SimpleWorkResult.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.tasks.compile;
-
-import org.gradle.api.tasks.WorkResult;
-
-public class SimpleWorkResult implements WorkResult {
- private final boolean didWork;
-
- public SimpleWorkResult(boolean didWork) {
- this.didWork = didWork;
- }
-
- public boolean getDidWork() {
- return didWork;
- }
-}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/StaleClassCleaner.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/StaleClassCleaner.java
deleted file mode 100644
index 688f374..0000000
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/StaleClassCleaner.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.tasks.compile;
-
-import org.gradle.api.file.FileCollection;
-import org.gradle.api.tasks.compile.CompileOptions;
-
-import java.io.File;
-
-public abstract class StaleClassCleaner {
- private File destinationDir;
- CompileOptions compileOptions;
- FileCollection source;
-
- public abstract void execute();
-
- public CompileOptions getCompileOptions() {
- return compileOptions;
- }
-
- public void setCompileOptions(CompileOptions compileOptions) {
- this.compileOptions = compileOptions;
- }
-
- public FileCollection getSource() {
- return source;
- }
-
- public void setSource(FileCollection source) {
- this.source = source;
- }
-
- public void setDestinationDir(File destinationDir) {
- this.destinationDir = destinationDir;
- }
-
- public File getDestinationDir() {
- return destinationDir;
- }
-}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/SunJavaCompiler.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/SunJavaCompiler.java
index 4b15316..3c37109 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/SunJavaCompiler.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/SunJavaCompiler.java
@@ -16,6 +16,7 @@
package org.gradle.api.internal.tasks.compile;
import com.sun.tools.javac.Main;
+import org.gradle.api.internal.tasks.SimpleWorkResult;
import org.gradle.api.tasks.WorkResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/TransformingClassLoader.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/TransformingClassLoader.java
deleted file mode 100644
index 21c75b5..0000000
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/TransformingClassLoader.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.tasks.compile;
-
-import com.google.common.io.ByteStreams;
-import org.codehaus.groovy.transform.GroovyASTTransformationClass;
-import org.gradle.api.UncheckedIOException;
-import org.gradle.internal.classpath.ClassPath;
-import org.gradle.util.MutableURLClassLoader;
-import org.objectweb.asm.*;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Transforms @GroovyASTTransformationClass(classes = {classLiterals}) into @GroovyASTTransformationClass([classNames]),
- * to work around GROOVY-5416.
- */
-class TransformingClassLoader extends MutableURLClassLoader {
- private static final String ANNOTATION_DESCRIPTOR = Type.getType(GroovyASTTransformationClass.class).getDescriptor();
-
- public TransformingClassLoader(ClassPath classpath) {
- super(null, classpath);
- }
-
- @Override
- protected Class<?> findClass(String name) throws ClassNotFoundException {
- URL resource = findResource(name.replace(".", "/") + ".class");
- if (resource == null) {
- throw new ClassNotFoundException(name);
- }
- try {
- byte[] bytes = loadBytecode(resource);
- bytes = transform(bytes);
- return super.defineClass(name, bytes, 0, bytes.length);
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- private byte[] loadBytecode(URL resource) throws IOException {
- InputStream inputStream = resource.openStream();
- try {
- return ByteStreams.toByteArray(inputStream);
- } finally {
- inputStream.close();
- }
- }
-
- private byte[] transform(byte[] bytes) {
- // First scan for annotation, and short circuit transformation if not present
- ClassReader classReader = new ClassReader(bytes);
-
- AnnotationDetector detector = new AnnotationDetector();
- classReader.accept(detector, ClassReader.SKIP_DEBUG | ClassReader.SKIP_CODE);
- if (!detector.found) {
- return bytes;
- }
-
- ClassWriter classWriter = new ClassWriter(0);
- classReader.accept(new TransformingAdapter(classWriter), 0);
- bytes = classWriter.toByteArray();
- return bytes;
- }
-
- private static class AnnotationDetector extends ClassVisitor {
- private boolean found;
-
- private AnnotationDetector() {
- super(Opcodes.ASM4);
- }
-
- public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
- if (desc.equals(ANNOTATION_DESCRIPTOR)) {
- found = true;
- }
- return null;
- }
- }
-
- private static class TransformingAdapter extends ClassVisitor {
- public TransformingAdapter(ClassWriter classWriter) {
- super(Opcodes.ASM4, classWriter);
- }
-
- @Override
- public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
- if (desc.equals(ANNOTATION_DESCRIPTOR)) {
- return new AnnotationTransformingVisitor(super.visitAnnotation(desc, visible));
- }
- return super.visitAnnotation(desc, visible);
- }
-
- private static class AnnotationTransformingVisitor extends AnnotationVisitor {
- private final List<String> names = new ArrayList<String>();
-
- public AnnotationTransformingVisitor(AnnotationVisitor annotationVisitor) {
- super(Opcodes.ASM4, annotationVisitor);
- }
-
- public AnnotationVisitor visitArray(String name) {
- if (name.equals("classes")) {
- return new AnnotationVisitor(Opcodes.ASM4){
- @Override
- public void visit(String name, Object value) {
- Type type = (Type) value;
- names.add(type.getClassName());
- }
- };
- } else if (name.equals("value")) {
- return new AnnotationVisitor(Opcodes.ASM4) {
- @Override
- public void visit(String name, Object value) {
- String type = (String) value;
- names.add(type);
- }
- };
- } else {
- return super.visitArray(name);
- }
- }
-
- public void visitEnd() {
- if (!names.isEmpty()) {
- AnnotationVisitor visitor = super.visitArray("value");
- for (String name : names) {
- visitor.visit(null, name);
- }
- visitor.visitEnd();
- }
- super.visitEnd();
- }
- }
- }
-}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/daemon/InProcessCompilerDaemonFactory.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/daemon/InProcessCompilerDaemonFactory.java
index 0378c04..8285495 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/daemon/InProcessCompilerDaemonFactory.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/daemon/InProcessCompilerDaemonFactory.java
@@ -20,6 +20,7 @@ import org.gradle.api.internal.project.ProjectInternal;
import org.gradle.api.internal.tasks.compile.CompileSpec;
import org.gradle.api.internal.tasks.compile.Compiler;
import org.gradle.internal.UncheckedException;
+import org.gradle.internal.classloader.*;
import org.gradle.internal.classpath.DefaultClassPath;
import org.gradle.internal.io.ClassLoaderObjectInputStream;
import org.gradle.util.*;
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/jdk6/Jdk6JavaCompiler.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/jdk6/Jdk6JavaCompiler.java
index 4ec606b..5baf594 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/jdk6/Jdk6JavaCompiler.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/compile/jdk6/Jdk6JavaCompiler.java
@@ -15,10 +15,14 @@
*/
package org.gradle.api.internal.tasks.compile.jdk6;
-import org.gradle.api.internal.tasks.compile.*;
+import org.gradle.api.internal.tasks.SimpleWorkResult;
+import org.gradle.api.internal.tasks.compile.CompilationFailedException;
import org.gradle.api.internal.tasks.compile.Compiler;
+import org.gradle.api.internal.tasks.compile.JavaCompileSpec;
+import org.gradle.api.internal.tasks.compile.JavaCompilerArgumentsBuilder;
import org.gradle.api.tasks.WorkResult;
import org.gradle.api.tasks.compile.CompileOptions;
+import org.gradle.internal.jvm.Jvm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -26,6 +30,7 @@ import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
+import java.io.File;
import java.io.Serializable;
import java.nio.charset.Charset;
import java.util.List;
@@ -34,7 +39,7 @@ public class Jdk6JavaCompiler implements Compiler<JavaCompileSpec>, Serializable
private static final Logger LOGGER = LoggerFactory.getLogger(Jdk6JavaCompiler.class);
public WorkResult execute(JavaCompileSpec spec) {
- LOGGER.info("Compiling with JDK 6 Java compiler API.");
+ LOGGER.info("Compiling with JDK Java compiler API.");
JavaCompiler.CompilationTask task = createCompileTask(spec);
boolean success = task.call();
@@ -47,7 +52,7 @@ public class Jdk6JavaCompiler implements Compiler<JavaCompileSpec>, Serializable
private JavaCompiler.CompilationTask createCompileTask(JavaCompileSpec spec) {
List<String> options = new JavaCompilerArgumentsBuilder(spec).build();
- JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+ JavaCompiler compiler = findCompiler();
if(compiler==null){
throw new RuntimeException("Cannot find System Java Compiler. Ensure that you have installed a JDK (not just a JRE) and configured your JAVA_HOME system variable to point to the according directory.");
}
@@ -56,4 +61,19 @@ public class Jdk6JavaCompiler implements Compiler<JavaCompileSpec>, Serializable
Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(spec.getSource());
return compiler.getTask(null, null, null, options, null, compilationUnits);
}
+
+ private static JavaCompiler findCompiler() {
+ File realJavaHome = Jvm.current().getJavaHome();
+ File javaHomeFromToolProvidersPointOfView = new File(System.getProperty("java.home"));
+ if (realJavaHome.equals(javaHomeFromToolProvidersPointOfView)) {
+ return ToolProvider.getSystemJavaCompiler();
+ }
+
+ System.setProperty("java.home", realJavaHome.getAbsolutePath());
+ try {
+ return ToolProvider.getSystemJavaCompiler();
+ } finally {
+ System.setProperty("java.home", javaHomeFromToolProvidersPointOfView.getAbsolutePath());
+ }
+ }
}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/DefaultJUnitXmlReport.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/DefaultJUnitXmlReport.java
new file mode 100644
index 0000000..3fd7bf4
--- /dev/null
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/DefaultJUnitXmlReport.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.tasks.testing;
+
+import org.gradle.api.Task;
+import org.gradle.api.reporting.internal.TaskGeneratedSingleDirectoryReport;
+import org.gradle.api.tasks.Input;
+import org.gradle.api.tasks.testing.JUnitXmlReport;
+
+public class DefaultJUnitXmlReport extends TaskGeneratedSingleDirectoryReport implements JUnitXmlReport {
+
+ private boolean outputPerTestCase;
+
+ public DefaultJUnitXmlReport(String name, Task task) {
+ super(name, task, null);
+ }
+
+ @Input
+ public boolean isOutputPerTestCase() {
+ return outputPerTestCase;
+ }
+
+ public void setOutputPerTestCase(boolean outputPerTestCase) {
+ this.outputPerTestCase = outputPerTestCase;
+ }
+
+}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/DefaultTestClassRunInfo.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/DefaultTestClassRunInfo.java
index 10dfd54..f2c807a 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/DefaultTestClassRunInfo.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/DefaultTestClassRunInfo.java
@@ -17,9 +17,6 @@ package org.gradle.api.internal.tasks.testing;
import org.apache.commons.lang.StringUtils;
-/**
- * @author Tom Eyckmans
- */
public class DefaultTestClassRunInfo implements TestClassRunInfo {
private String testClassName;
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/DefaultTestOutputEvent.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/DefaultTestOutputEvent.java
index 3fa55ae..6952a83 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/DefaultTestOutputEvent.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/DefaultTestOutputEvent.java
@@ -37,4 +37,32 @@ public class DefaultTestOutputEvent implements Serializable, TestOutputEvent {
public String getMessage() {
return message;
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ DefaultTestOutputEvent that = (DefaultTestOutputEvent) o;
+
+ if (destination != that.destination) {
+ return false;
+ }
+ if (!message.equals(that.message)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = destination.hashCode();
+ result = 31 * result + message.hashCode();
+ return result;
+ }
}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/DefaultTestTaskReports.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/DefaultTestTaskReports.java
new file mode 100644
index 0000000..131acb0
--- /dev/null
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/DefaultTestTaskReports.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.tasks.testing;
+
+import org.gradle.api.Task;
+import org.gradle.api.reporting.ConfigurableReport;
+import org.gradle.api.reporting.DirectoryReport;
+import org.gradle.api.reporting.Report;
+import org.gradle.api.reporting.internal.TaskGeneratedSingleDirectoryReport;
+import org.gradle.api.reporting.internal.TaskReportContainer;
+import org.gradle.api.tasks.Nested;
+import org.gradle.api.tasks.testing.TestTaskReports;
+
+public class DefaultTestTaskReports extends TaskReportContainer<Report> implements TestTaskReports {
+
+ public DefaultTestTaskReports(Task task) {
+ super(ConfigurableReport.class, task);
+
+ add(DefaultJUnitXmlReport.class, "junitXml", task);
+ add(TaskGeneratedSingleDirectoryReport.class, "html", task, "index.html");
+ }
+
+ public DirectoryReport getHtml() {
+ return (DirectoryReport) getByName("html");
+ }
+
+ @Nested
+ public DefaultJUnitXmlReport getJunitXml() {
+ return (DefaultJUnitXmlReport) getByName("junitXml");
+ }
+
+}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/TestClassProcessor.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/TestClassProcessor.java
index 68a04dd..da2fb6b 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/TestClassProcessor.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/TestClassProcessor.java
@@ -20,8 +20,6 @@ import org.gradle.internal.Stoppable;
/**
* A processor for executing tests. Implementations are not required to be thread-safe.
- *
- * @author Tom Eyckmans
*/
public interface TestClassProcessor extends Stoppable {
/**
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/TestClassRunInfo.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/TestClassRunInfo.java
index c553c4e..1dfee50 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/TestClassRunInfo.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/TestClassRunInfo.java
@@ -17,9 +17,6 @@ package org.gradle.api.internal.tasks.testing;
import java.io.Serializable;
-/**
- * @author Tom Eyckmans
- */
public interface TestClassRunInfo extends Serializable {
String getTestClassName();
}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/TestFramework.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/TestFramework.java
index 6074f56..10a4bea 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/TestFramework.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/TestFramework.java
@@ -21,9 +21,6 @@ import org.gradle.api.internal.tasks.testing.detection.TestFrameworkDetector;
import org.gradle.api.tasks.testing.TestFrameworkOptions;
import org.gradle.process.internal.WorkerProcessBuilder;
-/**
- * @author Tom Eyckmans
- */
public interface TestFramework {
/**
@@ -36,7 +33,7 @@ public interface TestFramework {
/**
* Returns a factory which is used to create a {@link org.gradle.api.internal.tasks.testing.TestClassProcessor} in
- * each worker process. This factory is serialized across to the worker process, and then it's {@link
+ * each worker process. This factory is serialized across to the worker process, and then its {@link
* org.gradle.api.internal.tasks.testing.WorkerTestClassProcessorFactory#create(org.gradle.internal.service.ServiceRegistry)}
* method is called to create the test processor.
*/
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/detection/AbstractTestFrameworkDetector.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/detection/AbstractTestFrameworkDetector.java
index ba6589b..88a438b 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/detection/AbstractTestFrameworkDetector.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/detection/AbstractTestFrameworkDetector.java
@@ -31,9 +31,6 @@ import java.io.FileInputStream;
import java.io.InputStream;
import java.util.*;
-/**
- * @author Tom Eyckmans
- */
public abstract class AbstractTestFrameworkDetector<T extends TestClassVisitor> implements TestFrameworkDetector {
protected static final String TEST_CASE = "junit/framework/TestCase";
protected static final String GROOVY_TEST_CASE = "groovy/util/GroovyTestCase";
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/detection/ClassFileExtractionManager.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/detection/ClassFileExtractionManager.java
index 2088cd8..93e1d84 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/detection/ClassFileExtractionManager.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/detection/ClassFileExtractionManager.java
@@ -30,8 +30,6 @@ import java.util.*;
/**
* This class manages class file extraction from library jar files.
- *
- * @author Tom Eyckmans
*/
public class ClassFileExtractionManager {
private static final Logger LOGGER = LoggerFactory.getLogger(ClassFileExtractionManager.class);
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/detection/DefaultTestClassScanner.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/detection/DefaultTestClassScanner.java
index 88b5254..7e5a168 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/detection/DefaultTestClassScanner.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/detection/DefaultTestClassScanner.java
@@ -28,8 +28,6 @@ import java.io.File;
/**
* The default test class scanner. Depending on the availability of a test framework detector,
* a detection or filename scan is performed to find test classes.
- *
- * @author Tom Eyckmans
*/
public class DefaultTestClassScanner implements Runnable {
private final FileTree candidateClassFiles;
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/detection/DefaultTestExecuter.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/detection/DefaultTestExecuter.java
index ed8ea46..5af69d8 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/detection/DefaultTestExecuter.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/detection/DefaultTestExecuter.java
@@ -33,8 +33,6 @@ import org.gradle.process.internal.WorkerProcessBuilder;
/**
* The default test class scanner factory.
- *
- * @author Tom Eyckmans
*/
public class DefaultTestExecuter implements TestExecuter {
private final Factory<WorkerProcessBuilder> workerFactory;
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/detection/JarFilePackageListener.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/detection/JarFilePackageListener.java
index 99e9dfa..71a88ae 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/detection/JarFilePackageListener.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/detection/JarFilePackageListener.java
@@ -16,9 +16,6 @@
package org.gradle.api.internal.tasks.testing.detection;
-/**
- * @author Tom Eyckmans
- */
public interface JarFilePackageListener {
void receivePackage(String packageName);
}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/detection/JarFilePackageLister.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/detection/JarFilePackageLister.java
index 3bd4b96..fa3e984 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/detection/JarFilePackageLister.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/detection/JarFilePackageLister.java
@@ -24,9 +24,6 @@ import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
-/**
- * @author Tom Eyckmans
- */
public class JarFilePackageLister {
public void listJarPackages(File jarFile, JarFilePackageListener listener) {
if (jarFile == null) {
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/detection/TestClassVisitor.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/detection/TestClassVisitor.java
index f26fd7a..b8bcd5a 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/detection/TestClassVisitor.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/detection/TestClassVisitor.java
@@ -21,8 +21,6 @@ import org.objectweb.asm.Opcodes;
/**
* Base class for ASM test class scanners.
- *
- * @author Tom Eyckmans
*/
public abstract class TestClassVisitor extends ClassVisitor {
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/detection/TestExecuter.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/detection/TestExecuter.java
index 012ea2f..8ab500b 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/detection/TestExecuter.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/detection/TestExecuter.java
@@ -19,9 +19,6 @@ package org.gradle.api.internal.tasks.testing.detection;
import org.gradle.api.internal.tasks.testing.TestResultProcessor;
import org.gradle.api.tasks.testing.Test;
-/**
- * @author Tom Eyckmans
- */
public interface TestExecuter {
void execute(Test testTask, TestResultProcessor testResultProcessor);
}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/detection/TestFrameworkDetector.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/detection/TestFrameworkDetector.java
index 5134366..92394d7 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/detection/TestFrameworkDetector.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/detection/TestFrameworkDetector.java
@@ -20,9 +20,6 @@ import org.gradle.api.internal.tasks.testing.TestClassProcessor;
import java.io.File;
-/**
- * @author Tom Eyckmans
- */
public interface TestFrameworkDetector {
void startDetection(TestClassProcessor testClassProcessor);
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/CategoryFilter.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/CategoryFilter.java
new file mode 100644
index 0000000..685da83
--- /dev/null
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/CategoryFilter.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.tasks.testing.junit;
+
+import org.apache.commons.lang.StringUtils;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.Description;
+import org.junit.runner.manipulation.Filter;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * This filter is used for filtering classes and methods that are annotated with the @Category annotation.
+ *
+ */
+class CategoryFilter extends Filter {
+ // the way filters are implemented makes this unnecessarily complicated,
+ // buggy, and difficult to specify. A new way of handling filters could
+ // someday enable a better new implementation.
+ // https://github.com/junit-team/junit/issues/172
+
+ private final Set<Class<?>> inclusions;
+ private final Set<Class<?>> exclusions;
+
+ public CategoryFilter(final Set<Class<?>> inclusions, final Set<Class<?>> exclusions) {
+ this.inclusions = inclusions;
+ this.exclusions = exclusions;
+ }
+
+ @Override
+ public boolean shouldRun(final Description description) {
+ return shouldRun(description, description.isSuite() ? null : Description.createSuiteDescription(description.getTestClass()));
+ }
+
+ private boolean shouldRun(final Description description, final Description parent) {
+ final Set<Class<?>> categories = new HashSet<Class<?>>();
+ Category annotation = description.getAnnotation(Category.class);
+ if (annotation != null) {
+ categories.addAll(Arrays.asList(annotation.value()));
+ }
+
+ if (parent != null) {
+ annotation = parent.getAnnotation(Category.class);
+ if (annotation != null) {
+ categories.addAll(Arrays.asList(annotation.value()));
+ }
+ }
+
+ boolean result = inclusions.isEmpty();
+
+ for (Class<?> category : categories) {
+ if (matches(category, inclusions)) {
+ result = true;
+ break;
+ }
+ }
+
+ if (result) {
+ for (Class<?> category : categories) {
+ if (matches(category, exclusions)) {
+ result = false;
+ break;
+ }
+ }
+ }
+ return result;
+ }
+
+ private boolean matches(final Class<?> category, final Set<Class<?>> categories) {
+ for (Class<?> cls : categories) {
+ if (cls.isAssignableFrom(category)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public final String describe() {
+ StringBuilder sb = new StringBuilder();
+ if (!inclusions.isEmpty()) {
+ sb.append("(");
+ sb.append(StringUtils.join(inclusions, " OR "));
+ sb.append(")");
+ if (!exclusions.isEmpty()) {
+ sb.append(" AND ");
+ }
+ }
+ if (!exclusions.isEmpty()) {
+ sb.append("NOT (");
+ sb.append(StringUtils.join(exclusions, " OR "));
+ sb.append(")");
+ }
+
+ return sb.toString();
+ }
+}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/JUnitDetector.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/JUnitDetector.java
index a7fa601..2067040 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/JUnitDetector.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/JUnitDetector.java
@@ -23,9 +23,6 @@ import org.slf4j.LoggerFactory;
import java.io.File;
-/**
- * @author Tom Eyckmans
- */
public class JUnitDetector extends AbstractTestFrameworkDetector<JUnitTestClassDetecter> {
private static final Logger LOGGER = LoggerFactory.getLogger(JUnitDetector.class);
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/JUnitSpec.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/JUnitSpec.java
new file mode 100644
index 0000000..8132f25
--- /dev/null
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/JUnitSpec.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.tasks.testing.junit;
+
+import org.gradle.api.tasks.testing.junit.JUnitOptions;
+
+import java.io.Serializable;
+import java.util.Set;
+
+public class JUnitSpec implements Serializable {
+
+ private final Set<String> includeCategories;
+ private final Set<String> excludeCategories;
+
+ public JUnitSpec(final JUnitOptions options){
+ this.includeCategories = options.getIncludeCategories();
+ this.excludeCategories = options.getExcludeCategories();
+ }
+
+ public Set<String> getIncludeCategories() {
+ return includeCategories;
+ }
+
+ public Set<String> getExcludeCategories() {
+ return excludeCategories;
+ }
+
+ public boolean hasCategoryConfiguration() {
+ return !(excludeCategories.isEmpty() && includeCategories.isEmpty());
+
+ }
+}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/JUnitTestClassDetecter.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/JUnitTestClassDetecter.java
index 62c4204..e17160c 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/JUnitTestClassDetecter.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/JUnitTestClassDetecter.java
@@ -21,9 +21,6 @@ import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
-/**
- * @author Tom Eyckmans
- */
class JUnitTestClassDetecter extends TestClassVisitor {
private boolean isAbstract;
private String className;
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/JUnitTestClassExecuter.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/JUnitTestClassExecuter.java
index f958a02..c97c088 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/JUnitTestClassExecuter.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/JUnitTestClassExecuter.java
@@ -16,7 +16,10 @@
package org.gradle.api.internal.tasks.testing.junit;
+import org.gradle.api.InvalidUserDataException;
+import org.gradle.api.Transformer;
import org.gradle.internal.concurrent.ThreadSafe;
+import org.gradle.util.CollectionUtils;
import org.junit.runner.Request;
import org.junit.runner.Runner;
import org.junit.runner.notification.RunListener;
@@ -25,12 +28,14 @@ import org.junit.runner.notification.RunNotifier;
public class JUnitTestClassExecuter {
private final ClassLoader applicationClassLoader;
private final RunListener listener;
+ private final JUnitSpec options;
private final TestClassExecutionListener executionListener;
- public JUnitTestClassExecuter(ClassLoader applicationClassLoader, RunListener listener, TestClassExecutionListener executionListener) {
+ public JUnitTestClassExecuter(ClassLoader applicationClassLoader, JUnitSpec spec, RunListener listener, TestClassExecutionListener executionListener) {
assert executionListener instanceof ThreadSafe;
this.applicationClassLoader = applicationClassLoader;
this.listener = listener;
+ this.options = spec;
this.executionListener = executionListener;
}
@@ -48,10 +53,33 @@ public class JUnitTestClassExecuter {
}
private void runTestClass(String testClassName) throws ClassNotFoundException {
- Class<?> testClass = Class.forName(testClassName, true, applicationClassLoader);
- Runner runner = Request.aClass(testClass).getRunner();
- RunNotifier notifier = new RunNotifier();
- notifier.addListener(listener);
- runner.run(notifier);
+ final Class<?> testClass = Class.forName(testClassName, true, applicationClassLoader);
+ Request request = Request.aClass(testClass);
+ if (options.hasCategoryConfiguration()) {
+ Transformer<Class<?>, String> transformer = new Transformer<Class<?>, String>() {
+ public Class<?> transform(final String original) {
+ try {
+ return applicationClassLoader.loadClass(original);
+ } catch (ClassNotFoundException e) {
+ throw new InvalidUserDataException(String.format("Can't load category class [%s].", original), e);
+ }
+ }
+ };
+ request = request.filterWith(new CategoryFilter(
+ CollectionUtils.collect(options.getIncludeCategories(), transformer),
+ CollectionUtils.collect(options.getExcludeCategories(), transformer)
+ ));
+ }
+
+ Runner runner = request.getRunner();
+ //In case of no matching methods junit will return a ErrorReportingRunner for org.junit.runner.manipulation.Filter.class.
+ //Will be fixed with adding class filters
+ if (!org.junit.runner.manipulation.Filter.class.getName().equals(runner.getDescription().getDisplayName())) {
+ RunNotifier notifier = new RunNotifier();
+ notifier.addListener(listener);
+ runner.run(notifier);
+ }
}
+
+
}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/JUnitTestClassProcessor.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/JUnitTestClassProcessor.java
index 1ff8140..537fbdf 100755
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/JUnitTestClassProcessor.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/JUnitTestClassProcessor.java
@@ -30,22 +30,20 @@ import org.gradle.messaging.actor.ActorFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.File;
-
public class JUnitTestClassProcessor implements TestClassProcessor {
private static final Logger LOGGER = LoggerFactory.getLogger(JUnitTestClassProcessor.class);
- private final File testResultsDir;
private final IdGenerator<?> idGenerator;
private final ActorFactory actorFactory;
private final StandardOutputRedirector outputRedirector;
private final TimeProvider timeProvider = new TrueTimeProvider();
+ private final JUnitSpec spec;
private JUnitTestClassExecuter executer;
private Actor resultProcessorActor;
- public JUnitTestClassProcessor(File testResultsDir, IdGenerator<?> idGenerator, ActorFactory actorFactory,
+ public JUnitTestClassProcessor(JUnitSpec spec, IdGenerator<?> idGenerator, ActorFactory actorFactory,
StandardOutputRedirector standardOutputRedirector) {
- this.testResultsDir = testResultsDir;
this.idGenerator = idGenerator;
+ this.spec = spec;
this.actorFactory = actorFactory;
this.outputRedirector = standardOutputRedirector;
}
@@ -63,7 +61,7 @@ public class JUnitTestClassProcessor implements TestClassProcessor {
// Build the JUnit adaptor stuff
JUnitTestEventAdapter junitEventAdapter = new JUnitTestEventAdapter(threadSafeResultProcessor, timeProvider, idGenerator);
- executer = new JUnitTestClassExecuter(applicationClassLoader, junitEventAdapter, threadSafeTestClassListener);
+ executer = new JUnitTestClassExecuter(applicationClassLoader, spec, junitEventAdapter, threadSafeTestClassListener);
}
public void processTestClass(TestClassRunInfo testClass) {
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/JUnitTestFramework.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/JUnitTestFramework.java
index e2dbdda..951337c 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/JUnitTestFramework.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/JUnitTestFramework.java
@@ -17,23 +17,22 @@
package org.gradle.api.internal.tasks.testing.junit;
import org.gradle.api.Action;
+import org.gradle.api.GradleException;
import org.gradle.api.internal.tasks.testing.TestClassProcessor;
import org.gradle.api.internal.tasks.testing.TestFramework;
import org.gradle.api.internal.tasks.testing.WorkerTestClassProcessorFactory;
import org.gradle.api.internal.tasks.testing.detection.ClassFileExtractionManager;
import org.gradle.api.tasks.testing.Test;
import org.gradle.api.tasks.testing.junit.JUnitOptions;
+import org.gradle.internal.classpath.DefaultClassPath;
import org.gradle.internal.id.IdGenerator;
import org.gradle.internal.service.ServiceRegistry;
import org.gradle.messaging.actor.ActorFactory;
import org.gradle.process.internal.WorkerProcessBuilder;
-import java.io.File;
import java.io.Serializable;
+import java.net.URLClassLoader;
-/**
- * @author Tom Eyckmans
- */
public class JUnitTestFramework implements TestFramework {
private JUnitOptions options;
private JUnitDetector detector;
@@ -46,8 +45,19 @@ public class JUnitTestFramework implements TestFramework {
}
public WorkerTestClassProcessorFactory getProcessorFactory() {
- final File testResultsDir = testTask.getTestResultsDir();
- return new TestClassProcessorFactoryImpl(testResultsDir);
+ verifyJUnitCategorySupport();
+ return new TestClassProcessorFactoryImpl(new JUnitSpec(options));
+ }
+
+ private void verifyJUnitCategorySupport() {
+ if (!options.getExcludeCategories().isEmpty() || !options.getIncludeCategories().isEmpty()) {
+ ClassLoader testClassloader = new URLClassLoader(new DefaultClassPath(testTask.getClasspath()).getAsURLArray(), null);
+ try {
+ testClassloader.loadClass("org.junit.experimental.categories.Category");
+ } catch (ClassNotFoundException e) {
+ throw new GradleException("JUnit Categories defined but declared JUnit version does not support Categories.");
+ }
+ }
}
public Action<WorkerProcessBuilder> getWorkerConfigurationAction() {
@@ -73,14 +83,14 @@ public class JUnitTestFramework implements TestFramework {
}
private static class TestClassProcessorFactoryImpl implements WorkerTestClassProcessorFactory, Serializable {
- private final File testResultsDir;
+ private final JUnitSpec spec;
- public TestClassProcessorFactoryImpl(File testResultsDir) {
- this.testResultsDir = testResultsDir;
+ public TestClassProcessorFactoryImpl(JUnitSpec spec) {
+ this.spec = spec;
}
public TestClassProcessor create(ServiceRegistry serviceRegistry) {
- return new JUnitTestClassProcessor(testResultsDir, serviceRegistry.get(IdGenerator.class), serviceRegistry.get(ActorFactory.class), new JULRedirector());
+ return new JUnitTestClassProcessor(spec, serviceRegistry.get(IdGenerator.class), serviceRegistry.get(ActorFactory.class), new JULRedirector());
}
}
}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/JUnitTestMethodDetecter.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/JUnitTestMethodDetecter.java
index ace1986..1b84358 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/JUnitTestMethodDetecter.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/JUnitTestMethodDetecter.java
@@ -19,9 +19,6 @@ import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
-/**
- * @author Tom Eyckmans
- */
class JUnitTestMethodDetecter extends MethodVisitor {
private final JUnitTestClassDetecter testClassDetecter;
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/report/AllTestResults.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/report/AllTestResults.java
index dc585ac..89cf015 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/report/AllTestResults.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/report/AllTestResults.java
@@ -38,13 +38,13 @@ public class AllTestResults extends CompositeTestResults {
return packages.values();
}
- public TestResult addTest(String className, String testName, long duration) {
+ public TestResult addTest(long classId, String className, String testName, long duration) {
PackageTestResults packageResults = addPackageForClass(className);
- return addTest(packageResults.addTest(className, testName, duration));
+ return addTest(packageResults.addTest(classId, className, testName, duration));
}
- public ClassTestResults addTestClass(String className) {
- return addPackageForClass(className).addClass(className);
+ public ClassTestResults addTestClass(long classId, String className) {
+ return addPackageForClass(className).addClass(classId, className);
}
private PackageTestResults addPackageForClass(String className) {
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/report/ClassPageRenderer.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/report/ClassPageRenderer.java
index 13320db..a8ca202 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/report/ClassPageRenderer.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/report/ClassPageRenderer.java
@@ -16,20 +16,20 @@
package org.gradle.api.internal.tasks.testing.junit.report;
import org.gradle.api.internal.ErroringAction;
+import org.gradle.api.internal.html.SimpleHtmlWriter;
import org.gradle.api.internal.tasks.testing.junit.result.TestResultsProvider;
import org.gradle.api.tasks.testing.TestOutputEvent;
import org.gradle.reporting.CodePanelRenderer;
-import org.gradle.api.internal.html.SimpleHtmlWriter;
import java.io.IOException;
class ClassPageRenderer extends PageRenderer<ClassTestResults> {
private final CodePanelRenderer codePanelRenderer = new CodePanelRenderer();
private final TestResultsProvider resultsProvider;
- private final String className;
+ private final long classId;
- public ClassPageRenderer(String className, TestResultsProvider provider) {
- this.className = className;
+ public ClassPageRenderer(long classId, TestResultsProvider provider) {
+ this.classId = classId;
this.resultsProvider = provider;
}
@@ -84,27 +84,27 @@ class ClassPageRenderer extends PageRenderer<ClassTestResults> {
renderTests(writer);
}
});
- if (resultsProvider.hasOutput(className, TestOutputEvent.Destination.StdOut)) {
+ if (resultsProvider.hasOutput(classId, TestOutputEvent.Destination.StdOut)) {
addTab("Standard output", new ErroringAction<SimpleHtmlWriter>() {
@Override
protected void doExecute(SimpleHtmlWriter htmlWriter) throws IOException {
htmlWriter.startElement("span").attribute("class", "code")
.startElement("pre")
.characters("");
- resultsProvider.writeOutputs(className, TestOutputEvent.Destination.StdOut, htmlWriter);
+ resultsProvider.writeAllOutput(classId, TestOutputEvent.Destination.StdOut, htmlWriter);
htmlWriter.endElement()
.endElement();
}
});
}
- if (resultsProvider.hasOutput(className, TestOutputEvent.Destination.StdErr)) {
+ if (resultsProvider.hasOutput(classId, TestOutputEvent.Destination.StdErr)) {
addTab("Standard error", new ErroringAction<SimpleHtmlWriter>() {
@Override
protected void doExecute(SimpleHtmlWriter element) throws Exception {
element.startElement("span").attribute("class", "code")
.startElement("pre")
.characters("");
- resultsProvider.writeOutputs(className, TestOutputEvent.Destination.StdErr, element);
+ resultsProvider.writeAllOutput(classId, TestOutputEvent.Destination.StdErr, element);
element.endElement()
.endElement();
}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/report/ClassTestResults.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/report/ClassTestResults.java
index 4dc2e2a..e69f06d 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/report/ClassTestResults.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/report/ClassTestResults.java
@@ -25,16 +25,22 @@ import java.util.TreeSet;
* Test results for a given class.
*/
public class ClassTestResults extends CompositeTestResults {
+ private final long id;
private final String name;
private final PackageTestResults packageResults;
private final Set<TestResult> results = new TreeSet<TestResult>();
- public ClassTestResults(String name, PackageTestResults packageResults) {
+ public ClassTestResults(long id, String name, PackageTestResults packageResults) {
super(packageResults);
+ this.id = id;
this.name = name;
this.packageResults = packageResults;
}
+ public long getId() {
+ return id;
+ }
+
@Override
public String getTitle() {
return String.format("Class %s", name);
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/report/DefaultTestReport.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/report/DefaultTestReport.java
index 46aeb74..d770cc7 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/report/DefaultTestReport.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/report/DefaultTestReport.java
@@ -54,10 +54,10 @@ public class DefaultTestReport implements TestReporter {
final AllTestResults model = new AllTestResults();
resultsProvider.visitClasses(new Action<TestClassResult>() {
public void execute(TestClassResult classResult) {
- model.addTestClass(classResult.getClassName());
+ model.addTestClass(classResult.getId(), classResult.getClassName());
List<TestMethodResult> collectedResults = classResult.getResults();
for (TestMethodResult collectedResult : collectedResults) {
- final TestResult testResult = model.addTest(classResult.getClassName(), collectedResult.getName(), collectedResult.getDuration());
+ final TestResult testResult = model.addTest(classResult.getId(), classResult.getClassName(), collectedResult.getName(), collectedResult.getDuration());
if (collectedResult.getResultType() == org.gradle.api.tasks.testing.TestResult.ResultType.SKIPPED) {
testResult.ignored();
} else {
@@ -94,7 +94,7 @@ public class DefaultTestReport implements TestReporter {
for (PackageTestResults packageResults : model.getPackages()) {
generatePage(packageResults, new PackagePageRenderer(), new File(reportDir, packageResults.getName() + ".html"));
for (ClassTestResults classResults : packageResults.getClasses()) {
- generatePage(classResults, new ClassPageRenderer(classResults.getName(), resultsProvider), new File(reportDir, classResults.getName() + ".html"));
+ generatePage(classResults, new ClassPageRenderer(classResults.getId(), resultsProvider), new File(reportDir, classResults.getName() + ".html"));
}
}
} catch (Exception e) {
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/report/LocaleSafeDecimalFormat.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/report/LocaleSafeDecimalFormat.java
index c398f33..e51b64a 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/report/LocaleSafeDecimalFormat.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/report/LocaleSafeDecimalFormat.java
@@ -20,9 +20,6 @@ import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;
-/**
- * @author Szczepan Faber, @date: 09.03.11
- */
public class LocaleSafeDecimalFormat {
/**
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/report/OverviewPageRenderer.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/report/OverviewPageRenderer.java
index 69b9355..6391609 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/report/OverviewPageRenderer.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/report/OverviewPageRenderer.java
@@ -64,7 +64,7 @@ class OverviewPageRenderer extends PageRenderer<AllTestResults> {
htmlWriter.startElement("td").characters(Integer.toString(testPackage.getTestCount())).endElement();
htmlWriter.startElement("td").characters(Integer.toString(testPackage.getFailureCount())).endElement();
htmlWriter.startElement("td").characters(testPackage.getFormattedDuration()).endElement();
- htmlWriter.startElement("td").attribute("class", testPackage.getStatusClass()).characters(testPackage.getFormattedDuration()).endElement();
+ htmlWriter.startElement("td").attribute("class", testPackage.getStatusClass()).characters(testPackage.getFormattedSuccessRate()).endElement();
htmlWriter.endElement();
}
htmlWriter.endElement();
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/report/PackageTestResults.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/report/PackageTestResults.java
index 916397b..59117f6 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/report/PackageTestResults.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/report/PackageTestResults.java
@@ -45,15 +45,15 @@ public class PackageTestResults extends CompositeTestResults {
return classes.values();
}
- public TestResult addTest(String className, String testName, long duration) {
- ClassTestResults classResults = addClass(className);
+ public TestResult addTest(long classId, String className, String testName, long duration) {
+ ClassTestResults classResults = addClass(classId, className);
return addTest(classResults.addTest(testName, duration));
}
- public ClassTestResults addClass(String className) {
+ public ClassTestResults addClass(long classId, String className) {
ClassTestResults classResults = classes.get(className);
if (classResults == null) {
- classResults = new ClassTestResults(className, this);
+ classResults = new ClassTestResults(classId, className, this);
classes.put(className, classResults);
}
return classResults;
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/AggregateTestResultsProvider.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/AggregateTestResultsProvider.java
index f1debb0..72247b5 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/AggregateTestResultsProvider.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/AggregateTestResultsProvider.java
@@ -17,46 +17,89 @@
package org.gradle.api.internal.tasks.testing.junit.result;
import org.gradle.api.Action;
+import org.gradle.api.specs.Spec;
import org.gradle.api.tasks.testing.TestOutputEvent;
+import org.gradle.internal.CompositeStoppable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.File;
+import java.io.IOException;
import java.io.Writer;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Map;
+import java.util.Set;
+
+import static org.gradle.util.CollectionUtils.any;
public class AggregateTestResultsProvider implements TestResultsProvider {
private static final Logger LOGGER = LoggerFactory.getLogger(AggregateTestResultsProvider.class);
- private final Iterable<File> binaryResultDirs;
- private Map<String, TestResultsProvider> classOutputProviders;
+ private final Iterable<TestResultsProvider> providers;
+ private Map<Long, TestResultsProvider> classOutputProviders;
+ private Map<Long, Long> idMappings;
- public AggregateTestResultsProvider(Iterable<File> binaryResultDirs) {
- this.binaryResultDirs = binaryResultDirs;
+ public AggregateTestResultsProvider(Iterable<TestResultsProvider> providers) {
+ this.providers = providers;
}
public void visitClasses(final Action<? super TestClassResult> visitor) {
- classOutputProviders = new HashMap<String, TestResultsProvider>();
- for (File dir : binaryResultDirs) {
- final BinaryResultBackedTestResultsProvider provider = new BinaryResultBackedTestResultsProvider(dir);
+ classOutputProviders = new HashMap<Long, TestResultsProvider>();
+ idMappings = new HashMap<Long, Long>();
+ final Set<String> seenClasses = new HashSet<String>();
+ final long[] newIdCounter = {1};
+ for (final TestResultsProvider provider : providers) {
provider.visitClasses(new Action<TestClassResult>() {
public void execute(TestClassResult classResult) {
- if (classOutputProviders.containsKey(classResult.getClassName())) {
+ if (seenClasses.contains(classResult.getClassName())) {
LOGGER.warn("Discarding duplicate results for test class {}.", classResult.getClassName());
return;
}
- classOutputProviders.put(classResult.getClassName(), provider);
- visitor.execute(classResult);
+
+ long newId = newIdCounter[0]++;
+ classOutputProviders.put(newId, provider);
+ idMappings.put(newId, classResult.getId());
+ TestClassResult newIdResult = new OverlayedIdTestClassResult(newId, classResult);
+ visitor.execute(newIdResult);
}
});
}
}
- public boolean hasOutput(String className, TestOutputEvent.Destination destination) {
- return classOutputProviders.get(className).hasOutput(className, destination);
+ private static class OverlayedIdTestClassResult extends TestClassResult {
+ public OverlayedIdTestClassResult(long id, TestClassResult delegate) {
+ super(id, delegate.getClassName(), delegate.getStartTime());
+
+ for (TestMethodResult result : delegate.getResults()) {
+ add(result);
+ }
+ }
+ }
+
+ public boolean hasOutput(long id, TestOutputEvent.Destination destination) {
+ return classOutputProviders.get(id).hasOutput(id, destination);
+ }
+
+ public void writeAllOutput(long id, TestOutputEvent.Destination destination, Writer writer) {
+ classOutputProviders.get(id).writeAllOutput(id, destination, writer);
+ }
+
+ public boolean isHasResults() {
+ return any(providers, new Spec<TestResultsProvider>() {
+ public boolean isSatisfiedBy(TestResultsProvider element) {
+ return element.isHasResults();
+ }
+ });
+ }
+
+ public void writeNonTestOutput(long id, TestOutputEvent.Destination destination, Writer writer) {
+ classOutputProviders.get(id).writeNonTestOutput(id, destination, writer);
+ }
+
+ public void writeTestOutput(long classId, long testId, TestOutputEvent.Destination destination, Writer writer) {
+ classOutputProviders.get(classId).writeTestOutput(classId, testId, destination, writer);
}
- public void writeOutputs(String className, TestOutputEvent.Destination destination, Writer writer) {
- classOutputProviders.get(className).writeOutputs(className, destination, writer);
+ public void close() throws IOException {
+ CompositeStoppable.stoppable(providers).stop();
}
}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/Binary2JUnitXmlReportGenerator.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/Binary2JUnitXmlReportGenerator.java
index 844ef3b..323c9eb 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/Binary2JUnitXmlReportGenerator.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/Binary2JUnitXmlReportGenerator.java
@@ -37,10 +37,10 @@ public class Binary2JUnitXmlReportGenerator {
JUnitXmlResultWriter saxWriter;
private final static Logger LOG = Logging.getLogger(Binary2JUnitXmlReportGenerator.class);
- public Binary2JUnitXmlReportGenerator(File testResultsDir, TestResultsProvider testResultsProvider) {
+ public Binary2JUnitXmlReportGenerator(File testResultsDir, TestResultsProvider testResultsProvider, TestOutputAssociation outputAssociation) {
this.testResultsDir = testResultsDir;
this.testResultsProvider = testResultsProvider;
- this.saxWriter = new JUnitXmlResultWriter(getHostname(), testResultsProvider);
+ this.saxWriter = new JUnitXmlResultWriter(getHostname(), testResultsProvider, outputAssociation);
}
public void generate() {
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/BinaryResultBackedTestResultsProvider.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/BinaryResultBackedTestResultsProvider.java
index 217a4db..670b392 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/BinaryResultBackedTestResultsProvider.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/BinaryResultBackedTestResultsProvider.java
@@ -20,27 +20,43 @@ import org.gradle.api.Action;
import org.gradle.api.tasks.testing.TestOutputEvent;
import java.io.File;
+import java.io.IOException;
import java.io.Writer;
public class BinaryResultBackedTestResultsProvider implements TestResultsProvider {
- private final File resultsDir;
- private final TestOutputSerializer outputSerializer;
- private final TestResultSerializer resultSerializer = new TestResultSerializer();
+ private final TestOutputStore.Reader outputReader;
+ private final TestResultSerializer resultSerializer;
public BinaryResultBackedTestResultsProvider(File resultsDir) {
- this.resultsDir = resultsDir;
- outputSerializer = new TestOutputSerializer(resultsDir);
+ this.outputReader = new TestOutputStore(resultsDir).reader();
+ this.resultSerializer = new TestResultSerializer(resultsDir);
}
- public boolean hasOutput(String className, TestOutputEvent.Destination destination) {
- return outputSerializer.hasOutput(className, destination);
+ public boolean hasOutput(long id, TestOutputEvent.Destination destination) {
+ return outputReader.hasOutput(id, destination);
}
- public void writeOutputs(String className, TestOutputEvent.Destination destination, Writer writer) {
- outputSerializer.writeOutputs(className, destination, writer);
+ public void writeAllOutput(long id, TestOutputEvent.Destination destination, Writer writer) {
+ outputReader.writeAllOutput(id, destination, writer);
+ }
+
+ public boolean isHasResults() {
+ return resultSerializer.isHasResults();
+ }
+
+ public void writeNonTestOutput(long id, TestOutputEvent.Destination destination, Writer writer) {
+ outputReader.writeNonTestOutput(id, destination, writer);
+ }
+
+ public void writeTestOutput(long classId, long testId, TestOutputEvent.Destination destination, Writer writer) {
+ outputReader.writeTestOutput(classId, testId, destination, writer);
}
public void visitClasses(final Action<? super TestClassResult> visitor) {
- resultSerializer.read(resultsDir, visitor);
+ resultSerializer.read(visitor);
+ }
+
+ public void close() throws IOException {
+ outputReader.close();
}
}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/CachingFileWriter.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/CachingFileWriter.java
deleted file mode 100644
index 2d8841a..0000000
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/CachingFileWriter.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.tasks.testing.junit.result;
-
-import org.gradle.api.UncheckedIOException;
-import org.gradle.api.logging.Logger;
-import org.gradle.api.logging.Logging;
-
-import java.io.*;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-import static org.gradle.internal.CompositeStoppable.stoppable;
-
-/**
- * by Szczepan Faber, created at: 11/19/12
- */
-public class CachingFileWriter {
-
- private final static Logger LOG = Logging.getLogger(CachingFileWriter.class);
-
- final LinkedHashMap<File, Writer> openFiles = new LinkedHashMap<File, Writer>();
- private final int maxOpenFiles;
-
- public CachingFileWriter(int maxOpenFiles) {
- this.maxOpenFiles = maxOpenFiles;
- }
-
- public void write(File file, String text) {
- Writer out;
- try {
- try {
- if (openFiles.containsKey(file)) {
- out = openFiles.get(file);
- } else {
- out = new OutputStreamWriter(new BufferedOutputStream(new FileOutputStream(file, true)), "UTF-8");
- openFiles.put(file, out);
- if (openFiles.size() > maxOpenFiles) {
- //remove first
- Iterator<Map.Entry<File, Writer>> iterator = openFiles.entrySet().iterator();
- close(iterator.next().getValue(), file.toString());
- iterator.remove();
- }
- }
- out.write(text);
- } catch (IOException e) {
- throw new UncheckedIOException("Problems writing to file: " + file, e);
- }
- } catch (UncheckedIOException e) {
- cleanUpQuietly();
- throw e;
- }
- }
-
- public void closeAll() {
- try {
- for (Map.Entry<File, Writer> entry : openFiles.entrySet()) {
- close(entry.getValue(), entry.getKey().toString());
- }
- } catch (UncheckedIOException e) {
- cleanUpQuietly();
- throw e;
- } finally {
- openFiles.clear();
- }
- }
-
- private void cleanUpQuietly() {
- try {
- stoppable(openFiles.values()).stop();
- } catch (Exception e) {
- LOG.debug("Problems closing files", e);
- } finally {
- openFiles.clear();
- }
- }
-
- private void close(Closeable c, String displayName) {
- try {
- c.close();
- } catch (IOException e) {
- throw new UncheckedIOException("Problems closing file: " + displayName, e);
- }
- }
-}
\ No newline at end of file
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/InMemoryTestResultsProvider.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/InMemoryTestResultsProvider.java
new file mode 100644
index 0000000..6eee582
--- /dev/null
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/InMemoryTestResultsProvider.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.tasks.testing.junit.result;
+
+import org.gradle.api.Action;
+import org.gradle.api.tasks.testing.TestOutputEvent;
+
+import java.io.IOException;
+import java.io.Writer;
+
+public class InMemoryTestResultsProvider implements TestResultsProvider {
+ private final Iterable<TestClassResult> results;
+ private final TestOutputStore.Reader outputReader;
+
+ public InMemoryTestResultsProvider(Iterable<TestClassResult> results, TestOutputStore.Reader outputReader) {
+ this.results = results;
+ this.outputReader = outputReader;
+ }
+
+ public boolean hasOutput(long id, TestOutputEvent.Destination destination) {
+ return outputReader.hasOutput(id, destination);
+ }
+
+ public void writeAllOutput(long id, TestOutputEvent.Destination destination, Writer writer) {
+ outputReader.writeAllOutput(id, destination, writer);
+ }
+
+ public void writeNonTestOutput(long id, TestOutputEvent.Destination destination, Writer writer) {
+ outputReader.writeNonTestOutput(id, destination, writer);
+ }
+
+ public void writeTestOutput(long classId, long testId, TestOutputEvent.Destination destination, Writer writer) {
+ outputReader.writeTestOutput(classId, testId, destination, writer);
+ }
+
+ public void visitClasses(final Action<? super TestClassResult> visitor) {
+ for (TestClassResult result : results) {
+ visitor.execute(result);
+ }
+ }
+
+ public boolean isHasResults() {
+ return results.iterator().hasNext();
+ }
+
+ public void close() throws IOException {
+ outputReader.close();
+ }
+}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/JUnitXmlResultWriter.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/JUnitXmlResultWriter.java
index b2a06ee..da3de32 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/JUnitXmlResultWriter.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/JUnitXmlResultWriter.java
@@ -28,21 +28,22 @@ import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
-/**
- * by Szczepan Faber, created at: 11/13/12
- */
public class JUnitXmlResultWriter {
private final String hostName;
private final TestResultsProvider testResultsProvider;
+ private final TestOutputAssociation outputAssociation;
- public JUnitXmlResultWriter(String hostName, TestResultsProvider testResultsProvider) {
+ public JUnitXmlResultWriter(String hostName, TestResultsProvider testResultsProvider, TestOutputAssociation outputAssociation) {
this.hostName = hostName;
this.testResultsProvider = testResultsProvider;
+ this.outputAssociation = outputAssociation;
}
public void write(TestClassResult result, OutputStream output) {
String className = result.getClassName();
+ long classId = result.getId();
+
try {
SimpleXmlWriter writer = new SimpleXmlWriter(output, " ");
writer.startElement("testsuite")
@@ -57,27 +58,38 @@ public class JUnitXmlResultWriter {
writer.startElement("properties");
writer.endElement();
- writeTests(writer, result.getResults(), className);
+ writeTests(writer, result.getResults(), className, classId);
writer.startElement("system-out");
- writeOutputs(writer, className, TestOutputEvent.Destination.StdOut);
+ writeOutputs(writer, classId, outputAssociation.equals(TestOutputAssociation.WITH_SUITE), TestOutputEvent.Destination.StdOut);
writer.endElement();
writer.startElement("system-err");
- writeOutputs(writer, className, TestOutputEvent.Destination.StdErr);
+ writeOutputs(writer, classId, outputAssociation.equals(TestOutputAssociation.WITH_SUITE), TestOutputEvent.Destination.StdErr);
writer.endElement();
+
writer.endElement();
} catch (IOException e) {
throw UncheckedException.throwAsUncheckedException(e);
}
}
- private void writeOutputs(SimpleXmlWriter writer, String className, TestOutputEvent.Destination destination) throws IOException {
+ private void writeOutputs(SimpleXmlWriter writer, long classId, boolean allClassOutput, TestOutputEvent.Destination destination) throws IOException {
writer.startCDATA();
- testResultsProvider.writeOutputs(className, destination, writer);
+ if (allClassOutput) {
+ testResultsProvider.writeAllOutput(classId, destination, writer);
+ } else {
+ testResultsProvider.writeNonTestOutput(classId, destination, writer);
+ }
writer.endCDATA();
}
- private void writeTests(SimpleXmlWriter writer, Iterable<TestMethodResult> methodResults, String className) throws IOException {
+ private void writeOutputs(SimpleXmlWriter writer, long classId, long testId, TestOutputEvent.Destination destination) throws IOException {
+ writer.startCDATA();
+ testResultsProvider.writeTestOutput(classId, testId, destination, writer);
+ writer.endCDATA();
+ }
+
+ private void writeTests(SimpleXmlWriter writer, Iterable<TestMethodResult> methodResults, String className, long classId) throws IOException {
for (TestMethodResult methodResult : methodResults) {
String testCase = methodResult.getResultType() == TestResult.ResultType.SKIPPED ? "ignored-testcase" : "testcase";
writer.startElement(testCase)
@@ -94,6 +106,16 @@ public class JUnitXmlResultWriter {
writer.endElement();
}
+
+ if (outputAssociation.equals(TestOutputAssociation.WITH_TESTCASE)) {
+ writer.startElement("system-out");
+ writeOutputs(writer, classId, methodResult.getId(), TestOutputEvent.Destination.StdOut);
+ writer.endElement();
+ writer.startElement("system-err");
+ writeOutputs(writer, classId, methodResult.getId(), TestOutputEvent.Destination.StdErr);
+ writer.endElement();
+ }
+
writer.endElement();
}
}
@@ -102,7 +124,7 @@ public class JUnitXmlResultWriter {
try {
return throwable.toString();
} catch (Throwable t) {
- String exceptionClassName = throwable instanceof PlaceholderException ? ((PlaceholderException)throwable).getExceptionClassName() : throwable.getClass().getName();
+ String exceptionClassName = throwable instanceof PlaceholderException ? ((PlaceholderException) throwable).getExceptionClassName() : throwable.getClass().getName();
return String.format("Could not determine failure message for exception of type %s: %s",
exceptionClassName, t);
}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestClassResult.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestClassResult.java
index 75f7bd6..6835240 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestClassResult.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestClassResult.java
@@ -21,20 +21,26 @@ import org.gradle.api.tasks.testing.TestResult;
import java.util.ArrayList;
import java.util.List;
-/**
- * by Szczepan Faber, created at: 11/13/12
- */
public class TestClassResult {
private final List<TestMethodResult> methodResults = new ArrayList<TestMethodResult>();
private final String className;
private final long startTime;
private int failuresCount;
+ private long id;
- public TestClassResult(String className, long startTime) {
+ public TestClassResult(long id, String className, long startTime) {
+ if (id < 1) {
+ throw new IllegalArgumentException("id must be > 0");
+ }
+ this.id = id;
this.className = className;
this.startTime = startTime;
}
+ public long getId() {
+ return id;
+ }
+
public String getClassName() {
return className;
}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestMethodResult.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestMethodResult.java
index 39121c2..0b768f5 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestMethodResult.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestMethodResult.java
@@ -20,17 +20,16 @@ import org.gradle.api.tasks.testing.TestResult;
import java.util.List;
-/**
- * by Szczepan Faber, created at: 11/13/12
- */
public class TestMethodResult {
+ private final long id;
private final String name;
private final TestResult.ResultType resultType;
private final long duration;
private final long endTime;
private final List<Throwable> exceptions;
- public TestMethodResult(String name, TestResult result) {
+ public TestMethodResult(long id, String name, TestResult result) {
+ this.id = id;
this.name = name;
resultType = result.getResultType();
duration = result.getEndTime() - result.getStartTime();
@@ -38,7 +37,11 @@ public class TestMethodResult {
exceptions = result.getExceptions();
}
- public TestMethodResult(String name, TestResult.ResultType resultType, long duration, long endTime, List<Throwable> exceptions) {
+ public TestMethodResult(long id, String name, TestResult.ResultType resultType, long duration, long endTime, List<Throwable> exceptions) {
+ if (id < 1) {
+ throw new IllegalArgumentException("id must be > 0");
+ }
+ this.id = id;
this.name = name;
this.resultType = resultType;
this.duration = duration;
@@ -46,6 +49,10 @@ public class TestMethodResult {
this.exceptions = exceptions;
}
+ public long getId() {
+ return id;
+ }
+
public String getName() {
return name;
}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestOutputAssociation.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestOutputAssociation.java
new file mode 100644
index 0000000..40e4c83
--- /dev/null
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestOutputAssociation.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.tasks.testing.junit.result;
+
+public enum TestOutputAssociation {
+ WITH_SUITE,
+ WITH_TESTCASE
+}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestOutputSerializer.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestOutputSerializer.java
deleted file mode 100644
index 929394f..0000000
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestOutputSerializer.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.tasks.testing.junit.result;
-
-import org.gradle.api.UncheckedIOException;
-import org.gradle.api.tasks.testing.TestOutputEvent;
-
-import java.io.*;
-
-/**
- * Assembles test results. Keeps a copy of the results in memory to provide them later and spools test output to file.
- *
- * by Szczepan Faber, created at: 11/13/12
- */
-public class TestOutputSerializer {
- private final File resultsDir;
- private final CachingFileWriter cachingFileWriter;
-
- public TestOutputSerializer(File resultsDir) {
- //TODO SF calculate number of open files based on parallel forks
- this(resultsDir, new CachingFileWriter(10));
- }
-
- private TestOutputSerializer(File resultsDir, CachingFileWriter cachingFileWriter) {
- this.resultsDir = resultsDir;
- this.cachingFileWriter = cachingFileWriter;
- }
-
- private File outputsFile(String className, TestOutputEvent.Destination destination) {
- return destination == TestOutputEvent.Destination.StdOut ? standardOutputFile(className) : standardErrorFile(className);
- }
-
- private File standardErrorFile(String className) {
- return new File(resultsDir, className + ".stderr");
- }
-
- private File standardOutputFile(String className) {
- return new File(resultsDir, className + ".stdout");
- }
-
- public boolean hasOutput(String className, TestOutputEvent.Destination destination){
- return outputsFile(className, destination).exists();
- }
-
- public void writeOutputs(String className, TestOutputEvent.Destination destination, Writer writer) {
- final File file = outputsFile(className, destination);
- if (!file.exists()) {
- return;
- }
- try {
- Reader reader = new InputStreamReader(new BufferedInputStream(new FileInputStream(file)), "UTF-8");
- try {
- char[] buffer = new char[2048];
- while (true) {
- int read = reader.read(buffer);
- if (read < 0) {
- return;
- }
- writer.write(buffer, 0, read);
- }
- } finally {
- reader.close();
- }
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public void finishOutputs() {
- cachingFileWriter.closeAll();
- }
-
- public void onOutput(String className, TestOutputEvent.Destination destination, String message) {
- cachingFileWriter.write(outputsFile(className, destination), message);
- }
-}
\ No newline at end of file
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestOutputStore.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestOutputStore.java
new file mode 100644
index 0000000..fbc4ef1
--- /dev/null
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestOutputStore.java
@@ -0,0 +1,388 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.tasks.testing.junit.result;
+
+import com.esotericsoftware.kryo.io.Input;
+import com.esotericsoftware.kryo.io.Output;
+import com.google.common.collect.ImmutableMap;
+import org.gradle.api.UncheckedIOException;
+import org.gradle.api.tasks.testing.TestOutputEvent;
+import org.gradle.internal.UncheckedException;
+import org.gradle.util.GFileUtils;
+
+import java.io.*;
+import java.nio.charset.Charset;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+public class TestOutputStore {
+
+ private final File resultsDir;
+ private final Charset messageStorageCharset;
+
+ public TestOutputStore(File resultsDir) {
+ this.resultsDir = resultsDir;
+ this.messageStorageCharset = Charset.forName("UTF-8");
+ }
+
+ File getOutputsFile() {
+ return new File(resultsDir, "output.bin");
+ }
+
+ File getIndexFile() {
+ return new File(resultsDir, getOutputsFile().getName() + ".idx");
+ }
+
+ private static class Region {
+ long start;
+ long stop;
+
+ private Region() {
+ start = -1;
+ stop = -1;
+ }
+
+ private Region(long start, long stop) {
+ this.start = start;
+ this.stop = stop;
+ }
+ }
+
+ private static class TestCaseRegion {
+ Region stdOutRegion = new Region();
+ Region stdErrRegion = new Region();
+ }
+
+ public class Writer implements Closeable {
+ private final Output output;
+
+ private final Map<Long, Map<Long, TestCaseRegion>> index = new LinkedHashMap<Long, Map<Long, TestCaseRegion>>();
+
+ public Writer() {
+ try {
+ output = new Output(new FileOutputStream(getOutputsFile()));
+ } catch (FileNotFoundException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+
+ public void close() {
+ output.close();
+ writeIndex();
+ }
+
+ public void onOutput(long classId, TestOutputEvent outputEvent) {
+ onOutput(classId, 0, outputEvent);
+ }
+
+ public void onOutput(long classId, long testId, TestOutputEvent outputEvent) {
+ boolean stdout = outputEvent.getDestination() == TestOutputEvent.Destination.StdOut;
+ mark(classId, testId, stdout);
+
+ output.writeBoolean(stdout);
+ output.writeLong(classId);
+ output.writeLong(testId);
+
+ byte[] bytes;
+ try {
+ bytes = outputEvent.getMessage().getBytes(messageStorageCharset.name());
+ } catch (UnsupportedEncodingException e) {
+ throw UncheckedException.throwAsUncheckedException(e);
+ }
+ output.writeInt(bytes.length);
+ output.writeBytes(bytes);
+ }
+
+ private void mark(long classId, long testId, boolean isStdout) {
+ if (!index.containsKey(classId)) {
+ index.put(classId, new LinkedHashMap<Long, TestCaseRegion>());
+ }
+
+ Map<Long, TestCaseRegion> testCaseRegions = index.get(classId);
+ if (!testCaseRegions.containsKey(testId)) {
+ TestCaseRegion region = new TestCaseRegion();
+ testCaseRegions.put(testId, region);
+ }
+
+ TestCaseRegion region = testCaseRegions.get(testId);
+
+ Region streamRegion = isStdout ? region.stdOutRegion : region.stdErrRegion;
+
+ int total = output.total();
+ if (streamRegion.start < 0) {
+ streamRegion.start = total;
+ }
+ streamRegion.stop = total;
+ }
+
+ private void writeIndex() {
+ Output indexOutput;
+ try {
+ indexOutput = new Output(new FileOutputStream(getIndexFile()));
+ } catch (FileNotFoundException e) {
+ throw new UncheckedIOException(e);
+ }
+
+
+ try {
+ indexOutput.writeInt(index.size(), true);
+
+ for (Map.Entry<Long, Map<Long, TestCaseRegion>> classEntry : index.entrySet()) {
+ Long classId = classEntry.getKey();
+ Map<Long, TestCaseRegion> regions = classEntry.getValue();
+
+ indexOutput.writeLong(classId, true);
+ indexOutput.writeInt(regions.size(), true);
+
+ for (Map.Entry<Long, TestCaseRegion> testCaseEntry : regions.entrySet()) {
+ long id = testCaseEntry.getKey();
+ TestCaseRegion region = testCaseEntry.getValue();
+ indexOutput.writeLong(id, true);
+ indexOutput.writeLong(region.stdOutRegion.start);
+ indexOutput.writeLong(region.stdOutRegion.stop);
+ indexOutput.writeLong(region.stdErrRegion.start);
+ indexOutput.writeLong(region.stdErrRegion.stop);
+ }
+ }
+ } finally {
+ indexOutput.close();
+ }
+ }
+ }
+
+ public Writer writer() {
+ return new Writer();
+ }
+
+ private static class Index {
+ final ImmutableMap<Long, Index> children;
+ final Region stdOut;
+ final Region stdErr;
+
+ private Index() {
+ this(new Region(), new Region());
+ }
+
+ private Index(Region stdOut, Region stdErr) {
+ this.children = ImmutableMap.of();
+ this.stdOut = stdOut;
+ this.stdErr = stdErr;
+ }
+
+ private Index(ImmutableMap<Long, Index> children, Region stdOut, Region stdErr) {
+ this.children = children;
+ this.stdOut = stdOut;
+ this.stdErr = stdErr;
+ }
+ }
+
+ private static class IndexBuilder {
+ final Region stdOut = new Region();
+ final Region stdErr = new Region();
+
+ private final ImmutableMap.Builder<Long, Index> children = ImmutableMap.builder();
+
+ void add(long key, Index index) {
+ if (stdOut.start < 0) {
+ stdOut.start = index.stdOut.start;
+ }
+ if (stdErr.start < 0) {
+ stdErr.start = index.stdErr.start;
+ }
+ if (index.stdOut.stop > stdOut.stop) {
+ stdOut.stop = index.stdOut.stop;
+ }
+ if (index.stdErr.stop > stdErr.stop) {
+ stdErr.stop = index.stdErr.stop;
+ }
+
+ children.put(key, index);
+ }
+
+ Index build() {
+ return new Index(children.build(), stdOut, stdErr);
+ }
+ }
+
+ public class Reader implements Closeable {
+
+ private final static int RECORD_HEADER_LENGTH = 1 + 8 + 8 + 4; // bool(1) + long(8) + long(8) + int(4)
+
+ private final Index index;
+ private final RandomAccessFile dataFile;
+ private byte[] recordHeaderBuffer = new byte[RECORD_HEADER_LENGTH];
+
+ public Reader() {
+ File indexFile = getIndexFile();
+ File outputsFile = getOutputsFile();
+
+ if (outputsFile.exists()) {
+ if (!indexFile.exists()) {
+ throw new IllegalStateException(String.format("Test outputs data file '{}' exists but the index file '{}' does not", outputsFile, indexFile));
+ }
+
+ Input input;
+ try {
+ input = new Input(new FileInputStream(indexFile));
+ } catch (FileNotFoundException e) {
+ throw new UncheckedIOException(e);
+ }
+
+ IndexBuilder rootBuilder = null;
+ try {
+ int numClasses = input.readInt(true);
+ rootBuilder = new IndexBuilder();
+
+ for (int classCounter = 0; classCounter < numClasses; ++classCounter) {
+ long classId = input.readLong(true);
+ IndexBuilder classBuilder = new IndexBuilder();
+
+ int numEntries = input.readInt(true);
+ for (int entryCounter = 0; entryCounter < numEntries; ++entryCounter) {
+ long testId = input.readLong(true);
+ Region stdOut = new Region(input.readLong(), input.readLong());
+ Region stdErr = new Region(input.readLong(), input.readLong());
+ classBuilder.add(testId, new Index(stdOut, stdErr));
+ }
+
+ rootBuilder.add(classId, classBuilder.build());
+ }
+ } finally {
+ input.close();
+ }
+
+ index = rootBuilder.build();
+ } else { // no outputs file
+ if (indexFile.exists()) {
+ throw new IllegalStateException(String.format("Test outputs data file '{}' does not exist but the index file '{}' does", outputsFile, indexFile));
+ }
+
+ GFileUtils.touch(getOutputsFile());
+ index = new Index();
+ }
+
+ try {
+ dataFile = new RandomAccessFile(getOutputsFile(), "r");
+ } catch (FileNotFoundException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+
+ public void close() throws IOException {
+ dataFile.close();
+ }
+
+ public boolean hasOutput(long classId, TestOutputEvent.Destination destination) {
+ Index classIndex = index.children.get(classId);
+ if (classIndex == null) {
+ return false;
+ } else {
+ Region region = destination == TestOutputEvent.Destination.StdOut ? classIndex.stdOut : classIndex.stdErr;
+ return region.start >= 0;
+ }
+ }
+
+ public void writeAllOutput(long classId, TestOutputEvent.Destination destination, java.io.Writer writer) {
+ doRead(classId, 0, true, destination, writer);
+ }
+
+ public void writeNonTestOutput(long classId, TestOutputEvent.Destination destination, java.io.Writer writer) {
+ doRead(classId, 0, false, destination, writer);
+ }
+
+ public void writeTestOutput(long classId, long testId, TestOutputEvent.Destination destination, java.io.Writer writer) {
+ doRead(classId, testId, false, destination, writer);
+ }
+
+ private void doRead(long classId, long testId, boolean allClassOutput, TestOutputEvent.Destination destination, java.io.Writer writer) {
+ Index targetIndex = index.children.get(classId);
+ if (targetIndex != null && testId != 0) {
+ targetIndex = targetIndex.children.get(testId);
+ }
+
+ if (targetIndex == null) {
+ return;
+ }
+
+ boolean stdout = destination == TestOutputEvent.Destination.StdOut;
+ Region region = stdout ? targetIndex.stdOut : targetIndex.stdErr;
+
+ if (region.start < 0) {
+ return;
+ }
+
+ boolean ignoreClassLevel = !allClassOutput && testId != 0;
+ boolean ignoreTestLevel = !allClassOutput && testId == 0;
+
+ try {
+ dataFile.seek(region.start);
+
+ while (dataFile.getFilePointer() <= region.stop) {
+ dataFile.read(recordHeaderBuffer);
+ Input input = new Input(recordHeaderBuffer);
+ boolean readStdout = input.readBoolean();
+ long readClassId = input.readLong();
+ long readTestId = input.readLong();
+ int readLength = input.readInt();
+ input.close();
+
+ boolean isClassLevel = readTestId == 0;
+
+ if (stdout != readStdout || classId != readClassId) {
+ dataFile.skipBytes(readLength);
+ continue;
+ }
+
+ if (ignoreClassLevel && isClassLevel) {
+ dataFile.skipBytes(readLength);
+ continue;
+ }
+
+ if (ignoreTestLevel && !isClassLevel) {
+ dataFile.skipBytes(readLength);
+ continue;
+ }
+
+ if (testId == 0 || testId == readTestId) {
+ byte[] stringBytes = new byte[readLength];
+ dataFile.read(stringBytes);
+ String message;
+ try {
+ message = new String(stringBytes, messageStorageCharset.name());
+ } catch (UnsupportedEncodingException e) {
+ // shouldn't happen
+ throw UncheckedException.throwAsUncheckedException(e);
+ }
+
+ writer.write(message);
+ } else {
+ dataFile.skipBytes(readLength);
+ continue;
+ }
+ }
+ } catch (IOException e1) {
+ throw new UncheckedIOException(e1);
+ }
+
+ }
+ }
+
+ // IMPORTANT: return must be closed when done with.
+ public Reader reader() {
+ return new Reader();
+ }
+}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestReportDataCollector.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestReportDataCollector.java
index 8b0ab17..e34c7cd 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestReportDataCollector.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestReportDataCollector.java
@@ -16,47 +16,32 @@
package org.gradle.api.internal.tasks.testing.junit.result;
-import org.gradle.api.Action;
+import org.gradle.api.internal.tasks.testing.TestDescriptorInternal;
import org.gradle.api.tasks.testing.*;
-import java.io.File;
-import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
/**
- * Assembles test results. Keeps a copy of the results in memory to provide them later and spools test output to file.
- *
- * by Szczepan Faber, created at: 11/13/12
+ * Collects the test results into memory and spools the test output to file during execution (to avoid holding it all in memory).
*/
-public class TestReportDataCollector implements TestListener, TestOutputListener, TestResultsProvider {
- private final Map<String, TestClassResult> results = new HashMap<String, TestClassResult>();
- private final TestResultSerializer resultSerializer;
- private final File resultsDir;
- private final TestOutputSerializer outputSerializer;
-
- public TestReportDataCollector(File resultsDir) {
- this(resultsDir, new TestOutputSerializer(resultsDir), new TestResultSerializer());
- }
+public class TestReportDataCollector implements TestListener, TestOutputListener {
+
+ private final Map<String, TestClassResult> results;
+ private final TestOutputStore.Writer outputWriter;
+
+ private final Map<Object, Long> idMappings = new HashMap<Object, Long>();
+ private long internalIdCounter = 1;
- TestReportDataCollector(File resultsDir, TestOutputSerializer outputSerializer, TestResultSerializer resultSerializer) {
- this.resultsDir = resultsDir;
- this.outputSerializer = outputSerializer;
- this.resultSerializer = resultSerializer;
+ public TestReportDataCollector(Map<String, TestClassResult> results, TestOutputStore.Writer outputWriter) {
+ this.results = results;
+ this.outputWriter = outputWriter;
}
public void beforeSuite(TestDescriptor suite) {
}
public void afterSuite(TestDescriptor suite, TestResult result) {
- if (suite.getParent() == null) {
- outputSerializer.finishOutputs();
- writeResults();
- }
- }
-
- private void writeResults() {
- resultSerializer.write(results.values(), resultsDir);
}
public void beforeTest(TestDescriptor testDescriptor) {
@@ -65,10 +50,10 @@ public class TestReportDataCollector implements TestListener, TestOutputListener
public void afterTest(TestDescriptor testDescriptor, TestResult result) {
if (!testDescriptor.isComposite()) {
String className = testDescriptor.getClassName();
- TestMethodResult methodResult = new TestMethodResult(testDescriptor.getName(), result);
+ TestMethodResult methodResult = new TestMethodResult(getInternalId((TestDescriptorInternal) testDescriptor), testDescriptor.getName(), result);
TestClassResult classResult = results.get(className);
if (classResult == null) {
- classResult = new TestClassResult(className, result.getStartTime());
+ classResult = new TestClassResult(internalIdCounter++, className, result.getStartTime());
results.put(className, classResult);
}
classResult.add(methodResult);
@@ -82,25 +67,32 @@ public class TestReportDataCollector implements TestListener, TestOutputListener
//we don't have a place for such output in any of the reports so skipping.
return;
}
+ TestDescriptorInternal testDescriptorInternal = (TestDescriptorInternal) testDescriptor;
TestClassResult classResult = results.get(className);
if (classResult == null) {
- classResult = new TestClassResult(className, 0);
+ classResult = new TestClassResult(internalIdCounter++, className, 0);
results.put(className, classResult);
}
- outputSerializer.onOutput(className, outputEvent.getDestination(), outputEvent.getMessage());
- }
- public void visitClasses(Action<? super TestClassResult> visitor) {
- for (TestClassResult classResult : results.values()) {
- visitor.execute(classResult);
- }
- }
+ String name = testDescriptor.getName();
- public boolean hasOutput(String className, TestOutputEvent.Destination destination) {
- return outputSerializer.hasOutput(className, destination);
+ // This is a rather weak contract, but given the current inputs is the best we can do
+ boolean isClassLevelOutput = name.equals(className);
+
+ if (isClassLevelOutput) {
+ outputWriter.onOutput(classResult.getId(), outputEvent);
+ } else {
+ outputWriter.onOutput(classResult.getId(), getInternalId(testDescriptorInternal), outputEvent);
+ }
}
- public void writeOutputs(String className, TestOutputEvent.Destination destination, Writer writer) {
- outputSerializer.writeOutputs(className, destination, writer);
+ private long getInternalId(TestDescriptorInternal testDescriptor) {
+ Object id = testDescriptor.getId();
+ Long internalId = idMappings.get(id);
+ if (internalId == null) {
+ internalId = internalIdCounter++;
+ idMappings.put(id, internalId);
+ }
+ return internalId;
}
}
\ No newline at end of file
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestResultSerializer.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestResultSerializer.java
index 51a3f3a..69dbbe5 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestResultSerializer.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestResultSerializer.java
@@ -31,16 +31,23 @@ import java.util.List;
public class TestResultSerializer {
private static final int RESULT_VERSION = 1;
- private static final String RESULTS_FILE_NAME = "results.bin";
- public void write(Collection<TestClassResult> results, File outputDir) {
+ private final File resultsFile;
+
+ public TestResultSerializer(File resultsDir) {
+ this.resultsFile = new File(resultsDir, "results.bin");
+ }
+
+ public void write(Collection<TestClassResult> results) {
try {
- OutputStream outputStream = new FileOutputStream(new File(outputDir, RESULTS_FILE_NAME));
+ OutputStream outputStream = new FileOutputStream(resultsFile);
try {
- Output output = new Output(outputStream);
- output.writeInt(RESULT_VERSION, true);
- write(results, output);
- output.flush();
+ if (!results.isEmpty()) { // only write if we have results, otherwise truncate
+ Output output = new Output(outputStream);
+ output.writeInt(RESULT_VERSION, true);
+ write(results, output);
+ output.flush();
+ }
} finally {
outputStream.close();
}
@@ -57,6 +64,7 @@ public class TestResultSerializer {
}
private void write(TestClassResult classResult, Output output) throws IOException {
+ output.writeLong(classResult.getId(), true);
output.writeString(classResult.getClassName());
output.writeLong(classResult.getStartTime());
output.writeInt(classResult.getResults().size(), true);
@@ -66,6 +74,7 @@ public class TestResultSerializer {
}
private void write(TestMethodResult methodResult, Output output) throws IOException {
+ output.writeLong(methodResult.getId(), true);
output.writeString(methodResult.getName());
output.writeInt(methodResult.getResultType().ordinal(), true);
output.writeLong(methodResult.getDuration(), true);
@@ -78,14 +87,17 @@ public class TestResultSerializer {
}
}
- public void read(File inputDir, Action<? super TestClassResult> visitor) {
+ public void read(Action<? super TestClassResult> visitor) {
+ if (!isHasResults()) {
+ return;
+ }
try {
- InputStream inputStream = new FileInputStream(new File(inputDir, "results.bin"));
+ InputStream inputStream = new FileInputStream(resultsFile);
try {
Input input = new Input(inputStream);
int version = input.readInt(true);
if (version != RESULT_VERSION) {
- throw new IllegalArgumentException(String.format("Unexpected result file version %d found in %s.", version, inputDir));
+ throw new IllegalArgumentException(String.format("Unexpected result file version %d found in %s.", version, resultsFile));
}
readResults(input, visitor);
} finally {
@@ -96,6 +108,10 @@ public class TestResultSerializer {
}
}
+ public boolean isHasResults() {
+ return resultsFile.exists() && resultsFile.length() > 0;
+ }
+
private void readResults(Input input, Action<? super TestClassResult> visitor) throws ClassNotFoundException, IOException {
int classCount = input.readInt(true);
for (int i = 0; i < classCount; i++) {
@@ -105,9 +121,10 @@ public class TestResultSerializer {
}
private TestClassResult readClassResult(Input input) throws IOException, ClassNotFoundException {
+ long id = input.readLong(true);
String className = input.readString();
long startTime = input.readLong();
- TestClassResult result = new TestClassResult(className, startTime);
+ TestClassResult result = new TestClassResult(id, className, startTime);
int testMethodCount = input.readInt(true);
for (int i = 0; i < testMethodCount; i++) {
TestMethodResult methodResult = readMethodResult(input);
@@ -117,6 +134,7 @@ public class TestResultSerializer {
}
private TestMethodResult readMethodResult(Input input) throws ClassNotFoundException, IOException {
+ long id = input.readLong(true);
String name = input.readString();
TestResult.ResultType resultType = TestResult.ResultType.values()[input.readInt(true)];
long duration = input.readLong(true);
@@ -128,6 +146,7 @@ public class TestResultSerializer {
} else {
failures = Collections.emptyList();
}
- return new TestMethodResult(name, resultType, duration, endTime, failures);
+ return new TestMethodResult(id, name, resultType, duration, endTime, failures);
}
+
}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestResultsProvider.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestResultsProvider.java
index 9fc3550..4b2b163 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestResultsProvider.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestResultsProvider.java
@@ -19,21 +19,32 @@ package org.gradle.api.internal.tasks.testing.junit.result;
import org.gradle.api.Action;
import org.gradle.api.tasks.testing.TestOutputEvent;
+import java.io.Closeable;
import java.io.Writer;
-/**
- * by Szczepan Faber, created at: 11/16/12
- */
-public interface TestResultsProvider {
+public interface TestResultsProvider extends Closeable {
/**
* Writes the output of the given test to the given writer. This method must be called only after {@link #visitClasses(org.gradle.api.Action)}.
+ *
+ * Writes all output for the test class.
*/
- void writeOutputs(String className, TestOutputEvent.Destination destination, Writer writer);
+ void writeAllOutput(long id, TestOutputEvent.Destination destination, Writer writer);
+
+ void writeNonTestOutput(long id, TestOutputEvent.Destination destination, Writer writer);
+
+ /**
+ * Writes the output of the given test to the given writer. This method must be called only after {@link #visitClasses(org.gradle.api.Action)}.
+ *
+ * Write all output for the given test case name of the test class.
+ */
+ void writeTestOutput(long classId, long testId, TestOutputEvent.Destination destination, Writer writer);
/**
* Visits the results of each test class, in no specific order. Each class is visited exactly once.
*/
void visitClasses(Action<? super TestClassResult> visitor);
- boolean hasOutput(String className, TestOutputEvent.Destination destination);
+ boolean hasOutput(long id, TestOutputEvent.Destination destination);
+
+ boolean isHasResults();
}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/results/TestState.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/results/TestState.java
index 17dc070..e892c40 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/results/TestState.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/results/TestState.java
@@ -25,11 +25,6 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
-/**
- * Extracted from the StateTrackingTestResultProcessor
- *
- * by Szczepan Faber, created at: 10/14/11
- */
public class TestState {
public final TestDescriptorInternal test;
final TestStartEvent startEvent;
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/results/UnknownTestDescriptor.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/results/UnknownTestDescriptor.java
index 3962a70..8a9fc48 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/results/UnknownTestDescriptor.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/results/UnknownTestDescriptor.java
@@ -15,12 +15,14 @@
*/
package org.gradle.api.internal.tasks.testing.results;
+import org.gradle.api.internal.tasks.testing.TestDescriptorInternal;
import org.gradle.api.tasks.testing.TestDescriptor;
-/**
- * by Szczepan Faber, created at: 1/8/12
- */
-public class UnknownTestDescriptor implements TestDescriptor {
+public class UnknownTestDescriptor implements TestDescriptorInternal {
+
+ public Object getId() {
+ return "Unknown test (possible bug, please report)";
+ }
public String getName() {
return "Unknown test (possible bug, please report)";
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/testng/TestNGDetector.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/testng/TestNGDetector.java
index ae64537..1bd389c 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/testng/TestNGDetector.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/testng/TestNGDetector.java
@@ -23,9 +23,6 @@ import org.slf4j.LoggerFactory;
import java.io.File;
-/**
- * @author Tom Eyckmans
- */
class TestNGDetector extends AbstractTestFrameworkDetector<TestNGTestClassDetecter> {
private static final Logger LOGGER = LoggerFactory.getLogger(TestNGDetector.class);
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/testng/TestNGListenerAdapterFactory.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/testng/TestNGListenerAdapterFactory.java
index a801553..a570dcd 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/testng/TestNGListenerAdapterFactory.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/testng/TestNGListenerAdapterFactory.java
@@ -15,7 +15,8 @@
*/
package org.gradle.api.internal.tasks.testing.testng;
-import org.gradle.util.ReflectionUtil;
+import org.gradle.internal.reflect.JavaReflectionUtil;
+import org.gradle.util.JavaMethod;
import org.testng.ITestListener;
import java.lang.reflect.InvocationHandler;
@@ -42,7 +43,7 @@ class TestNGListenerAdapterFactory {
throw new UnsupportedOperationException("Neither found interface 'org.testng.IConfigurationListener2' nor interface 'org.testng.internal.IConfigurationListener'. Which version of TestNG are you using?");
}
-
+
private Class<?> tryLoadClass(String name) {
try {
return classLoader.loadClass(name);
@@ -50,11 +51,23 @@ class TestNGListenerAdapterFactory {
return null;
}
}
-
+
private ITestListener createProxy(Class<?> configListenerClass, final ITestListener listener) {
- return (ITestListener) Proxy.newProxyInstance(classLoader, new Class<?>[] {ITestListener.class, configListenerClass}, new InvocationHandler() {
- public Object invoke(Object proxy, Method method, Object[] args) {
- return ReflectionUtil.invoke(listener, method.getName(), args);
+ return (ITestListener) Proxy.newProxyInstance(classLoader, new Class<?>[]{ITestListener.class, configListenerClass}, new InvocationHandler() {
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ Class<?> realReturnType = method.getReturnType();
+ Class<?> boxedReturnType = realReturnType;
+ if (!realReturnType.equals(void.class) && realReturnType.isPrimitive()) {
+ boxedReturnType = JavaReflectionUtil.getWrapperTypeForPrimitiveType(realReturnType);
+ }
+
+ return invoke(listener.getClass(), listener, boxedReturnType, method, args);
+ }
+
+ private <T, R> R invoke(Class<T> listenerType, Object listener, Class<R> returnType, Method method, Object[] args) {
+ T listenerCast = listenerType.cast(listener);
+ JavaMethod<T, R> javaMethod = JavaReflectionUtil.method(listenerType, returnType, method.getName(), method.getParameterTypes());
+ return javaMethod.invoke(listenerCast, args);
}
});
}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/testng/TestNGTestClassDetecter.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/testng/TestNGTestClassDetecter.java
index 61e0e5a..ddb4b44 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/testng/TestNGTestClassDetecter.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/testng/TestNGTestClassDetecter.java
@@ -21,9 +21,6 @@ import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
-/**
- * @author Tom Eyckmans
- */
class TestNGTestClassDetecter extends TestClassVisitor {
private boolean isAbstract;
private String className;
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/testng/TestNGTestClassProcessor.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/testng/TestNGTestClassProcessor.java
index ad884ec..fd4a094 100755
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/testng/TestNGTestClassProcessor.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/testng/TestNGTestClassProcessor.java
@@ -25,7 +25,6 @@ import org.gradle.internal.id.IdGenerator;
import org.gradle.logging.StandardOutputRedirector;
import org.gradle.util.CollectionUtils;
import org.gradle.util.GFileUtils;
-import org.gradle.util.ReflectionUtil;
import org.testng.ITestListener;
import org.testng.TestNG;
@@ -79,7 +78,6 @@ public class TestNGTestClassProcessor implements TestClassProcessor {
try {
final Method setAnnotations = TestNG.class.getMethod("setAnnotations");
setAnnotations.invoke(testNg, options.getAnnotations());
- ReflectionUtil.invoke(testNg, "setAnnotations", options.getAnnotations());
} catch (NoSuchMethodException e) {
/* do nothing; method has been removed in TestNG 6.3 */
} catch (Exception e) {
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/testng/TestNGTestFramework.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/testng/TestNGTestFramework.java
index af43966..cd3945f 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/testng/TestNGTestFramework.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/testng/TestNGTestFramework.java
@@ -33,9 +33,6 @@ import java.io.File;
import java.io.Serializable;
import java.util.List;
-/**
- * @author Tom Eyckmans
- */
public class TestNGTestFramework implements TestFramework {
private TestNGOptions options;
private TestNGDetector detector;
@@ -51,7 +48,7 @@ public class TestNGTestFramework implements TestFramework {
public WorkerTestClassProcessorFactory getProcessorFactory() {
options.setTestResources(testTask.getTestSrcDirs());
List<File> suiteFiles = options.getSuites(testTask.getTemporaryDir());
- return new TestClassProcessorFactoryImpl(testTask.getTestReportDir(), new TestNGSpec(options), suiteFiles);
+ return new TestClassProcessorFactoryImpl(testTask.getReports().getHtml().getDestination(), new TestNGSpec(options), suiteFiles);
}
public Action<WorkerProcessBuilder> getWorkerConfigurationAction() {
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/testng/TestNGTestMethodDetecter.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/testng/TestNGTestMethodDetecter.java
index 381a484..e7ef57b 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/testng/TestNGTestMethodDetecter.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/testng/TestNGTestMethodDetecter.java
@@ -22,9 +22,6 @@ import org.objectweb.asm.Opcodes;
import java.util.HashSet;
import java.util.Set;
-/**
- * @author Tom Eyckmans
- */
class TestNGTestMethodDetecter extends MethodVisitor {
private final TestNGTestClassDetecter testClassDetecter;
private final Set<String> testMethodAnnotations = new HashSet<String>();
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/testng/TestNGTestResultProcessorAdapter.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/testng/TestNGTestResultProcessorAdapter.java
index b669ac4..8d549a2 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/testng/TestNGTestResultProcessorAdapter.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/testng/TestNGTestResultProcessorAdapter.java
@@ -70,7 +70,9 @@ public class TestNGTestResultProcessorAdapter implements ITestListener, TestNGCo
TestDescriptorInternal testInternal;
Object parentId;
synchronized (lock) {
- testInternal = new DefaultTestMethodDescriptor(idGenerator.generateId(), iTestResult.getTestClass().getName(), iTestResult.getName());
+ String name = calculateTestCaseName(iTestResult);
+
+ testInternal = new DefaultTestMethodDescriptor(idGenerator.generateId(), iTestResult.getTestClass().getName(), name);
Object oldTestId = tests.put(iTestResult, testInternal.getId());
assert oldTestId == null : "Apparently some other test has started but it hasn't finished. "
+ "Expect the resultProcessor to break. "
@@ -80,6 +82,44 @@ public class TestNGTestResultProcessorAdapter implements ITestListener, TestNGCo
assert parentId != null;
}
resultProcessor.started(testInternal, new TestStartEvent(iTestResult.getStartMillis(), parentId));
+
+ if (iTestResult.getThrowable() instanceof UnrepresentableParameterException) {
+ throw (UnrepresentableParameterException) iTestResult.getThrowable();
+ }
+ }
+
+ private String calculateTestCaseName(ITestResult iTestResult) {
+ Object[] parameters = iTestResult.getParameters();
+ String name = iTestResult.getName();
+ if (parameters != null && parameters.length > 0) {
+ StringBuilder builder = new StringBuilder(name).
+ append("[").
+ append(iTestResult.getMethod().getCurrentInvocationCount()).
+ append("]");
+
+ StringBuilder paramsListBuilder = new StringBuilder("(");
+ int i = 0;
+ for (Object parameter : parameters) {
+ if (parameter == null) {
+ paramsListBuilder.append("null");
+ } else {
+ try {
+ paramsListBuilder.append(parameter.toString());
+ } catch (Exception e) {
+ // This may be thrown by the caller of this method at a later time
+ iTestResult.setThrowable(new UnrepresentableParameterException(iTestResult, i, e));
+ return builder.toString();
+ }
+ }
+ if (++i < parameters.length) {
+ paramsListBuilder.append(", ");
+ }
+ }
+ paramsListBuilder.append(")");
+ return builder.append(paramsListBuilder.toString()).toString();
+ } else {
+ return name;
+ }
}
public void onTestSuccess(ITestResult iTestResult) {
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/testng/UnrepresentableParameterException.java b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/testng/UnrepresentableParameterException.java
new file mode 100644
index 0000000..bd3c319
--- /dev/null
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/internal/tasks/testing/testng/UnrepresentableParameterException.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.tasks.testing.testng;
+
+import org.gradle.api.GradleException;
+import org.testng.ITestResult;
+
+public class UnrepresentableParameterException extends GradleException {
+
+ public UnrepresentableParameterException(ITestResult iTestResult, int paramIndex, Throwable cause) {
+ super(
+ String.format("Parameter %s of iteration %s of method '%s' toString() method threw exception",
+ paramIndex + 1, iTestResult.getMethod().getCurrentInvocationCount() + 1, iTestResult.getName()
+ ),
+ cause
+ );
+ }
+}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/java/archives/Attributes.java b/subprojects/plugins/src/main/groovy/org/gradle/api/java/archives/Attributes.java
index 05b30a3..faba4ac 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/java/archives/Attributes.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/java/archives/Attributes.java
@@ -19,8 +19,6 @@ import java.util.Map;
/**
* Represent the attributes of a manifest section.
- *
- * @author Hans Dockter
*/
public interface Attributes extends Map<String, Object> {
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/java/archives/ManifestException.java b/subprojects/plugins/src/main/groovy/org/gradle/api/java/archives/ManifestException.java
index 0cf3cb6..d757f4e 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/java/archives/ManifestException.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/java/archives/ManifestException.java
@@ -20,8 +20,6 @@ import org.gradle.api.GradleException;
/**
* Is thrown in the case an operation is applied against a {@link org.gradle.api.java.archives.Manifest} that violates
* the Manifest specification.
- *
- * @author Hans Dockter
*/
public class ManifestException extends GradleException {
public ManifestException(String message) {
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/java/archives/internal/DefaultAttributes.java b/subprojects/plugins/src/main/groovy/org/gradle/api/java/archives/internal/DefaultAttributes.java
index 631a7aa..3c9899f 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/java/archives/internal/DefaultAttributes.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/java/archives/internal/DefaultAttributes.java
@@ -23,9 +23,6 @@ import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
-/**
- * @author Hans Dockter
- */
public class DefaultAttributes implements Attributes {
protected Map<String, Object> attributes = new LinkedHashMap<String, Object>();
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/java/archives/internal/DefaultManifest.java b/subprojects/plugins/src/main/groovy/org/gradle/api/java/archives/internal/DefaultManifest.java
index 7463325..1472295 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/java/archives/internal/DefaultManifest.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/java/archives/internal/DefaultManifest.java
@@ -32,9 +32,6 @@ import org.gradle.util.ConfigureUtil;
import java.io.*;
import java.util.*;
-/**
- * @author Hans Dockter
- */
public class DefaultManifest implements org.gradle.api.java.archives.Manifest {
private List<ManifestMergeSpec> manifestMergeSpecs = new ArrayList<ManifestMergeSpec>();
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/java/archives/internal/DefaultManifestMergeDetails.java b/subprojects/plugins/src/main/groovy/org/gradle/api/java/archives/internal/DefaultManifestMergeDetails.java
index 4871cfe..d011aff 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/java/archives/internal/DefaultManifestMergeDetails.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/java/archives/internal/DefaultManifestMergeDetails.java
@@ -17,9 +17,6 @@ package org.gradle.api.java.archives.internal;
import org.gradle.api.java.archives.ManifestMergeDetails;
-/**
- * @author Hans Dockter
- */
public class DefaultManifestMergeDetails implements ManifestMergeDetails {
private String section;
private String key;
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/ApplicationPlugin.groovy b/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/ApplicationPlugin.groovy
index 305fc76..4ab5f9f 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/ApplicationPlugin.groovy
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/ApplicationPlugin.groovy
@@ -15,21 +15,19 @@
*/
package org.gradle.api.plugins
+import org.gradle.api.GradleException
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.file.CopySpec
import org.gradle.api.tasks.JavaExec
import org.gradle.api.tasks.Sync
import org.gradle.api.tasks.application.CreateStartScripts
-import org.gradle.api.tasks.bundling.Zip
-import org.gradle.api.tasks.bundling.Tar
import org.gradle.api.tasks.bundling.AbstractArchiveTask
-import org.gradle.api.GradleException
+import org.gradle.api.tasks.bundling.Tar
+import org.gradle.api.tasks.bundling.Zip
/**
* <p>A {@link Plugin} which runs a project as a Java Application.</p>
- *
- * @author Rene Groeschke
*/
class ApplicationPlugin implements Plugin<Project> {
static final String APPLICATION_PLUGIN_NAME = "application"
@@ -66,25 +64,27 @@ class ApplicationPlugin implements Plugin<Project> {
}
private void addRunTask() {
- def run = project.tasks.add(TASK_RUN_NAME, JavaExec)
+ def run = project.tasks.create(TASK_RUN_NAME, JavaExec)
run.description = "Runs this project as a JVM application"
run.group = APPLICATION_GROUP
run.classpath = project.sourceSets.main.runtimeClasspath
run.conventionMapping.main = { pluginConvention.mainClassName }
+ run.conventionMapping.jvmArgs = { pluginConvention.applicationDefaultJvmArgs }
}
// @Todo: refactor this task configuration to extend a copy task and use replace tokens
private void addCreateScriptsTask() {
- def startScripts = project.tasks.add(TASK_START_SCRIPTS_NAME, CreateStartScripts)
+ def startScripts = project.tasks.create(TASK_START_SCRIPTS_NAME, CreateStartScripts)
startScripts.description = "Creates OS specific scripts to run the project as a JVM application."
startScripts.classpath = project.tasks[JavaPlugin.JAR_TASK_NAME].outputs.files + project.configurations.runtime
startScripts.conventionMapping.mainClassName = { pluginConvention.mainClassName }
startScripts.conventionMapping.applicationName = { pluginConvention.applicationName }
startScripts.conventionMapping.outputDir = { new File(project.buildDir, 'scripts') }
+ startScripts.conventionMapping.defaultJvmOpts = { pluginConvention.applicationDefaultJvmArgs }
}
private void addInstallTask() {
- def installTask = project.tasks.add(TASK_INSTALL_NAME, Sync)
+ def installTask = project.tasks.create(TASK_INSTALL_NAME, Sync)
installTask.description = "Installs the project as a JVM application along with libs and OS specific scripts."
installTask.group = APPLICATION_GROUP
installTask.with pluginConvention.applicationDistribution
@@ -113,7 +113,7 @@ class ApplicationPlugin implements Plugin<Project> {
}
private <T extends AbstractArchiveTask> void addArchiveTask(String name, Class<T> type) {
- def archiveTask = project.tasks.add(name, type)
+ def archiveTask = project.tasks.create(name, type)
archiveTask.description = "Bundles the project as a JVM application with libs and OS specific scripts."
archiveTask.group = APPLICATION_GROUP
archiveTask.conventionMapping.baseName = { pluginConvention.applicationName }
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/ApplicationPluginConvention.groovy b/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/ApplicationPluginConvention.groovy
index 85f3f27..3efa1f2 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/ApplicationPluginConvention.groovy
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/ApplicationPluginConvention.groovy
@@ -20,8 +20,6 @@ import org.gradle.api.file.CopySpec
/**
* <p>A {@link Convention} used for the ApplicationPlugin.</p>
- *
- * @author Rene Groeschke
*/
class ApplicationPluginConvention {
/**
@@ -35,6 +33,11 @@ class ApplicationPluginConvention {
String mainClassName
/**
+ * Array of string arguments to pass to the JVM when running the application
+ */
+ Iterable<String> applicationDefaultJvmArgs = []
+
+ /**
* <p>The specification of the contents of the distribution.</p>
* <p>
* Use this {@link org.gradle.api.file.CopySpec} to include extra files/resource in the application distribution.
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/BasePlugin.java b/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/BasePlugin.java
index ab10950..fd7fc5f 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/BasePlugin.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/BasePlugin.java
@@ -60,7 +60,7 @@ public class BasePlugin implements Plugin<Project> {
}
private void addAssemble(Project project) {
- Task assembleTask = project.getTasks().add(ASSEMBLE_TASK_NAME);
+ Task assembleTask = project.getTasks().create(ASSEMBLE_TASK_NAME);
assembleTask.setDescription("Assembles the outputs of this project.");
assembleTask.setGroup(BUILD_GROUP);
assembleTask.dependsOn(project.getConfigurations().getByName(Dependency.ARCHIVES_CONFIGURATION).getAllArtifacts().getBuildDependencies());
@@ -103,7 +103,7 @@ public class BasePlugin implements Plugin<Project> {
}
private void addClean(final Project project) {
- Delete clean = project.getTasks().add(CLEAN_TASK_NAME, Delete.class);
+ Delete clean = project.getTasks().create(CLEAN_TASK_NAME, Delete.class);
clean.setDescription("Deletes the build directory.");
clean.setGroup(BUILD_GROUP);
clean.delete(new Callable<File>() {
@@ -129,10 +129,10 @@ public class BasePlugin implements Plugin<Project> {
ConfigurationContainer configurations = project.getConfigurations();
project.setProperty("status", "integration");
- Configuration archivesConfiguration = configurations.add(Dependency.ARCHIVES_CONFIGURATION).
+ Configuration archivesConfiguration = configurations.create(Dependency.ARCHIVES_CONFIGURATION).
setDescription("Configuration for archive artifacts.");
- configurations.add(Dependency.DEFAULT_CONFIGURATION).
+ configurations.create(Dependency.DEFAULT_CONFIGURATION).
setDescription("Configuration for default artifacts.");
final DefaultArtifactPublicationSet defaultArtifacts = project.getExtensions().create(
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/GroovyBasePlugin.java b/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/GroovyBasePlugin.java
index 7b85715..92cc706 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/GroovyBasePlugin.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/GroovyBasePlugin.java
@@ -16,42 +16,49 @@
package org.gradle.api.plugins;
-import com.google.common.collect.Lists;
import org.gradle.api.Action;
-import org.gradle.api.Nullable;
import org.gradle.api.Plugin;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.Dependency;
-import org.gradle.api.file.FileCollection;
import org.gradle.api.file.FileTreeElement;
import org.gradle.api.internal.file.FileResolver;
import org.gradle.api.internal.plugins.DslObject;
-import org.gradle.api.internal.plugins.GroovyJarFile;
import org.gradle.api.internal.project.ProjectInternal;
import org.gradle.api.internal.tasks.DefaultGroovySourceSet;
import org.gradle.api.internal.tasks.DefaultSourceSet;
import org.gradle.api.reporting.ReportingExtension;
import org.gradle.api.specs.Spec;
+import org.gradle.api.tasks.GroovyRuntime;
import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.compile.GroovyCompile;
import org.gradle.api.tasks.javadoc.Groovydoc;
+import org.gradle.util.DeprecationLogger;
import javax.inject.Inject;
import java.io.File;
-import java.util.List;
import java.util.concurrent.Callable;
/**
* Extends {@link org.gradle.api.plugins.JavaBasePlugin} to provide support for compiling and documenting Groovy
* source files.
- *
- * @author Hans Dockter
*/
public class GroovyBasePlugin implements Plugin<ProjectInternal> {
+ /**
+ * The name of the configuration holding the Groovy compiler and tools.
+ *
+ * @deprecated Typically, usages of {@code groovy} can simply be replaced with {@code compile}.
+ * In some cases, it may be necessary to additionally configure the {@code groovyClasspath} property
+ * of {@code GroovyCompile} and {@code Groovydoc} tasks.
+ */
+ @Deprecated
public static final String GROOVY_CONFIGURATION_NAME = "groovy";
+ public static final String GROOVY_RUNTIME_EXTENSION_NAME = "groovyRuntime";
+
private final FileResolver fileResolver;
+
private ProjectInternal project;
+ private GroovyRuntime groovyRuntime;
@Inject
public GroovyBasePlugin(FileResolver fileResolver) {
@@ -62,20 +69,40 @@ public class GroovyBasePlugin implements Plugin<ProjectInternal> {
this.project = project;
JavaBasePlugin javaBasePlugin = project.getPlugins().apply(JavaBasePlugin.class);
- project.getConfigurations().add(GROOVY_CONFIGURATION_NAME).setVisible(false).
- setDescription("The Groovy libraries to be used for this Groovy project.");
-
+ configureConfigurations(project);
+ configureGroovyRuntimeExtension();
configureCompileDefaults();
configureSourceSetDefaults(javaBasePlugin);
configureGroovydoc();
}
+ private void configureConfigurations(ProjectInternal project) {
+ Configuration groovyConfiguration = project.getConfigurations().create(GROOVY_CONFIGURATION_NAME).setVisible(false).
+ setDescription("The Groovy libraries to be used for this Groovy project. (Deprecated)");
+ deprecateGroovyConfiguration(groovyConfiguration);
+ }
+
+ private void configureGroovyRuntimeExtension() {
+ groovyRuntime = project.getExtensions().create(GROOVY_RUNTIME_EXTENSION_NAME, GroovyRuntime.class, project);
+ }
+
+ private void deprecateGroovyConfiguration(Configuration groovyConfiguration) {
+ groovyConfiguration.getDependencies().whenObjectAdded(new Action<Dependency>() {
+ public void execute(Dependency dependency) {
+ DeprecationLogger.nagUserOfDiscontinuedConfiguration(GROOVY_CONFIGURATION_NAME, "Typically, usages of 'groovy' "
+ + "can simply be replaced with 'compile'. In some cases, it may be necessary to additionally configure "
+ + "the 'groovyClasspath' property of GroovyCompile and Groovydoc tasks.");
+ }
+ });
+ }
+
private void configureCompileDefaults() {
project.getTasks().withType(GroovyCompile.class, new Action<GroovyCompile>() {
- public void execute(final GroovyCompile compile) { compile.getConventionMapping().map("groovyClasspath", new Callable<Object>() {
+ public void execute(final GroovyCompile compile) {
+ compile.getConventionMapping().map("groovyClasspath", new Callable<Object>() {
public Object call() throws Exception {
- return getGroovyClasspath(compile.getClasspath());
+ return groovyRuntime.inferGroovyClasspath(compile.getClasspath());
}
});
}
@@ -98,7 +125,7 @@ public class GroovyBasePlugin implements Plugin<ProjectInternal> {
sourceSet.getAllSource().source(groovySourceSet.getGroovy());
String compileTaskName = sourceSet.getCompileTaskName("groovy");
- GroovyCompile compile = project.getTasks().add(compileTaskName, GroovyCompile.class);
+ GroovyCompile compile = project.getTasks().create(compileTaskName, GroovyCompile.class);
javaBasePlugin.configureForSourceSet(sourceSet, compile);
compile.dependsOn(sourceSet.getCompileJavaTaskName());
compile.setDescription(String.format("Compiles the %s Groovy source.", sourceSet.getName()));
@@ -114,7 +141,7 @@ public class GroovyBasePlugin implements Plugin<ProjectInternal> {
public void execute(final Groovydoc groovydoc) {
groovydoc.getConventionMapping().map("groovyClasspath", new Callable<Object>() {
public Object call() throws Exception {
- return getGroovyClasspath(groovydoc.getClasspath());
+ return groovyRuntime.inferGroovyClasspath(groovydoc.getClasspath());
}
});
groovydoc.getConventionMapping().map("destinationDir", new Callable<Object>() {
@@ -136,43 +163,7 @@ public class GroovyBasePlugin implements Plugin<ProjectInternal> {
});
}
- private FileCollection getGroovyClasspath(FileCollection classpath) {
- Configuration groovyConfiguration = project.getConfigurations().getByName(GROOVY_CONFIGURATION_NAME);
- if (!groovyConfiguration.getDependencies().isEmpty()) { return groovyConfiguration; }
-
- GroovyJarFile groovyJar = findGroovyJarFile(classpath);
- if (groovyJar == null) { return groovyConfiguration; }
-
- if (groovyJar.isGroovyAll()) {
- return project.files(groovyJar.getFile());
- }
-
- if (project.getRepositories().isEmpty()) {
- return groovyConfiguration;
- }
-
- String notation = groovyJar.getDependencyNotation();
- List<Dependency> dependencies = Lists.newArrayList();
- // project.getDependencies().create(String) seems to be the only feasible way to create a Dependency with a classifier
- dependencies.add(project.getDependencies().create(notation));
- if (groovyJar.getVersion().getMajor() >= 2) {
- // add groovy-ant to bring in AntGroovyCompiler
- dependencies.add(project.getDependencies().create(notation.replace(":groovy:", ":groovy-ant:")));
- }
- return project.getConfigurations().detachedConfiguration(dependencies.toArray(new Dependency[dependencies.size()]));
- }
-
private JavaPluginConvention java(Convention convention) {
return convention.getPlugin(JavaPluginConvention.class);
}
-
- @Nullable
- private GroovyJarFile findGroovyJarFile(Iterable<File> classpath) {
- if (classpath == null) { return null; }
- for (File file : classpath) {
- GroovyJarFile groovyJar = GroovyJarFile.parse(file);
- if (groovyJar != null) { return groovyJar; }
- }
- return null;
- }
}
\ No newline at end of file
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/GroovyPlugin.java b/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/GroovyPlugin.java
index a2fbe8f..8e90970 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/GroovyPlugin.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/GroovyPlugin.java
@@ -26,8 +26,6 @@ import org.gradle.api.tasks.javadoc.Groovydoc;
/**
* <p>A {@link Plugin} which extends the {@link JavaPlugin} to provide support for compiling and documenting Groovy
* source files.</p>
- *
- * @author Hans Dockter
*/
public class GroovyPlugin implements Plugin<Project> {
public static final String GROOVYDOC_TASK_NAME = "groovydoc";
@@ -46,7 +44,7 @@ public class GroovyPlugin implements Plugin<Project> {
}
private void configureGroovydoc(final Project project) {
- Groovydoc groovyDoc = project.getTasks().add(GROOVYDOC_TASK_NAME, Groovydoc.class);
+ Groovydoc groovyDoc = project.getTasks().create(GROOVYDOC_TASK_NAME, Groovydoc.class);
groovyDoc.setDescription("Generates Groovydoc API documentation for the main source code.");
groovyDoc.setGroup(JavaBasePlugin.DOCUMENTATION_GROUP);
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/JavaBasePlugin.java b/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/JavaBasePlugin.java
index 3a8b519..51e405b 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/JavaBasePlugin.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/JavaBasePlugin.java
@@ -23,11 +23,9 @@ import org.gradle.api.internal.ConventionMapping;
import org.gradle.api.internal.IConventionAware;
import org.gradle.api.internal.plugins.DslObject;
import org.gradle.api.internal.project.ProjectInternal;
-import org.gradle.api.internal.tasks.DefaultJavaSourceSet;
-import org.gradle.api.internal.tasks.DefaultResourceSet;
import org.gradle.api.internal.tasks.SourceSetCompileClasspath;
import org.gradle.api.reporting.ReportingExtension;
-import org.gradle.api.tasks.*;
+import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.compile.AbstractCompile;
import org.gradle.api.tasks.compile.JavaCompile;
import org.gradle.api.tasks.javadoc.Javadoc;
@@ -36,6 +34,14 @@ import org.gradle.api.tasks.testing.TestDescriptor;
import org.gradle.api.tasks.testing.TestListener;
import org.gradle.api.tasks.testing.TestResult;
import org.gradle.internal.reflect.Instantiator;
+import org.gradle.language.base.BinaryContainer;
+import org.gradle.language.base.FunctionalSourceSet;
+import org.gradle.language.base.ProjectSourceSet;
+import org.gradle.language.java.internal.DefaultJavaSourceSet;
+import org.gradle.language.jvm.ClassDirectoryBinary;
+import org.gradle.language.jvm.Classpath;
+import org.gradle.language.jvm.ResourceSet;
+import org.gradle.language.jvm.internal.DefaultResourceSet;
import org.gradle.util.WrapUtil;
import javax.inject.Inject;
@@ -44,8 +50,6 @@ import java.util.concurrent.Callable;
/**
* <p>A {@link org.gradle.api.Plugin} which compiles and tests Java source, and assembles it into a JAR file.</p>
- *
- * @author Hans Dockter
*/
public class JavaBasePlugin implements Plugin<Project> {
public static final String CHECK_TASK_NAME = "check";
@@ -93,18 +97,18 @@ public class JavaBasePlugin implements Plugin<Project> {
Configuration compileConfiguration = configurations.findByName(sourceSet.getCompileConfigurationName());
if (compileConfiguration == null) {
- compileConfiguration = configurations.add(sourceSet.getCompileConfigurationName());
+ compileConfiguration = configurations.create(sourceSet.getCompileConfigurationName());
}
compileConfiguration.setVisible(false);
- compileConfiguration.setDescription(String.format("Classpath for compiling the %s sources.", sourceSet.getName()));
+ compileConfiguration.setDescription(String.format("Compile classpath for %s.", sourceSet));
Configuration runtimeConfiguration = configurations.findByName(sourceSet.getRuntimeConfigurationName());
if (runtimeConfiguration == null) {
- runtimeConfiguration = configurations.add(sourceSet.getRuntimeConfigurationName());
+ runtimeConfiguration = configurations.create(sourceSet.getRuntimeConfigurationName());
}
runtimeConfiguration.setVisible(false);
runtimeConfiguration.extendsFrom(compileConfiguration);
- runtimeConfiguration.setDescription(String.format("Classpath for running the compiled %s classes.", sourceSet.getName()));
+ runtimeConfiguration.setDescription(String.format("Runtime classpath for %s.", sourceSet));
sourceSet.setCompileClasspath(compileConfiguration);
sourceSet.setRuntimeClasspath(sourceSet.getOutput().plus(runtimeConfiguration));
@@ -133,8 +137,8 @@ public class JavaBasePlugin implements Plugin<Project> {
ResourceSet resourceSet = instantiator.newInstance(DefaultResourceSet.class, "resources", sourceSet.getResources(), functionalSourceSet);
functionalSourceSet.add(resourceSet);
- JvmBinaryContainer jvmBinaryContainer = project.getPlugins().getPlugin(JvmLanguagePlugin.class).getJvmBinaryContainer();
- ClassDirectoryBinary binary = jvmBinaryContainer.create(sourceSet.getName(), ClassDirectoryBinary.class);
+ BinaryContainer binaryContainer = project.getExtensions().getByType(BinaryContainer.class);
+ ClassDirectoryBinary binary = binaryContainer.create(String.format("%sClasses", sourceSet.getName()), ClassDirectoryBinary.class);
ConventionMapping conventionMapping = new DslObject(binary).getConventionMapping();
conventionMapping.map("classesDir", new Callable<File>() {
public File call() throws Exception {
@@ -150,8 +154,7 @@ public class JavaBasePlugin implements Plugin<Project> {
binary.getSource().add(javaSourceSet);
binary.getSource().add(resourceSet);
- // TODO:DAZ review this
- binary.getClassesTask().dependsOn(sourceSet.getOutput().getDirs());
+ binary.dependsOn(sourceSet.getOutput().getDirs());
}
});
}
@@ -219,13 +222,13 @@ public class JavaBasePlugin implements Plugin<Project> {
}
private void configureCheck(final Project project) {
- Task checkTask = project.getTasks().add(CHECK_TASK_NAME);
+ Task checkTask = project.getTasks().create(CHECK_TASK_NAME);
checkTask.setDescription("Runs all checks.");
checkTask.setGroup(VERIFICATION_GROUP);
}
private void configureBuild(Project project) {
- DefaultTask buildTask = project.getTasks().add(BUILD_TASK_NAME, DefaultTask.class);
+ DefaultTask buildTask = project.getTasks().create(BUILD_TASK_NAME, DefaultTask.class);
buildTask.setDescription("Assembles and tests this project.");
buildTask.setGroup(BasePlugin.BUILD_GROUP);
buildTask.dependsOn(BasePlugin.ASSEMBLE_TASK_NAME);
@@ -233,14 +236,14 @@ public class JavaBasePlugin implements Plugin<Project> {
}
private void configureBuildNeeded(Project project) {
- DefaultTask buildTask = project.getTasks().add(BUILD_NEEDED_TASK_NAME, DefaultTask.class);
+ DefaultTask buildTask = project.getTasks().create(BUILD_NEEDED_TASK_NAME, DefaultTask.class);
buildTask.setDescription("Assembles and tests this project and all projects it depends on.");
buildTask.setGroup(BasePlugin.BUILD_GROUP);
buildTask.dependsOn(BUILD_TASK_NAME);
}
private void configureBuildDependents(Project project) {
- DefaultTask buildTask = project.getTasks().add(BUILD_DEPENDENTS_TASK_NAME, DefaultTask.class);
+ DefaultTask buildTask = project.getTasks().create(BUILD_DEPENDENTS_TASK_NAME, DefaultTask.class);
buildTask.setDescription("Assembles and tests this project and all projects that depend on it.");
buildTask.setGroup(BasePlugin.BUILD_GROUP);
buildTask.dependsOn(BUILD_TASK_NAME);
@@ -256,7 +259,7 @@ public class JavaBasePlugin implements Plugin<Project> {
public void execute(Project project) {
project.getTasks().withType(Test.class, new Action<Test>() {
public void execute(Test test) {
- overwriteIncludesIfSinglePropertyIsSet(test);
+ configureBasedOnSingleProperty(test);
overwriteDebugIfDebugPropertyIsSet(test);
}
});
@@ -276,9 +279,13 @@ public class JavaBasePlugin implements Plugin<Project> {
}
}
- private void overwriteIncludesIfSinglePropertyIsSet(final Test test) {
+ private void configureBasedOnSingleProperty(final Test test) {
String singleTest = getTaskPrefixedProperty(test, "single");
if (singleTest == null) {
+ //configure inputs so that the test task is skipped when there are no source files.
+ //unfortunately, this only applies when 'test.single' is *not* applied
+ //We should fix this distinction, the behavior with 'test.single' or without it should be the same
+ test.getInputs().source(test.getCandidateClassFiles());
return;
}
test.doFirst(new Action<Task>() {
@@ -322,12 +329,15 @@ public class JavaBasePlugin implements Plugin<Project> {
}
private void configureTestDefaults(final Test test, Project project, final JavaPluginConvention convention) {
- test.getConventionMapping().map("testResultsDir", new Callable<Object>() {
+ DslObject htmlReport = new DslObject(test.getReports().getHtml());
+ DslObject xmlReport = new DslObject(test.getReports().getJunitXml());
+
+ xmlReport.getConventionMapping().map("destination", new Callable<Object>() {
public Object call() throws Exception {
return convention.getTestResultsDir();
}
});
- test.getConventionMapping().map("testReportDir", new Callable<Object>() {
+ htmlReport.getConventionMapping().map("destination", new Callable<Object>() {
public Object call() throws Exception {
return convention.getTestReportDir();
}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/JavaLanguagePlugin.java b/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/JavaLanguagePlugin.java
index 8717fb7..ee64e00 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/JavaLanguagePlugin.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/JavaLanguagePlugin.java
@@ -16,45 +16,56 @@
package org.gradle.api.plugins;
import org.gradle.api.*;
+import org.gradle.api.internal.ConventionMapping;
import org.gradle.api.internal.file.DefaultSourceDirectorySet;
-import org.gradle.api.internal.tasks.DefaultClasspath;
-import org.gradle.api.internal.tasks.DefaultJavaSourceSet;
-import org.gradle.api.internal.tasks.DefaultProjectSourceSet;
-import org.gradle.api.tasks.*;
+import org.gradle.api.internal.file.FileResolver;
+import org.gradle.language.base.BinaryContainer;
+import org.gradle.language.base.internal.BinaryInternal;
+import org.gradle.language.base.internal.BinaryNamingScheme;
+import org.gradle.language.java.internal.DefaultJavaSourceSet;
+import org.gradle.language.java.JavaSourceSet;
+import org.gradle.api.tasks.compile.AbstractCompile;
import org.gradle.api.tasks.compile.JavaCompile;
import org.gradle.internal.reflect.Instantiator;
+import org.gradle.language.base.FunctionalSourceSet;
+import org.gradle.language.base.ProjectSourceSet;
+import org.gradle.language.jvm.internal.DefaultClasspath;
+import org.gradle.language.base.internal.DefaultProjectSourceSet;
+import org.gradle.language.jvm.ClassDirectoryBinary;
+import org.gradle.language.jvm.plugins.JvmLanguagePlugin;
import javax.inject.Inject;
+import java.util.concurrent.Callable;
/**
- * Plugin for compiling Java code. Applies the {@link JvmLanguagePlugin}.
- * Adds a {@link JavaCompile} task for each {@link JavaSourceSet} added to a {@link ClassDirectoryBinary}.
- * Registers the {@link JavaSourceSet} element type for each {@link FunctionalSourceSet} added to {@link ProjectSourceSet}.
+ * Plugin for compiling Java code. Applies the {@link org.gradle.language.jvm.plugins.JvmLanguagePlugin}.
+ * Adds a {@link JavaCompile} task for each {@link JavaSourceSet} added to a {@link org.gradle.language.jvm.ClassDirectoryBinary}.
+ * Registers the {@link JavaSourceSet} element type for each {@link org.gradle.language.base.FunctionalSourceSet} added to {@link org.gradle.language.base.ProjectSourceSet}.
*/
@Incubating
public class JavaLanguagePlugin implements Plugin<Project> {
private final Instantiator instantiator;
+ private final FileResolver fileResolver;
@Inject
- public JavaLanguagePlugin(Instantiator instantiator) {
+ public JavaLanguagePlugin(Instantiator instantiator, FileResolver fileResolver) {
this.instantiator = instantiator;
+ this.fileResolver = fileResolver;
}
public void apply(final Project target) {
- final JvmLanguagePlugin jvmLanguagePlugin = target.getPlugins().apply(JvmLanguagePlugin.class);
+ target.getPlugins().apply(JvmLanguagePlugin.class);
- JvmBinaryContainer jvmBinaryContainer = jvmLanguagePlugin.getJvmBinaryContainer();
- jvmBinaryContainer.all(new Action<ClassDirectoryBinary>() {
+ BinaryContainer jvmBinaryContainer = target.getExtensions().getByType(BinaryContainer.class);
+ jvmBinaryContainer.withType(ClassDirectoryBinary.class).all(new Action<ClassDirectoryBinary>() {
public void execute(final ClassDirectoryBinary binary) {
+ final BinaryNamingScheme namingScheme = ((BinaryInternal) binary).getNamingScheme();
binary.getSource().withType(JavaSourceSet.class).all(new Action<JavaSourceSet>() {
public void execute(JavaSourceSet javaSourceSet) {
- JavaCompile compileTask = (JavaCompile) binary.getCompileTask(); // TODO: can't simply cast
- if (compileTask == null) {
- compileTask = target.getTasks().add(binary.getTaskName("compile", "java"), JavaCompile.class);
- jvmLanguagePlugin.configureCompileTask(compileTask, javaSourceSet, binary);
- binary.setCompileTask(compileTask);
- binary.getClassesTask().dependsOn(compileTask);
- }
+ // TODO: handle case where binary has multiple JavaSourceSet's
+ JavaCompile compileTask = target.getTasks().create(namingScheme.getTaskName("compile", "java"), JavaCompile.class);
+ configureCompileTask(compileTask, javaSourceSet, binary);
+ binary.dependsOn(compileTask);
}
});
}
@@ -66,11 +77,37 @@ public class JavaLanguagePlugin implements Plugin<Project> {
functionalSourceSet.registerFactory(JavaSourceSet.class, new NamedDomainObjectFactory<JavaSourceSet>() {
public JavaSourceSet create(String name) {
return instantiator.newInstance(DefaultJavaSourceSet.class, name,
- instantiator.newInstance(DefaultSourceDirectorySet.class),
- instantiator.newInstance(DefaultClasspath.class), functionalSourceSet);
+ instantiator.newInstance(DefaultSourceDirectorySet.class, name, fileResolver),
+ instantiator.newInstance(DefaultClasspath.class, fileResolver,
+ target.getTasks()), functionalSourceSet);
}
});
}
});
}
+
+
+ /**
+ * Preconfigures the specified compile task based on the specified source set and class directory binary.
+ *
+ * @param compile the compile task to be preconfigured
+ * @param sourceSet the source set for the compile task
+ * @param binary the binary for the compile task
+ */
+ public void configureCompileTask(AbstractCompile compile, final JavaSourceSet sourceSet, final ClassDirectoryBinary binary) {
+ compile.setDescription(String.format("Compiles %s.", sourceSet));
+ compile.setSource(sourceSet.getSource());
+ compile.dependsOn(sourceSet);
+ ConventionMapping conventionMapping = compile.getConventionMapping();
+ conventionMapping.map("classpath", new Callable<Object>() {
+ public Object call() throws Exception {
+ return sourceSet.getCompileClasspath().getFiles();
+ }
+ });
+ conventionMapping.map("destinationDir", new Callable<Object>() {
+ public Object call() throws Exception {
+ return binary.getClassesDir();
+ }
+ });
+ }
}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/JavaLibraryDistributionPlugin.groovy b/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/JavaLibraryDistributionPlugin.groovy
index 090b856..9f20878 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/JavaLibraryDistributionPlugin.groovy
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/JavaLibraryDistributionPlugin.groovy
@@ -23,8 +23,6 @@ import org.gradle.api.distribution.plugins.DistributionPlugin
/**
* A {@link Plugin} which package a Java project as a distribution including the JAR and runtime dependencies.
- *
- * @author scogneau
*/
@Incubating
class JavaLibraryDistributionPlugin implements Plugin<Project> {
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/JavaPlugin.java b/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/JavaPlugin.java
index e306224..8b009da 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/JavaPlugin.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/JavaPlugin.java
@@ -42,8 +42,6 @@ import java.util.concurrent.Callable;
/**
* <p>A {@link Plugin} which compiles and tests Java source, and assembles it into a JAR file.</p>
- *
- * @author Hans Dockter
*/
public class JavaPlugin implements Plugin<Project> {
public static final String PROCESS_RESOURCES_TASK_NAME = "processResources";
@@ -79,9 +77,9 @@ public class JavaPlugin implements Plugin<Project> {
private void configureSourceSets(final JavaPluginConvention pluginConvention) {
final Project project = pluginConvention.getProject();
- SourceSet main = pluginConvention.getSourceSets().add(SourceSet.MAIN_SOURCE_SET_NAME);
+ SourceSet main = pluginConvention.getSourceSets().create(SourceSet.MAIN_SOURCE_SET_NAME);
- SourceSet test = pluginConvention.getSourceSets().add(SourceSet.TEST_SOURCE_SET_NAME);
+ SourceSet test = pluginConvention.getSourceSets().create(SourceSet.TEST_SOURCE_SET_NAME);
test.setCompileClasspath(project.files(main.getOutput(), project.getConfigurations().getByName(TEST_COMPILE_CONFIGURATION_NAME)));
test.setRuntimeClasspath(project.files(test.getOutput(), main.getOutput(), project.getConfigurations().getByName(TEST_RUNTIME_CONFIGURATION_NAME)));
}
@@ -90,7 +88,7 @@ public class JavaPlugin implements Plugin<Project> {
Project project = pluginConvention.getProject();
SourceSet mainSourceSet = pluginConvention.getSourceSets().getByName(SourceSet.MAIN_SOURCE_SET_NAME);
- Javadoc javadoc = project.getTasks().add(JAVADOC_TASK_NAME, Javadoc.class);
+ Javadoc javadoc = project.getTasks().create(JAVADOC_TASK_NAME, Javadoc.class);
javadoc.setDescription("Generates Javadoc API documentation for the main source code.");
javadoc.setGroup(JavaBasePlugin.DOCUMENTATION_GROUP);
javadoc.setClasspath(mainSourceSet.getOutput().plus(mainSourceSet.getCompileClasspath()));
@@ -99,7 +97,7 @@ public class JavaPlugin implements Plugin<Project> {
}
private void configureArchivesAndComponent(final Project project, final JavaPluginConvention pluginConvention) {
- Jar jar = project.getTasks().add(JAR_TASK_NAME, Jar.class);
+ Jar jar = project.getTasks().create(JAR_TASK_NAME, Jar.class);
jar.getManifest().from(pluginConvention.getManifest());
jar.setDescription("Assembles a jar archive containing the main classes.");
jar.setGroup(BasePlugin.BUILD_GROUP);
@@ -146,7 +144,7 @@ public class JavaPlugin implements Plugin<Project> {
});
}
});
- Test test = project.getTasks().add(TEST_TASK_NAME, Test.class);
+ Test test = project.getTasks().create(TEST_TASK_NAME, Test.class);
project.getTasks().getByName(JavaBasePlugin.CHECK_TASK_NAME).dependsOn(test);
test.setDescription("Runs the unit tests.");
test.setGroup(JavaBasePlugin.VERIFICATION_GROUP);
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/JavaPluginConvention.groovy b/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/JavaPluginConvention.groovy
index d8bfbb7..657c7b4 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/JavaPluginConvention.groovy
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/JavaPluginConvention.groovy
@@ -30,8 +30,6 @@ import org.gradle.util.ConfigureUtil
/**
* Is mixed in into the project when applying the {@link org.gradle.api.plugins.JavaBasePlugin} or the
* {@link org.gradle.api.plugins.JavaPlugin}.
- *
- * @author Hans Dockter
*/
class JavaPluginConvention {
ProjectInternal project
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/JvmLanguagePlugin.java b/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/JvmLanguagePlugin.java
deleted file mode 100644
index 6618927..0000000
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/JvmLanguagePlugin.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright 2013 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.plugins;
-
-import org.gradle.api.*;
-import org.gradle.api.internal.ConventionMapping;
-import org.gradle.api.internal.plugins.DslObject;
-import org.gradle.api.internal.plugins.ProcessResources;
-import org.gradle.api.internal.tasks.DefaultBinariesContainer;
-import org.gradle.api.internal.tasks.DefaultClassDirectoryBinary;
-import org.gradle.api.internal.tasks.DefaultJvmBinaryContainer;
-import org.gradle.api.tasks.*;
-import org.gradle.api.tasks.compile.AbstractCompile;
-import org.gradle.internal.reflect.Instantiator;
-
-import javax.inject.Inject;
-import java.io.File;
-import java.util.concurrent.Callable;
-
-/**
- * Base plugin for JVM language support. Applies the {@link LanguageBasePlugin}.
- * Adds a {@link JvmBinaryContainer} named {@code jvm} to the project's {@link BinariesContainer}.
- * Registers the {@link ClassDirectoryBinary} element type for that container.
- * Adds a lifecycle task named {@code classes} for each {@link ClassDirectoryBinary}.
- * Adds a {@link Copy} task named {@code processXYZResources} for each {@link ResourceSet} added to a {@link ClassDirectoryBinary}.
- */
- at Incubating
-public class JvmLanguagePlugin implements Plugin<Project> {
- private final Instantiator instantiator;
-
- private JvmBinaryContainer jvmBinaryContainer;
-
- @Inject
- public JvmLanguagePlugin(Instantiator instantiator) {
- this.instantiator = instantiator;
- }
-
- public void apply(final Project target) {
- target.getPlugins().apply(LanguageBasePlugin.class);
-
- BinariesContainer binariesContainer = target.getExtensions().getByType(DefaultBinariesContainer.class);
- jvmBinaryContainer = instantiator.newInstance(DefaultJvmBinaryContainer.class, instantiator);
- binariesContainer.add(jvmBinaryContainer);
-
- jvmBinaryContainer.registerFactory(ClassDirectoryBinary.class, new NamedDomainObjectFactory<ClassDirectoryBinary>() {
- public ClassDirectoryBinary create(String name) {
- return instantiator.newInstance(DefaultClassDirectoryBinary.class, name);
- };
- });
-
- jvmBinaryContainer.all(new Action<ClassDirectoryBinary>() {
- public void execute(final ClassDirectoryBinary binary) {
- ConventionMapping conventionMapping = new DslObject(binary).getConventionMapping();
- conventionMapping.map("classesDir", new Callable<File>() {
- public File call() throws Exception {
- return new File(new File(target.getBuildDir(), "classes"), binary.getName());
- }
- });
- final Task classesTask = target.getTasks().add(binary.getTaskName(null, "classes"));
- classesTask.setDescription(String.format("Assembles the %s classes.", binary.getName()));
- binary.setClassesTask(classesTask);
- binary.getSource().withType(ResourceSet.class).all(new Action<ResourceSet>() {
- public void execute(ResourceSet resourceSet) {
- Copy resourcesTask = binary.getResourcesTask();
- if (resourcesTask == null) {
- resourcesTask = target.getTasks().add(binary.getTaskName("process", "resources"), ProcessResources.class);
- resourcesTask.setDescription(String.format("Processes the %s resources.", binary.getName()));
- new DslObject(resourcesTask).getConventionMapping().map("destinationDir", new Callable<File>() {
- public File call() throws Exception {
- return binary.getResourcesDir();
- }
- });
- binary.setResourcesTask(resourcesTask);
- classesTask.dependsOn(resourcesTask);
- }
- resourcesTask.from(resourceSet.getSource());
- }
- });
- }
- });
- }
-
- /**
- * Returns the {@code binaries.jvm} container that was added by this plugin to the project.
- *
- * @return the {@code binaries.jvm} container that was added by this plugin to the project
- */
- public JvmBinaryContainer getJvmBinaryContainer() {
- return jvmBinaryContainer;
- }
-
- /**
- * Preconfigures the specified compile task based on the specified source set and class directory binary.
- *
- * @param compile the compile task to be preconfigured
- * @param sourceSet the source set for the compile task
- * @param binary the binary for the compile task
- */
- public void configureCompileTask(AbstractCompile compile, final JvmLanguageSourceSet sourceSet, final ClassDirectoryBinary binary) {
- compile.setDescription(String.format("Compiles the %s.", sourceSet));
- compile.setSource(sourceSet.getSource());
- compile.dependsOn(sourceSet);
- ConventionMapping conventionMapping = compile.getConventionMapping();
- conventionMapping.map("classpath", new Callable<Object>() {
- public Object call() throws Exception {
- return sourceSet.getCompileClasspath().getFiles();
- }
- });
- conventionMapping.map("destinationDir", new Callable<Object>() {
- public Object call() throws Exception {
- return binary.getClassesDir();
- }
- });
- }
-}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/LanguageBasePlugin.java b/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/LanguageBasePlugin.java
deleted file mode 100644
index a62a71a..0000000
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/LanguageBasePlugin.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright 2013 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.plugins;
-
-import org.gradle.api.*;
-import org.gradle.api.internal.file.DefaultSourceDirectorySet;
-import org.gradle.api.internal.file.FileResolver;
-import org.gradle.api.internal.tasks.*;
-import org.gradle.api.tasks.*;
-import org.gradle.internal.reflect.Instantiator;
-
-import javax.inject.Inject;
-
-/**
- * Base plugin for language support.
- * Adds a {@link BinariesContainer} named {@code binaries} to the project.
- * Adds a {@link ProjectSourceSet} named {@code sources} to the project.
- * Registers the {@link ResourceSet} element type for each {@link FunctionalSourceSet} added to {@link ProjectSourceSet}.
- */
- at Incubating
-public class LanguageBasePlugin implements Plugin<Project> {
- private final Instantiator instantiator;
- private final FileResolver fileResolver;
-
- @Inject
- public LanguageBasePlugin(Instantiator instantiator, FileResolver fileResolver) {
- this.instantiator = instantiator;
- this.fileResolver = fileResolver;
- }
-
- public void apply(Project target) {
- target.getExtensions().create("binaries", DefaultBinariesContainer.class, instantiator);
- ProjectSourceSet projectSourceSet = target.getExtensions().create("sources", DefaultProjectSourceSet.class, instantiator);
-
- // TODO: move to JvmLanguagePlugin?
- projectSourceSet.all(new Action<FunctionalSourceSet>() {
- public void execute(final FunctionalSourceSet functionalSourceSet) {
- functionalSourceSet.registerFactory(ResourceSet.class, new NamedDomainObjectFactory<ResourceSet>() {
- public ResourceSet create(String name) {
- return instantiator.newInstance(DefaultResourceSet.class, name,
- instantiator.newInstance(DefaultSourceDirectorySet.class, name, fileResolver), functionalSourceSet);
- }
- });
- }
- });
- }
-}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/WarPlugin.java b/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/WarPlugin.java
index 040f7b0..d14541a 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/WarPlugin.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/WarPlugin.java
@@ -24,8 +24,8 @@ import org.gradle.api.artifacts.ConfigurationContainer;
import org.gradle.api.artifacts.PublishArtifact;
import org.gradle.api.file.FileCollection;
import org.gradle.api.internal.artifacts.publish.ArchivePublishArtifact;
-import org.gradle.api.internal.plugins.DefaultArtifactPublicationSet;
import org.gradle.api.internal.java.WebApplication;
+import org.gradle.api.internal.plugins.DefaultArtifactPublicationSet;
import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.bundling.War;
@@ -34,8 +34,6 @@ import java.util.concurrent.Callable;
/**
* <p>A {@link Plugin} which extends the {@link JavaPlugin} to add tasks which assemble a web application into a WAR
* file.</p>
- *
- * @author Hans Dockter
*/
public class WarPlugin implements Plugin<Project> {
public static final String PROVIDED_COMPILE_CONFIGURATION_NAME = "providedCompile";
@@ -73,7 +71,7 @@ public class WarPlugin implements Plugin<Project> {
}
});
- War war = project.getTasks().add(WAR_TASK_NAME, War.class);
+ War war = project.getTasks().create(WAR_TASK_NAME, War.class);
war.setDescription("Generates a war archive with all the compiled classes, the web-app content and the libraries.");
war.setGroup(BasePlugin.BUILD_GROUP);
ArchivePublishArtifact warArtifact = new ArchivePublishArtifact(war);
@@ -83,9 +81,9 @@ public class WarPlugin implements Plugin<Project> {
}
public void configureConfigurations(ConfigurationContainer configurationContainer) {
- Configuration provideCompileConfiguration = configurationContainer.add(PROVIDED_COMPILE_CONFIGURATION_NAME).setVisible(false).
+ Configuration provideCompileConfiguration = configurationContainer.create(PROVIDED_COMPILE_CONFIGURATION_NAME).setVisible(false).
setDescription("Additional compile classpath for libraries that should not be part of the WAR archive.");
- Configuration provideRuntimeConfiguration = configurationContainer.add(PROVIDED_RUNTIME_CONFIGURATION_NAME).setVisible(false).
+ Configuration provideRuntimeConfiguration = configurationContainer.create(PROVIDED_RUNTIME_CONFIGURATION_NAME).setVisible(false).
extendsFrom(provideCompileConfiguration).
setDescription("Additional runtime classpath for libraries that should not be part of the WAR archive.");
configurationContainer.getByName(JavaPlugin.COMPILE_CONFIGURATION_NAME).extendsFrom(provideCompileConfiguration);
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/BinariesContainer.java b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/BinariesContainer.java
deleted file mode 100644
index 4951358..0000000
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/BinariesContainer.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2013 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.tasks;
-
-import org.gradle.api.*;
-
-/**
- * A container for binaries that in turn contains more specialized containers.
- * Added to a project by the {@link org.gradle.api.plugins.LanguageBasePlugin}.
- */
-// TODO: ideally this would be a container where each element type is only allowed once and elements can be looked up by type
-// for now I solved the lookup (usability) problem with a JvmLanguagePlugin.getJvmBinariesContainer() method; maybe that's good enough
- at Incubating
-public interface BinariesContainer extends NamedDomainObjectSet<Named> {}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/ClassDirectoryBinary.java b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/ClassDirectoryBinary.java
deleted file mode 100644
index ae2a94a..0000000
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/ClassDirectoryBinary.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2013 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.tasks;
-
-import org.gradle.api.*;
-import org.gradle.api.tasks.compile.AbstractCompile;
-
-import java.io.File;
-
-/**
- * An exploded binary containing resources and compiled class files.
- */
-// TODO: maybe we need to allow additional dirs like SourceSetOutput does
-// (esp. for backwards compatibility). Wonder if it's still necessary to distinguish
-// between classes and resources dirs, instead of just maintaining a collection of dirs.
-// As far as generated resources are concerned, it might be better to model
-// them as an additional (Buildable) ResourceSet.
- at Incubating
-public interface ClassDirectoryBinary extends Named, Buildable {
- File getClassesDir();
- void setClassesDir(File dir);
- File getResourcesDir();
- void setResourcesDir(File dir);
- DomainObjectCollection<LanguageSourceSet> getSource();
- Task getClassesTask();
- void setClassesTask(Task task);
- @Nullable
- Copy getResourcesTask();
- void setResourcesTask(Copy task);
- // TODO: having a single compile task won't work if multiple separately compiled langs are used
- @Nullable
- AbstractCompile getCompileTask();
- void setCompileTask(AbstractCompile task);
- String getTaskName(String verb, String target);
- String getTaskBaseName();
-}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/Classpath.java b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/Classpath.java
deleted file mode 100644
index 6c6a4e4..0000000
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/Classpath.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2013 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.tasks;
-
-import org.gradle.api.Buildable;
-import org.gradle.api.Incubating;
-import org.gradle.api.file.FileCollection;
-
-/**
- * A collection of files to be used as a class path.
- */
- at Incubating
-public interface Classpath extends Buildable {
- FileCollection getFiles();
-}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/FunctionalSourceSet.java b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/FunctionalSourceSet.java
deleted file mode 100644
index c12c4d0..0000000
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/FunctionalSourceSet.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2013 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.tasks;
-
-import org.gradle.api.ExtensiblePolymorphicDomainObjectContainer;
-import org.gradle.api.Incubating;
-import org.gradle.api.Named;
-
-/**
- * A container holding {@link LanguageSourceSet}s with a similar function
- * (production code, test code, etc.).
- */
- at Incubating
-public interface FunctionalSourceSet extends ExtensiblePolymorphicDomainObjectContainer<LanguageSourceSet>, Named {}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/GroovyRuntime.java b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/GroovyRuntime.java
new file mode 100644
index 0000000..cfca7e1
--- /dev/null
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/GroovyRuntime.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.tasks;
+
+import com.google.common.collect.Lists;
+import org.gradle.api.*;
+import org.gradle.api.artifacts.Configuration;
+import org.gradle.api.artifacts.Dependency;
+import org.gradle.api.file.FileCollection;
+import org.gradle.api.internal.file.collections.LazilyInitializedFileCollection;
+import org.gradle.api.internal.plugins.GroovyJarFile;
+import org.gradle.api.plugins.GroovyBasePlugin;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Provides information related to the Groovy runtime(s) used in a project. Added by the
+ * {@link GroovyBasePlugin} as a project extension named {@code groovyRuntime}.
+ *
+ * <p>Example usage:
+ *
+ * <pre autoTested="">
+ * apply plugin: "groovy"
+ *
+ * repositories {
+ * mavenCentral()
+ * }
+ *
+ * dependencies {
+ * compile "org.codehaus.groovy:groovy-all:2.1.2"
+ * }
+ *
+ * def groovyClasspath = groovyRuntime.inferGroovyClasspath(configurations.compile)
+ * // The returned class path can be used to configure the 'groovyClasspath' property of tasks
+ * // such as 'GroovyCompile' or 'Groovydoc', or to execute these and other Groovy tools directly.
+ * </pre>
+ */
+ at Incubating
+public class GroovyRuntime {
+ private final Project project;
+
+ public GroovyRuntime(Project project) {
+ this.project = project;
+ }
+
+ /**
+ * Searches the specified class path for Groovy Jars ({@code groovy(-indy)}, {@code groovy-all(-indy)})
+ * and returns a corresponding class path for executing Groovy tools such as the Groovy compiler and Groovydoc tool.
+ * The tool versions will match those of the Groovy Jars found. If no Groovy Jars are found on the specified class
+ * path, a class path with the contents of the {@code groovy} configuration will be returned.
+ *
+ * <p>The returned class path may be empty, or may fail to resolve when asked for its contents.
+ *
+ * @param classpath a class path containing Groovy Jars
+ * @return a corresponding class path for executing Groovy tools such as the Groovy compiler and Groovydoc tool
+ */
+ public FileCollection inferGroovyClasspath(final Iterable<File> classpath) {
+ final Configuration groovyConfiguration = project.getConfigurations().getByName(GroovyBasePlugin.GROOVY_CONFIGURATION_NAME);
+ if (!groovyConfiguration.getDependencies().isEmpty()) {
+ return groovyConfiguration;
+ }
+
+ // alternatively, we could return project.files(Runnable)
+ // would differ in at least the following ways: 1. live 2. no autowiring
+ return new LazilyInitializedFileCollection() {
+ @Override
+ public FileCollection createDelegate() {
+ GroovyJarFile groovyJar = findGroovyJarFile(classpath);
+ if (groovyJar == null) {
+ throw new GradleException(String.format("Cannot infer Groovy class path because no Groovy Jar was found on class path: %s", classpath));
+ }
+
+ if (groovyJar.isGroovyAll()) {
+ return project.files(groovyJar.getFile());
+ }
+
+ if (project.getRepositories().isEmpty()) {
+ throw new GradleException("Cannot infer Groovy class path because no repository is declared for the project.");
+ }
+
+ String notation = groovyJar.getDependencyNotation();
+ List<Dependency> dependencies = Lists.newArrayList();
+ // project.getDependencies().create(String) seems to be the only feasible way to create a Dependency with a classifier
+ dependencies.add(project.getDependencies().create(notation));
+ if (groovyJar.getVersion().getMajor() >= 2) {
+ // add groovy-ant to bring in AntGroovyCompiler
+ dependencies.add(project.getDependencies().create(notation.replace(":groovy:", ":groovy-ant:")));
+ }
+ return project.getConfigurations().detachedConfiguration(dependencies.toArray(new Dependency[dependencies.size()]));
+ }
+
+ // let's override this so that delegate isn't created at autowiring time (which would mean on every build)
+ @Override
+ public TaskDependency getBuildDependencies() {
+ if (classpath instanceof Buildable) {
+ return ((Buildable) classpath).getBuildDependencies();
+ }
+ return new TaskDependency() {
+ public Set<? extends Task> getDependencies(Task task) {
+ return Collections.emptySet();
+ }
+ };
+ }
+ };
+ }
+
+ private GroovyJarFile findGroovyJarFile(Iterable<File> classpath) {
+ if (classpath == null) { return null; }
+ for (File file : classpath) {
+ GroovyJarFile groovyJar = GroovyJarFile.parse(file);
+ if (groovyJar != null) { return groovyJar; }
+ }
+ return null;
+ }
+}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/JavaSourceSet.java b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/JavaSourceSet.java
deleted file mode 100644
index 163c7e7..0000000
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/JavaSourceSet.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2013 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.tasks;
-
-import org.gradle.api.Incubating;
-
-/**
- * A set of sources passed to the Java compiler.
- */
- at Incubating
-public interface JavaSourceSet extends JvmLanguageSourceSet {}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/JvmBinaryContainer.java b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/JvmBinaryContainer.java
deleted file mode 100644
index 0a59bb6..0000000
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/JvmBinaryContainer.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2013 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.tasks;
-
-import org.gradle.api.ExtensiblePolymorphicDomainObjectContainer;
-import org.gradle.api.Incubating;
-import org.gradle.api.Named;
-
-/**
- * A container for JVM binaries.
- */
- at Incubating
-public interface JvmBinaryContainer extends ExtensiblePolymorphicDomainObjectContainer<ClassDirectoryBinary>, Named {
-}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/JvmLanguageSourceSet.java b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/JvmLanguageSourceSet.java
deleted file mode 100644
index 4a9c85e..0000000
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/JvmLanguageSourceSet.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2013 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.tasks;
-
-import org.gradle.api.Incubating;
-
-/**
- * A set of sources for a JVM language.
- */
- at Incubating
-public interface JvmLanguageSourceSet extends LanguageSourceSet {
- Classpath getCompileClasspath();
-}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/LanguageSourceSet.java b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/LanguageSourceSet.java
deleted file mode 100644
index 7fd9b13..0000000
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/LanguageSourceSet.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2013 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.tasks;
-
-import org.gradle.api.Buildable;
-import org.gradle.api.Incubating;
-import org.gradle.api.Named;
-import org.gradle.api.file.SourceDirectorySet;
-
-/**
- * A set of sources for a programming language.
- */
- at Incubating
-public interface LanguageSourceSet extends Named, Buildable {
- // TODO: do we want to keep using SourceDirectorySet in the new API?
- // would feel more natural if dirs could be added directly to LanguageSourceSet
- // could also think about extending SourceDirectorySet
- SourceDirectorySet getSource();
- FunctionalSourceSet getParent();
-}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/ProjectSourceSet.java b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/ProjectSourceSet.java
deleted file mode 100644
index 6831762..0000000
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/ProjectSourceSet.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2013 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.tasks;
-
-import org.gradle.api.Incubating;
-import org.gradle.api.NamedDomainObjectContainer;
-
-/**
- * A container of {@link FunctionalSourceSet}s. Added to a project by the
- * {@link org.gradle.api.plugins.LanguageBasePlugin}.
- */
- at Incubating
-public interface ProjectSourceSet extends NamedDomainObjectContainer<FunctionalSourceSet> {}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/ResourceSet.java b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/ResourceSet.java
deleted file mode 100644
index b40e94e..0000000
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/ResourceSet.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2013 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.tasks;
-
-import org.gradle.api.Incubating;
-
-/**
- * A set of resource files.
- */
- at Incubating
-public interface ResourceSet extends LanguageSourceSet {}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/SourceSetContainer.java b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/SourceSetContainer.java
index d2ceb64..e77b0de 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/SourceSetContainer.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/SourceSetContainer.java
@@ -30,7 +30,9 @@ public interface SourceSetContainer extends NamedDomainObjectContainer<SourceSet
* @param name The name of the new source set.
* @return The newly added source set.
* @throws org.gradle.api.InvalidUserDataException when a source set with the given name already exists in this container.
+ * @deprecated use {@link #create(String)} instead
*/
+ @Deprecated
SourceSet add(String name) throws InvalidUserDataException;
/**
@@ -41,6 +43,8 @@ public interface SourceSetContainer extends NamedDomainObjectContainer<SourceSet
* @param configureClosure The closure to use to configure the source set.
* @return The newly added source set.
* @throws InvalidUserDataException when a source set with the given name already exists in this container.
+ * @deprecated use {@link #create(String, groovy.lang.Closure)} instead
*/
+ @Deprecated
SourceSet add(String name, Closure configureClosure) throws InvalidUserDataException;
}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/application/CreateStartScripts.groovy b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/application/CreateStartScripts.groovy
index 2b503b6..b1acfaf 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/application/CreateStartScripts.groovy
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/application/CreateStartScripts.groovy
@@ -18,16 +18,11 @@ package org.gradle.api.tasks.application
import org.gradle.api.file.FileCollection
import org.gradle.api.internal.ConventionTask
import org.gradle.api.internal.plugins.StartScriptGenerator
-import org.gradle.api.tasks.Input
-import org.gradle.api.tasks.InputFiles
-import org.gradle.api.tasks.OutputFile
-import org.gradle.api.tasks.TaskAction
+import org.gradle.api.tasks.*
import org.gradle.util.GUtil
/**
* <p>A {@link org.gradle.api.Task} for creating OS dependent start scripts.</p>
- *
- * @author Rene Groeschke
*/
public class CreateStartScripts extends ConventionTask {
@@ -43,6 +38,13 @@ public class CreateStartScripts extends ConventionTask {
String mainClassName
/**
+ * The application's default JVM options.
+ */
+ @Input
+ @Optional
+ Iterable<String> defaultJvmOpts = []
+
+ /**
* The application's name.
*/
@Input
@@ -98,6 +100,7 @@ public class CreateStartScripts extends ConventionTask {
def generator = new StartScriptGenerator()
generator.applicationName = getApplicationName()
generator.mainClassName = getMainClassName()
+ generator.defaultJvmOpts = getDefaultJvmOpts()
generator.optsEnvironmentVar = getOptsEnvironmentVar()
generator.exitEnvironmentVar = getExitEnvironmentVar()
generator.classpath = getClasspath().collect { "lib/${it.name}" }
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/bundling/Jar.groovy b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/bundling/Jar.groovy
index 6fc0a30..0b1f15a 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/bundling/Jar.groovy
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/bundling/Jar.groovy
@@ -17,30 +17,29 @@
package org.gradle.api.tasks.bundling
import org.gradle.api.file.CopySpec
+import org.gradle.api.file.FileCopyDetails
+import org.gradle.api.internal.file.FileResolver
+import org.gradle.api.internal.file.collections.FileTreeAdapter
import org.gradle.api.internal.file.collections.MapFileTree
+import org.gradle.api.internal.file.copy.DefaultCopySpec
+import org.gradle.api.java.archives.Manifest
import org.gradle.api.java.archives.internal.DefaultManifest
import org.gradle.util.ConfigureUtil
-import org.gradle.api.internal.file.copy.CopySpecImpl
-import org.gradle.api.file.FileCopyDetails
-import org.gradle.api.java.archives.Manifest
-import org.gradle.api.internal.file.collections.FileTreeAdapter
/**
* Assembles a JAR archive.
- *
- * @author Hans Dockter
*/
public class Jar extends Zip {
public static final String DEFAULT_EXTENSION = 'jar'
private Manifest manifest
- private final CopySpecImpl metaInf
+ private final DefaultCopySpec metaInf
Jar() {
extension = DEFAULT_EXTENSION
- manifest = new DefaultManifest(project.fileResolver)
+ manifest = new DefaultManifest(getServices().get(FileResolver))
// Add these as separate specs, so they are not affected by the changes to the main spec
- metaInf = copyAction.rootSpec.addFirst().into('META-INF')
+ metaInf = rootSpec.addFirst().into('META-INF')
metaInf.addChild().from {
MapFileTree manifestSource = new MapFileTree(temporaryDirFactory)
manifestSource.add('MANIFEST.MF') {OutputStream outstr ->
@@ -49,7 +48,7 @@ public class Jar extends Zip {
}
return new FileTreeAdapter(manifestSource)
}
- copyAction.mainSpec.eachFile { FileCopyDetails details ->
+ mainSpec.eachFile { FileCopyDetails details ->
if (details.path.equalsIgnoreCase('META-INF/MANIFEST.MF')) {
details.exclude()
}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/bundling/War.groovy b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/bundling/War.groovy
index edbec72..333c325 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/bundling/War.groovy
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/bundling/War.groovy
@@ -18,16 +18,14 @@ package org.gradle.api.tasks.bundling
import org.gradle.api.file.CopySpec
import org.gradle.api.file.FileCollection
+import org.gradle.api.internal.file.copy.DefaultCopySpec
import org.gradle.api.tasks.InputFile
import org.gradle.api.tasks.InputFiles
import org.gradle.api.tasks.Optional
import org.gradle.util.ConfigureUtil
-import org.gradle.api.internal.file.copy.CopySpecImpl
/**
* Assembles a WAR archive.
- *
- * @author Hans Dockter
*/
class War extends Jar {
public static final String WAR_EXTENSION = 'war'
@@ -35,12 +33,13 @@ class War extends Jar {
private File webXml
private FileCollection classpath
- private final CopySpecImpl webInf
+ private final DefaultCopySpec webInf
War() {
extension = WAR_EXTENSION
// Add these as separate specs, so they are not affected by the changes to the main spec
- webInf = copyAction.rootSpec.addChild().into('WEB-INF')
+
+ webInf = rootSpec.addFirst().into('WEB-INF')
webInf.into('classes') {
from {
def classpath = getClasspath()
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/compile/AbstractOptions.java b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/compile/AbstractOptions.java
index dff02e1..163e8c9 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/compile/AbstractOptions.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/compile/AbstractOptions.java
@@ -29,8 +29,6 @@ import java.util.Map;
/**
* Base class for compilation-related options.
- *
- * @author Hans Dockter
*/
public abstract class AbstractOptions implements Serializable {
private static final long serialVersionUID = 0;
@@ -38,7 +36,7 @@ public abstract class AbstractOptions implements Serializable {
public void define(@Nullable Map<String, Object> args) {
if (args == null) { return; }
for (Map.Entry<String, Object> arg: args.entrySet()) {
- JavaReflectionUtil.writeProperty(this, arg.getKey(), arg.getValue());
+ JavaReflectionUtil.writeableProperty(getClass(), arg.getKey()).setValue(this, arg.getValue());
}
}
@@ -77,7 +75,7 @@ public abstract class AbstractOptions implements Serializable {
}
private void addValueToMapIfNotNull(Map<String, Object> map, Field field) {
- Object value = JavaReflectionUtil.readProperty(this, field.getName());
+ Object value = JavaReflectionUtil.readableProperty(getClass(), field.getName()).getValue(this);
if (value != null) {
map.put(getAntPropertyName(field.getName()), getAntPropertyValue(field.getName(), value));
}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/compile/BaseForkOptions.java b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/compile/BaseForkOptions.java
index 2646237..50fbfbc 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/compile/BaseForkOptions.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/compile/BaseForkOptions.java
@@ -16,7 +16,6 @@
package org.gradle.api.tasks.compile;
import com.google.common.collect.Lists;
-
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.Optional;
@@ -25,8 +24,6 @@ import java.util.List;
/**
* Fork options for compilation. Only take effect if {@code fork}
* is {@code true}.
- *
- * @author Hans Dockter
*/
public class BaseForkOptions extends AbstractOptions {
private static final long serialVersionUID = 0;
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/compile/Compile.java b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/compile/Compile.java
index 1fa0a64..6409e5d 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/compile/Compile.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/compile/Compile.java
@@ -17,15 +17,14 @@
package org.gradle.api.tasks.compile;
import org.gradle.api.AntBuilder;
-import org.gradle.api.internal.file.TemporaryFileProvider;
import org.gradle.api.internal.project.ProjectInternal;
-import org.gradle.api.internal.tasks.compile.*;
import org.gradle.api.internal.tasks.compile.Compiler;
-import org.gradle.internal.Factory;
+import org.gradle.api.internal.tasks.compile.*;
import org.gradle.api.tasks.Nested;
import org.gradle.api.tasks.OutputDirectory;
import org.gradle.api.tasks.TaskAction;
import org.gradle.api.tasks.WorkResult;
+import org.gradle.internal.Factory;
import org.gradle.util.DeprecationLogger;
import java.io.File;
@@ -33,7 +32,6 @@ import java.io.File;
/**
* Compiles Java source files.
*
- * @author Hans Dockter
* @deprecated This class has been replaced by {@link JavaCompile}.
*/
@Deprecated
@@ -49,8 +47,7 @@ public class Compile extends AbstractCompile {
Factory<AntBuilder> antBuilderFactory = getServices().getFactory(AntBuilder.class);
JavaCompilerFactory inProcessCompilerFactory = new InProcessJavaCompilerFactory();
ProjectInternal projectInternal = (ProjectInternal) getProject();
- TemporaryFileProvider tempFileProvider = projectInternal.getServices().get(TemporaryFileProvider.class);
- JavaCompilerFactory defaultCompilerFactory = new DefaultJavaCompilerFactory(projectInternal, tempFileProvider, antBuilderFactory, inProcessCompilerFactory);
+ JavaCompilerFactory defaultCompilerFactory = new DefaultJavaCompilerFactory(projectInternal, antBuilderFactory, inProcessCompilerFactory);
Compiler<JavaCompileSpec> delegatingCompiler = new DelegatingJavaCompiler(defaultCompilerFactory);
javaCompiler = new IncrementalJavaCompiler(delegatingCompiler, antBuilderFactory, getOutputs());
}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/compile/CompileOptions.java b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/compile/CompileOptions.java
index 3a41797..5bd2de6 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/compile/CompileOptions.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/compile/CompileOptions.java
@@ -28,8 +28,6 @@ import java.util.Map;
/**
* Main options for Java compilation.
- *
- * @author Hans Dockter
*/
public class CompileOptions extends AbstractOptions {
private static final long serialVersionUID = 0;
@@ -78,16 +76,19 @@ public class CompileOptions extends AbstractOptions {
/**
* Tells whether to fail the build when compilation fails. Defaults to {@code true}.
*/
+ @Input
public boolean isFailOnError() {
return failOnError;
}
/**
- * Tells whether to fail the build when compilation fails. Defaults to {@code true}.
+ * Deprecated.
+ *
+ * @deprecated use {@link #isFailOnError()}
*/
- // @Input not recognized if there is only an "is" method
- @Input
+ @Deprecated
public boolean getFailOnError() {
+ DeprecationLogger.nagUserOfDiscontinuedProperty("CompileOptions.getFailOnError()", "CompileOptions.isFailOnError()");
return failOnError;
}
@@ -212,17 +213,19 @@ public class CompileOptions extends AbstractOptions {
* Tells whether to include debugging information in the generated class files. Defaults
* to {@code true}. See {@link DebugOptions#getDebugLevel()} for which debugging information will be generated.
*/
+ @Input
public boolean isDebug() {
return debug;
}
/**
- * Tells whether to include debugging information in the generated class files. Defaults
- * to {@code true}. See {@link DebugOptions#getDebugLevel()} for which debugging information will be generated.
+ * Deprecated.
+ *
+ * @deprecated use {@link #isDebug()}
*/
- // @Input not recognized if there is only an "is" method
- @Input
+ @Deprecated
public boolean getDebug() {
+ DeprecationLogger.nagUserOfReplacedMethod("getDebug()", "isDebug()");
return debug;
}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/compile/DebugOptions.java b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/compile/DebugOptions.java
index be6b558..6bdcccf 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/compile/DebugOptions.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/compile/DebugOptions.java
@@ -22,8 +22,6 @@ import org.gradle.api.tasks.Optional;
/**
* Debug options for Java compilation. Only take effect if {@link CompileOptions#debug}
* is set to {@code true}.
- *
- * @author Hans Dockter
*/
public class DebugOptions extends AbstractOptions {
private static final long serialVersionUID = 0;
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/compile/DependOptions.java b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/compile/DependOptions.java
index f87283b..ca8836b 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/compile/DependOptions.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/compile/DependOptions.java
@@ -29,8 +29,6 @@ import com.google.common.collect.ImmutableSet;
* <p>The {@code srcDir}, {@code destDir}, and {@code cache} properties of the Ant task
* are set automatically. The latter is replaced by a {@code useCache} option to enable/disable caching of
* dependency information.
- *
- * @author Steve Appling
*/
public class DependOptions extends AbstractOptions {
private static final long serialVersionUID = 0;
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/compile/ForkOptions.java b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/compile/ForkOptions.java
index e3d7b1e..00bfaa4 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/compile/ForkOptions.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/compile/ForkOptions.java
@@ -21,8 +21,6 @@ import org.gradle.api.tasks.Optional;
/**
* Fork options for Java compilation. Only take effect if {@code CompileOptions.fork} is {@code true}.
- *
- * @author Hans Dockter
*/
public class ForkOptions extends BaseForkOptions {
private static final long serialVersionUID = 0;
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/compile/GroovyCompile.java b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/compile/GroovyCompile.java
index 1e36dc5..6287ea0 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/compile/GroovyCompile.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/compile/GroovyCompile.java
@@ -23,8 +23,8 @@ import org.gradle.api.internal.ClassPathRegistry;
import org.gradle.api.internal.file.TemporaryFileProvider;
import org.gradle.api.internal.project.IsolatedAntBuilder;
import org.gradle.api.internal.project.ProjectInternal;
-import org.gradle.api.internal.tasks.compile.*;
import org.gradle.api.internal.tasks.compile.Compiler;
+import org.gradle.api.internal.tasks.compile.*;
import org.gradle.api.tasks.InputFiles;
import org.gradle.api.tasks.Nested;
import org.gradle.api.tasks.WorkResult;
@@ -35,8 +35,6 @@ import java.io.File;
/**
* Compiles Groovy source files, and optionally, Java source files.
- *
- * @author Hans Dockter
*/
public class GroovyCompile extends AbstractCompile {
private Compiler<GroovyJavaJointCompileSpec> compiler;
@@ -44,7 +42,7 @@ public class GroovyCompile extends AbstractCompile {
private final CompileOptions compileOptions = new CompileOptions();
private final GroovyCompileOptions groovyCompileOptions = new GroovyCompileOptions();
private final TemporaryFileProvider tempFileProvider;
-
+
public GroovyCompile() {
ProjectInternal projectInternal = (ProjectInternal) getProject();
IsolatedAntBuilder antBuilder = getServices().get(IsolatedAntBuilder.class);
@@ -52,7 +50,7 @@ public class GroovyCompile extends AbstractCompile {
Factory<AntBuilder> antBuilderFactory = getServices().getFactory(AntBuilder.class);
JavaCompilerFactory inProcessCompilerFactory = new InProcessJavaCompilerFactory();
tempFileProvider = projectInternal.getServices().get(TemporaryFileProvider.class);
- DefaultJavaCompilerFactory javaCompilerFactory = new DefaultJavaCompilerFactory(projectInternal, tempFileProvider, antBuilderFactory, inProcessCompilerFactory);
+ DefaultJavaCompilerFactory javaCompilerFactory = new DefaultJavaCompilerFactory(projectInternal, antBuilderFactory, inProcessCompilerFactory);
GroovyCompilerFactory groovyCompilerFactory = new GroovyCompilerFactory(projectInternal, antBuilder, classPathRegistry, javaCompilerFactory);
Compiler<GroovyJavaJointCompileSpec> delegatingCompiler = new DelegatingGroovyCompiler(groovyCompilerFactory);
compiler = new IncrementalGroovyCompiler(delegatingCompiler, getOutputs());
@@ -80,7 +78,8 @@ public class GroovyCompile extends AbstractCompile {
private void checkGroovyClasspathIsNonEmpty() {
if (getGroovyClasspath().isEmpty()) {
- throw new InvalidUserDataException("'" + getName() + ".groovyClasspath' must not be empty. It is either configured automatically by the 'groovy-base' plugin, or can be set manually.");
+ throw new InvalidUserDataException("'" + getName() + ".groovyClasspath' must not be empty. If a Groovy compile dependency is provided, "
+ + "the 'groovy-base' plugin will attempt to configure 'groovyClasspath' automatically. Alternatively, you may configure 'groovyClasspath' explicitly.");
}
}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/compile/GroovyCompileOptions.java b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/compile/GroovyCompileOptions.java
index 26812f8..4fb0829 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/compile/GroovyCompileOptions.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/compile/GroovyCompileOptions.java
@@ -18,7 +18,6 @@ package org.gradle.api.tasks.compile;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
-
import org.gradle.api.Incubating;
import org.gradle.api.tasks.Input;
import org.gradle.util.DeprecationLogger;
@@ -29,8 +28,6 @@ import java.util.Map;
/**
* Compilation options to be passed to the Groovy compiler.
- *
- * @author Hans Dockter
*/
public class GroovyCompileOptions extends AbstractOptions {
private static final long serialVersionUID = 0;
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/compile/GroovyForkOptions.java b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/compile/GroovyForkOptions.java
index 5aecce1..7e7b000 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/compile/GroovyForkOptions.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/compile/GroovyForkOptions.java
@@ -18,8 +18,6 @@ package org.gradle.api.tasks.compile;
/**
* Fork options for Groovy compilation. Only take effect if {@code GroovyCompileOptions.fork}
* is {@code true}.
- *
- * @author Hans Dockter
*/
public class GroovyForkOptions extends BaseForkOptions {
private static final long serialVersionUID = 0;
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/javadoc/AntGroovydoc.groovy b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/javadoc/AntGroovydoc.groovy
index 60c0c42..ccd8e45 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/javadoc/AntGroovydoc.groovy
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/javadoc/AntGroovydoc.groovy
@@ -21,9 +21,6 @@ import org.gradle.api.file.FileCollection
import org.gradle.api.internal.ClassPathRegistry
import org.gradle.api.internal.project.IsolatedAntBuilder
-/**
- * @author Hans Dockter
- */
class AntGroovydoc {
private final IsolatedAntBuilder ant
private final ClassPathRegistry classPathRegistry
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/javadoc/AntJavadoc.groovy b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/javadoc/AntJavadoc.groovy
index 0f48808..9446beb 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/javadoc/AntJavadoc.groovy
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/javadoc/AntJavadoc.groovy
@@ -17,8 +17,9 @@
package org.gradle.api.tasks.javadoc
/**
- * @author Hans Dockter
+ * @deprecated No replacement
*/
+ at Deprecated
class AntJavadoc {
void execute(List<File> sourceDirs, File destDir, Set<File> classpathFiles, String windowTitle, String maxMemory,
List<String> includes, List<String> excludes, boolean verbose, AntBuilder ant) {
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/javadoc/Groovydoc.java b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/javadoc/Groovydoc.java
index 27f6667..19011e9 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/javadoc/Groovydoc.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/javadoc/Groovydoc.java
@@ -34,8 +34,6 @@ import java.util.*;
* some severe limitations at the moment (for example no doc for properties comments). The version of the Groovydoc that
* is used, is the one from the Groovy defined in the build script. Please note also, that the Groovydoc tool prints to
* System.out for many of its statements and does circumvents our logging currently.
- *
- * @author Hans Dockter
*/
public class Groovydoc extends SourceTask {
private FileCollection groovyClasspath;
@@ -184,14 +182,14 @@ public class Groovydoc extends SourceTask {
/**
* Sets title for the package index(first) page (optional).
*
- * @param docTitle the docTitle as html-code
+ * @param docTitle the docTitle as HTML
*/
public void setDocTitle(String docTitle) {
this.docTitle = docTitle;
}
/**
- * Returns the html header for each page. Set to {@code null} when there is no header.
+ * Returns the HTML header for each page. Set to {@code null} when there is no header.
*/
@Input @Optional
public String getHeader() {
@@ -201,14 +199,14 @@ public class Groovydoc extends SourceTask {
/**
* Sets header text for each page (optional).
*
- * @param header the header as html-code
+ * @param header the header as HTML
*/
public void setHeader(String header) {
this.header = header;
}
/**
- * Returns the html footer for each page. Set to {@code null} when there is no footer.
+ * Returns the HTML footer for each page. Set to {@code null} when there is no footer.
*/
@Input @Optional
public String getFooter() {
@@ -218,21 +216,21 @@ public class Groovydoc extends SourceTask {
/**
* Sets footer text for each page (optional).
*
- * @param footer the footer as html-code
+ * @param footer the footer as HTML
*/
public void setFooter(String footer) {
this.footer = footer;
}
/**
- * Returns a html file to be used for overview documentation. Set to {@code null} when there is no overview file.
+ * Returns a HTML file to be used for overview documentation. Set to {@code null} when there is no overview file.
*/
public String getOverview() {
return overview;
}
/**
- * Sets a html file to be used for overview documentation (optional).
+ * Sets a HTML file to be used for overview documentation (optional).
*/
public void setOverview(String overview) {
this.overview = overview;
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/javadoc/Javadoc.java b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/javadoc/Javadoc.java
index 3da6c79..65472c5 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/javadoc/Javadoc.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/javadoc/Javadoc.java
@@ -16,6 +16,7 @@
package org.gradle.api.tasks.javadoc;
+import groovy.lang.Closure;
import org.gradle.api.GradleException;
import org.gradle.api.file.FileCollection;
import org.gradle.api.tasks.*;
@@ -26,8 +27,6 @@ import org.gradle.process.internal.ExecAction;
import org.gradle.process.internal.ExecException;
import org.gradle.util.GUtil;
-import groovy.lang.Closure;
-
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
@@ -67,8 +66,6 @@ import java.util.List;
* options.addStringOption("jaxrscontext", "http://localhost:8080/myapp")
* }
* </pre>
- *
- * @author Hans Dockter
*/
public class Javadoc extends SourceTask {
private JavadocExecHandleBuilder javadocExecHandleBuilder = new JavadocExecHandleBuilder();
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/testing/JUnitXmlReport.java b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/testing/JUnitXmlReport.java
new file mode 100644
index 0000000..692c2dc
--- /dev/null
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/testing/JUnitXmlReport.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.tasks.testing;
+
+import org.gradle.api.Incubating;
+import org.gradle.api.reporting.DirectoryReport;
+
+/**
+ * The JUnit XML files, commonly used to communicate results to CI servers.
+ */
+public interface JUnitXmlReport extends DirectoryReport {
+
+ /**
+ * Should the output be associated with individual test cases instead of at the suite level.
+ */
+ @Incubating
+ boolean isOutputPerTestCase();
+
+ /**
+ * Should the output be associated with individual test cases instead of at the suite level.
+ */
+ @Incubating
+ void setOutputPerTestCase(boolean outputPerTestCase);
+
+}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/testing/Test.java b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/testing/Test.java
index 2a4aa96..c393edf 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/testing/Test.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/testing/Test.java
@@ -24,6 +24,7 @@ import org.gradle.api.file.FileTree;
import org.gradle.api.file.FileTreeElement;
import org.gradle.api.internal.ConventionTask;
import org.gradle.api.internal.file.FileResolver;
+import org.gradle.api.internal.tasks.testing.DefaultTestTaskReports;
import org.gradle.api.internal.tasks.testing.TestFramework;
import org.gradle.api.internal.tasks.testing.TestResultProcessor;
import org.gradle.api.internal.tasks.testing.detection.DefaultTestExecuter;
@@ -31,18 +32,20 @@ import org.gradle.api.internal.tasks.testing.detection.TestExecuter;
import org.gradle.api.internal.tasks.testing.junit.JUnitTestFramework;
import org.gradle.api.internal.tasks.testing.junit.report.DefaultTestReport;
import org.gradle.api.internal.tasks.testing.junit.report.TestReporter;
-import org.gradle.api.internal.tasks.testing.junit.result.Binary2JUnitXmlReportGenerator;
-import org.gradle.api.internal.tasks.testing.junit.result.TestReportDataCollector;
+import org.gradle.api.internal.tasks.testing.junit.result.*;
import org.gradle.api.internal.tasks.testing.logging.*;
import org.gradle.api.internal.tasks.testing.results.TestListenerAdapter;
import org.gradle.api.internal.tasks.testing.testng.TestNGTestFramework;
import org.gradle.api.logging.LogLevel;
+import org.gradle.api.reporting.DirectoryReport;
+import org.gradle.api.reporting.Reporting;
import org.gradle.api.specs.Spec;
import org.gradle.api.tasks.*;
import org.gradle.api.tasks.testing.logging.TestLogging;
import org.gradle.api.tasks.testing.logging.TestLoggingContainer;
import org.gradle.api.tasks.util.PatternFilterable;
import org.gradle.api.tasks.util.PatternSet;
+import org.gradle.internal.CompositeStoppable;
import org.gradle.internal.Factory;
import org.gradle.internal.reflect.Instantiator;
import org.gradle.listener.ClosureBackedMethodInvocationDispatch;
@@ -57,13 +60,11 @@ import org.gradle.process.ProcessForkOptions;
import org.gradle.process.internal.DefaultJavaForkOptions;
import org.gradle.process.internal.WorkerProcessBuilder;
import org.gradle.util.ConfigureUtil;
+import org.gradle.util.DeprecationLogger;
import javax.inject.Inject;
import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
import static java.util.Arrays.asList;
@@ -106,34 +107,32 @@ import static java.util.Arrays.asList;
* }
* }
* </pre>
- *
- * @author Hans Dockter
*/
-public class Test extends ConventionTask implements JavaForkOptions, PatternFilterable, VerificationTask {
+public class Test extends ConventionTask implements JavaForkOptions, PatternFilterable, VerificationTask, Reporting<TestTaskReports> {
private final ListenerBroadcast<TestListener> testListenerBroadcaster;
private final ListenerBroadcast<TestOutputListener> testOutputListenerBroadcaster;
private final StyledTextOutputFactory textOutputFactory;
private final ProgressLoggerFactory progressLoggerFactory;
private final TestLoggingContainer testLogging;
- private final DefaultJavaForkOptions options;
+ private final DefaultJavaForkOptions forkOptions;
private TestExecuter testExecuter;
private List<File> testSrcDirs = new ArrayList<File>();
private File testClassesDir;
- private File testResultsDir;
private File binResultsDir;
- private File testReportDir;
private PatternFilterable patternSet = new PatternSet();
private boolean ignoreFailures;
private FileCollection classpath;
private TestFramework testFramework;
- private boolean testReport = true;
private boolean scanForTestClasses = true;
private long forkEvery;
private int maxParallelForks = 1;
private TestReporter testReporter;
+ @Nested
+ private final DefaultTestTaskReports reports;
+
@Inject
public Test(ListenerManager listenerManager, StyledTextOutputFactory textOutputFactory, FileResolver fileResolver,
Factory<WorkerProcessBuilder> processBuilderFactory, ActorFactory actorFactory, Instantiator instantiator,
@@ -142,19 +141,24 @@ public class Test extends ConventionTask implements JavaForkOptions, PatternFilt
testListenerBroadcaster = listenerManager.createAnonymousBroadcaster(TestListener.class);
testOutputListenerBroadcaster = listenerManager.createAnonymousBroadcaster(TestOutputListener.class);
this.textOutputFactory = textOutputFactory;
- options = new DefaultJavaForkOptions(fileResolver);
- options.setEnableAssertions(true);
+ forkOptions = new DefaultJavaForkOptions(fileResolver);
+ forkOptions.setEnableAssertions(true);
testExecuter = new DefaultTestExecuter(processBuilderFactory, actorFactory);
testLogging = instantiator.newInstance(DefaultTestLoggingContainer.class, instantiator);
testReporter = new DefaultTestReport();
+
+ reports = instantiator.newInstance(DefaultTestTaskReports.class, this);
+ reports.getJunitXml().setEnabled(true);
+ reports.getHtml().setEnabled(true);
}
/**
* ATM. for testing only
- * */
- void setTestReporter(TestReporter testReporter){
+ */
+ void setTestReporter(TestReporter testReporter) {
this.testReporter = testReporter;
}
+
void setTestExecuter(TestExecuter testExecuter) {
this.testExecuter = testExecuter;
}
@@ -164,21 +168,21 @@ public class Test extends ConventionTask implements JavaForkOptions, PatternFilt
*/
@Input
public File getWorkingDir() {
- return options.getWorkingDir();
+ return forkOptions.getWorkingDir();
}
/**
* {@inheritDoc}
*/
public void setWorkingDir(Object dir) {
- options.setWorkingDir(dir);
+ forkOptions.setWorkingDir(dir);
}
/**
* {@inheritDoc}
*/
public Test workingDir(Object dir) {
- options.workingDir(dir);
+ forkOptions.workingDir(dir);
return this;
}
@@ -187,14 +191,14 @@ public class Test extends ConventionTask implements JavaForkOptions, PatternFilt
*/
@Input
public String getExecutable() {
- return options.getExecutable();
+ return forkOptions.getExecutable();
}
/**
* {@inheritDoc}
*/
public Test executable(Object executable) {
- options.executable(executable);
+ forkOptions.executable(executable);
return this;
}
@@ -202,7 +206,7 @@ public class Test extends ConventionTask implements JavaForkOptions, PatternFilt
* {@inheritDoc}
*/
public void setExecutable(Object executable) {
- options.setExecutable(executable);
+ forkOptions.setExecutable(executable);
}
/**
@@ -210,21 +214,21 @@ public class Test extends ConventionTask implements JavaForkOptions, PatternFilt
*/
@Input
public Map<String, Object> getSystemProperties() {
- return options.getSystemProperties();
+ return forkOptions.getSystemProperties();
}
/**
* {@inheritDoc}
*/
public void setSystemProperties(Map<String, ?> properties) {
- options.setSystemProperties(properties);
+ forkOptions.setSystemProperties(properties);
}
/**
* {@inheritDoc}
*/
public Test systemProperties(Map<String, ?> properties) {
- options.systemProperties(properties);
+ forkOptions.systemProperties(properties);
return this;
}
@@ -232,7 +236,7 @@ public class Test extends ConventionTask implements JavaForkOptions, PatternFilt
* {@inheritDoc}
*/
public Test systemProperty(String name, Object value) {
- options.systemProperty(name, value);
+ forkOptions.systemProperty(name, value);
return this;
}
@@ -241,21 +245,21 @@ public class Test extends ConventionTask implements JavaForkOptions, PatternFilt
*/
@Input
public FileCollection getBootstrapClasspath() {
- return options.getBootstrapClasspath();
+ return forkOptions.getBootstrapClasspath();
}
/**
* {@inheritDoc}
*/
public void setBootstrapClasspath(FileCollection classpath) {
- options.setBootstrapClasspath(classpath);
+ forkOptions.setBootstrapClasspath(classpath);
}
/**
* {@inheritDoc}
*/
public Test bootstrapClasspath(Object... classpath) {
- options.bootstrapClasspath(classpath);
+ forkOptions.bootstrapClasspath(classpath);
return this;
}
@@ -263,42 +267,42 @@ public class Test extends ConventionTask implements JavaForkOptions, PatternFilt
* {@inheritDoc}
*/
public String getMinHeapSize() {
- return options.getMinHeapSize();
+ return forkOptions.getMinHeapSize();
}
/**
* {@inheritDoc}
*/
public String getDefaultCharacterEncoding() {
- return options.getDefaultCharacterEncoding();
+ return forkOptions.getDefaultCharacterEncoding();
}
/**
* {@inheritDoc}
*/
public void setDefaultCharacterEncoding(String defaultCharacterEncoding) {
- options.setDefaultCharacterEncoding(defaultCharacterEncoding);
+ forkOptions.setDefaultCharacterEncoding(defaultCharacterEncoding);
}
/**
* {@inheritDoc}
*/
public void setMinHeapSize(String heapSize) {
- options.setMinHeapSize(heapSize);
+ forkOptions.setMinHeapSize(heapSize);
}
/**
* {@inheritDoc}
*/
public String getMaxHeapSize() {
- return options.getMaxHeapSize();
+ return forkOptions.getMaxHeapSize();
}
/**
* {@inheritDoc}
*/
public void setMaxHeapSize(String heapSize) {
- options.setMaxHeapSize(heapSize);
+ forkOptions.setMaxHeapSize(heapSize);
}
/**
@@ -306,21 +310,21 @@ public class Test extends ConventionTask implements JavaForkOptions, PatternFilt
*/
@Input
public List<String> getJvmArgs() {
- return options.getJvmArgs();
+ return forkOptions.getJvmArgs();
}
/**
* {@inheritDoc}
*/
public void setJvmArgs(Iterable<?> arguments) {
- options.setJvmArgs(arguments);
+ forkOptions.setJvmArgs(arguments);
}
/**
* {@inheritDoc}
*/
public Test jvmArgs(Iterable<?> arguments) {
- options.jvmArgs(arguments);
+ forkOptions.jvmArgs(arguments);
return this;
}
@@ -328,7 +332,7 @@ public class Test extends ConventionTask implements JavaForkOptions, PatternFilt
* {@inheritDoc}
*/
public Test jvmArgs(Object... arguments) {
- options.jvmArgs(arguments);
+ forkOptions.jvmArgs(arguments);
return this;
}
@@ -337,56 +341,56 @@ public class Test extends ConventionTask implements JavaForkOptions, PatternFilt
*/
@Input
public boolean getEnableAssertions() {
- return options.getEnableAssertions();
+ return forkOptions.getEnableAssertions();
}
/**
* {@inheritDoc}
*/
public void setEnableAssertions(boolean enabled) {
- options.setEnableAssertions(enabled);
+ forkOptions.setEnableAssertions(enabled);
}
/**
* {@inheritDoc}
*/
public boolean getDebug() {
- return options.getDebug();
+ return forkOptions.getDebug();
}
/**
* {@inheritDoc}
*/
public void setDebug(boolean enabled) {
- options.setDebug(enabled);
+ forkOptions.setDebug(enabled);
}
/**
* {@inheritDoc}
*/
public List<String> getAllJvmArgs() {
- return options.getAllJvmArgs();
+ return forkOptions.getAllJvmArgs();
}
/**
* {@inheritDoc}
*/
public void setAllJvmArgs(Iterable<?> arguments) {
- options.setAllJvmArgs(arguments);
+ forkOptions.setAllJvmArgs(arguments);
}
/**
* {@inheritDoc}
*/
public Map<String, Object> getEnvironment() {
- return options.getEnvironment();
+ return forkOptions.getEnvironment();
}
/**
* {@inheritDoc}
*/
public Test environment(Map<String, ?> environmentVariables) {
- options.environment(environmentVariables);
+ forkOptions.environment(environmentVariables);
return this;
}
@@ -394,7 +398,7 @@ public class Test extends ConventionTask implements JavaForkOptions, PatternFilt
* {@inheritDoc}
*/
public Test environment(String name, Object value) {
- options.environment(name, value);
+ forkOptions.environment(name, value);
return this;
}
@@ -402,14 +406,14 @@ public class Test extends ConventionTask implements JavaForkOptions, PatternFilt
* {@inheritDoc}
*/
public void setEnvironment(Map<String, ?> environmentVariables) {
- options.setEnvironment(environmentVariables);
+ forkOptions.setEnvironment(environmentVariables);
}
/**
* {@inheritDoc}
*/
public Test copyTo(ProcessForkOptions target) {
- options.copyTo(target);
+ forkOptions.copyTo(target);
return this;
}
@@ -417,7 +421,7 @@ public class Test extends ConventionTask implements JavaForkOptions, PatternFilt
* {@inheritDoc}
*/
public Test copyTo(JavaForkOptions target) {
- options.copyTo(target);
+ forkOptions.copyTo(target);
return this;
}
@@ -434,7 +438,12 @@ public class Test extends ConventionTask implements JavaForkOptions, PatternFilt
getProject().delete(binaryResultsDir);
getProject().mkdir(binaryResultsDir);
- TestReportDataCollector testReportDataCollector = new TestReportDataCollector(binaryResultsDir);
+ Map<String, TestClassResult> results = new HashMap<String, TestClassResult>();
+ TestOutputStore testOutputStore = new TestOutputStore(binaryResultsDir);
+
+ TestOutputStore.Writer outputWriter = testOutputStore.writer();
+ TestReportDataCollector testReportDataCollector = new TestReportDataCollector(results, outputWriter);
+
addTestListener(testReportDataCollector);
addTestOutputListener(testReportDataCollector);
@@ -449,15 +458,31 @@ public class Test extends ConventionTask implements JavaForkOptions, PatternFilt
} finally {
testListenerBroadcaster.removeAll(asList(eventLogger, testReportDataCollector, testCountLogger));
testOutputListenerBroadcaster.removeAll(asList(eventLogger, testReportDataCollector));
+ outputWriter.close();
}
- Binary2JUnitXmlReportGenerator binary2JUnitXmlReportGenerator = new Binary2JUnitXmlReportGenerator(getTestResultsDir(), testReportDataCollector);
- binary2JUnitXmlReportGenerator.generate();
+ new TestResultSerializer(binaryResultsDir).write(results.values());
- if (!isTestReport()) {
- getLogger().info("Test report disabled, omitting generation of the HTML test report.");
- } else {
- testReporter.generateReport(testReportDataCollector, getTestReportDir());
+ TestResultsProvider testResultsProvider = new InMemoryTestResultsProvider(results.values(), testOutputStore.reader());
+
+ try {
+ JUnitXmlReport junitXml = reports.getJunitXml();
+ if (junitXml.isEnabled()) {
+ TestOutputAssociation outputAssociation = junitXml.isOutputPerTestCase()
+ ? TestOutputAssociation.WITH_TESTCASE
+ : TestOutputAssociation.WITH_SUITE;
+ Binary2JUnitXmlReportGenerator binary2JUnitXmlReportGenerator = new Binary2JUnitXmlReportGenerator(junitXml.getDestination(), testResultsProvider, outputAssociation);
+ binary2JUnitXmlReportGenerator.generate();
+ }
+
+ DirectoryReport html = reports.getHtml();
+ if (!html.isEnabled()) {
+ getLogger().info("Test report disabled, omitting generation of the HTML test report.");
+ } else {
+ testReporter.generateReport(testResultsProvider, html.getDestination());
+ }
+ } finally {
+ CompositeStoppable.stoppable(testResultsProvider).stop();
}
testFramework = null;
@@ -664,19 +689,24 @@ public class Test extends ConventionTask implements JavaForkOptions, PatternFilt
* Returns the root folder for the test results in XML format.
*
* @return the test result directory, containing the test results in XML format.
+ * @deprecated Replaced by {@code getReports().getJunitXml().getDestination()}
*/
- @OutputDirectory
+ @Deprecated
public File getTestResultsDir() {
- return testResultsDir;
+ DeprecationLogger.nagUserOfReplacedProperty("Test.testResultsDir", "Test.getReports().getJunitXml().getDestination()");
+ return reports.getJunitXml().getDestination();
}
/**
* Sets the root folder for the test results.
*
* @param testResultsDir The root folder
+ * @deprecated Replaced by {@code getReports().getJunitXml().setDestination()}
*/
+ @Deprecated
public void setTestResultsDir(File testResultsDir) {
- this.testResultsDir = testResultsDir;
+ DeprecationLogger.nagUserOfReplacedProperty("Test.testResultsDir", "Test.getReports().getJunitXml().setDestination()");
+ reports.getJunitXml().setDestination(testResultsDir);
}
/**
@@ -684,7 +714,8 @@ public class Test extends ConventionTask implements JavaForkOptions, PatternFilt
*
* @return the test result directory, containing the test results in binary format.
*/
- @OutputDirectory @Incubating
+ @OutputDirectory
+ @Incubating
public File getBinResultsDir() {
return binResultsDir;
}
@@ -703,19 +734,24 @@ public class Test extends ConventionTask implements JavaForkOptions, PatternFilt
* Returns the root folder for the test reports.
*
* @return the test report directory, containing the test report mostly in HTML form.
+ * @deprecated Replaced by {@code getReports().getHtml().getDestination()}
*/
- @OutputDirectory
+ @Deprecated
public File getTestReportDir() {
- return testReportDir;
+ DeprecationLogger.nagUserOfReplacedProperty("Test.testReportDir", "Test.getReports().getHtml().getDestination()");
+ return reports.getHtml().getDestination();
}
/**
* Sets the root folder for the test reports.
*
* @param testReportDir The root folder
+ * @deprecated Replaced by {@code getReports().getHtml().setDestination()}
*/
+ @Deprecated
public void setTestReportDir(File testReportDir) {
- this.testReportDir = testReportDir;
+ DeprecationLogger.nagUserOfReplacedProperty("Test.testReportDir", "Test.getReports().getHtml().getDestination()");
+ reports.getHtml().setDestination(testReportDir);
}
/**
@@ -802,7 +838,7 @@ public class Test extends ConventionTask implements JavaForkOptions, PatternFilt
*/
public TestFrameworkOptions options(Closure testFrameworkConfigure) {
TestFrameworkOptions options = getTestFramework().getOptions();
- ConfigureUtil.configure(testFrameworkConfigure, testFramework.getOptions());
+ ConfigureUtil.configure(testFrameworkConfigure, options);
return options;
}
@@ -825,32 +861,34 @@ public class Test extends ConventionTask implements JavaForkOptions, PatternFilt
}
/**
- * Specifies that JUnit should be used to execute the tests.
+ * Specifies that JUnit should be used to execute the tests. <p> To configure TestNG specific options, see {@link #useJUnit(groovy.lang.Closure)}.
*/
public void useJUnit() {
useJUnit(null);
}
/**
- * Specifies that JUnit should be used to execute the tests.
+ * Specifies that JUnit should be used to execute the tests, configuring JUnit specific options. <p> The supplied closure configures an instance of {@link
+ * org.gradle.api.tasks.testing.junit.JUnitOptions}, which can be used to configure how JUnit runs.
*
- * @param testFrameworkConfigure A closure used to configure the JUnit options. This closure is passed an instance of type {@link org.gradle.api.tasks.testing.junit.JUnitOptions}.
+ * @param testFrameworkConfigure A closure used to configure the JUnit options.
*/
public void useJUnit(Closure testFrameworkConfigure) {
useTestFramework(new JUnitTestFramework(this), testFrameworkConfigure);
}
/**
- * Specifies that TestNG should be used to execute the tests.
+ * Specifies that TestNG should be used to execute the tests. <p> To configure TestNG specific options, see {@link #useTestNG(Closure)}.
*/
public void useTestNG() {
useTestNG(null);
}
/**
- * Specifies that TestNG should be used to execute the tests.
+ * Specifies that TestNG should be used to execute the tests, configuring TestNG specific options. <p> The supplied closure configures an instance of {@link
+ * org.gradle.api.tasks.testing.testng.TestNGOptions}, which can be used to configure how TestNG runs.
*
- * @param testFrameworkConfigure A closure used to configure the TestNG options. This closure is passed an instance of type {@link org.gradle.api.tasks.testing.testng.TestNGOptions}.
+ * @param testFrameworkConfigure A closure used to configure the TestNG options.
*/
public void useTestNG(Closure testFrameworkConfigure) {
useTestFramework(new TestNGTestFramework(this), testFrameworkConfigure);
@@ -870,22 +908,48 @@ public class Test extends ConventionTask implements JavaForkOptions, PatternFilt
/**
* Specifies whether the test HTML report should be generated.
+ *
+ * @deprecated Replaced by {@code getReports().getHtml().isEnabled()}
*/
- @Input
+ @Deprecated
public boolean isTestReport() {
- return testReport;
+ DeprecationLogger.nagUserOfReplacedProperty("Test.testReport", "Test.getReports().getHtml().isEnabled()");
+ return reports.getHtml().isEnabled();
}
+ /**
+ * Sets whether the test HTML report should be generated.
+ *
+ * @deprecated Replaced by {@code getReports().getHtml().setEnabled()}
+ */
+ @Deprecated
public void setTestReport(boolean testReport) {
- this.testReport = testReport;
+ DeprecationLogger.nagUserOfReplacedProperty("Test.testReport", "Test.getReports().getHtml().setEnabled()");
+ reports.getHtml().setEnabled(testReport);
}
+ /**
+ * Enables the HTML test report.
+ *
+ * @deprecated Replaced by {@code getReports().getHtml().setEnabled()}
+ */
+ @SuppressWarnings("UnusedDeclaration")
+ @Deprecated
public void enableTestReport() {
- this.testReport = true;
+ DeprecationLogger.nagUserOfReplacedProperty("Test.testReport", "Test.getReports().getHtml().setEnabled()");
+ reports.getHtml().setEnabled(true);
}
+ /**
+ * Disables the HTML test report.
+ *
+ * @deprecated Replaced by {@code getReports().getHtml().setEnabled()}
+ */
+ @SuppressWarnings("UnusedDeclaration")
+ @Deprecated
public void disableTestReport() {
- this.testReport = false;
+ DeprecationLogger.nagUserOfReplacedProperty("Test.testReport", "Test.getReports().getHtml().setEnabled()");
+ reports.getHtml().setEnabled(false);
}
/**
@@ -961,7 +1025,7 @@ public class Test extends ConventionTask implements JavaForkOptions, PatternFilt
* @return The candidate class files.
*/
@InputFiles
- @Input // Also marked as input to force tests to run when the set of candidate class files changes
+ @Input
public FileTree getCandidateClassFiles() {
return getProject().fileTree(getTestClassesDir()).matching(patternSet);
}
@@ -992,6 +1056,26 @@ public class Test extends ConventionTask implements JavaForkOptions, PatternFilt
ConfigureUtil.configure(closure, testLogging);
}
+ /**
+ * The reports that this task potentially produces.
+ *
+ * @return The reports that this task potentially produces
+ */
+ public TestTaskReports getReports() {
+ return reports;
+ }
+
+ /**
+ * Configures the reports that this task potentially produces.
+ *
+ * @param closure The configuration
+ * @return The reports that this task potentially produces
+ */
+ public TestTaskReports reports(Closure closure) {
+ reports.configure(closure);
+ return reports;
+ }
+
// only way I know of to determine current log level
private LogLevel getCurrentLogLevel() {
for (LogLevel level : LogLevel.values()) {
@@ -1014,8 +1098,20 @@ public class Test extends ConventionTask implements JavaForkOptions, PatternFilt
}
private void handleTestFailures() {
- String reportUrl = new ConsoleRenderer().asClickableFileUrl(new File(getTestReportDir(), "index.html"));
- String message = "There were failing tests. See the report at: " + reportUrl;
+ String message = "There were failing tests";
+
+ DirectoryReport htmlReport = reports.getHtml();
+ if (htmlReport.isEnabled()) {
+ String reportUrl = new ConsoleRenderer().asClickableFileUrl(htmlReport.getEntryPoint());
+ message = message.concat(". See the report at: " + reportUrl);
+ } else {
+ DirectoryReport junitXmlReport = reports.getJunitXml();
+ if (junitXmlReport.isEnabled()) {
+ String resultsUrl = new ConsoleRenderer().asClickableFileUrl(junitXmlReport.getEntryPoint());
+ message = message.concat(". See the results at: " + resultsUrl);
+ }
+ }
+
if (getIgnoreFailures()) {
getLogger().warn(message);
} else {
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/testing/TestDescriptor.java b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/testing/TestDescriptor.java
index 005c349..f3d651a 100755
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/testing/TestDescriptor.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/testing/TestDescriptor.java
@@ -16,10 +16,13 @@
package org.gradle.api.tasks.testing;
+import org.gradle.api.internal.HasInternalProtocol;
+
/**
* Describes a test. A test may be a single atomic test, such as the execution of a test method, or it may be a
* composite test, made up of zero or more tests.
*/
+ at HasInternalProtocol
public interface TestDescriptor {
/**
* Returns the name of the test. Not guaranteed to be unique.
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/testing/TestReport.java b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/testing/TestReport.java
index e4c65d4..489e334 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/testing/TestReport.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/testing/TestReport.java
@@ -18,10 +18,12 @@ package org.gradle.api.tasks.testing;
import org.gradle.api.DefaultTask;
import org.gradle.api.Incubating;
+import org.gradle.api.Transformer;
import org.gradle.api.file.FileCollection;
import org.gradle.api.internal.file.UnionFileCollection;
import org.gradle.api.internal.tasks.testing.junit.report.DefaultTestReport;
import org.gradle.api.internal.tasks.testing.junit.result.AggregateTestResultsProvider;
+import org.gradle.api.internal.tasks.testing.junit.result.BinaryResultBackedTestResultsProvider;
import org.gradle.api.internal.tasks.testing.junit.result.TestResultsProvider;
import org.gradle.api.tasks.InputFiles;
import org.gradle.api.tasks.OutputDirectory;
@@ -30,8 +32,12 @@ import org.gradle.api.tasks.TaskAction;
import java.io.File;
import java.util.ArrayList;
+import java.util.LinkedList;
import java.util.List;
+import static org.gradle.internal.CompositeStoppable.stoppable;
+import static org.gradle.util.CollectionUtils.collect;
+
/**
* Generates an HTML test report from the results of one or more {@link Test} tasks.
*/
@@ -117,8 +123,30 @@ public class TestReport extends DefaultTask {
@TaskAction
void generateReport() {
- TestResultsProvider resultsProvider = new AggregateTestResultsProvider(getTestResultDirs().getFiles());
- DefaultTestReport testReport = new DefaultTestReport();
- testReport.generateReport(resultsProvider, getDestinationDir());
+ TestResultsProvider resultsProvider = createAggregateProvider();
+ try {
+ if (resultsProvider.isHasResults()) {
+ DefaultTestReport testReport = new DefaultTestReport();
+ testReport.generateReport(resultsProvider, getDestinationDir());
+ } else {
+ setDidWork(false);
+ }
+ } finally {
+ stoppable(resultsProvider).stop();
+ }
+ }
+
+ private TestResultsProvider createAggregateProvider() {
+ List<TestResultsProvider> resultsProviders = new LinkedList<TestResultsProvider>();
+ try {
+ return new AggregateTestResultsProvider(collect(getTestResultDirs(), resultsProviders, new Transformer<TestResultsProvider, File>() {
+ public TestResultsProvider transform(File dir) {
+ return new BinaryResultBackedTestResultsProvider(dir);
+ }
+ }));
+ } catch (RuntimeException e) {
+ stoppable(resultsProviders).stop();
+ throw e;
+ }
}
}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/testing/TestTaskReports.java b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/testing/TestTaskReports.java
new file mode 100644
index 0000000..efb2407
--- /dev/null
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/testing/TestTaskReports.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.tasks.testing;
+
+import org.gradle.api.reporting.DirectoryReport;
+import org.gradle.api.reporting.Report;
+import org.gradle.api.reporting.ReportContainer;
+
+/**
+ * The reports produced by the {@link Test} task.
+ */
+public interface TestTaskReports extends ReportContainer<Report> {
+
+ /**
+ * A HTML report indicate the results of the test execution.
+ *
+ * @return The HTML report
+ */
+ DirectoryReport getHtml();
+
+ /**
+ * The test results in “JUnit XML” format.
+ *
+ * @return The test results in “JUnit XML” format
+ */
+ JUnitXmlReport getJunitXml();
+
+}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/testing/junit/JUnitOptions.groovy b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/testing/junit/JUnitOptions.groovy
new file mode 100644
index 0000000..64c3342
--- /dev/null
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/testing/junit/JUnitOptions.groovy
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.tasks.testing.junit
+
+import org.gradle.api.Incubating;
+import org.gradle.api.tasks.testing.TestFrameworkOptions;
+
+/**
+ * The JUnit specific test options.
+ */
+public class JUnitOptions extends TestFrameworkOptions {
+
+ /**
+ * The set of categories to run.
+ */
+ @Incubating
+ Set<String> includeCategories = new HashSet<String>();
+
+ /**
+ * The set of categories to exclude.
+ */
+ @Incubating
+ Set<String> excludeCategories = new HashSet<String>();
+
+
+ @Incubating
+ JUnitOptions includeCategories(String... includeCategories) {
+ this.includeCategories.addAll(Arrays.asList(includeCategories));
+ this;
+ }
+
+ @Incubating
+ JUnitOptions excludeCategories(String... excludeCategories) {
+ this.excludeCategories.addAll(Arrays.asList(excludeCategories));
+ this;
+ }
+}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/testing/junit/JUnitOptions.java b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/testing/junit/JUnitOptions.java
deleted file mode 100644
index 05db5ad..0000000
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/testing/junit/JUnitOptions.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.tasks.testing.junit;
-
-import org.gradle.api.tasks.testing.TestFrameworkOptions;
-
-/**
- * The JUnit specific test options.
- */
-public class JUnitOptions extends TestFrameworkOptions {
-}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/testing/testng/TestNGOptions.groovy b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/testing/testng/TestNGOptions.groovy
index 1067436..dc9bac1 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/testing/testng/TestNGOptions.groovy
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/testing/testng/TestNGOptions.groovy
@@ -19,9 +19,6 @@ import groovy.xml.MarkupBuilder
import org.gradle.api.JavaVersion
import org.gradle.api.tasks.testing.TestFrameworkOptions
-/**
- * @author Tom Eyckmans
- */
public class TestNGOptions extends TestFrameworkOptions{
static final String JDK_ANNOTATIONS = 'JDK'
static final String JAVADOC_ANNOTATIONS = 'Javadoc'
@@ -64,7 +61,7 @@ public class TestNGOptions extends TestFrameworkOptions{
*
* test {
* useTestNG() {
- * //creates emailable html file
+ * //creates emailable HTML file
* //this reporter typically ships with TestNG library
* listeners << 'org.testng.reporters.EmailableReporter'
* }
@@ -105,25 +102,25 @@ public class TestNGOptions extends TestFrameworkOptions{
*
* //turn off Gradle's HTML report to avoid replacing the
* //reports generated by TestNG library:
- * testReport = false
+ * reports.html.enabled = false
* }
* </pre>
*
* Please refer to the documentation of your version of TestNG what are the default listeners.
* At the moment of writing this documentation, the default listeners are a set of reporters that generate:
- * TestNG variant of html results, TestNG variant of xml results in JUnit format, emailable html test report,
- * xml results in TestNG format.
+ * TestNG variant of HTML results, TestNG variant of XML results in JUnit format, emailable HTML test report,
+ * XML results in TestNG format.
*
*/
boolean useDefaultListeners = false
/**
- * Sets the default name of the test suite, if one is not specified in a suite xml file or in the source code.
+ * Sets the default name of the test suite, if one is not specified in a suite XML file or in the source code.
*/
String suiteName = 'Gradle suite'
/**
- * Sets the default name of the test, if one is not specified in a suite xml file or in the source code.
+ * Sets the default name of the test, if one is not specified in a suite XML file or in the source code.
*/
String testName = 'Gradle test'
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/wrapper/Wrapper.java b/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/wrapper/Wrapper.java
deleted file mode 100644
index 8c5d3bc..0000000
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/tasks/wrapper/Wrapper.java
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.tasks.wrapper;
-
-import org.gradle.api.DefaultTask;
-import org.gradle.api.GradleException;
-import org.gradle.api.internal.file.FileResolver;
-import org.gradle.api.internal.plugins.StartScriptGenerator;
-import org.gradle.api.tasks.Input;
-import org.gradle.api.tasks.OutputFile;
-import org.gradle.api.tasks.TaskAction;
-import org.gradle.util.*;
-import org.gradle.wrapper.GradleWrapperMain;
-import org.gradle.wrapper.Install;
-import org.gradle.wrapper.WrapperExecutor;
-
-import java.io.File;
-import java.net.URL;
-import java.util.Properties;
-
-/**
- * <p>Generates scripts (for *nix and windows) which allow you to build your project with Gradle, without having to
- * install Gradle.
- *
- * <p>When a user executes a wrapper script the first time, the script downloads and installs the appropriate Gradle
- * distribution and runs the build against this downloaded distribution. Any installed Gradle distribution is ignored
- * when using the wrapper scripts.
- *
- * <p>The scripts generated by this task are intended to be committed to your version control system. This task also
- * generates a small {@code gradle-wrapper.jar} bootstrap JAR file and properties file which should also be committed to
- * your VCS. The scripts delegates to this JAR.
- *
- * @author Hans Dockter
- */
-public class Wrapper extends DefaultTask {
- public static final String DEFAULT_DISTRIBUTION_PARENT_NAME = Install.DEFAULT_DISTRIBUTION_PATH;
-
- private String distributionUrl;
-
- /**
- * Specifies how the wrapper path should be interpreted.
- */
- public enum PathBase {
- PROJECT, GRADLE_USER_HOME
- }
-
- private Object scriptFile;
- private Object jarFile;
-
- @Input
- private String distributionPath;
-
- @Input
- private PathBase distributionBase = PathBase.GRADLE_USER_HOME;
-
- private GradleVersion gradleVersion;
-
- @Input
- private String archivePath;
-
- @Input
- private PathBase archiveBase = PathBase.GRADLE_USER_HOME;
-
- private final DistributionLocator locator = new DistributionLocator();
-
- public Wrapper() {
- scriptFile = "gradlew";
- jarFile = "gradle/wrapper/gradle-wrapper.jar";
- distributionPath = DEFAULT_DISTRIBUTION_PARENT_NAME;
- archivePath = DEFAULT_DISTRIBUTION_PARENT_NAME;
- gradleVersion = GradleVersion.current();
- }
-
- @TaskAction
- void generate() {
- File jarFileDestination = getJarFile();
- File unixScript = getScriptFile();
- FileResolver resolver = getServices().get(FileResolver.class).withBaseDir(unixScript.getParentFile());
- String jarFileRelativePath = resolver.resolveAsRelativePath(jarFileDestination);
-
- writeProperties(getPropertiesFile());
-
- URL jarFileSource = Wrapper.class.getResource("/gradle-wrapper.jar");
- if (jarFileSource == null) {
- throw new GradleException("Cannot locate wrapper JAR resource.");
- }
- GFileUtils.copyURLToFile(jarFileSource, jarFileDestination);
-
- StartScriptGenerator generator = new StartScriptGenerator();
- generator.setApplicationName("Gradle");
- generator.setMainClassName(GradleWrapperMain.class.getName());
- generator.setClasspath(WrapUtil.toList(jarFileRelativePath));
- generator.setOptsEnvironmentVar("GRADLE_OPTS");
- generator.setExitEnvironmentVar("GRADLE_EXIT_CONSOLE");
- generator.setAppNameSystemProperty("org.gradle.appname");
- generator.setScriptRelPath(unixScript.getName());
- generator.generateUnixScript(unixScript);
- generator.generateWindowsScript(getBatchScript());
- }
-
- private void writeProperties(File propertiesFileDestination) {
- Properties wrapperProperties = new Properties();
- wrapperProperties.put(WrapperExecutor.DISTRIBUTION_URL_PROPERTY, getDistributionUrl());
- wrapperProperties.put(WrapperExecutor.DISTRIBUTION_BASE_PROPERTY, distributionBase.toString());
- wrapperProperties.put(WrapperExecutor.DISTRIBUTION_PATH_PROPERTY, distributionPath);
- wrapperProperties.put(WrapperExecutor.ZIP_STORE_BASE_PROPERTY, archiveBase.toString());
- wrapperProperties.put(WrapperExecutor.ZIP_STORE_PATH_PROPERTY, archivePath);
- GUtil.saveProperties(wrapperProperties, propertiesFileDestination);
- }
-
- /**
- * Returns the file to write the wrapper script to.
- */
- @OutputFile
- public File getScriptFile() {
- return getProject().file(scriptFile);
- }
-
- public void setScriptFile(Object scriptFile) {
- this.scriptFile = scriptFile;
- }
-
- /**
- * Returns the file to write the wrapper batch script to.
- */
- @OutputFile
- public File getBatchScript() {
- File scriptFile = getScriptFile();
- return new File(scriptFile.getParentFile(), scriptFile.getName().replaceFirst("(\\.[^\\.]+)?$", ".bat"));
- }
-
- /**
- * Returns the file to write the wrapper jar file to.
- */
- @OutputFile
- public File getJarFile() {
- return getProject().file(jarFile);
- }
-
- public void setJarFile(Object jarFile) {
- this.jarFile = jarFile;
- }
-
- /**
- * Returns the file to write the wrapper properties to.
- */
- @OutputFile
- public File getPropertiesFile() {
- File jarFileDestination = getJarFile();
- return new File(jarFileDestination.getParentFile(), jarFileDestination.getName().replaceAll("\\.jar$",
- ".properties"));
- }
-
- /**
- * Returns the path where the gradle distributions needed by the wrapper are unzipped. The path is relative to the
- * distribution base directory
- *
- * @see #setDistributionPath(String)
- */
- public String getDistributionPath() {
- return distributionPath;
- }
-
- /**
- * Sets the path where the gradle distributions needed by the wrapper are unzipped. The path is relative to the
- * distribution base directory
- *
- * @see #setDistributionPath(String)
- */
- public void setDistributionPath(String distributionPath) {
- this.distributionPath = distributionPath;
- }
-
- /**
- * Returns the gradle version for the wrapper.
- *
- * @see #setGradleVersion(String)
- */
- public String getGradleVersion() {
- return gradleVersion.getVersion();
- }
-
- /**
- * The version of the gradle distribution required by the wrapper. This is usually the same version of Gradle you
- * use for building your project.
- */
- public void setGradleVersion(String gradleVersion) {
- this.gradleVersion = GradleVersion.version(gradleVersion);
- }
-
- /**
- * The URL to download the gradle distribution from.
- *
- * <p>If not set, the download URL is the default for the specified {@link #getGradleVersion()}.
- *
- * <p>If {@link #getGradleVersion()} is not set, will return null.
- *
- * <p>The wrapper downloads a certain distribution only once and caches it. If your distribution base is the
- * project, you might submit the distribution to your version control system. That way no download is necessary at
- * all. This might be in particular interesting, if you provide a custom gradle snapshot to the wrapper, because you
- * don't need to provide a download server then.
- */
- @Input
- public String getDistributionUrl() {
- if (distributionUrl != null) {
- return distributionUrl;
- } else if (gradleVersion != null) {
- return locator.getDistributionFor(gradleVersion).toString();
- } else {
- return null;
- }
- }
-
- public void setDistributionUrl(String url) {
- this.distributionUrl = url;
- }
-
- /**
- * The distribution base specifies whether the unpacked wrapper distribution should be stored in the project or in
- * the gradle user home dir.
- */
- public PathBase getDistributionBase() {
- return distributionBase;
- }
-
- /**
- * The distribution base specifies whether the unpacked wrapper distribution should be stored in the project or in
- * the gradle user home dir.
- */
- public void setDistributionBase(PathBase distributionBase) {
- this.distributionBase = distributionBase;
- }
-
- /**
- * Returns the path where the gradle distributions archive should be saved (i.e. the parent dir). The path is
- * relative to the archive base directory.
- */
- public String getArchivePath() {
- return archivePath;
- }
-
- /**
- * Set's the path where the gradle distributions archive should be saved (i.e. the parent dir). The path is relative
- * to the parent dir specified with {@link #getArchiveBase()}.
- */
- public void setArchivePath(String archivePath) {
- this.archivePath = archivePath;
- }
-
- /**
- * The archive base specifies whether the unpacked wrapper distribution should be stored in the project or in the
- * gradle user home dir.
- */
- public PathBase getArchiveBase() {
- return archiveBase;
- }
-
- /**
- * The archive base specifies whether the unpacked wrapper distribution should be stored in the project or in the
- * gradle user home dir.
- */
- public void setArchiveBase(PathBase archiveBase) {
- this.archiveBase = archiveBase;
- }
-
-}
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/CoreJavadocOptions.java b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/CoreJavadocOptions.java
index fa51c72..cf49de0 100755
--- a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/CoreJavadocOptions.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/CoreJavadocOptions.java
@@ -29,8 +29,6 @@ import java.util.List;
/**
* Provides the core Javadoc Options. That is, provides the options which are not doclet specific.
- *
- * @author Tom Eyckmans
*/
public abstract class CoreJavadocOptions implements MinimalJavadocOptions {
private final JavadocOptionFile optionFile;
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/JavadocMemberLevel.java b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/JavadocMemberLevel.java
index 337f955..ab06d8d 100755
--- a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/JavadocMemberLevel.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/JavadocMemberLevel.java
@@ -18,8 +18,6 @@ package org.gradle.external.javadoc;
/**
* This enum maps to the -public, -protected, -package and -private options of the javadoc executable.
- *
- * @author Tom Eyckmans
*/
public enum JavadocMemberLevel {
/**
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/JavadocOfflineLink.java b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/JavadocOfflineLink.java
index be86bb1..e51618f 100755
--- a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/JavadocOfflineLink.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/JavadocOfflineLink.java
@@ -20,8 +20,6 @@ package org.gradle.external.javadoc;
/**
* This class is used to hold the information that can be provided to the javadoc executable via the -linkoffline
* option.
- *
- * @author Tom Eyckmans
*/
public class JavadocOfflineLink {
private final String extDocUrl;
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/JavadocOptionFileOption.java b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/JavadocOptionFileOption.java
index e824f6b..146ac56 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/JavadocOptionFileOption.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/JavadocOptionFileOption.java
@@ -19,7 +19,6 @@ package org.gradle.external.javadoc;
/**
* Represents a Javadoc command-line option.
*
- * @author Tom Eyckmans
* @param <T> The type which this option represents.
*/
public interface JavadocOptionFileOption<T> extends OptionLessJavadocOptionFileOption<T> {
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/JavadocOutputLevel.java b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/JavadocOutputLevel.java
index d7dcf43..742286c 100755
--- a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/JavadocOutputLevel.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/JavadocOutputLevel.java
@@ -18,8 +18,6 @@ package org.gradle.external.javadoc;
/**
* This enum maps to the -verbose and -quiet options of the javadoc executable.
- *
- * @author Tom Eyckmans
*/
public enum JavadocOutputLevel {
/**
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/MinimalJavadocOptions.java b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/MinimalJavadocOptions.java
index cec29b6..4a649f5 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/MinimalJavadocOptions.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/MinimalJavadocOptions.java
@@ -27,8 +27,6 @@ import java.util.List;
/**
* Provides the core Javadoc options.
- *
- * @author Tom Eyckmans
*/
public interface MinimalJavadocOptions {
@Input @Optional
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/OptionLessJavadocOptionFileOption.java b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/OptionLessJavadocOptionFileOption.java
index aced83b..e95b98a 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/OptionLessJavadocOptionFileOption.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/OptionLessJavadocOptionFileOption.java
@@ -23,7 +23,6 @@ import java.io.IOException;
/**
* Represents a Javadoc option.
*
- * @author Tom Eyckmans
* @param <T> The type which this option represents.
*/
public interface OptionLessJavadocOptionFileOption<T> {
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/StandardJavadocDocletOptions.java b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/StandardJavadocDocletOptions.java
index 26de0fa..5a78f55 100755
--- a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/StandardJavadocDocletOptions.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/StandardJavadocDocletOptions.java
@@ -16,17 +16,17 @@
package org.gradle.external.javadoc;
-import org.gradle.external.javadoc.internal.JavadocOptionFile;
import org.gradle.external.javadoc.internal.GroupsJavadocOptionFileOption;
+import org.gradle.external.javadoc.internal.JavadocOptionFile;
import org.gradle.external.javadoc.internal.LinksOfflineJavadocOptionFileOption;
import java.io.File;
-import java.util.*;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
/**
* Provides the options for the standard Javadoc doclet.
- *
- * @author Tom Eyckmans
*/
public class StandardJavadocDocletOptions extends CoreJavadocOptions implements MinimalJavadocOptions {
@@ -257,7 +257,7 @@ public class StandardJavadocDocletOptions extends CoreJavadocOptions implements
/**
* -doctitle title
* Specifies the title to be placed near the top of the overview summary file. The title will be placed as a centered,
- * level-one heading directly beneath the upper navigation bar. The title may contain html tags and white space,
+ * level-one heading directly beneath the upper navigation bar. The title may contain HTML tags and white space,
* though if it does, it must be enclosed in quotes. Any internal quotation marks within title may have to be escaped.
* C:> javadoc -doctitle "Java<sup><font size=\"-2\">TM</font></sup>" com.mypackage
*/
@@ -279,7 +279,7 @@ public class StandardJavadocDocletOptions extends CoreJavadocOptions implements
/**
* -footer footer
* Specifies the footer text to be placed at the bottom of each output file.
- * The footer will be placed to the right of the lower navigation bar. footer may contain html tags and white space,
+ * The footer will be placed to the right of the lower navigation bar. footer may contain HTML tags and white space,
* though if it does, it must be enclosed in quotes. Any internal quotation marks within footer may have to be escaped.
*/
private final JavadocOptionFileOption<String> footer;
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/AbstractJavadocOptionFileOption.java b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/AbstractJavadocOptionFileOption.java
index d269bd9..24f9185 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/AbstractJavadocOptionFileOption.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/AbstractJavadocOptionFileOption.java
@@ -21,7 +21,6 @@ import org.gradle.external.javadoc.JavadocOptionFileOption;
/**
* A base class for {@link org.gradle.external.javadoc.JavadocOptionFileOption} implementations.
*
- * @author Tom Eyckmans
* @param <T> The type which this option represents.
*/
public abstract class AbstractJavadocOptionFileOption<T> implements JavadocOptionFileOption<T> {
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/AbstractListJavadocOptionFileOption.java b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/AbstractListJavadocOptionFileOption.java
index 5ff8a12..c56c88c 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/AbstractListJavadocOptionFileOption.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/AbstractListJavadocOptionFileOption.java
@@ -16,14 +16,13 @@
package org.gradle.external.javadoc.internal;
-import java.util.List;
import java.io.IOException;
+import java.util.List;
/**
* A base class for {@link org.gradle.external.javadoc.JavadocOptionFileOption} implementations whose value is a {@code List}.
*
* @param <T> The type which this option represents.
- * @author Tom Eyckmans
*/
public abstract class AbstractListJavadocOptionFileOption<T extends List> extends AbstractJavadocOptionFileOption<T> {
protected String joinBy;
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/BooleanJavadocOptionFileOption.java b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/BooleanJavadocOptionFileOption.java
index 55ddb97..751e665 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/BooleanJavadocOptionFileOption.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/BooleanJavadocOptionFileOption.java
@@ -20,8 +20,6 @@ import java.io.IOException;
/**
* A {@link org.gradle.external.javadoc.JavadocOptionFileOption} whose value is a boolean.
- *
- * @author Tom Eyckmans
*/
public class BooleanJavadocOptionFileOption extends AbstractJavadocOptionFileOption<Boolean> {
protected BooleanJavadocOptionFileOption(String option) {
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/EnumJavadocOptionFileOption.java b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/EnumJavadocOptionFileOption.java
index 3284812..2c5ae4e 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/EnumJavadocOptionFileOption.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/EnumJavadocOptionFileOption.java
@@ -36,7 +36,6 @@ import java.io.IOException;
/**
* @param <T> The type which this option represents.
- * @author Tom Eyckmans
*/
public class EnumJavadocOptionFileOption<T> extends AbstractJavadocOptionFileOption<T> {
public EnumJavadocOptionFileOption(String option) {
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/FileJavadocOptionFileOption.java b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/FileJavadocOptionFileOption.java
index 22c28d7..40ca88b 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/FileJavadocOptionFileOption.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/FileJavadocOptionFileOption.java
@@ -21,8 +21,6 @@ import java.io.IOException;
/**
* A {@link org.gradle.external.javadoc.JavadocOptionFileOption} whose value is a file.
- *
- * @author Tom Eyckmans
*/
public class FileJavadocOptionFileOption extends AbstractJavadocOptionFileOption<File> {
protected FileJavadocOptionFileOption(String option) {
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/GroupsJavadocOptionFileOption.java b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/GroupsJavadocOptionFileOption.java
index 27f8d9c..a578647 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/GroupsJavadocOptionFileOption.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/GroupsJavadocOptionFileOption.java
@@ -26,8 +26,6 @@ import java.util.Map;
/**
* A {@link org.gradle.external.javadoc.JavadocOptionFileOption} which represents the -groups command line
* option.
- *
- * @author Tom Eyckmans
*/
public class GroupsJavadocOptionFileOption extends AbstractJavadocOptionFileOption<Map<String, List<String>>> {
public GroupsJavadocOptionFileOption(String option) {
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/JavadocExecHandleBuilder.java b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/JavadocExecHandleBuilder.java
index cdba757..e991bb4 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/JavadocExecHandleBuilder.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/JavadocExecHandleBuilder.java
@@ -26,9 +26,6 @@ import org.gradle.util.GUtil;
import java.io.File;
import java.io.IOException;
-/**
- * @author Tom Eyckmans
- */
public class JavadocExecHandleBuilder {
private File execDirectory;
private MinimalJavadocOptions options;
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/JavadocOptionFile.java b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/JavadocOptionFile.java
index 1af9711..482f96c 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/JavadocOptionFile.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/JavadocOptionFile.java
@@ -23,9 +23,6 @@ import java.io.File;
import java.io.IOException;
import java.util.*;
-/**
- * @author Tom Eyckmans
- */
public class JavadocOptionFile {
private final Map<String, JavadocOptionFileOption> options;
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/JavadocOptionFileWriter.java b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/JavadocOptionFileWriter.java
index 02d4761..b4d136f 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/JavadocOptionFileWriter.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/JavadocOptionFileWriter.java
@@ -26,9 +26,6 @@ import java.io.IOException;
import java.util.Map;
import java.util.TreeMap;
-/**
- * @author Tom Eyckmans
- */
public class JavadocOptionFileWriter {
private final JavadocOptionFile optionFile;
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/JavadocOptionFileWriterContext.java b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/JavadocOptionFileWriterContext.java
index 925fbe1..0888bf7 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/JavadocOptionFileWriterContext.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/JavadocOptionFileWriterContext.java
@@ -17,14 +17,11 @@
package org.gradle.external.javadoc.internal;
import java.io.BufferedWriter;
-import java.io.IOException;
import java.io.File;
+import java.io.IOException;
import java.util.Collection;
import java.util.Iterator;
-/**
- * @author Tom Eyckmans
- */
public class JavadocOptionFileWriterContext {
private final BufferedWriter writer;
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/LinksOfflineJavadocOptionFileOption.java b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/LinksOfflineJavadocOptionFileOption.java
index 2c7f016..1eadf0e 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/LinksOfflineJavadocOptionFileOption.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/LinksOfflineJavadocOptionFileOption.java
@@ -18,13 +18,10 @@ package org.gradle.external.javadoc.internal;
import org.gradle.external.javadoc.JavadocOfflineLink;
-import java.util.List;
-import java.util.ArrayList;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
-/**
- * @author Tom Eyckmans
- */
public class LinksOfflineJavadocOptionFileOption extends AbstractJavadocOptionFileOption<List<JavadocOfflineLink>> {
public LinksOfflineJavadocOptionFileOption(String option) {
super(option, new ArrayList<JavadocOfflineLink>());
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/MultilineStringsJavadocOptionFileOption.java b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/MultilineStringsJavadocOptionFileOption.java
index 1ff9693..1309822 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/MultilineStringsJavadocOptionFileOption.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/MultilineStringsJavadocOptionFileOption.java
@@ -16,13 +16,10 @@
package org.gradle.external.javadoc.internal;
-import java.util.List;
-import java.util.ArrayList;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
-/**
- * @author Melanie Pfautz
- */
public class MultilineStringsJavadocOptionFileOption extends AbstractListJavadocOptionFileOption<List<String>> {
// We should never attempt to join strings so if you see this, there's a problem
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/OptionLessStringsJavadocOptionFileOption.java b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/OptionLessStringsJavadocOptionFileOption.java
index 9f1cc5b..47b9e64 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/OptionLessStringsJavadocOptionFileOption.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/OptionLessStringsJavadocOptionFileOption.java
@@ -18,13 +18,10 @@ package org.gradle.external.javadoc.internal;
import org.gradle.external.javadoc.OptionLessJavadocOptionFileOption;
-import java.util.List;
-import java.util.ArrayList;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
-/**
- * @author Tom Eyckmans
- */
public class OptionLessStringsJavadocOptionFileOption implements OptionLessJavadocOptionFileOption<List<String>> {
private List<String> value;
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/PathJavadocOptionFileOption.java b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/PathJavadocOptionFileOption.java
index 599248c..d34d799 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/PathJavadocOptionFileOption.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/PathJavadocOptionFileOption.java
@@ -18,12 +18,9 @@ package org.gradle.external.javadoc.internal;
import java.io.File;
import java.io.IOException;
-import java.util.List;
import java.util.ArrayList;
+import java.util.List;
-/**
- * @author Tom Eyckmans
- */
public class PathJavadocOptionFileOption extends AbstractListJavadocOptionFileOption<List<File>> {
public PathJavadocOptionFileOption(String option, String joinBy) {
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/StringJavadocOptionFileOption.java b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/StringJavadocOptionFileOption.java
index 4b4cecc..e96c9db 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/StringJavadocOptionFileOption.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/StringJavadocOptionFileOption.java
@@ -18,9 +18,6 @@ package org.gradle.external.javadoc.internal;
import java.io.IOException;
-/**
- * @author Tom Eyckmans
- */
public class StringJavadocOptionFileOption extends AbstractJavadocOptionFileOption<String> {
public StringJavadocOptionFileOption(String option) {
super(option);
diff --git a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/StringsJavadocOptionFileOption.java b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/StringsJavadocOptionFileOption.java
index bb60153..daa28ed 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/StringsJavadocOptionFileOption.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/external/javadoc/internal/StringsJavadocOptionFileOption.java
@@ -16,13 +16,10 @@
package org.gradle.external.javadoc.internal;
-import java.util.List;
-import java.util.ArrayList;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
-/**
- * @author Tom Eyckmans
- */
public class StringsJavadocOptionFileOption extends AbstractListJavadocOptionFileOption<List<String>> {
protected StringsJavadocOptionFileOption(String option, String joinBy) {
super(option, new ArrayList<String>(), joinBy);
diff --git a/subprojects/plugins/src/main/resources/META-INF/gradle-plugins/jvm-lang.properties b/subprojects/plugins/src/main/resources/META-INF/gradle-plugins/jvm-lang.properties
index ca08f4c..6a30765 100644
--- a/subprojects/plugins/src/main/resources/META-INF/gradle-plugins/jvm-lang.properties
+++ b/subprojects/plugins/src/main/resources/META-INF/gradle-plugins/jvm-lang.properties
@@ -1 +1 @@
-implementation-class=org.gradle.api.plugins.JvmLanguagePlugin
+implementation-class=org.gradle.language.jvm.plugins.JvmLanguagePlugin
diff --git a/subprojects/plugins/src/main/resources/META-INF/gradle-plugins/lang-base.properties b/subprojects/plugins/src/main/resources/META-INF/gradle-plugins/lang-base.properties
index 7507f57..c8d282e 100644
--- a/subprojects/plugins/src/main/resources/META-INF/gradle-plugins/lang-base.properties
+++ b/subprojects/plugins/src/main/resources/META-INF/gradle-plugins/lang-base.properties
@@ -1 +1 @@
-implementation-class=org.gradle.api.plugins.LanguageBasePlugin
+implementation-class=org.gradle.language.base.plugins.LanguageBasePlugin
diff --git a/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt b/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
old mode 100644
new mode 100755
index 8732f7f..bec72be
--- a/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+++ b/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
@@ -7,7 +7,7 @@
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and ${optsEnvironmentVar} to pass JVM options to this script.
-DEFAULT_JVM_OPTS=""
+DEFAULT_JVM_OPTS=${defaultJvmOpts}
APP_NAME="${applicationName}"
APP_BASE_NAME=`basename "\$0"`
diff --git a/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/windowsStartScript.txt b/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/windowsStartScript.txt
index 7e034c0..03f2bac 100644
--- a/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/windowsStartScript.txt
+++ b/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/windowsStartScript.txt
@@ -9,7 +9,7 @@
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and ${optsEnvironmentVar} to pass JVM options to this script.
-set DEFAULT_JVM_OPTS=
+set DEFAULT_JVM_OPTS=${defaultJvmOpts}
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.\
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/distribution/plugins/DistributionPluginTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/distribution/plugins/DistributionPluginTest.groovy
index aed4ace..33c2149 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/distribution/plugins/DistributionPluginTest.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/distribution/plugins/DistributionPluginTest.groovy
@@ -21,11 +21,11 @@ import org.gradle.api.distribution.DistributionContainer
import org.gradle.api.tasks.Sync
import org.gradle.api.tasks.bundling.Zip
import org.gradle.api.tasks.bundling.Tar
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import spock.lang.Specification
class DistributionPluginTest extends Specification {
- private final Project project = HelperUtil.builder().withName("test-project").build()
+ private final Project project = TestUtil.builder().withName("test-project").build()
def "adds convention object and a main distribution"() {
when:
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/plugins/StartScriptGeneratorTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/plugins/StartScriptGeneratorTest.groovy
index 708f46f..e327936 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/plugins/StartScriptGeneratorTest.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/plugins/StartScriptGeneratorTest.groovy
@@ -70,4 +70,103 @@ class StartScriptGeneratorTest extends Specification {
then:
windowsScriptContent.split(TextUtil.windowsLineSeparator).length == 90
}
+
+ def "defaultJvmOpts is expanded properly in windows script"() {
+ given:
+ generator.defaultJvmOpts = ['-Dfoo=bar', '-Xint']
+ generator.scriptRelPath = "bin"
+ when:
+ String windowsScriptContent = generator.generateWindowsScriptContent()
+ then:
+ windowsScriptContent.contains('set DEFAULT_JVM_OPTS="-Dfoo=bar" "-Xint"')
+ }
+
+ def "defaultJvmOpts is expanded properly in windows script -- spaces"() {
+ given:
+ generator.defaultJvmOpts = ['-Dfoo=bar baz', '-Xint']
+ generator.scriptRelPath = "bin"
+ when:
+ String windowsScriptContent = generator.generateWindowsScriptContent()
+ then:
+ windowsScriptContent.contains(/set DEFAULT_JVM_OPTS="-Dfoo=bar baz" "-Xint"/)
+ }
+
+ def "defaultJvmOpts is expanded properly in windows script -- double quotes"() {
+ given:
+ generator.defaultJvmOpts = ['-Dfoo=b"ar baz', '-Xi""nt', '-Xpatho\\"logical']
+ generator.scriptRelPath = "bin"
+ when:
+ String windowsScriptContent = generator.generateWindowsScriptContent()
+ then:
+ windowsScriptContent.contains(/set DEFAULT_JVM_OPTS="-Dfoo=b\"ar baz" "-Xi\"\"nt" "-Xpatho\\\"logical"/)
+ }
+
+ def "defaultJvmOpts is expanded properly in windows script -- backslashes and shell metacharacters"() {
+ given:
+ generator.defaultJvmOpts = ['-Dfoo=b\\ar baz', '-Xint%PATH%']
+ generator.scriptRelPath = "bin"
+ when:
+ String windowsScriptContent = generator.generateWindowsScriptContent()
+ then:
+ windowsScriptContent.contains(/set DEFAULT_JVM_OPTS="-Dfoo=b\ar baz" "-Xint%%PATH%%"/)
+ }
+
+ def "defaultJvmOpts is expanded properly in unix script"() {
+ given:
+ generator.defaultJvmOpts = ['-Dfoo=bar', '-Xint']
+ generator.scriptRelPath = "bin"
+ when:
+ String unixScriptContent = generator.generateUnixScriptContent()
+ then:
+ unixScriptContent.contains('DEFAULT_JVM_OPTS=\'"-Dfoo=bar" "-Xint"\'')
+ }
+
+ def "defaultJvmOpts is expanded properly in unix script -- spaces"() {
+ given:
+ generator.defaultJvmOpts = ['-Dfoo=bar baz', '-Xint']
+ generator.scriptRelPath = "bin"
+ when:
+ String unixScriptContent = generator.generateUnixScriptContent()
+ then:
+ unixScriptContent.contains(/DEFAULT_JVM_OPTS='"-Dfoo=bar baz" "-Xint"'/)
+ }
+
+ def "defaultJvmOpts is expanded properly in unix script -- double quotes"() {
+ given:
+ generator.defaultJvmOpts = ['-Dfoo=b"ar baz', '-Xi""nt']
+ generator.scriptRelPath = "bin"
+ when:
+ String unixScriptContent = generator.generateUnixScriptContent()
+ then:
+ unixScriptContent.contains(/DEFAULT_JVM_OPTS='"-Dfoo=b\"ar baz" "-Xi\"\"nt"'/)
+ }
+
+ def "defaultJvmOpts is expanded properly in unix script -- single quotes"() {
+ given:
+ generator.defaultJvmOpts = ['-Dfoo=b\'ar baz', '-Xi\'\'n`t']
+ generator.scriptRelPath = "bin"
+ when:
+ String unixScriptContent = generator.generateUnixScriptContent()
+ then:
+ unixScriptContent.contains(/DEFAULT_JVM_OPTS='"-Dfoo=b'"'"'ar baz" "-Xi'"'"''"'"'n'"`"'t"'/)
+ }
+
+ def "defaultJvmOpts is expanded properly in unix script -- backslashes and shell metacharacters"() {
+ given:
+ generator.defaultJvmOpts = ['-Dfoo=b\\ar baz', '-Xint$PATH']
+ generator.scriptRelPath = "bin"
+ when:
+ String unixScriptContent = generator.generateUnixScriptContent()
+ then:
+ unixScriptContent.contains(/DEFAULT_JVM_OPTS='"-Dfoo=b\\ar baz" "-Xint/ + '\\$PATH' + /"'/)
+ }
+
+ def "defaultJvmOpts is expanded properly in unix script -- empty list"() {
+ given:
+ generator.scriptRelPath = "bin"
+ when:
+ String unixScriptContent = generator.generateUnixScriptContent()
+ then:
+ unixScriptContent.contains(/DEFAULT_JVM_OPTS=""/)
+ }
}
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/DefaultSourceSetTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/DefaultSourceSetTest.groovy
index b00bc1e..72f69d2 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/DefaultSourceSetTest.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/DefaultSourceSetTest.groovy
@@ -37,7 +37,7 @@ class DefaultSourceSetTest {
@Test
public void hasUsefulDisplayName() {
SourceSet sourceSet = sourceSet('int-test')
- assertThat(sourceSet.toString(), equalTo('source set int test'));
+ assertThat(sourceSet.toString(), equalTo("source set 'int test'"));
}
@Test public void defaultValues() {
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/compile/DefaultJavaCompilerFactoryTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/compile/DefaultJavaCompilerFactoryTest.groovy
index dcc670e..f551205 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/compile/DefaultJavaCompilerFactoryTest.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/compile/DefaultJavaCompilerFactoryTest.groovy
@@ -18,7 +18,6 @@ package org.gradle.api.internal.tasks.compile
import org.gradle.api.internal.project.ProjectInternal
import org.gradle.api.internal.tasks.compile.daemon.DaemonJavaCompiler
import org.gradle.api.tasks.compile.CompileOptions
-import org.gradle.api.internal.file.TemporaryFileProvider
import org.gradle.internal.Factory
import spock.lang.Specification
@@ -26,7 +25,7 @@ import spock.lang.Specification
class DefaultJavaCompilerFactoryTest extends Specification {
def inProcessCompiler = Mock(Compiler)
def inProcessCompilerFactory = Mock(JavaCompilerFactory)
- def factory = new DefaultJavaCompilerFactory(Mock(ProjectInternal), Mock(TemporaryFileProvider), Mock(Factory), inProcessCompilerFactory)
+ def factory = new DefaultJavaCompilerFactory(Mock(ProjectInternal), Mock(Factory), inProcessCompilerFactory)
def options = new CompileOptions()
def setup() {
@@ -67,7 +66,6 @@ class DefaultJavaCompilerFactoryTest extends Specification {
options.forkOptions.executable = "/path/to/javac"
expect:
- expect:
def compiler = factory.create(options)
compiler instanceof NormalizingJavaCompiler
compiler.delegate instanceof CommandLineJavaCompiler
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/compile/GroovyCompileTransformingClassLoaderTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/compile/GroovyCompileTransformingClassLoaderTest.groovy
new file mode 100644
index 0000000..d51aa95
--- /dev/null
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/compile/GroovyCompileTransformingClassLoaderTest.groovy
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.tasks.compile
+
+import spock.lang.Specification
+import org.codehaus.groovy.transform.GroovyASTTransformationClass
+import org.gradle.internal.classloader.ClasspathUtil
+import org.gradle.internal.classpath.DefaultClassPath
+
+class GroovyCompileTransformingClassLoaderTest extends Specification {
+ GroovyCompileTransformingClassLoader loader
+ Class<?> classAnnotation
+
+ def setup() {
+ def classPath = new DefaultClassPath(ClasspathUtil.getClasspathForClass(getClass()), ClasspathUtil.getClasspathForClass(GroovyASTTransformationClass))
+ loader = new GroovyCompileTransformingClassLoader(classPath)
+ classAnnotation = loader.loadClass(GroovyASTTransformationClass.name)
+ }
+
+ def "loads class annotated with transformer name"() {
+ expect:
+ def cl = loader.loadClass(WithNameSpecified.name)
+ def annotation = cl.getAnnotation(classAnnotation)
+ annotation.value() == ['some-type'] as String[]
+ annotation.classes() == [] as Class[]
+ }
+
+ def "loads class annotated with transformer names"() {
+ expect:
+ def cl = loader.loadClass(WithNamesSpecified.name)
+ def annotation = cl.getAnnotation(classAnnotation)
+ annotation.value() == ['some-type', 'some-other-type'] as String[]
+ annotation.classes() == [] as Class[]
+ }
+
+ def "loads class annotated with transformer class"() {
+ expect:
+ def cl = loader.loadClass(WithClassSpecified.name)
+ def annotation = cl.getAnnotation(classAnnotation)
+ annotation.value() == [Transformer.name] as String[]
+ annotation.classes() == [] as Class[]
+ }
+
+ def "loads class annotated with transformer classes"() {
+ expect:
+ def cl = loader.loadClass(WithClassesSpecified.name)
+ def annotation = cl.getAnnotation(classAnnotation)
+ annotation.value() == [Transformer.name, Runnable.name] as String[]
+ annotation.classes() == [] as Class[]
+ }
+
+ def "loads class annotated with transformer names and classes"() {
+ expect:
+ def cl = loader.loadClass(WithBothSpecified.name)
+ def annotation = cl.getAnnotation(classAnnotation)
+ annotation.value() as Set == ["some-type", Transformer.name, Runnable.name] as Set
+ annotation.classes() == [] as Class[]
+ }
+
+ static class Transformer {
+ }
+}
+
+ at GroovyASTTransformationClass("some-type")
+ at interface WithNameSpecified {
+}
+
+ at GroovyASTTransformationClass(["some-type", "some-other-type"])
+ at interface WithNamesSpecified {
+}
+
+ at GroovyASTTransformationClass(classes = [GroovyCompileTransformingClassLoaderTest.Transformer])
+ at interface WithClassSpecified {
+}
+
+ at GroovyASTTransformationClass(classes = [GroovyCompileTransformingClassLoaderTest.Transformer, Runnable])
+ at interface WithClassesSpecified {
+}
+
+ at GroovyASTTransformationClass(value = "some-type", classes = [GroovyCompileTransformingClassLoaderTest.Transformer, Runnable])
+ at interface WithBothSpecified {
+}
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/compile/IncrementalJavaCompilerTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/compile/IncrementalJavaCompilerTest.groovy
index d39407a..9590fa1 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/compile/IncrementalJavaCompilerTest.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/compile/IncrementalJavaCompilerTest.groovy
@@ -15,6 +15,7 @@
*/
package org.gradle.api.internal.tasks.compile
+import org.gradle.language.jvm.internal.StaleClassCleaner
import spock.lang.Specification
import org.gradle.api.tasks.WorkResult
import org.gradle.api.file.FileCollection
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/compile/SimpleStaleClassCleanerTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/compile/SimpleStaleClassCleanerTest.groovy
index 9c7feb2..487d188 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/compile/SimpleStaleClassCleanerTest.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/compile/SimpleStaleClassCleanerTest.groovy
@@ -17,6 +17,7 @@ package org.gradle.api.internal.tasks.compile
import org.gradle.api.file.FileCollection
import org.gradle.api.internal.TaskOutputsInternal
+import org.gradle.language.jvm.internal.SimpleStaleClassCleaner
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
import org.junit.Rule
import spock.lang.Specification
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/compile/TransformingClassLoaderTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/compile/TransformingClassLoaderTest.groovy
deleted file mode 100644
index 6213475..0000000
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/compile/TransformingClassLoaderTest.groovy
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.tasks.compile
-
-import spock.lang.Specification
-import org.codehaus.groovy.transform.GroovyASTTransformationClass
-import org.gradle.util.ClasspathUtil
-import org.gradle.internal.classpath.DefaultClassPath
-
-class TransformingClassLoaderTest extends Specification {
- TransformingClassLoader loader
- Class<?> classAnnotation
-
- def setup() {
- def classPath = new DefaultClassPath(ClasspathUtil.getClasspathForClass(getClass()), ClasspathUtil.getClasspathForClass(GroovyASTTransformationClass))
- loader = new TransformingClassLoader(classPath)
- classAnnotation = loader.loadClass(GroovyASTTransformationClass.name)
- }
-
- def "loads class annotated with transformer name"() {
- expect:
- def cl = loader.loadClass(WithNameSpecified.name)
- def annotation = cl.getAnnotation(classAnnotation)
- annotation.value() == ['some-type'] as String[]
- annotation.classes() == [] as Class[]
- }
-
- def "loads class annotated with transformer names"() {
- expect:
- def cl = loader.loadClass(WithNamesSpecified.name)
- def annotation = cl.getAnnotation(classAnnotation)
- annotation.value() == ['some-type', 'some-other-type'] as String[]
- annotation.classes() == [] as Class[]
- }
-
- def "loads class annotated with transformer class"() {
- expect:
- def cl = loader.loadClass(WithClassSpecified.name)
- def annotation = cl.getAnnotation(classAnnotation)
- annotation.value() == [Transformer.name] as String[]
- annotation.classes() == [] as Class[]
- }
-
- def "loads class annotated with transformer classes"() {
- expect:
- def cl = loader.loadClass(WithClassesSpecified.name)
- def annotation = cl.getAnnotation(classAnnotation)
- annotation.value() == [Transformer.name, Runnable.name] as String[]
- annotation.classes() == [] as Class[]
- }
-
- def "loads class annotated with transformer names and classes"() {
- expect:
- def cl = loader.loadClass(WithBothSpecified.name)
- def annotation = cl.getAnnotation(classAnnotation)
- annotation.value() as Set == ["some-type", Transformer.name, Runnable.name] as Set
- annotation.classes() == [] as Class[]
- }
-
- static class Transformer {
- }
-}
-
- at GroovyASTTransformationClass("some-type")
- at interface WithNameSpecified {
-}
-
- at GroovyASTTransformationClass(["some-type", "some-other-type"])
- at interface WithNamesSpecified {
-}
-
- at GroovyASTTransformationClass(classes = [TransformingClassLoaderTest.Transformer])
- at interface WithClassSpecified {
-}
-
- at GroovyASTTransformationClass(classes = [TransformingClassLoaderTest.Transformer, Runnable])
- at interface WithClassesSpecified {
-}
-
- at GroovyASTTransformationClass(value = "some-type", classes = [TransformingClassLoaderTest.Transformer, Runnable])
- at interface WithBothSpecified {
-}
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/AbstractTestFrameworkTest.java b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/AbstractTestFrameworkTest.java
index acb6d0b..a298d8e 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/AbstractTestFrameworkTest.java
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/AbstractTestFrameworkTest.java
@@ -30,9 +30,6 @@ import java.io.File;
import java.util.Arrays;
import java.util.List;
-/**
- * @author Tom Eyckmans
- */
@RunWith(JMock.class)
public abstract class AbstractTestFrameworkTest {
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/JUnitTestClassProcessorTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/JUnitTestClassProcessorTest.groovy
index d4c638d..d734252 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/JUnitTestClassProcessorTest.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/JUnitTestClassProcessorTest.groovy
@@ -20,6 +20,7 @@ import junit.framework.TestCase
import junit.framework.TestSuite
import org.gradle.api.internal.tasks.testing.*
import org.gradle.api.tasks.testing.TestResult
+import org.gradle.api.tasks.testing.junit.JUnitOptions
import org.gradle.internal.id.LongIdGenerator
import org.gradle.logging.StandardOutputRedirector
import org.gradle.messaging.actor.ActorFactory
@@ -45,7 +46,8 @@ class JUnitTestClassProcessorTest {
public final TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider();
private final TestResultProcessor resultProcessor = context.mock(TestResultProcessor.class);
private final ActorFactory actorFactory = new TestActorFactory()
- private final JUnitTestClassProcessor processor = new JUnitTestClassProcessor(tmpDir.testDirectory, new LongIdGenerator(), actorFactory, {} as StandardOutputRedirector);
+ private final JUnitSpec spec = new JUnitSpec(new JUnitOptions());
+ private final JUnitTestClassProcessor processor = new JUnitTestClassProcessor(spec, new LongIdGenerator(), actorFactory, {} as StandardOutputRedirector);
@Test
public void executesAJUnit4TestClass() {
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/JUnitTestFrameworkTest.java b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/JUnitTestFrameworkTest.java
index b4b4a82..8654bec 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/JUnitTestFrameworkTest.java
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/JUnitTestFrameworkTest.java
@@ -28,14 +28,12 @@ import org.jmock.Expectations;
import org.junit.Before;
import java.io.File;
+import java.util.Collections;
import static junit.framework.Assert.assertNotNull;
import static org.hamcrest.Matchers.instanceOf;
import static org.junit.Assert.assertThat;
-/**
- * @author Tom Eyckmans
- */
public class JUnitTestFrameworkTest extends AbstractTestFrameworkTest {
private JUnitTestFramework jUnitTestFramework;
private JUnitOptions jUnitOptionsMock;
@@ -63,6 +61,8 @@ public class JUnitTestFrameworkTest extends AbstractTestFrameworkTest {
will(returnValue(context.mock(AntBuilder.class)));
allowing(testMock).getTemporaryDirFactory();
will(returnValue(temporaryDirFactory));
+ allowing(classpathMock).iterator();
+ will(returnIterator(Collections.EMPTY_LIST));
}});
}
@@ -81,8 +81,10 @@ public class JUnitTestFrameworkTest extends AbstractTestFrameworkTest {
final ActorFactory actorFactory = context.mock(ActorFactory.class);
context.checking(new Expectations() {{
- one(testMock).getTestResultsDir();
- will(returnValue(testResultsDir));
+ allowing(jUnitOptionsMock).getIncludeCategories();
+ will(returnValue(Collections.emptySet()));
+ allowing(jUnitOptionsMock).getExcludeCategories();
+ will(returnValue(Collections.emptySet()));
one(serviceRegistry).get(IdGenerator.class);
will(returnValue(idGenerator));
one(serviceRegistry).get(ActorFactory.class);
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/report/AllTestResultsTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/report/AllTestResultsTest.groovy
index fc3b8ce..9ae6866 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/report/AllTestResultsTest.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/report/AllTestResultsTest.groovy
@@ -22,7 +22,7 @@ class AllTestResultsTest extends Specification {
def addsTest() {
when:
- def test = results.addTest('org.gradle.Test', 'test', 90)
+ def test = results.addTest(1, 'org.gradle.Test', 'test', 90)
then:
test.name == 'test'
@@ -33,7 +33,7 @@ class AllTestResultsTest extends Specification {
def addsTestInDefaultPackage() {
when:
- def test = results.addTest('Test', 'test', 90)
+ def test = results.addTest(1, 'Test', 'test', 90)
then:
test.name == 'test'
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/report/ClassTestResultsTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/report/ClassTestResultsTest.groovy
index e546714..519fd94 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/report/ClassTestResultsTest.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/report/ClassTestResultsTest.groovy
@@ -20,7 +20,7 @@ import spock.lang.Specification
class ClassTestResultsTest extends Specification {
def determinesSimpleName() {
expect:
- new ClassTestResults('org.gradle.Test', null).simpleName == 'Test'
- new ClassTestResults('Test', null).simpleName == 'Test'
+ new ClassTestResults(1, 'org.gradle.Test', null).simpleName == 'Test'
+ new ClassTestResults(2, 'Test', null).simpleName == 'Test'
}
}
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/report/CompositeTestResultsTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/report/CompositeTestResultsTest.groovy
index 6dd21b8..500013c 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/report/CompositeTestResultsTest.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/report/CompositeTestResultsTest.groovy
@@ -63,6 +63,6 @@ class CompositeTestResultsTest extends Specification {
}
private TestResult test() {
- return new TestResult('test', 45, new ClassTestResults('test', null))
+ return new TestResult('test', 45, new ClassTestResults(1, 'test', null))
}
}
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/report/DefaultTestReportTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/report/DefaultTestReportTest.groovy
index bb8ba78..9d3988b 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/report/DefaultTestReportTest.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/report/DefaultTestReportTest.groovy
@@ -15,18 +15,12 @@
*/
package org.gradle.api.internal.tasks.testing.junit.report
-import org.gradle.api.Action
-import org.gradle.api.internal.tasks.testing.junit.result.TestClassResult
-import org.gradle.api.internal.tasks.testing.junit.result.TestMethodResult
+import org.gradle.api.internal.tasks.testing.BuildableTestResultsProvider
import org.gradle.api.internal.tasks.testing.junit.result.TestResultsProvider
-import org.gradle.api.internal.tasks.testing.logging.SimpleTestResult
-import org.gradle.api.tasks.testing.TestOutputEvent
import org.gradle.api.tasks.testing.TestResult
import org.gradle.test.fixtures.file.TestFile
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
import org.gradle.util.ConfigureUtil
-import org.jsoup.Jsoup
-import org.jsoup.nodes.Document
import org.junit.Rule
import spock.lang.Specification
@@ -55,33 +49,24 @@ class DefaultTestReportTest extends Specification {
}
TestResultsProvider buildResults(Closure closure) {
- TestResultsBuilder builder = new TestResultsBuilder()
- ConfigureUtil.configure(closure, builder)
- return builder;
+ ConfigureUtil.configure(closure, new BuildableTestResultsProvider())
}
def generatesReportWhichIncludesContentsOfEachTestResultFile() {
given:
def testTestResults = buildResults {
testClassResult("org.gradle.Test") {
- testcase("test1") {
- duration = 1
- }
+ testcase("test1")
testcase("test2") {
- duration = 4
+ stdout "this is\nstandard output"
+ stderr "this is\nstandard error"
}
- stdout = "this is\nstandard output"
- stderr = "this is\nstandard error"
}
testClassResult("org.gradle.Test2") {
- testcase("test3") {
- duration = 102001
- }
+ testcase("test3")
}
testClassResult("org.gradle.sub.Test") {
- testcase("test4") {
- duration = 12900
- }
+ testcase("test4")
}
}
@@ -93,10 +78,12 @@ class DefaultTestReportTest extends Specification {
index.assertHasTests(4)
index.assertHasFailures(0)
index.assertHasSuccessRate(100)
- index.assertHasDuration("1m54.91s")
+ index.assertHasDuration("0.400s")
index.assertHasLinkTo('org.gradle')
index.assertHasLinkTo('org.gradle.sub')
index.assertHasLinkTo('org.gradle.Test', 'org.gradle.Test')
+ index.packageDetails("org.gradle").assertSuccessRate(100)
+ index.packageDetails("org.gradle.sub").assertSuccessRate(100)
reportDir.file("style.css").assertIsFile()
@@ -104,7 +91,7 @@ class DefaultTestReportTest extends Specification {
packageFile.assertHasTests(3)
packageFile.assertHasFailures(0)
packageFile.assertHasSuccessRate(100)
- packageFile.assertHasDuration("1m42.01s")
+ packageFile.assertHasDuration("0.300s")
packageFile.assertHasLinkTo('org.gradle.Test', 'Test')
packageFile.assertHasLinkTo('org.gradle.Test2', 'Test2')
@@ -112,7 +99,7 @@ class DefaultTestReportTest extends Specification {
testClassFile.assertHasTests(2)
testClassFile.assertHasFailures(0)
testClassFile.assertHasSuccessRate(100)
- testClassFile.assertHasDuration("0.005s")
+ testClassFile.assertHasDuration("0.200s")
testClassFile.assertHasTest('test1')
testClassFile.assertHasTest('test2')
testClassFile.assertHasStandardOutput('this is\nstandard output')
@@ -130,9 +117,10 @@ class DefaultTestReportTest extends Specification {
testcase("test2") {
duration = 0
failure("a multi-line\nmessage\"", "this is a failure.")
+ stdout "this is\nstandard output"
+ stderr "this is\nstandard error"
+
}
- stdout = "this is\nstandard output"
- stderr = "this is\nstandard error"
}
testClassResult("org.gradle.Test2") {
@@ -155,6 +143,8 @@ class DefaultTestReportTest extends Specification {
index.assertHasFailures(2)
index.assertHasSuccessRate(50)
index.assertHasFailedTest('org.gradle.Test', 'test1')
+ index.packageDetails("org.gradle").assertSuccessRate(33)
+ index.packageDetails("org.gradle.sub").assertSuccessRate(100)
def packageFile = results(reportDir.file('org.gradle.html'))
packageFile.assertHasTests(3)
@@ -229,11 +219,11 @@ class DefaultTestReportTest extends Specification {
def testTestResults = buildResults {
testClassResult("org.gradle.Test") {
testcase("test1 < test2") {
- duration = 0
failure("something failed", "<a failure>")
+
+ stdout "</html> & "
+ stderr "</div> & "
}
- stdout = "</html> & "
- stderr = "</div> & "
}
}
when:
@@ -253,9 +243,9 @@ class DefaultTestReportTest extends Specification {
testClassResult("org.gradle.Test") {
testcase('\u0107') {
duration = 0
+ stdout "out:\u0256"
+ stderr "err:\u0102"
}
- stdout = "out:\u0256"
- stderr = "err:\u0102"
}
}
when:
@@ -269,7 +259,7 @@ class DefaultTestReportTest extends Specification {
}
def results(TestFile file) {
- return new TestResultsFixture(file)
+ return new HtmlTestResultsFixture(file)
}
def emptyResultSet() {
@@ -277,201 +267,4 @@ class DefaultTestReportTest extends Specification {
}
}
-class TestResultsBuilder implements TestResultsProvider {
- def testClasses = [:]
-
- void testClassResult(String className, Closure configClosure) {
- BuildableTestClassResult testSuite = new BuildableTestClassResult(className, System.currentTimeMillis())
- ConfigureUtil.configure(configClosure, testSuite)
-
- testClasses[className] = testSuite
- }
-
- void writeOutputs(String className, TestOutputEvent.Destination destination, Writer writer) {
- if (destination == TestOutputEvent.Destination.StdOut) {
- writer.append(testClasses[className].stdout);
- } else if (destination == TestOutputEvent.Destination.StdErr) {
- writer.append(testClasses[className].stderr);
- }
- }
-
- void visitClasses(Action<? super TestClassResult> visitor) {
- testClasses.values().each {
- visitor.execute(it)
- }
- }
-
- boolean hasOutput(String className, TestOutputEvent.Destination destination) {
- if (destination == TestOutputEvent.Destination.StdOut) {
- return testClasses[className].stdout != null && testClasses[className].stdout.length() != 0
- } else if (destination == TestOutputEvent.Destination.StdErr) {
- return testClasses[className].stderr != null && testClasses[className].stderr.length() != 0
- }
- }
-
- private static class BuildableTestClassResult extends TestClassResult {
- String stderr;
- String stdout;
-
- BuildableTestClassResult(String className, long startTime) {
- super(className, startTime)
- }
-
- TestMethodResult testcase(String name) {
- BuildableTestMethodResult methodResult = new BuildableTestMethodResult(name, new SimpleTestResult())
- add(methodResult)
- return methodResult
- }
-
- def testcase(String name, Closure configClosure) {
- BuildableTestMethodResult methodResult = testcase(name);
- ConfigureUtil.configure(configClosure, methodResult)
- return methodResult
- }
- }
-
- private static class BuildableTestMethodResult extends TestMethodResult {
- long duration
- List<Throwable> exceptions = []
- TestResult.ResultType resultType = TestResult.ResultType.SUCCESS
-
- BuildableTestMethodResult(String name, TestResult result) {
- super(name, result)
- duration = result.endTime - result.startTime;
- }
-
- void failure(String message, String text) {
- exceptions.add(new ResultException(message, text));
- }
- }
-
- private static class ResultException extends Exception {
- private final String message
- private final String text
-
- public ResultException(String message, String text) {
- this.text = text
- this.message = message
- }
-
- public String toString() {
- return message
- }
-
- public void printStackTrace(PrintWriter s) {
- s.print(text);
- }
- }
-}
-
-class TestResultsFixture {
- Document content
-
- TestResultsFixture(TestFile file) {
- file.assertIsFile()
- content = Jsoup.parse(file, null)
- }
-
- void assertHasTests(int tests) {
- def testDiv = content.select("div#tests")
- assert testDiv != null
- def counter = testDiv.select("div.counter")
- assert counter != null
- assert counter.text() == tests as String
- }
-
- void assertHasFailures(int tests) {
- def testDiv = content.select("div#failures")
- assert testDiv != null
- def counter = testDiv.select("div.counter")
- assert counter != null
- assert counter.text() == tests as String
- }
-
- void assertHasDuration(String duration) {
- def testDiv = content.select("div#duration")
- assert testDiv != null
- def counter = testDiv.select("div.counter")
- assert counter != null
- assert counter.text() == duration as String
-
- }
-
- void assertHasNoDuration() {
- def testDiv = content.select("div#duration")
- assert testDiv != null
- def counter = testDiv.select("div.counter")
- assert counter != null
- assert counter.text() == "-"
- }
-
- void assertHasSuccessRate(int rate) {
- def testDiv = content.select("div#successRate")
- assert testDiv != null
- def counter = testDiv.select("div.percent")
- assert counter != null
- assert counter.text() == "${rate}%"
- }
- void assertHasNoSuccessRate() {
- def testDiv = content.select("div#successRate")
- assert testDiv != null
- def counter = testDiv.select("div.percent")
- assert counter != null
- assert counter.text() == "-"
- }
-
- void assertHasNoNavLinks() {
- assert findTab('Packages').isEmpty()
- }
-
- void assertHasLinkTo(String target, String display = target) {
- assert content.select("a[href=${target}.html]").find{it.text() == display}
- }
-
- void assertHasFailedTest(String className, String testName) {
- def tab = findTab('Failed tests')
- assert tab != null
- assert tab.select("a[href=${className}.html#$testName]").find{it.text() == testName}
- }
-
- void assertHasTest(String testName) {
- assert findTestDetails(testName)
- }
-
- void assertTestIgnored(String testName) {
- def row = findTestDetails(testName)
- assert row.select("tr > td:eq(2)").text() == 'ignored'
- }
-
- void assertHasFailure(String testName, String stackTrace) {
- def detailsRow = findTestDetails(testName)
- assert detailsRow.select("tr > td:eq(2)").text() == 'failed'
- def tab = findTab('Failed tests')
- assert tab != null && !tab.isEmpty()
- assert tab.select("pre").find {it.text() == stackTrace.trim() }
- }
-
- private def findTestDetails(String testName) {
- def tab = findTab('Tests')
- def anchor = tab.select("TD").find {it.text() == testName}
- return anchor?.parent()
- }
-
- void assertHasStandardOutput(String stdout) {
- def tab = findTab('Standard output')
- assert tab != null
- assert tab.select("SPAN > PRE").find{it.text() == stdout.trim() }
- }
-
- void assertHasStandardError(String stderr) {
- def tab = findTab('Standard error')
- assert tab != null
- assert tab.select("SPAN > PRE").find{it.text() == stderr.trim() }
- }
-
- private def findTab(String title) {
- def tab = content.select("div.tab:has(h2:contains($title))")
- return tab
- }
-}
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/report/LocaleSafeDecimalFormatTest.java b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/report/LocaleSafeDecimalFormatTest.java
index 17d0caa..76a032a 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/report/LocaleSafeDecimalFormatTest.java
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/report/LocaleSafeDecimalFormatTest.java
@@ -23,9 +23,6 @@ import java.util.Locale;
import static junit.framework.Assert.assertEquals;
-/**
- * @author Szczepan Faber, @date: 09.03.11
- */
public class LocaleSafeDecimalFormatTest {
Locale defaultLocale = Locale.getDefault();
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/result/Binary2JUnitXmlReportGeneratorSpec.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/result/Binary2JUnitXmlReportGeneratorSpec.groovy
index 1715eb5..608bbc3 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/result/Binary2JUnitXmlReportGeneratorSpec.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/result/Binary2JUnitXmlReportGeneratorSpec.groovy
@@ -16,33 +16,30 @@
package org.gradle.api.internal.tasks.testing.junit.result
+import org.gradle.api.Action
+import org.gradle.api.GradleException
import org.gradle.api.tasks.testing.TestResult
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
import org.junit.Rule
import spock.lang.Specification
-import org.gradle.api.GradleException
-import org.gradle.api.Action
-/**
- * by Szczepan Faber, created at: 11/19/12
- */
class Binary2JUnitXmlReportGeneratorSpec extends Specification {
@Rule private TestNameTestDirectoryProvider temp = new TestNameTestDirectoryProvider()
private resultsProvider = Mock(TestResultsProvider)
- private generator = new Binary2JUnitXmlReportGenerator(temp.testDirectory, resultsProvider)
+ private generator = new Binary2JUnitXmlReportGenerator(temp.testDirectory, resultsProvider, TestOutputAssociation.WITH_SUITE)
def setup() {
generator.saxWriter = Mock(JUnitXmlResultWriter)
}
def "writes results"() {
- def fooTest = new TestClassResult('FooTest', 100)
- .add(new TestMethodResult("foo", Mock(TestResult)))
+ def fooTest = new TestClassResult(1, 'FooTest', 100)
+ .add(new TestMethodResult(1, "foo", Mock(TestResult)))
- def barTest = new TestClassResult('BarTest', 100)
- .add(new TestMethodResult("bar", Mock(TestResult)))
- .add(new TestMethodResult("bar2", Mock(TestResult)))
+ def barTest = new TestClassResult(2, 'BarTest', 100)
+ .add(new TestMethodResult(2, "bar", Mock(TestResult)))
+ .add(new TestMethodResult(3, "bar2", Mock(TestResult)))
resultsProvider.visitClasses(_) >> { Action action ->
action.execute(fooTest)
@@ -59,8 +56,8 @@ class Binary2JUnitXmlReportGeneratorSpec extends Specification {
}
def "adds context information to the failure if something goes wrong"() {
- def fooTest = new TestClassResult('FooTest', 100)
- .add(new TestMethodResult("foo", Mock(TestResult)))
+ def fooTest = new TestClassResult(1, 'FooTest', 100)
+ .add(new TestMethodResult(1, "foo", Mock(TestResult)))
resultsProvider.visitClasses(_) >> { Action action ->
action.execute(fooTest)
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/result/CachingFileWriterSpec.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/result/CachingFileWriterSpec.groovy
deleted file mode 100644
index aaf046e..0000000
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/result/CachingFileWriterSpec.groovy
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.tasks.testing.junit.result
-
-import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
-import org.junit.Rule
-import spock.lang.Specification
-
-/**
- * by Szczepan Faber, created at: 11/19/12
- */
-class CachingFileWriterSpec extends Specification {
-
- private @Rule TestNameTestDirectoryProvider temp = new TestNameTestDirectoryProvider()
- private writer = new CachingFileWriter(2)
-
- def cleanup() {
- writer.closeAll()
- }
-
- def "keeps n files open"() {
- when:
- writer.write(temp.file("1.txt"), "1")
-
- then:
- writer.openFiles.keySet()*.name == ["1.txt"]
-
- when:
- writer.write(temp.file("2.txt"), "2")
-
- then:
- writer.openFiles.keySet()*.name == ["1.txt", "2.txt"]
-
- when:
- writer.write(temp.file("3.txt"), "3")
-
- then:
- writer.openFiles.keySet()*.name == ["2.txt", "3.txt"]
-
- when:
- writer.closeAll()
-
- then:
- writer.openFiles.isEmpty()
- }
-
- def "writes to files"() {
- when:
- writer.write(temp.file("1.txt"), "1")
- writer.write(temp.file("2.txt"), "2")
- writer.write(temp.file("3.txt"), "3")
- writer.write(temp.file("4.txt"), "4")
- writer.write(temp.file("1.txt"), "a")
- writer.write(temp.file("2.txt"), "b")
- writer.write(temp.file("3.txt"), "c")
-
- and:
- writer.closeAll()
-
- then:
- writer.openFiles.isEmpty()
-
- and:
- temp.file("1.txt").text == '1a'
- temp.file("2.txt").text == '2b'
- temp.file("3.txt").text == '3c'
- temp.file("4.txt").text == '4'
- }
-}
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/result/JUnitXmlResultWriterSpec.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/result/JUnitXmlResultWriterSpec.groovy
index 112b659..617b309 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/result/JUnitXmlResultWriterSpec.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/result/JUnitXmlResultWriterSpec.groovy
@@ -16,51 +16,56 @@
package org.gradle.api.internal.tasks.testing.junit.result
+import org.gradle.api.internal.tasks.testing.BuildableTestResultsProvider
import org.gradle.api.internal.tasks.testing.results.DefaultTestResult
import org.gradle.integtests.fixtures.JUnitTestClassExecutionResult
+import org.gradle.integtests.fixtures.TestResultOutputAssociation
+import org.gradle.internal.SystemProperties
import spock.lang.Specification
+import static TestOutputAssociation.WITH_SUITE
+import static TestOutputAssociation.WITH_TESTCASE
import static java.util.Arrays.asList
import static java.util.Collections.emptyList
import static org.gradle.api.tasks.testing.TestOutputEvent.Destination.StdErr
import static org.gradle.api.tasks.testing.TestOutputEvent.Destination.StdOut
import static org.gradle.api.tasks.testing.TestResult.ResultType.*
import static org.hamcrest.Matchers.equalTo
-import org.gradle.internal.SystemProperties
-/**
- * by Szczepan Faber, created at: 11/16/12
- */
class JUnitXmlResultWriterSpec extends Specification {
private provider = Mock(TestResultsProvider)
- private generator = new JUnitXmlResultWriter("localhost", provider)
+ private mode = WITH_SUITE
+
+ protected JUnitXmlResultWriter getGenerator() {
+ new JUnitXmlResultWriter("localhost", provider, mode)
+ }
private startTime = 1353344968049
def "writes xml JUnit result"() {
- TestClassResult result = new TestClassResult("com.foo.FooTest", startTime)
- result.add(new TestMethodResult("some test", new DefaultTestResult(SUCCESS, startTime + 10, startTime + 25, 1, 1, 0, emptyList())))
- result.add(new TestMethodResult("some test two", new DefaultTestResult(SUCCESS, startTime + 15, startTime + 30, 1, 1, 0, emptyList())))
- result.add(new TestMethodResult("some failing test", new DefaultTestResult(FAILURE, startTime + 30, startTime + 40, 1, 0, 1, [new RuntimeException("Boo!")])))
- result.add(new TestMethodResult("some skipped test", new DefaultTestResult(SKIPPED, startTime + 35, startTime + 45, 1, 0, 1, asList())))
+ TestClassResult result = new TestClassResult(1, "com.foo.FooTest", startTime)
+ result.add(new TestMethodResult(1, "some test", new DefaultTestResult(SUCCESS, startTime + 10, startTime + 25, 1, 1, 0, emptyList())))
+ result.add(new TestMethodResult(2, "some test two", new DefaultTestResult(SUCCESS, startTime + 15, startTime + 30, 1, 1, 0, emptyList())))
+ result.add(new TestMethodResult(3, "some failing test", new DefaultTestResult(FAILURE, startTime + 30, startTime + 40, 1, 0, 1, [new RuntimeException("Boo!")])))
+ result.add(new TestMethodResult(4, "some skipped test", new DefaultTestResult(SKIPPED, startTime + 35, startTime + 45, 1, 0, 1, asList())))
- provider.writeOutputs("com.foo.FooTest", StdOut, _) >> { args -> args[2].write("1st output message\n2nd output message\n") }
- provider.writeOutputs("com.foo.FooTest", StdErr, _) >> { args -> args[2].write("err") }
+ provider.writeAllOutput(1, StdOut, _) >> { args -> args[2].write("1st output message\n2nd output message\n") }
+ provider.writeAllOutput(1, StdErr, _) >> { args -> args[2].write("err") }
when:
def xml = getXml(result)
then:
- new JUnitTestClassExecutionResult(xml, "com.foo.FooTest")
- .assertTestCount(4, 1, 0)
- .assertTestFailed("some failing test", equalTo('java.lang.RuntimeException: Boo!'))
- .assertTestsSkipped("some skipped test")
- .assertTestsExecuted("some test", "some test two", "some failing test")
- .assertStdout(equalTo("""1st output message
+ new JUnitTestClassExecutionResult(xml, "com.foo.FooTest", TestResultOutputAssociation.WITH_SUITE)
+ .assertTestCount(4, 1, 0)
+ .assertTestFailed("some failing test", equalTo('java.lang.RuntimeException: Boo!'))
+ .assertTestsSkipped("some skipped test")
+ .assertTestsExecuted("some test", "some test two", "some failing test")
+ .assertStdout(equalTo("""1st output message
2nd output message
"""))
- .assertStderr(equalTo("err"))
+ .assertStderr(equalTo("err"))
and:
xml.startsWith """<?xml version="1.1" encoding="UTF-8"?>
@@ -83,9 +88,9 @@ class JUnitXmlResultWriterSpec extends Specification {
}
def "writes results with empty outputs"() {
- TestClassResult result = new TestClassResult("com.foo.FooTest", startTime)
- result.add(new TestMethodResult("some test", new DefaultTestResult(SUCCESS, startTime + 100, startTime + 300, 1, 1, 0, emptyList())))
- _ * provider.writeOutputs(_, _, _)
+ TestClassResult result = new TestClassResult(1, "com.foo.FooTest", startTime)
+ result.add(new TestMethodResult(1, "some test", new DefaultTestResult(SUCCESS, startTime + 100, startTime + 300, 1, 1, 0, emptyList())))
+ _ * provider.writeAllOutput(_, _, _)
when:
def xml = getXml(result)
@@ -102,10 +107,10 @@ class JUnitXmlResultWriterSpec extends Specification {
}
def "encodes xml"() {
- TestClassResult result = new TestClassResult("com.foo.FooTest", startTime)
- result.add(new TestMethodResult("some test", new DefaultTestResult(FAILURE, 100, 300, 1, 1, 0, [new RuntimeException("<> encoded!")])))
- provider.writeOutputs(_, StdErr, _) >> { args -> args[2].write("with CDATA end token: ]]> some ascii: ż") }
- provider.writeOutputs(_, StdOut, _) >> { args -> args[2].write("with CDATA end token: ]]> some ascii: ż") }
+ TestClassResult result = new TestClassResult(1, "com.foo.FooTest", startTime)
+ result.add(new TestMethodResult(1, "some test", new DefaultTestResult(FAILURE, 100, 300, 1, 1, 0, [new RuntimeException("<> encoded!")])))
+ provider.writeAllOutput(_, StdErr, _) >> { args -> args[2].write("with CDATA end token: ]]> some ascii: ż") }
+ provider.writeAllOutput(_, StdOut, _) >> { args -> args[2].write("with CDATA end token: ]]> some ascii: ż") }
when:
def xml = getXml(result)
@@ -119,7 +124,7 @@ class JUnitXmlResultWriterSpec extends Specification {
}
def "writes results with no tests"() {
- TestClassResult result = new TestClassResult("com.foo.IgnoredTest", startTime)
+ TestClassResult result = new TestClassResult(1, "com.foo.IgnoredTest", startTime)
when:
def xml = getXml(result)
@@ -134,6 +139,48 @@ class JUnitXmlResultWriterSpec extends Specification {
"""
}
+ def "can generate with output per test"() {
+ given:
+ mode = WITH_TESTCASE
+ provider = new BuildableTestResultsProvider()
+ def testClass = provider.testClassResult("com.Foo")
+
+ when:
+ testClass.with {
+ stdout "class-out"
+ stderr "class-err"
+ testcase("m1").with {
+ stderr " m1-err-1"
+ stdout " m1-out-1"
+ stdout " m1-out-2"
+ stderr " m1-err-2"
+ }
+ testcase("m2").with {
+ stderr " m2-err-1"
+ stdout " m2-out-1"
+ stdout " m2-out-2"
+ stderr " m2-err-2"
+ }
+ }
+
+ then:
+ getXml(testClass) == """<?xml version="1.1" encoding="UTF-8"?>
+<testsuite name="com.Foo" tests="2" failures="0" errors="0" timestamp="1970-01-01T00:00:00" hostname="localhost" time="1.0">
+ <properties/>
+ <testcase name="m1" classname="com.Foo" time="0.1">
+ <system-out><![CDATA[ m1-out-1 m1-out-2]]></system-out>
+ <system-err><![CDATA[ m1-err-1 m1-err-2]]></system-err>
+ </testcase>
+ <testcase name="m2" classname="com.Foo" time="0.1">
+ <system-out><![CDATA[ m2-out-1 m2-out-2]]></system-out>
+ <system-err><![CDATA[ m2-err-1 m2-err-2]]></system-err>
+ </testcase>
+ <system-out><![CDATA[class-out]]></system-out>
+ <system-err><![CDATA[class-err]]></system-err>
+</testsuite>
+"""
+ }
+
def getXml(TestClassResult result) {
def text = new ByteArrayOutputStream()
generator.write(result, text)
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestClassResultSpec.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestClassResultSpec.groovy
index cd3bbe2..bd91d9c 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestClassResultSpec.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestClassResultSpec.groovy
@@ -20,19 +20,16 @@ import org.gradle.api.internal.tasks.testing.results.DefaultTestResult
import org.gradle.api.tasks.testing.TestResult
import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 11/19/12
- */
class TestClassResultSpec extends Specification {
def "provides test class result information"() {
- def result = new TestClassResult('class', 100)
+ def result = new TestClassResult(1, 'class', 100)
assert result.duration == 0
when:
- result.add(new TestMethodResult("foo", new DefaultTestResult(TestResult.ResultType.SUCCESS, 100, 200, 1, 1, 0, [])))
- result.add(new TestMethodResult("fail", new DefaultTestResult(TestResult.ResultType.FAILURE, 250, 300, 1, 0, 1, [new RuntimeException("bar")])))
- result.add(new TestMethodResult("fail2", new DefaultTestResult(TestResult.ResultType.FAILURE, 300, 450, 1, 0, 1, [new RuntimeException("foo")])))
+ result.add(new TestMethodResult(1, "foo", new DefaultTestResult(TestResult.ResultType.SUCCESS, 100, 200, 1, 1, 0, [])))
+ result.add(new TestMethodResult(2, "fail", new DefaultTestResult(TestResult.ResultType.FAILURE, 250, 300, 1, 0, 1, [new RuntimeException("bar")])))
+ result.add(new TestMethodResult(3, "fail2", new DefaultTestResult(TestResult.ResultType.FAILURE, 300, 450, 1, 0, 1, [new RuntimeException("foo")])))
then:
result.failuresCount == 2
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestOutputSerializerTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestOutputSerializerTest.groovy
deleted file mode 100644
index 8dd7729..0000000
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestOutputSerializerTest.groovy
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.tasks.testing.junit.result
-
-import org.gradle.api.tasks.testing.TestOutputEvent
-import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
-import org.junit.Rule
-import spock.lang.Specification
-
-import static org.gradle.api.tasks.testing.TestOutputEvent.Destination.StdErr
-import static org.gradle.api.tasks.testing.TestOutputEvent.Destination.StdOut
-
-/**
- * by Szczepan Faber, created at: 11/19/12
- */
-class TestOutputSerializerTest extends Specification {
- @Rule
- private TestNameTestDirectoryProvider temp = new TestNameTestDirectoryProvider()
- private serializer = new TestOutputSerializer(temp.testDirectory)
-
- def "flushes all output when output finishes"() {
- when:
- serializer.onOutput("Class1", StdOut, "[out]")
- serializer.onOutput("Class2", StdErr, "[err]")
- serializer.onOutput("Class1", StdErr, "[err]")
- serializer.onOutput("Class1", StdOut, "[out2]")
- serializer.finishOutputs()
-
- then:
- collectOutput("Class1", StdOut) == "[out][out2]"
- collectOutput("Class1", StdErr) == "[err]"
- collectOutput("Class2", StdErr) == "[err]"
- }
-
- def "writes nothing for unknown test class"() {
- when:
- serializer.finishOutputs()
-
- then:
- collectOutput("Unknown", StdErr) == ""
- }
-
- def "can query whether output is available for a test class"() {
- when:
- serializer.onOutput("Class1", StdOut, "[out]")
- serializer.finishOutputs()
-
- then:
- serializer.hasOutput("Class1", StdOut)
- !serializer.hasOutput("Class1", StdErr)
- !serializer.hasOutput("Unknown", StdErr)
- }
-
- String collectOutput(String className, TestOutputEvent.Destination destination) {
- def writer = new StringWriter()
- serializer.writeOutputs(className, destination, writer)
- return writer.toString()
- }
-}
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestOutputStoreSpec.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestOutputStoreSpec.groovy
new file mode 100644
index 0000000..ea0d4a1
--- /dev/null
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestOutputStoreSpec.groovy
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.tasks.testing.junit.result
+
+import org.gradle.api.internal.tasks.testing.DefaultTestOutputEvent
+import org.gradle.api.internal.tasks.testing.TestDescriptorInternal
+import org.gradle.api.tasks.testing.TestOutputEvent
+import org.gradle.test.fixtures.file.WorkspaceTest
+
+import static org.gradle.api.tasks.testing.TestOutputEvent.Destination.StdErr
+import static org.gradle.api.tasks.testing.TestOutputEvent.Destination.StdOut
+
+class TestOutputStoreSpec extends WorkspaceTest {
+
+ private output = new TestOutputStore(testDirectory)
+
+ TestDescriptorInternal descriptor(String className, Object testId) {
+ Stub(TestDescriptorInternal) {
+ getClassName() >> className
+ getId() >> testId
+ }
+ }
+
+ def "flushes all output when output finishes"() {
+ when:
+ def writer = output.writer()
+ writer.onOutput(1, 1, output(StdOut, "[out]"))
+ writer.onOutput(2, 1, output(StdErr, "[err]"))
+ writer.onOutput(1, 1, output(StdErr, "[err]"))
+ writer.onOutput(1, 1, output(StdOut, "[out2]"))
+ writer.close()
+ def reader = output.reader()
+
+ then:
+ collectOutput(reader, 1, StdOut) == "[out][out2]"
+ collectOutput(reader, 1, StdErr) == "[err]"
+ collectOutput(reader, 2, StdErr) == "[err]"
+ }
+
+ def DefaultTestOutputEvent output(TestOutputEvent.Destination destination, String msg) {
+ new DefaultTestOutputEvent(destination, msg)
+ }
+
+ def "writes nothing for unknown test class"() {
+ when:
+ def writer = output.writer()
+ writer.close()
+
+ then:
+ def reader = output.reader()
+ collectOutput(reader, 20, StdErr) == ""
+ }
+
+ def "can query whether output is available for a test class"() {
+ when:
+ def writer = output.writer()
+ writer.onOutput(1, 1, output(StdOut, "[out]"))
+ writer.close()
+ def reader = output.reader()
+
+ then:
+ reader.hasOutput(1, StdOut)
+ !reader.hasOutput(1, StdErr)
+ !reader.hasOutput(2, StdErr)
+
+ cleanup:
+ reader.close()
+ }
+
+ def "can open empty reader"() {
+ // neither file
+ expect:
+ output.reader().close() // no exception
+ }
+
+ def "exception if no output file"() {
+ when:
+ output.indexFile.createNewFile()
+ def reader = output.reader()
+
+ then:
+ thrown(IllegalStateException)
+
+ cleanup:
+ reader?.close()
+ }
+
+ def "exception if no index file, but index"() {
+ when:
+ output.outputsFile.createNewFile()
+ def reader = output.reader()
+
+ then:
+ thrown(IllegalStateException)
+
+ cleanup:
+ reader?.close()
+ }
+
+ String collectOutput(TestOutputStore.Reader reader, long classId, TestOutputEvent.Destination destination) {
+ def writer = new StringWriter()
+ reader.writeAllOutput(classId, destination, writer)
+ return writer.toString()
+ }
+}
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestReportDataCollectorSpec.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestReportDataCollectorSpec.groovy
index dcee91b..8784a76 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestReportDataCollectorSpec.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestReportDataCollectorSpec.groovy
@@ -16,12 +16,9 @@
package org.gradle.api.internal.tasks.testing.junit.result
-import org.gradle.api.Action
+import org.gradle.api.internal.tasks.testing.*
import org.gradle.api.internal.tasks.testing.results.DefaultTestResult
-import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
-import org.junit.Rule
import spock.lang.Specification
-import org.gradle.api.internal.tasks.testing.*
import static java.util.Arrays.asList
import static org.gradle.api.tasks.testing.TestOutputEvent.Destination.StdErr
@@ -29,54 +26,10 @@ import static org.gradle.api.tasks.testing.TestOutputEvent.Destination.StdOut
import static org.gradle.api.tasks.testing.TestResult.ResultType.FAILURE
import static org.gradle.api.tasks.testing.TestResult.ResultType.SUCCESS
-/**
- * by Szczepan Faber, created at: 11/19/12
- */
class TestReportDataCollectorSpec extends Specification {
- @Rule
- private TestNameTestDirectoryProvider temp = new TestNameTestDirectoryProvider()
- private TestOutputSerializer outputSerializer = Mock()
- private TestResultSerializer resultSerializer = Mock()
- private collector = new TestReportDataCollector(temp.testDirectory, outputSerializer, resultSerializer)
-
- def "closes output when root finishes"() {
- def root = new DefaultTestSuiteDescriptor("1", "Suite")
- def clazz = new DecoratingTestDescriptor(new DefaultTestClassDescriptor("1.1", "Class"), root)
-
- def dummyResult = new DefaultTestResult(SUCCESS, 0, 0, 0, 0, 0, asList())
-
- when:
- collector.afterSuite(clazz, dummyResult)
-
- then:
- 0 * outputSerializer.finishOutputs()
-
- when:
- collector.afterSuite(root, dummyResult)
-
- then:
- 1 * outputSerializer.finishOutputs()
- }
-
- def "writes results when root finishes"() {
- def root = new DefaultTestSuiteDescriptor("1", "Suite")
- def clazz = new DecoratingTestDescriptor(new DefaultTestClassDescriptor("1.1", "Class"), root)
-
- def dummyResult = new DefaultTestResult(SUCCESS, 0, 0, 0, 0, 0, asList())
-
- when:
- collector.afterSuite(clazz, dummyResult)
-
- then:
- 0 * resultSerializer._
-
- when:
- collector.afterSuite(root, dummyResult)
-
- then:
- 1 * resultSerializer.write(_, temp.testDirectory)
- 0 * resultSerializer._
- }
+ def Map<String, TestClassResult> results = [:]
+ def TestOutputStore.Writer writer = Mock()
+ def collector = new TestReportDataCollector(results, writer)
def "keeps track of test results"() {
def root = new DefaultTestSuiteDescriptor("1", "Suite")
@@ -99,12 +52,9 @@ class TestReportDataCollectorSpec extends Specification {
collector.afterSuite(root, new DefaultTestResult(FAILURE, 0, 500, 2, 1, 1, asList(new RuntimeException("Boo!"))))
- def results = []
- collector.visitClasses({ results << it } as Action)
-
then:
results.size() == 1
- def fooTest = results[0]
+ def fooTest = results.values().toList().first()
fooTest.className == 'FooTest'
fooTest.startTime == 100
fooTest.testsCount == 2
@@ -126,18 +76,9 @@ class TestReportDataCollectorSpec extends Specification {
collector.onOutput(test2, new DefaultTestOutputEvent(StdOut, "out"))
then:
- 1 * outputSerializer.onOutput("FooTest", StdErr, "err")
- 1 * outputSerializer.onOutput("FooTest", StdOut, "out")
- 0 * outputSerializer._
+ 1 * writer.onOutput(1, 2, new DefaultTestOutputEvent(StdErr, "err"))
+ 1 * writer.onOutput(1, 3, new DefaultTestOutputEvent(StdOut, "out"))
+ 0 * writer._
}
- def "provides outputs"() {
- def writer = new StringWriter()
-
- when:
- collector.writeOutputs("TestClass", StdErr, writer)
-
- then:
- 1 * outputSerializer.writeOutputs("TestClass", StdErr, writer)
- }
}
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestResultSerializerTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestResultSerializerTest.groovy
index d554f26..abb92d1 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestResultSerializerTest.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/junit/result/TestResultSerializerTest.groovy
@@ -15,26 +15,25 @@
*/
package org.gradle.api.internal.tasks.testing.junit.result
+import org.gradle.api.Action
+import org.gradle.api.tasks.testing.TestResult
+import org.gradle.messaging.remote.internal.PlaceholderException
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
import org.junit.Rule
import spock.lang.Specification
-import org.gradle.api.tasks.testing.TestResult
-import org.gradle.messaging.remote.internal.PlaceholderException
-import org.gradle.api.Action
class TestResultSerializerTest extends Specification {
@Rule
private TestNameTestDirectoryProvider tmp = new TestNameTestDirectoryProvider()
- final TestResultSerializer serializer = new TestResultSerializer()
def "can write and read results"() {
- def class1 = new TestClassResult('Class1', 1234)
+ def class1 = new TestClassResult(1, 'Class1', 1234)
def failure = new RuntimeException("broken")
- def method1 = new TestMethodResult("method1", TestResult.ResultType.SUCCESS, 100, 2300, [])
- def method2 = new TestMethodResult("method2", TestResult.ResultType.FAILURE, 200, 2700, [failure])
+ def method1 = new TestMethodResult(1, "method1", TestResult.ResultType.SUCCESS, 100, 2300, [])
+ def method2 = new TestMethodResult(2, "method2", TestResult.ResultType.FAILURE, 200, 2700, [failure])
class1.add(method1)
class1.add(method2)
- def class2 = new TestClassResult('Class2', 5678)
+ def class2 = new TestClassResult(2, 'Class2', 5678)
def results = [class1, class2]
when:
@@ -71,11 +70,11 @@ class TestResultSerializerTest extends Specification {
}
def "can write and read exceptions that are not serializable"() {
- def class1 = new TestClassResult('Class1', 1234)
+ def class1 = new TestClassResult(1, 'Class1', 1234)
def failure = new RuntimeException("broken") {
final Object field = new Object()
}
- def method1 = new TestMethodResult("method1", TestResult.ResultType.FAILURE, 200, 2700, [failure])
+ def method1 = new TestMethodResult(1, "method1", TestResult.ResultType.FAILURE, 200, 2700, [failure])
class1.add(method1)
def results = [class1]
@@ -94,10 +93,10 @@ class TestResultSerializerTest extends Specification {
}
List<TestClassResult> serialize(Collection<TestClassResult> results) {
- def dir = tmp.createDir("results")
- serializer.write(results, dir)
+ def serializer = new TestResultSerializer(tmp.createDir("results"))
+ serializer.write(results)
def result = []
- serializer.read(dir, { result << it } as Action)
+ serializer.read({ result << it } as Action)
return result
}
}
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/logging/SimpleTestResult.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/logging/SimpleTestResult.groovy
deleted file mode 100644
index 9b4cdb4..0000000
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/logging/SimpleTestResult.groovy
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.internal.tasks.testing.logging
-
-import org.gradle.api.tasks.testing.TestResult
-
-class SimpleTestResult implements TestResult {
- TestResult.ResultType resultType = TestResult.ResultType.SUCCESS
- List<Throwable> exceptions = []
- Throwable exception = exceptions[0]
- long startTime = System.currentTimeMillis()
- long endTime = startTime + 100
- long testCount = 1
- long successfulTestCount = 1
- long failedTestCount = 0
- long skippedTestCount = 0
-}
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/logging/TestEventLoggerTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/logging/TestEventLoggerTest.groovy
index 2c4b407..35174fd 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/logging/TestEventLoggerTest.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/logging/TestEventLoggerTest.groovy
@@ -16,12 +16,12 @@
package org.gradle.api.internal.tasks.testing.logging
+import org.gradle.api.internal.tasks.testing.SimpleTestResult
import org.gradle.api.logging.LogLevel
-import org.gradle.api.tasks.testing.logging.TestLogEvent
import org.gradle.api.tasks.testing.TestResult
-
-import spock.lang.Specification
+import org.gradle.api.tasks.testing.logging.TestLogEvent
import org.gradle.logging.TestStyledTextOutputFactory
+import spock.lang.Specification
class TestEventLoggerTest extends Specification {
def textOutputFactory = new TestStyledTextOutputFactory()
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/results/DefaultTestResultTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/results/DefaultTestResultTest.groovy
index 8ad5615..9ea1ee6 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/results/DefaultTestResultTest.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/results/DefaultTestResultTest.groovy
@@ -23,9 +23,6 @@ import org.gradle.api.internal.tasks.testing.TestStartEvent
import org.gradle.api.tasks.testing.TestResult.ResultType
import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 10/14/11
- */
public class DefaultTestResultTest extends Specification {
def "construct itself from the state"() {
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/testng/TestNGTestFrameworkTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/testng/TestNGTestFrameworkTest.groovy
index aac8f74..667111e 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/testng/TestNGTestFrameworkTest.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/internal/tasks/testing/testng/TestNGTestFrameworkTest.groovy
@@ -20,16 +20,13 @@ import org.gradle.api.tasks.testing.Test
import org.gradle.api.tasks.testing.testng.TestNGOptions
import org.gradle.internal.service.ServiceRegistry
import org.gradle.testfixtures.ProjectBuilder
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import spock.lang.Specification
-/**
- * @author Szczepan Faber
- */
public class TestNGTestFrameworkTest extends Specification {
private project = new ProjectBuilder().build()
- Test testTask = HelperUtil.createTask(Test, project)
+ Test testTask = TestUtil.createTask(Test, project)
void setup() {
project.ext.sourceCompatibility = "1.7"
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/java/archives/internal/DefaultAttributesTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/java/archives/internal/DefaultAttributesTest.groovy
index d9bdbe8..424cea0 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/java/archives/internal/DefaultAttributesTest.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/java/archives/internal/DefaultAttributesTest.groovy
@@ -15,12 +15,9 @@
*/
package org.gradle.api.java.archives.internal
-import spock.lang.Specification
import org.gradle.api.java.archives.ManifestException
+import spock.lang.Specification
-/**
- * @author Hans Dockter
- */
class DefaultAttributesTest extends Specification {
DefaultAttributes attributes = new DefaultAttributes();
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/java/archives/internal/DefaultManifestMergeSpecTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/java/archives/internal/DefaultManifestMergeSpecTest.groovy
index 8744feb..ba4974f 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/java/archives/internal/DefaultManifestMergeSpecTest.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/java/archives/internal/DefaultManifestMergeSpecTest.groovy
@@ -23,9 +23,6 @@ import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
import org.junit.Rule
import spock.lang.Specification
-/**
- * @author Hans Dockter
- */
class DefaultManifestMergeSpecTest extends Specification {
def static final MANIFEST_VERSION_MAP = ['Manifest-Version': '1.0']
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/java/archives/internal/DefaultManifestTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/java/archives/internal/DefaultManifestTest.groovy
index 9bf7616..80fdcc8 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/java/archives/internal/DefaultManifestTest.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/java/archives/internal/DefaultManifestTest.groovy
@@ -25,9 +25,6 @@ import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
import org.junit.Rule
import spock.lang.Specification
-/**
- * @author Hans Dockter
- */
class DefaultManifestTest extends Specification {
def static final MANIFEST_VERSION_MAP = ['Manifest-Version': '1.0']
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/ApplicationPluginTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/ApplicationPluginTest.groovy
index 2851aaf..aece950 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/ApplicationPluginTest.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/ApplicationPluginTest.groovy
@@ -17,19 +17,18 @@ package org.gradle.api.plugins
import org.gradle.api.Project
import org.gradle.api.tasks.application.CreateStartScripts
-import org.gradle.api.tasks.Copy
import org.gradle.api.tasks.JavaExec
import org.gradle.api.tasks.SourceSet
import org.gradle.api.tasks.bundling.Zip
import org.gradle.api.tasks.bundling.Tar
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import org.gradle.util.Matchers
import spock.lang.Specification
import org.gradle.api.tasks.Sync
import org.gradle.api.file.CopySpec
class ApplicationPluginTest extends Specification {
- private final Project project = HelperUtil.createRootProject();
+ private final Project project = TestUtil.createRootProject();
private final ApplicationPlugin plugin = new ApplicationPlugin();
def "applies JavaPlugin and adds convention object with default values"() {
@@ -41,6 +40,7 @@ class ApplicationPluginTest extends Specification {
project.convention.getPlugin(ApplicationPluginConvention.class) != null
project.applicationName == project.name
project.mainClassName == null
+ project.applicationDefaultJvmArgs == []
project.applicationDistribution instanceof CopySpec
}
@@ -64,6 +64,7 @@ class ApplicationPluginTest extends Specification {
task instanceof CreateStartScripts
task.applicationName == project.applicationName
task.outputDir == project.file('build/scripts')
+ task.defaultJvmOpts == []
}
public void "adds installApp task to project with default target"() {
@@ -131,4 +132,24 @@ class ApplicationPluginTest extends Specification {
def startScripts = project.tasks[ApplicationPlugin.TASK_START_SCRIPTS_NAME]
startScripts.mainClassName == "Acme"
}
+
+ public void "applicationDefaultJvmArgs in project delegates to jvmArgs in run task"() {
+ when:
+ plugin.apply(project)
+ project.applicationDefaultJvmArgs = ['-Dfoo=bar', '-Xmx500m']
+
+ then:
+ def run = project.tasks[ApplicationPlugin.TASK_RUN_NAME]
+ run.jvmArgs == ['-Dfoo=bar', '-Xmx500m']
+ }
+
+ public void "applicationDefaultJvmArgs in project delegates to defaultJvmOpts in startScripts task"() {
+ when:
+ plugin.apply(project);
+ project.applicationDefaultJvmArgs = ['-Dfoo=bar', '-Xmx500m']
+
+ then:
+ def startScripts = project.tasks[ApplicationPlugin.TASK_START_SCRIPTS_NAME]
+ startScripts.defaultJvmOpts == ['-Dfoo=bar', '-Xmx500m']
+ }
}
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/BasePluginConventionTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/BasePluginConventionTest.groovy
index b6de9c9..3d40dcb 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/BasePluginConventionTest.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/BasePluginConventionTest.groovy
@@ -17,16 +17,14 @@
package org.gradle.api.plugins
import org.gradle.api.internal.project.DefaultProject
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import org.junit.Before
import org.junit.Test
+
import static org.junit.Assert.assertEquals
-/**
- * @author Hans Dockter
- */
class BasePluginConventionTest {
- private DefaultProject project = HelperUtil.createRootProject()
+ private DefaultProject project = TestUtil.createRootProject()
private File testDir = project.projectDir
private BasePluginConvention convention
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/BasePluginTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/BasePluginTest.groovy
index d057909..03c03b3 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/BasePluginTest.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/BasePluginTest.groovy
@@ -27,16 +27,14 @@ import org.gradle.api.tasks.Upload
import org.gradle.api.tasks.bundling.Jar
import org.gradle.api.tasks.bundling.Tar
import org.gradle.api.tasks.bundling.Zip
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import spock.lang.Specification
+
import static org.gradle.util.Matchers.dependsOn
import static org.hamcrest.Matchers.instanceOf
-/**
- * @author Hans Dockter
- */
class BasePluginTest extends Specification {
- private final Project project = HelperUtil.createRootProject()
+ private final Project project = TestUtil.createRootProject()
private final BasePlugin plugin = new BasePlugin()
public void addsConventionObjects() {
@@ -65,7 +63,7 @@ class BasePluginTest extends Specification {
public void assembleTaskBuildsThePublishedArtifacts() {
given:
- def someJar = project.tasks.add('someJar', Jar)
+ def someJar = project.tasks.create('someJar', Jar)
when:
plugin.apply(project)
@@ -86,7 +84,7 @@ class BasePluginTest extends Specification {
public void addsImplicitTasksForConfiguration() {
given:
- def someJar = project.tasks.add('someJar', Jar)
+ def someJar = project.tasks.create('someJar', Jar)
when:
plugin.apply(project)
@@ -103,7 +101,7 @@ class BasePluginTest extends Specification {
uploadArchives dependsOn('someJar')
when:
- project.configurations.add('conf')
+ project.configurations.create('conf')
project.artifacts.conf someJar
then:
@@ -153,19 +151,19 @@ class BasePluginTest extends Specification {
project.version = '1.0'
then:
- def someJar = project.tasks.add('someJar', Jar)
+ def someJar = project.tasks.create('someJar', Jar)
someJar.destinationDir == project.libsDir
someJar.version == project.version
someJar.baseName == project.archivesBaseName
and:
- def someZip = project.tasks.add('someZip', Zip)
+ def someZip = project.tasks.create('someZip', Zip)
someZip.destinationDir == project.distsDir
someZip.version == project.version
someZip.baseName == project.archivesBaseName
and:
- def someTar = project.tasks.add('someTar', Tar)
+ def someTar = project.tasks.create('someTar', Tar)
someTar.destinationDir == project.distsDir
someTar.version == project.version
someTar.baseName == project.archivesBaseName
@@ -176,7 +174,7 @@ class BasePluginTest extends Specification {
plugin.apply(project)
then:
- def task = project.tasks.add('someJar', Jar)
+ def task = project.tasks.create('someJar', Jar)
task.version == null
when:
@@ -208,7 +206,7 @@ class BasePluginTest extends Specification {
when:
plugin.apply(project)
- project.configurations.add("custom").artifacts.add(artifact)
+ project.configurations.create("custom").artifacts.add(artifact)
then:
project.configurations[Dependency.ARCHIVES_CONFIGURATION].artifacts.contains(artifact)
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/GroovyBasePluginTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/GroovyBasePluginTest.groovy
index f096025..98a5d35 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/GroovyBasePluginTest.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/GroovyBasePluginTest.groovy
@@ -21,7 +21,7 @@ import org.gradle.api.internal.artifacts.configurations.Configurations
import org.gradle.api.reporting.ReportingExtension
import org.gradle.api.tasks.compile.GroovyCompile
import org.gradle.api.tasks.javadoc.Groovydoc
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import org.junit.Before
import org.junit.Test
@@ -31,12 +31,9 @@ import static org.gradle.util.WrapUtil.toSet
import static org.hamcrest.Matchers.*
import static org.junit.Assert.*
-/**
- * @author Hans Dockter
- */
class GroovyBasePluginTest {
- private final Project project = HelperUtil.createRootProject()
+ private final Project project = TestUtil.createRootProject()
@Before
void before() {
@@ -56,13 +53,13 @@ class GroovyBasePluginTest {
}
@Test void appliesMappingsToNewSourceSet() {
- def sourceSet = project.sourceSets.add('custom')
+ def sourceSet = project.sourceSets.create('custom')
assertThat(sourceSet.groovy.displayName, equalTo("custom Groovy source"))
assertThat(sourceSet.groovy.srcDirs, equalTo(toLinkedSet(project.file("src/custom/groovy"))))
}
@Test void addsCompileTaskToNewSourceSet() {
- project.sourceSets.add('custom')
+ project.sourceSets.create('custom')
def task = project.tasks['compileCustomGroovy']
assertThat(task, instanceOf(GroovyCompile.class))
@@ -71,7 +68,7 @@ class GroovyBasePluginTest {
}
@Test void dependenciesOfJavaPluginTasksIncludeGroovyCompileTasks() {
- project.sourceSets.add('custom')
+ project.sourceSets.create('custom')
def task = project.tasks['customClasses']
assertThat(task, dependsOn(hasItem('compileCustomGroovy')))
}
@@ -82,22 +79,4 @@ class GroovyBasePluginTest {
assertThat(task.docTitle, equalTo(project.extensions.getByType(ReportingExtension).apiDocTitle))
assertThat(task.windowTitle, equalTo(project.extensions.getByType(ReportingExtension).apiDocTitle))
}
-
- @Test void defaultsGroovyClasspathToGroovyConfigurationIfTheLatterIsNonEmpty() {
- project.sourceSets.add('custom')
- def configuration = project.configurations.groovy
- project.dependencies {
- groovy "org.codehaus.groovy:groovy-all:2.0.5"
- }
-
- def compileTask = project.tasks.compileCustomGroovy
- assertSame(configuration, compileTask.groovyClasspath)
-
- def groovydocTask = project.task('groovydoc', type: Groovydoc)
- assertSame(configuration, groovydocTask.groovyClasspath)
- }
-
- // see GroovyBasePluginIntegrationTest
- @Test void defaultsGroovyClasspathToInferredGroovyDependencyIfGroovyConfigurationIsEmpty() {
- }
}
\ No newline at end of file
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/GroovyPluginTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/GroovyPluginTest.groovy
index 6e55872..3e6b3db 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/GroovyPluginTest.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/GroovyPluginTest.groovy
@@ -22,7 +22,7 @@ import org.gradle.api.reporting.ReportingExtension
import org.gradle.api.tasks.compile.GroovyCompile
import org.gradle.api.tasks.javadoc.Groovydoc
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import org.junit.Rule
import org.junit.Test
@@ -32,13 +32,10 @@ import static org.gradle.util.WrapUtil.toSet
import static org.hamcrest.Matchers.*
import static org.junit.Assert.*
-/**
- * @author Hans Dockter
- */
class GroovyPluginTest {
@Rule
public TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider()
- private final Project project = HelperUtil.createRootProject()
+ private final Project project = TestUtil.createRootProject()
private final GroovyPlugin groovyPlugin = new GroovyPlugin()
@Test public void appliesTheJavaPluginToTheProject() {
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/JavaBasePluginTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/JavaBasePluginTest.groovy
index b7c10a6..23ca786 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/JavaBasePluginTest.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/JavaBasePluginTest.groovy
@@ -14,35 +14,30 @@
* limitations under the License.
*/
package org.gradle.api.plugins
-
import org.gradle.api.DefaultTask
import org.gradle.api.Project
import org.gradle.api.reporting.ReportingExtension
-import org.gradle.api.tasks.ClassDirectoryBinary
import org.gradle.api.tasks.Copy
+import org.gradle.api.tasks.SourceSet
import org.gradle.api.tasks.bundling.Jar
import org.gradle.api.tasks.compile.JavaCompile
import org.gradle.api.tasks.javadoc.Javadoc
import org.gradle.api.tasks.testing.Test
import org.gradle.internal.reflect.Instantiator
-import org.gradle.util.HelperUtil
+import org.gradle.language.jvm.ClassDirectoryBinary
import org.gradle.util.Matchers
import org.gradle.util.SetSystemProperties
+import org.gradle.util.TestUtil
import org.junit.Rule
-
import spock.lang.Specification
import static org.gradle.util.Matchers.sameCollection
import static org.gradle.util.WrapUtil.toLinkedSet
-/**
- * @author Hans Dockter
- */
-
class JavaBasePluginTest extends Specification {
@Rule
public SetSystemProperties sysProperties = new SetSystemProperties()
- private final Project project = HelperUtil.createRootProject()
+ private final Project project = TestUtil.createRootProject()
private final JavaBasePlugin javaBasePlugin = new JavaBasePlugin(project.services.get(Instantiator))
void appliesBasePluginsAndAddsConventionObject() {
@@ -59,17 +54,16 @@ class JavaBasePluginTest extends Specification {
void createsTasksAndAppliesMappingsForNewSourceSet() {
when:
javaBasePlugin.apply(project)
- project.sourceSets.add('custom')
+ project.sourceSets.create('custom')
then:
- def set = project.sourceSets.custom
+ SourceSet set = project.sourceSets.custom
set.java.srcDirs == toLinkedSet(project.file('src/custom/java'))
set.resources.srcDirs == toLinkedSet(project.file('src/custom/resources'))
set.output.classesDir == new File(project.buildDir, 'classes/custom')
- Matchers.builtBy('customClasses').matches(set.output)
def processResources = project.tasks['processCustomResources']
- processResources.description == 'Processes the custom resources.'
+ processResources.description == "Processes source set 'custom:resources'."
processResources instanceof Copy
Matchers.dependsOn().matches(processResources)
processResources.destinationDir == project.sourceSets.custom.output.resourcesDir
@@ -77,27 +71,43 @@ class JavaBasePluginTest extends Specification {
resources sameCollection(project.sourceSets.custom.resources)
def compileJava = project.tasks['compileCustomJava']
- compileJava.description == 'Compiles the custom/java source set.'
+ compileJava.description == "Compiles source set 'custom:java'."
compileJava instanceof JavaCompile
Matchers.dependsOn().matches(compileJava)
compileJava.classpath.is(project.sourceSets.custom.compileClasspath)
compileJava.destinationDir == project.sourceSets.custom.output.classesDir
+
def sources = compileJava.source
sources sameCollection(project.sourceSets.custom.java)
+
def classes = project.tasks['customClasses']
- classes.description == 'Assembles the custom classes.'
+ classes.description == "Assembles classes 'custom'."
classes instanceof DefaultTask
Matchers.dependsOn('processCustomResources', 'compileCustomJava').matches(classes)
- classes.dependsOn.contains project.sourceSets.custom.output.dirs
+ Matchers.builtBy('customClasses').matches(project.sourceSets.custom.output)
}
-
+
+ void "wires generated resources task into classes task for sourceset"() {
+ when:
+ javaBasePlugin.apply(project)
+ project.sourceSets.create('custom')
+
+ and:
+ final someTask = project.task("someTask")
+ project.sourceSets.custom.output.dir('some-dir', builtBy: someTask)
+
+ then:
+ def customClasses = project.tasks['customClasses']
+ Matchers.dependsOn('someTask', 'processCustomResources', 'compileCustomJava').matches(customClasses)
+ }
+
void tasksReflectChangesToSourceSetConfiguration() {
def classesDir = project.file('target/classes')
def resourcesDir = project.file('target/resources')
when:
javaBasePlugin.apply(project)
- project.sourceSets.add('custom')
+ project.sourceSets.create('custom')
project.sourceSets.custom.output.classesDir = classesDir
project.sourceSets.custom.output.resourcesDir = resourcesDir
@@ -112,21 +122,21 @@ class JavaBasePluginTest extends Specification {
void createsConfigurationsForNewSourceSet() {
when:
javaBasePlugin.apply(project)
- def sourceSet = project.sourceSets.add('custom')
+ def sourceSet = project.sourceSets.create('custom')
then:
def compile = project.configurations.customCompile
compile.transitive
!compile.visible
compile.extendsFrom == [] as Set
- compile.description == 'Classpath for compiling the custom sources.'
+ compile.description == "Compile classpath for source set 'custom'."
and:
def runtime = project.configurations.customRuntime
runtime.transitive
!runtime.visible
runtime.extendsFrom == [compile] as Set
- runtime.description == 'Classpath for running the compiled custom classes.'
+ runtime.description == "Runtime classpath for source set 'custom'."
and:
def runtimeClasspath = sourceSet.runtimeClasspath
@@ -200,7 +210,7 @@ class JavaBasePluginTest extends Specification {
def configuresTestTaskWhenDebugSystemPropertyIsSet() {
javaBasePlugin.apply(project)
- def task = project.tasks.add('test', Test.class)
+ def task = project.tasks.create('test', Test.class)
when:
System.setProperty("test.debug", "true")
@@ -210,9 +220,9 @@ class JavaBasePluginTest extends Specification {
task.debug
}
- def configuresTestTaskWhenSingleTestSystemPropertyIsSet() {
+ def "configures test task when test.single is used"() {
javaBasePlugin.apply(project)
- def task = project.tasks.add('test', Test.class)
+ def task = project.tasks.create('test', Test.class)
task.include 'ignoreme'
when:
@@ -221,6 +231,7 @@ class JavaBasePluginTest extends Specification {
then:
task.includes == ['**/pattern*.class'] as Set
+ task.inputs.getSourceFiles().empty
}
def "adds functional and language source sets for each source set added to the 'sourceSets' container"() {
@@ -267,7 +278,7 @@ class JavaBasePluginTest extends Specification {
}
then:
- def binary = project.binaries.jvm.findByName("custom")
+ def binary = project.binaries.findByName("customClasses")
binary instanceof ClassDirectoryBinary
binary.classesDir == project.file("classes")
binary.resourcesDir == project.file("resources")
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/JavaLanguagePluginTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/JavaLanguagePluginTest.groovy
index 24c0c45..f02ddce 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/JavaLanguagePluginTest.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/JavaLanguagePluginTest.groovy
@@ -16,12 +16,16 @@
package org.gradle.api.plugins
import org.gradle.api.Project
-import org.gradle.util.HelperUtil
+import org.gradle.language.java.JavaSourceSet
+import org.gradle.api.tasks.compile.JavaCompile
+import org.gradle.language.jvm.ClassDirectoryBinary
+import org.gradle.language.jvm.plugins.JvmLanguagePlugin
+import org.gradle.util.TestUtil
import spock.lang.Specification
class JavaLanguagePluginTest extends Specification {
- Project project = HelperUtil.createRootProject()
+ Project project = TestUtil.createRootProject()
def setup() {
project.plugins.apply(JavaLanguagePlugin)
@@ -32,8 +36,15 @@ class JavaLanguagePluginTest extends Specification {
project.plugins.hasPlugin(JvmLanguagePlugin)
}
- // TODO once we have a DSL for adding source sets/binaries
def "adds a JavaCompile task for every JavaSourceSet added to a ClassDirectoryBinary"() {
+ when:
+ project.sources.create("model").create("java", JavaSourceSet)
+ project.binaries.create("integTest", ClassDirectoryBinary)
+ project.binaries.integTest.source << project.sources.model.java
+ then:
+ def task = project.tasks.findByName("compileIntegTestJava")
+ task instanceof JavaCompile
+ task.description == "Compiles source set 'model:java'."
}
}
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/JavaLibraryDistributionPluginTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/JavaLibraryDistributionPluginTest.groovy
index 2babac1..e87eaa5 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/JavaLibraryDistributionPluginTest.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/JavaLibraryDistributionPluginTest.groovy
@@ -19,11 +19,11 @@ import org.gradle.api.Project
import org.gradle.api.distribution.DistributionContainer
import org.gradle.api.distribution.plugins.DistributionPlugin
import org.gradle.api.tasks.bundling.Zip
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import spock.lang.Specification
class JavaLibraryDistributionPluginTest extends Specification {
- private final Project project = HelperUtil.builder().withName("test-project").build()
+ private final Project project = TestUtil.builder().withName("test-project").build()
def "applies JavaPlugin and adds convention object with default values"() {
when:
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/JavaPluginConventionTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/JavaPluginConventionTest.groovy
index 82c3ac2..cbd6ca1 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/JavaPluginConventionTest.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/JavaPluginConventionTest.groovy
@@ -24,8 +24,8 @@ import org.gradle.api.java.archives.internal.DefaultManifest
import org.gradle.internal.reflect.Instantiator
import org.gradle.test.fixtures.file.TestFile
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
-import org.gradle.util.HelperUtil
import org.gradle.util.JUnit4GroovyMockery
+import org.gradle.util.TestUtil
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@@ -34,12 +34,9 @@ import static org.hamcrest.Matchers.*
import static org.junit.Assert.assertEquals
import static org.junit.Assert.assertThat
-/**
- * @author Hans Dockter
- */
class JavaPluginConventionTest {
private final JUnit4GroovyMockery context = new JUnit4GroovyMockery()
- private DefaultProject project = HelperUtil.createRootProject()
+ private DefaultProject project = TestUtil.createRootProject()
private Instantiator instantiator = project.services.get(Instantiator)
private JavaPluginConvention convention
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/JavaPluginTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/JavaPluginTest.groovy
index 5bcbb76..e4e3f89 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/JavaPluginTest.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/JavaPluginTest.groovy
@@ -30,7 +30,7 @@ import org.gradle.api.tasks.bundling.Jar
import org.gradle.api.tasks.compile.JavaCompile
import org.gradle.api.tasks.javadoc.Javadoc
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import org.junit.Rule
import org.junit.Test
@@ -40,13 +40,10 @@ import static org.gradle.util.WrapUtil.toSet
import static org.hamcrest.Matchers.*
import static org.junit.Assert.*
-/**
- * @author Hans Dockter
- */
class JavaPluginTest {
@Rule
public TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider()
- private final Project project = HelperUtil.createRootProject()
+ private final Project project = TestUtil.createRootProject()
private final JavaPlugin javaPlugin = new JavaPlugin()
@Test public void appliesBasePluginsAndAddsConventionObject() {
@@ -134,7 +131,7 @@ class JavaPluginTest {
@Test public void createsMappingsForCustomSourceSets() {
javaPlugin.apply(project)
- def set = project.sourceSets.add('custom')
+ def set = project.sourceSets.create('custom')
assertThat(set.java.srcDirs, equalTo(toLinkedSet(project.file('src/custom/java'))))
assertThat(set.resources.srcDirs, equalTo(toLinkedSet(project.file('src/custom/resources'))))
assertThat(set.compileClasspath, sameInstance(project.configurations.customCompile))
@@ -184,7 +181,7 @@ class JavaPluginTest {
assertThat(task, instanceOf(Jar))
assertThat(task, dependsOn(JavaPlugin.CLASSES_TASK_NAME))
assertThat(task.destinationDir, equalTo(project.libsDir))
- assertThat(task.copyAction.mainSpec.sourcePaths, equalTo([project.sourceSets.main.output] as Set))
+ assertThat(task.mainSpec.sourcePaths, equalTo([project.sourceSets.main.output] as Set))
assertThat(task.manifest, notNullValue())
assertThat(task.manifest, not(sameInstance(project.manifest)))
assertThat(task.manifest.mergeSpecs.size(), equalTo(1))
@@ -250,9 +247,9 @@ class JavaPluginTest {
}
@Test public void buildOtherProjects() {
- DefaultProject commonProject = HelperUtil.createChildProject(project, "common");
- DefaultProject middleProject = HelperUtil.createChildProject(project, "middle");
- DefaultProject appProject = HelperUtil.createChildProject(project, "app");
+ DefaultProject commonProject = TestUtil.createChildProject(project, "common");
+ DefaultProject middleProject = TestUtil.createChildProject(project, "middle");
+ DefaultProject appProject = TestUtil.createChildProject(project, "app");
javaPlugin.apply(project);
javaPlugin.apply(commonProject);
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/JvmLanguagePluginTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/JvmLanguagePluginTest.groovy
index 3ced8ca..f003289 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/JvmLanguagePluginTest.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/JvmLanguagePluginTest.groovy
@@ -14,43 +14,49 @@
* limitations under the License.
*/
package org.gradle.api.plugins
-
-import org.gradle.api.internal.plugins.ProcessResources
-import org.gradle.api.tasks.ClassDirectoryBinary
-import org.gradle.api.tasks.JvmBinaryContainer
-import org.gradle.api.tasks.ResourceSet
-import org.gradle.util.HelperUtil
-
+import org.gradle.language.jvm.ClassDirectoryBinary
+import org.gradle.language.jvm.ResourceSet
+import org.gradle.language.jvm.internal.DefaultClassDirectoryBinary
+import org.gradle.language.jvm.plugins.JvmLanguagePlugin
+import org.gradle.language.jvm.tasks.ProcessResources
+import org.gradle.util.TestUtil
import spock.lang.Specification
class JvmLanguagePluginTest extends Specification {
- def project = HelperUtil.createRootProject()
+ def project = TestUtil.createRootProject()
def jvmLanguagePlugin = project.plugins.apply(JvmLanguagePlugin)
- def "adds a 'binaries.jvm' container to the project"() {
- def binaries = project.extensions.findByName("binaries")
+ def "registers the 'ResourceSet' type for each functional source set added to the 'sources' container"() {
+ when:
+ project.sources.create("custom")
+ project.sources.custom.create("resources", ResourceSet)
- expect:
- binaries != null
- binaries.jvm instanceof JvmBinaryContainer
+ then:
+ project.sources.custom.resources instanceof ResourceSet
}
- def "allows the JvmBinaryContainer to be looked up on the plugin"() {
+ def "registers the ClassDirectoryBinary type with the binaries container"() {
+ def binaries = project.extensions.findByName("binaries")
+ def binary = binaries.create("test", ClassDirectoryBinary)
+
expect:
- jvmLanguagePlugin.jvmBinaryContainer instanceof JvmBinaryContainer
+ binary != null
+ binary instanceof DefaultClassDirectoryBinary
}
def "adds a 'classes' task for every ClassDirectoryBinary added to the container"() {
when:
- def binary = project.binaries.jvm.create("prod", ClassDirectoryBinary)
+ def binary = project.binaries.create("prod", ClassDirectoryBinary)
then:
binary.classesDir == new File("$project.buildDir/classes/prod")
- project.tasks.findByName("prodClasses") != null
+ def task = project.tasks.findByName("prodClasses")
+ task != null
+ task.description == "Assembles classes 'prod'."
}
def "adds a 'processResources' task for every ResourceSet added to a ClassDirectoryBinary"() {
- ClassDirectoryBinary binary = project.binaries.jvm.create("prod", ClassDirectoryBinary)
+ ClassDirectoryBinary binary = project.binaries.create("prod", ClassDirectoryBinary)
ResourceSet resources = project.sources.create("main").create("resources", ResourceSet)
when:
@@ -58,6 +64,26 @@ class JvmLanguagePluginTest extends Specification {
then:
project.tasks.size() == old(project.tasks.size()) + 1
- project.tasks.findByName("processProdResources") instanceof ProcessResources
+ def task = project.tasks.findByName("processProdResources")
+ task instanceof ProcessResources
+ task.description == "Processes source set 'main:resources'."
+ }
+
+ def "adds tasks based on short name when ClassDirectoryBinary has name ending in Classes"() {
+ when:
+ ClassDirectoryBinary binary = project.binaries.create("fooClasses", ClassDirectoryBinary)
+ ResourceSet resources = project.sources.create("main").create("resources", ResourceSet)
+ binary.source.add(resources)
+
+ then:
+ binary.classesDir == new File("$project.buildDir/classes/foo")
+ def task = project.tasks.findByName("fooClasses")
+ task != null
+ task.description == "Assembles classes 'foo'."
+
+ and:
+ def resourcesTask = project.tasks.findByName("processFooResources")
+ resourcesTask instanceof ProcessResources
+ resourcesTask.description == "Processes source set 'main:resources'."
}
}
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/LanguageBasePluginTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/LanguageBasePluginTest.groovy
index 626f2ab..e227cf5 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/LanguageBasePluginTest.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/LanguageBasePluginTest.groovy
@@ -14,17 +14,17 @@
* limitations under the License.
*/
package org.gradle.api.plugins
-
import org.gradle.api.Project
-import org.gradle.api.tasks.BinariesContainer
-import org.gradle.api.tasks.ProjectSourceSet
-import org.gradle.api.tasks.ResourceSet
-import org.gradle.util.HelperUtil
-
+import org.gradle.language.base.BinaryContainer
+import org.gradle.language.base.ProjectSourceSet
+import org.gradle.language.base.internal.BinaryInternal
+import org.gradle.language.base.internal.BinaryNamingScheme
+import org.gradle.language.base.plugins.LanguageBasePlugin
+import org.gradle.util.TestUtil
import spock.lang.Specification
class LanguageBasePluginTest extends Specification {
- Project project = HelperUtil.createRootProject()
+ Project project = TestUtil.createRootProject()
def setup() {
project.plugins.apply(LanguageBasePlugin)
@@ -32,7 +32,7 @@ class LanguageBasePluginTest extends Specification {
def "adds a 'binaries' container to the project"() {
expect:
- project.extensions.findByName("binaries") instanceof BinariesContainer
+ project.extensions.findByName("binaries") instanceof BinaryContainer
}
def "adds a 'sources' container to the project"() {
@@ -40,12 +40,17 @@ class LanguageBasePluginTest extends Specification {
project.extensions.findByName("sources") instanceof ProjectSourceSet
}
- def "registers the 'ResourceSet' type for each functional source set added to the 'sources' container"() {
+ def "creates a lifecycle task for each binary"() {
+ def binary = Mock(BinaryInternal)
+ def namingScheme = Mock(BinaryNamingScheme)
+
when:
- project.sources.create("custom")
- project.sources.custom.create("resources", ResourceSet)
+ project.extensions.findByType(BinaryContainer).add(binary)
then:
- project.sources.custom.resources instanceof ResourceSet
+ _ * binary.name >> "binaryName"
+ 1 * binary.namingScheme >> namingScheme
+ 1 * namingScheme.lifecycleTaskName >> "lifecycle"
+ 1 * binary.setLifecycleTask({it == project.tasks.findByName("lifecycle")})
}
}
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/WarPluginTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/WarPluginTest.groovy
index 0e1b351..359aa23 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/WarPluginTest.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/WarPluginTest.groovy
@@ -21,24 +21,22 @@ import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.Dependency
import org.gradle.api.internal.artifacts.configurations.Configurations
import org.gradle.api.tasks.bundling.War
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import org.junit.Before
import org.junit.Test
+
import static org.gradle.util.Matchers.dependsOn
import static org.gradle.util.WrapUtil.toSet
import static org.hamcrest.Matchers.*
import static org.junit.Assert.*
-/**
- * @author Hans Dockter
- */
class WarPluginTest {
- private Project project // = HelperUtil.createRootProject()
+ private Project project // = TestUtil.createRootProject()
private WarPlugin warPlugin// = new WarPlugin()
@Before
public void setUp() {
- project = HelperUtil.createRootProject()
+ project = TestUtil.createRootProject()
warPlugin = new WarPlugin()
}
@@ -88,7 +86,7 @@ class WarPluginTest {
@Test public void dependsOnRuntimeConfig() {
warPlugin.apply(project)
- Project childProject = HelperUtil.createChildProject(project, 'child')
+ Project childProject = TestUtil.createChildProject(project, 'child')
JavaPlugin javaPlugin = new JavaPlugin()
javaPlugin.apply(childProject)
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/GroovyRuntimeTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/GroovyRuntimeTest.groovy
new file mode 100644
index 0000000..27cebdd
--- /dev/null
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/GroovyRuntimeTest.groovy
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.tasks
+
+import org.gradle.api.GradleException
+import org.gradle.api.artifacts.Configuration
+import org.gradle.api.internal.file.collections.LazilyInitializedFileCollection
+import org.gradle.api.plugins.GroovyBasePlugin
+import org.gradle.util.TestUtil
+import spock.lang.Specification
+
+class GroovyRuntimeTest extends Specification {
+ def project = TestUtil.createRootProject()
+
+ def setup() {
+ project.plugins.apply(GroovyBasePlugin)
+ }
+
+ GroovyRuntime getGroovyRuntime() {
+ project.extensions.getByType(GroovyRuntime)
+ }
+
+ def "inferred Groovy class path uses same 'groovy-all' Jar that is found on class path"() {
+ when:
+ def classpath = project.groovyRuntime.inferGroovyClasspath([project.file("other.jar"), project.file("groovy-all-2.1.2${classifier}.jar")])
+
+ then:
+ classpath.singleFile == project.file("groovy-all-2.1.2${classifier}.jar")
+
+ where:
+ classifier << ["", "-indy"]
+ }
+
+ def "inferred Groovy class path uses repository dependency if 'groovy' Jar is found on class path (to get transitive dependencies right)"() {
+ project.repositories {
+ mavenCentral()
+ }
+
+ when:
+ def classpath = project.groovyRuntime.inferGroovyClasspath([project.file("other.jar"), project.file("groovy-2.1.2${classifier}.jar")])
+
+ then:
+ classpath instanceof LazilyInitializedFileCollection
+ with(classpath.delegate) {
+ it instanceof Configuration
+ state == Configuration.State.UNRESOLVED
+ dependencies.size() == 2
+ dependencies.any { it.group == "org.codehaus.groovy" && it.name == "groovy" && it.version == "2.1.2" } // not sure how to check classifier
+ dependencies.any { it.group == "org.codehaus.groovy" && it.name == "groovy-ant" && it.version == "2.1.2" } // not sure how to check classifier
+ }
+
+ where:
+ classifier << ["", "-indy"]
+ }
+
+ def "inferred Groovy class path falls back to contents of 'groovy' configuration if the latter is explicitly configured"() {
+ project.dependencies {
+ groovy project.files("my-groovy.jar")
+ }
+
+ when:
+ def classpath = project.groovyRuntime.inferGroovyClasspath([project.file("other.jar"), project.file("groovy-all-2.1.2.jar")])
+
+ then:
+ classpath.singleFile.name == "my-groovy.jar"
+ }
+
+ def "inferred Groovy class path falls back to contents of 'groovy' configuration if no Groovy Jar found on class path"() {
+ project.dependencies {
+ groovy project.files("my-groovy.jar")
+ }
+
+ when:
+ def classpath = project.groovyRuntime.inferGroovyClasspath([project.file("other.jar"), project.file("other2.jar")])
+
+ then:
+ classpath.singleFile.name == "my-groovy.jar"
+ }
+
+ def "inferred Groovy class path falls back to contents of 'groovy' configuration if 'groovy' Jar found and no repository declared"() {
+ project.dependencies {
+ groovy project.files("my-groovy.jar")
+ }
+
+ when:
+ def classpath = project.groovyRuntime.inferGroovyClasspath([project.file("other.jar"), project.file("groovy-2.1.2.jar")])
+
+ then:
+ classpath.singleFile.name == "my-groovy.jar"
+ }
+
+ def "useful error message is produced when no groovy runtime could be found on a classpath"() {
+ given:
+ def classpath = [project.file("other.jar")]
+
+ when:
+ groovyRuntime.inferGroovyClasspath(classpath).files
+
+ then:
+ def exception = thrown(GradleException)
+ exception.message.contains "no Groovy Jar was found on class path: $classpath"
+ }
+}
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/application/CreateStartScriptsTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/application/CreateStartScriptsTest.groovy
index 9a7912a..9f95392 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/application/CreateStartScriptsTest.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/application/CreateStartScriptsTest.groovy
@@ -16,10 +16,10 @@
package org.gradle.api.tasks.application
import spock.lang.Specification
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
class CreateStartScriptsTest extends Specification {
- final CreateStartScripts task = HelperUtil.createTask(CreateStartScripts.class)
+ final CreateStartScripts task = TestUtil.createTask(CreateStartScripts.class)
def scriptNameDefaultsToApplicationName() {
task.outputDir = new File('output')
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/bundling/JarTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/bundling/JarTest.groovy
index 1216a14..1f9dd44 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/bundling/JarTest.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/bundling/JarTest.groovy
@@ -19,12 +19,10 @@ package org.gradle.api.tasks.bundling
import org.gradle.api.java.archives.internal.DefaultManifest
import org.junit.Before
import org.junit.Test
+
import static org.junit.Assert.assertEquals
import static org.junit.Assert.assertNotNull
-/**
- * @author Hans Dockter
- */
class JarTest extends AbstractArchiveTaskTest {
Jar jar
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/bundling/WarTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/bundling/WarTest.groovy
index 5eae4de..c95e78a 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/bundling/WarTest.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/bundling/WarTest.groovy
@@ -18,11 +18,9 @@ package org.gradle.api.tasks.bundling
import org.junit.Before
import org.junit.Test
+
import static org.junit.Assert.assertEquals
-/**
- * @author Hans Dockter
- */
class WarTest extends AbstractArchiveTaskTest {
War war
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/compile/CompileOptionsTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/compile/CompileOptionsTest.groovy
index 21d04a0..8eee899 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/compile/CompileOptionsTest.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/compile/CompileOptionsTest.groovy
@@ -18,12 +18,10 @@ package org.gradle.api.tasks.compile
import org.junit.Before
import org.junit.Test
-import static org.junit.Assert.*;
-import static org.gradle.util.Matchers.*
-/**
- * @author Hans Dockter
- */
+import static org.gradle.util.Matchers.isEmpty
+import static org.junit.Assert.*
+
class CompileOptionsTest {
static final Map TEST_DEBUG_OPTION_MAP = [someDebugOption: 'someDebugOptionValue']
static final Map TEST_FORK_OPTION_MAP = [someForkOption: 'someForkOptionValue']
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/compile/DebugOptionsTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/compile/DebugOptionsTest.groovy
index e0ba8aa..353aaa6 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/compile/DebugOptionsTest.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/compile/DebugOptionsTest.groovy
@@ -18,9 +18,6 @@ package org.gradle.api.tasks.compile
import org.junit.Test
-/**
- * @author Hans Dockter
- */
class DebugOptionsTest {
DebugOptions debugOptions = new DebugOptions()
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/compile/ForkOptionsTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/compile/ForkOptionsTest.groovy
index e6a8991..d60fe05 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/compile/ForkOptionsTest.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/compile/ForkOptionsTest.groovy
@@ -16,13 +16,11 @@
package org.gradle.api.tasks.compile
-import static org.junit.Assert.*
import org.junit.Before
import org.junit.Test
-/**
- * @author Hans Dockter
- */
+import static org.junit.Assert.assertEquals
+
class ForkOptionsTest {
static final List PROPS = ['executable', 'memoryInitialSize', 'memoryMaximumSize', 'tempDir']
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/compile/GroovyCompileOptionsTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/compile/GroovyCompileOptionsTest.groovy
index f88fedf..c64fb7e 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/compile/GroovyCompileOptionsTest.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/compile/GroovyCompileOptionsTest.groovy
@@ -16,13 +16,11 @@
package org.gradle.api.tasks.compile
-import org.junit.Test
import org.junit.Before
+import org.junit.Test
+
import static org.junit.Assert.*
-/**
- * @author Hans Dockter
- */
class GroovyCompileOptionsTest {
static final Map TEST_FORK_OPTION_MAP = [someForkOption: 'someForkOptionValue']
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/compile/GroovyCompileTest.java b/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/compile/GroovyCompileTest.java
index 65efbe0..e4ed4f5 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/compile/GroovyCompileTest.java
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/compile/GroovyCompileTest.java
@@ -33,12 +33,9 @@ import org.junit.runner.RunWith;
import java.io.File;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.junit.Assert.*;
-/**
- * @author Hans Dockter
- */
@RunWith(org.jmock.integration.junit4.JMock.class)
public class GroovyCompileTest extends AbstractCompileTest {
@@ -91,10 +88,15 @@ public class GroovyCompileTest extends AbstractCompileTest {
assertFalse(testObj.getDidWork());
}
- @Test(expected = InvalidUserDataException.class)
+ @Test
public void testMoansIfGroovyClasspathIsEmpty() {
setUpMocksAndAttributes(testObj, true);
- testObj.compile();
+ try {
+ testObj.compile();
+ fail();
+ } catch (InvalidUserDataException e) {
+ assertThat(e.getMessage(), containsString("'testTask.groovyClasspath' must not be empty."));
+ }
}
void setUpMocksAndAttributes(GroovyCompile compile, final boolean groovyClasspathEmpty) {
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/compile/GroovyForkOptionsTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/compile/GroovyForkOptionsTest.groovy
index 66ef05b..4b3a0b2 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/compile/GroovyForkOptionsTest.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/compile/GroovyForkOptionsTest.groovy
@@ -15,13 +15,11 @@
*/
package org.gradle.api.tasks.compile
+import org.junit.Before
import org.junit.Test
-import org.junit.Before;
+
import static org.junit.Assert.*
-/**
- * @author Hans Dockter
- */
public class GroovyForkOptionsTest {
static final Map PROPS = [memoryInitialSize: 'memoryInitialSize', memoryMaximumSize: 'memoryMaximumSize']
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/compile/JavaCompileTest.java b/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/compile/JavaCompileTest.java
index bd1afa7..1be1aba 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/compile/JavaCompileTest.java
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/compile/JavaCompileTest.java
@@ -34,9 +34,6 @@ import java.io.File;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-/**
- * @author Hans Dockter
- */
@RunWith(org.jmock.integration.junit4.JMock.class)
public class JavaCompileTest extends AbstractCompileTest {
private JavaCompile compile;
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/javadoc/GroovydocTest.java b/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/javadoc/GroovydocTest.java
index 111e76d..a1f1ea2 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/javadoc/GroovydocTest.java
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/javadoc/GroovydocTest.java
@@ -15,8 +15,6 @@
*/
package org.gradle.api.tasks.javadoc;
-import java.util.Set;
-
import org.gradle.api.InvalidUserDataException;
import org.gradle.api.internal.ConventionTask;
import org.gradle.api.internal.file.collections.SimpleFileCollection;
@@ -25,12 +23,11 @@ import org.gradle.util.WrapUtil;
import org.junit.Before;
import org.junit.Test;
+import java.util.Set;
+
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
-/**
- * @author Hans Dockter
- */
public class GroovydocTest extends AbstractConventionTaskTest {
private Groovydoc groovydoc;
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/javadoc/JavadocTest.java b/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/javadoc/JavadocTest.java
index 94c1737..b408421 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/javadoc/JavadocTest.java
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/javadoc/JavadocTest.java
@@ -76,7 +76,7 @@ public class JavadocTest extends AbstractConventionTaskTest {
will(returnValue(javadocExecHandleBuilderMock));
one(javadocExecHandleBuilderMock).options(task.getOptions());
will(returnValue(javadocExecHandleBuilderMock));
- one(javadocExecHandleBuilderMock).optionsFile(new File(getProject().getBuildDir(), "tmp/taskname/javadoc.options"));
+ one(javadocExecHandleBuilderMock).optionsFile(new File(getProject().getBuildDir(), "tmp/testTask/javadoc.options"));
will(returnValue(javadocExecHandleBuilderMock));
one(javadocExecHandleBuilderMock).getExecHandle();
will(returnValue(execActionMock));
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/testing/AbstractTestFrameworkOptionsTest.java b/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/testing/AbstractTestFrameworkOptionsTest.java
index 75dd311..5a29ce6 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/testing/AbstractTestFrameworkOptionsTest.java
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/testing/AbstractTestFrameworkOptionsTest.java
@@ -20,9 +20,6 @@ import org.gradle.api.internal.tasks.testing.TestFramework;
import org.gradle.util.JUnit4GroovyMockery;
import org.jmock.lib.legacy.ClassImposteriser;
-/**
- * @author Tom Eyckmans
- */
public class AbstractTestFrameworkOptionsTest<T extends TestFramework> {
protected JUnit4GroovyMockery context = new JUnit4GroovyMockery();
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/testing/TestReportTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/testing/TestReportTest.groovy
index 8db4e9d..f173d89 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/testing/TestReportTest.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/testing/TestReportTest.groovy
@@ -16,13 +16,13 @@
package org.gradle.api.tasks.testing
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import org.junit.Rule
import spock.lang.Specification
class TestReportTest extends Specification {
@Rule TestNameTestDirectoryProvider tmp
- def reportTask = HelperUtil.createTask(TestReport)
+ def reportTask = TestUtil.createTask(TestReport)
def "infers dependencies and results dirs from input tests"() {
def test1 = test("test1")
@@ -49,7 +49,7 @@ class TestReportTest extends Specification {
}
def test(String name) {
- def test = HelperUtil.createTask(Test, HelperUtil.createRootProject(), name)
+ def test = TestUtil.createTask(Test, TestUtil.createRootProject(), name)
test.binResultsDir = tmp.file(name)
return test
}
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/testing/TestTaskSpec.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/testing/TestTaskSpec.groovy
index 4ba1207..28e19d3 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/testing/TestTaskSpec.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/testing/TestTaskSpec.groovy
@@ -21,12 +21,9 @@ import org.gradle.api.internal.tasks.testing.TestResultProcessor
import org.gradle.api.internal.tasks.testing.detection.TestExecuter
import org.gradle.api.internal.tasks.testing.junit.report.TestReporter
import org.gradle.listener.ListenerBroadcast
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 12/7/12
- */
class TestTaskSpec extends Specification {
private testExecuter = Mock(TestExecuter)
@@ -34,7 +31,7 @@ class TestTaskSpec extends Specification {
private testListenerBroadcaster = Mock(ListenerBroadcast)
private testOutputListenerBroadcaster = Mock(ListenerBroadcast)
- private task = HelperUtil.createTask(Test, [testExecuter: testExecuter, testFramework: testFramework,
+ private task = TestUtil.createTask(Test, [testExecuter: testExecuter, testFramework: testFramework,
testListenerBroadcaster: testListenerBroadcaster, testOutputListenerBroadcaster: testOutputListenerBroadcaster])
public setup(){
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/testing/TestTest.java b/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/testing/TestTest.java
index 5b69a28..b12159d 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/testing/TestTest.java
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/testing/TestTest.java
@@ -37,7 +37,7 @@ import org.gradle.api.internal.tasks.testing.results.TestListenerAdapter;
import org.gradle.api.tasks.AbstractConventionTaskTest;
import org.gradle.process.internal.WorkerProcessBuilder;
import org.gradle.util.GFileUtils;
-import org.gradle.util.HelperUtil;
+import org.gradle.util.TestUtil;
import org.gradle.util.TestClosure;
import org.hamcrest.Description;
import org.jmock.Expectations;
@@ -62,9 +62,6 @@ import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
-/**
- * @author Hans Dockter
- */
@RunWith(JMock.class)
public class TestTest extends AbstractConventionTaskTest {
static final String TEST_PATTERN_1 = "pattern1";
@@ -242,7 +239,7 @@ public class TestTest extends AbstractConventionTaskTest {
@org.junit.Test
public void notifiesListenerBeforeSuite() {
final TestClosure closure = context.mock(TestClosure.class);
- test.beforeSuite(HelperUtil.toClosure(closure));
+ test.beforeSuite(TestUtil.toClosure(closure));
final TestDescriptor testDescriptor = context.mock(TestDescriptor.class);
@@ -256,7 +253,7 @@ public class TestTest extends AbstractConventionTaskTest {
@org.junit.Test
public void notifiesListenerAfterSuite() {
final TestClosure closure = context.mock(TestClosure.class);
- test.afterSuite(HelperUtil.toClosure(closure));
+ test.afterSuite(TestUtil.toClosure(closure));
final TestDescriptor testDescriptor = context.mock(TestDescriptor.class);
final TestResult result = context.mock(TestResult.class);
@@ -271,7 +268,7 @@ public class TestTest extends AbstractConventionTaskTest {
@org.junit.Test
public void notifiesListenerBeforeTest() {
final TestClosure closure = context.mock(TestClosure.class);
- test.beforeTest(HelperUtil.toClosure(closure));
+ test.beforeTest(TestUtil.toClosure(closure));
final TestDescriptor testDescriptor = context.mock(TestDescriptor.class);
@@ -285,7 +282,7 @@ public class TestTest extends AbstractConventionTaskTest {
@org.junit.Test
public void notifiesListenerAfterTest() {
final TestClosure closure = context.mock(TestClosure.class);
- test.afterTest(HelperUtil.toClosure(closure));
+ test.afterTest(TestUtil.toClosure(closure));
final TestDescriptor testDescriptor = context.mock(TestDescriptor.class);
final TestResult result = context.mock(TestResult.class);
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/testing/testng/TestNGOptionsTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/testing/testng/TestNGOptionsTest.groovy
index fe2a0c9..31b0993 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/testing/testng/TestNGOptionsTest.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/testing/testng/TestNGOptionsTest.groovy
@@ -15,17 +15,14 @@
*/
package org.gradle.api.tasks.testing.testng
-import org.junit.Before
-import org.junit.Test
-import static org.junit.Assert.*;
-import static org.hamcrest.Matchers.*
-import org.gradle.api.tasks.testing.AbstractTestFrameworkOptionsTest
import org.gradle.api.JavaVersion
import org.gradle.api.internal.tasks.testing.testng.TestNGTestFramework
+import org.gradle.api.tasks.testing.AbstractTestFrameworkOptionsTest
+import org.junit.Before
+import org.junit.Test
-/**
- * @author Tom Eyckmans
- */
+import static org.hamcrest.Matchers.hasItems
+import static org.junit.Assert.*
public class TestNGOptionsTest extends AbstractTestFrameworkOptionsTest<TestNGTestFramework> {
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/wrapper/WrapperTest.java b/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/wrapper/WrapperTest.java
deleted file mode 100644
index 508b20c..0000000
--- a/subprojects/plugins/src/test/groovy/org/gradle/api/tasks/wrapper/WrapperTest.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.tasks.wrapper;
-
-import org.gradle.api.internal.AbstractTask;
-import org.gradle.api.tasks.AbstractTaskTest;
-import org.gradle.test.fixtures.file.TestFile;
-import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider;
-import org.gradle.util.GUtil;
-import org.gradle.util.GradleVersion;
-import org.gradle.util.WrapUtil;
-import org.gradle.wrapper.GradleWrapperMain;
-import org.gradle.wrapper.WrapperExecutor;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Properties;
-
-import static org.hamcrest.Matchers.equalTo;
-import static org.junit.Assert.*;
-
-/**
- * @author Hans Dockter
- */
-public class WrapperTest extends AbstractTaskTest {
-
- private Wrapper wrapper;
- private String targetWrapperJarPath;
- private TestFile expectedTargetWrapperJar;
- private File expectedTargetWrapperProperties;
- @Rule
- public TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider();
-
- @Before
- public void setUp() {
- wrapper = createTask(Wrapper.class);
- wrapper.setGradleVersion("1.0");
- targetWrapperJarPath = "gradle/wrapper";
- expectedTargetWrapperJar = new TestFile(getProject().getProjectDir(),
- targetWrapperJarPath + "/gradle-wrapper.jar");
- expectedTargetWrapperProperties = new File(getProject().getProjectDir(),
- targetWrapperJarPath + "/gradle-wrapper.properties");
- new File(getProject().getProjectDir(), targetWrapperJarPath).mkdirs();
- wrapper.setDistributionPath("somepath");
- }
-
- public AbstractTask getTask() {
- return wrapper;
- }
-
- @Test
- public void testWrapperDefaults() {
- wrapper = createTask(Wrapper.class);
- assertEquals(new File(getProject().getProjectDir(), "gradle/wrapper/gradle-wrapper.jar"), wrapper.getJarFile());
- assertEquals(new File(getProject().getProjectDir(), "gradlew"), wrapper.getScriptFile());
- assertEquals(new File(getProject().getProjectDir(), "gradlew.bat"), wrapper.getBatchScript());
- assertEquals(GradleVersion.current().getVersion(), wrapper.getGradleVersion());
- assertEquals(Wrapper.DEFAULT_DISTRIBUTION_PARENT_NAME, wrapper.getDistributionPath());
- assertEquals(Wrapper.DEFAULT_DISTRIBUTION_PARENT_NAME, wrapper.getArchivePath());
- assertEquals(Wrapper.PathBase.GRADLE_USER_HOME, wrapper.getDistributionBase());
- assertEquals(Wrapper.PathBase.GRADLE_USER_HOME, wrapper.getArchiveBase());
- assertNotNull(wrapper.getDistributionUrl());
- }
-
- @Test
- public void testDeterminesWindowsScriptPathFromUnixScriptPath() {
- wrapper.setScriptFile("build/gradle.sh");
- assertEquals(getProject().file("build/gradle.bat"), wrapper.getBatchScript());
-
- wrapper.setScriptFile("build/gradle-wrapper");
- assertEquals(getProject().file("build/gradle-wrapper.bat"), wrapper.getBatchScript());
- }
-
- @Test
- public void testDeterminesPropertiesFilePathFromJarPath() {
- wrapper.setJarFile("build/gradle-wrapper.jar");
- assertEquals(getProject().file("build/gradle-wrapper.properties"), wrapper.getPropertiesFile());
- }
-
- @Test
- public void testDownloadsFromReleaseRepositoryForReleaseVersions() {
- wrapper.setGradleVersion("0.9.1");
- assertEquals("http://services.gradle.org/distributions/gradle-0.9.1-bin.zip", wrapper.getDistributionUrl());
- }
-
- @Test
- public void testDownloadsFromReleaseRepositoryForPreviewReleaseVersions() {
- wrapper.setGradleVersion("1.0-milestone-1");
- assertEquals("http://services.gradle.org/distributions/gradle-1.0-milestone-1-bin.zip", wrapper.getDistributionUrl());
- }
-
- @Test
- public void testDownloadsFromSnapshotRepositoryForSnapshotVersions() {
- wrapper.setGradleVersion("0.9.1-20101224110000+1100");
- assertEquals("http://services.gradle.org/distributions-snapshots/gradle-0.9.1-20101224110000+1100-bin.zip", wrapper.getDistributionUrl());
- }
-
- @Test
- public void testUsesExplicitlyDefinedDistributionUrl() {
- wrapper.setGradleVersion("0.9");
- wrapper.setDistributionUrl("http://some-url");
- assertEquals("http://some-url", wrapper.getDistributionUrl());
- }
-
- @Test
- public void testExecuteWithNonExistingWrapperJarParentDir() throws IOException {
- checkExecute();
- }
-
- @Test
- public void testCheckInputs() throws IOException {
- assertThat(wrapper.getInputs().getProperties().keySet(),
- equalTo(WrapUtil.toSet("distributionBase", "distributionPath", "distributionUrl", "archiveBase", "archivePath")));
- }
-
- @Test
- public void testExecuteWithExistingWrapperJarParentDirAndExistingWrapperJar() throws IOException {
- File jarDir = new File(getProject().getProjectDir(), "lib");
- jarDir.mkdirs();
- File wrapperJar = new File(getProject().getProjectDir(), targetWrapperJarPath);
- File parentFile = expectedTargetWrapperJar.getParentFile();
- assertTrue(parentFile.isDirectory() || parentFile.mkdirs());
- try {
- assertTrue(expectedTargetWrapperJar.createNewFile());
- } catch (IOException e) {
- throw new RuntimeException(String.format("Could not create %s.", wrapperJar), e);
- }
- checkExecute();
- }
-
- private void checkExecute() throws IOException {
- wrapper.execute();
- TestFile unjarDir = tmpDir.createDir("unjar");
- expectedTargetWrapperJar.unzipTo(unjarDir);
- unjarDir.file(GradleWrapperMain.class.getName().replace(".", "/") + ".class").assertIsFile();
- Properties properties = GUtil.loadProperties(expectedTargetWrapperProperties);
- assertEquals(properties.getProperty(WrapperExecutor.DISTRIBUTION_URL_PROPERTY), wrapper.getDistributionUrl());
- assertEquals(properties.getProperty(WrapperExecutor.DISTRIBUTION_BASE_PROPERTY), wrapper.getDistributionBase().toString());
- assertEquals(properties.getProperty(WrapperExecutor.DISTRIBUTION_PATH_PROPERTY), wrapper.getDistributionPath());
- assertEquals(properties.getProperty(WrapperExecutor.ZIP_STORE_BASE_PROPERTY), wrapper.getArchiveBase().toString());
- assertEquals(properties.getProperty(WrapperExecutor.ZIP_STORE_PATH_PROPERTY), wrapper.getArchivePath());
- }
-
- private String toNative(String s) {
- return s.replace("/", File.separator);
- }
-}
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/StandardJavadocDocletOptionsTest.java b/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/StandardJavadocDocletOptionsTest.java
index 5ef1024..83e1342 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/StandardJavadocDocletOptionsTest.java
+++ b/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/StandardJavadocDocletOptionsTest.java
@@ -16,23 +16,21 @@
package org.gradle.external.javadoc;
+import org.gradle.external.javadoc.internal.GroupsJavadocOptionFileOption;
+import org.gradle.external.javadoc.internal.JavadocOptionFile;
import org.gradle.external.javadoc.internal.LinksOfflineJavadocOptionFileOption;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.After;
-import static org.junit.Assert.*;
+import org.jmock.Expectations;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.jmock.lib.legacy.ClassImposteriser;
-import org.jmock.Expectations;
-import org.gradle.external.javadoc.internal.JavadocOptionFile;
-import org.gradle.external.javadoc.internal.GroupsJavadocOptionFileOption;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
-import java.util.*;
import java.io.File;
+import java.util.*;
+
+import static org.junit.Assert.*;
-/**
- * @author Tom Eyckmans
- */
public class StandardJavadocDocletOptionsTest {
private final JUnit4Mockery context = new JUnit4Mockery();
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/BooleanJavadocOptionFileOptionTest.java b/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/BooleanJavadocOptionFileOptionTest.java
index 0d4ee00..5d0f84f 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/BooleanJavadocOptionFileOptionTest.java
+++ b/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/BooleanJavadocOptionFileOptionTest.java
@@ -16,17 +16,14 @@
package org.gradle.external.javadoc.internal;
-import org.junit.Before;
-import org.junit.Test;
+import org.jmock.Expectations;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.jmock.lib.legacy.ClassImposteriser;
-import org.jmock.Expectations;
+import org.junit.Before;
+import org.junit.Test;
import java.io.IOException;
-/**
- * @author Tom Eyckmans
- */
public class BooleanJavadocOptionFileOptionTest {
private final JUnit4Mockery context = new JUnit4Mockery();
private JavadocOptionFileWriterContext writerContextMock;
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/EnumJavadocOptionFileOptionTest.java b/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/EnumJavadocOptionFileOptionTest.java
index 1388066..4e35abb 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/EnumJavadocOptionFileOptionTest.java
+++ b/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/EnumJavadocOptionFileOptionTest.java
@@ -16,18 +16,15 @@
package org.gradle.external.javadoc.internal;
+import org.gradle.external.javadoc.JavadocMemberLevel;
+import org.jmock.Expectations;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.jmock.lib.legacy.ClassImposteriser;
-import org.jmock.Expectations;
import org.junit.Before;
import org.junit.Test;
-import org.gradle.external.javadoc.JavadocMemberLevel;
import java.io.IOException;
-/**
- * @author Tom Eyckmans
- */
public class EnumJavadocOptionFileOptionTest {
private final JUnit4Mockery context = new JUnit4Mockery();
private JavadocOptionFileWriterContext writerContextMock;
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/FileJavadocOptionFileOptionTest.java b/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/FileJavadocOptionFileOptionTest.java
index 1916bcb..57c8851 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/FileJavadocOptionFileOptionTest.java
+++ b/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/FileJavadocOptionFileOptionTest.java
@@ -16,18 +16,15 @@
package org.gradle.external.javadoc.internal;
+import org.jmock.Expectations;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.jmock.lib.legacy.ClassImposteriser;
-import org.jmock.Expectations;
import org.junit.Before;
import org.junit.Test;
-import java.io.IOException;
import java.io.File;
+import java.io.IOException;
-/**
- * @author Tom Eyckmans
- */
public class FileJavadocOptionFileOptionTest {
private final JUnit4Mockery context = new JUnit4Mockery();
private JavadocOptionFileWriterContext writerContextMock;
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/GroupsJavadocOptionFileOptionTest.java b/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/GroupsJavadocOptionFileOptionTest.java
index e2dae37..948a02d 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/GroupsJavadocOptionFileOptionTest.java
+++ b/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/GroupsJavadocOptionFileOptionTest.java
@@ -16,19 +16,16 @@
package org.gradle.external.javadoc.internal;
+import org.jmock.Expectations;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.jmock.lib.legacy.ClassImposteriser;
-import org.jmock.Expectations;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
-import java.util.List;
import java.util.Arrays;
+import java.util.List;
-/**
- * @author Tom Eyckmans
- */
public class GroupsJavadocOptionFileOptionTest {
private final JUnit4Mockery context = new JUnit4Mockery();
private JavadocOptionFileWriterContext writerContextMock;
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/JavadocExecHandleBuilderTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/JavadocExecHandleBuilderTest.groovy
index 2f2261d..4076433 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/JavadocExecHandleBuilderTest.groovy
+++ b/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/JavadocExecHandleBuilderTest.groovy
@@ -14,18 +14,15 @@
* limitations under the License.
*/
-package org.gradle.external.javadoc.internal;
-
+package org.gradle.external.javadoc.internal
+import org.gradle.external.javadoc.MinimalJavadocOptions
import org.gradle.internal.jvm.Jvm
import org.junit.Test
import spock.lang.Specification
+
import static org.junit.Assert.assertTrue
-import org.gradle.external.javadoc.MinimalJavadocOptions
-/**
- * @author Tom Eyckmans
- */
public class JavadocExecHandleBuilderTest extends Specification {
private JavadocExecHandleBuilder javadocExecHandleBuilder = new JavadocExecHandleBuilder()
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/JavadocOptionFileTest.java b/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/JavadocOptionFileTest.java
index a221d96..e35a515 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/JavadocOptionFileTest.java
+++ b/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/JavadocOptionFileTest.java
@@ -25,9 +25,6 @@ import org.junit.Test;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
-/**
- * @author Tom Eyckmans
- */
public class JavadocOptionFileTest {
private final JUnit4Mockery context = new JUnit4GroovyMockery();
@SuppressWarnings("unchecked")
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/JavadocOptionFileWriterContextTest.java b/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/JavadocOptionFileWriterContextTest.java
index 097bf81..65a5eee 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/JavadocOptionFileWriterContextTest.java
+++ b/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/JavadocOptionFileWriterContextTest.java
@@ -16,19 +16,16 @@
package org.gradle.external.javadoc.internal;
+import org.gradle.util.WrapUtil;
+import org.jmock.Expectations;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.jmock.lib.legacy.ClassImposteriser;
-import org.jmock.Expectations;
import org.junit.Before;
import org.junit.Test;
-import org.gradle.util.WrapUtil;
import java.io.BufferedWriter;
import java.io.IOException;
-/**
- * @author Tom Eyckmans
- */
public class JavadocOptionFileWriterContextTest {
private final JUnit4Mockery context = new JUnit4Mockery();
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/LinksOfflineJavadocOptionFileOptionTest.java b/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/LinksOfflineJavadocOptionFileOptionTest.java
index 36ea5e5..95ba46e 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/LinksOfflineJavadocOptionFileOptionTest.java
+++ b/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/LinksOfflineJavadocOptionFileOptionTest.java
@@ -16,18 +16,15 @@
package org.gradle.external.javadoc.internal;
+import org.gradle.external.javadoc.JavadocOfflineLink;
+import org.jmock.Expectations;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.jmock.lib.legacy.ClassImposteriser;
-import org.jmock.Expectations;
import org.junit.Before;
import org.junit.Test;
-import org.gradle.external.javadoc.JavadocOfflineLink;
import java.io.IOException;
-/**
- * @author Tom Eyckmans
- */
public class LinksOfflineJavadocOptionFileOptionTest {
private final JUnit4Mockery context = new JUnit4Mockery();
private JavadocOptionFileWriterContext writerContextMock;
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/MultilineStringsJavadocOptionFileOptionTest.java b/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/MultilineStringsJavadocOptionFileOptionTest.java
index 51a6b3b..324b7ec 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/MultilineStringsJavadocOptionFileOptionTest.java
+++ b/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/MultilineStringsJavadocOptionFileOptionTest.java
@@ -16,9 +16,9 @@
package org.gradle.external.javadoc.internal;
+import org.jmock.Expectations;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.jmock.lib.legacy.ClassImposteriser;
-import org.jmock.Expectations;
import org.junit.Before;
import org.junit.Test;
@@ -26,9 +26,6 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
-/**
- * @author Melanie Pfautz
- */
public class MultilineStringsJavadocOptionFileOptionTest {
private final JUnit4Mockery context = new JUnit4Mockery();
private JavadocOptionFileWriterContext writerContextMock;
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/OptionLessStringsJavadocOptionFileOptionTest.java b/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/OptionLessStringsJavadocOptionFileOptionTest.java
index eac4d65..afbf7e0 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/OptionLessStringsJavadocOptionFileOptionTest.java
+++ b/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/OptionLessStringsJavadocOptionFileOptionTest.java
@@ -16,17 +16,14 @@
package org.gradle.external.javadoc.internal;
+import org.jmock.Expectations;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.jmock.lib.legacy.ClassImposteriser;
-import org.jmock.Expectations;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
-/**
- * @author Tom Eyckmans
- */
public class OptionLessStringsJavadocOptionFileOptionTest {
private final JUnit4Mockery context = new JUnit4Mockery();
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/PathJavadocOptionFileOptionTest.java b/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/PathJavadocOptionFileOptionTest.java
index 35238bd..03c6dcb 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/PathJavadocOptionFileOptionTest.java
+++ b/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/PathJavadocOptionFileOptionTest.java
@@ -16,18 +16,15 @@
package org.gradle.external.javadoc.internal;
+import org.jmock.Expectations;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.jmock.lib.legacy.ClassImposteriser;
-import org.jmock.Expectations;
import org.junit.Before;
import org.junit.Test;
-import java.io.IOException;
import java.io.File;
+import java.io.IOException;
-/**
- * @author Tom Eyckmans
- */
public class PathJavadocOptionFileOptionTest {
private final JUnit4Mockery context = new JUnit4Mockery();
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/StringJavadocOptionFileOptionTest.java b/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/StringJavadocOptionFileOptionTest.java
index 65c64b6..1ca2994 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/StringJavadocOptionFileOptionTest.java
+++ b/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/StringJavadocOptionFileOptionTest.java
@@ -16,17 +16,14 @@
package org.gradle.external.javadoc.internal;
+import org.jmock.Expectations;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.jmock.lib.legacy.ClassImposteriser;
-import org.jmock.Expectations;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
-/**
- * @author Tom Eyckmans
- */
public class StringJavadocOptionFileOptionTest {
private final JUnit4Mockery context = new JUnit4Mockery();
private JavadocOptionFileWriterContext writerContextMock;
diff --git a/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/StringsJavadocOptionFileOptionTest.java b/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/StringsJavadocOptionFileOptionTest.java
index e5e58a2..9bae650 100644
--- a/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/StringsJavadocOptionFileOptionTest.java
+++ b/subprojects/plugins/src/test/groovy/org/gradle/external/javadoc/internal/StringsJavadocOptionFileOptionTest.java
@@ -16,17 +16,14 @@
package org.gradle.external.javadoc.internal;
+import org.jmock.Expectations;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.jmock.lib.legacy.ClassImposteriser;
-import org.jmock.Expectations;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
-/**
- * @author Tom Eyckmans
- */
public class StringsJavadocOptionFileOptionTest {
private final JUnit4Mockery context = new JUnit4Mockery();
diff --git a/subprojects/plugins/src/testFixtures/groovy/org/gradle/api/internal/tasks/testing/BuildableTestMethodResult.groovy b/subprojects/plugins/src/testFixtures/groovy/org/gradle/api/internal/tasks/testing/BuildableTestMethodResult.groovy
new file mode 100644
index 0000000..7ff0f11
--- /dev/null
+++ b/subprojects/plugins/src/testFixtures/groovy/org/gradle/api/internal/tasks/testing/BuildableTestMethodResult.groovy
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.tasks.testing
+
+import org.gradle.api.internal.tasks.testing.junit.result.TestMethodResult
+import org.gradle.api.tasks.testing.TestOutputEvent
+import org.gradle.api.tasks.testing.TestResult
+
+class BuildableTestMethodResult extends TestMethodResult {
+ List<Throwable> exceptions = []
+
+ TestResult.ResultType resultType = TestResult.ResultType.SUCCESS
+
+ private final List<MethodTestOutputEvent> outputEvents
+
+ BuildableTestMethodResult(String name, List<MethodTestOutputEvent> outputEvents, TestResult result) {
+ super(name, result)
+ this.outputEvents = outputEvents
+ }
+
+ void failure(String message, String text = message) {
+ failure(new TestResultException(message, text))
+ }
+
+ void failure(Exception e) {
+ exceptions.add(e)
+ resultType = TestResult.ResultType.FAILURE
+ }
+
+ def stderr(String output) {
+ outputEvents << new MethodTestOutputEvent(name, new DefaultTestOutputEvent(TestOutputEvent.Destination.StdErr, output))
+ }
+
+ def stdout(String output) {
+ outputEvents << new MethodTestOutputEvent(name, new DefaultTestOutputEvent(TestOutputEvent.Destination.StdOut, output))
+ }
+
+ static class TestResultException extends Exception {
+
+ private final String message
+ private final String text
+
+ TestResultException(String message, String text) {
+ super(message)
+ this.text = text
+ }
+
+ String toString() {
+ return message
+ }
+
+ public void printStackTrace(PrintWriter s) {
+ s.print(text);
+ }
+ }
+
+}
diff --git a/subprojects/plugins/src/testFixtures/groovy/org/gradle/api/internal/tasks/testing/BuildableTestResultsProvider.groovy b/subprojects/plugins/src/testFixtures/groovy/org/gradle/api/internal/tasks/testing/BuildableTestResultsProvider.groovy
new file mode 100644
index 0000000..f89050e
--- /dev/null
+++ b/subprojects/plugins/src/testFixtures/groovy/org/gradle/api/internal/tasks/testing/BuildableTestResultsProvider.groovy
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.tasks.testing
+
+import org.gradle.api.Action
+import org.gradle.api.internal.tasks.testing.junit.result.TestClassResult
+import org.gradle.api.internal.tasks.testing.junit.result.TestMethodResult
+import org.gradle.api.internal.tasks.testing.junit.result.TestResultsProvider
+import org.gradle.api.tasks.testing.TestOutputEvent
+import org.gradle.api.tasks.testing.TestResult
+import org.gradle.util.ConfigureUtil
+
+import static org.gradle.api.tasks.testing.TestOutputEvent.Destination.StdErr
+import static org.gradle.api.tasks.testing.TestOutputEvent.Destination.StdOut
+
+class BuildableTestResultsProvider implements TestResultsProvider {
+
+ long timestamp = 0
+ Map<Long, BuildableTestClassResult> testClasses = [:]
+ long idCounter = 1
+
+ BuildableTestClassResult testClassResult(String className, Closure configClosure = {}) {
+ BuildableTestClassResult testSuite = new BuildableTestClassResult(idCounter++, className, timestamp)
+ testSuite.with(configClosure)
+ testClasses[testSuite.id] = testSuite
+ }
+
+ void writeAllOutput(long id, TestOutputEvent.Destination destination, Writer writer) {
+ doWrite(id, 0, true, destination, writer)
+ }
+
+ void writeNonTestOutput(long id, TestOutputEvent.Destination destination, Writer writer) {
+ doWrite(id, 0, false, destination, writer)
+ }
+
+ void writeTestOutput(long classId, long testId, TestOutputEvent.Destination destination, Writer writer) {
+ doWrite(classId, testId, false, destination, writer)
+ }
+
+ void doWrite(long classId, long testId, boolean allClassOutput, TestOutputEvent.Destination destination, Writer writer) {
+ BuildableTestClassResult testCase = testClasses[classId]
+ testCase.outputEvents.each { BuildableOutputEvent event ->
+ if (event.testOutputEvent.destination == destination && (allClassOutput || testId == event.testId)) {
+ writer.append(event.testOutputEvent.message)
+ }
+ }
+ }
+
+ void visitClasses(Action<? super TestClassResult> visitor) {
+ testClasses.values().each {
+ visitor.execute(it)
+ }
+ }
+
+ boolean isHasResults() {
+ !testClasses.isEmpty()
+ }
+
+ boolean hasOutput(long classId, TestOutputEvent.Destination destination) {
+ testClasses[classId]?.outputEvents?.find { it.testOutputEvent.destination == destination }
+ }
+
+ static class BuildableOutputEvent {
+ long testId
+ TestOutputEvent testOutputEvent
+
+ BuildableOutputEvent(long testId, TestOutputEvent testOutputEvent) {
+ this.testId = testId
+ this.testOutputEvent = testOutputEvent
+ }
+ }
+
+ class BuildableTestClassResult extends TestClassResult {
+ List<BuildableOutputEvent> outputEvents = []
+
+ long duration = 1000
+
+ BuildableTestClassResult(long id, String className, long startTime) {
+ super(id, className, startTime)
+ }
+
+ BuildableTestMethodResult testcase(String name, Closure configClosure = {}) {
+ BuildableTestMethodResult methodResult = new BuildableTestMethodResult(idCounter++, name, outputEvents, new SimpleTestResult())
+ add(methodResult)
+ ConfigureUtil.configure(configClosure, methodResult)
+ }
+
+ BuildableTestMethodResult testcase(long id, String name, Closure configClosure = {}) {
+ BuildableTestMethodResult methodResult = new BuildableTestMethodResult(id, name, outputEvents, new SimpleTestResult())
+ add(methodResult)
+ ConfigureUtil.configure(configClosure, methodResult)
+ }
+
+ def stderr(String output) {
+ outputEvents << new BuildableOutputEvent(0, new DefaultTestOutputEvent(StdErr, output))
+ }
+
+ def stdout(String output) {
+ outputEvents << new BuildableOutputEvent(0, new DefaultTestOutputEvent(StdOut, output))
+ }
+
+ @Override
+ long getDuration() {
+ this.duration
+ }
+ }
+
+ static class BuildableTestMethodResult extends TestMethodResult {
+
+ long duration
+ List<Throwable> exceptions = []
+
+ TestResult.ResultType resultType = TestResult.ResultType.SUCCESS
+
+ private final List<BuildableOutputEvent> outputEvents
+
+ BuildableTestMethodResult(long id, String name, List<BuildableOutputEvent> outputEvents, TestResult result) {
+ super(id, name, result)
+ this.outputEvents = outputEvents
+ duration = result.endTime - result.startTime;
+ }
+
+ void failure(String message, String text) {
+ exceptions.add(new TestResultException(message, text))
+ }
+
+ def stderr(String output) {
+ outputEvents << new BuildableOutputEvent(getId(), new DefaultTestOutputEvent(StdErr, output))
+ }
+
+ def stdout(String output) {
+ outputEvents << new BuildableOutputEvent(getId(), new DefaultTestOutputEvent(StdOut, output))
+ }
+ }
+
+ static class TestResultException extends Exception {
+
+ private final String message
+ private final String text
+
+ TestResultException(String message, String text) {
+ super(message)
+ this.text = text
+ }
+
+ String toString() {
+ return message
+ }
+
+ public void printStackTrace(PrintWriter s) {
+ s.print(text);
+ }
+ }
+
+ void close() throws IOException {
+ // nothing
+ }
+}
+
+
+
diff --git a/subprojects/plugins/src/testFixtures/groovy/org/gradle/api/internal/tasks/testing/MethodTestOutputEvent.groovy b/subprojects/plugins/src/testFixtures/groovy/org/gradle/api/internal/tasks/testing/MethodTestOutputEvent.groovy
new file mode 100644
index 0000000..65a6249
--- /dev/null
+++ b/subprojects/plugins/src/testFixtures/groovy/org/gradle/api/internal/tasks/testing/MethodTestOutputEvent.groovy
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.tasks.testing
+
+import org.gradle.api.tasks.testing.TestOutputEvent
+
+class MethodTestOutputEvent {
+ String testMethodName
+ TestOutputEvent testOutputEvent
+
+ MethodTestOutputEvent(String testMethodName, TestOutputEvent testOutputEvent) {
+ this.testMethodName = testMethodName
+ this.testOutputEvent = testOutputEvent
+ }
+}
diff --git a/subprojects/plugins/src/testFixtures/groovy/org/gradle/api/internal/tasks/testing/SimpleTestResult.groovy b/subprojects/plugins/src/testFixtures/groovy/org/gradle/api/internal/tasks/testing/SimpleTestResult.groovy
new file mode 100644
index 0000000..0213e5c
--- /dev/null
+++ b/subprojects/plugins/src/testFixtures/groovy/org/gradle/api/internal/tasks/testing/SimpleTestResult.groovy
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.tasks.testing
+
+import org.gradle.api.tasks.testing.TestResult
+
+class SimpleTestResult implements TestResult {
+ TestResult.ResultType resultType = TestResult.ResultType.SUCCESS
+ List<Throwable> exceptions = []
+ Throwable exception = exceptions[0]
+ long startTime = 0
+ long endTime = startTime + 100
+ long testCount = 1
+ long successfulTestCount = 1
+ long failedTestCount = 0
+ long skippedTestCount = 0
+
+ SimpleTestResult(long endTime = 100) {
+ this.endTime = endTime
+ }
+}
diff --git a/subprojects/plugins/src/testFixtures/groovy/org/gradle/api/internal/tasks/testing/junit/report/HtmlTestResultsFixture.groovy b/subprojects/plugins/src/testFixtures/groovy/org/gradle/api/internal/tasks/testing/junit/report/HtmlTestResultsFixture.groovy
new file mode 100644
index 0000000..50717d3
--- /dev/null
+++ b/subprojects/plugins/src/testFixtures/groovy/org/gradle/api/internal/tasks/testing/junit/report/HtmlTestResultsFixture.groovy
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.internal.tasks.testing.junit.report
+
+import org.gradle.test.fixtures.file.TestFile
+import org.jsoup.Jsoup
+import org.jsoup.nodes.Document
+import org.jsoup.nodes.Element
+
+class HtmlTestResultsFixture {
+ Document content
+
+ HtmlTestResultsFixture(TestFile file) {
+ file.assertIsFile()
+ content = Jsoup.parse(file, null)
+ }
+
+ void assertHasTests(int tests) {
+ def testDiv = content.select("div#tests")
+ assert testDiv != null
+ def counter = testDiv.select("div.counter")
+ assert counter != null
+ assert counter.text() == tests as String
+ }
+
+ void assertHasFailures(int tests) {
+ def testDiv = content.select("div#failures")
+ assert testDiv != null
+ def counter = testDiv.select("div.counter")
+ assert counter != null
+ assert counter.text() == tests as String
+ }
+
+ void assertHasDuration(String duration) {
+ def testDiv = content.select("div#duration")
+ assert testDiv != null
+ def counter = testDiv.select("div.counter")
+ assert counter != null
+ assert counter.text() == duration as String
+
+ }
+
+ void assertHasNoDuration() {
+ def testDiv = content.select("div#duration")
+ assert testDiv != null
+ def counter = testDiv.select("div.counter")
+ assert counter != null
+ assert counter.text() == "-"
+ }
+
+ void assertHasSuccessRate(int rate) {
+ def testDiv = content.select("div#successRate")
+ assert testDiv != null
+ def counter = testDiv.select("div.percent")
+ assert counter != null
+ assert counter.text() == "${rate}%"
+ }
+
+ void assertHasNoSuccessRate() {
+ def testDiv = content.select("div#successRate")
+ assert testDiv != null
+ def counter = testDiv.select("div.percent")
+ assert counter != null
+ assert counter.text() == "-"
+ }
+
+ void assertHasNoNavLinks() {
+ assert findTab('Packages').isEmpty()
+ }
+
+ void assertHasLinkTo(String target, String display = target) {
+ assert content.select("a[href=${target}.html]").find { it.text() == display }
+ }
+
+ void assertHasFailedTest(String className, String testName) {
+ def tab = findTab('Failed tests')
+ assert tab != null
+ assert tab.select("a[href=${className}.html#$testName]").find { it.text() == testName }
+ }
+
+ void assertHasTest(String testName) {
+ assert findTestDetails(testName)
+ }
+
+ HtmlTestResultsFixture.PackageDetails packageDetails(String packageName) {
+ def packageElement = findPackageDetails(packageName)
+ new HtmlTestResultsFixture.PackageDetails(packageElement)
+ }
+
+ void assertTestIgnored(String testName) {
+ def row = findTestDetails(testName)
+ assert row.select("tr > td:eq(2)").text() == 'ignored'
+ }
+
+ void assertHasFailure(String testName, String stackTrace) {
+ def detailsRow = findTestDetails(testName)
+ assert detailsRow.select("tr > td:eq(2)").text() == 'failed'
+ def tab = findTab('Failed tests')
+ assert tab != null && !tab.isEmpty()
+ assert tab.select("pre").find { it.text() == stackTrace.trim() }
+ }
+
+ private def findTestDetails(String testName) {
+ def tab = findTab('Tests')
+ def anchor = tab.select("TD").find { it.text() == testName }
+ return anchor?.parent()
+ }
+
+ private def findPackageDetails(String packageName) {
+ def tab = findTab('Packages')
+ def anchor = tab.select("TD").find { it.text() == packageName }
+ return anchor?.parent()
+ }
+
+ void assertHasStandardOutput(String stdout) {
+ def tab = findTab('Standard output')
+ assert tab != null
+ assert tab.select("SPAN > PRE").find { it.text() == stdout.trim() }
+ }
+
+ void assertHasStandardError(String stderr) {
+ def tab = findTab('Standard error')
+ assert tab != null
+ assert tab.select("SPAN > PRE").find { it.text() == stderr.trim() }
+ }
+
+ private def findTab(String title) {
+ def tab = content.select("div.tab:has(h2:contains($title))")
+ return tab
+ }
+
+ class PackageDetails {
+ private final Element packageElement
+
+ PackageDetails(Element packageElement) {
+ this.packageElement = packageElement
+ }
+
+ void assertSuccessRate(int expected) {
+ assert packageElement.select("tr > td:eq(4)").text() == "${expected}%"
+ }
+ }
+}
diff --git a/subprojects/plugins/src/testFixtures/groovy/org/gradle/api/tasks/compile/AbstractCompileTest.java b/subprojects/plugins/src/testFixtures/groovy/org/gradle/api/tasks/compile/AbstractCompileTest.java
index fd89800..9d6396e 100644
--- a/subprojects/plugins/src/testFixtures/groovy/org/gradle/api/tasks/compile/AbstractCompileTest.java
+++ b/subprojects/plugins/src/testFixtures/groovy/org/gradle/api/tasks/compile/AbstractCompileTest.java
@@ -25,12 +25,9 @@ import org.junit.Test;
import java.io.File;
import java.util.List;
-import static org.gradle.util.Matchers.*;
+import static org.gradle.util.Matchers.isEmpty;
import static org.junit.Assert.*;
-/**
- * @author Hans Dockter
- */
public abstract class AbstractCompileTest extends AbstractConventionTaskTest {
public static final String TEST_PATTERN_1 = "pattern1";
public static final String TEST_PATTERN_2 = "pattern2";
diff --git a/subprojects/publish/publish.gradle b/subprojects/publish/publish.gradle
index 6d7a3dc..a212189 100644
--- a/subprojects/publish/publish.gradle
+++ b/subprojects/publish/publish.gradle
@@ -15,8 +15,10 @@
*/
dependencies {
- groovy libraries.groovy
compile project(':core')
+ compile project(':coreImpl')
+
+ testCompile libraries.groovy
integTestRuntime project(":ivy")
integTestRuntime project(":maven")
diff --git a/subprojects/publish/src/main/groovy/org/gradle/api/publish/PublicationContainer.java b/subprojects/publish/src/main/groovy/org/gradle/api/publish/PublicationContainer.java
index fc1c6ca..6e3a419 100644
--- a/subprojects/publish/src/main/groovy/org/gradle/api/publish/PublicationContainer.java
+++ b/subprojects/publish/src/main/groovy/org/gradle/api/publish/PublicationContainer.java
@@ -16,10 +16,7 @@
package org.gradle.api.publish;
-import org.gradle.api.Action;
-import org.gradle.api.Incubating;
-import org.gradle.api.InvalidUserDataException;
-import org.gradle.api.NamedDomainObjectSet;
+import org.gradle.api.*;
/**
* A {@code PublicationContainer} is responsible for creating and managing {@link Publication} instances.
@@ -30,48 +27,22 @@ import org.gradle.api.NamedDomainObjectSet;
* <li>The {@link org.gradle.api.publish.ivy.plugins.IvyPublishPlugin} makes it possible to create {@link org.gradle.api.publish.ivy.IvyPublication} instances.</li>
* </ul>
*
- * See the documentation for {@link PublishingExtension#publications(org.gradle.api.Action)} for more examples of how to create and configure publications.
+ *
+ * <pre autoTested="true">
+ * apply plugin: 'ivy-publish'
+ *
+ * publishing.publications.create('publication-name', IvyPublication) {
+ * // Configure the ivy publication here
+ * }
+ * </pre>
+ *
+ * The usual way to add publications is via a configuration block.
+ * See the documentation for {@link PublishingExtension#publications(org.gradle.api.Action)} for examples of how to create and configure publications.
*
* @since 1.3
* @see Publication
* @see PublishingExtension
*/
@Incubating
-public interface PublicationContainer extends NamedDomainObjectSet<Publication> {
-
- /**
- * Creates a publication with the specified name and type, adding it to the container.
- *
- * <pre autoTested="true">
- * apply plugin: 'maven-publish'
- *
- * publishing.publications.add('publication-name', MavenPublication)
- * </pre>
- *
- * @param name The publication name.
- * @param type The publication type.
- * @return The added publication
- * @throws InvalidUserDataException If type is not a valid publication type, or if a publication named "name" already exists.
- */
- <T extends Publication> T add(String name, Class<T> type) throws InvalidUserDataException;
-
- /**
- * Creates a publication with the specified name and type, adding it to the container and configuring it with the supplied action.
- * A {@link groovy.lang.Closure} can be supplied in place of an action, through type coercion.
- *
- * <pre autoTested="true">
- * apply plugin: 'ivy-publish'
- *
- * publishing.publications.add('publication-name', IvyPublication) {
- * // Configure the ivy publication here
- * }
- * </pre>
- *
- * @param name The publication name.
- * @param type The publication type.
- * @param configuration The action or closure to configure the publication with.
- * @return The added publication
- * @throws InvalidUserDataException If type is not a valid publication type, or if a publication named "name" already exists.
- */
- <T extends Publication> T add(String name, Class<T> type, Action<? super T> configuration) throws InvalidUserDataException;
+public interface PublicationContainer extends ExtensiblePolymorphicDomainObjectContainer<Publication> {
}
diff --git a/subprojects/publish/src/main/groovy/org/gradle/api/publish/PublishingExtension.java b/subprojects/publish/src/main/groovy/org/gradle/api/publish/PublishingExtension.java
index ccc34aa..299ced1 100644
--- a/subprojects/publish/src/main/groovy/org/gradle/api/publish/PublishingExtension.java
+++ b/subprojects/publish/src/main/groovy/org/gradle/api/publish/PublishingExtension.java
@@ -26,6 +26,29 @@ import org.gradle.api.artifacts.dsl.RepositoryHandler;
* This new publishing mechanism will eventually replace the current mechanism of upload tasks and configurations. At this time, it is an
* incubating feature and under development.
*
+ * <p>
+ * The PublishingExtension is a {@link org.gradle.api.plugins.DeferredConfigurable} model element, meaning that extension will be configured as late as possible in the build.
+ * So any 'publishing' configuration blocks are not evaluated until either:
+ * <ol>
+ * <li>The project is about to execute, or</li>
+ * <li>he publishing extension is referenced as an instance, as opposed to via a configuration closure.</li>
+ * </ol>
+ * <p>
+ * A 'publishing' configuration block does not need to dereference the publishing extension, and so will be evaluated late. eg:
+ * <pre>
+ * publishing {
+ * publications { ... }
+ * repositories.maven { ... }
+ * }
+ * </pre>
+ *
+ * <p>
+ * Any use that accesses the publishing extension as an instance does require the publishing extension to be realised, forcing all configuration blocks to be evaluated. eg:
+ * <pre>
+ * publishing.publications { ... }
+ * publishing.repositories.maven { ... }
+ * </pre>
+ *
* @since 1.3
*/
@Incubating
diff --git a/subprojects/publish/src/main/groovy/org/gradle/api/publish/internal/CompositePublicationFactory.java b/subprojects/publish/src/main/groovy/org/gradle/api/publish/internal/CompositePublicationFactory.java
deleted file mode 100644
index 04fe530..0000000
--- a/subprojects/publish/src/main/groovy/org/gradle/api/publish/internal/CompositePublicationFactory.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2013 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.publish.internal;
-
-import org.gradle.api.InvalidUserDataException;
-import org.gradle.api.publish.Publication;
-
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-public class CompositePublicationFactory {
- private final Map<Class<? extends Publication>, PublicationFactory> factories = new LinkedHashMap<Class<? extends Publication>, PublicationFactory>();
-
- public void register(Class<? extends Publication> type, PublicationFactory factory) {
- factories.put(type, factory);
- }
-
- public <T extends Publication> T create(Class<T> type, String name) {
- for (Map.Entry<Class<? extends Publication>, PublicationFactory> entry : factories.entrySet()) {
- if (type.isAssignableFrom(entry.getKey())) {
- return type.cast(entry.getValue().create(name));
- }
- }
- throw new InvalidUserDataException("Cannot create publications of type: " + type);
- }
-}
diff --git a/subprojects/publish/src/main/groovy/org/gradle/api/publish/internal/DefaultPublicationContainer.java b/subprojects/publish/src/main/groovy/org/gradle/api/publish/internal/DefaultPublicationContainer.java
index bd4442b..5d9cc94 100644
--- a/subprojects/publish/src/main/groovy/org/gradle/api/publish/internal/DefaultPublicationContainer.java
+++ b/subprojects/publish/src/main/groovy/org/gradle/api/publish/internal/DefaultPublicationContainer.java
@@ -16,16 +16,13 @@
package org.gradle.api.publish.internal;
-import org.gradle.api.Action;
import org.gradle.api.InvalidUserDataException;
-import org.gradle.api.internal.DefaultNamedDomainObjectSet;
+import org.gradle.api.internal.DefaultPolymorphicDomainObjectContainer;
import org.gradle.api.publish.Publication;
+import org.gradle.api.publish.PublicationContainer;
import org.gradle.internal.reflect.Instantiator;
-public class DefaultPublicationContainer extends DefaultNamedDomainObjectSet<Publication> implements PublicationContainerInternal {
-
- private final CompositePublicationFactory publicationFactories = new CompositePublicationFactory();
-
+public class DefaultPublicationContainer extends DefaultPolymorphicDomainObjectContainer<Publication> implements PublicationContainer {
public DefaultPublicationContainer(Instantiator instantiator) {
super(Publication.class, instantiator);
}
@@ -34,20 +31,4 @@ public class DefaultPublicationContainer extends DefaultNamedDomainObjectSet<Pub
protected void handleAttemptToAddItemWithNonUniqueName(Publication o) {
throw new InvalidUserDataException(String.format("Publication with name '%s' added multiple times", o.getName()));
}
-
- public <T extends Publication> T add(String name, Class<T> type) {
- T publication = publicationFactories.create(type, name);
- add(publication);
- return publication;
- }
-
- public <T extends Publication> T add(String name, Class<T> type, Action<? super T> action) {
- T publication = add(name, type);
- action.execute(publication);
- return publication;
- }
-
- public void registerFactory(Class<? extends Publication> type, PublicationFactory publicationFactory) {
- publicationFactories.register(type, publicationFactory);
- }
}
diff --git a/subprojects/publish/src/main/groovy/org/gradle/api/publish/internal/GroovyPublicationContainer.groovy b/subprojects/publish/src/main/groovy/org/gradle/api/publish/internal/GroovyPublicationContainer.groovy
deleted file mode 100644
index 90efb2f..0000000
--- a/subprojects/publish/src/main/groovy/org/gradle/api/publish/internal/GroovyPublicationContainer.groovy
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.publish.internal
-
-import org.gradle.internal.reflect.Instantiator
-
-class GroovyPublicationContainer extends DefaultPublicationContainer {
- GroovyPublicationContainer(Instantiator instantiator) {
- super(instantiator)
- }
-
- def methodMissing(String name, args) {
- if (args.length == 1 && args[0] instanceof Class) {
- return add(name, args[0]);
- }
- if (args.length == 2 && args[0] instanceof Class && args[1] instanceof Closure) {
- return add(name, args[0], args[1])
- }
- throw new MissingMethodException(name, this.class, args)
- }
-}
diff --git a/subprojects/publish/src/main/groovy/org/gradle/api/publish/internal/ProjectDependencyPublicationResolver.java b/subprojects/publish/src/main/groovy/org/gradle/api/publish/internal/ProjectDependencyPublicationResolver.java
new file mode 100644
index 0000000..656ea91
--- /dev/null
+++ b/subprojects/publish/src/main/groovy/org/gradle/api/publish/internal/ProjectDependencyPublicationResolver.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.publish.internal;
+
+import org.gradle.api.Project;
+import org.gradle.api.artifacts.ModuleVersionIdentifier;
+import org.gradle.api.artifacts.ProjectDependency;
+import org.gradle.api.internal.project.ProjectInternal;
+import org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier;
+import org.gradle.api.publish.PublishingExtension;
+
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * The start of a service that will resolve a ProjectDependency into publication coordinates, to use for publishing.
+ * For now is a simple implementation, but at some point could utilise components in the dependency project, usage in the referencing project, etc.
+ */
+public class ProjectDependencyPublicationResolver {
+ public ModuleVersionIdentifier resolve(ProjectDependency dependency) {
+ Project dependencyProject = dependency.getDependencyProject();
+ ((ProjectInternal) dependencyProject).evaluate();
+
+ PublishingExtension publishing = dependencyProject.getExtensions().findByType(PublishingExtension.class);
+
+ if (publishing == null || publishing.getPublications().withType(PublicationInternal.class).isEmpty()) {
+ // Project does not apply publishing (or has no publications): simply use the project name in place of the dependency name
+ return new DefaultModuleVersionIdentifier(dependency.getGroup(), dependencyProject.getName(), dependency.getVersion());
+ }
+
+ // See if all publications have the same identifier
+ Set<? extends PublicationInternal> publications = publishing.getPublications().withType(PublicationInternal.class);
+ Iterator<? extends PublicationInternal> iterator = publications.iterator();
+ ModuleVersionIdentifier candidate = iterator.next().getCoordinates();
+ while (iterator.hasNext()) {
+ ModuleVersionIdentifier alternative = iterator.next().getCoordinates();
+ if (!candidate.equals(alternative)) {
+ throw new UnsupportedOperationException("Publishing is not yet able to resolve a dependency on a project with multiple different publications.");
+ }
+ }
+ return candidate;
+
+ }
+}
diff --git a/subprojects/publish/src/main/groovy/org/gradle/api/publish/internal/PublicationContainerInternal.java b/subprojects/publish/src/main/groovy/org/gradle/api/publish/internal/PublicationContainerInternal.java
deleted file mode 100644
index 3e45898..0000000
--- a/subprojects/publish/src/main/groovy/org/gradle/api/publish/internal/PublicationContainerInternal.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright 2013 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.publish.internal;
-
-import org.gradle.api.publish.Publication;
-import org.gradle.api.publish.PublicationContainer;
-
-public interface PublicationContainerInternal extends PublicationContainer {
- void registerFactory(Class<? extends Publication> type, PublicationFactory publicationFactory);
-}
diff --git a/subprojects/publish/src/main/groovy/org/gradle/api/publish/internal/PublicationFactory.java b/subprojects/publish/src/main/groovy/org/gradle/api/publish/internal/PublicationFactory.java
deleted file mode 100644
index 65ff686..0000000
--- a/subprojects/publish/src/main/groovy/org/gradle/api/publish/internal/PublicationFactory.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright 2013 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.publish.internal;
-
-import org.gradle.api.publish.Publication;
-
-public interface PublicationFactory {
- Publication create(String name);
-}
diff --git a/subprojects/publish/src/main/groovy/org/gradle/api/publish/internal/PublicationInternal.java b/subprojects/publish/src/main/groovy/org/gradle/api/publish/internal/PublicationInternal.java
new file mode 100644
index 0000000..8df4b9a
--- /dev/null
+++ b/subprojects/publish/src/main/groovy/org/gradle/api/publish/internal/PublicationInternal.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.publish.internal;
+
+import org.gradle.api.artifacts.ModuleVersionIdentifier;
+import org.gradle.api.publish.Publication;
+
+public interface PublicationInternal extends Publication {
+ ModuleVersionIdentifier getCoordinates();
+}
diff --git a/subprojects/publish/src/main/groovy/org/gradle/api/publish/plugins/PublishingPlugin.java b/subprojects/publish/src/main/groovy/org/gradle/api/publish/plugins/PublishingPlugin.java
index adb19b8..9b7a706 100644
--- a/subprojects/publish/src/main/groovy/org/gradle/api/publish/plugins/PublishingPlugin.java
+++ b/subprojects/publish/src/main/groovy/org/gradle/api/publish/plugins/PublishingPlugin.java
@@ -19,10 +19,12 @@ package org.gradle.api.publish.plugins;
import org.gradle.api.*;
import org.gradle.api.artifacts.dsl.RepositoryHandler;
import org.gradle.api.internal.artifacts.ArtifactPublicationServices;
+import org.gradle.api.internal.project.ProjectInternal;
import org.gradle.api.publish.PublicationContainer;
import org.gradle.api.publish.PublishingExtension;
+import org.gradle.api.publish.internal.DefaultPublicationContainer;
import org.gradle.api.publish.internal.DefaultPublishingExtension;
-import org.gradle.api.publish.internal.GroovyPublicationContainer;
+import org.gradle.configuration.project.ProjectConfigurationActionContainer;
import org.gradle.internal.reflect.Instantiator;
import javax.inject.Inject;
@@ -35,31 +37,34 @@ import javax.inject.Inject;
@Incubating
public class PublishingPlugin implements Plugin<Project> {
+ public static final String PUBLISH_TASK_GROUP = "publishing";
public static final String PUBLISH_LIFECYCLE_TASK_NAME = "publish";
private final Instantiator instantiator;
+ private final ProjectConfigurationActionContainer configurationActions;
private final ArtifactPublicationServices publicationServices;
@Inject
- public PublishingPlugin(ArtifactPublicationServices publicationServices, Instantiator instantiator) {
+ public PublishingPlugin(ArtifactPublicationServices publicationServices, Instantiator instantiator, ProjectConfigurationActionContainer configurationActions) {
this.publicationServices = publicationServices;
this.instantiator = instantiator;
+ this.configurationActions = configurationActions;
}
- public void apply(Project project) {
+ public void apply(final Project project) {
RepositoryHandler repositories = publicationServices.createRepositoryHandler();
- PublicationContainer publications = instantiator.newInstance(GroovyPublicationContainer.class, instantiator);
+ PublicationContainer publications = instantiator.newInstance(DefaultPublicationContainer.class, instantiator);
project.getExtensions().create(PublishingExtension.NAME, DefaultPublishingExtension.class, repositories, publications);
- // Access the publishing extension to ensure that it is configured and tasks are created
- project.afterEvaluate(new Action<Project>() {
- public void execute(Project project) {
- project.getExtensions().getByType(PublishingExtension.class);
+ Task publishLifecycleTask = project.getTasks().create(PUBLISH_LIFECYCLE_TASK_NAME);
+ publishLifecycleTask.setDescription("Publishes all publications produced by this project.");
+ publishLifecycleTask.setGroup(PUBLISH_TASK_GROUP);
+
+ configurationActions.add(new Action<ProjectInternal>() {
+ public void execute(ProjectInternal projectInternal) {
+ // Trigger the configuration of the publishing extension
+ project.getExtensions().getByType(DefaultPublishingExtension.class);
}
});
-
- Task publishLifecycleTask = project.getTasks().add(PUBLISH_LIFECYCLE_TASK_NAME);
- publishLifecycleTask.setDescription("Publishes all publications produced by this project.");
- publishLifecycleTask.setGroup("publishing");
}
}
diff --git a/subprojects/publish/src/test/groovy/org/gradle/api/publish/internal/DefaultPublicationContainerTest.groovy b/subprojects/publish/src/test/groovy/org/gradle/api/publish/internal/DefaultPublicationContainerTest.groovy
index 5c8f84d..e94c1dd 100644
--- a/subprojects/publish/src/test/groovy/org/gradle/api/publish/internal/DefaultPublicationContainerTest.groovy
+++ b/subprojects/publish/src/test/groovy/org/gradle/api/publish/internal/DefaultPublicationContainerTest.groovy
@@ -16,6 +16,7 @@
package org.gradle.api.publish.internal
import org.gradle.api.InvalidUserDataException
+import org.gradle.api.NamedDomainObjectFactory
import org.gradle.api.UnknownDomainObjectException
import org.gradle.api.internal.ThreadGlobalInstantiator
import org.gradle.api.publish.Publication
@@ -25,7 +26,7 @@ import spock.lang.Specification
class DefaultPublicationContainerTest extends Specification {
Instantiator instantiator = ThreadGlobalInstantiator.getOrCreate()
- GroovyPublicationContainer container = instantiator.newInstance(GroovyPublicationContainer, instantiator)
+ DefaultPublicationContainer container = instantiator.newInstance(DefaultPublicationContainer, instantiator)
def "exception is thrown on unknown access"() {
given:
@@ -45,11 +46,11 @@ class DefaultPublicationContainerTest extends Specification {
def "can add and configure publication with API"() {
given:
Publication pub = publication("test")
- PublicationFactory factory = Mock()
+ NamedDomainObjectFactory<Publication> factory = Mock()
container.registerFactory(Publication, factory)
when:
- container.add("name", Publication) {
+ container.create("name", Publication) {
value = 2
}
@@ -61,54 +62,19 @@ class DefaultPublicationContainerTest extends Specification {
pub.value == 2
}
- def "can add publication with DSL"() {
- given:
- Publication testPub = publication("test")
- PublicationFactory factory = Mock()
- container.registerFactory(Publication, factory)
-
- when:
- container.publication_name(Publication)
-
- then:
- 1 * factory.create("publication_name") >> testPub
-
- and:
- container.getByName("test") == testPub
- }
-
- def "can add and configure publication with DSL"() {
- given:
- TestPublication testPub = publication("test")
- PublicationFactory factory = Mock()
- container.registerFactory(TestPublication, factory)
-
- when:
- container.publication_name(TestPublication) {
- value = 2
- }
-
- then:
- 1 * factory.create("publication_name") >> testPub
-
- and:
- container.getByName("test") == testPub
- testPub.value == 2
- }
-
def "cannot add multiple publications with same name"() {
given:
- PublicationFactory factory = Mock()
+ NamedDomainObjectFactory<TestPublication> factory = Mock()
container.registerFactory(TestPublication, factory)
when:
- container.publication_name(TestPublication)
+ container.create("publication_name", TestPublication)
then:
1 * factory.create("publication_name") >> publication("test")
when:
- container.publication_name(TestPublication)
+ container.create("publication_name", TestPublication)
then:
1 * factory.create("publication_name") >> publication("test")
diff --git a/subprojects/publish/src/test/groovy/org/gradle/api/publish/internal/ProjectDependencyPublicationResolverTest.groovy b/subprojects/publish/src/test/groovy/org/gradle/api/publish/internal/ProjectDependencyPublicationResolverTest.groovy
new file mode 100644
index 0000000..2fa9981
--- /dev/null
+++ b/subprojects/publish/src/test/groovy/org/gradle/api/publish/internal/ProjectDependencyPublicationResolverTest.groovy
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.publish.internal
+import org.gradle.api.artifacts.ModuleVersionIdentifier
+import org.gradle.api.artifacts.ProjectDependency
+import org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier
+import org.gradle.api.internal.plugins.ExtensionContainerInternal
+import org.gradle.api.internal.project.ProjectInternal
+import org.gradle.api.publish.PublishingExtension
+import org.gradle.internal.reflect.DirectInstantiator
+import spock.lang.Specification
+
+public class ProjectDependencyPublicationResolverTest extends Specification {
+ def projectDependency = Mock(ProjectDependency)
+ def project = Mock(ProjectInternal)
+ def extensions = Mock(ExtensionContainerInternal)
+ def publishing = Mock(PublishingExtension)
+ def publications = new DefaultPublicationContainer(new DirectInstantiator())
+ def publication = Mock(PublicationInternal)
+
+ def "resolves project coordinates if project does not have publishing extension"() {
+ when:
+ projectDependency.dependencyProject >> project
+ project.evaluate() >> project
+ project.extensions >> extensions
+ extensions.findByType(PublishingExtension) >> null
+
+ projectDependency.group >> "dep-group"
+ project.name >> "project-name"
+ projectDependency.version >> "dep-version"
+
+ then:
+ with (resolve()) {
+ group == "dep-group"
+ name == "project-name"
+ version == "dep-version"
+ }
+ }
+
+ def "uses project coordinates when dependent project has no publications"() {
+ when:
+ dependentProjectHasPublications()
+
+ projectDependency.group >> "dep-group"
+ project.name >> "project-name"
+ projectDependency.version >> "dep-version"
+
+ then:
+ with (resolve()) {
+ group == "dep-group"
+ name == "project-name"
+ version == "dep-version"
+ }
+ }
+
+ def "uses coordinates of single publication from dependent project"() {
+ when:
+ def publication = Mock(PublicationInternal)
+ publication.name >> 'mock'
+ publication.coordinates >> new DefaultModuleVersionIdentifier("pub-group", "pub-name", "pub-version")
+
+ dependentProjectHasPublications(publication)
+
+ then:
+ with (resolve()) {
+ group == "pub-group"
+ name == "pub-name"
+ version == "pub-version"
+ }
+ }
+
+ def "prefers coordinates of publication from dependent project where all publications share coordinates"() {
+ when:
+ def publication = pub('mock', "pub-group", "pub-name", "pub-version")
+ def publication2 = pub('pub2', "pub-group", "pub-name", "pub-version")
+
+ dependentProjectHasPublications(publication, publication2)
+
+ then:
+ with (resolve()) {
+ group == "pub-group"
+ name == "pub-name"
+ version == "pub-version"
+ }
+ }
+
+ def "fails if cannot resolve single publication"() {
+ when:
+ def publication = pub('mock', "pub-group", "pub-name", "pub-version")
+ def publication2 = pub('pub2', "other-group", "other-name", "other-version")
+
+ dependentProjectHasPublications(publication, publication2)
+
+ and:
+ resolve()
+
+ then:
+ def e = thrown(UnsupportedOperationException)
+ e.message == "Publishing is not yet able to resolve a dependency on a project with multiple different publications."
+ }
+
+ private ModuleVersionIdentifier resolve() {
+ new ProjectDependencyPublicationResolver().resolve(projectDependency)
+ }
+
+ private void dependentProjectHasPublications(PublicationInternal... added) {
+ projectDependency.dependencyProject >> project
+ project.evaluate() >> project
+ project.extensions >> extensions
+ extensions.findByType(PublishingExtension) >> publishing
+ publishing.publications >> publications
+ publications.addAll(added)
+ }
+
+ private PublicationInternal pub(def name, def group, def module, def version) {
+ def publication = Mock(PublicationInternal)
+ publication.name >> name
+ publication.coordinates >> new DefaultModuleVersionIdentifier(group, module, version)
+ return publication
+ }
+}
diff --git a/subprojects/publish/src/test/groovy/org/gradle/api/publish/plugins/PublishingPluginTest.groovy b/subprojects/publish/src/test/groovy/org/gradle/api/publish/plugins/PublishingPluginTest.groovy
index 1ebcf6f..137fd1c 100644
--- a/subprojects/publish/src/test/groovy/org/gradle/api/publish/plugins/PublishingPluginTest.groovy
+++ b/subprojects/publish/src/test/groovy/org/gradle/api/publish/plugins/PublishingPluginTest.groovy
@@ -21,12 +21,12 @@ import org.gradle.api.artifacts.dsl.RepositoryHandler
import org.gradle.api.publish.Publication
import org.gradle.api.publish.PublicationContainer
import org.gradle.api.publish.PublishingExtension
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import spock.lang.Specification
class PublishingPluginTest extends Specification {
- Project project = HelperUtil.createRootProject()
+ Project project = TestUtil.createRootProject()
PublishingExtension extension
def setup() {
diff --git a/subprojects/reporting/reporting.gradle b/subprojects/reporting/reporting.gradle
index e094d99..7b21d94 100644
--- a/subprojects/reporting/reporting.gradle
+++ b/subprojects/reporting/reporting.gradle
@@ -1,10 +1,11 @@
dependencies {
- groovy libraries.groovy
+ compile libraries.groovy
compile project(':core')
compile 'com.googlecode.jatl:jatl:0.2.2'
testCompile libraries.jsoup
integTestRuntime project(':codeQuality')
+ integTestRuntime project(':jacoco')
}
useTestFixtures()
\ No newline at end of file
diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/api/reporting/internal/TaskReportContainerIntegTest.groovy b/subprojects/reporting/src/integTest/groovy/org/gradle/api/reporting/internal/TaskReportContainerIntegTest.groovy
similarity index 100%
rename from subprojects/plugins/src/integTest/groovy/org/gradle/api/reporting/internal/TaskReportContainerIntegTest.groovy
rename to subprojects/reporting/src/integTest/groovy/org/gradle/api/reporting/internal/TaskReportContainerIntegTest.groovy
diff --git a/subprojects/reporting/src/integTest/groovy/org/gradle/api/reporting/plugins/BuildDashboardPluginIntegrationTest.groovy b/subprojects/reporting/src/integTest/groovy/org/gradle/api/reporting/plugins/BuildDashboardPluginIntegrationTest.groovy
index cc4e082..6ce2f9d 100644
--- a/subprojects/reporting/src/integTest/groovy/org/gradle/api/reporting/plugins/BuildDashboardPluginIntegrationTest.groovy
+++ b/subprojects/reporting/src/integTest/groovy/org/gradle/api/reporting/plugins/BuildDashboardPluginIntegrationTest.groovy
@@ -19,55 +19,88 @@ package org.gradle.api.reporting.plugins
import org.gradle.integtests.fixtures.WellBehavedPluginTest
import org.gradle.test.fixtures.file.TestFile
import org.jsoup.Jsoup
-
-import static org.gradle.api.reporting.plugins.BuildDashboardPlugin.BUILD_DASHBOARD_TASK_NAME
+import org.jsoup.nodes.Document
class BuildDashboardPluginIntegrationTest extends WellBehavedPluginTest {
void setup() {
writeBuildFile()
- writeProjectFiles(testDirectory)
}
- private void writeProjectFiles(TestFile root) {
- root.file("src/main/groovy/org/gradle/class1.groovy") << "package org.gradle; class class1 { }"
- root.file("config/codenarc/rulesets.groovy") << ""
+ private void goodCode(TestFile root = testDirectory) {
+ root.file("src/main/groovy/org/gradle/Class1.groovy") << "package org.gradle; class Class1 { }"
+ buildFile << """
+ allprojects {
+ apply plugin: 'groovy'
+
+ dependencies {
+ compile localGroovy()
+ }
+ }
+ """
}
- private TestFile getBuildDashboardFile() {
- file("build/reports/buildDashboard/index.html")
+ private void withTests() {
+ buildFile << """
+ allprojects {
+ dependencies{
+ testCompile "junit:junit:4.11"
+ }
+ }
+"""
}
- private int getDashboardLinksCount() {
- Jsoup.parse(buildDashboardFile, null).select('ul li a').size()
+ private void goodTests(TestFile root = testDirectory) {
+ root.file("src/test/groovy/org/gradle/Class1.groovy") << "package org.gradle; class TestClass1 { @org.junit.Test void ok() { } }"
+ withTests()
}
- private void writeBuildFile() {
- buildFile << """
- apply plugin: 'build-dashboard'
+ private void badTests(TestFile root = testDirectory) {
+ root.file("src/test/groovy/org/gradle/Class1.groovy") << "package org.gradle; class TestClass1 { @org.junit.Test void broken() { throw new RuntimeException() } }"
+ withTests()
+ }
+ private void withCodenarc(TestFile root = testDirectory) {
+ root.file("config/codenarc/rulesets.groovy") << """
+ ruleset {
+ ruleset('rulesets/naming.xml')
+ }
+ """
+ buildFile << """
allprojects {
- apply plugin: 'groovy'
apply plugin: 'codenarc'
codenarc {
configFile = file('config/codenarc/rulesets.groovy')
}
+ }
+"""
+ }
+ private void writeBuildFile() {
+ buildFile << """
+ apply plugin: 'build-dashboard'
+
+ allprojects {
repositories {
mavenCentral()
}
-
- dependencies {
- codenarc 'org.codenarc:CodeNarc:0.16.1'
- groovy localGroovy()
- }
}
"""
}
+ private void failingDependenciesForTestTask() {
+ buildFile << """
+ task failingTask << { throw new RuntimeException() }
+
+ test.dependsOn failingTask
+ """
+ }
+
private void setupSubproject() {
- writeProjectFiles(file('subproject'))
+ def subprojectDir = file('subproject')
+ goodCode(subprojectDir)
+ goodTests(subprojectDir)
file('settings.gradle') << "include 'subproject'"
}
@@ -76,55 +109,166 @@ class BuildDashboardPluginIntegrationTest extends WellBehavedPluginTest {
}
String getMainTask() {
- BUILD_DASHBOARD_TASK_NAME
+ 'buildDashboard'
+ }
+
+ void 'build dashboard for a project with no other reports lists just the dashboard'() {
+ when:
+ run('buildDashboard')
+
+ then:
+ reports.size() == 1
+ hasReport(':buildDashboard', 'html')
+ unavailableReports.empty
+ }
+
+ void 'build dashboard lists the enabled reports for the project'() {
+ given:
+ goodCode()
+ goodTests()
+
+ when:
+ run('check', 'buildDashboard')
+
+ then:
+ reports.size() == 3
+ hasReport(':buildDashboard', 'html')
+ hasReport(':test', 'html')
+ hasReport(':test', 'junitXml')
+ }
+
+ void 'build dashboard lists the reports which have not been generated'() {
+ given:
+ goodCode()
+ goodTests()
+
+ when:
+ run('buildDashboard')
+
+ then:
+ reports.size() == 1
+ hasReport(':buildDashboard', 'html')
+ unavailableReports.size() == 2
+ hasUnavailableReport(':test', 'html')
+ hasUnavailableReport(':test', 'junitXml')
+ }
+
+ void 'build dashboard is always generated after report generating tasks have executed'() {
+ given:
+ goodCode()
+ goodTests()
+
+ when:
+ run('buildDashboard', 'check')
+
+ then:
+ reports.size() == 3
+ hasReport(':buildDashboard', 'html')
+ hasReport(':test', 'html')
+ hasReport(':test', 'junitXml')
+ }
+
+ void 'running a report generating task also generates build dashboard'() {
+ given:
+ goodCode()
+ goodTests()
+
+ when:
+ run('test')
+
+ then:
+ reports.size() == 3
+ hasReport(':buildDashboard', 'html')
+ hasReport(':test', 'html')
+ hasReport(':test', 'junitXml')
}
- void 'running buildDashboard task on its own generates a link to it in the dashboard'() {
+ void 'build dashboard is generated even if report generating task fails'() {
+ given:
+ goodCode()
+ badTests()
+
when:
- run(BUILD_DASHBOARD_TASK_NAME)
+ runAndFail('check')
then:
- dashboardLinksCount == 1
+ reports.size() == 3
+ hasReport(':buildDashboard', 'html')
+ hasReport(':test', 'html')
+ hasReport(':test', 'junitXml')
}
- void 'running buildDashboard task after some report generating task generates link to it in the dashboard'() {
+ void 'build dashboard is not generated if a dependency of the report generating task fails'() {
+ given:
+ goodCode()
+ goodTests()
+ failingDependenciesForTestTask()
+
when:
- run('check', BUILD_DASHBOARD_TASK_NAME)
+ runAndFail('check')
then:
- dashboardLinksCount == 2
+ !buildDashboardFile.exists()
}
- void 'no report is generated if it is disabled'() {
+ void 'build dashboard is not generated if a dependency of the report generating task fails even with --continue'() {
given:
+ goodCode()
+ goodTests()
+ failingDependenciesForTestTask()
+
+ when:
+ args('--continue')
+ runAndFail('check')
+
+ then:
+ !buildDashboardFile.exists()
+ }
+
+ void 'dashboard is not generated if it is disabled'() {
+ given:
+ goodCode()
+
buildFile << """
- $BUILD_DASHBOARD_TASK_NAME {
+ buildDashboard {
reports.html.enabled = false
}
"""
when:
- run(BUILD_DASHBOARD_TASK_NAME)
+ run('buildDashboard')
then:
!buildDashboardFile.exists()
}
void 'buildDashboard is incremental'() {
+ given:
+ goodCode()
+
expect:
- run(BUILD_DASHBOARD_TASK_NAME) && ":$BUILD_DASHBOARD_TASK_NAME".toString() in nonSkippedTasks
- run(BUILD_DASHBOARD_TASK_NAME) && ":$BUILD_DASHBOARD_TASK_NAME".toString() in skippedTasks
+ run('buildDashboard') && ':buildDashboard' in nonSkippedTasks
+ run('buildDashboard') && ':buildDashboard' in skippedTasks
when:
buildDashboardFile.delete()
then:
- run(BUILD_DASHBOARD_TASK_NAME) && ":$BUILD_DASHBOARD_TASK_NAME".toString() in nonSkippedTasks
+ run('buildDashboard') && ':buildDashboard' in nonSkippedTasks
}
void 'enabling an additional report renders buildDashboard out-of-date'() {
- expect:
- run('check', BUILD_DASHBOARD_TASK_NAME) && ":$BUILD_DASHBOARD_TASK_NAME".toString() in nonSkippedTasks
+ given:
+ goodCode()
+ withCodenarc()
+
+ when:
+ run('check') && ':buildDashboard' in nonSkippedTasks
+
+ then:
+ reports.size() == 2
+ hasReport(':buildDashboard', 'html')
+ hasReport(':codenarcMain', 'html')
when:
buildFile << """
@@ -133,19 +277,125 @@ class BuildDashboardPluginIntegrationTest extends WellBehavedPluginTest {
}
"""
+ and:
+ run('check') && ':buildDashboard' in nonSkippedTasks
+
+ then:
+ reports.size() == 3
+ hasReport(':buildDashboard', 'html')
+ hasReport(':codenarcMain', 'html')
+ hasReport(':codenarcMain', 'text')
+ }
+
+ void 'generating a report that was previously not available renders buildDashboard out-of-date'() {
+ given:
+ goodCode()
+ goodTests()
+
+ when:
+ run('buildDashboard') && ':buildDashboard' in nonSkippedTasks
+
+ then:
+ reports.size() == 1
+ hasReport(':buildDashboard', 'html')
+ unavailableReports.size() == 2
+ hasUnavailableReport(':test', 'html')
+ hasUnavailableReport(':test', 'junitXml')
+
+ when:
+ run('test') && ':buildDashboard' in nonSkippedTasks
+
then:
- run('check', BUILD_DASHBOARD_TASK_NAME) && ":$BUILD_DASHBOARD_TASK_NAME".toString() in nonSkippedTasks
- dashboardLinksCount == 3
+ reports.size() == 3
+ hasReport(':buildDashboard', 'html')
+ hasReport(':test', 'html')
+ hasReport(':test', 'junitXml')
+ unavailableReports.empty
}
void 'reports from subprojects are aggregated'() {
given:
+ goodCode()
+ goodTests()
setupSubproject()
when:
- run('check', BUILD_DASHBOARD_TASK_NAME)
+ run('buildDashboard', 'check')
+
+ then:
+ reports.size() == 5
+ hasReport(':buildDashboard', 'html')
+ hasReport(':test', 'html')
+ hasReport(':test', 'junitXml')
+ hasReport(':subproject:test', 'html')
+ hasReport(':subproject:test', 'junitXml')
+ }
+
+ void 'dashboard includes JaCoCo reports'() {
+ given:
+ goodCode()
+ goodTests()
+ buildFile << """
+ apply plugin:'jacoco'
+ """
+
+ when:
+ run("test", "jacocoTestReport")
+
+ then:
+ reports.size() == 4
+ hasReport(':buildDashboard', 'html')
+ hasReport(':test', 'html')
+ hasReport(':test', 'junitXml')
+ hasReport(':jacocoTestReport', 'html')
+ }
+
+ void 'dashboard includes CodeNarc reports'() {
+ given:
+ goodCode()
+ withCodenarc()
+
+ when:
+ run("check")
then:
- dashboardLinksCount == 3
+ reports.size() == 2
+ hasReport(':buildDashboard', 'html')
+ hasReport(':codenarcMain', 'html')
}
+
+ void hasReport(String task, String name) {
+ assert reports.contains("Report generated by task '$task' ($name)" as String)
+ }
+
+ List<String> getReports() {
+ dashboard.select("div#content li a")*.text()
+ }
+
+ void hasUnavailableReport(String task, String name) {
+ assert unavailableReports.contains("Report generated by task '$task' ($name)" as String)
+ }
+
+ List<String> getUnavailableReports() {
+ dashboard.select("div#content li span.unavailable")*.text()
+ }
+
+ private TestFile getBuildDashboardFile() {
+ file("build/reports/buildDashboard/index.html")
+ }
+
+ private Document doc
+ private boolean attached
+
+ Document getDashboard() {
+ if (doc == null) {
+ doc = Jsoup.parse(buildDashboardFile, "utf8")
+ }
+ if (!attached) {
+ executer.beforeExecute { doc = null }
+ attached = true
+ }
+ return doc
+ }
+
}
diff --git a/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/BuildDashboardReports.java b/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/BuildDashboardReports.java
index e899f26..aa3a57b 100644
--- a/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/BuildDashboardReports.java
+++ b/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/BuildDashboardReports.java
@@ -22,11 +22,11 @@ import org.gradle.api.Incubating;
* The reporting configuration for the the {@link GenerateBuildDashboard} task.
*/
@Incubating
-public interface BuildDashboardReports extends ReportContainer<SingleFileReport> {
+public interface BuildDashboardReports extends ReportContainer<Report> {
/**
- * The build dashboard html report
+ * The build dashboard HTML report
*
- * @return The build dashboard html report
+ * @return The build dashboard HTML report
*/
- SingleFileReport getHtml();
+ DirectoryReport getHtml();
}
diff --git a/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/ConfigurableReport.java b/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/ConfigurableReport.java
new file mode 100644
index 0000000..b5980b6
--- /dev/null
+++ b/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/ConfigurableReport.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.reporting;
+
+import org.gradle.api.Incubating;
+
+/**
+ * A file based report to be created with a configurable destination.
+ */
+ at Incubating
+public interface ConfigurableReport extends Report {
+ /**
+ * Sets the destination for the report.
+ *
+ * The file parameter is evaluated as per {@link org.gradle.api.Project#file(Object)}.
+ *
+ * @param file The destination for the report.
+ */
+ void setDestination(Object file);
+}
diff --git a/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/DirectoryReport.java b/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/DirectoryReport.java
new file mode 100644
index 0000000..b7976ba
--- /dev/null
+++ b/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/DirectoryReport.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.reporting;
+
+import org.gradle.api.Incubating;
+
+import java.io.File;
+
+/**
+ * A directory based report to be created.
+ */
+ at Incubating
+public interface DirectoryReport extends ConfigurableReport {
+
+ /**
+ * Returns the entry point of a directory based Report
+ *
+ * This can be the index.html file in a html report
+ *
+ * @return the entry point of the report or
+ * {@link org.gradle.api.reporting.DirectoryReport#getDestination()}
+ * if no entry point defined
+ *
+ */
+ File getEntryPoint();
+
+ /**
+ * Always returns {@link Report.OutputType#DIRECTORY}
+ *
+ * @return {@link Report.OutputType#DIRECTORY}
+ */
+ OutputType getOutputType();
+}
diff --git a/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/GenerateBuildDashboard.java b/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/GenerateBuildDashboard.java
index 0b12c6b..d53b434 100644
--- a/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/GenerateBuildDashboard.java
+++ b/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/GenerateBuildDashboard.java
@@ -31,7 +31,9 @@ import org.gradle.util.CollectionUtils;
import javax.inject.Inject;
import java.io.File;
+import java.io.Serializable;
import java.util.Arrays;
+import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
@@ -40,8 +42,7 @@ import java.util.Set;
*/
@Incubating
public class GenerateBuildDashboard extends DefaultTask implements Reporting<BuildDashboardReports> {
-
- private Set<Reporting> aggregated = new LinkedHashSet<Reporting>();
+ private Set<Reporting<? extends ReportContainer<?>>> aggregated = new LinkedHashSet<Reporting<? extends ReportContainer<?>>>();
@Nested
private final DefaultBuildDashboardReports reports;
@@ -52,22 +53,22 @@ public class GenerateBuildDashboard extends DefaultTask implements Reporting<Bui
reports.getHtml().setEnabled(true);
}
- /**
- * A set of report files that will be aggregated by the generated report.
- * @return A set of input report files.
- */
@Input
- public Set<File> getInputReportsFiles() {
- return CollectionUtils.collect(getEnabledInputReports(), new Transformer<File, Report>() {
- public File transform(Report original) {
- return original.getDestination();
+ public Set<ReportState> getInputReports() {
+ Set<ReportState> inputs = new HashSet<ReportState>();
+ for (Report report : getEnabledInputReports()) {
+ if (getReports().contains(report)) {
+ // A report to be generated, ignore
+ continue;
}
- });
+ inputs.add(new ReportState(report.getDisplayName(), report.getDestination(), report.getDestination().exists()));
+ }
+ return inputs;
}
private Set<Report> getEnabledInputReports() {
- Set<NamedDomainObjectSet<Report>> enabledReportSets = CollectionUtils.collect(aggregated, new Transformer<NamedDomainObjectSet<Report>, Reporting>() {
- public NamedDomainObjectSet<Report> transform(Reporting reporting) {
+ Set<NamedDomainObjectSet<? extends Report>> enabledReportSets = CollectionUtils.collect(aggregated, new Transformer<NamedDomainObjectSet<? extends Report>, Reporting<? extends ReportContainer<?>>>() {
+ public NamedDomainObjectSet<? extends Report> transform(Reporting<? extends ReportContainer<?>> reporting) {
return reporting.getReports().getEnabled();
}
});
@@ -75,7 +76,7 @@ public class GenerateBuildDashboard extends DefaultTask implements Reporting<Bui
}
/**
- * Configures which reportings are to be aggregated in the build dashboard report generated by this task.
+ * Configures which reports are to be aggregated in the build dashboard report generated by this task.
*
* <pre>
* buildDashboard {
@@ -85,7 +86,7 @@ public class GenerateBuildDashboard extends DefaultTask implements Reporting<Bui
*
* @param reportings an array of {@link Reporting} instances that are to be aggregated
*/
- public void aggregate(Reporting... reportings) {
+ public void aggregate(Reporting<? extends ReportContainer<?>>... reportings) {
aggregated.addAll(Arrays.asList(reportings));
}
@@ -123,10 +124,33 @@ public class GenerateBuildDashboard extends DefaultTask implements Reporting<Bui
@TaskAction
void run() {
if (getReports().getHtml().isEnabled()) {
- BuildDashboardGenerator generator = new BuildDashboardGenerator(getEnabledInputReports(), reports.getHtml().getDestination());
+ BuildDashboardGenerator generator = new BuildDashboardGenerator(getEnabledInputReports(), reports.getHtml().getEntryPoint());
generator.generate();
- }else {
+ } else {
setDidWork(false);
}
}
+
+ private static class ReportState implements Serializable {
+ private final String name;
+ private final File destination;
+ private final boolean available;
+
+ private ReportState(String name, File destination, boolean available) {
+ this.name = name;
+ this.destination = destination;
+ this.available = available;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ ReportState other = (ReportState) obj;
+ return name.equals(other.name) && destination.equals(other.destination) && available == other.available;
+ }
+
+ @Override
+ public int hashCode() {
+ return name.hashCode() ^ destination.hashCode();
+ }
+ }
}
diff --git a/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/Report.java b/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/Report.java
index b371e8f..a223e41 100644
--- a/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/Report.java
+++ b/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/Report.java
@@ -24,6 +24,8 @@ import java.io.Serializable;
/**
* A file based report to be created.
+ * <p>
+ * Tasks that produce reports expose instances of this type for configuration via the {@link Reporting} interface.
*/
public interface Report extends Serializable, Configurable<Report> {
@@ -35,13 +37,13 @@ public interface Report extends Serializable, Configurable<Report> {
/**
* The symbolic name of this report.
- *
- * The name of the report usually indicates the format (e.g. xml, html etc.) but can be anything.
- *
+ * <p>
+ * The name of the report usually indicates the format (e.g. XML, HTML etc.) but can be anything.
+ * <p>
* When part of a {@link ReportContainer}, reports are accessed via their name. That is, given a report container variable
* named {@code reports} containing a report who's {@code getName()} returns {@code "html"}, the report could be accessed
* via:
- *
+ * <p>
* <pre>
* reports.html
* </pre>
@@ -59,7 +61,7 @@ public interface Report extends Serializable, Configurable<Report> {
/**
* Whether or not this report should be generated by whatever generates it.
- *
+ * <p>
* If {@code true}, the generator of this report will generate it at the appropriate time.
* If {@code false}, the generator of this report will not generate this report.
*
@@ -77,10 +79,10 @@ public interface Report extends Serializable, Configurable<Report> {
/**
* The location on the filesystem of the report when it is generated.
- *
+ * <p>
* Depending on the {@link #getOutputType() output type} of the report, this may point to
* a file or a directory.
- *
+ * <p>
* Subtypes may implement setters for the destination.
*
* @return The location on the filesystem of the report when it is generated
@@ -94,14 +96,14 @@ public interface Report extends Serializable, Configurable<Report> {
/**
* The report outputs a single file.
- *
+ * <p>
* That is, the {@link #getDestination()} file points a single file.
*/
FILE,
/**
* The report outputs files into a directory.
- *
+ * <p>
* That is, the {@link #getDestination()} file points to a directory.
*/
DIRECTORY
diff --git a/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/ReportContainer.java b/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/ReportContainer.java
index 95aa5f9..15f2c7b 100644
--- a/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/ReportContainer.java
+++ b/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/ReportContainer.java
@@ -21,13 +21,13 @@ import org.gradle.api.NamedDomainObjectSet;
import org.gradle.util.Configurable;
/**
- * A container of potential reports.
- *
+ * A container of {@link Report} objects, that represent potential reports.
+ * <p>
* Things that produce reports (typically tasks) expose a report container that contains {@link Report} objects for each
* possible report that they can produce. Each report object can be configured individually, including whether or not it should
* be produced by way of its {@link Report#setEnabled(boolean) enabled} property.
- *
- * ReportContainer implementations are <b>immutable</b> in that standard collection methods such as {@code add()}, {@code remove()}
+ * <p>
+ * {@code ReportContainer} implementations are <b>immutable</b> in that standard collection methods such as {@code add()}, {@code remove()}
* and {@code clear()} will throw an {@link ImmutableViolationException}. However, implementations may provide new methods that allow
* the addition of new report object and/or the removal of existing report objects.
*
@@ -37,7 +37,7 @@ public interface ReportContainer<T extends Report> extends NamedDomainObjectSet<
/**
* The exception thrown when any of this container's mutation methods are called.
- *
+ * <p>
* This applies to the standard {@link java.util.Collection} methods such as {@code add()}, {@code remove()}
* and {@code clear()}.
*/
@@ -48,8 +48,8 @@ public interface ReportContainer<T extends Report> extends NamedDomainObjectSet<
}
/**
- * Returns an immutable collection of all the enabled reports.
- *
+ * Returns an immutable collection of all the enabled {@link Report} objects in this container.
+ * <p>
* The returned collection is live. That is, as reports are enabled/disabled the returned collection always
* reflects the current set of enabled reports.
*
diff --git a/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/Reporting.java b/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/Reporting.java
index b3e907d..37c1016 100644
--- a/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/Reporting.java
+++ b/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/Reporting.java
@@ -19,14 +19,48 @@ package org.gradle.api.reporting;
import groovy.lang.Closure;
/**
- * An object that provides reporting options
+ * An object that provides reporting options.
+ * <p>
+ * Tasks that produce reports as part of their execution expose configuration options of those reports via these methods.
+ * The {@code Reporting} interface is parameterized, where the parameter denotes the specific type of reporting container
+ * that is exposed. The specific type of the reporting container denotes the different types of reports available.
+ * <p>
+ * For example, given a task such as:
+ * </p>
+ * <pre>
+ * class MyTask implements Reporting<MyReportContainer> {
+ * // implementation
+ * }
+ *
+ * interface MyReportContainer extends ReportContainer<Report> {
+ * Report getHtml();
+ * Report getCsv();
+ * }
+ * </pre>
+ * <p>
+ * The reporting aspects of such a task can be configured as such:
+ * </p>
+ * <pre>
+ * task my(type: MyTask) {
+ * reports {
+ * html.enabled = true
+ * csv.enabled = false
+ * }
+ * }
+ * </pre>
+ * <p>
+ * See the documentation for the specific {@code ReportContainer} type for the task for information on report types and options.
+ * </p>
*
* @param <T> The base type of the report container
*/
public interface Reporting<T extends ReportContainer> {
/**
- * Returns the report container.
+ * A {@link ReportContainer} instance.
+ * <p>
+ * Implementors specify a specific implementation of {@link ReportContainer} that describes the types of reports that
+ * are available.
*
* @return The report container
*/
@@ -35,8 +69,6 @@ public interface Reporting<T extends ReportContainer> {
/**
* Allow configuration of the report container by closure.
*
- * For example…
- *
* <pre>
* reports {
* html {
diff --git a/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/ReportingExtension.java b/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/ReportingExtension.java
index a3d9e42..f9923e4 100644
--- a/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/ReportingExtension.java
+++ b/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/ReportingExtension.java
@@ -22,15 +22,18 @@ import java.io.File;
import java.util.concurrent.Callable;
/**
- * Adds base configuration for reporting tasks.
- *
+ * A project extension named "reporting" that provides basic reporting settings and utilities.
+ * <p>
* Example usage:
- *
+ * <p>
* <pre>
* reporting {
* baseDir "$buildDir/our-reports"
* }
* </pre>
+ * <p>
+ * When implementing a task that produces reports, the location of where to generate reports should be obtained
+ * via the {@link #file(String)} method of this extension.
*/
public class ReportingExtension {
@@ -61,7 +64,7 @@ public class ReportingExtension {
/**
* The base directory for all reports
- *
+ * <p>
* This value can be changed, so any files derived from this should be calculated on demand.
*
* @return The base directory for all reports
@@ -72,7 +75,7 @@ public class ReportingExtension {
/**
* Sets the base directory to use for all reports
- *
+ * <p>
* The value will be converted to a {@code File} on demand via {@link Project#file(Object)}.
*
* @param baseDir The base directory to use for all reports
@@ -83,7 +86,7 @@ public class ReportingExtension {
/**
* Creates a file object for the given path, relative to {@link #getBaseDir()}.
- *
+ * <p>
* The reporting base dir can be changed, so users of this method should use it on demand where appropriate.
*
* @param path the relative path
diff --git a/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/SingleFileReport.java b/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/SingleFileReport.java
index 037c78e..e82c796 100644
--- a/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/SingleFileReport.java
+++ b/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/SingleFileReport.java
@@ -19,17 +19,7 @@ package org.gradle.api.reporting;
/**
* A report that is a single file.
*/
-public interface SingleFileReport extends Report {
-
- /**
- * Sets the destination for the report.
- *
- * The file parameter is evaluated as per {@link org.gradle.api.Project#file(Object)}.
- *
- * @param file The destination for the report.
- */
- void setDestination(Object file);
-
+public interface SingleFileReport extends ConfigurableReport {
/**
* Always returns {@link Report.OutputType#FILE}
*
diff --git a/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/internal/BuildDashboardGenerator.java b/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/internal/BuildDashboardGenerator.java
index e68023e..b5d0034 100644
--- a/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/internal/BuildDashboardGenerator.java
+++ b/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/internal/BuildDashboardGenerator.java
@@ -18,80 +18,88 @@ package org.gradle.api.reporting.internal;
import com.googlecode.jatl.Html;
import org.gradle.api.UncheckedIOException;
+import org.gradle.api.reporting.DirectoryReport;
import org.gradle.api.reporting.Report;
-import org.gradle.api.specs.Spec;
-import org.gradle.util.CollectionUtils;
import org.gradle.util.GFileUtils;
+import org.gradle.util.GradleVersion;
import java.io.*;
+import java.util.Comparator;
import java.util.Set;
+import java.util.TreeSet;
public class BuildDashboardGenerator {
private Set<Report> reports;
private File outputFile;
public BuildDashboardGenerator(Set<Report> reports, File outputFile) {
- this.reports = reports;
+ this.reports = new TreeSet<Report>(new Comparator<Report>() {
+ public int compare(Report o1, Report o2) {
+ return o1.getDisplayName().compareTo(o2.getDisplayName());
+ }
+ });
+ this.reports.addAll(reports);
this.outputFile = outputFile;
}
public void generate() {
- BufferedWriter writer = null;
try {
GFileUtils.parentMkdirs(outputFile);
- writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outputFile), "UTF-8"));
- generate(writer);
+ Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outputFile), "UTF-8"));
+ try {
+ generate(writer);
+ } finally {
+ writer.close();
+ }
copyCss();
} catch (IOException e) {
throw new UncheckedIOException(e);
- } finally {
- if (writer != null) {
- try {
- writer.close();
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
}
}
private void copyCss() {
- File cssFile = new File(outputFile.getParent(), "base-style.css");
- GFileUtils.copyURLToFile(getClass().getResource("/org/gradle/reporting/base-style.css"), cssFile);
+ GFileUtils.copyURLToFile(getClass().getResource("/org/gradle/reporting/base-style.css"), new File(outputFile.getParent(), "base-style.css"));
+ GFileUtils.copyURLToFile(getClass().getResource("style.css"), new File(outputFile.getParent(), "style.css"));
}
- private Set<Report> getReportsWithExistingDestination() {
- return CollectionUtils.filter(reports, new Spec<Report>() {
- public boolean isSatisfiedBy(Report report) {
- File destination = report.getDestination();
- return destination != null && destination.exists();
- }
- });
- }
-
- private void generate(BufferedWriter writer) {
+ private void generate(Writer writer) {
new Html(writer) {{
html();
head();
meta().httpEquiv("Content-Type").content("text/html; charset=utf-8");
- link().rel("stylesheet").type("text/css").href("base-style.css");
- end(2);
+ link().rel("stylesheet").type("text/css").href("base-style.css").end();
+ link().rel("stylesheet").type("text/css").href("style.css").end();
+ title().text("Build dashboard").end();
+ end();
body();
div().id("content");
- Set<Report> reports = getReportsWithExistingDestination();
if (reports.size() > 0) {
- h1().text("Available build reports:").end();
+ h1().text("Build reports").end();
ul();
for (Report report : reports) {
li();
- a().href(GFileUtils.relativePath(outputFile.getParentFile(), report.getDestination())).text(report.getDisplayName());
+ if (report.getDestination().exists()) {
+ a().href(GFileUtils.relativePath(outputFile.getParentFile(), getHtmlLinkedFileFromReport(report))).text(report.getDisplayName());
+ } else {
+ span().classAttr("unavailable").text(report.getDisplayName());
+ }
end(2);
}
end();
} else {
h1().text("There are no build reports available.").end();
}
+ end();
+ div().id("footer").text(String.format("Generated by %s", GradleVersion.current()));
endAll();
}};
}
+
+ private File getHtmlLinkedFileFromReport(Report report) {
+ if(report instanceof DirectoryReport){
+ return ((DirectoryReport) report).getEntryPoint();
+ } else{
+ return report.getDestination();
+ }
+ }
}
diff --git a/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/internal/DefaultBuildDashboardReports.java b/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/internal/DefaultBuildDashboardReports.java
index 171c2d7..b15faa3 100644
--- a/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/internal/DefaultBuildDashboardReports.java
+++ b/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/internal/DefaultBuildDashboardReports.java
@@ -18,17 +18,17 @@ package org.gradle.api.reporting.internal;
import org.gradle.api.Task;
import org.gradle.api.reporting.BuildDashboardReports;
-import org.gradle.api.reporting.SingleFileReport;
+import org.gradle.api.reporting.DirectoryReport;
+import org.gradle.api.reporting.Report;
-public class DefaultBuildDashboardReports extends TaskReportContainer<SingleFileReport> implements BuildDashboardReports {
+public class DefaultBuildDashboardReports extends TaskReportContainer<Report> implements BuildDashboardReports {
public DefaultBuildDashboardReports(Task task) {
- super(SingleFileReport.class, task);
-
- add(TaskGeneratedSingleFileReport.class, "html", task);
+ super(DirectoryReport.class, task);
+ add(TaskGeneratedSingleDirectoryReport.class, "html", task, "index.html");
}
- public SingleFileReport getHtml() {
- return getByName("html");
+ public DirectoryReport getHtml() {
+ return (DirectoryReport)getByName("html");
}
}
diff --git a/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/internal/DefaultReportContainer.java b/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/internal/DefaultReportContainer.java
index a141072..44574d9 100644
--- a/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/internal/DefaultReportContainer.java
+++ b/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/internal/DefaultReportContainer.java
@@ -19,12 +19,11 @@ package org.gradle.api.reporting.internal;
import groovy.lang.Closure;
import org.gradle.api.InvalidUserDataException;
import org.gradle.api.NamedDomainObjectSet;
-import org.gradle.api.internal.ConfigureDelegate;
import org.gradle.api.internal.DefaultNamedDomainObjectSet;
-import org.gradle.internal.reflect.Instantiator;
import org.gradle.api.reporting.Report;
import org.gradle.api.reporting.ReportContainer;
import org.gradle.api.specs.Spec;
+import org.gradle.internal.reflect.Instantiator;
import org.gradle.util.ConfigureUtil;
import java.util.SortedMap;
@@ -54,7 +53,7 @@ public class DefaultReportContainer<T extends Report> extends DefaultNamedDomain
}
public ReportContainer<T> configure(Closure cl) {
- ConfigureUtil.configure(cl, new ConfigureDelegate(cl.getOwner(), this), false);
+ ConfigureUtil.configure(cl, this, false);
return this;
}
diff --git a/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/internal/TaskGeneratedSingleDirectoryReport.java b/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/internal/TaskGeneratedSingleDirectoryReport.java
new file mode 100644
index 0000000..532880a
--- /dev/null
+++ b/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/internal/TaskGeneratedSingleDirectoryReport.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.reporting.internal;
+
+import org.gradle.api.Task;
+import org.gradle.api.reporting.DirectoryReport;
+
+import java.io.File;
+
+public class TaskGeneratedSingleDirectoryReport extends TaskGeneratedReport implements DirectoryReport {
+
+ private final String relativeEntryPath;
+
+ public TaskGeneratedSingleDirectoryReport(String name, Task task, String relativeEntryPath) {
+ super(name, OutputType.DIRECTORY, task);
+ this.relativeEntryPath = relativeEntryPath;
+ }
+
+ public File getEntryPoint() {
+ if (relativeEntryPath == null) {
+ return getDestination();
+ } else {
+ return new File(getDestination(), relativeEntryPath);
+ }
+ }
+
+ @Override
+ public void setDestination(Object destination) {
+ super.setDestination(destination);
+ }
+}
diff --git a/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/plugins/BuildDashboardPlugin.groovy b/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/plugins/BuildDashboardPlugin.groovy
deleted file mode 100644
index 22ccb22..0000000
--- a/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/plugins/BuildDashboardPlugin.groovy
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.api.reporting.plugins
-
-import org.gradle.api.Incubating
-import org.gradle.api.Plugin
-import org.gradle.api.Project
-import org.gradle.api.internal.project.ProjectInternal
-import org.gradle.api.plugins.ReportingBasePlugin
-import org.gradle.api.reporting.GenerateBuildDashboard
-import org.gradle.api.reporting.Reporting
-import org.gradle.api.reporting.ReportingExtension
-import org.gradle.api.reporting.SingleFileReport
-
-/**
- * <p>A {@link Plugin} which allows to generate build dashboard report.</p>
- */
- at Incubating
-public class BuildDashboardPlugin implements Plugin<ProjectInternal> {
- public static final String BUILD_DASHBOARD_TASK_NAME = "buildDashboard"
-
- public void apply(ProjectInternal project) {
- project.plugins.apply(ReportingBasePlugin)
-
- GenerateBuildDashboard buildDashboardTask = project.tasks.add(BUILD_DASHBOARD_TASK_NAME, GenerateBuildDashboard)
-
- project.allprojects.each { aggregateReportings(it, buildDashboardTask) }
- addReportDestinationConventionMapping(project, buildDashboardTask.reports.html);
- }
-
- private void addReportDestinationConventionMapping(ProjectInternal project, SingleFileReport buildDashboardReport) {
- buildDashboardReport.conventionMapping.map('destination') {
- project.extensions.getByType(ReportingExtension).file('buildDashboard/index.html')
- }
- }
-
- private void aggregateReportings(Project project, GenerateBuildDashboard buildDashboardTask) {
- project.tasks.withType(Reporting).all {
- buildDashboardTask.aggregate(it)
- }
- }
-}
diff --git a/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/plugins/BuildDashboardPlugin.java b/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/plugins/BuildDashboardPlugin.java
new file mode 100644
index 0000000..cece2c6
--- /dev/null
+++ b/subprojects/reporting/src/main/groovy/org/gradle/api/reporting/plugins/BuildDashboardPlugin.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.reporting.plugins;
+
+import org.gradle.api.*;
+import org.gradle.api.internal.ConventionMapping;
+import org.gradle.api.internal.plugins.DslObject;
+import org.gradle.api.internal.project.ProjectInternal;
+import org.gradle.api.plugins.ReportingBasePlugin;
+import org.gradle.api.reporting.DirectoryReport;
+import org.gradle.api.reporting.GenerateBuildDashboard;
+import org.gradle.api.reporting.Reporting;
+import org.gradle.api.reporting.ReportingExtension;
+
+import java.util.concurrent.Callable;
+
+/**
+ * Adds a task, "buildDashboard", that aggregates the output of all tasks executed during the build that produce reports.
+ */
+ at Incubating
+public class BuildDashboardPlugin implements Plugin<ProjectInternal> {
+
+ public static final String BUILD_DASHBOARD_TASK_NAME = "buildDashboard";
+
+ public void apply(final ProjectInternal project) {
+ project.getPlugins().apply(ReportingBasePlugin.class);
+
+ final GenerateBuildDashboard buildDashboardTask = project.getTasks().create(BUILD_DASHBOARD_TASK_NAME, GenerateBuildDashboard.class);
+
+ DirectoryReport htmlReport = buildDashboardTask.getReports().getHtml();
+ ConventionMapping htmlReportConventionMapping = new DslObject(htmlReport).getConventionMapping();
+ htmlReportConventionMapping.map("destination", new Callable<Object>() {
+ public Object call() throws Exception {
+ return project.getExtensions().getByType(ReportingExtension.class).file("buildDashboard");
+ }
+ });
+
+ Action<Task> captureReportingTasks = new Action<Task>() {
+ public void execute(Task task) {
+ if (!(task instanceof Reporting)) {
+ return;
+ }
+
+ Reporting reporting = (Reporting) task;
+
+ buildDashboardTask.aggregate(reporting);
+
+ if (!task.equals(buildDashboardTask)) {
+ task.finalizedBy(buildDashboardTask);
+ }
+ }
+ };
+
+ for (Project aProject : project.getAllprojects()) {
+ aProject.getTasks().all(captureReportingTasks);
+ }
+ }
+
+}
diff --git a/subprojects/reporting/src/main/resources/org/gradle/api/reporting/internal/style.css b/subprojects/reporting/src/main/resources/org/gradle/api/reporting/internal/style.css
new file mode 100644
index 0000000..d6272e4
--- /dev/null
+++ b/subprojects/reporting/src/main/resources/org/gradle/api/reporting/internal/style.css
@@ -0,0 +1,3 @@
+.unavailable {
+ color: #808080;
+}
\ No newline at end of file
diff --git a/subprojects/reporting/src/test/groovy/org/gradle/api/plugins/ReportingBasePluginConventionTest.groovy b/subprojects/reporting/src/test/groovy/org/gradle/api/plugins/ReportingBasePluginConventionTest.groovy
new file mode 100644
index 0000000..bfd0d2e
--- /dev/null
+++ b/subprojects/reporting/src/test/groovy/org/gradle/api/plugins/ReportingBasePluginConventionTest.groovy
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.plugins.binaries.tasks
+
+import org.gradle.api.Project
+import org.gradle.api.plugins.ReportingBasePluginConvention
+import org.gradle.api.reporting.ReportingExtension
+import org.gradle.testfixtures.ProjectBuilder
+import spock.lang.Specification
+
+// Note: ReportingBasePluginConvention has been deprecated
+public class ReportingBasePluginConventionTest extends Specification {
+
+ Project project = ProjectBuilder.builder().build()
+ ReportingExtension extension = new ReportingExtension(project)
+ ReportingBasePluginConvention convention = new ReportingBasePluginConvention(project, extension)
+
+ def "defaults to reports dir in build dir"() {
+ expect:
+ convention.reportsDirName == ReportingExtension.DEFAULT_REPORTS_DIR_NAME
+ convention.reportsDir == new File(project.buildDir, ReportingExtension.DEFAULT_REPORTS_DIR_NAME)
+ }
+
+ def "can set reports dir by name, relative to build dir"() {
+ when:
+ convention.reportsDirName = "something-else"
+
+ then:
+ convention.reportsDir == new File(project.buildDir, "something-else")
+
+ when:
+ project.buildDir = new File(project.buildDir, "new-build-dir")
+
+ then:
+ convention.reportsDir == new File(project.buildDir, "something-else")
+ }
+
+ def "calculates api doc title from project name and version"() {
+ expect:
+ project.version == Project.DEFAULT_VERSION
+
+ and:
+ convention.apiDocTitle == "$project.name API"
+
+ when:
+ project.version = "1.0"
+
+ then:
+ convention.apiDocTitle == "$project.name 1.0 API"
+ }
+
+}
diff --git a/subprojects/reporting/src/test/groovy/org/gradle/api/plugins/ReportingBasePluginTest.groovy b/subprojects/reporting/src/test/groovy/org/gradle/api/plugins/ReportingBasePluginTest.groovy
new file mode 100644
index 0000000..2889b6d
--- /dev/null
+++ b/subprojects/reporting/src/test/groovy/org/gradle/api/plugins/ReportingBasePluginTest.groovy
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.plugins.binaries.tasks
+
+import org.gradle.api.Project
+import org.gradle.api.plugins.ReportingBasePlugin
+import org.gradle.api.plugins.ReportingBasePluginConvention
+import org.gradle.api.reporting.ReportingExtension
+import org.gradle.util.TestUtil
+import spock.lang.Specification
+
+public class ReportingBasePluginTest extends Specification {
+
+ Project project = TestUtil.createRootProject();
+
+ def setup() {
+ project.plugins.apply(ReportingBasePlugin)
+ }
+
+ def addsTasksAndConventionToProject() {
+ expect:
+ project.convention.plugins.get("reportingBase") instanceof ReportingBasePluginConvention
+ }
+
+ def "adds reporting extension"() {
+ expect:
+ project.reporting instanceof ReportingExtension
+
+ project.configure(project) {
+ reporting {
+ baseDir "somewhere"
+ }
+ }
+ }
+}
diff --git a/subprojects/reporting/src/test/groovy/org/gradle/api/reporting/GenerateBuildDashboardSpec.groovy b/subprojects/reporting/src/test/groovy/org/gradle/api/reporting/GenerateBuildDashboardSpec.groovy
index debd8c7..1d1702c 100644
--- a/subprojects/reporting/src/test/groovy/org/gradle/api/reporting/GenerateBuildDashboardSpec.groovy
+++ b/subprojects/reporting/src/test/groovy/org/gradle/api/reporting/GenerateBuildDashboardSpec.groovy
@@ -15,7 +15,7 @@
*/
package org.gradle.api.reporting
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import org.junit.Test
import spock.lang.Specification
@@ -24,7 +24,7 @@ class GenerateBuildDashboardSpec extends Specification {
@Test
def "does no work if html report is disabled"() {
setup:
- GenerateBuildDashboard task = HelperUtil.createTask(GenerateBuildDashboard)
+ GenerateBuildDashboard task = TestUtil.createTask(GenerateBuildDashboard)
when:
task.reports.html.enabled = false
and:
diff --git a/subprojects/reporting/src/test/groovy/org/gradle/api/reporting/internal/BuildDashboardGeneratorSpec.groovy b/subprojects/reporting/src/test/groovy/org/gradle/api/reporting/internal/BuildDashboardGeneratorSpec.groovy
index 0a8889f..2fc4dad 100644
--- a/subprojects/reporting/src/test/groovy/org/gradle/api/reporting/internal/BuildDashboardGeneratorSpec.groovy
+++ b/subprojects/reporting/src/test/groovy/org/gradle/api/reporting/internal/BuildDashboardGeneratorSpec.groovy
@@ -16,6 +16,7 @@
package org.gradle.api.reporting.internal
+import org.gradle.api.reporting.DirectoryReport
import org.gradle.api.reporting.Report
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
import org.jsoup.Jsoup
@@ -49,6 +50,15 @@ class BuildDashboardGeneratorSpec extends Specification {
}
}
+ Report mockDirectoryReport(String name, File destinationDirectory) {
+ Stub(DirectoryReport){
+ getDisplayName() >> name
+ getDestination() >> destinationDirectory
+ getEntryPoint() >> new File(destinationDirectory, "index.html")
+ }
+ }
+
+
void 'appropriate message is displayed when there are no reports available'() {
given:
generatorFor([])
@@ -62,22 +72,28 @@ class BuildDashboardGeneratorSpec extends Specification {
void 'links to reports are added to the generated markup'() {
given:
+ def htmlFolder = tmpDir.createDir('htmlContent');
+ htmlFolder.createFile("index.html")
generatorFor([
mockReport('a', tmpDir.createFile('report.html')),
mockReport('b', tmpDir.createDir('inner').createFile('otherReport.html')),
mockReport('c', tmpDir.file('idonotexist.html')),
- mockReport('d', null)
+ mockDirectoryReport('d', htmlFolder),
+ mockReport('e', tmpDir.createDir('simpleDirectory')),
])
when:
generator.generate()
then:
- outputHtml.select('h1').text() == 'Available build reports:'
+ outputHtml.select('h1').text() == 'Build reports'
with outputHtml.select('ul li'), {
- size() == 2
+ size() == 5
select('a[href=report.html]').text() == 'a'
select('a[href=inner/otherReport.html]').text() == 'b'
+ select('span[class=unavailable]').text() == 'c'
+ select('a[href=htmlContent/index.html]').text() == 'd'
+ select('a[href=simpleDirectory]').text() == 'e'
}
}
diff --git a/subprojects/resources/resources.gradle b/subprojects/resources/resources.gradle
new file mode 100644
index 0000000..6474d53
--- /dev/null
+++ b/subprojects/resources/resources.gradle
@@ -0,0 +1,11 @@
+/*
+ * A set of general-purpose resource abstractions.
+ */
+dependencies {
+ compile libraries.slf4j_api
+ compile project(':baseServices')
+ testCompile libraries.groovy
+}
+
+useTestFixtures()
+useClassycle()
diff --git a/subprojects/resources/src/main/java/org/gradle/internal/filestore/FileStore.java b/subprojects/resources/src/main/java/org/gradle/internal/filestore/FileStore.java
new file mode 100644
index 0000000..7d12d92
--- /dev/null
+++ b/subprojects/resources/src/main/java/org/gradle/internal/filestore/FileStore.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.filestore;
+
+import org.gradle.api.Action;
+import org.gradle.internal.resource.local.LocallyAvailableResource;
+
+import java.io.File;
+
+public interface FileStore<K> {
+
+ LocallyAvailableResource move(K key, File source);
+
+ LocallyAvailableResource copy(K key, File source);
+
+ void moveFilestore(File destination);
+
+ LocallyAvailableResource add(K key, Action<File> addAction);
+}
diff --git a/subprojects/resources/src/main/java/org/gradle/internal/filestore/FileStoreSearcher.java b/subprojects/resources/src/main/java/org/gradle/internal/filestore/FileStoreSearcher.java
new file mode 100644
index 0000000..44bbfb9
--- /dev/null
+++ b/subprojects/resources/src/main/java/org/gradle/internal/filestore/FileStoreSearcher.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.filestore;
+
+import org.gradle.internal.resource.local.LocallyAvailableResource;
+
+import java.util.Set;
+
+public interface FileStoreSearcher<S> {
+
+ Set<? extends LocallyAvailableResource> search(S key);
+
+}
diff --git a/subprojects/resources/src/main/java/org/gradle/internal/resource/local/AbstractLocallyAvailableResource.java b/subprojects/resources/src/main/java/org/gradle/internal/resource/local/AbstractLocallyAvailableResource.java
new file mode 100644
index 0000000..fa88ca7
--- /dev/null
+++ b/subprojects/resources/src/main/java/org/gradle/internal/resource/local/AbstractLocallyAvailableResource.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.resource.local;
+
+import org.gradle.util.hash.HashUtil;
+import org.gradle.util.hash.HashValue;
+
+public abstract class AbstractLocallyAvailableResource implements LocallyAvailableResource {
+ // Calculated on demand
+ private HashValue sha1;
+ private Long contentLength;
+ private Long lastModified;
+
+ protected AbstractLocallyAvailableResource() {
+ }
+
+ protected AbstractLocallyAvailableResource(HashValue sha1) {
+ this.sha1 = sha1;
+ }
+
+ public HashValue getSha1() {
+ if (sha1 == null) {
+ this.sha1 = HashUtil.sha1(getFile());
+ }
+ return sha1;
+ }
+
+ public long getContentLength() {
+ if (contentLength == null) {
+ contentLength = getFile().length();
+ }
+ return contentLength;
+ }
+
+ public long getLastModified() {
+ if (lastModified == null) {
+ lastModified = getFile().lastModified();
+ }
+ return lastModified;
+ }
+
+}
diff --git a/subprojects/resources/src/main/java/org/gradle/internal/resource/local/DefaultLocallyAvailableResource.java b/subprojects/resources/src/main/java/org/gradle/internal/resource/local/DefaultLocallyAvailableResource.java
new file mode 100644
index 0000000..c177151
--- /dev/null
+++ b/subprojects/resources/src/main/java/org/gradle/internal/resource/local/DefaultLocallyAvailableResource.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.resource.local;
+
+import org.gradle.util.hash.HashValue;
+
+import java.io.File;
+
+public class DefaultLocallyAvailableResource extends AbstractLocallyAvailableResource {
+ private final File origin;
+
+ public DefaultLocallyAvailableResource(File origin) {
+ this.origin = origin;
+ }
+
+ public DefaultLocallyAvailableResource(File origin, HashValue sha1) {
+ super(sha1);
+ this.origin = origin;
+ }
+
+ public File getFile() {
+ return origin;
+ }
+}
diff --git a/subprojects/resources/src/main/java/org/gradle/internal/resource/local/LocallyAvailableResource.java b/subprojects/resources/src/main/java/org/gradle/internal/resource/local/LocallyAvailableResource.java
new file mode 100644
index 0000000..7004312
--- /dev/null
+++ b/subprojects/resources/src/main/java/org/gradle/internal/resource/local/LocallyAvailableResource.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.resource.local;
+
+import org.gradle.util.hash.HashValue;
+
+import java.io.File;
+
+public interface LocallyAvailableResource {
+
+ File getFile();
+
+ HashValue getSha1();
+
+ long getLastModified();
+
+ long getContentLength();
+}
diff --git a/subprojects/resources/src/test/groovy/org/gradle/internal/resource/local/DefaultLocallyAvailableResourceTest.groovy b/subprojects/resources/src/test/groovy/org/gradle/internal/resource/local/DefaultLocallyAvailableResourceTest.groovy
new file mode 100644
index 0000000..c401937
--- /dev/null
+++ b/subprojects/resources/src/test/groovy/org/gradle/internal/resource/local/DefaultLocallyAvailableResourceTest.groovy
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.internal.resource.local
+
+import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
+import org.gradle.util.hash.HashUtil
+import org.junit.Rule
+import spock.lang.Specification
+
+public class DefaultLocallyAvailableResourceTest extends Specification {
+ @Rule final TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider()
+
+ def "uses value from origin file"() {
+ given:
+ def origin = tmpDir.file("origin")
+ origin << "some text"
+
+ when:
+ def DefaultLocallyAvailableResource resource = new DefaultLocallyAvailableResource(origin)
+
+ then:
+ resource.sha1 == HashUtil.createHash(origin, 'SHA1')
+ resource.contentLength == origin.length()
+ resource.lastModified == origin.lastModified()
+ }
+
+ def "sha1 content length and last modified do not change when file is subsequently modified"() {
+ given:
+ def origin = tmpDir.file("origin")
+ origin << "some text"
+
+
+ when:
+ def DefaultLocallyAvailableResource resource = new DefaultLocallyAvailableResource(origin)
+ def originalSha1 = resource.sha1
+ def originalContentLength = resource.contentLength
+ def originalLastModified = resource.lastModified
+
+ and:
+ origin << "some more text"
+ origin.setLastModified(11)
+
+ then:
+ resource.sha1 != HashUtil.createHash(origin, 'SHA1')
+ resource.contentLength != origin.length()
+ resource.lastModified != origin.lastModified()
+
+ and:
+ resource.sha1 == originalSha1
+ resource.contentLength == originalContentLength
+ resource.lastModified == originalLastModified
+ }
+}
diff --git a/subprojects/scala/scala.gradle b/subprojects/scala/scala.gradle
index d06a73a..59f983f 100644
--- a/subprojects/scala/scala.gradle
+++ b/subprojects/scala/scala.gradle
@@ -17,15 +17,18 @@
apply from: "$rootDir/gradle/providedConfiguration.gradle"
dependencies {
- groovy libraries.groovy
+ compile libraries.groovy
compile project(":core")
+ compile project(":languageJvm")
compile project(":plugins")
// keep in sync with ScalaBasePlugin code
provided("com.typesafe.zinc:zinc:0.2.1")
testCompile libraries.slf4j_api
+
+ integTestRuntime project(":ide")
}
useTestFixtures(project: ":plugins") // includes core test fixtures
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/ScalaPluginGoodBehaviourTest.groovy b/subprojects/scala/src/integTest/groovy/org/gradle/integtests/ScalaPluginGoodBehaviourTest.groovy
similarity index 100%
rename from subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/ScalaPluginGoodBehaviourTest.groovy
rename to subprojects/scala/src/integTest/groovy/org/gradle/integtests/ScalaPluginGoodBehaviourTest.groovy
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/ScalaProjectIntegrationTest.java b/subprojects/scala/src/integTest/groovy/org/gradle/integtests/ScalaProjectIntegrationTest.java
similarity index 100%
rename from subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/ScalaProjectIntegrationTest.java
rename to subprojects/scala/src/integTest/groovy/org/gradle/integtests/ScalaProjectIntegrationTest.java
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesMixedJavaAndScalaIntegrationTest.groovy b/subprojects/scala/src/integTest/groovy/org/gradle/integtests/samples/SamplesMixedJavaAndScalaIntegrationTest.groovy
similarity index 100%
rename from subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesMixedJavaAndScalaIntegrationTest.groovy
rename to subprojects/scala/src/integTest/groovy/org/gradle/integtests/samples/SamplesMixedJavaAndScalaIntegrationTest.groovy
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesScalaCustomizedLayoutIntegrationTest.groovy b/subprojects/scala/src/integTest/groovy/org/gradle/integtests/samples/SamplesScalaCustomizedLayoutIntegrationTest.groovy
similarity index 100%
rename from subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesScalaCustomizedLayoutIntegrationTest.groovy
rename to subprojects/scala/src/integTest/groovy/org/gradle/integtests/samples/SamplesScalaCustomizedLayoutIntegrationTest.groovy
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesScalaQuickstartIntegrationTest.groovy b/subprojects/scala/src/integTest/groovy/org/gradle/integtests/samples/SamplesScalaQuickstartIntegrationTest.groovy
similarity index 100%
rename from subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesScalaQuickstartIntegrationTest.groovy
rename to subprojects/scala/src/integTest/groovy/org/gradle/integtests/samples/SamplesScalaQuickstartIntegrationTest.groovy
diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesScalaZincIntegrationTest.groovy b/subprojects/scala/src/integTest/groovy/org/gradle/integtests/samples/SamplesScalaZincIntegrationTest.groovy
similarity index 100%
rename from subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/SamplesScalaZincIntegrationTest.groovy
rename to subprojects/scala/src/integTest/groovy/org/gradle/integtests/samples/SamplesScalaZincIntegrationTest.groovy
diff --git a/subprojects/scala/src/integTest/groovy/org/gradle/scala/ScalaBasePluginIntegrationTest.groovy b/subprojects/scala/src/integTest/groovy/org/gradle/scala/ScalaBasePluginIntegrationTest.groovy
index a770434..9a4838a 100644
--- a/subprojects/scala/src/integTest/groovy/org/gradle/scala/ScalaBasePluginIntegrationTest.groovy
+++ b/subprojects/scala/src/integTest/groovy/org/gradle/scala/ScalaBasePluginIntegrationTest.groovy
@@ -18,7 +18,8 @@ package org.gradle.scala
import org.gradle.integtests.fixtures.AbstractIntegrationSpec
class ScalaBasePluginIntegrationTest extends AbstractIntegrationSpec {
- def "defaults scalaClasspath to inferred Scala compiler dependency if scalaTools configuration is empty"() {
+ def "defaults scalaClasspath to 'scalaTools' configuration if the latter is non-empty"() {
+ executer.withDeprecationChecksDisabled()
file("build.gradle") << """
apply plugin: "scala-base"
@@ -29,8 +30,38 @@ sourceSets {
repositories {
mavenCentral()
}
+
+dependencies {
+ scalaTools "org.scala-lang:scala-compiler:2.10.1"
+}
+
+task scaladoc(type: ScalaDoc)
+
+task verify << {
+ assert compileCustomScala.scalaClasspath.is(configurations.scalaTools)
+ assert scalaCustomConsole.classpath.is(configurations.scalaTools)
+ assert scaladoc.scalaClasspath.is(configurations.scalaTools)
+}
+"""
+
+ expect:
+ succeeds("verify")
+ }
+
+ def "defaults scalaClasspath to inferred Scala compiler dependency if 'scalaTools' configuration is empty"() {
+ file("build.gradle") << """
+apply plugin: "scala-base"
+
+sourceSets {
+ custom
+}
+
+repositories {
+ mavenCentral()
+}
+
dependencies {
- customCompile "org.scala-lang:scala-library:2.9.2"
+ customCompile "org.scala-lang:scala-library:2.10.1"
}
task scaladoc(type: ScalaDoc) {
@@ -38,9 +69,9 @@ task scaladoc(type: ScalaDoc) {
}
task verify << {
- assert compileCustomScala.scalaClasspath.files.any { it.name == "scala-compiler-2.9.2.jar" }
- assert scalaCustomConsole.classpath.files.any { it.name == "scala-compiler-2.9.2.jar" }
- assert scaladoc.scalaClasspath.files.any { it.name == "scala-compiler-2.9.2.jar" }
+ assert compileCustomScala.scalaClasspath.files.any { it.name == "scala-compiler-2.10.1.jar" }
+ assert scalaCustomConsole.classpath.files.any { it.name == "scala-compiler-2.10.1.jar" }
+ assert scaladoc.scalaClasspath.files.any { it.name == "scala-compiler-2.10.1.jar" }
}
"""
@@ -48,7 +79,7 @@ task verify << {
succeeds("verify")
}
- def "defaults scalaClasspath to (empty) scalaTools configuration if Scala compiler dependency isn't found on class path"() {
+ def "only resolves source class path feeding into inferred Scala class path if/when the latter is actually used (but not during autowiring)"() {
file("build.gradle") << """
apply plugin: "scala-base"
@@ -60,16 +91,51 @@ repositories {
mavenCentral()
}
-task scaladoc(type: ScalaDoc)
+dependencies {
+ customCompile "org.scala-lang:scala-library:2.10.1"
+}
+
+task scaladoc(type: ScalaDoc) {
+ classpath = sourceSets.custom.runtimeClasspath
+}
task verify << {
- assert compileCustomScala.scalaClasspath.is(configurations.scalaTools)
- assert scalaCustomConsole.classpath.is(configurations.scalaTools)
- assert scaladoc.scalaClasspath.is(configurations.scalaTools)
+ assert configurations.customCompile.state.toString() == "UNRESOLVED"
+ assert configurations.customRuntime.state.toString() == "UNRESOLVED"
}
-"""
+ """
expect:
succeeds("verify")
}
+
+ def "not specifying a scala runtime produces decent error message"() {
+ given:
+ buildFile << """
+ apply plugin: "scala-base"
+
+ sourceSets {
+ main {}
+ }
+
+ repositories {
+ mavenCentral()
+ }
+
+ dependencies {
+ compile "com.google.guava:guava:11.0.2"
+ }
+ """
+
+ file("src/main/scala/Thing.scala") << """
+ class Thing
+ """
+
+ when:
+ fails "compileScala"
+
+ then:
+ failure.assertHasDescription "Cannot infer Scala class path because no Scala library Jar was found on class path: configuration ':compile'"
+ }
+
}
\ No newline at end of file
diff --git a/subprojects/scala/src/integTest/groovy/org/gradle/scala/environment/JreJavaHomeScalaIntegrationTest.groovy b/subprojects/scala/src/integTest/groovy/org/gradle/scala/environment/JreJavaHomeScalaIntegrationTest.groovy
index bcccb82..ee032c0 100644
--- a/subprojects/scala/src/integTest/groovy/org/gradle/scala/environment/JreJavaHomeScalaIntegrationTest.groovy
+++ b/subprojects/scala/src/integTest/groovy/org/gradle/scala/environment/JreJavaHomeScalaIntegrationTest.groovy
@@ -26,6 +26,7 @@ import spock.lang.Unroll
class JreJavaHomeScalaIntegrationTest extends AbstractIntegrationSpec {
@IgnoreIf({ AvailableJavaHomes.bestJre == null})
+ @Requires(TestPrecondition.JDK6)
@Unroll
def "scala java cross compilation works in forking mode = #forkMode when JAVA_HOME is set to JRE"() {
given:
@@ -51,8 +52,9 @@ class JreJavaHomeScalaIntegrationTest extends AbstractIntegrationSpec {
compile 'org.scala-lang:scala-library:2.9.2'
}
- compileScala{
- options.fork = ${forkMode}
+ compileScala {
+ scalaCompileOptions.useAnt = ${useAnt}
+ scalaCompileOptions.fork = ${forkMode}
}
"""
when:
@@ -62,7 +64,11 @@ class JreJavaHomeScalaIntegrationTest extends AbstractIntegrationSpec {
file("build/classes/main/org/test/ScalaClazz.class").exists()
where:
- forkMode << [false, true]
+ forkMode | useAnt
+// false | false
+ false | true
+ true | false
+ true | true
}
@Requires(TestPrecondition.WINDOWS)
diff --git a/subprojects/scala/src/main/groovy/org/gradle/api/internal/tasks/scala/AntScalaCompiler.groovy b/subprojects/scala/src/main/groovy/org/gradle/api/internal/tasks/scala/AntScalaCompiler.groovy
index 3363d40..d624935 100644
--- a/subprojects/scala/src/main/groovy/org/gradle/api/internal/tasks/scala/AntScalaCompiler.groovy
+++ b/subprojects/scala/src/main/groovy/org/gradle/api/internal/tasks/scala/AntScalaCompiler.groovy
@@ -101,7 +101,7 @@ class AntScalaCompiler implements Compiler<ScalaCompileSpec> {
if (target <= VersionNumber.parse("1.5")) { return "jvm-${target.major}.${target.minor}" }
def scalaVersion = sniffScalaVersion(spec.scalaClasspath)
- if (scalaVersion >= VersionNumber.parse("2.10.0-M5") || scalaVersion == VersionNumber.parse("2.10.0")) {
+ if (scalaVersion >= VersionNumber.parse("2.10.0-M5")) {
return "jvm-${target.major}.${target.minor}"
}
diff --git a/subprojects/scala/src/main/groovy/org/gradle/api/internal/tasks/scala/IncrementalScalaCompiler.java b/subprojects/scala/src/main/groovy/org/gradle/api/internal/tasks/scala/IncrementalScalaCompiler.java
index 43fb239..7822d5a 100644
--- a/subprojects/scala/src/main/groovy/org/gradle/api/internal/tasks/scala/IncrementalScalaCompiler.java
+++ b/subprojects/scala/src/main/groovy/org/gradle/api/internal/tasks/scala/IncrementalScalaCompiler.java
@@ -18,6 +18,8 @@ package org.gradle.api.internal.tasks.scala;
import org.gradle.api.internal.TaskOutputsInternal;
import org.gradle.api.internal.tasks.compile.*;
import org.gradle.api.internal.tasks.compile.Compiler;
+import org.gradle.language.jvm.internal.SimpleStaleClassCleaner;
+import org.gradle.language.jvm.internal.StaleClassCleaner;
public class IncrementalScalaCompiler extends IncrementalJavaCompilerSupport<ScalaJavaJointCompileSpec>
implements Compiler<ScalaJavaJointCompileSpec> {
diff --git a/subprojects/scala/src/main/groovy/org/gradle/api/internal/tasks/scala/NormalizingScalaCompiler.java b/subprojects/scala/src/main/groovy/org/gradle/api/internal/tasks/scala/NormalizingScalaCompiler.java
index baf4054..acd789b 100644
--- a/subprojects/scala/src/main/groovy/org/gradle/api/internal/tasks/scala/NormalizingScalaCompiler.java
+++ b/subprojects/scala/src/main/groovy/org/gradle/api/internal/tasks/scala/NormalizingScalaCompiler.java
@@ -19,8 +19,10 @@ package org.gradle.api.internal.tasks.scala;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import org.gradle.api.internal.file.collections.SimpleFileCollection;
-import org.gradle.api.internal.tasks.compile.*;
+import org.gradle.api.internal.tasks.SimpleWorkResult;
+import org.gradle.api.internal.tasks.compile.CompilationFailedException;
import org.gradle.api.internal.tasks.compile.Compiler;
+import org.gradle.api.internal.tasks.compile.JavaCompilerArgumentsBuilder;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
import org.gradle.api.tasks.WorkResult;
diff --git a/subprojects/scala/src/main/groovy/org/gradle/api/internal/tasks/scala/jdk6/ZincScalaCompiler.java b/subprojects/scala/src/main/groovy/org/gradle/api/internal/tasks/scala/jdk6/ZincScalaCompiler.java
index 0d1b980..4abd158 100644
--- a/subprojects/scala/src/main/groovy/org/gradle/api/internal/tasks/scala/jdk6/ZincScalaCompiler.java
+++ b/subprojects/scala/src/main/groovy/org/gradle/api/internal/tasks/scala/jdk6/ZincScalaCompiler.java
@@ -22,13 +22,12 @@ import com.typesafe.zinc.Inputs;
import com.typesafe.zinc.SbtJars;
import com.typesafe.zinc.ScalaLocation;
import com.typesafe.zinc.Setup;
-
import org.gradle.api.GradleException;
import org.gradle.api.JavaVersion;
+import org.gradle.api.internal.tasks.SimpleWorkResult;
import org.gradle.api.internal.tasks.compile.CompilationFailedException;
import org.gradle.api.internal.tasks.compile.Compiler;
import org.gradle.api.internal.tasks.compile.JavaCompilerArgumentsBuilder;
-import org.gradle.api.internal.tasks.compile.SimpleWorkResult;
import org.gradle.api.internal.tasks.scala.ScalaCompilerArgumentsGenerator;
import org.gradle.api.internal.tasks.scala.ScalaJavaJointCompileSpec;
import org.gradle.api.logging.Logger;
diff --git a/subprojects/scala/src/main/groovy/org/gradle/api/plugins/scala/ScalaBasePlugin.groovy b/subprojects/scala/src/main/groovy/org/gradle/api/plugins/scala/ScalaBasePlugin.groovy
index cf25d89..ecc9b00 100644
--- a/subprojects/scala/src/main/groovy/org/gradle/api/plugins/scala/ScalaBasePlugin.groovy
+++ b/subprojects/scala/src/main/groovy/org/gradle/api/plugins/scala/ScalaBasePlugin.groovy
@@ -15,130 +15,86 @@
*/
package org.gradle.api.plugins.scala
-import org.gradle.api.Incubating
-import org.gradle.api.Nullable;
import org.gradle.api.Plugin
import org.gradle.api.Project
-import org.gradle.api.file.FileCollection
+import org.gradle.api.artifacts.Configuration
import org.gradle.api.file.FileTreeElement
-import org.gradle.api.internal.artifacts.dependencies.DefaultExternalModuleDependency
import org.gradle.api.internal.file.FileResolver
import org.gradle.api.internal.tasks.DefaultScalaSourceSet
import org.gradle.api.plugins.JavaBasePlugin
import org.gradle.api.plugins.JavaPluginConvention
import org.gradle.api.reporting.ReportingExtension
+import org.gradle.api.tasks.ScalaRuntime
import org.gradle.api.tasks.SourceSet
import org.gradle.api.tasks.scala.ScalaCompile
import org.gradle.api.tasks.scala.ScalaDoc
import org.gradle.api.tasks.JavaExec
+import org.gradle.util.DeprecationLogger
import javax.inject.Inject
-import java.util.regex.Pattern
class ScalaBasePlugin implements Plugin<Project> {
- // public configurations
+ /**
+ * The name of the configuration holding the Scala compiler and tools.
+ *
+ * @deprecated Typically, usages of {@code scalaTools} can simply be removed,
+ * and the Scala tools libraries to be used will be inferred from the Scala
+ * library found on the regular (compile) class path. In some cases, it may
+ * be necessary to additionally configure the {@code scalaClasspath} property
+ * of {@code ScalaCompile} and {@code ScalaDoc} tasks.
+ */
static final String SCALA_TOOLS_CONFIGURATION_NAME = "scalaTools"
+
static final String ZINC_CONFIGURATION_NAME = "zinc"
+ static final String SCALA_RUNTIME_EXTENSION_NAME = "scalaRuntime"
+
private static final String DEFAULT_ZINC_VERSION = "0.2.1"
- private static final Pattern SCALA_JAR_PATTERN = Pattern.compile("scala-(\\w.*?)-(\\d.*).jar")
- private Project project
private final FileResolver fileResolver
+ private Project project
+ private ScalaRuntime scalaRuntime
+
@Inject
ScalaBasePlugin(FileResolver fileResolver) {
this.fileResolver = fileResolver
}
- /**
- * Infers a Scala compiler class path (containing a 'scala-compiler' Jar and its dependencies)
- * based on the 'scala-library' Jar found on the specified class path.
- *
- * <p>Falls back to returning the 'scalaTools' configuration if one of the following holds:
- *
- * <ol>
- * <li>The 'scalaTools' configuration is explicitly configured (ie. has dependencies declared).
- * This is important for backwards compatibility.</li>
- * <li>No repository is declared for the project.</li>
- * <li>A 'scala-library' Jar cannot be found on the specified class path, or its
- * version cannot be determined.</li>
- * </ol>
- *
- * Note that the returned class path may be empty, or may fail to resolve when asked for its contents.
- * If this happens at task execution time, it should usually be treated as a configuration error on part of the user.
- *
- * @param classpath a class path (supposedly) containing a 'scala-library' Jar
- * @return a Scala compiler class path
- */
- @Incubating
- FileCollection inferScalaCompilerClasspath(Iterable<File> classpath) {
- def scalaTools = project.configurations[SCALA_TOOLS_CONFIGURATION_NAME]
- if (!scalaTools.dependencies.empty || project.repositories.empty) { return scalaTools }
-
- def scalaLibraryJar = findScalaJar(classpath, "library")
- if (scalaLibraryJar == null) { return scalaTools }
-
- def scalaVersion = getScalaVersion(scalaLibraryJar)
- if (scalaVersion == null) {
- throw new AssertionError("Unexpectedly failed to determine version of Scala Jar file: $scalaLibraryJar")
- }
-
- return project.configurations.detachedConfiguration(
- new DefaultExternalModuleDependency("org.scala-lang", "scala-compiler", scalaVersion))
- }
-
- /**
- * Searches the specified class path for a Scala Jar file matching the specified
- * module (compiler, library, jdbc, etc.).
- *
- * @param classpath the class path to search
- * @param module the module to search for
- * @return a matching Scala Jar file, or {@code null} if no match was found
- */
- @Nullable
- @Incubating
- File findScalaJar(Iterable<File> classpath, String module) {
- for (file in classpath) {
- def matcher = SCALA_JAR_PATTERN.matcher(file.name)
- if (matcher.matches() && matcher.group(1) == module) {
- return file
- }
- }
- return null
- }
-
- /**
- * Determines the version of a Scala Jar file (scala-compiler, scala-library, scala-jdbc, etc.).
- * If the version cannot be determined, {@code null} is returned.
- *
- * <p>Implementation note: The version is determined by parsing the file name, which
- * is expected to match the pattern 'scala-[component]-[version].jar'.
- *
- * @param scalaJar a Scala Jar file
- * @return the version of the Jar file
- */
- @Nullable
- @Incubating
- String getScalaVersion(File scalaJar) {
- def matcher = SCALA_JAR_PATTERN.matcher(scalaJar.name)
- matcher.matches() ? matcher.group(2) : null
- }
-
void apply(Project project) {
this.project = project
def javaPlugin = project.plugins.apply(JavaBasePlugin.class)
- project.configurations.add(SCALA_TOOLS_CONFIGURATION_NAME)
+ configureConfigurations(project)
+ configureScalaRuntimeExtension()
+ configureCompileDefaults()
+ configureSourceSetDefaults(javaPlugin)
+ configureScaladoc()
+ }
+
+ private void configureConfigurations(Project project) {
+ def scalaToolsConfiguration = project.configurations.create(SCALA_TOOLS_CONFIGURATION_NAME)
.setVisible(false)
- .setDescription("The Scala tools libraries to be used for this Scala project.")
- project.configurations.add(ZINC_CONFIGURATION_NAME)
+ .setDescription("The Scala tools libraries to be used for this Scala project. (Deprecated)")
+ deprecateScalaToolsConfiguration(scalaToolsConfiguration)
+
+ project.configurations.create(ZINC_CONFIGURATION_NAME)
.setVisible(false)
.setDescription("The Zinc incremental compiler to be used for this Scala project.")
+ }
- configureCompileDefaults()
- configureSourceSetDefaults(javaPlugin)
- configureScaladoc()
+ private void deprecateScalaToolsConfiguration(Configuration scalaConfiguration) {
+ scalaConfiguration.dependencies.whenObjectAdded {
+ DeprecationLogger.nagUserOfDiscontinuedConfiguration(SCALA_TOOLS_CONFIGURATION_NAME,
+ "Typically, usages of 'scalaTools' can simply be removed, and the Scala tools libraries " +
+ "to be used will be inferred from the Scala library found on the regular (compile) class path. " +
+ "In some cases, it may be necessary to additionally configure the 'scalaClasspath' property of " +
+ "ScalaCompile and ScalaDoc tasks.");
+ }
+ }
+
+ private void configureScalaRuntimeExtension() {
+ scalaRuntime = project.extensions.create(SCALA_RUNTIME_EXTENSION_NAME, ScalaRuntime, project)
}
private void configureSourceSetDefaults(JavaBasePlugin javaPlugin) {
@@ -156,7 +112,7 @@ class ScalaBasePlugin implements Plugin<Project> {
private void configureScalaCompile(JavaBasePlugin javaPlugin, SourceSet sourceSet) {
def taskName = sourceSet.getCompileTaskName('scala')
- def scalaCompile = project.tasks.add(taskName, ScalaCompile)
+ def scalaCompile = project.tasks.create(taskName, ScalaCompile)
scalaCompile.dependsOn sourceSet.compileJavaTaskName
javaPlugin.configureForSourceSet(sourceSet, scalaCompile)
scalaCompile.description = "Compiles the $sourceSet.scala."
@@ -180,11 +136,11 @@ class ScalaBasePlugin implements Plugin<Project> {
private void configureScalaConsole(SourceSet sourceSet) {
def taskName = sourceSet.getTaskName("scala", "Console")
- def scalaConsole = project.tasks.add(taskName, JavaExec)
+ def scalaConsole = project.tasks.create(taskName, JavaExec)
scalaConsole.dependsOn(sourceSet.runtimeClasspath)
scalaConsole.description = "Starts a Scala REPL with the $sourceSet.name runtime class path."
scalaConsole.main = "scala.tools.nsc.MainGenericRunner"
- scalaConsole.conventionMapping.classpath = { inferScalaCompilerClasspath(sourceSet.runtimeClasspath) }
+ scalaConsole.conventionMapping.classpath = { scalaRuntime.inferScalaClasspath(sourceSet.runtimeClasspath) }
scalaConsole.systemProperty("scala.usejavacp", true)
scalaConsole.standardInput = System.in
scalaConsole.conventionMapping.jvmArgs = { ["-classpath", sourceSet.runtimeClasspath.asPath] }
@@ -192,7 +148,7 @@ class ScalaBasePlugin implements Plugin<Project> {
private void configureCompileDefaults() {
project.tasks.withType(ScalaCompile.class) { ScalaCompile compile ->
- compile.conventionMapping.scalaClasspath = { inferScalaCompilerClasspath(compile.classpath) }
+ compile.conventionMapping.scalaClasspath = { scalaRuntime.inferScalaClasspath(compile.classpath) }
compile.conventionMapping.zincClasspath = {
def config = project.configurations[ZINC_CONFIGURATION_NAME]
if (!compile.scalaCompileOptions.useAnt && config.dependencies.empty) {
@@ -209,7 +165,7 @@ class ScalaBasePlugin implements Plugin<Project> {
project.tasks.withType(ScalaDoc) { ScalaDoc scalaDoc ->
scalaDoc.conventionMapping.destinationDir = { project.file("$project.docsDir/scaladoc") }
scalaDoc.conventionMapping.title = { project.extensions.getByType(ReportingExtension).apiDocTitle }
- scalaDoc.conventionMapping.scalaClasspath = { inferScalaCompilerClasspath(scalaDoc.classpath) }
+ scalaDoc.conventionMapping.scalaClasspath = { scalaRuntime.inferScalaClasspath(scalaDoc.classpath) }
}
}
}
\ No newline at end of file
diff --git a/subprojects/scala/src/main/groovy/org/gradle/api/plugins/scala/ScalaPlugin.groovy b/subprojects/scala/src/main/groovy/org/gradle/api/plugins/scala/ScalaPlugin.groovy
index 0aa1beb..56fda28 100644
--- a/subprojects/scala/src/main/groovy/org/gradle/api/plugins/scala/ScalaPlugin.groovy
+++ b/subprojects/scala/src/main/groovy/org/gradle/api/plugins/scala/ScalaPlugin.groovy
@@ -15,7 +15,6 @@
*/
package org.gradle.api.plugins.scala;
-
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.plugins.JavaPlugin
@@ -38,8 +37,8 @@ public class ScalaPlugin implements Plugin<Project> {
scalaDoc.conventionMapping.classpath = { project.sourceSets.main.output + project.sourceSets.main.compileClasspath }
scalaDoc.source = project.sourceSets.main.scala
}
- ScalaDoc scalaDoc = project.tasks.add(SCALA_DOC_TASK_NAME, ScalaDoc.class)
- scalaDoc.description = "Generates scaladoc for the main source code.";
+ ScalaDoc scalaDoc = project.tasks.create(SCALA_DOC_TASK_NAME, ScalaDoc.class)
+ scalaDoc.description = "Generates Scaladoc for the main source code.";
scalaDoc.group = JavaBasePlugin.DOCUMENTATION_GROUP
}
}
diff --git a/subprojects/scala/src/main/groovy/org/gradle/api/tasks/ScalaRuntime.groovy b/subprojects/scala/src/main/groovy/org/gradle/api/tasks/ScalaRuntime.groovy
new file mode 100644
index 0000000..7a1f5d0
--- /dev/null
+++ b/subprojects/scala/src/main/groovy/org/gradle/api/tasks/ScalaRuntime.groovy
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.tasks
+
+import org.gradle.api.GradleException
+import org.gradle.api.Incubating
+import org.gradle.api.Nullable
+import org.gradle.api.Project
+import org.gradle.api.Buildable
+import org.gradle.api.Task
+import org.gradle.api.file.FileCollection
+import org.gradle.api.internal.artifacts.dependencies.DefaultExternalModuleDependency
+import org.gradle.api.internal.file.collections.LazilyInitializedFileCollection
+import org.gradle.api.plugins.scala.ScalaBasePlugin
+
+import java.util.regex.Pattern
+
+/**
+ * Provides information related to the Scala runtime(s) used in a project. Added by the
+ * {@link ScalaBasePlugin} as a project extension named {@code scalaRuntime}.
+ *
+ * <p>Example usage:
+ *
+ * <pre autoTested="">
+ * apply plugin: "scala"
+ *
+ * repositories {
+ * mavenCentral()
+ * }
+ *
+ * dependencies {
+ * compile "org.scala-lang:scala-library:2.10.1"
+ * }
+ *
+ * def scalaClasspath = scalaRuntime.inferScalaClasspath(configurations.compile)
+ * // The returned class path can be used to configure the 'scalaClasspath' property of tasks
+ * // such as 'ScalaCompile' or 'ScalaDoc', or to execute these and other Scala tools directly.
+ * </pre>
+ */
+ at Incubating
+class ScalaRuntime {
+ private static final Pattern SCALA_JAR_PATTERN = Pattern.compile("scala-(\\w.*?)-(\\d.*).jar")
+
+ // should be private but Groovy can't handle this
+ protected final Project project
+
+ ScalaRuntime(Project project) {
+ this.project = project
+ }
+
+ /**
+ * Searches the specified class path for a 'scala-library' Jar, and returns a class path
+ * containing a corresponding (same version) 'scala-compiler' Jar and its dependencies.
+ *
+ * <p>If the (deprecated) 'scalaTools' configuration is explicitly configured, no repository
+ * is declared for the project, no 'scala-library' Jar is found on the specified class path,
+ * or its version cannot be determined, a class path with the contents of the 'scalaTools'
+ * configuration is returned.
+ *
+ * <p>The returned class path may be empty, or may fail to resolve when asked for its contents.
+ *
+ * @param classpath a class path containing a 'scala-library' Jar
+ * @return a class path containing a corresponding 'scala-compiler' Jar and its dependencies
+ */
+ FileCollection inferScalaClasspath(Iterable<File> classpath) {
+ def scalaTools = project.configurations[ScalaBasePlugin.SCALA_TOOLS_CONFIGURATION_NAME]
+ if (!scalaTools.dependencies.empty) {
+ return scalaTools
+ }
+
+ // alternatively, we could return project.files(Runnable)
+ // would differ in the following ways: 1. live (not sure if we want live here) 2. no autowiring (probably want autowiring here)
+ return new LazilyInitializedFileCollection() {
+ @Override
+ FileCollection createDelegate() {
+ if (project.repositories.empty) {
+ throw new GradleException("Cannot infer Scala class path because no repository is declared for the project.")
+ }
+
+ def scalaLibraryJar = findScalaJar(classpath, "library")
+ if (scalaLibraryJar == null) {
+ throw new GradleException("Cannot infer Scala class path because no Scala library Jar was found on class path: $classpath")
+ }
+
+ def scalaVersion = getScalaVersion(scalaLibraryJar)
+ if (scalaVersion == null) {
+ throw new AssertionError("Unexpectedly failed to parse version of Scala Jar file: $scalaLibraryJar")
+ }
+
+ return project.configurations.detachedConfiguration(
+ new DefaultExternalModuleDependency("org.scala-lang", "scala-compiler", scalaVersion))
+ }
+
+ // let's override this so that delegate isn't created at autowiring time (which would mean on every build)
+ @Override
+ TaskDependency getBuildDependencies() {
+ if (classpath instanceof Buildable) {
+ return classpath.buildDependencies
+ }
+ return new TaskDependency() {
+ Set<? extends Task> getDependencies(Task task) {
+ Collections.emptySet()
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Searches the specified class path for a Scala Jar file (scala-compiler, scala-library,
+ * scala-jdbc, etc.) with the specified appendix (compiler, library, jdbc, etc.).
+ * If no such file is found, {@code null} is returned.
+ *
+ * @param classpath the class path to search
+ * @param appendix the appendix to search for
+ * @return a Scala Jar file with the specified appendix
+ */
+ @Nullable
+ File findScalaJar(Iterable<File> classpath, String appendix) {
+ for (file in classpath) {
+ def matcher = SCALA_JAR_PATTERN.matcher(file.name)
+ if (matcher.matches() && matcher.group(1) == appendix) {
+ return file
+ }
+ }
+ return null
+ }
+
+ /**
+ * Determines the version of a Scala Jar file (scala-compiler, scala-library,
+ * scala-jdbc, etc.). If the version cannot be determined, or the file is not a Scala
+ * Jar file, {@code null} is returned.
+ *
+ * <p>Implementation note: The version is determined by parsing the file name, which
+ * is expected to match the pattern 'scala-[component]-[version].jar'.
+ *
+ * @param scalaJar a Scala Jar file
+ * @return the version of the Scala Jar file
+ */
+ @Nullable
+ String getScalaVersion(File scalaJar) {
+ def matcher = SCALA_JAR_PATTERN.matcher(scalaJar.name)
+ matcher.matches() ? matcher.group(2) : null
+ }
+}
diff --git a/subprojects/scala/src/main/groovy/org/gradle/api/tasks/scala/ScalaCompile.java b/subprojects/scala/src/main/groovy/org/gradle/api/tasks/scala/ScalaCompile.java
index 3e36208..ddc1576 100644
--- a/subprojects/scala/src/main/groovy/org/gradle/api/tasks/scala/ScalaCompile.java
+++ b/subprojects/scala/src/main/groovy/org/gradle/api/tasks/scala/ScalaCompile.java
@@ -135,7 +135,8 @@ public class ScalaCompile extends AbstractCompile {
private void checkScalaClasspathIsNonEmpty() {
if (getScalaClasspath().isEmpty()) {
- throw new InvalidUserDataException("'" + getName() + ".scalaClasspath' must not be empty");
+ throw new InvalidUserDataException("'" + getName() + ".scalaClasspath' must not be empty. If a Scala compile dependency is provided, "
+ + "the 'scala-base' plugin will attempt to configure 'scalaClasspath' automatically. Alternatively, you may configure 'scalaClasspath' explicitly.");
}
}
diff --git a/subprojects/scala/src/test/groovy/org/gradle/api/plugins/scala/ScalaBasePluginTest.groovy b/subprojects/scala/src/test/groovy/org/gradle/api/plugins/scala/ScalaBasePluginTest.groovy
index 0cfb847..939b15f 100644
--- a/subprojects/scala/src/test/groovy/org/gradle/api/plugins/scala/ScalaBasePluginTest.groovy
+++ b/subprojects/scala/src/test/groovy/org/gradle/api/plugins/scala/ScalaBasePluginTest.groovy
@@ -23,8 +23,8 @@ import org.gradle.api.tasks.bundling.Jar
import org.gradle.api.tasks.scala.ScalaCompile
import org.gradle.api.tasks.scala.ScalaDoc
import org.gradle.api.artifacts.Configuration
-import org.gradle.util.HelperUtil
-
+import org.gradle.util.TestUtil
+import org.junit.Before
import org.junit.Test
import static org.gradle.util.Matchers.dependsOn
@@ -35,45 +35,25 @@ import static org.hamcrest.Matchers.*
import static org.junit.Assert.*
public class ScalaBasePluginTest {
- private final Project project = HelperUtil.createRootProject()
+ private final Project project = TestUtil.createRootProject()
- @Test void appliesTheJavaPluginToTheProject() {
+ @Before
+ void before() {
project.plugins.apply(ScalaBasePlugin)
+ }
+
+ @Test void appliesTheJavaPluginToTheProject() {
assertTrue(project.getPlugins().hasPlugin(JavaBasePlugin))
}
@Test void addsScalaToolsConfigurationToTheProject() {
- project.plugins.apply(ScalaBasePlugin)
def configuration = project.configurations.getByName(ScalaBasePlugin.SCALA_TOOLS_CONFIGURATION_NAME)
assertThat(Configurations.getNames(configuration.extendsFrom, false), equalTo(toSet()))
assertFalse(configuration.visible)
assertTrue(configuration.transitive)
}
- @Test void defaultsScalaClasspathToScalaToolsConfigurationIfTheLatterIsNonEmpty() {
- project.plugins.apply(ScalaBasePlugin)
- project.sourceSets.add('custom')
- def configuration = project.configurations.scalaTools
- project.dependencies {
- scalaTools "org.scala-lang:scala-compiler:2.10"
- }
-
- def compileTask = project.tasks.compileCustomScala
- assertSame(configuration, compileTask.scalaClasspath)
-
- def consoleTask = project.tasks.scalaCustomConsole
- assertSame(configuration, consoleTask.classpath)
-
- def scaladocTask = project.task("scaladoc", type: ScalaDoc)
- assertSame(configuration, scaladocTask.scalaClasspath)
- }
-
- // see ScalaBasePluginIntegrationTest
- @Test void defaultsScalaClasspathToInferredScalaCompilerDependencyIfScalaToolsConfigurationIsEmpty() {
- }
-
@Test void addsZincConfigurationToTheProject() {
- project.plugins.apply(ScalaBasePlugin)
def configuration = project.configurations.getByName(ScalaBasePlugin.ZINC_CONFIGURATION_NAME)
assertThat(Configurations.getNames(configuration.extendsFrom, false), equalTo(toSet()))
assertFalse(configuration.visible)
@@ -81,8 +61,7 @@ public class ScalaBasePluginTest {
}
@Test void preconfiguresZincClasspathForCompileTasksThatUseZinc() {
- project.plugins.apply(ScalaBasePlugin)
- project.sourceSets.add('custom')
+ project.sourceSets.create('custom')
def task = project.tasks.compileCustomScala
task.scalaCompileOptions.useAnt = false
assert task.zincClasspath instanceof Configuration
@@ -90,8 +69,7 @@ public class ScalaBasePluginTest {
}
@Test void doesNotPreconfigureZincClasspathForCompileTasksThatUseAnt() {
- project.plugins.apply(ScalaBasePlugin)
- project.sourceSets.add('custom')
+ project.sourceSets.create('custom')
def task = project.tasks.compileCustomScala
task.scalaCompileOptions.useAnt = true
assert task.zincClasspath instanceof Configuration
@@ -99,31 +77,24 @@ public class ScalaBasePluginTest {
}
@Test void addsScalaConventionToNewSourceSet() {
- project.plugins.apply(ScalaBasePlugin)
-
- def sourceSet = project.sourceSets.add('custom')
+ def sourceSet = project.sourceSets.create('custom')
assertThat(sourceSet.scala.displayName, equalTo("custom Scala source"))
assertThat(sourceSet.scala.srcDirs, equalTo(toLinkedSet(project.file("src/custom/scala"))))
}
@Test void addsCompileTaskForNewSourceSet() {
- project.plugins.apply(ScalaBasePlugin)
-
- project.sourceSets.add('custom')
+ project.sourceSets.create('custom')
def task = project.tasks['compileCustomScala']
assertThat(task, instanceOf(ScalaCompile.class))
assertThat(task.description, equalTo('Compiles the custom Scala source.'))
assertThat(task.classpath, equalTo(project.sourceSets.custom.compileClasspath))
- assertThat(task.scalaClasspath, equalTo(project.configurations[ScalaBasePlugin.SCALA_TOOLS_CONFIGURATION_NAME]))
assertThat(task.source as List, equalTo(project.sourceSets.custom.scala as List))
assertThat(task, dependsOn('compileCustomJava'))
}
@Test void preconfiguresIncrementalCompileOptions() {
- project.plugins.apply(ScalaBasePlugin)
-
- project.sourceSets.add('custom')
- project.tasks.add('customJar', Jar)
+ project.sourceSets.create('custom')
+ project.tasks.create('customJar', Jar)
ScalaCompile task = project.tasks['compileCustomScala']
project.gradle.buildListenerBroadcaster.projectsEvaluated(project.gradle)
@@ -132,10 +103,8 @@ public class ScalaBasePluginTest {
}
@Test void incrementalCompileOptionsCanBeOverridden() {
- project.plugins.apply(ScalaBasePlugin)
-
- project.sourceSets.add('custom')
- project.tasks.add('customJar', Jar)
+ project.sourceSets.create('custom')
+ project.tasks.create('customJar', Jar)
ScalaCompile task = project.tasks['compileCustomScala']
task.scalaCompileOptions.incrementalOptions.analysisFile = new File("/my/file")
task.scalaCompileOptions.incrementalOptions.publishedCode = new File("/my/published/code.jar")
@@ -146,96 +115,21 @@ public class ScalaBasePluginTest {
}
@Test void dependenciesOfJavaPluginTasksIncludeScalaCompileTasks() {
- project.plugins.apply(ScalaBasePlugin)
-
- project.sourceSets.add('custom')
+ project.sourceSets.create('custom')
def task = project.tasks['customClasses']
assertThat(task, dependsOn(hasItem('compileCustomScala')))
}
@Test void configuresCompileTasksDefinedByTheBuildScript() {
- project.plugins.apply(ScalaBasePlugin)
-
def task = project.task('otherCompile', type: ScalaCompile)
assertThat(task.source, isEmpty())
- assertThat(task.scalaClasspath, equalTo(project.configurations[ScalaBasePlugin.SCALA_TOOLS_CONFIGURATION_NAME]))
assertThat(task, dependsOn())
}
@Test void configuresScalaDocTasksDefinedByTheBuildScript() {
- project.plugins.apply(ScalaBasePlugin)
-
def task = project.task('otherScaladoc', type: ScalaDoc)
assertThat(task.destinationDir, equalTo(project.file("$project.docsDir/scaladoc")))
assertThat(task.title, equalTo(project.extensions.getByType(ReportingExtension).apiDocTitle))
- assertThat(task.scalaClasspath, equalTo(project.configurations[ScalaBasePlugin.SCALA_TOOLS_CONFIGURATION_NAME]))
assertThat(task, dependsOn())
}
-
- @Test void allowsToInferScalaCompilerClasspath() {
- def plugin = project.plugins.apply(ScalaBasePlugin)
-
- project.repositories {
- mavenCentral()
- }
-
- def classpath = plugin.inferScalaCompilerClasspath([new File("other.jar"), new File("scala-library-2.10.0.jar")])
-
- assert classpath instanceof Configuration
- assert classpath.state == Configuration.State.UNRESOLVED
- assert classpath.dependencies.size() == 1
- classpath.dependencies.iterator().next().with {
- assert group == "org.scala-lang"
- assert name == "scala-compiler"
- assert version == "2.10.0"
- }
- }
-
- @Test void inferenceFallsBackToScalaToolsIfNoRepositoryDeclared() {
- def plugin = project.plugins.apply(ScalaBasePlugin)
-
- def classpath = plugin.inferScalaCompilerClasspath([new File("other.jar"), new File("scala-library-2.10.0.jar")])
-
- assert classpath == project.configurations.scalaTools
- }
-
- @Test void inferenceFallsBackToScalaToolsIfScalaLibraryNotFoundOnClassPath() {
- def plugin = project.plugins.apply(ScalaBasePlugin)
-
- def classpath = plugin.inferScalaCompilerClasspath([new File("other.jar"), new File("other2.jar")])
-
- assert classpath == project.configurations.scalaTools
- }
-
- @Test void allowsToFindScalaJarInClassPath() {
- def plugin = project.plugins.apply(ScalaBasePlugin)
-
- def file = plugin.findScalaJar([new File("other.jar"), new File("scala-jdbc-1.5.jar"), new File("scala-compiler-1.7.jar")], "jdbc")
-
- assert file.name == "scala-jdbc-1.5.jar"
- }
-
- @Test void returnsNullIfScalaJarNotFound() {
- def plugin = project.plugins.apply(ScalaBasePlugin)
-
- def file = plugin.findScalaJar([new File("other.jar"), new File("scala-jdbc-1.5.jar"), new File("scala-compiler-1.7.jar")], "library")
-
- assert file == null
- }
-
- @Test void allowsToDetermineVersionOfScalaJar() {
- def plugin = project.plugins.apply(ScalaBasePlugin)
-
- assert plugin.getScalaVersion(new File("scala-compiler-2.9.2.jar")) == "2.9.2"
- assert plugin.getScalaVersion(new File("scala-jdbc-2.9.2.jar")) == "2.9.2"
- assert plugin.getScalaVersion(new File("scala-library-2.10.0-SNAPSHOT.jar")) == "2.10.0-SNAPSHOT"
- assert plugin.getScalaVersion(new File("scala-library-2.10.0-rc-3.jar")) == "2.10.0-rc-3"
- }
-
- @Test void returnsNullIfScalaVersionCannotBeDetermined() {
- def plugin = project.plugins.apply(ScalaBasePlugin)
-
- assert plugin.getScalaVersion(new File("scala-compiler.jar")) == null
- assert plugin.getScalaVersion(new File("groovy-compiler-2.1.0.jar")) == null
- }
}
\ No newline at end of file
diff --git a/subprojects/scala/src/test/groovy/org/gradle/api/plugins/scala/ScalaPluginTest.groovy b/subprojects/scala/src/test/groovy/org/gradle/api/plugins/scala/ScalaPluginTest.groovy
index 8c21a59..8245f87 100644
--- a/subprojects/scala/src/test/groovy/org/gradle/api/plugins/scala/ScalaPluginTest.groovy
+++ b/subprojects/scala/src/test/groovy/org/gradle/api/plugins/scala/ScalaPluginTest.groovy
@@ -20,8 +20,8 @@ import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.reporting.ReportingExtension
import org.gradle.api.tasks.scala.ScalaCompile
import org.gradle.api.tasks.scala.ScalaDoc
-import org.gradle.util.HelperUtil
import org.gradle.util.Matchers
+import org.gradle.util.TestUtil
import org.junit.Test
import static org.gradle.util.Matchers.dependsOn
@@ -31,7 +31,7 @@ import static org.junit.Assert.assertThat
import static org.junit.Assert.assertTrue
class ScalaPluginTest {
- private final Project project = HelperUtil.createRootProject()
+ private final Project project = TestUtil.createRootProject()
private final ScalaPlugin scalaPlugin = new ScalaPlugin()
@Test void appliesTheJavaPluginToTheProject() {
diff --git a/subprojects/scala/src/test/groovy/org/gradle/api/tasks/ScalaRuntimeTest.groovy b/subprojects/scala/src/test/groovy/org/gradle/api/tasks/ScalaRuntimeTest.groovy
new file mode 100644
index 0000000..f3863b7
--- /dev/null
+++ b/subprojects/scala/src/test/groovy/org/gradle/api/tasks/ScalaRuntimeTest.groovy
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.api.tasks
+
+import org.gradle.api.GradleException
+import org.gradle.api.artifacts.Configuration
+import org.gradle.api.internal.file.collections.LazilyInitializedFileCollection
+import org.gradle.api.plugins.scala.ScalaBasePlugin
+import org.gradle.util.TestUtil
+
+import spock.lang.Specification
+
+class ScalaRuntimeTest extends Specification {
+ def project = TestUtil.createRootProject()
+
+ def setup() {
+ project.plugins.apply(ScalaBasePlugin)
+ }
+
+ def "inferred Scala class path contains 'scala-compiler' repository dependency matching 'scala-library' Jar found on class path"() {
+ project.repositories {
+ mavenCentral()
+ }
+
+ when:
+ def classpath = project.scalaRuntime.inferScalaClasspath([new File("other.jar"), new File("scala-library-2.10.1.jar")])
+
+ then:
+ classpath instanceof LazilyInitializedFileCollection
+ with(classpath.delegate) {
+ it instanceof Configuration
+ it.state == Configuration.State.UNRESOLVED
+ it.dependencies.size() == 1
+ with(it.dependencies.iterator().next()) {
+ group == "org.scala-lang"
+ name == "scala-compiler"
+ version == "2.10.1"
+ }
+ }
+ }
+
+ def "inferred Scala class path falls back to 'scalaTools' configuration if the latter is non-empty"() {
+ project.dependencies {
+ scalaTools "org.scala-lang:scala-compiler:2.10.1"
+ }
+
+ when:
+ def classpath = project.scalaRuntime.inferScalaClasspath([new File("other.jar"), new File("scala-library-2.10.1.jar")])
+
+ then:
+ classpath == project.configurations.scalaTools
+ }
+
+ def "inference fails if 'scalaTools' configuration is empty and no repository declared"() {
+ when:
+ def scalaClasspath = project.scalaRuntime.inferScalaClasspath([new File("other.jar"), new File("scala-library-2.10.1.jar")])
+ scalaClasspath.files
+
+ then:
+ GradleException e = thrown()
+ e.message == "Cannot infer Scala class path because no repository is declared for the project."
+ }
+
+ def "inference fails if 'scalaTools' configuration is empty and no Scala library Jar is found on class path"() {
+ project.repositories {
+ mavenCentral()
+ }
+
+ when:
+ def scalaClasspath = project.scalaRuntime.inferScalaClasspath([new File("other.jar"), new File("other2.jar")])
+ scalaClasspath.files
+
+ then:
+ GradleException e = thrown()
+ e.message.startsWith("Cannot infer Scala class path because no Scala library Jar was found on class path:")
+ }
+
+ def "allows to find Scala Jar on class path"() {
+ when:
+ def file = project.scalaRuntime.findScalaJar([new File("other.jar"), new File("scala-jdbc-1.5.jar"), new File("scala-compiler-1.7.jar")], "jdbc")
+
+ then:
+ file.name == "scala-jdbc-1.5.jar"
+ }
+
+ def "returns null if Scala Jar not found"() {
+ when:
+ def file = project.scalaRuntime.findScalaJar([new File("other.jar"), new File("scala-jdbc-1.5.jar"), new File("scala-compiler-1.7.jar")], "library")
+
+ then:
+ file == null
+ }
+
+ def "allows to determine version of Scala Jar"() {
+ expect:
+ with(project.scalaRuntime) {
+ getScalaVersion(new File("scala-compiler-2.9.2.jar")) == "2.9.2"
+ getScalaVersion(new File("scala-jdbc-2.9.2.jar")) == "2.9.2"
+ getScalaVersion(new File("scala-library-2.10.0-SNAPSHOT.jar")) == "2.10.0-SNAPSHOT"
+ getScalaVersion(new File("scala-library-2.10.0-rc-3.jar")) == "2.10.0-rc-3"
+ }
+ }
+
+ def "returns null if Scala version cannot be determined"() {
+ expect:
+ with(project.scalaRuntime) {
+ getScalaVersion(new File("scala-compiler.jar")) == null
+ getScalaVersion(new File("groovy-compiler-2.1.0.jar")) == null
+ }
+ }
+}
diff --git a/subprojects/scala/src/test/groovy/org/gradle/api/tasks/scala/ScalaCompileTest.java b/subprojects/scala/src/test/groovy/org/gradle/api/tasks/scala/ScalaCompileTest.java
index be14ffd..71db9f8 100644
--- a/subprojects/scala/src/test/groovy/org/gradle/api/tasks/scala/ScalaCompileTest.java
+++ b/subprojects/scala/src/test/groovy/org/gradle/api/tasks/scala/ScalaCompileTest.java
@@ -28,11 +28,15 @@ import org.hamcrest.core.IsNull;
import org.jmock.Expectations;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
import java.io.File;
public class ScalaCompileTest extends AbstractCompileTest {
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
private ScalaCompile scalaCompile;
@@ -71,13 +75,16 @@ public class ScalaCompileTest extends AbstractCompileTest {
scalaCompile.compile();
}
- @Test(expected = InvalidUserDataException.class)
+ @Test
public void testMoansIfScalaClasspathIsEmpty() {
setUpMocksAndAttributes(scalaCompile);
context.checking(new Expectations() {{
allowing(scalaClasspath).isEmpty(); will(returnValue(true));
}});
+ thrown.expect(InvalidUserDataException.class);
+ thrown.expectMessage("'testTask.scalaClasspath' must not be empty");
+
scalaCompile.compile();
}
diff --git a/subprojects/signing/signing.gradle b/subprojects/signing/signing.gradle
index dd4ae7f..16e1455 100644
--- a/subprojects/signing/signing.gradle
+++ b/subprojects/signing/signing.gradle
@@ -15,7 +15,7 @@
*/
dependencies {
- groovy libraries.groovy
+ compile libraries.groovy
compile project(':core')
compile project(":plugins")
diff --git a/subprojects/signing/src/main/groovy/org/gradle/plugins/signing/SigningExtension.groovy b/subprojects/signing/src/main/groovy/org/gradle/plugins/signing/SigningExtension.groovy
index 265592b..43ec2a1 100644
--- a/subprojects/signing/src/main/groovy/org/gradle/plugins/signing/SigningExtension.groovy
+++ b/subprojects/signing/src/main/groovy/org/gradle/plugins/signing/SigningExtension.groovy
@@ -131,7 +131,7 @@ class SigningExtension {
def configurations = project.configurations
def configuration = configurations.findByName(DEFAULT_CONFIGURATION_NAME)
if (configuration == null) {
- configuration = configurations.add(DEFAULT_CONFIGURATION_NAME)
+ configuration = configurations.create(DEFAULT_CONFIGURATION_NAME)
}
configuration
}
@@ -323,9 +323,9 @@ class SigningExtension {
}
/**
- * Signs the POM artifact for the given maven deployment.
+ * Signs the POM artifact for the given Maven deployment.
*
- * <p>You can use this method to sign the generated pom when publishing to a maven repository with the maven plugin.
+ * <p>You can use this method to sign the generated POM when publishing to a Maven repository with the Maven plugin.
* </p>
* <pre autoTested=''>
* uploadArchives {
@@ -344,7 +344,7 @@ class SigningExtension {
* this method will silently do nothing. That is, a signature for the POM file will not be uploaded.
*
* @param mavenDeployment The deployment to sign the POM of
- * @param closure the configuration of the underlying {@link SignOperation sign operation} for the pom (optional)
+ * @param closure the configuration of the underlying {@link SignOperation sign operation} for the POM (optional)
* @return the generated signature artifact
*/
Signature signPom(MavenDeployment mavenDeployment, Closure closure = null) {
diff --git a/subprojects/signing/src/main/groovy/org/gradle/plugins/signing/SigningPluginConvention.groovy b/subprojects/signing/src/main/groovy/org/gradle/plugins/signing/SigningPluginConvention.groovy
index 11ae0e1..aa00154 100644
--- a/subprojects/signing/src/main/groovy/org/gradle/plugins/signing/SigningPluginConvention.groovy
+++ b/subprojects/signing/src/main/groovy/org/gradle/plugins/signing/SigningPluginConvention.groovy
@@ -22,6 +22,7 @@ import org.gradle.util.DeprecationLogger
/**
* @deprecated Use {@link SigningExtension}
*/
+ at Deprecated
class SigningPluginConvention {
private SigningExtension extension
@@ -33,6 +34,7 @@ class SigningPluginConvention {
/**
* @deprecated Use {@link SigningExtension#sign(PublishArtifact...) project.signing.sign(PublishArtifact...) }
*/
+ @Deprecated
SignOperation sign(PublishArtifact... publishArtifacts) {
DeprecationLogger.nagUserOfReplacedMethod("sign()", "signing.sign()")
extension.sign(publishArtifacts)
@@ -41,6 +43,7 @@ class SigningPluginConvention {
/**
* @deprecated Use {@link SigningExtension#sign(File...) project.signing.sign(File...) }
*/
+ @Deprecated
SignOperation sign(File... files) {
DeprecationLogger.nagUserOfReplacedMethod("sign()", "signing.sign()")
extension.sign(files)
@@ -49,6 +52,7 @@ class SigningPluginConvention {
/**
* @deprecated Use {@link SigningExtension#sign(String, File...) project.signing.sign(String, File...)}
*/
+ @Deprecated
SignOperation sign(String classifier, File... files) {
DeprecationLogger.nagUserOfReplacedMethod("sign()", "signing.sign()")
extension.sign(classifier, files)
@@ -57,6 +61,7 @@ class SigningPluginConvention {
/**
* @deprecated Use {@link SigningExtension#sign(Closure) project.signing.sign \{ } }
*/
+ @Deprecated
SignOperation sign(Closure closure) {
DeprecationLogger.nagUserOfReplacedMethod("sign()", "signing.sign()")
extension.sign(closure)
@@ -65,10 +70,9 @@ class SigningPluginConvention {
/**
* @deprecated Use {@link SigningExtension#signPom() project.signing.signPom}
*/
+ @Deprecated
Signature signPom(MavenDeployment mavenDeployment, Closure closure = null) {
DeprecationLogger.nagUserOfReplacedMethod("signPom()", "signing.signPom()")
extension.signPom(mavenDeployment, closure)
}
-
-
}
\ No newline at end of file
diff --git a/subprojects/signing/src/test/groovy/org/gradle/plugins/signing/SigningProjectSpec.groovy b/subprojects/signing/src/test/groovy/org/gradle/plugins/signing/SigningProjectSpec.groovy
index 5068fdf..1adabe3 100644
--- a/subprojects/signing/src/test/groovy/org/gradle/plugins/signing/SigningProjectSpec.groovy
+++ b/subprojects/signing/src/test/groovy/org/gradle/plugins/signing/SigningProjectSpec.groovy
@@ -18,7 +18,7 @@ package org.gradle.plugins.signing
import org.gradle.api.Project
import org.gradle.api.tasks.bundling.Jar
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
-import org.gradle.util.HelperUtil
+import org.gradle.util.TestUtil
import org.junit.Rule
import spock.lang.Specification
@@ -28,7 +28,7 @@ class SigningProjectSpec extends Specification {
@Rule public TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider()
- Project project = HelperUtil.createRootProject()
+ Project project = TestUtil.createRootProject()
private assertProject() {
assert project != null : "You haven't created a project"
diff --git a/subprojects/sonar/sonar.gradle b/subprojects/sonar/sonar.gradle
index 0a17a37..078aebe 100644
--- a/subprojects/sonar/sonar.gradle
+++ b/subprojects/sonar/sonar.gradle
@@ -19,6 +19,7 @@ apply from: "$rootDir/gradle/providedConfiguration.gradle"
dependencies {
compile project(":core")
compile project(":plugins")
+ compile project(":jacoco")
compile libraries.groovy
// Sonar Runner plugin
@@ -42,4 +43,4 @@ dependencies {
}
useTestFixtures()
-
+useClassycle()
diff --git a/subprojects/sonar/src/integTest/groovy/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest.groovy b/subprojects/sonar/src/integTest/groovy/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest.groovy
index 8076b66..c0341a5 100644
--- a/subprojects/sonar/src/integTest/groovy/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest.groovy
+++ b/subprojects/sonar/src/integTest/groovy/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest.groovy
@@ -19,11 +19,11 @@ package org.gradle.api.plugins.sonar
import org.gradle.integtests.fixtures.AbstractIntegrationSpec
import org.gradle.integtests.fixtures.TestResources
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
+import org.gradle.test.fixtures.server.http.ServletContainer
import org.gradle.util.AvailablePortFinder
-import org.gradle.util.ClasspathUtil
+import org.gradle.internal.classloader.ClasspathUtil
import org.junit.Rule
-import org.mortbay.jetty.Server
-import org.mortbay.jetty.webapp.WebAppContext
+
import spock.lang.AutoCleanup
import spock.lang.Shared
@@ -32,7 +32,7 @@ class SonarSmokeIntegrationTest extends AbstractIntegrationSpec {
AvailablePortFinder portFinder = AvailablePortFinder.createPrivate()
@AutoCleanup("stop")
- Server webServer = new Server(0)
+ ServletContainer container
@Rule
TestNameTestDirectoryProvider tempDir = new TestNameTestDirectoryProvider()
@@ -61,10 +61,8 @@ sonar.jdbc.url=jdbc:h2:mem:sonartest
sonar.embeddedDatabase.port=$databasePort
""".trim()
- def context = new WebAppContext()
- context.war = warFile
- webServer.addHandler(context)
- webServer.start()
+ container = new ServletContainer(warFile)
+ container.start()
}
def "can run Sonar analysis"() {
@@ -76,7 +74,7 @@ sonar.embeddedDatabase.port=$databasePort
// the wrong class loader.
when:
executer.requireGradleHome()
- .withArgument("-PserverUrl=http://localhost:${webServer.connectors[0].localPort}")
+ .withArgument("-PserverUrl=http://localhost:${container.port}")
.withArgument("-PdatabaseUrl=jdbc:h2:tcp://localhost:$databasePort/mem:sonartest")
.withTasks("build", "sonarAnalyze").run()
diff --git a/subprojects/sonar/src/integTest/groovy/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest.groovy b/subprojects/sonar/src/integTest/groovy/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest.groovy
index 9d9b4ed..be3f96b 100644
--- a/subprojects/sonar/src/integTest/groovy/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest.groovy
+++ b/subprojects/sonar/src/integTest/groovy/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest.groovy
@@ -19,11 +19,11 @@ package org.gradle.api.sonar.runner
import org.gradle.integtests.fixtures.AbstractIntegrationSpec
import org.gradle.integtests.fixtures.TestResources
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
+import org.gradle.test.fixtures.server.http.ServletContainer
import org.gradle.util.AvailablePortFinder
-import org.gradle.util.ClasspathUtil
+import org.gradle.internal.classloader.ClasspathUtil
import org.junit.Rule
-import org.mortbay.jetty.Server
-import org.mortbay.jetty.webapp.WebAppContext
+
import spock.lang.AutoCleanup
import spock.lang.Shared
@@ -32,7 +32,7 @@ class SonarRunnerSmokeIntegrationTest extends AbstractIntegrationSpec {
AvailablePortFinder portFinder = AvailablePortFinder.createPrivate()
@AutoCleanup("stop")
- Server webServer = new Server(0)
+ ServletContainer container
@Rule
TestNameTestDirectoryProvider tempDir = new TestNameTestDirectoryProvider()
@@ -61,10 +61,8 @@ sonar.jdbc.url=jdbc:h2:mem:sonartest
sonar.embeddedDatabase.port=$databasePort
""".trim()
- def context = new WebAppContext()
- context.war = warFile
- webServer.addHandler(context)
- webServer.start()
+ container = new ServletContainer(warFile)
+ container.start()
}
def "execute 'sonarRunner' task"() {
@@ -74,7 +72,7 @@ sonar.embeddedDatabase.port=$databasePort
.withArgument("-i")
.withArgument("-PserverUrl=foo") // dummy value for configuring sonarAnalyze task
.withArgument("-PdatabaseUrl=bar") // dummy value for configuring sonarAnalyze task
- .withArgument("-Dsonar.host.url=http://localhost:${webServer.connectors[0].localPort}")
+ .withArgument("-Dsonar.host.url=http://localhost:${container.port}")
.withArgument("-Dsonar.jdbc.url=jdbc:h2:tcp://localhost:$databasePort/mem:sonartest")
.withTasks("sonarRunner").run()
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/build.gradle b/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/build.gradle
deleted file mode 100644
index 2d8cfa3..0000000
--- a/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/build.gradle
+++ /dev/null
@@ -1,2 +0,0 @@
-description = "Sonar Test Java Project"
-
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/build.gradle b/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/build.gradle
new file mode 100644
index 0000000..3f3cb77
--- /dev/null
+++ b/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/build.gradle
@@ -0,0 +1,5 @@
+if(!org.gradle.internal.os.OperatingSystem.current().isWindows()){
+ apply plugin:'jacoco'
+}
+description = "Sonar Test Java Project"
+
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/main/java/org/gradle/test/javaProject/Production1.java b/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/java/org/gradle/test/javaProject/Production1.java
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/main/java/org/gradle/test/javaProject/Production1.java
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/java/org/gradle/test/javaProject/Production1.java
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/main/java/org/gradle/test/javaProject/Production10.java b/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/java/org/gradle/test/javaProject/Production10.java
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/main/java/org/gradle/test/javaProject/Production10.java
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/java/org/gradle/test/javaProject/Production10.java
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/main/java/org/gradle/test/javaProject/Production2.java b/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/java/org/gradle/test/javaProject/Production2.java
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/main/java/org/gradle/test/javaProject/Production2.java
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/java/org/gradle/test/javaProject/Production2.java
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/main/java/org/gradle/test/javaProject/Production3.java b/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/java/org/gradle/test/javaProject/Production3.java
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/main/java/org/gradle/test/javaProject/Production3.java
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/java/org/gradle/test/javaProject/Production3.java
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/main/java/org/gradle/test/javaProject/Production4.java b/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/java/org/gradle/test/javaProject/Production4.java
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/main/java/org/gradle/test/javaProject/Production4.java
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/java/org/gradle/test/javaProject/Production4.java
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/main/java/org/gradle/test/javaProject/Production5.java b/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/java/org/gradle/test/javaProject/Production5.java
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/main/java/org/gradle/test/javaProject/Production5.java
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/java/org/gradle/test/javaProject/Production5.java
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/main/java/org/gradle/test/javaProject/Production6.java b/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/java/org/gradle/test/javaProject/Production6.java
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/main/java/org/gradle/test/javaProject/Production6.java
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/java/org/gradle/test/javaProject/Production6.java
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/main/java/org/gradle/test/javaProject/Production7.java b/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/java/org/gradle/test/javaProject/Production7.java
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/main/java/org/gradle/test/javaProject/Production7.java
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/java/org/gradle/test/javaProject/Production7.java
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/main/java/org/gradle/test/javaProject/Production8.java b/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/java/org/gradle/test/javaProject/Production8.java
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/main/java/org/gradle/test/javaProject/Production8.java
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/java/org/gradle/test/javaProject/Production8.java
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/main/java/org/gradle/test/javaProject/Production9.java b/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/java/org/gradle/test/javaProject/Production9.java
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/main/java/org/gradle/test/javaProject/Production9.java
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/java/org/gradle/test/javaProject/Production9.java
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/main/resources/org/gradle/test/javaProject/productionResource.xml b/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/resources/org/gradle/test/javaProject/productionResource.xml
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/main/resources/org/gradle/test/javaProject/productionResource.xml
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/resources/org/gradle/test/javaProject/productionResource.xml
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/test/java/org/gradle/test/javaProject/Test1.java b/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/java/org/gradle/test/javaProject/Test1.java
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/test/java/org/gradle/test/javaProject/Test1.java
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/java/org/gradle/test/javaProject/Test1.java
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/test/java/org/gradle/test/javaProject/Test10.java b/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/java/org/gradle/test/javaProject/Test10.java
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/test/java/org/gradle/test/javaProject/Test10.java
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/java/org/gradle/test/javaProject/Test10.java
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/test/java/org/gradle/test/javaProject/Test2.java b/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/java/org/gradle/test/javaProject/Test2.java
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/test/java/org/gradle/test/javaProject/Test2.java
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/java/org/gradle/test/javaProject/Test2.java
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/test/java/org/gradle/test/javaProject/Test3.java b/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/java/org/gradle/test/javaProject/Test3.java
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/test/java/org/gradle/test/javaProject/Test3.java
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/java/org/gradle/test/javaProject/Test3.java
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/test/java/org/gradle/test/javaProject/Test4.java b/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/java/org/gradle/test/javaProject/Test4.java
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/test/java/org/gradle/test/javaProject/Test4.java
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/java/org/gradle/test/javaProject/Test4.java
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/test/java/org/gradle/test/javaProject/Test5.java b/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/java/org/gradle/test/javaProject/Test5.java
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/test/java/org/gradle/test/javaProject/Test5.java
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/java/org/gradle/test/javaProject/Test5.java
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/test/java/org/gradle/test/javaProject/Test6.java b/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/java/org/gradle/test/javaProject/Test6.java
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/test/java/org/gradle/test/javaProject/Test6.java
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/java/org/gradle/test/javaProject/Test6.java
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/test/java/org/gradle/test/javaProject/Test7.java b/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/java/org/gradle/test/javaProject/Test7.java
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/test/java/org/gradle/test/javaProject/Test7.java
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/java/org/gradle/test/javaProject/Test7.java
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/test/java/org/gradle/test/javaProject/Test8.java b/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/java/org/gradle/test/javaProject/Test8.java
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/test/java/org/gradle/test/javaProject/Test8.java
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/java/org/gradle/test/javaProject/Test8.java
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/test/java/org/gradle/test/javaProject/Test9.java b/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/java/org/gradle/test/javaProject/Test9.java
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/test/java/org/gradle/test/javaProject/Test9.java
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/java/org/gradle/test/javaProject/Test9.java
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/test/resources/org/gradle/test/javaProject/testResource.xml b/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/resources/org/gradle/test/javaProject/testResource.xml
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProject/src/test/resources/org/gradle/test/javaProject/testResource.xml
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/resources/org/gradle/test/javaProject/testResource.xml
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/settings.gradle b/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/settings.gradle
index fbb7d87..be3f4a3 100644
--- a/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/settings.gradle
+++ b/subprojects/sonar/src/integTest/resources/org/gradle/api/plugins/sonar/SonarSmokeIntegrationTest/shared/settings.gradle
@@ -1,3 +1,3 @@
-include "javaProject", "skippedProject", "customizedProject", "nested:nested2:nestedProject"
+include "javaProjectWithJacoco", "skippedProject", "customizedProject", "nested:nested2:nestedProject"
rootProject.name = "Sonar Test Build" // spaces are intentional
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/build.gradle b/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/build.gradle
deleted file mode 100644
index 2d8cfa3..0000000
--- a/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/build.gradle
+++ /dev/null
@@ -1,2 +0,0 @@
-description = "Sonar Test Java Project"
-
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/build.gradle b/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/build.gradle
new file mode 100644
index 0000000..3f3cb77
--- /dev/null
+++ b/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/build.gradle
@@ -0,0 +1,5 @@
+if(!org.gradle.internal.os.OperatingSystem.current().isWindows()){
+ apply plugin:'jacoco'
+}
+description = "Sonar Test Java Project"
+
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/main/java/org/gradle/test/javaProject/Production1.java b/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/java/org/gradle/test/javaProject/Production1.java
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/main/java/org/gradle/test/javaProject/Production1.java
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/java/org/gradle/test/javaProject/Production1.java
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/main/java/org/gradle/test/javaProject/Production10.java b/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/java/org/gradle/test/javaProject/Production10.java
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/main/java/org/gradle/test/javaProject/Production10.java
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/java/org/gradle/test/javaProject/Production10.java
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/main/java/org/gradle/test/javaProject/Production2.java b/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/java/org/gradle/test/javaProject/Production2.java
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/main/java/org/gradle/test/javaProject/Production2.java
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/java/org/gradle/test/javaProject/Production2.java
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/main/java/org/gradle/test/javaProject/Production3.java b/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/java/org/gradle/test/javaProject/Production3.java
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/main/java/org/gradle/test/javaProject/Production3.java
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/java/org/gradle/test/javaProject/Production3.java
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/main/java/org/gradle/test/javaProject/Production4.java b/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/java/org/gradle/test/javaProject/Production4.java
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/main/java/org/gradle/test/javaProject/Production4.java
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/java/org/gradle/test/javaProject/Production4.java
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/main/java/org/gradle/test/javaProject/Production5.java b/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/java/org/gradle/test/javaProject/Production5.java
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/main/java/org/gradle/test/javaProject/Production5.java
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/java/org/gradle/test/javaProject/Production5.java
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/main/java/org/gradle/test/javaProject/Production6.java b/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/java/org/gradle/test/javaProject/Production6.java
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/main/java/org/gradle/test/javaProject/Production6.java
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/java/org/gradle/test/javaProject/Production6.java
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/main/java/org/gradle/test/javaProject/Production7.java b/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/java/org/gradle/test/javaProject/Production7.java
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/main/java/org/gradle/test/javaProject/Production7.java
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/java/org/gradle/test/javaProject/Production7.java
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/main/java/org/gradle/test/javaProject/Production8.java b/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/java/org/gradle/test/javaProject/Production8.java
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/main/java/org/gradle/test/javaProject/Production8.java
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/java/org/gradle/test/javaProject/Production8.java
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/main/java/org/gradle/test/javaProject/Production9.java b/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/java/org/gradle/test/javaProject/Production9.java
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/main/java/org/gradle/test/javaProject/Production9.java
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/java/org/gradle/test/javaProject/Production9.java
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/main/resources/org/gradle/test/javaProject/productionResource.xml b/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/resources/org/gradle/test/javaProject/productionResource.xml
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/main/resources/org/gradle/test/javaProject/productionResource.xml
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/main/resources/org/gradle/test/javaProject/productionResource.xml
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/test/java/org/gradle/test/javaProject/Test1.java b/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/java/org/gradle/test/javaProject/Test1.java
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/test/java/org/gradle/test/javaProject/Test1.java
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/java/org/gradle/test/javaProject/Test1.java
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/test/java/org/gradle/test/javaProject/Test10.java b/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/java/org/gradle/test/javaProject/Test10.java
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/test/java/org/gradle/test/javaProject/Test10.java
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/java/org/gradle/test/javaProject/Test10.java
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/test/java/org/gradle/test/javaProject/Test2.java b/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/java/org/gradle/test/javaProject/Test2.java
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/test/java/org/gradle/test/javaProject/Test2.java
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/java/org/gradle/test/javaProject/Test2.java
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/test/java/org/gradle/test/javaProject/Test3.java b/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/java/org/gradle/test/javaProject/Test3.java
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/test/java/org/gradle/test/javaProject/Test3.java
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/java/org/gradle/test/javaProject/Test3.java
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/test/java/org/gradle/test/javaProject/Test4.java b/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/java/org/gradle/test/javaProject/Test4.java
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/test/java/org/gradle/test/javaProject/Test4.java
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/java/org/gradle/test/javaProject/Test4.java
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/test/java/org/gradle/test/javaProject/Test5.java b/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/java/org/gradle/test/javaProject/Test5.java
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/test/java/org/gradle/test/javaProject/Test5.java
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/java/org/gradle/test/javaProject/Test5.java
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/test/java/org/gradle/test/javaProject/Test6.java b/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/java/org/gradle/test/javaProject/Test6.java
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/test/java/org/gradle/test/javaProject/Test6.java
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/java/org/gradle/test/javaProject/Test6.java
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/test/java/org/gradle/test/javaProject/Test7.java b/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/java/org/gradle/test/javaProject/Test7.java
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/test/java/org/gradle/test/javaProject/Test7.java
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/java/org/gradle/test/javaProject/Test7.java
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/test/java/org/gradle/test/javaProject/Test8.java b/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/java/org/gradle/test/javaProject/Test8.java
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/test/java/org/gradle/test/javaProject/Test8.java
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/java/org/gradle/test/javaProject/Test8.java
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/test/java/org/gradle/test/javaProject/Test9.java b/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/java/org/gradle/test/javaProject/Test9.java
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/test/java/org/gradle/test/javaProject/Test9.java
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/java/org/gradle/test/javaProject/Test9.java
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/test/resources/org/gradle/test/javaProject/testResource.xml b/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/resources/org/gradle/test/javaProject/testResource.xml
similarity index 100%
rename from subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProject/src/test/resources/org/gradle/test/javaProject/testResource.xml
rename to subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/javaProjectWithJacoco/src/test/resources/org/gradle/test/javaProject/testResource.xml
diff --git a/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/settings.gradle b/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/settings.gradle
index ed2f902..cb7798c 100644
--- a/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/settings.gradle
+++ b/subprojects/sonar/src/integTest/resources/org/gradle/api/sonar/runner/SonarRunnerSmokeIntegrationTest/shared/settings.gradle
@@ -1,3 +1,3 @@
-include "javaProject", "groovyProject", "skippedProject", "customizedProject", "nested:nested2:nestedProject"
+include "javaProjectWithJacoco", "groovyProject", "skippedProject", "customizedProject", "nested:nested2:nestedProject"
rootProject.name = "SonarTestBuild"
diff --git a/subprojects/sonar/src/main/groovy/org/gradle/api/plugins/sonar/SonarAnalyze.groovy b/subprojects/sonar/src/main/groovy/org/gradle/api/plugins/sonar/SonarAnalyze.groovy
index 0f7a50b..d5e8ce4 100644
--- a/subprojects/sonar/src/main/groovy/org/gradle/api/plugins/sonar/SonarAnalyze.groovy
+++ b/subprojects/sonar/src/main/groovy/org/gradle/api/plugins/sonar/SonarAnalyze.groovy
@@ -18,7 +18,7 @@ package org.gradle.api.plugins.sonar
import org.sonar.batch.bootstrapper.Bootstrapper
import org.gradle.api.internal.ConventionTask
import org.gradle.api.tasks.TaskAction
-import org.gradle.util.ClasspathUtil
+import org.gradle.internal.classloader.ClasspathUtil
import org.gradle.api.plugins.sonar.model.SonarRootModel
import org.gradle.util.GFileUtils
diff --git a/subprojects/sonar/src/main/groovy/org/gradle/api/plugins/sonar/SonarPlugin.groovy b/subprojects/sonar/src/main/groovy/org/gradle/api/plugins/sonar/SonarPlugin.groovy
index d744c34..51475ff 100644
--- a/subprojects/sonar/src/main/groovy/org/gradle/api/plugins/sonar/SonarPlugin.groovy
+++ b/subprojects/sonar/src/main/groovy/org/gradle/api/plugins/sonar/SonarPlugin.groovy
@@ -17,13 +17,14 @@ package org.gradle.api.plugins.sonar
import org.gradle.api.Plugin
import org.gradle.api.Project
-import org.gradle.internal.reflect.Instantiator
import org.gradle.api.internal.project.ProjectInternal
import org.gradle.api.plugins.JavaBasePlugin
import org.gradle.api.plugins.JavaPlugin
-import org.gradle.util.GradleVersion
-import org.gradle.internal.jvm.Jvm
import org.gradle.api.plugins.sonar.model.*
+import org.gradle.internal.jvm.Jvm
+import org.gradle.internal.reflect.Instantiator
+import org.gradle.testing.jacoco.plugins.JacocoPlugin
+import org.gradle.util.GradleVersion
import javax.inject.Inject
@@ -60,7 +61,7 @@ class SonarPlugin implements Plugin<ProjectInternal> {
}
private SonarAnalyze configureSonarTask(Project project) {
- project.tasks.add(SONAR_ANALYZE_TASK_NAME, SonarAnalyze)
+ project.tasks.create(SONAR_ANALYZE_TASK_NAME, SonarAnalyze)
}
private SonarRootModel configureSonarRootModel(Project project) {
@@ -142,11 +143,15 @@ class SonarPlugin implements Plugin<ProjectInternal> {
}
libraries
}
- testReportPath = { project.test.testResultsDir }
+ testReportPath = { project.test.reports.junitXml.destination }
language = { "java" }
}
+ project.plugins.withType(JacocoPlugin) {
+ sonarProject.withProjectProperties { props ->
+ props['sonar.jacoco.reportPath'] = project.test.jacoco.destinationFile
+ }
+ }
}
-
sonarProject
}
}
diff --git a/subprojects/sonar/src/main/groovy/org/gradle/api/sonar/runner/SonarRunnerPlugin.groovy b/subprojects/sonar/src/main/groovy/org/gradle/api/sonar/runner/SonarRunnerPlugin.groovy
index 391e507..2f43e17 100644
--- a/subprojects/sonar/src/main/groovy/org/gradle/api/sonar/runner/SonarRunnerPlugin.groovy
+++ b/subprojects/sonar/src/main/groovy/org/gradle/api/sonar/runner/SonarRunnerPlugin.groovy
@@ -22,6 +22,7 @@ import org.gradle.api.plugins.JavaBasePlugin
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.tasks.SourceSet
import org.gradle.internal.jvm.Jvm
+import org.gradle.testing.jacoco.plugins.JacocoPlugin
/**
* A plugin for analyzing projects with the
@@ -100,7 +101,10 @@ class SonarRunnerPlugin implements Plugin<Project> {
void apply(Project project) {
targetProject = project
- def sonarRunnerTask = project.tasks.add("sonarRunner", SonarRunner)
+ def sonarRunnerTask = project.tasks.create("sonarRunner", SonarRunner)
+ sonarRunnerTask.with {
+ description = "Analyzes $project and its subprojects with Sonar Runner."
+ }
sonarRunnerTask.conventionMapping.with {
sonarProperties = {
def properties = new Properties()
@@ -120,21 +124,27 @@ class SonarRunnerPlugin implements Plugin<Project> {
void computeSonarProperties(Project project, Properties properties) {
def extension = project.extensions.getByType(SonarRunnerExtension)
- if (extension.skipProject) { return }
+ if (extension.skipProject) {
+ return
+ }
Map<String, Object> rawProperties = [:]
addGradleDefaults(project, rawProperties)
extension.evaluateSonarPropertiesBlocks(rawProperties)
- if (project == targetProject) { addSystemProperties(rawProperties) }
+ if (project == targetProject) {
+ addSystemProperties(rawProperties)
+ }
def projectPrefix = project.path.substring(targetProject.path.size()).replace(":", ".")
if (projectPrefix.startsWith(".")) {
projectPrefix = projectPrefix.substring(1)
}
convertProperties(rawProperties, projectPrefix, properties)
-
- def enabledChildProjects = project.childProjects.values().findAll { !it.sonarRunner.skipProject }
- if (enabledChildProjects.empty) { return }
+
+ def enabledChildProjects = project.childProjects.values().findAll { !it.sonarRunner.skipProject }.sort()
+ if (enabledChildProjects.empty) {
+ return
+ }
properties[convertKey("sonar.modules", projectPrefix)] = convertValue(enabledChildProjects.name)
for (childProject in enabledChildProjects) {
@@ -172,7 +182,12 @@ class SonarRunnerPlugin implements Plugin<Project> {
properties["sonar.tests"] = test.allSource.srcDirs.findAll { it.exists() } ?: null
properties["sonar.binaries"] = main.runtimeClasspath.findAll { it.directory } ?: null
properties["sonar.libraries"] = getLibraries(main)
- properties["sonar.surefire.reportsPath"] = project.test.testResultsDir.exists() ? project.test.testResultsDir : null
+ File testResultsDir = project.test.reports.junitXml.destination
+ properties["sonar.surefire.reportsPath"] = testResultsDir.exists() ? testResultsDir : null
+
+ project.plugins.withType(JacocoPlugin) {
+ properties["sonar.jacoco.reportPath"] = project.test.jacoco.destinationFile.exists() ? project.test.jacoco.destinationFile : null
+ }
}
if (properties["sonar.sources"] == null) {
@@ -211,12 +226,13 @@ class SonarRunnerPlugin implements Plugin<Project> {
}
}
}
-
+
private String convertKey(String key, String projectPrefix) {
projectPrefix ? "${projectPrefix}.$key" : key
}
-
+
private String convertValue(Object value) {
value instanceof Iterable ? value.collect { convertValue(it) }.join(",") : value.toString()
}
+
}
diff --git a/subprojects/sonar/src/test/groovy/org/gradle/api/plugins/sonar/SonarAnalyzeTest.groovy b/subprojects/sonar/src/test/groovy/org/gradle/api/plugins/sonar/SonarAnalyzeTest.groovy
index 9898aab..bc2a197 100644
--- a/subprojects/sonar/src/test/groovy/org/gradle/api/plugins/sonar/SonarAnalyzeTest.groovy
+++ b/subprojects/sonar/src/test/groovy/org/gradle/api/plugins/sonar/SonarAnalyzeTest.groovy
@@ -18,7 +18,7 @@ package org.gradle.api.plugins.sonar
import spock.lang.Specification
class SonarAnalyzeTest extends Specification {
-// SonarAnalyze task = HelperUtil.createTask(SonarAnalyze)
+// SonarAnalyze task = TestUtil.createTask(SonarAnalyze)
//
// @Issue("GRADLE-1499")
// def "can configure project properties"() {
diff --git a/subprojects/sonar/src/test/groovy/org/gradle/api/plugins/sonar/SonarPluginTest.groovy b/subprojects/sonar/src/test/groovy/org/gradle/api/plugins/sonar/SonarPluginTest.groovy
index 94d68fc..6e49766 100644
--- a/subprojects/sonar/src/test/groovy/org/gradle/api/plugins/sonar/SonarPluginTest.groovy
+++ b/subprojects/sonar/src/test/groovy/org/gradle/api/plugins/sonar/SonarPluginTest.groovy
@@ -15,22 +15,21 @@
*/
package org.gradle.api.plugins.sonar
-import org.gradle.api.plugins.sonar.model.SonarRootModel
-import org.gradle.api.plugins.sonar.model.SonarProjectModel
-import org.gradle.api.plugins.sonar.model.SonarProject
import org.gradle.api.Project
import org.gradle.api.plugins.JavaBasePlugin
import org.gradle.api.plugins.JavaPlugin
-import org.gradle.util.ConfigureUtil
-import org.gradle.util.HelperUtil
+import org.gradle.api.plugins.sonar.model.SonarProject
+import org.gradle.api.plugins.sonar.model.SonarProjectModel
+import org.gradle.api.plugins.sonar.model.SonarRootModel
import org.gradle.internal.jvm.Jvm
-
-import spock.lang.Specification
+import org.gradle.util.ConfigureUtil
+import org.gradle.util.TestUtil
import spock.lang.Issue
+import spock.lang.Specification
class SonarPluginTest extends Specification {
def "adds model and task to root project"() {
- def project = HelperUtil.createRootProject()
+ def project = TestUtil.createRootProject()
when:
project.plugins.apply(SonarPlugin)
@@ -41,8 +40,8 @@ class SonarPluginTest extends Specification {
}
def "adds model to subprojects"() {
- def project = HelperUtil.createRootProject()
- def child = HelperUtil.createChildProject(project, "child")
+ def project = TestUtil.createRootProject()
+ def child = TestUtil.createChildProject(project, "child")
when:
project.plugins.apply(SonarPlugin)
@@ -53,7 +52,7 @@ class SonarPluginTest extends Specification {
}
def "provides defaults for global configuration"() {
- def project = HelperUtil.createRootProject()
+ def project = TestUtil.createRootProject()
when:
project.plugins.apply(SonarPlugin)
@@ -110,7 +109,7 @@ class SonarPluginTest extends Specification {
sonarProject.binaryDirs == [project.sourceSets.main.output.classesDir]
sonarProject.libraries.files as List == [Jvm.current().runtimeJar]
- sonarProject.testReportPath == project.test.testResultsDir
+ sonarProject.testReportPath == project.test.reports.junitXml.destination
sonarProject.language == "java"
where:
@@ -128,11 +127,11 @@ class SonarPluginTest extends Specification {
}
private Project createMultiProject(Closure commonConfig = {}) {
- def root = HelperUtil.createRootProject()
+ def root = TestUtil.createRootProject()
ConfigureUtil.configure(commonConfig, root)
root.group = "group"
- def child = HelperUtil.createChildProject(root, "child")
+ def child = TestUtil.createChildProject(root, "child")
ConfigureUtil.configure(commonConfig, child)
child.group = "group"
diff --git a/subprojects/sonar/src/test/groovy/org/gradle/api/sonar/runner/SonarRunnerPluginTest.groovy b/subprojects/sonar/src/test/groovy/org/gradle/api/sonar/runner/SonarRunnerPluginTest.groovy
index eb84184..cdf736c 100644
--- a/subprojects/sonar/src/test/groovy/org/gradle/api/sonar/runner/SonarRunnerPluginTest.groovy
+++ b/subprojects/sonar/src/test/groovy/org/gradle/api/sonar/runner/SonarRunnerPluginTest.groovy
@@ -19,8 +19,8 @@ import org.gradle.api.plugins.JavaBasePlugin
import org.gradle.api.plugins.JavaPlugin
import org.gradle.internal.jvm.Jvm
import org.gradle.test.fixtures.file.TestFile
-import org.gradle.testfixtures.ProjectBuilder
import org.gradle.util.SetSystemProperties
+import org.gradle.util.TestUtil
import org.junit.Rule
import spock.lang.Specification
@@ -32,11 +32,11 @@ import static org.hamcrest.Matchers.*
class SonarRunnerPluginTest extends Specification {
@Rule SetSystemProperties systemProperties
- def rootProject = ProjectBuilder.builder().withName("root").build()
- def parentProject = ProjectBuilder.builder().withName("parent").withParent(rootProject).build()
- def childProject = ProjectBuilder.builder().withName("child").withParent(parentProject).build()
- def childProject2 = ProjectBuilder.builder().withName("child2").withParent(parentProject).build()
- def leafProject = ProjectBuilder.builder().withName("leaf").withParent(childProject).build()
+ def rootProject = TestUtil.builder().withName("root").build()
+ def parentProject = TestUtil.builder().withName("parent").withParent(rootProject).build()
+ def childProject = TestUtil.builder().withName("child").withParent(parentProject).build()
+ def childProject2 = TestUtil.builder().withName("child2").withParent(parentProject).build()
+ def leafProject = TestUtil.builder().withName("leaf").withParent(childProject).build()
def setup() {
parentProject.plugins.apply(SonarRunnerPlugin)
@@ -58,6 +58,8 @@ class SonarRunnerPluginTest extends Specification {
def "adds a sonarRunner task to the target project"() {
expect:
parentProject.tasks.findByName("sonarRunner") instanceof SonarRunner
+ parentProject.tasks.sonarRunner.description == "Analyzes project ':parent' and its subprojects with Sonar Runner."
+
childProject.tasks.findByName("sonarRunner") == null
}
@@ -240,17 +242,17 @@ class SonarRunnerPluginTest extends Specification {
def properties = parentProject.tasks.sonarRunner.sonarProperties
then:
- properties["sonar.modules"] in ["child,child2", "child2,child"]
+ properties["sonar.modules"] == "child,child2"
properties["child.sonar.modules"] == "leaf"
!properties.containsKey("child2.sonar.modules")
!properties.containsKey("child.leaf.sonar.modules")
}
def "handles 'modules' properties correctly if plugin is applied to root project"() {
- def rootProject = ProjectBuilder.builder().withName("root").build()
- def project = ProjectBuilder.builder().withName("parent").withParent(rootProject).build()
- def project2 = ProjectBuilder.builder().withName("parent2").withParent(rootProject).build()
- def childProject = ProjectBuilder.builder().withName("child").withParent(project).build()
+ def rootProject = TestUtil.builder().withName("root").build()
+ def project = TestUtil.builder().withName("parent").withParent(rootProject).build()
+ def project2 = TestUtil.builder().withName("parent2").withParent(rootProject).build()
+ def childProject = TestUtil.builder().withName("child").withParent(project).build()
rootProject.plugins.apply(SonarRunnerPlugin)
@@ -258,7 +260,7 @@ class SonarRunnerPluginTest extends Specification {
def properties = rootProject.tasks.sonarRunner.sonarProperties
then:
- properties["sonar.modules"] in ["parent,parent2", "parent2,parent"]
+ properties["sonar.modules"] == "parent,parent2"
properties["parent.sonar.modules"] == "child"
!properties.containsKey("parent2.sonar.modules")
!properties.containsKey("parent.child.sonar.modules")
@@ -328,8 +330,8 @@ class SonarRunnerPluginTest extends Specification {
}
def "handles system properties correctly if plugin is applied to root project"() {
- def rootProject = ProjectBuilder.builder().withName("root").build()
- def project = ProjectBuilder.builder().withName("parent").withParent(rootProject).build()
+ def rootProject = TestUtil.builder().withName("root").build()
+ def project = TestUtil.builder().withName("parent").withParent(rootProject).build()
rootProject.allprojects { version = 1.3 }
rootProject.plugins.apply(SonarRunnerPlugin)
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/AutoTestedSamplesToolingApiTest.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/AutoTestedSamplesToolingApiTest.groovy
index 7ea9830..13a4ea4 100644
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/AutoTestedSamplesToolingApiTest.groovy
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/AutoTestedSamplesToolingApiTest.groovy
@@ -20,14 +20,11 @@ import org.gradle.api.JavaVersion
import org.gradle.integtests.fixtures.AutoTestedSamplesUtil
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
import org.gradle.tooling.model.Element
-import org.gradle.util.ClasspathUtil
+import org.gradle.internal.classloader.ClasspathUtil
import org.junit.Rule
import spock.lang.IgnoreIf
import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 1/5/12
- */
@IgnoreIf({!JavaVersion.current().java6Compatible})
public class AutoTestedSamplesToolingApiTest extends Specification {
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/ToolingApiClasspathIntegrationTest.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/ToolingApiClasspathIntegrationTest.groovy
index 8e2ae48..924c2b5 100644
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/ToolingApiClasspathIntegrationTest.groovy
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/ToolingApiClasspathIntegrationTest.groovy
@@ -28,8 +28,11 @@ class ToolingApiClasspathIntegrationTest extends AbstractIntegrationSpec {
ToolingApiDistribution resolve = resolver.resolve(distribution.getVersion().version)
then:
- resolve.classpath.files.size() == 2
- resolve.classpath.files.any {it.name ==~ /slf4j-api-.*\.jar/}
- resolve.classpath.files.find {it.name ==~ /gradle-tooling-api.*\.jar/}.size() < 1.5 * 1024 * 1024
+ resolve.classpath.size() == 2
+ resolve.classpath.any {it.name ==~ /slf4j-api-.*\.jar/}
+ resolve.classpath.find {it.name ==~ /gradle-tooling-api.*\.jar/}.size() < 1.5 * 1024 * 1024
+
+ cleanup:
+ resolver.stop()
}
}
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/ToolingApiIntegrationTest.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/ToolingApiIntegrationTest.groovy
index be64f48..52903b2 100644
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/ToolingApiIntegrationTest.groovy
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/ToolingApiIntegrationTest.groovy
@@ -24,7 +24,6 @@ import org.gradle.integtests.tooling.fixture.TextUtil
import org.gradle.integtests.tooling.fixture.ToolingApi
import org.gradle.test.fixtures.file.TestFile
import org.gradle.tooling.GradleConnector
-import org.gradle.tooling.UnsupportedVersionException
import org.gradle.tooling.model.GradleProject
import org.gradle.util.GradleVersion
import spock.lang.Issue
@@ -33,7 +32,6 @@ class ToolingApiIntegrationTest extends AbstractIntegrationSpec {
final ToolingApi toolingApi = new ToolingApi(distribution, temporaryFolder)
final GradleDistribution otherVersion = new ReleasedVersionDistributions().mostRecentFinalRelease
- final IntegrationTestBuildContext buildContext = new IntegrationTestBuildContext()
TestFile projectDir
@@ -142,18 +140,6 @@ allprojects {
model != null
}
- def "tooling api reports an error when the specified gradle version does not support the tooling api"() {
- def distroZip = buildContext.distribution('0.9.2').binDistribution
-
- when:
- toolingApi.withConnector { connector -> connector.useDistribution(distroZip.toURI()) }
- toolingApi.maybeFailWithConnection { connection -> connection.getModel(GradleProject.class) }
-
- then:
- UnsupportedVersionException e = thrown()
- e.message == "The specified Gradle distribution '${distroZip.toURI()}' is not supported by this tooling API version (${GradleVersion.current().version}, protocol version 4)"
- }
-
@Issue("GRADLE-2419")
def "tooling API does not hold JVM open"() {
given:
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/ToolingApiUnsupportedVersionIntegrationTest.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/ToolingApiUnsupportedVersionIntegrationTest.groovy
new file mode 100644
index 0000000..9b52144
--- /dev/null
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/ToolingApiUnsupportedVersionIntegrationTest.groovy
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests.tooling
+
+import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+import org.gradle.integtests.fixtures.executer.GradleDistribution
+import org.gradle.integtests.fixtures.versions.ReleasedVersionDistributions
+import org.gradle.integtests.tooling.fixture.ToolingApi
+import org.gradle.integtests.tooling.r18.NullAction
+import org.gradle.tooling.UnsupportedVersionException
+import org.gradle.tooling.model.GradleProject
+import org.gradle.util.GradleVersion
+
+class ToolingApiUnsupportedVersionIntegrationTest extends AbstractIntegrationSpec {
+ final ToolingApi toolingApi = new ToolingApi(distribution, temporaryFolder)
+ final GradleDistribution otherVersion = new ReleasedVersionDistributions().getDistribution(GradleVersion.version("0.9.2"))
+ final URI distroZip = otherVersion.binDistribution.toURI()
+
+ def setup() {
+ toolingApi.withConnector { connector -> connector.useDistribution(distroZip) }
+ }
+
+ def "tooling api reports an error when requesting a model using a gradle version that does not implement the tooling api"() {
+ when:
+ toolingApi.withConnection { connection -> connection.getModel(GradleProject.class) }
+
+ then:
+ UnsupportedVersionException e = thrown()
+ e.message == "The specified Gradle distribution '${distroZip}' does not implement the tooling API. Support for the tooling API was added in Gradle 1.0-milestone-3 and is available in all later versions."
+ }
+
+ def "tooling api reports an error when running a build using a gradle version does not implement the tooling api"() {
+ when:
+ toolingApi.withConnection { connection -> connection.newBuild().run() }
+
+ then:
+ UnsupportedVersionException e = thrown()
+ e.message == "The specified Gradle distribution '${distroZip}' does not implement the tooling API. Support for the tooling API was added in Gradle 1.0-milestone-3 and is available in all later versions."
+ }
+
+ def "tooling api reports an error when running a build action using a gradle version does not implement the tooling api"() {
+ when:
+ toolingApi.withConnection { connection -> connection.action(new NullAction()).run() }
+
+ then:
+ UnsupportedVersionException e = thrown()
+ e.message == "The specified Gradle distribution '${distroZip}' does not implement the tooling API. Support for the tooling API was added in Gradle 1.0-milestone-3 and is available in all later versions."
+ }
+}
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/ConfigurableOperation.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/ConfigurableOperation.groovy
index b20c450..856de4e 100644
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/ConfigurableOperation.groovy
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/ConfigurableOperation.groovy
@@ -19,9 +19,6 @@ package org.gradle.integtests.tooling.fixture
import org.gradle.tooling.ModelBuilder
import org.gradle.tooling.ProgressListener
-/**
- * by Szczepan Faber, created at: 12/19/11
- */
class ConfigurableOperation {
def operation
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/ExternalToolingApiDistribution.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/ExternalToolingApiDistribution.groovy
index 22537c6..e8e8520 100644
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/ExternalToolingApiDistribution.groovy
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/ExternalToolingApiDistribution.groovy
@@ -16,23 +16,23 @@
package org.gradle.integtests.tooling.fixture
-import org.gradle.util.DefaultClassLoaderFactory
-import org.gradle.api.file.FileCollection
+import org.gradle.internal.classloader.DefaultClassLoaderFactory
+import org.gradle.util.GradleVersion
class ExternalToolingApiDistribution implements ToolingApiDistribution {
- private final String version
- private final FileCollection classpath
+ private final GradleVersion version
+ private final Collection<File> classpath
- ExternalToolingApiDistribution(String version, FileCollection classpath) {
- this.version = version
+ ExternalToolingApiDistribution(String version, Collection<File> classpath) {
+ this.version = GradleVersion.version(version)
this.classpath = classpath
}
- String getVersion() {
+ GradleVersion getVersion() {
version
}
- FileCollection getClasspath() {
+ Collection<File> getClasspath() {
classpath
}
@@ -42,6 +42,6 @@ class ExternalToolingApiDistribution implements ToolingApiDistribution {
}
String toString() {
- "Tooling API $version"
+ "Tooling API $version.version"
}
}
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/IncludeAllPermutations.java b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/IncludeAllPermutations.java
deleted file mode 100644
index 3eca69f..0000000
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/IncludeAllPermutations.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.integtests.tooling.fixture;
-
-import java.lang.annotation.*;
-
- at Retention(RetentionPolicy.RUNTIME)
- at Target(ElementType.TYPE)
- at Inherited
-public @interface IncludeAllPermutations {}
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/MaxTargetGradleVersion.java b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/MaxTargetGradleVersion.java
deleted file mode 100644
index f46b9d9..0000000
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/MaxTargetGradleVersion.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.integtests.tooling.fixture;
-
-import java.lang.annotation.*;
-
- at Retention(RetentionPolicy.RUNTIME)
- at Target(ElementType.TYPE)
- at Inherited
-public @interface MaxTargetGradleVersion {
- String value();
-}
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/MinTargetGradleVersion.java b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/MinTargetGradleVersion.java
deleted file mode 100644
index 9128a76..0000000
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/MinTargetGradleVersion.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.integtests.tooling.fixture;
-
-import java.lang.annotation.*;
-
- at Retention(RetentionPolicy.RUNTIME)
- at Target(ElementType.TYPE)
- at Inherited
-public @interface MinTargetGradleVersion {
- String value();
-}
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/MinToolingApiVersion.java b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/MinToolingApiVersion.java
deleted file mode 100644
index 26f2008..0000000
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/MinToolingApiVersion.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.integtests.tooling.fixture;
-
-import java.lang.annotation.*;
-
- at Retention(RetentionPolicy.RUNTIME)
- at Target(ElementType.TYPE)
- at Inherited
-public @interface MinToolingApiVersion {
- String value();
-}
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/TargetGradleVersion.java b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/TargetGradleVersion.java
new file mode 100644
index 0000000..8e623f7
--- /dev/null
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/TargetGradleVersion.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests.tooling.fixture;
+
+import java.lang.annotation.*;
+
+/**
+ * Specifies the range of target Gradle versions that the given tooling API test can work with.
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target({ElementType.TYPE, ElementType.METHOD})
+ at Inherited
+public @interface TargetGradleVersion {
+ /**
+ * The requested target Gradle version. Can use '>=nnn', '<=nnn', '<nnn', '=nnn', 'current' or '!current' or space-separated list of patterns.
+ */
+ String value();
+}
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/TestClasspathToolingApiDistribution.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/TestClasspathToolingApiDistribution.groovy
index ab54a5b..92cc0c4 100644
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/TestClasspathToolingApiDistribution.groovy
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/TestClasspathToolingApiDistribution.groovy
@@ -17,14 +17,13 @@
package org.gradle.integtests.tooling.fixture
import org.gradle.util.GradleVersion
-import org.gradle.api.file.FileCollection
class TestClasspathToolingApiDistribution implements ToolingApiDistribution {
- String getVersion() {
- GradleVersion.current().version
+ GradleVersion getVersion() {
+ GradleVersion.current()
}
- FileCollection getClasspath() {
+ Collection<File> getClasspath() {
null
}
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/ToolingApi.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/ToolingApi.groovy
index 24656e2..10367d4 100644
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/ToolingApi.groovy
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/ToolingApi.groovy
@@ -15,14 +15,13 @@
*/
package org.gradle.integtests.tooling.fixture
-import org.gradle.integtests.fixtures.IntegrationTestHint
import org.gradle.integtests.fixtures.executer.GradleContextualExecuter
import org.gradle.integtests.fixtures.executer.GradleDistribution
import org.gradle.integtests.fixtures.executer.IntegrationTestBuildContext
import org.gradle.test.fixtures.file.TestDirectoryProvider
import org.gradle.tooling.GradleConnector
import org.gradle.tooling.ProjectConnection
-import org.gradle.tooling.UnsupportedVersionException
+import org.gradle.util.GradleVersion
import org.slf4j.Logger
import org.slf4j.LoggerFactory
@@ -60,26 +59,35 @@ class ToolingApi {
}
public <T> T withConnection(GradleConnector connector, Closure<T> cl) {
- try {
- return withConnectionRaw(connector, cl)
- } catch (UnsupportedVersionException e) {
- throw new IntegrationTestHint(e);
- }
+ return withConnectionRaw(connector, cl)
}
- public void maybeFailWithConnection(Closure cl) {
- GradleConnector connector = connector()
- try {
- withConnectionRaw(connector, cl)
- } catch (Throwable e) {
- throw e
+ private validate(Throwable throwable) {
+ if (dist.version != GradleVersion.current()) {
+ return
}
+
+ // Verify that the exception carries the calling thread's stack information
+ def currentThreadStack = Thread.currentThread().stackTrace as List
+ while (!currentThreadStack.empty && (currentThreadStack[0].className != ToolingApi.name || currentThreadStack[0].methodName != 'withConnectionRaw')) {
+ currentThreadStack.remove(0)
+ }
+ assert currentThreadStack.size() > 1
+ currentThreadStack.remove(0)
+ String currentThreadStackStr = currentThreadStack.join("\n")
+
+ def throwableStack = throwable.stackTrace.join("\n")
+
+ assert throwableStack.endsWith(currentThreadStackStr)
}
private <T> T withConnectionRaw(GradleConnector connector, Closure<T> cl) {
ProjectConnection connection = connector.connect()
try {
return cl.call(connection)
+ } catch (Throwable t) {
+ validate(t)
+ throw t
} finally {
connection.close()
}
@@ -90,7 +98,7 @@ class ToolingApi {
connector.useGradleUserHomeDir(userHomeDir)
connector.forProjectDirectory(testWorkDirProvider.testDirectory)
connector.searchUpwards(false)
- connector.daemonMaxIdleTime(60, TimeUnit.SECONDS)
+ connector.daemonMaxIdleTime(120, TimeUnit.SECONDS)
if (connector.metaClass.hasProperty(connector, 'verboseLogging')) {
connector.verboseLogging = verboseLogging
}
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/ToolingApiCompatibilitySuiteRunner.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/ToolingApiCompatibilitySuiteRunner.groovy
index 2cd1116..7e798a4 100755
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/ToolingApiCompatibilitySuiteRunner.groovy
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/ToolingApiCompatibilitySuiteRunner.groovy
@@ -15,44 +15,38 @@
*/
package org.gradle.integtests.tooling.fixture
+import org.gradle.api.specs.Spec
+import org.gradle.api.specs.Specs
import org.gradle.integtests.fixtures.AbstractCompatibilityTestRunner
import org.gradle.integtests.fixtures.AbstractMultiTestRunner
import org.gradle.integtests.fixtures.executer.GradleDistribution
+import org.gradle.internal.classloader.ClasspathUtil
+import org.gradle.internal.classloader.DefaultClassLoaderFactory
+import org.gradle.internal.classloader.MultiParentClassLoader
+import org.gradle.internal.classloader.MutableURLClassLoader
import org.gradle.internal.os.OperatingSystem
import org.gradle.util.*
-/**
- * Executes instances of {@link ToolingApiSpecification} against all compatible versions of tooling API consumer
- * and provider, including the current Gradle version under test.
- *
- * <p>A test can be annotated with {@link MinToolingApiVersion} and {@link MinTargetGradleVersion} to indicate the
- * minimum tooling API or Gradle versions required for the test.
- */
class ToolingApiCompatibilitySuiteRunner extends AbstractCompatibilityTestRunner {
private static final Map<String, ClassLoader> TEST_CLASS_LOADERS = [:]
ToolingApiCompatibilitySuiteRunner(Class<? extends ToolingApiSpecification> target) {
- super(target, includesAllPermutations(target))
- }
-
- static String includesAllPermutations(Class target) {
- if (target.getAnnotation(IncludeAllPermutations)) {
- return "all";
- } else {
- return null; //just use whatever is the default
- }
+ super(target)
}
@Override
protected void createExecutions() {
- ToolingApiDistributionResolver resolver = new ToolingApiDistributionResolver().withDefaultRepository()
-
- add(new Permutation(resolver.resolve(current.version.version), current))
- previous.each {
- if (it.toolingApiSupported) {
- add(new Permutation(resolver.resolve(current.version.version), it))
- add(new Permutation(resolver.resolve(it.version.version), current))
+ def resolver = new ToolingApiDistributionResolver().withDefaultRepository()
+ try {
+ add(new Permutation(resolver.resolve(current.version.version), current))
+ previous.each {
+ if (it.toolingApiSupported) {
+ add(new Permutation(resolver.resolve(current.version.version), it))
+ add(new Permutation(resolver.resolve(it.version.version), current))
+ }
}
+ } finally {
+ resolver.stop()
}
}
@@ -67,7 +61,12 @@ class ToolingApiCompatibilitySuiteRunner extends AbstractCompatibilityTestRunner
@Override
protected String getDisplayName() {
- return "${displayName(GradleVersion.version(toolingApi.version))} -> ${displayName(gradle.version)}"
+ return "${displayName(toolingApi.version)} -> ${displayName(gradle.version)}"
+ }
+
+ @Override
+ String toString() {
+ return displayName
}
private String displayName(GradleVersion version) {
@@ -78,7 +77,7 @@ class ToolingApiCompatibilitySuiteRunner extends AbstractCompatibilityTestRunner
}
@Override
- protected boolean isEnabled() {
+ protected boolean isTestEnabled(AbstractMultiTestRunner.TestDetails testDetails) {
if (!gradle.daemonSupported) {
return false
}
@@ -89,16 +88,12 @@ class ToolingApiCompatibilitySuiteRunner extends AbstractCompatibilityTestRunner
// So, for windows we'll only run tests against target gradle that supports ttl
return false
}
- MinToolingApiVersion minToolingApiVersion = target.getAnnotation(MinToolingApiVersion)
- if (minToolingApiVersion && GradleVersion.version(toolingApi.version) < extractVersion(minToolingApiVersion)) {
- return false
- }
- MinTargetGradleVersion minTargetGradleVersion = target.getAnnotation(MinTargetGradleVersion)
- if (minTargetGradleVersion && gradle.version < extractVersion(minTargetGradleVersion)) {
+ ToolingApiVersion toolingApiVersion = testDetails.getAnnotation(ToolingApiVersion)
+ if (!toVersionSpec(toolingApiVersion).isSatisfiedBy(toolingApi.version)) {
return false
}
- MaxTargetGradleVersion maxTargetGradleVersion = target.getAnnotation(MaxTargetGradleVersion)
- if (maxTargetGradleVersion && gradle.version > extractVersion(maxTargetGradleVersion)) {
+ TargetGradleVersion targetGradleVersion = testDetails.getAnnotation(TargetGradleVersion)
+ if (!toVersionSpec(targetGradleVersion).isSatisfiedBy(gradle.version)) {
return false
}
@@ -106,10 +101,6 @@ class ToolingApiCompatibilitySuiteRunner extends AbstractCompatibilityTestRunner
}
private GradleVersion extractVersion(annotation) {
- if (GradleVersion.current().isSnapshot() && GradleVersion.current().version.startsWith(annotation.value())) {
- //so that one can use an unreleased version in the annotation value
- return GradleVersion.current()
- }
if ("current".equals(annotation.value())) {
//so that one can use 'current' literal in the annotation value
//(useful if you don't know if the feature makes its way to the upcoming release)
@@ -118,6 +109,13 @@ class ToolingApiCompatibilitySuiteRunner extends AbstractCompatibilityTestRunner
return GradleVersion.version(annotation.value())
}
+ private Spec<GradleVersion> toVersionSpec(annotation) {
+ if (annotation == null) {
+ return Specs.SATISFIES_ALL
+ }
+ return GradleVersionSpec.toSpec(annotation.value())
+ }
+
@Override
protected List<? extends Class<?>> loadTargetClasses() {
def testClassLoader = getTestClassLoader()
@@ -152,6 +150,8 @@ class ToolingApiCompatibilitySuiteRunner extends AbstractCompatibilityTestRunner
sharedClassLoader.allowClass(OperatingSystem)
sharedClassLoader.allowClass(Requires)
sharedClassLoader.allowClass(TestPrecondition)
+ sharedClassLoader.allowClass(TargetGradleVersion)
+ sharedClassLoader.allowClass(ToolingApiVersion)
sharedClassLoader.allowResources(target.name.replace('.', '/'))
def parentClassLoader = new MultiParentClassLoader(toolingApi.classLoader, sharedClassLoader)
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/ToolingApiDistribution.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/ToolingApiDistribution.groovy
index 0a69936..f1e16ee 100644
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/ToolingApiDistribution.groovy
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/ToolingApiDistribution.groovy
@@ -16,11 +16,11 @@
package org.gradle.integtests.tooling.fixture
-import org.gradle.api.file.FileCollection
import org.gradle.api.Nullable
+import org.gradle.util.GradleVersion
interface ToolingApiDistribution {
- String getVersion()
- @Nullable FileCollection getClasspath()
+ GradleVersion getVersion()
+ @Nullable Collection<File> getClasspath()
ClassLoader getClassLoader()
}
\ No newline at end of file
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/ToolingApiDistributionResolver.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/ToolingApiDistributionResolver.groovy
index 8d1015a..eb62698 100644
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/ToolingApiDistributionResolver.groovy
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/ToolingApiDistributionResolver.groovy
@@ -20,18 +20,20 @@ import org.gradle.StartParameter
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.Dependency
import org.gradle.api.internal.artifacts.DependencyResolutionServices
-import org.gradle.api.internal.project.GlobalServicesRegistry
-import org.gradle.api.internal.project.ProjectInternalServiceRegistry
-import org.gradle.api.internal.project.TopLevelBuildServiceRegistry
import org.gradle.integtests.fixtures.executer.GradleContextualExecuter
import org.gradle.integtests.fixtures.executer.IntegrationTestBuildContext
-import org.gradle.util.HelperUtil
+import org.gradle.internal.CompositeStoppable
+import org.gradle.internal.service.scopes.BuildScopeServices
+import org.gradle.internal.service.scopes.GlobalScopeServices
+import org.gradle.internal.service.scopes.ProjectScopeServices
+import org.gradle.util.TestUtil
class ToolingApiDistributionResolver {
private final DependencyResolutionServices resolutionServices
private final Map<String, ToolingApiDistribution> distributions = [:]
private final IntegrationTestBuildContext buildContext = new IntegrationTestBuildContext()
private boolean useExternalToolingApiDistribution = false;
+ private CompositeStoppable stopLater = new CompositeStoppable()
ToolingApiDistributionResolver() {
resolutionServices = createResolutionServices()
@@ -54,7 +56,7 @@ class ToolingApiDistributionResolver {
} else {
Dependency toolingApiDep = resolutionServices.dependencyHandler.create("org.gradle:gradle-tooling-api:$toolingApiVersion")
Configuration toolingApiConfig = resolutionServices.configurationContainer.detachedConfiguration(toolingApiDep)
- distributions[toolingApiVersion] = new ExternalToolingApiDistribution(toolingApiVersion, toolingApiConfig)
+ distributions[toolingApiVersion] = new ExternalToolingApiDistribution(toolingApiVersion, toolingApiConfig.files)
}
}
distributions[toolingApiVersion]
@@ -67,16 +69,26 @@ class ToolingApiDistributionResolver {
}
private DependencyResolutionServices createResolutionServices() {
- GlobalServicesRegistry globalRegistry = new GlobalServicesRegistry()
+ GlobalScopeServices globalRegistry = new GlobalScopeServices()
StartParameter startParameter = new StartParameter()
startParameter.gradleUserHomeDir = new IntegrationTestBuildContext().gradleUserHomeDir
- TopLevelBuildServiceRegistry topLevelRegistry = new TopLevelBuildServiceRegistry(globalRegistry, startParameter)
- ProjectInternalServiceRegistry projectRegistry = new ProjectInternalServiceRegistry(topLevelRegistry, HelperUtil.createRootProject())
- projectRegistry.get(DependencyResolutionServices)
+ BuildScopeServices topLevelRegistry = new BuildScopeServices(globalRegistry, startParameter)
+ ProjectScopeServices projectRegistry = new ProjectScopeServices(topLevelRegistry, TestUtil.createRootProject())
+
+ stopLater.add(projectRegistry)
+ stopLater.add(topLevelRegistry)
+ // TODO:ADAM - switch this back on
+// stopLater.add(globalRegistry)
+
+ return projectRegistry.get(DependencyResolutionServices)
}
ToolingApiDistributionResolver withExternalToolingApiDistribution() {
this.useExternalToolingApiDistribution = true
this
}
+
+ void stop() {
+ stopLater.stop()
+ }
}
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/ToolingApiSpecification.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/ToolingApiSpecification.groovy
index e0003cb..45b1ca0 100644
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/ToolingApiSpecification.groovy
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/ToolingApiSpecification.groovy
@@ -24,12 +24,22 @@ import org.gradle.tooling.GradleConnector
import org.gradle.util.GradleVersion
import org.gradle.util.SetSystemProperties
import org.junit.Rule
-import org.junit.internal.AssumptionViolatedException
import org.junit.runner.RunWith
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import spock.lang.Specification
+/**
+ * A spec that executes tests against all compatible versions of tooling API consumer and provider, including the current Gradle version under test.
+ *
+ * <p>A test class or test method can be annotated with the following annotations to specify which versions the test is compatible with:
+ * </p>
+ *
+ * <ul>
+ * <li>{@link ToolingApiVersion} - specifies the tooling API consumer versions that the test is compatible with.
+ * <li>{@link TargetGradleVersion} - specifies the tooling API provider versions that the test is compatible with.
+ * </ul>
+ */
@RunWith(ToolingApiCompatibilitySuiteRunner)
abstract class ToolingApiSpecification extends Specification {
static final Logger LOGGER = LoggerFactory.getLogger(ToolingApiSpecification)
@@ -52,10 +62,6 @@ abstract class ToolingApiSpecification extends Specification {
def consumerGradle = GradleVersion.current()
def target = GradleVersion.version(VERSION.get().version.version)
LOGGER.info(" Using Tooling API consumer ${consumerGradle}, provider ${target}")
- boolean accept = accept(consumerGradle, target)
- if (!accept) {
- throw new AssumptionViolatedException("Test class ${getClass().name} does not work with tooling API ${consumerGradle} and Gradle ${target}.")
- }
this.toolingApi.withConnector {
if (consumerGradle.version != target.version) {
LOGGER.info("Overriding daemon tooling API provider to use installation: " + target);
@@ -65,11 +71,8 @@ abstract class ToolingApiSpecification extends Specification {
}
}
- /**
- * Returns true if this test class works with the given combination of tooling API consumer and provider.
- */
- protected boolean accept(GradleVersion toolingApi, GradleVersion targetGradle) {
- return true
+ public void withConnector(Closure cl) {
+ toolingApi.withConnector(cl)
}
public <T> T withConnection(Closure<T> cl) {
@@ -102,10 +105,6 @@ abstract class ToolingApiSpecification extends Specification {
toolingApi.connector()
}
- void maybeFailWithConnection(Closure cl) {
- toolingApi.maybeFailWithConnection(cl)
- }
-
TestFile getProjectDir() {
temporaryFolder.testDirectory
}
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/ToolingApiVersion.java b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/ToolingApiVersion.java
new file mode 100644
index 0000000..a05b648
--- /dev/null
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/fixture/ToolingApiVersion.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests.tooling.fixture;
+
+import java.lang.annotation.*;
+
+/**
+ * Specifies the range of tooling API versions that the given tooling API test can work with.
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target({ElementType.TYPE, ElementType.METHOD})
+ at Inherited
+public @interface ToolingApiVersion {
+ /**
+ * The requested tooling API version. Can use '>=nnn', '<=nnn', '<nnn', '=nnn', 'current' or '!current' or space-separated list of patterns.
+ */
+ String value();
+}
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m3/ToolingApiLoggingCrossVersionSpec.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m3/ToolingApiLoggingCrossVersionSpec.groovy
new file mode 100644
index 0000000..38ac731
--- /dev/null
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m3/ToolingApiLoggingCrossVersionSpec.groovy
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests.tooling.m3
+
+import org.gradle.integtests.tooling.fixture.ToolingApiSpecification
+import org.gradle.test.fixtures.ConcurrentTestUtil
+import org.gradle.tooling.GradleConnectionException
+import org.gradle.tooling.ProjectConnection
+import org.gradle.tooling.ResultHandler
+
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.TimeUnit
+
+class ToolingApiLoggingCrossVersionSpec extends ToolingApiSpecification {
+ def setup() {
+ toolingApi.isEmbedded = false
+ }
+
+ def "logging is live"() {
+ def marker = file("marker.txt")
+
+ file("build.gradle") << """
+task log << {
+ println "waiting"
+ def marker = file('${marker.toURI()}')
+ long timeout = System.currentTimeMillis() + 10000
+ while (!marker.file && System.currentTimeMillis() < timeout) { Thread.sleep(200) }
+ if (!marker.file) { throw new RuntimeException("Timeout waiting for marker file") }
+ println "finished"
+}
+"""
+
+ when:
+ def resultHandler = new TestResultHandler()
+ def output = new TestOutputStream()
+ withConnection { ProjectConnection connection ->
+ def build = connection.newBuild()
+ build.standardOutput = output
+ build.forTasks("log")
+ build.run(resultHandler)
+ ConcurrentTestUtil.poll(10) { output.toString().contains("waiting") }
+ marker.text = 'go!'
+ resultHandler.finished()
+ }
+
+ then:
+ output.toString().contains("waiting")
+ output.toString().contains("finished")
+ }
+
+ class TestResultHandler implements ResultHandler<Object> {
+ final latch = new CountDownLatch(1)
+ def failure
+
+ void onComplete(Object result) {
+ latch.countDown()
+ }
+
+ void onFailure(GradleConnectionException failure) {
+ this.failure = failure
+ latch.countDown()
+ }
+
+ def finished() {
+ latch.await(10, TimeUnit.SECONDS)
+ if (failure != null) {
+ throw failure
+ }
+ }
+ }
+
+ class TestOutputStream extends OutputStream {
+ final buffer = new ByteArrayOutputStream()
+
+ @Override
+ void write(int b) throws IOException {
+ synchronized (buffer) {
+ buffer.write(b)
+ }
+ }
+
+ @Override
+ String toString() {
+ synchronized (buffer) {
+ return buffer.toString()
+ }
+ }
+ }
+}
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m4/ToolingApiEclipseLinkedResourcesCrossVersionSpec.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m4/ToolingApiEclipseLinkedResourcesCrossVersionSpec.groovy
index e7350ca..2061b82 100644
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m4/ToolingApiEclipseLinkedResourcesCrossVersionSpec.groovy
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m4/ToolingApiEclipseLinkedResourcesCrossVersionSpec.groovy
@@ -16,16 +16,13 @@
package org.gradle.integtests.tooling.m4
-import org.gradle.integtests.tooling.fixture.MinTargetGradleVersion
-import org.gradle.integtests.tooling.fixture.MinToolingApiVersion
+import org.gradle.integtests.tooling.fixture.TargetGradleVersion
+import org.gradle.integtests.tooling.fixture.ToolingApiVersion
import org.gradle.integtests.tooling.fixture.ToolingApiSpecification
import org.gradle.tooling.model.eclipse.HierarchicalEclipseProject
-/**
- * @author: Szczepan Faber, created at: 6/11/11
- */
- at MinToolingApiVersion('1.0-milestone-4')
- at MinTargetGradleVersion('1.0-milestone-4')
+ at ToolingApiVersion('>=1.0-milestone-4')
+ at TargetGradleVersion('>=1.0-milestone-4')
class ToolingApiEclipseLinkedResourcesCrossVersionSpec extends ToolingApiSpecification {
def "can build linked resources"() {
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m4/ToolingApiEclipseMinimalModelCrossVersionSpec.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m4/ToolingApiEclipseMinimalModelCrossVersionSpec.groovy
index f9fdfd3..52a7e10 100644
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m4/ToolingApiEclipseMinimalModelCrossVersionSpec.groovy
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m4/ToolingApiEclipseMinimalModelCrossVersionSpec.groovy
@@ -15,11 +15,11 @@
*/
package org.gradle.integtests.tooling.m4
-import org.gradle.integtests.tooling.fixture.MinTargetGradleVersion
+import org.gradle.integtests.tooling.fixture.TargetGradleVersion
import org.gradle.integtests.tooling.fixture.ToolingApiSpecification
import org.gradle.tooling.model.eclipse.HierarchicalEclipseProject
- at MinTargetGradleVersion('1.0-milestone-4')
+ at TargetGradleVersion('>=1.0-milestone-4')
class ToolingApiEclipseMinimalModelCrossVersionSpec extends ToolingApiSpecification {
def "minimal Eclipse model does not attempt to resolve external dependencies"() {
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m5/EclipseModelWithFlatRepoCrossVersionSpec.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m5/EclipseModelWithFlatRepoCrossVersionSpec.groovy
index cc75efd..57ad728 100644
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m5/EclipseModelWithFlatRepoCrossVersionSpec.groovy
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m5/EclipseModelWithFlatRepoCrossVersionSpec.groovy
@@ -16,12 +16,12 @@
package org.gradle.integtests.tooling.m5
-import org.gradle.integtests.tooling.fixture.MinTargetGradleVersion
+import org.gradle.integtests.tooling.fixture.TargetGradleVersion
import org.gradle.integtests.tooling.fixture.ToolingApiSpecification
import org.gradle.tooling.model.eclipse.EclipseProject
import spock.lang.Issue
- at MinTargetGradleVersion('1.0-milestone-5')
+ at TargetGradleVersion('>=1.0-milestone-5')
class EclipseModelWithFlatRepoCrossVersionSpec extends ToolingApiSpecification {
@Issue("GRADLE-1621")
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m5/ToolingApiBuildExecutionCrossVersionSpec.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m5/ToolingApiBuildExecutionCrossVersionSpec.groovy
index 5840fef..dbe9248 100644
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m5/ToolingApiBuildExecutionCrossVersionSpec.groovy
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m5/ToolingApiBuildExecutionCrossVersionSpec.groovy
@@ -15,16 +15,16 @@
*/
package org.gradle.integtests.tooling.m5
-import org.gradle.integtests.tooling.fixture.MinTargetGradleVersion
-import org.gradle.integtests.tooling.fixture.MinToolingApiVersion
+import org.gradle.integtests.tooling.fixture.TargetGradleVersion
import org.gradle.integtests.tooling.fixture.ToolingApiSpecification
+import org.gradle.integtests.tooling.fixture.ToolingApiVersion
import org.gradle.tooling.BuildException
import org.gradle.tooling.model.GradleProject
import org.gradle.tooling.model.Task
import org.gradle.tooling.model.eclipse.EclipseProject
- at MinToolingApiVersion('1.0-milestone-5')
- at MinTargetGradleVersion('1.0-milestone-5')
+ at ToolingApiVersion('>=1.0-milestone-5')
+ at TargetGradleVersion('>=1.0-milestone-5')
class ToolingApiBuildExecutionCrossVersionSpec extends ToolingApiSpecification {
def "can build the set of tasks for a project"() {
file('build.gradle') << '''
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m5/ToolingApiBuildableEclipseModelFixesCrossVersionSpec.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m5/ToolingApiBuildableEclipseModelFixesCrossVersionSpec.groovy
index 3e00e10..d95aa5f 100644
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m5/ToolingApiBuildableEclipseModelFixesCrossVersionSpec.groovy
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m5/ToolingApiBuildableEclipseModelFixesCrossVersionSpec.groovy
@@ -15,15 +15,15 @@
*/
package org.gradle.integtests.tooling.m5
-import org.gradle.integtests.tooling.fixture.MinTargetGradleVersion
-import org.gradle.integtests.tooling.fixture.MinToolingApiVersion
+import org.gradle.integtests.tooling.fixture.TargetGradleVersion
+import org.gradle.integtests.tooling.fixture.ToolingApiVersion
import org.gradle.integtests.tooling.fixture.ToolingApiSpecification
import org.gradle.tooling.model.GradleProject
import org.gradle.tooling.model.eclipse.EclipseProject
import spock.lang.Issue
- at MinToolingApiVersion('1.0-milestone-5')
- at MinTargetGradleVersion('1.0-milestone-5')
+ at ToolingApiVersion('>=1.0-milestone-5')
+ at TargetGradleVersion('>=1.0-milestone-5')
class ToolingApiBuildableEclipseModelFixesCrossVersionSpec extends ToolingApiSpecification {
@Issue("GRADLE-1529")
//this is just one of the ways of fixing the problem. See the issue for details
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m5/ToolingApiEclipseModelCrossVersionSpec.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m5/ToolingApiEclipseModelCrossVersionSpec.groovy
index 88c223c..a511ac2 100644
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m5/ToolingApiEclipseModelCrossVersionSpec.groovy
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m5/ToolingApiEclipseModelCrossVersionSpec.groovy
@@ -15,13 +15,11 @@
*/
package org.gradle.integtests.tooling.m5
-import org.gradle.integtests.tooling.fixture.MinTargetGradleVersion
-import org.gradle.integtests.tooling.fixture.MinToolingApiVersion
+import org.gradle.integtests.tooling.fixture.ToolingApiVersion
import org.gradle.integtests.tooling.fixture.ToolingApiSpecification
import org.gradle.tooling.model.eclipse.EclipseProject
- at MinToolingApiVersion('1.0-milestone-5')
- at MinTargetGradleVersion('1.0-milestone-3')
+ at ToolingApiVersion('>=1.0-milestone-5')
class ToolingApiEclipseModelCrossVersionSpec extends ToolingApiSpecification {
def "eclipse project has access to gradle project and its tasks"() {
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m5/ToolingApiGradleProjectCrossVersionSpec.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m5/ToolingApiGradleProjectCrossVersionSpec.groovy
index 74a52b3..08cdd50 100644
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m5/ToolingApiGradleProjectCrossVersionSpec.groovy
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m5/ToolingApiGradleProjectCrossVersionSpec.groovy
@@ -15,14 +15,12 @@
*/
package org.gradle.integtests.tooling.m5
-import org.gradle.integtests.tooling.fixture.MinTargetGradleVersion
-import org.gradle.integtests.tooling.fixture.MinToolingApiVersion
+import org.gradle.integtests.tooling.fixture.ToolingApiVersion
import org.gradle.integtests.tooling.fixture.ToolingApiSpecification
import org.gradle.tooling.model.GradleProject
import org.gradle.tooling.model.GradleTask
- at MinToolingApiVersion('1.0-milestone-5')
- at MinTargetGradleVersion('1.0-milestone-3')
+ at ToolingApiVersion('>=1.0-milestone-5')
class ToolingApiGradleProjectCrossVersionSpec extends ToolingApiSpecification {
def "provides tasks of a project"() {
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m5/ToolingApiHonorsProjectCustomizationsCrossVersionSpec.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m5/ToolingApiHonorsProjectCustomizationsCrossVersionSpec.groovy
index 49f4683..adbb978 100755
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m5/ToolingApiHonorsProjectCustomizationsCrossVersionSpec.groovy
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m5/ToolingApiHonorsProjectCustomizationsCrossVersionSpec.groovy
@@ -15,14 +15,14 @@
*/
package org.gradle.integtests.tooling.m5
-import org.gradle.integtests.tooling.fixture.MinTargetGradleVersion
-import org.gradle.integtests.tooling.fixture.MinToolingApiVersion
+import org.gradle.integtests.tooling.fixture.TargetGradleVersion
import org.gradle.integtests.tooling.fixture.ToolingApiSpecification
+import org.gradle.integtests.tooling.fixture.ToolingApiVersion
import org.gradle.tooling.ProjectConnection
import org.gradle.tooling.model.eclipse.EclipseProject
- at MinToolingApiVersion('1.0-milestone-5')
- at MinTargetGradleVersion('1.0-milestone-5')
+ at ToolingApiVersion('>=1.0-milestone-5')
+ at TargetGradleVersion('>=1.0-milestone-5')
class ToolingApiHonorsProjectCustomizationsCrossVersionSpec extends ToolingApiSpecification {
def "should honour reconfigured project names"() {
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m5/ToolingApiIdeaModelCrossVersionSpec.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m5/ToolingApiIdeaModelCrossVersionSpec.groovy
index 954aaee..9894ddd 100644
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m5/ToolingApiIdeaModelCrossVersionSpec.groovy
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m5/ToolingApiIdeaModelCrossVersionSpec.groovy
@@ -15,14 +15,14 @@
*/
package org.gradle.integtests.tooling.m5
-import org.gradle.integtests.tooling.fixture.MinTargetGradleVersion
-import org.gradle.integtests.tooling.fixture.MinToolingApiVersion
+import org.gradle.integtests.tooling.fixture.TargetGradleVersion
import org.gradle.integtests.tooling.fixture.ToolingApiSpecification
+import org.gradle.integtests.tooling.fixture.ToolingApiVersion
import org.gradle.test.fixtures.maven.MavenFileRepository
import org.gradle.tooling.model.idea.*
- at MinToolingApiVersion('1.0-milestone-5')
- at MinTargetGradleVersion('1.0-milestone-5')
+ at ToolingApiVersion('>=1.0-milestone-5')
+ at TargetGradleVersion('>=1.0-milestone-5')
class ToolingApiIdeaModelCrossVersionSpec extends ToolingApiSpecification {
def "builds the model even if idea plugin not applied"() {
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m5/ToolingApiModelCrossVersionSpec.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m5/ToolingApiModelCrossVersionSpec.groovy
index fc782a4..ec22d1f 100644
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m5/ToolingApiModelCrossVersionSpec.groovy
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m5/ToolingApiModelCrossVersionSpec.groovy
@@ -15,14 +15,14 @@
*/
package org.gradle.integtests.tooling.m5
-import org.gradle.integtests.tooling.fixture.MinTargetGradleVersion
-import org.gradle.integtests.tooling.fixture.MinToolingApiVersion
+import org.gradle.integtests.tooling.fixture.TargetGradleVersion
+import org.gradle.integtests.tooling.fixture.ToolingApiVersion
import org.gradle.integtests.tooling.fixture.ToolingApiSpecification
import org.gradle.tooling.BuildException
import org.gradle.tooling.model.GradleProject
- at MinToolingApiVersion('1.0-milestone-5')
- at MinTargetGradleVersion('1.0-milestone-5')
+ at ToolingApiVersion('>=1.0-milestone-5')
+ at TargetGradleVersion('>=1.0-milestone-5')
class ToolingApiModelCrossVersionSpec extends ToolingApiSpecification {
def "receives progress while the model is building"() {
file('build.gradle') << '''
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m5/ToolingApiReceivingStandardStreamsCrossVersionSpec.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m5/ToolingApiReceivingStandardStreamsCrossVersionSpec.groovy
index e7fd795..3820282 100644
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m5/ToolingApiReceivingStandardStreamsCrossVersionSpec.groovy
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m5/ToolingApiReceivingStandardStreamsCrossVersionSpec.groovy
@@ -15,13 +15,13 @@
*/
package org.gradle.integtests.tooling.m5
-import org.gradle.integtests.tooling.fixture.MinTargetGradleVersion
-import org.gradle.integtests.tooling.fixture.MinToolingApiVersion
+import org.gradle.integtests.tooling.fixture.TargetGradleVersion
import org.gradle.integtests.tooling.fixture.ToolingApiSpecification
+import org.gradle.integtests.tooling.fixture.ToolingApiVersion
import org.gradle.tooling.model.GradleProject
- at MinToolingApiVersion('1.0-milestone-5')
- at MinTargetGradleVersion('1.0-milestone-5')
+ at ToolingApiVersion('>=1.0-milestone-5')
+ at TargetGradleVersion('>=1.0-milestone-5')
class ToolingApiReceivingStandardStreamsCrossVersionSpec extends ToolingApiSpecification {
def setup() {
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m5/UnsupportedModelFeedbackCrossVersionSpec.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m5/UnsupportedModelFeedbackCrossVersionSpec.groovy
new file mode 100644
index 0000000..2572087
--- /dev/null
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m5/UnsupportedModelFeedbackCrossVersionSpec.groovy
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests.tooling.m5
+
+import org.gradle.integtests.tooling.fixture.TargetGradleVersion
+import org.gradle.integtests.tooling.fixture.ToolingApiSpecification
+import org.gradle.tooling.UnknownModelException
+import org.gradle.tooling.model.idea.BasicIdeaProject
+import org.gradle.tooling.model.idea.IdeaProject
+
+ at TargetGradleVersion('<=1.0-milestone-4')
+class UnsupportedModelFeedbackCrossVersionSpec extends ToolingApiSpecification {
+ def "fails gracefully when unsupported model requested"() {
+ when:
+ withConnection { it.getModel(model) }
+
+ then:
+ UnknownModelException e = thrown()
+ e.message.contains(model.simpleName)
+
+ where:
+ model << [IdeaProject, BasicIdeaProject]
+ }
+}
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m8/BuildEnvironmentModelCrossVersionSpec.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m8/BuildEnvironmentModelCrossVersionSpec.groovy
index 14d9260..635bc0b 100644
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m8/BuildEnvironmentModelCrossVersionSpec.groovy
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m8/BuildEnvironmentModelCrossVersionSpec.groovy
@@ -16,14 +16,14 @@
package org.gradle.integtests.tooling.m8
-import org.gradle.integtests.tooling.fixture.MinTargetGradleVersion
-import org.gradle.integtests.tooling.fixture.MinToolingApiVersion
+import org.gradle.integtests.tooling.fixture.TargetGradleVersion
import org.gradle.integtests.tooling.fixture.ToolingApiSpecification
+import org.gradle.integtests.tooling.fixture.ToolingApiVersion
import org.gradle.tooling.model.GradleProject
import org.gradle.tooling.model.build.BuildEnvironment
- at MinToolingApiVersion('1.0-milestone-8')
- at MinTargetGradleVersion('1.0-milestone-8')
+ at ToolingApiVersion('>=1.0-milestone-8')
+ at TargetGradleVersion('>=1.0-milestone-8')
class BuildEnvironmentModelCrossVersionSpec extends ToolingApiSpecification {
def "informs about build environment"() {
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m8/ConsumingStandardInputCrossVersionSpec.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m8/ConsumingStandardInputCrossVersionSpec.groovy
index bf0e97c..3346da2 100644
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m8/ConsumingStandardInputCrossVersionSpec.groovy
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m8/ConsumingStandardInputCrossVersionSpec.groovy
@@ -16,15 +16,15 @@
package org.gradle.integtests.tooling.m8
-import org.gradle.integtests.tooling.fixture.MinTargetGradleVersion
-import org.gradle.integtests.tooling.fixture.MinToolingApiVersion
+import org.gradle.integtests.tooling.fixture.TargetGradleVersion
+import org.gradle.integtests.tooling.fixture.ToolingApiVersion
import org.gradle.integtests.tooling.fixture.ToolingApiSpecification
import org.gradle.tooling.ProjectConnection
import org.gradle.tooling.model.GradleProject
import spock.lang.Timeout
- at MinToolingApiVersion('1.0-milestone-8')
- at MinTargetGradleVersion('1.0-milestone-8')
+ at ToolingApiVersion('>=1.0-milestone-8')
+ at TargetGradleVersion('>=1.0-milestone-8')
class ConsumingStandardInputCrossVersionSpec extends ToolingApiSpecification {
def setup() {
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m8/GradlePropertiesToolingApiCrossVersionSpec.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m8/GradlePropertiesToolingApiCrossVersionSpec.groovy
index 4573b64..89c13e8 100644
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m8/GradlePropertiesToolingApiCrossVersionSpec.groovy
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m8/GradlePropertiesToolingApiCrossVersionSpec.groovy
@@ -17,15 +17,15 @@
package org.gradle.integtests.tooling.m8
import org.gradle.integtests.fixtures.AvailableJavaHomes
-import org.gradle.integtests.tooling.fixture.MinTargetGradleVersion
-import org.gradle.integtests.tooling.fixture.MinToolingApiVersion
+import org.gradle.integtests.tooling.fixture.TargetGradleVersion
+import org.gradle.integtests.tooling.fixture.ToolingApiVersion
import org.gradle.integtests.tooling.fixture.TextUtil
import org.gradle.integtests.tooling.fixture.ToolingApiSpecification
import org.gradle.tooling.model.build.BuildEnvironment
import spock.lang.IgnoreIf
- at MinToolingApiVersion('1.0-milestone-8')
- at MinTargetGradleVersion('1.0-milestone-8')
+ at ToolingApiVersion('>=1.0-milestone-8')
+ at TargetGradleVersion('>=1.0-milestone-8')
class GradlePropertiesToolingApiCrossVersionSpec extends ToolingApiSpecification {
def setup() {
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m8/JavaConfigurabilityCrossVersionSpec.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m8/JavaConfigurabilityCrossVersionSpec.groovy
index d822b72..e2d4468 100644
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m8/JavaConfigurabilityCrossVersionSpec.groovy
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m8/JavaConfigurabilityCrossVersionSpec.groovy
@@ -16,16 +16,16 @@
package org.gradle.integtests.tooling.m8
-import org.gradle.integtests.tooling.fixture.MinTargetGradleVersion
-import org.gradle.integtests.tooling.fixture.MinToolingApiVersion
+import org.gradle.integtests.tooling.fixture.TargetGradleVersion
import org.gradle.integtests.tooling.fixture.ToolingApiSpecification
+import org.gradle.integtests.tooling.fixture.ToolingApiVersion
import org.gradle.tooling.model.GradleProject
import org.gradle.tooling.model.build.BuildEnvironment
import spock.lang.Issue
import spock.lang.Timeout
- at MinToolingApiVersion('1.0-milestone-8')
- at MinTargetGradleVersion('1.0-milestone-8')
+ at ToolingApiVersion('>=1.0-milestone-8')
+ at TargetGradleVersion('>=1.0-milestone-8')
class JavaConfigurabilityCrossVersionSpec extends ToolingApiSpecification {
def setup() {
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m8/StrictLongRunningOperationCrossVersionSpec.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m8/StrictLongRunningOperationCrossVersionSpec.groovy
index c9e400c..65ec7a0 100644
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m8/StrictLongRunningOperationCrossVersionSpec.groovy
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m8/StrictLongRunningOperationCrossVersionSpec.groovy
@@ -17,19 +17,15 @@
package org.gradle.integtests.tooling.m8
import org.gradle.integtests.fixtures.AvailableJavaHomes
-import org.gradle.integtests.tooling.fixture.MaxTargetGradleVersion
-import org.gradle.integtests.tooling.fixture.MinTargetGradleVersion
-import org.gradle.integtests.tooling.fixture.MinToolingApiVersion
+import org.gradle.integtests.tooling.fixture.TargetGradleVersion
import org.gradle.integtests.tooling.fixture.ToolingApiSpecification
+import org.gradle.integtests.tooling.fixture.ToolingApiVersion
import org.gradle.tooling.exceptions.UnsupportedOperationConfigurationException
-import org.gradle.tooling.model.UnsupportedMethodException
import org.gradle.tooling.model.build.BuildEnvironment
-import org.gradle.tooling.model.internal.Exceptions
import spock.lang.IgnoreIf
- at MinToolingApiVersion('1.0-milestone-8')
- at MinTargetGradleVersion('1.0-milestone-3')
- at MaxTargetGradleVersion('1.0-milestone-7') //the configuration was not supported for old versions
+ at ToolingApiVersion('>=1.0-milestone-8')
+ at TargetGradleVersion('<=1.0-milestone-7')
class StrictLongRunningOperationCrossVersionSpec extends ToolingApiSpecification {
def setup() {
@@ -42,7 +38,7 @@ class StrictLongRunningOperationCrossVersionSpec extends ToolingApiSpecification
def "fails eagerly when java home unsupported for model"() {
def java = AvailableJavaHomes.bestAlternative
when:
- maybeFailWithConnection {
+ withConnection {
def model = it.model(BuildEnvironment.class)
model.setJavaHome(java)
model.get()
@@ -57,7 +53,7 @@ class StrictLongRunningOperationCrossVersionSpec extends ToolingApiSpecification
def "fails eagerly when java home unsupported for build"() {
def java = AvailableJavaHomes.bestAlternative
when:
- maybeFailWithConnection {
+ withConnection {
def build = it.newBuild()
build.setJavaHome(java)
build.forTasks('tasks').run()
@@ -70,7 +66,7 @@ class StrictLongRunningOperationCrossVersionSpec extends ToolingApiSpecification
def "fails eagerly when java args unsupported"() {
when:
- maybeFailWithConnection {
+ withConnection {
def model = it.model(BuildEnvironment.class)
model.setJvmArguments("-Xmx512m")
model.get()
@@ -83,7 +79,7 @@ class StrictLongRunningOperationCrossVersionSpec extends ToolingApiSpecification
def "fails eagerly when standard input unsupported"() {
when:
- maybeFailWithConnection {
+ withConnection {
def model = it.model(BuildEnvironment.class)
model.setStandardInput(new ByteArrayInputStream('yo!'.bytes))
model.get()
@@ -95,11 +91,6 @@ class StrictLongRunningOperationCrossVersionSpec extends ToolingApiSpecification
}
void assertExceptionInformative(UnsupportedOperationConfigurationException actual, String expectedMessageSubstring) {
- assert !actual.message.contains(Exceptions.INCOMPATIBLE_VERSION_HINT) //no need for hint, the message is already good
assert actual.message.contains(expectedMessageSubstring)
-
- //we don't really need that exception as a cause
- //but one of the versions was released with it as a cause so to keep things compatible
- assert actual.cause instanceof UnsupportedMethodException
}
}
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m8/ToolingApiEclipseModelCrossVersionSpec.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m8/ToolingApiEclipseModelCrossVersionSpec.groovy
index 68a2b9e..df96e11 100644
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m8/ToolingApiEclipseModelCrossVersionSpec.groovy
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m8/ToolingApiEclipseModelCrossVersionSpec.groovy
@@ -15,15 +15,15 @@
*/
package org.gradle.integtests.tooling.m8
-import org.gradle.integtests.tooling.fixture.MinTargetGradleVersion
-import org.gradle.integtests.tooling.fixture.MinToolingApiVersion
+import org.gradle.integtests.tooling.fixture.TargetGradleVersion
+import org.gradle.integtests.tooling.fixture.ToolingApiVersion
import org.gradle.integtests.tooling.fixture.ToolingApiSpecification
import org.gradle.tooling.model.eclipse.EclipseProject
- at MinToolingApiVersion('1.0-milestone-3')
- at MinTargetGradleVersion('1.0-milestone-8')
+ at ToolingApiVersion('>=1.0-milestone-3')
+ at TargetGradleVersion('>=1.0-milestone-8')
class ToolingApiEclipseModelCrossVersionSpec extends ToolingApiSpecification {
- def "can customise model late in the configuration phase"() {
+ def "can customize model late in the configuration phase"() {
projectDir.file('build.gradle').text = """
apply plugin: 'java'
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m8/ToolingApiLoggingCrossVersionSpec.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m8/ToolingApiLoggingCrossVersionSpec.groovy
index 39ec358..79cf549 100644
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m8/ToolingApiLoggingCrossVersionSpec.groovy
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m8/ToolingApiLoggingCrossVersionSpec.groovy
@@ -16,13 +16,14 @@
package org.gradle.integtests.tooling.m8
-import org.gradle.integtests.tooling.fixture.MinTargetGradleVersion
-import org.gradle.integtests.tooling.fixture.MinToolingApiVersion
+import org.gradle.integtests.tooling.fixture.TargetGradleVersion
import org.gradle.integtests.tooling.fixture.ToolingApiSpecification
+import org.gradle.integtests.tooling.fixture.ToolingApiVersion
import org.gradle.tooling.internal.consumer.ConnectorServices
+import org.junit.Assume
- at MinToolingApiVersion('1.0-milestone-8')
- at MinTargetGradleVersion('1.0-milestone-8')
+ at ToolingApiVersion('>=1.0-milestone-8')
+ at TargetGradleVersion('>=1.0-milestone-8')
class ToolingApiLoggingCrossVersionSpec extends ToolingApiSpecification {
def setup() {
@@ -35,7 +36,7 @@ class ToolingApiLoggingCrossVersionSpec extends ToolingApiSpecification {
new ConnectorServices().reset()
}
- def "logs necessary information when verbose"() {
+ def "client receives same stdout and stderr when in verbose mode as if running from the command-line in debug mode"() {
toolingApi.verboseLogging = true
file("build.gradle") << """
@@ -73,42 +74,48 @@ project.logger.debug("debug logging yyy");
shouldNotContainProviderLogging(err)
}
- def "logs necessary information"() {
+ def "client receives same standard output and standard error as if running from the command-line"() {
+ Assume.assumeTrue targetDist.toolingApiNonAsciiOutputSupported
toolingApi.verboseLogging = false
file("build.gradle") << """
-System.err.println "sys err logging xxx"
+System.err.println "System.err \u03b1\u03b2"
-println "println logging yyy"
+println "System.out \u03b1\u03b2"
-project.logger.error("error logging xxx");
-project.logger.warn("warn logging yyy");
-project.logger.lifecycle("lifecycle logging yyy");
-project.logger.quiet("quiet logging yyy");
-project.logger.info ("info logging yyy");
-project.logger.debug("debug logging yyy");
+project.logger.error("error logging \u03b1\u03b2");
+project.logger.warn("warn logging");
+project.logger.lifecycle("lifecycle logging \u03b1\u03b2");
+project.logger.quiet("quiet logging");
+project.logger.info ("info logging");
+project.logger.debug("debug logging");
"""
when:
+ def commandLineResult = targetDist.executer(temporaryFolder).run();
+
+ and:
def op = withBuild()
then:
def out = op.standardOutput
- out.count("debug logging yyy") == 0
- out.count("info logging yyy") == 0
- out.count("quiet logging yyy") == 1
- out.count("lifecycle logging yyy") == 1
- out.count("warn logging yyy") == 1
- out.count("println logging yyy") == 1
- out.count("error logging xxx") == 0
-
- shouldNotContainProviderLogging(out)
-
def err = op.standardError
- err.count("error logging") == 1
- err.count("sys err") == 1
- err.count("logging yyy") == 0
+ normaliseOutput(out) == normaliseOutput(commandLineResult.output)
+ err == commandLineResult.error
+
+ and:
+ err.count("System.err \u03b1\u03b2") == 1
+ err.count("error logging \u03b1\u03b2") == 1
+
+ and:
+ out.count("lifecycle logging \u03b1\u03b2") == 1
+ out.count("warn logging") == 1
+ out.count("quiet logging") == 1
+ out.count("info") == 0
+ out.count("debug") == 0
+ }
- shouldNotContainProviderLogging(err)
+ String normaliseOutput(String output) {
+ return output.replaceFirst("Total time: .+ secs", "Total time: 0 secs")
}
void shouldNotContainProviderLogging(String output) {
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m8/UnknownModelFeedbackCrossVersionSpec.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m8/UnknownModelFeedbackCrossVersionSpec.groovy
deleted file mode 100644
index 413c4fc..0000000
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m8/UnknownModelFeedbackCrossVersionSpec.groovy
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.integtests.tooling.m8
-
-import org.gradle.integtests.tooling.fixture.MinTargetGradleVersion
-import org.gradle.integtests.tooling.fixture.MinToolingApiVersion
-import org.gradle.integtests.tooling.fixture.ToolingApiSpecification
-import org.gradle.tooling.UnknownModelException
-
- at MinToolingApiVersion('1.0-milestone-8')
- at MinTargetGradleVersion('1.0-milestone-3')
-class UnknownModelFeedbackCrossVersionSpec extends ToolingApiSpecification {
-
- class UnknownModel {}
-
- def "fails gracefully when building unknown model"() {
- //this test exposes a daemon issue that appears in M5 and M6
- //basically when we ask to build a model for a an unknown type for given provider
- //the daemon breaks and does not return anything to the client making the client waiting forever.
-
- when:
- maybeFailWithConnection { it.getModel(UnknownModel.class) }
-
- then:
- UnknownModelException e = thrown()
- e.message.contains('Unknown model: \'UnknownModel\'.')
- }
-}
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m8/VersionOnlyBuildEnvironmentCrossVersionSpec.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m8/VersionOnlyBuildEnvironmentCrossVersionSpec.groovy
index b8757d2..18ff125 100644
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m8/VersionOnlyBuildEnvironmentCrossVersionSpec.groovy
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m8/VersionOnlyBuildEnvironmentCrossVersionSpec.groovy
@@ -16,16 +16,14 @@
package org.gradle.integtests.tooling.m8
-import org.gradle.integtests.tooling.fixture.MaxTargetGradleVersion
-import org.gradle.integtests.tooling.fixture.MinTargetGradleVersion
-import org.gradle.integtests.tooling.fixture.MinToolingApiVersion
+import org.gradle.integtests.tooling.fixture.TargetGradleVersion
import org.gradle.integtests.tooling.fixture.ToolingApiSpecification
+import org.gradle.integtests.tooling.fixture.ToolingApiVersion
import org.gradle.tooling.model.UnsupportedMethodException
import org.gradle.tooling.model.build.BuildEnvironment
- at MinToolingApiVersion('1.0-milestone-8')
- at MinTargetGradleVersion('1.0-milestone-3')
- at MaxTargetGradleVersion('1.0-milestone-7')
+ at ToolingApiVersion('>=1.0-milestone-8')
+ at TargetGradleVersion('<=1.0-milestone-7')
class VersionOnlyBuildEnvironmentCrossVersionSpec extends ToolingApiSpecification {
def "informs about version"() {
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m9/DaemonErrorFeedbackCrossVersionSpec.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m9/DaemonErrorFeedbackCrossVersionSpec.groovy
index 6ccde3d..151d34a 100644
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m9/DaemonErrorFeedbackCrossVersionSpec.groovy
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m9/DaemonErrorFeedbackCrossVersionSpec.groovy
@@ -16,15 +16,15 @@
package org.gradle.integtests.tooling.m9
-import org.gradle.integtests.tooling.fixture.MinTargetGradleVersion
-import org.gradle.integtests.tooling.fixture.MinToolingApiVersion
+import org.gradle.integtests.tooling.fixture.TargetGradleVersion
+import org.gradle.integtests.tooling.fixture.ToolingApiVersion
import org.gradle.integtests.tooling.fixture.ToolingApiSpecification
import org.gradle.tooling.GradleConnectionException
import spock.lang.Issue
import spock.lang.Timeout
- at MinToolingApiVersion('1.0-milestone-9')
- at MinTargetGradleVersion('1.0-milestone-9')
+ at ToolingApiVersion('>=1.0-milestone-9')
+ at TargetGradleVersion('>=1.0-milestone-9')
class DaemonErrorFeedbackCrossVersionSpec extends ToolingApiSpecification {
@Issue("GRADLE-1799")
@@ -35,7 +35,7 @@ class DaemonErrorFeedbackCrossVersionSpec extends ToolingApiSpecification {
toolingApi.isEmbedded = false
when:
- maybeFailWithConnection {
+ withConnection {
it.newBuild()
.setJvmArguments("-Xasdf")
.run()
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m9/M9JavaConfigurabilityCrossVersionSpec.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m9/M9JavaConfigurabilityCrossVersionSpec.groovy
index 9e3961a..2c489a9 100644
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m9/M9JavaConfigurabilityCrossVersionSpec.groovy
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/m9/M9JavaConfigurabilityCrossVersionSpec.groovy
@@ -17,8 +17,8 @@
package org.gradle.integtests.tooling.m9
import org.gradle.integtests.fixtures.AvailableJavaHomes
-import org.gradle.integtests.tooling.fixture.MinTargetGradleVersion
-import org.gradle.integtests.tooling.fixture.MinToolingApiVersion
+import org.gradle.integtests.tooling.fixture.TargetGradleVersion
+import org.gradle.integtests.tooling.fixture.ToolingApiVersion
import org.gradle.integtests.tooling.fixture.TextUtil
import org.gradle.integtests.tooling.fixture.ToolingApiSpecification
import org.gradle.tooling.GradleConnectionException
@@ -29,8 +29,8 @@ import spock.lang.IgnoreIf
import spock.lang.Issue
import spock.lang.Timeout
- at MinToolingApiVersion('1.0-milestone-9')
- at MinTargetGradleVersion('1.0-milestone-8')
+ at ToolingApiVersion('>=1.0-milestone-9')
+ at TargetGradleVersion('>=1.0-milestone-8')
class M9JavaConfigurabilityCrossVersionSpec extends ToolingApiSpecification {
def setup() {
@@ -58,7 +58,7 @@ class M9JavaConfigurabilityCrossVersionSpec extends ToolingApiSpecification {
def dummyJdk = file("wrong jdk location").createDir()
when:
- maybeFailWithConnection {
+ withConnection {
it.newBuild().setJavaHome(dummyJdk).run()
}
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r10rc1/PassingCommandLineArgumentsCrossVersionSpec.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r10rc1/PassingCommandLineArgumentsCrossVersionSpec.groovy
index 3495b2c..5252f14 100644
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r10rc1/PassingCommandLineArgumentsCrossVersionSpec.groovy
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r10rc1/PassingCommandLineArgumentsCrossVersionSpec.groovy
@@ -18,15 +18,15 @@
package org.gradle.integtests.tooling.r10rc1
-import org.gradle.integtests.tooling.fixture.MinTargetGradleVersion
-import org.gradle.integtests.tooling.fixture.MinToolingApiVersion
+import org.gradle.integtests.tooling.fixture.TargetGradleVersion
import org.gradle.integtests.tooling.fixture.ToolingApiSpecification
+import org.gradle.integtests.tooling.fixture.ToolingApiVersion
import org.gradle.tooling.ProjectConnection
import org.gradle.tooling.exceptions.UnsupportedBuildArgumentException
import org.gradle.tooling.model.GradleProject
- at MinToolingApiVersion("1.0-rc-1")
- at MinTargetGradleVersion("1.0-rc-2")
+ at ToolingApiVersion(">=1.0")
+ at TargetGradleVersion(">=1.0")
class PassingCommandLineArgumentsCrossVersionSpec extends ToolingApiSpecification {
// We don't want to validate *all* command line options here, just enough to make sure passing through works.
@@ -107,7 +107,7 @@ class PassingCommandLineArgumentsCrossVersionSpec extends ToolingApiSpecificatio
def "gives decent feedback for invalid option"() {
when:
- maybeFailWithConnection { ProjectConnection it ->
+ withConnection { ProjectConnection it ->
it.newBuild().withArguments('--foreground').run()
}
@@ -144,12 +144,11 @@ class PassingCommandLineArgumentsCrossVersionSpec extends ToolingApiSpecificatio
noExceptionThrown()
}
- def "can overwrite searchUpwards via build arguments"() {
+ def "can configure searchUpwards via build arguments"() {
given:
file('build.gradle') << "assert !gradle.startParameter.searchUpwards"
when:
- toolingApi.withConnector { it.searchUpwards(true) }
withConnection {
it.newBuild().withArguments('-u').run()
}
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r11rc1/DependencyMetaDataCrossVersionSpec.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r11rc1/DependencyMetaDataCrossVersionSpec.groovy
index 997fc35..9997424 100644
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r11rc1/DependencyMetaDataCrossVersionSpec.groovy
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r11rc1/DependencyMetaDataCrossVersionSpec.groovy
@@ -15,16 +15,16 @@
*/
package org.gradle.integtests.tooling.r11rc1
-import org.gradle.integtests.tooling.fixture.MinTargetGradleVersion
-import org.gradle.integtests.tooling.fixture.MinToolingApiVersion
+import org.gradle.integtests.tooling.fixture.TargetGradleVersion
import org.gradle.integtests.tooling.fixture.ToolingApiSpecification
+import org.gradle.integtests.tooling.fixture.ToolingApiVersion
import org.gradle.test.fixtures.maven.MavenFileRepository
import org.gradle.tooling.model.ExternalDependency
import org.gradle.tooling.model.eclipse.EclipseProject
import org.gradle.tooling.model.idea.IdeaProject
- at MinToolingApiVersion('1.1-rc-2')
- at MinTargetGradleVersion('1.1-rc-2')
+ at ToolingApiVersion('>=1.1')
+ at TargetGradleVersion('>=1.1')
class DependencyMetaDataCrossVersionSpec extends ToolingApiSpecification {
def "idea libraries contain gradle module information"() {
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r12rc1/BuildModelCrossVersionSpec.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r12rc1/BuildModelCrossVersionSpec.groovy
index bf87dac..eb314c2 100644
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r12rc1/BuildModelCrossVersionSpec.groovy
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r12rc1/BuildModelCrossVersionSpec.groovy
@@ -16,14 +16,14 @@
package org.gradle.integtests.tooling.r12rc1
-import org.gradle.integtests.tooling.fixture.MinTargetGradleVersion
-import org.gradle.integtests.tooling.fixture.MinToolingApiVersion
+import org.gradle.integtests.tooling.fixture.TargetGradleVersion
+import org.gradle.integtests.tooling.fixture.ToolingApiVersion
import org.gradle.integtests.tooling.fixture.ToolingApiSpecification
import org.gradle.tooling.ProjectConnection
import org.gradle.tooling.model.eclipse.HierarchicalEclipseProject
- at MinToolingApiVersion("1.2-rc-1")
- at MinTargetGradleVersion("1.2-rc-1")
+ at ToolingApiVersion(">=1.2")
+ at TargetGradleVersion(">=1.2")
class BuildModelCrossVersionSpec extends ToolingApiSpecification {
def "can run tasks before building Eclipse model"() {
file('build.gradle').text = '''
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r12rc1/ProjectOutcomesModuleCrossVersionSpec.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r12rc1/ProjectOutcomesModuleCrossVersionSpec.groovy
index bdefe22..86f58a7 100644
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r12rc1/ProjectOutcomesModuleCrossVersionSpec.groovy
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r12rc1/ProjectOutcomesModuleCrossVersionSpec.groovy
@@ -16,14 +16,14 @@
package org.gradle.integtests.tooling.r12rc1
-import org.gradle.integtests.tooling.fixture.MinTargetGradleVersion
-import org.gradle.integtests.tooling.fixture.MinToolingApiVersion
+import org.gradle.integtests.tooling.fixture.TargetGradleVersion
import org.gradle.integtests.tooling.fixture.ToolingApiSpecification
+import org.gradle.integtests.tooling.fixture.ToolingApiVersion
import org.gradle.tooling.ProjectConnection
import org.gradle.tooling.model.internal.outcomes.ProjectOutcomes
- at MinToolingApiVersion("1.2-rc-1")
- at MinTargetGradleVersion("1.2-rc-1")
+ at ToolingApiVersion(">=1.2")
+ at TargetGradleVersion(">=1.2")
class ProjectOutcomesModuleCrossVersionSpec extends ToolingApiSpecification {
def "modelContainsAllArchivesOnTheArchivesConfiguration"() {
given:
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r12rc1/UnsupportedOperationFeedbackCrossVersionSpec.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r12rc1/UnsupportedOperationFeedbackCrossVersionSpec.groovy
index 01dde7b..9c5ed54 100644
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r12rc1/UnsupportedOperationFeedbackCrossVersionSpec.groovy
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r12rc1/UnsupportedOperationFeedbackCrossVersionSpec.groovy
@@ -16,19 +16,19 @@
package org.gradle.integtests.tooling.r12rc1
-import org.gradle.integtests.tooling.fixture.MaxTargetGradleVersion
-import org.gradle.integtests.tooling.fixture.MinToolingApiVersion
+import org.gradle.integtests.tooling.fixture.TargetGradleVersion
import org.gradle.integtests.tooling.fixture.ToolingApiSpecification
+import org.gradle.integtests.tooling.fixture.ToolingApiVersion
import org.gradle.tooling.ProjectConnection
import org.gradle.tooling.exceptions.UnsupportedOperationConfigurationException
import org.gradle.tooling.model.eclipse.EclipseProject
- at MinToolingApiVersion("1.2-rc-1")
- at MaxTargetGradleVersion("1.1")
+ at ToolingApiVersion(">=1.2")
+ at TargetGradleVersion("<=1.1")
class UnsupportedOperationFeedbackCrossVersionSpec extends ToolingApiSpecification {
def "fails when attempting to run tasks when building a model"() {
when:
- maybeFailWithConnection { ProjectConnection connection ->
+ withConnection { ProjectConnection connection ->
connection.model(EclipseProject.class).forTasks('eclipse').get()
}
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r14/ToolingApiInitScriptCrossVersionIntegrationTest.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r14/ToolingApiInitScriptCrossVersionIntegrationTest.groovy
index b72c830..3eb919a 100644
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r14/ToolingApiInitScriptCrossVersionIntegrationTest.groovy
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r14/ToolingApiInitScriptCrossVersionIntegrationTest.groovy
@@ -16,7 +16,7 @@
package org.gradle.integtests.tooling.r14
-import org.gradle.integtests.tooling.fixture.MinTargetGradleVersion
+import org.gradle.integtests.tooling.fixture.TargetGradleVersion
import org.gradle.integtests.tooling.fixture.ToolingApiSpecification
import org.gradle.internal.os.OperatingSystem
import org.gradle.test.fixtures.file.TestFile
@@ -26,7 +26,7 @@ import spock.lang.Issue
/**
* Tests that init scripts are used from the _clients_ GRADLE_HOME, not the daemon server's.
*/
- at MinTargetGradleVersion('1.4')
+ at TargetGradleVersion('>=1.4')
@Issue("http://issues.gradle.org/browse/GRADLE-2408")
class ToolingApiInitScriptCrossVersionIntegrationTest extends ToolingApiSpecification {
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r15/CombiningCommandLineArgumentsCrossVersionSpec.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r15/CombiningCommandLineArgumentsCrossVersionSpec.groovy
index 1abe493..9393c5b 100644
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r15/CombiningCommandLineArgumentsCrossVersionSpec.groovy
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r15/CombiningCommandLineArgumentsCrossVersionSpec.groovy
@@ -20,13 +20,13 @@
package org.gradle.integtests.tooling.r15
-import org.gradle.integtests.tooling.fixture.MinTargetGradleVersion
-import org.gradle.integtests.tooling.fixture.MinToolingApiVersion
+import org.gradle.integtests.tooling.fixture.TargetGradleVersion
+import org.gradle.integtests.tooling.fixture.ToolingApiVersion
import org.gradle.integtests.tooling.fixture.ToolingApiSpecification
import spock.lang.Issue
- at MinToolingApiVersion("1.0")
- at MinTargetGradleVersion("1.5")
+ at ToolingApiVersion(">=1.0")
+ at TargetGradleVersion(">=1.5")
class CombiningCommandLineArgumentsCrossVersionSpec extends ToolingApiSpecification {
@Issue("GRADLE-2635")
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r15/ToolingApiConfigurationOnDemandCrossVersionSpec.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r15/ToolingApiConfigurationOnDemandCrossVersionSpec.groovy
index daaf1e3..661fe84 100644
--- a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r15/ToolingApiConfigurationOnDemandCrossVersionSpec.groovy
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r15/ToolingApiConfigurationOnDemandCrossVersionSpec.groovy
@@ -18,13 +18,13 @@
package org.gradle.integtests.tooling.r15
-import org.gradle.integtests.tooling.fixture.MinTargetGradleVersion
-import org.gradle.integtests.tooling.fixture.MinToolingApiVersion
+import org.gradle.integtests.tooling.fixture.TargetGradleVersion
import org.gradle.integtests.tooling.fixture.ToolingApiSpecification
+import org.gradle.integtests.tooling.fixture.ToolingApiVersion
import org.gradle.tooling.model.GradleProject
- at MinToolingApiVersion("1.0-milestone-5") //because we acquire GradleProject model
- at MinTargetGradleVersion("1.5")
+ at ToolingApiVersion(">=1.0-milestone-5") //because we acquire GradleProject model
+ at TargetGradleVersion(">=1.5")
class ToolingApiConfigurationOnDemandCrossVersionSpec extends ToolingApiSpecification {
def setup() {
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r16/CustomModel.java b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r16/CustomModel.java
new file mode 100644
index 0000000..1c32d4f
--- /dev/null
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r16/CustomModel.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests.tooling.r16;
+
+import java.util.Map;
+import java.util.Set;
+
+public interface CustomModel {
+ String getValue();
+
+ Set<Thing> getThings();
+
+ Map<String, Thing> getThingsByName();
+
+ interface Thing {
+ }
+}
\ No newline at end of file
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r16/CustomToolingModelCrossVersionSpec.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r16/CustomToolingModelCrossVersionSpec.groovy
new file mode 100644
index 0000000..0aa67b2
--- /dev/null
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r16/CustomToolingModelCrossVersionSpec.groovy
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests.tooling.r16
+
+import org.gradle.integtests.tooling.fixture.TargetGradleVersion
+import org.gradle.integtests.tooling.fixture.ToolingApiSpecification
+import org.gradle.integtests.tooling.fixture.ToolingApiVersion
+import spock.lang.Ignore
+
+ at ToolingApiVersion(">=1.6")
+ at TargetGradleVersion(">=1.6")
+class CustomToolingModelCrossVersionSpec extends ToolingApiSpecification {
+ def "plugin can contribute a custom tooling model"() {
+ file('build.gradle') << """
+import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry
+import org.gradle.tooling.provider.model.ToolingModelBuilder
+import javax.inject.Inject
+
+apply plugin: CustomPlugin
+
+class CustomModel implements Serializable {
+ String getValue() { 'greetings' }
+ Set<CustomThing> getThings() { return [new CustomThing()] }
+ Map<String, CustomThing> getThingsByName() { return [thing: new CustomThing()] }
+}
+class CustomThing implements Serializable {
+}
+class CustomBuilder implements ToolingModelBuilder {
+ boolean canBuild(String modelName) {
+ return modelName == '${CustomModel.name}'
+ }
+ Object buildAll(String modelName, Project project) {
+ return new CustomModel()
+ }
+}
+class CustomPlugin implements Plugin<Project> {
+ @Inject
+ CustomPlugin(ToolingModelBuilderRegistry registry) {
+ registry.register(new CustomBuilder())
+ }
+
+ public void apply(Project project) {
+ }
+}
+"""
+
+ when:
+ def model = withConnection { connection ->
+ connection.model(CustomModel).get()
+ }
+
+ then:
+ model.value == 'greetings'
+ model.things.find { it instanceof CustomModel.Thing }
+ model.thingsByName.thing instanceof CustomModel.Thing
+ }
+
+ @Ignore("work in progress")
+ def "gives reasonable error message when model build fails"() {
+ expect: false
+ }
+
+ @Ignore("work in progress")
+ def "gives reasonable error message when model cannot be transported to consumer"() {
+ expect: false
+ }
+}
\ No newline at end of file
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r16/UnknownCustomModelFeedbackCrossVersionSpec.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r16/UnknownCustomModelFeedbackCrossVersionSpec.groovy
new file mode 100644
index 0000000..69c4cc3
--- /dev/null
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r16/UnknownCustomModelFeedbackCrossVersionSpec.groovy
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests.tooling.r16
+
+import org.gradle.integtests.tooling.fixture.TargetGradleVersion
+import org.gradle.integtests.tooling.fixture.ToolingApiSpecification
+import org.gradle.integtests.tooling.fixture.ToolingApiVersion
+import org.gradle.tooling.GradleConnectionException
+import org.gradle.tooling.UnknownModelException
+
+class UnknownCustomModelFeedbackCrossVersionSpec extends ToolingApiSpecification {
+ @ToolingApiVersion("current")
+ @TargetGradleVersion(">=1.6")
+ def "fails gracefully when unknown model requested when custom models are supported by the target version"() {
+ when:
+ withConnection { it.getModel(CustomModel.class) }
+
+ then:
+ UnknownModelException e = thrown()
+ e.message == "No model of type 'CustomModel' is available in this build."
+ }
+
+ @ToolingApiVersion("current")
+ @TargetGradleVersion("<1.6")
+ def "fails gracefully when unknown model requested when custom models are not supported by the target version"() {
+ when:
+ withConnection { it.getModel(CustomModel.class) }
+
+ then:
+ UnknownModelException e = thrown()
+ e.message == "The version of Gradle you are using (${targetDist.version.version}) does not support building a model of type 'CustomModel'. Support for building custom tooling models was added in Gradle 1.6 and is available in all later versions."
+ }
+
+ @ToolingApiVersion("!current")
+ @TargetGradleVersion("current")
+ def "fails gracefully when unknown model requested by old tooling API version"() {
+ when:
+ withConnection { it.getModel(CustomModel.class) }
+
+ then:
+ GradleConnectionException e = thrown()
+ e.message.contains('CustomModel')
+ }
+}
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r18/BrokenAction.java b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r18/BrokenAction.java
new file mode 100644
index 0000000..796d8d3
--- /dev/null
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r18/BrokenAction.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests.tooling.r18;
+
+import org.gradle.tooling.BuildAction;
+import org.gradle.tooling.BuildController;
+
+class BrokenAction implements BuildAction<String> {
+ public String execute(BuildController controller) {
+ throw new CustomException();
+ }
+
+ static class CustomException extends RuntimeException {
+ }
+}
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r18/BuildActionCrossVersionSpec.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r18/BuildActionCrossVersionSpec.groovy
new file mode 100644
index 0000000..7417a13
--- /dev/null
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r18/BuildActionCrossVersionSpec.groovy
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests.tooling.r18
+
+import org.gradle.integtests.tooling.fixture.TargetGradleVersion
+import org.gradle.integtests.tooling.fixture.ToolingApiSpecification
+import org.gradle.integtests.tooling.fixture.ToolingApiVersion
+import org.gradle.tooling.BuildActionFailureException
+import org.gradle.tooling.BuildException
+import org.gradle.tooling.UnsupportedVersionException
+import org.gradle.tooling.model.idea.IdeaProject
+
+ at ToolingApiVersion('>=1.8')
+ at TargetGradleVersion('>=1.8')
+class BuildActionCrossVersionSpec extends ToolingApiSpecification {
+ def "client receives the result of running a build action"() {
+ given:
+ file("settings.gradle") << 'rootProject.name="hello-world"'
+
+ when:
+ CustomModel customModel = withConnection { it.action(new FetchCustomModel()).run() }
+
+ then:
+ customModel.gradle.name == "hello-world"
+ customModel.eclipse.gradleProject.name == "hello-world"
+
+ when:
+ IdeaProject ideaModel = withConnection { it.action(new FetchIdeaModel()).run() }
+
+ then:
+ ideaModel.name == "hello-world"
+ ideaModel.modules.size() == 1
+
+ when:
+ def nullModel = withConnection { it.action(new NullAction()).run() }
+
+ then:
+ nullModel == null
+ }
+
+ def "client receives the exception thrown by the build action"() {
+ when:
+ withConnection { it.action(new BrokenAction()).run() }
+
+ then:
+ BuildActionFailureException e = thrown()
+ e.message == /The supplied build action failed with an exception./
+ e.cause instanceof BrokenAction.CustomException
+ }
+
+ def "client receives the exception thrown when action requests unknown model"() {
+ when:
+ withConnection { it.action(new FetchUnknownModel()).run() }
+
+ then:
+ noExceptionThrown()
+ }
+
+ def "client receives the exception thrown when build fails"() {
+ given:
+ buildFile << 'throw new RuntimeException("broken")'
+
+ when:
+ withConnection { it.action(new FetchCustomModel()).run() }
+
+ then:
+ // TODO:ADAM - clean this up
+ BuildException e = thrown()
+ e.message.startsWith('Could not run build action using')
+ }
+
+ def causes(Throwable throwable) {
+ def causes = []
+ for (def c = throwable.cause; c != null; c = c.cause) {
+ causes << c
+ }
+ return causes
+ }
+
+ @ToolingApiVersion('current')
+ @TargetGradleVersion('<1.8')
+ def "gives reasonable error message when target Gradle version does not support build actions"() {
+ when:
+ withConnection { it.action(new FetchCustomModel()).run() }
+
+ then:
+ UnsupportedVersionException e = thrown()
+ e.message == "The version of Gradle you are using (${targetDist.version.version}) does not support execution of build actions provided by the tooling API client. Support for this was added in Gradle 1.8 and is available in all later versions."
+ }
+}
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r18/BuildScriptModelCrossVersionSpec.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r18/BuildScriptModelCrossVersionSpec.groovy
new file mode 100644
index 0000000..e6efd0f
--- /dev/null
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r18/BuildScriptModelCrossVersionSpec.groovy
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests.tooling.r18
+
+import org.gradle.integtests.tooling.fixture.TargetGradleVersion
+import org.gradle.integtests.tooling.fixture.ToolingApiSpecification
+import org.gradle.integtests.tooling.fixture.ToolingApiVersion
+import org.gradle.tooling.model.GradleProject
+import org.gradle.tooling.model.UnsupportedMethodException
+import org.gradle.tooling.model.eclipse.EclipseProject
+import org.gradle.tooling.model.idea.IdeaProject
+
+ at ToolingApiVersion('>=1.8')
+ at TargetGradleVersion('>=1.8')
+class BuildScriptModelCrossVersionSpec extends ToolingApiSpecification {
+ def "GradleProject provides details about the project's build script"() {
+ when:
+ buildFile << '//empty'
+ GradleProject project = withConnection { it.getModel(GradleProject.class) }
+
+ then:
+ project.buildScript.sourceFile == buildFile
+
+ when:
+ def custom = file('gradle/my-project.gradle') << '//empty'
+ file('settings.gradle') << "rootProject.buildFileName = 'gradle/my-project.gradle'"
+ project = withConnection { it.getModel(GradleProject.class) }
+
+ then:
+ project.buildScript.sourceFile == custom
+ }
+
+ @TargetGradleVersion('<1.8 >=1.0-milestone-5')
+ def "gives reasonable error message when target Gradle version does not provide build script details"() {
+ when:
+ GradleProject project = withConnection { it.getModel(GradleProject.class) }
+ project.buildScript
+
+ then:
+ UnsupportedMethodException e = thrown()
+ e.message.startsWith('Unsupported method: GradleProject.getBuildScript().')
+
+ when:
+ EclipseProject eclipseProject = withConnection { it.getModel(EclipseProject.class) }
+ eclipseProject.gradleProject.buildScript
+
+ then:
+ e = thrown()
+ e.message.startsWith('Unsupported method: GradleProject.getBuildScript().')
+
+ when:
+ IdeaProject ideaProject = withConnection { it.getModel(IdeaProject.class) }
+ ideaProject.modules.each { it.gradleProject.buildScript }
+
+ then:
+ e = thrown()
+ e.message.startsWith('Unsupported method: GradleProject.getBuildScript().')
+ }
+}
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r18/CustomModel.java b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r18/CustomModel.java
new file mode 100644
index 0000000..c14fbd5
--- /dev/null
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r18/CustomModel.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests.tooling.r18;
+
+import org.gradle.tooling.model.GradleProject;
+import org.gradle.tooling.model.eclipse.EclipseProject;
+
+import java.io.Serializable;
+
+class CustomModel implements Serializable {
+ EclipseProject eclipse;
+ GradleProject gradle;
+}
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r18/FetchCustomModel.java b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r18/FetchCustomModel.java
new file mode 100644
index 0000000..93d2189
--- /dev/null
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r18/FetchCustomModel.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests.tooling.r18;
+
+import org.gradle.tooling.BuildAction;
+import org.gradle.tooling.BuildController;
+import org.gradle.tooling.model.GradleProject;
+import org.gradle.tooling.model.eclipse.EclipseProject;
+
+class FetchCustomModel implements BuildAction<CustomModel> {
+ public CustomModel execute(BuildController controller) {
+ CustomModel model = new CustomModel();
+ model.gradle = controller.getModel(GradleProject.class);
+ model.eclipse = controller.getModel(EclipseProject.class);
+ return model;
+ }
+}
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r18/FetchIdeaModel.java b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r18/FetchIdeaModel.java
new file mode 100644
index 0000000..8294742
--- /dev/null
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r18/FetchIdeaModel.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests.tooling.r18;
+
+import org.gradle.tooling.BuildAction;
+import org.gradle.tooling.BuildController;
+import org.gradle.tooling.model.idea.IdeaProject;
+
+public class FetchIdeaModel implements BuildAction<IdeaProject> {
+ public IdeaProject execute(BuildController controller) {
+ return controller.getModel(IdeaProject.class);
+ }
+}
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r18/FetchUnknownModel.java b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r18/FetchUnknownModel.java
new file mode 100644
index 0000000..ff946f0
--- /dev/null
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r18/FetchUnknownModel.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests.tooling.r18;
+
+import org.gradle.tooling.BuildAction;
+import org.gradle.tooling.BuildController;
+import org.gradle.tooling.UnknownModelException;
+
+public class FetchUnknownModel implements BuildAction<CustomModel> {
+ public CustomModel execute(BuildController controller) {
+ try {
+ controller.getModel(CustomModel.class);
+ throw new AssertionError("Expected model request to fail.");
+ } catch (UnknownModelException e) {
+ return null;
+ }
+ }
+}
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r18/GradleBuildModelCrossVersionSpec.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r18/GradleBuildModelCrossVersionSpec.groovy
new file mode 100644
index 0000000..259c9fd
--- /dev/null
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r18/GradleBuildModelCrossVersionSpec.groovy
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests.tooling.r18
+
+import org.gradle.integtests.tooling.fixture.TargetGradleVersion
+import org.gradle.integtests.tooling.fixture.ToolingApiSpecification
+import org.gradle.integtests.tooling.fixture.ToolingApiVersion
+import org.gradle.tooling.model.gradle.GradleBuild
+
+ at ToolingApiVersion(">=1.8")
+class GradleBuildModelCrossVersionSpec extends ToolingApiSpecification {
+ def setup() {
+ file('settings.gradle') << '''
+include 'a'
+include 'b'
+include 'b:c'
+rootProject.name = 'test'
+'''
+ buildFile << """
+allprojects {
+ description = "project \$name"
+ task buildStuff
+}
+"""
+ }
+
+ // TODO:ADAM - make this work for all target versions
+ @TargetGradleVersion(">=1.8")
+ def "can request GradleBuild model"() {
+ when:
+ GradleBuild model = withConnection { connection -> connection.getModel(GradleBuild) }
+
+ then:
+ model.rootProject.name == 'test'
+ model.rootProject.path == ':'
+ model.rootProject.parent == null
+ model.rootProject.projectDirectory == projectDir
+ model.rootProject.children.size() == 2
+ model.rootProject.children.every { it.parent == model.rootProject }
+ model.projects*.name == ['test', 'a', 'b', 'c']
+ model.projects*.path == [':', ':a', ':b', ':b:c']
+ }
+}
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r18/NullAction.java b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r18/NullAction.java
new file mode 100644
index 0000000..edc5ab5
--- /dev/null
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r18/NullAction.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests.tooling.r18;
+
+import org.gradle.tooling.BuildAction;
+import org.gradle.tooling.BuildController;
+
+public class NullAction implements BuildAction<Object> {
+ public Object execute(BuildController controller) {
+ return null;
+ }
+}
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r18/ProjectLevelModelCrossVersionSpec.groovy b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r18/ProjectLevelModelCrossVersionSpec.groovy
new file mode 100644
index 0000000..e65dc47
--- /dev/null
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r18/ProjectLevelModelCrossVersionSpec.groovy
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests.tooling.r18
+
+import org.gradle.integtests.tooling.fixture.TargetGradleVersion
+import org.gradle.integtests.tooling.fixture.ToolingApiSpecification
+import org.gradle.integtests.tooling.fixture.ToolingApiVersion
+import org.gradle.integtests.tooling.r16.CustomModel
+
+ at ToolingApiVersion(">=1.8")
+class ProjectLevelModelCrossVersionSpec extends ToolingApiSpecification {
+ def setup() {
+ file('settings.gradle') << '''
+include 'a'
+include 'b'
+include 'b:c'
+rootProject.name = 'test'
+'''
+ file('b').mkdirs()
+
+ buildFile << """
+allprojects {
+ description = "project \$name"
+ apply plugin: CustomPlugin
+ task buildStuff
+}
+
+import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry
+import org.gradle.tooling.provider.model.ToolingModelBuilder
+import javax.inject.Inject
+
+class CustomModel implements Serializable {
+ String value
+}
+class CustomBuilder implements ToolingModelBuilder {
+ boolean canBuild(String modelName) {
+ return modelName == 'org.gradle.integtests.tooling.r16.CustomModel'
+ }
+ Object buildAll(String modelName, Project project) {
+ return new CustomModel(value: project.path)
+ }
+}
+class CustomPlugin implements Plugin<Project> {
+ @Inject
+ CustomPlugin(ToolingModelBuilderRegistry registry) {
+ registry.register(new CustomBuilder())
+ }
+
+ public void apply(Project project) {
+ }
+}
+"""
+ }
+
+ @TargetGradleVersion(">=1.8")
+ def "can use build model to request models for individual projects"() {
+ when:
+ Map<String, CustomModel> result = withConnection { connection -> connection.action(new UseGradleBuildToFetchProjectModel()).run() }
+
+ then:
+ result != null
+ result.keySet() == ['test', 'a', 'b', 'c'] as Set
+ result.values()*.value as Set == [':', ':a', ':b', ':b:c'] as Set
+
+ when:
+ withConnector { connector ->
+ connector.searchUpwards(true)
+ connector.forProjectDirectory(file("b"))
+ }
+ result = withConnection { connection -> connection.action(new UseGradleBuildToFetchProjectModel()).run() }
+
+ then:
+ result != null
+ result.keySet() == ['test', 'a', 'b', 'c'] as Set
+ result.values()*.value as Set == [':', ':a', ':b', ':b:c'] as Set
+
+ when:
+ file('gradle.properties') << 'org.gradle.configureondemand=true'
+ result = withConnection { connection -> connection.action(new UseGradleBuildToFetchProjectModel()).run() }
+
+ then:
+ result != null
+ result.keySet() == ['test', 'a', 'b', 'c'] as Set
+ result.values()*.value as Set == [':', ':a', ':b', ':b:c'] as Set
+ }
+
+ @TargetGradleVersion(">=1.8")
+ def "can request models using various element types"() {
+ when:
+ Map<String, CustomModel> result = withConnection { connection -> connection.action(new UseOtherTypesToFetchProjectModel()).run() }
+
+ then:
+ result != null
+ result.keySet() == ['test', 'a', 'b', 'c'] as Set
+ result.values()*.value as Set == [':', ':a', ':b', ':b:c'] as Set
+ }
+}
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r18/UseGradleBuildToFetchProjectModel.java b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r18/UseGradleBuildToFetchProjectModel.java
new file mode 100644
index 0000000..b43de3a
--- /dev/null
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r18/UseGradleBuildToFetchProjectModel.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests.tooling.r18;
+
+import org.gradle.integtests.tooling.r16.CustomModel;
+import org.gradle.tooling.BuildAction;
+import org.gradle.tooling.BuildController;
+import org.gradle.tooling.model.gradle.BasicGradleProject;
+import org.gradle.tooling.model.gradle.GradleBuild;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class UseGradleBuildToFetchProjectModel implements BuildAction<Map<String, CustomModel>> {
+ public Map<String, CustomModel> execute(BuildController controller) {
+ GradleBuild gradleBuild = controller.getBuildModel();
+ Map<String, CustomModel> projects = new HashMap<String, CustomModel>();
+ for (BasicGradleProject project : gradleBuild.getProjects()) {
+ projects.put(project.getName(), controller.getModel(project, CustomModel.class));
+ }
+ return projects;
+ }
+}
diff --git a/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r18/UseOtherTypesToFetchProjectModel.java b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r18/UseOtherTypesToFetchProjectModel.java
new file mode 100644
index 0000000..64be729
--- /dev/null
+++ b/subprojects/tooling-api/src/integTest/groovy/org/gradle/integtests/tooling/r18/UseOtherTypesToFetchProjectModel.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests.tooling.r18;
+
+import org.gradle.integtests.tooling.r16.CustomModel;
+import org.gradle.tooling.BuildAction;
+import org.gradle.tooling.BuildController;
+import org.gradle.tooling.model.GradleProject;
+import org.gradle.tooling.model.HierarchicalElement;
+import org.gradle.tooling.model.eclipse.EclipseProject;
+import org.gradle.tooling.model.idea.IdeaModule;
+import org.gradle.tooling.model.idea.IdeaProject;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class UseOtherTypesToFetchProjectModel implements BuildAction<Map<String, CustomModel>> {
+ public Map<String, CustomModel> execute(BuildController controller) {
+ // Use an IdeaModule to reference a project
+ IdeaProject ideaProject = controller.getModel(IdeaProject.class);
+ for (IdeaModule ideaModule : ideaProject.getModules()) {
+ visit(ideaModule, controller, new HashMap<String, CustomModel>());
+ }
+
+ // Use an EclipseProject to reference a project
+ EclipseProject eclipseProject = controller.getModel(EclipseProject.class);
+ visit(eclipseProject, controller, new HashMap<String, CustomModel>());
+
+ // Use a GradleProject to reference a project
+ GradleProject rootProject = controller.getModel(GradleProject.class);
+ Map<String, CustomModel> projects = new HashMap<String, CustomModel>();
+ visit(rootProject, controller, projects);
+ return projects;
+ }
+
+ void visit(HierarchicalElement element, BuildController buildController, Map<String, CustomModel> results) {
+ results.put(element.getName(), buildController.getModel(element, CustomModel.class));
+ for (HierarchicalElement child : element.getChildren()) {
+ visit(child, buildController, results);
+ }
+ }
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/BuildAction.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/BuildAction.java
new file mode 100644
index 0000000..d9f0bbf
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/BuildAction.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling;
+
+import org.gradle.api.Incubating;
+
+import java.io.Serializable;
+
+/**
+ * An action that executes against a Gradle build and produces a result of type {@code T}.
+ *
+ * <p>You can execute a {@code BuildAction} using the {@link ProjectConnection#action(BuildAction)} method.</p>
+ *
+ * @param <T> The type of result produced by this action.
+ * @since 1.8
+ */
+ at Incubating
+public interface BuildAction<T> extends Serializable {
+ /**
+ * Executes this action and returns the result.
+ *
+ * @param controller The controller to use to access and control the build.
+ * @return The result
+ * @since 1.8
+ */
+ T execute(BuildController controller);
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/BuildActionExecuter.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/BuildActionExecuter.java
new file mode 100644
index 0000000..dfd7d5c
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/BuildActionExecuter.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling;
+
+import org.gradle.api.Incubating;
+import org.gradle.tooling.exceptions.UnsupportedBuildArgumentException;
+import org.gradle.tooling.exceptions.UnsupportedOperationConfigurationException;
+
+/**
+ * Used to execute a {@link BuildAction} in the build process.
+ *
+ * @param <T> The type of result produced by this executer.
+ * @since 1.8
+ */
+ at Incubating
+public interface BuildActionExecuter<T> extends LongRunningOperation {
+ /**
+ * Runs the action, blocking until its result is available.
+ *
+ * @throws UnsupportedVersionException When the target Gradle version does not support build action execution.
+ * @throws UnsupportedOperationConfigurationException
+ * When the target Gradle version does not support some requested configuration option such as
+ * {@link #setStandardInput(java.io.InputStream)}, {@link #setJavaHome(java.io.File)},
+ * {@link #setJvmArguments(String...)}.
+ * @throws UnsupportedBuildArgumentException When there is a problem with build arguments provided by {@link #withArguments(String...)}.
+ * @throws BuildActionFailureException When the build action fails with an exception.
+ * @throws BuildException On some failure executing the Gradle build.
+ * @throws GradleConnectionException On some other failure using the connection.
+ * @throws IllegalStateException When the connection has been closed or is closing.
+ * @since 1.8
+ */
+ T run() throws GradleConnectionException, IllegalStateException, UnsupportedOperationConfigurationException, UnsupportedVersionException, UnsupportedBuildArgumentException, BuildException, BuildActionFailureException;
+
+ /**
+ * Starts executing the action, passing the result to the given handler when complete. This method returns immediately, and the result is later passed to the given handler's {@link
+ * ResultHandler#onComplete(Object)} method.
+ *
+ * <p>If the operation fails, the handler's {@link ResultHandler#onFailure(GradleConnectionException)} method is called with the appropriate exception. See
+ * {@link #run()} for a description of the various exceptions that the operation may fail with.
+ *
+ * @param handler The handler to supply the result to.
+ * @throws IllegalStateException When the connection has been closed or is closing.
+ * @since 1.8
+ */
+ void run(ResultHandler<? super T> handler) throws IllegalStateException;
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/BuildActionFailureException.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/BuildActionFailureException.java
new file mode 100644
index 0000000..845e1c5
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/BuildActionFailureException.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling;
+
+import org.gradle.api.Incubating;
+
+/**
+ * Thrown when a {@link BuildAction} fails.
+ *
+ * @since 1.8
+ */
+ at Incubating
+public class BuildActionFailureException extends GradleConnectionException {
+ public BuildActionFailureException(String message, Throwable throwable) {
+ super(message, throwable);
+ }
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/BuildController.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/BuildController.java
new file mode 100644
index 0000000..e4a1d88
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/BuildController.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling;
+
+import org.gradle.api.Incubating;
+import org.gradle.api.Nullable;
+import org.gradle.tooling.model.gradle.GradleBuild;
+import org.gradle.tooling.model.Model;
+
+/**
+ * Provides a {@link BuildAction} various ways to control a Gradle build and access information about the build.
+ *
+ * @since 1.8
+ */
+ at Incubating
+public interface BuildController {
+ /**
+ * Fetches a snapshot of the model of the given type for the default project. The default project is generally the
+ * project referenced when a {@link ProjectConnection} is created.
+ *
+ * <p>Any of following models types may be available, depending on the version of Gradle being used by the target
+ * build:
+ *
+ * <ul>
+ * <li>{@link GradleBuild}</li>
+ * <li>{@link org.gradle.tooling.model.build.BuildEnvironment}</li>
+ * <li>{@link org.gradle.tooling.model.GradleProject}</li>
+ * <li>{@link org.gradle.tooling.model.idea.IdeaProject}</li>
+ * <li>{@link org.gradle.tooling.model.idea.BasicIdeaProject}</li>
+ * <li>{@link org.gradle.tooling.model.eclipse.EclipseProject}</li>
+ * <li>{@link org.gradle.tooling.model.eclipse.HierarchicalEclipseProject}</li>
+ * </ul>
+ *
+ * <p>A build may also expose additional custom tooling models.
+ *
+ * @param modelType The model type.
+ * @param <T> The model type.
+ * @return The model.
+ * @throws UnknownModelException When the default project does not support the requested model.
+ *
+ * @since 1.8
+ */
+ <T> T getModel(Class<T> modelType) throws UnknownModelException;
+
+ /**
+ * Fetches a snapshot of the model of the given type, if available.
+ *
+ * <p>See {@link #getModel(Class)} for more details.</p>
+ *
+ * @param modelType The model type.
+ * @param <T> The model type.
+ * @return The model, or null if not present.
+ */
+ @Nullable
+ <T> T findModel(Class<T> modelType);
+
+ /**
+ * Returns an overview of the Gradle build, including some basic details of the projects that make up the build.
+ * This is equivalent to calling {@code #getModel(GradleBuild)}.
+ *
+ * @return The model.
+ */
+ GradleBuild getBuildModel();
+
+ /**
+ * Fetches a snapshot of the model of the given type for the given element, usually a Gradle project.
+ *
+ * <p>The following elements are supported:
+ *
+ * <ul>
+ * <li>Any {@link org.gradle.tooling.model.gradle.BasicGradleProject}</li>
+ * <li>Any {@link org.gradle.tooling.model.GradleProject}</li>
+ * <li>Any {@link org.gradle.tooling.model.eclipse.EclipseProject}</li>
+ * <li>Any {@link org.gradle.tooling.model.idea.IdeaModule}</li>
+ * </ul>
+ *
+ * <p>See {@link #getModel(Class)} for more details.
+ *
+ * @param target The target element, usually a project.
+ * @param modelType The model type.
+ * @param <T> The model type.
+ * @return The model.
+ * @throws UnknownModelException When the target project does not support the requested model.
+ */
+ <T> T getModel(Model target, Class<T> modelType) throws UnknownModelException;
+
+ /**
+ * Fetches a snapshot of the model of the given type, if available.
+ *
+ * <p>See {@link #getModel(Model, Class)} for more details.</p>
+ *
+ * @param modelType The model type.
+ * @param <T> The model type.
+ * @return The model, or null if not present.
+ */
+ @Nullable
+ <T> T findModel(Model target, Class<T> modelType);
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/BuildException.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/BuildException.java
index 2b912fa..57fcaa7 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/BuildException.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/BuildException.java
@@ -16,7 +16,9 @@
package org.gradle.tooling;
/**
- * Thrown when a Gradle build fails, or when a model cannot be built.
+ * Thrown when a Gradle build fails or when a model cannot be built.
+ *
+ * @since 1.0-milestone-3
*/
public class BuildException extends GradleConnectionException {
public BuildException(String message, Throwable throwable) {
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/BuildLauncher.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/BuildLauncher.java
index 4b73adb..45ef962 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/BuildLauncher.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/BuildLauncher.java
@@ -16,6 +16,7 @@
package org.gradle.tooling;
import org.gradle.tooling.exceptions.UnsupportedBuildArgumentException;
+import org.gradle.tooling.exceptions.UnsupportedOperationConfigurationException;
import org.gradle.tooling.model.Task;
import java.io.File;
@@ -105,7 +106,7 @@ public interface BuildLauncher extends LongRunningOperation {
/**
* {@inheritDoc}
- * @since 1.0-rc-1
+ * @since 1.0
*/
BuildLauncher withArguments(String ... arguments);
@@ -148,23 +149,26 @@ public interface BuildLauncher extends LongRunningOperation {
/**
* Executes the build, blocking until it is complete.
*
- * @throws UnsupportedVersionException When the target Gradle version does not support the features required for this build.
- * @throws org.gradle.tooling.exceptions.UnsupportedOperationConfigurationException
- * when you have configured the long running operation with a settings
- * like: {@link #setStandardInput(java.io.InputStream)}, {@link #setJavaHome(java.io.File)},
- * {@link #setJvmArguments(String...)} but those settings are not supported on the target Gradle.
+ * @throws UnsupportedVersionException When the target Gradle version does not support build execution.
+ * @throws UnsupportedOperationConfigurationException
+ * When the target Gradle version does not support some requested configuration option such as
+ * {@link #setStandardInput(java.io.InputStream)}, {@link #setJavaHome(java.io.File)},
+ * {@link #setJvmArguments(String...)}.
+ * @throws UnsupportedBuildArgumentException When there is a problem with build arguments provided by {@link #withArguments(String...)}.
* @throws BuildException On some failure executing the Gradle build.
* @throws GradleConnectionException On some other failure using the connection.
- * @throws UnsupportedBuildArgumentException When there is a problem with build arguments provided by {@link #withArguments(String...)}
* @throws IllegalStateException When the connection has been closed or is closing.
* @since 1.0-milestone-3
*/
void run() throws GradleConnectionException, UnsupportedBuildArgumentException, IllegalStateException,
- BuildException, UnsupportedVersionException;
+ BuildException, UnsupportedVersionException, UnsupportedOperationConfigurationException;
/**
* Launches the build. This method returns immediately, and the result is later passed to the given handler.
*
+ * <p>If the operation fails, the handler's {@link ResultHandler#onFailure(GradleConnectionException)}
+ * method is called with the appropriate exception. See {@link #run()} for a description of the various exceptions that the operation may fail with.
+ *
* @param handler The handler to supply the result to.
* @throws IllegalStateException When the connection has been closed or is closing.
* @since 1.0-milestone-3
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/GradleConnectionException.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/GradleConnectionException.java
index a9ffbe5..6e6c55d 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/GradleConnectionException.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/GradleConnectionException.java
@@ -17,6 +17,8 @@ package org.gradle.tooling;
/**
* Thrown when there is some problem using a Gradle connection.
+ *
+ * @since 1.0-milestone-3
*/
public class GradleConnectionException extends RuntimeException {
public GradleConnectionException(String message) {
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/LongRunningOperation.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/LongRunningOperation.java
index 856f2dd..7866b8a 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/LongRunningOperation.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/LongRunningOperation.java
@@ -29,9 +29,10 @@ import java.io.OutputStream;
* <p>
* Allows providing standard input that can be consumed by the gradle operation (useful for interactive builds).
* <p>
- * Enables configuring the build run / model request with options like the Java home or jvm arguments.
+ * Enables configuring the build run / model request with options like the Java home or JVM arguments.
* Those settings might not be supported by the target Gradle version. Refer to Javadoc for those methods
* to understand what kind of exception throw and when is it thrown.
+ *
* @since 1.0-milestone-7
*/
public interface LongRunningOperation {
@@ -40,7 +41,7 @@ public interface LongRunningOperation {
* Sets the {@link java.io.OutputStream} which should receive standard output logging generated while running the operation.
* The default is to discard the output.
*
- * @param outputStream The output stream.
+ * @param outputStream The output stream. The system default character encoding will be used to encode characters written to this stream.
* @return this
* @since 1.0-milestone-7
*/
@@ -50,31 +51,27 @@ public interface LongRunningOperation {
* Sets the {@link OutputStream} which should receive standard error logging generated while running the operation.
* The default is to discard the output.
*
- * @param outputStream The output stream.
+ * @param outputStream The output stream. The system default character encoding will be used to encode characters written to this stream.
* @return this
* @since 1.0-milestone-7
*/
LongRunningOperation setStandardError(OutputStream outputStream);
/**
- * If the target Gradle version supports it you can use this setting
- * to set the standard {@link java.io.InputStream} that will be used by builds.
- * Useful when the tooling api drives interactive builds.
+ * Sets the {@link java.io.InputStream} that will be used as standard input for this operation.
+ * Defaults to an empty input stream.
* <p>
- * If the target Gradle version does not support it the long running operation will fail eagerly with
+ * If the target Gradle version does not support it the long running operation will fail with
* {@link org.gradle.tooling.exceptions.UnsupportedOperationConfigurationException} when the operation is started.
- * <p>
- * If not configured or null passed the dummy input stream with zero bytes is used to avoid the build hanging problems.
*
* @param inputStream The input stream
* @return this
- * @since 1.0-milestone-7
+ * @since 1.0-milestone-8
*/
LongRunningOperation setStandardInput(InputStream inputStream);
/**
- * If the target Gradle version supports it you can use this setting
- * to specify the Java home directory to use for the long running operation.
+ * Specifies the Java home directory to use for this operation.
* <p>
* If the target Gradle version does not support it the long running operation will fail eagerly with
* {@link org.gradle.tooling.exceptions.UnsupportedOperationConfigurationException} when the operation is started.
@@ -92,8 +89,7 @@ public interface LongRunningOperation {
LongRunningOperation setJavaHome(File javaHome) throws IllegalArgumentException;
/**
- * If the target Gradle version supports it you can use this setting
- * to specify the Java vm arguments to use for the long running operation.
+ * Specifies the Java VM arguments to use for this operation.
* <p>
* If the target Gradle version does not support it the long running operation will fail eagerly with
* {@link org.gradle.tooling.exceptions.UnsupportedOperationConfigurationException} when the operation is started.
@@ -136,7 +132,7 @@ public interface LongRunningOperation {
*
* @param arguments Gradle command line arguments
* @return this
- * @since 1.0-rc-1
+ * @since 1.0
*/
LongRunningOperation withArguments(String ... arguments);
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/ModelBuilder.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/ModelBuilder.java
index 942d571..8fefd0c 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/ModelBuilder.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/ModelBuilder.java
@@ -16,7 +16,8 @@
package org.gradle.tooling;
import org.gradle.api.Incubating;
-import org.gradle.tooling.model.Model;
+import org.gradle.tooling.exceptions.UnsupportedBuildArgumentException;
+import org.gradle.tooling.exceptions.UnsupportedOperationConfigurationException;
import java.io.File;
import java.io.InputStream;
@@ -67,11 +68,11 @@ import java.io.OutputStream;
* @param <T> The type of model to build
* @since 1.0-milestone-3
*/
-public interface ModelBuilder<T extends Model> extends LongRunningOperation {
+public interface ModelBuilder<T> extends LongRunningOperation {
/**
* {@inheritDoc}
- * @since 1.0-rc-1
+ * @since 1.0
*/
ModelBuilder<T> withArguments(String ... arguments);
@@ -126,20 +127,26 @@ public interface ModelBuilder<T extends Model> extends LongRunningOperation {
* Fetch the model, blocking until it is available.
*
* @return The model.
- * @throws UnsupportedVersionException When the target Gradle version does not support the features required to build this model.
- * @throws org.gradle.tooling.exceptions.UnsupportedOperationConfigurationException
- * when you have configured the long running operation with a settings
- * like: {@link #setStandardInput(java.io.InputStream)}, {@link #setJavaHome(java.io.File)},
- * {@link #setJvmArguments(String...)} but those settings are not supported on the target Gradle.
+ * @throws UnsupportedVersionException When the target Gradle version does not support building models.
+ * @throws UnknownModelException When the target Gradle version or build does not support the requested model.
+ * @throws UnsupportedOperationConfigurationException
+ * When the target Gradle version does not support some requested configuration option such as
+ * {@link #setStandardInput(java.io.InputStream)}, {@link #setJavaHome(java.io.File)},
+ * {@link #setJvmArguments(String...)}.
+ * @throws UnsupportedBuildArgumentException When there is a problem with build arguments provided by {@link #withArguments(String...)}.
* @throws BuildException On some failure executing the Gradle build.
* @throws GradleConnectionException On some other failure using the connection.
* @throws IllegalStateException When the connection has been closed or is closing.
* @since 1.0-milestone-3
*/
- T get() throws GradleConnectionException;
+ T get() throws GradleConnectionException, UnsupportedVersionException, UnknownModelException, UnsupportedOperationConfigurationException, BuildException, IllegalStateException, UnsupportedBuildArgumentException;
/**
- * Starts fetching the build. This method returns immediately, and the result is later passed to the given handler.
+ * Starts fetching the model, passing the result to the given handler when complete. This method returns immediately, and the result is later passed to the given
+ * handler's {@link ResultHandler#onComplete(Object)} method.
+ *
+ * <p>If the operation fails, the handler's {@link ResultHandler#onFailure(GradleConnectionException)}
+ * method is called with the appropriate exception. See {@link #get()} for a description of the various exceptions that the operation may fail with.
*
* @param handler The handler to supply the result to.
* @throws IllegalStateException When the connection has been closed or is closing.
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/ProjectConnection.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/ProjectConnection.java
index f4e125f..2b0cf27 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/ProjectConnection.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/ProjectConnection.java
@@ -15,7 +15,7 @@
*/
package org.gradle.tooling;
-import org.gradle.tooling.model.Model;
+import org.gradle.api.Incubating;
/**
* Represents a long-lived connection to a Gradle project. You obtain an instance of a {@code ProjectConnection} by using {@link org.gradle.tooling.GradleConnector#connect()}.
@@ -50,36 +50,38 @@ import org.gradle.tooling.model.Model;
*/
public interface ProjectConnection {
/**
- * Fetches a snapshot of the model of the given type for this project.
+ * Fetches a snapshot of the model of the given type for this project. This method blocks until the model is available.
*
- * <p>This method blocks until the model is available.
+ * <p>This method is simply a convenience for calling {@code model(modelType).get()}</p>
*
- * @param viewType The model type.
+ * @param modelType The model type.
* @param <T> The model type.
* @return The model.
* @throws UnsupportedVersionException When the target Gradle version does not support the given model.
- * @throws UnknownModelException When you are building a model unknown to the Tooling API,
- * for example you attempt to build a model of a type does not come from the Tooling API.
+ * @throws UnknownModelException When the target Gradle version or build does not support the requested model.
* @throws BuildException On some failure executing the Gradle build, in order to build the model.
* @throws GradleConnectionException On some other failure using the connection.
* @throws IllegalStateException When this connection has been closed or is closing.
* @since 1.0-milestone-3
*/
- <T extends Model> T getModel(Class<T> viewType) throws UnsupportedVersionException,
- UnknownModelException, BuildException, GradleConnectionException, IllegalStateException;
+ <T> T getModel(Class<T> modelType) throws GradleConnectionException, IllegalStateException;
/**
- * Fetches a snapshot of the model for this project asynchronously. This method return immediately, and the result of the operation is passed to the supplied result handler.
+ * Starts fetching a snapshot of the given model, passing the result to the given handler when complete. This method returns immediately, and the result is later
+ * passed to the given handler's {@link ResultHandler#onComplete(Object)} method.
*
- * @param viewType The model type.
+ * <p>If the operation fails, the handler's {@link ResultHandler#onFailure(GradleConnectionException)} method is called with the appropriate exception.
+ * See {@link #getModel(Class)} for a description of the various exceptions that the operation may fail with.
+ *
+ * <p>This method is simply a convenience for calling {@code model(modelType).get(handler)}</p>
+ *
+ * @param modelType The model type.
* @param handler The handler to pass the result to.
* @param <T> The model type.
* @throws IllegalStateException When this connection has been closed or is closing.
- * @throws UnknownModelException When you are building a model unknown to the Tooling API,
- * for example you attempt to build a model of a type does not come from the Tooling API.
* @since 1.0-milestone-3
*/
- <T extends Model> void getModel(Class<T> viewType, ResultHandler<? super T> handler) throws IllegalStateException, UnknownModelException;
+ <T> void getModel(Class<T> modelType, ResultHandler<? super T> handler) throws IllegalStateException;
/**
* Creates a launcher which can be used to execute a build.
@@ -92,14 +94,39 @@ public interface ProjectConnection {
/**
* Creates a builder which can be used to build the model of the given type.
*
+ * <p>Any of following models types may be available, depending on the version of Gradle being used by the target
+ * build:
+ *
+ * <ul>
+ * <li>{@link org.gradle.tooling.model.gradle.GradleBuild}</li>
+ * <li>{@link org.gradle.tooling.model.build.BuildEnvironment}</li>
+ * <li>{@link org.gradle.tooling.model.GradleProject}</li>
+ * <li>{@link org.gradle.tooling.model.idea.IdeaProject}</li>
+ * <li>{@link org.gradle.tooling.model.idea.BasicIdeaProject}</li>
+ * <li>{@link org.gradle.tooling.model.eclipse.EclipseProject}</li>
+ * <li>{@link org.gradle.tooling.model.eclipse.HierarchicalEclipseProject}</li>
+ * </ul>
+ *
+ * <p>A build may also expose additional custom tooling models.
+ *
* @param modelType The model type
* @param <T> The model type.
* @return The builder.
- * @throws UnknownModelException When you are building a model unknown to the Tooling API,
- * for example you attempt to build a model of a type does not come from the Tooling API.
* @since 1.0-milestone-3
*/
- <T extends Model> ModelBuilder<T> model(Class<T> modelType) throws UnknownModelException;
+ <T> ModelBuilder<T> model(Class<T> modelType);
+
+ /**
+ * Creates an executer which can be used to run the given action. The action is serialized into the build
+ * process and executed, then its result is serialized back to the caller.
+ *
+ * @param buildAction The action to run.
+ * @param <T> The result type.
+ * @return The builder.
+ * @since 1.8
+ */
+ @Incubating
+ <T> BuildActionExecuter<T> action(BuildAction<T> buildAction);
/**
* Closes this connection. Blocks until any pending operations are complete. Once this method has returned, no more notifications will be delivered by any threads.
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/UnknownModelException.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/UnknownModelException.java
index 7739fb3..e6857b3 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/UnknownModelException.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/UnknownModelException.java
@@ -28,4 +28,8 @@ public class UnknownModelException extends UnsupportedVersionException {
public UnknownModelException(String message) {
super(message);
}
+
+ public UnknownModelException(String message, Throwable cause) {
+ super(message, cause);
+ }
}
\ No newline at end of file
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/UnsupportedVersionException.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/UnsupportedVersionException.java
index 069fa5c..e1d4984 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/UnsupportedVersionException.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/UnsupportedVersionException.java
@@ -17,6 +17,8 @@ package org.gradle.tooling;
/**
* Thrown when the target Gradle version does not support a particular feature.
+ *
+ * @since 1.0-milestone-3
*/
public class UnsupportedVersionException extends GradleConnectionException {
public UnsupportedVersionException(String message) {
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/exceptions/UnsupportedBuildArgumentException.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/exceptions/UnsupportedBuildArgumentException.java
index 007934d..5e85ddd 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/exceptions/UnsupportedBuildArgumentException.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/exceptions/UnsupportedBuildArgumentException.java
@@ -19,9 +19,9 @@ package org.gradle.tooling.exceptions;
import org.gradle.tooling.GradleConnectionException;
/**
- * Thrown when the {@link org.gradle.tooling.BuildLauncher} has been configured
- * with unsupported build arguments. For more information see docs for
- * {@link org.gradle.tooling.BuildLauncher#withArguments(String...)} method.
+ * Thrown when the {@link org.gradle.tooling.LongRunningOperation} has been configured
+ * with unsupported build arguments. For more information see the
+ * {@link org.gradle.tooling.LongRunningOperation#withArguments(String...)} method.
*/
public class UnsupportedBuildArgumentException extends GradleConnectionException {
public UnsupportedBuildArgumentException(String message) {
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/adapter/CollectionMapper.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/adapter/CollectionMapper.java
new file mode 100644
index 0000000..d488eef
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/adapter/CollectionMapper.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.adapter;
+
+import org.gradle.tooling.model.DomainObjectSet;
+
+import java.io.Serializable;
+import java.util.*;
+
+public class CollectionMapper implements Serializable {
+ Collection<Object> createEmptyCollection(Class<?> collectionType) {
+ if (collectionType.equals(DomainObjectSet.class)) {
+ return new ArrayList<Object>();
+ }
+ if (collectionType.isAssignableFrom(ArrayList.class)) {
+ return new ArrayList<Object>();
+ }
+ if (collectionType.isAssignableFrom(LinkedHashSet.class)) {
+ return new LinkedHashSet<Object>();
+ }
+ if (collectionType.isAssignableFrom(TreeSet.class)) {
+ return new TreeSet<Object>();
+ }
+ throw new UnsupportedOperationException(String.format("Cannot convert a Collection to type %s.", collectionType.getName()));
+ }
+
+ Map<Object, Object> createEmptyMap(Class<?> mapType) {
+ if (mapType.isAssignableFrom(LinkedHashMap.class)) {
+ return new LinkedHashMap<Object, Object>();
+ }
+ if (mapType.isAssignableFrom(TreeMap.class)) {
+ return new TreeMap<Object, Object>();
+ }
+ throw new UnsupportedOperationException(String.format("Cannot convert a Map to type %s.", mapType.getName()));
+ }
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/adapter/CompatibleIntrospector.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/adapter/CompatibleIntrospector.java
new file mode 100644
index 0000000..abeb726
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/adapter/CompatibleIntrospector.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.adapter;
+
+import org.gradle.internal.UncheckedException;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * Uses reflection to find out / call methods.
+ */
+public class CompatibleIntrospector {
+
+ private final Object target;
+
+ public CompatibleIntrospector(Object target) {
+ this.target = target;
+ }
+
+ private Method getMethod(String methodName) throws NoSuchMethodException {
+ Method[] methods = target.getClass().getDeclaredMethods();
+ for (Method m : methods) {
+ if (m.getName().equals(methodName)) {
+ return m;
+ }
+ }
+ throw new NoSuchMethodException("No such method: '" + methodName + "' on type: '" + target.getClass().getSimpleName() + "'.");
+ }
+
+ public <T> T getSafely(T defaultValue, String methodName) {
+ try {
+ Method method = getMethod(methodName);
+ method.setAccessible(true);
+ return (T) method.invoke(target);
+ } catch (NoSuchMethodException e) {
+ return defaultValue;
+ } catch (InvocationTargetException e) {
+ throw UncheckedException.throwAsUncheckedException(e.getCause());
+ } catch (Exception e) {
+ throw new RuntimeException("Unable to get value reflectively", e);
+ }
+ }
+
+ public void callSafely(String methodName, Object ... params) {
+ Method method;
+ try {
+ method = getMethod(methodName);
+ } catch (NoSuchMethodException e) {
+ return; // ignore
+ }
+
+ method.setAccessible(true);
+ try {
+ method.invoke(target, params);
+ } catch (InvocationTargetException e) {
+ throw UncheckedException.throwAsUncheckedException(e.getCause());
+ } catch (Exception e) {
+ throw new RuntimeException("Unable to call method reflectively", e);
+ }
+ }
+}
\ No newline at end of file
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/adapter/MethodInvocation.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/adapter/MethodInvocation.java
new file mode 100644
index 0000000..c3c201d
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/adapter/MethodInvocation.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.adapter;
+
+import java.lang.reflect.Type;
+
+public class MethodInvocation {
+ private final Object[] parameters;
+ private final Class returnType;
+ private final Type genericReturnType;
+ private final String name;
+ private final Class<?>[] parameterTypes;
+ private Object result;
+ private boolean found;
+ private Object delegate;
+
+ MethodInvocation(String name, Class returnType, Type genericReturnType, Class<?>[] parameterTypes, Object delegate, Object[] parameters) {
+ this.name = name;
+ this.returnType = returnType;
+ this.genericReturnType = genericReturnType;
+ this.parameterTypes = parameterTypes;
+ this.delegate = delegate;
+ this.parameters = parameters;
+ }
+
+ public Object[] getParameters() {
+ return parameters;
+ }
+
+ public Class getReturnType() {
+ return returnType;
+ }
+
+ public Type getGenericReturnType() {
+ return genericReturnType;
+ }
+
+ /**
+ * Marks the method as handled.
+ */
+ public void setResult(Object result) {
+ found = true;
+ this.result = result;
+ }
+
+ public Object getResult() {
+ return result;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Class<?>[] getParameterTypes() {
+ return parameterTypes;
+ }
+
+ public boolean found() {
+ return found;
+ }
+
+ public Object getDelegate() {
+ return delegate;
+ }
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/adapter/MethodInvoker.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/adapter/MethodInvoker.java
new file mode 100644
index 0000000..8387f5e
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/adapter/MethodInvoker.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.adapter;
+
+public interface MethodInvoker {
+ void invoke(MethodInvocation invocation) throws Throwable;
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/adapter/NoOpMethodInvoker.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/adapter/NoOpMethodInvoker.java
new file mode 100644
index 0000000..2bb45d9
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/adapter/NoOpMethodInvoker.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.adapter;
+
+import java.io.Serializable;
+
+public class NoOpMethodInvoker implements MethodInvoker, Serializable {
+ public void invoke(MethodInvocation invocation) throws Throwable {
+ }
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/adapter/ProtocolToModelAdapter.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/adapter/ProtocolToModelAdapter.java
new file mode 100644
index 0000000..17d7b47
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/adapter/ProtocolToModelAdapter.java
@@ -0,0 +1,489 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.adapter;
+
+import org.gradle.api.Action;
+import org.gradle.internal.UncheckedException;
+import org.gradle.internal.reflect.DirectInstantiator;
+import org.gradle.tooling.model.DomainObjectSet;
+import org.gradle.tooling.model.internal.Exceptions;
+import org.gradle.tooling.model.internal.ImmutableDomainObjectSet;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Adapts some source object to some target view type.
+ */
+public class ProtocolToModelAdapter implements Serializable {
+ private static final MethodInvoker NO_OP_HANDLER = new NoOpMethodInvoker();
+ private static final Action<SourceObjectMapping> NO_OP_MAPPER = new NoOpMapping();
+ private static final TargetTypeProvider IDENTITY_TYPE_PROVIDER = new TargetTypeProvider() {
+ public <T> Class<? extends T> getTargetType(Class<T> initialTargetType, Object protocolObject) {
+ return initialTargetType;
+ }
+ };
+ private static final Object[] EMPTY = new Object[0];
+ private static final Pattern IS_SUPPORT_METHOD = Pattern.compile("is(\\w+)Supported");
+ private static final Pattern GETTER_METHOD = Pattern.compile("get(\\w+)");
+ private static final Pattern IS_METHOD = Pattern.compile("is(\\w+)");
+ private final TargetTypeProvider targetTypeProvider;
+ private final CollectionMapper collectionMapper = new CollectionMapper();
+
+ public ProtocolToModelAdapter() {
+ this(IDENTITY_TYPE_PROVIDER);
+ }
+
+ public ProtocolToModelAdapter(TargetTypeProvider targetTypeProvider) {
+ this.targetTypeProvider = targetTypeProvider;
+ }
+
+ /**
+ * Adapts the source object to a view object.
+ */
+ public <T, S> T adapt(Class<T> targetType, S sourceObject) {
+ return adapt(targetType, sourceObject, NO_OP_MAPPER);
+ }
+
+ /**
+ * Adapts the source object to a view object.
+ *
+ * @param mixInClass A bean that provides implementations for methods of the target type. If this bean implements the given method, it is preferred over the source object's implementation.
+ */
+ public <T, S> T adapt(Class<T> targetType, final S sourceObject, final Class<?> mixInClass) {
+ return adapt(targetType, sourceObject, new Action<SourceObjectMapping>() {
+ public void execute(SourceObjectMapping mapping) {
+ if (mapping.getSourceObject() == sourceObject) {
+ mapping.mixIn(mixInClass);
+ }
+ }
+ });
+ }
+
+ /**
+ * Adapts the source object to a view object.
+ *
+ * @param mapper An action that is invoked for each source object in the graph that is to be adapted. The action can influence how the source object is adapted via the provided
+ * {@link SourceObjectMapping}.
+ */
+ public <T, S> T adapt(Class<T> targetType, S sourceObject, Action<? super SourceObjectMapping> mapper) {
+ if (sourceObject == null) {
+ return null;
+ }
+ Class<? extends T> wrapperType = targetTypeProvider.getTargetType(targetType, sourceObject);
+ DefaultSourceObjectMapping mapping = new DefaultSourceObjectMapping(sourceObject, targetType, wrapperType);
+ mapper.execute(mapping);
+ wrapperType = mapping.wrapperType.asSubclass(targetType);
+ if (wrapperType.isInstance(sourceObject)) {
+ return wrapperType.cast(sourceObject);
+ }
+ MethodInvoker overrideMethodInvoker = mapping.overrideInvoker;
+ MixInMethodInvoker mixInMethodInvoker = null;
+ if (mapping.mixInType != null) {
+ mixInMethodInvoker = new MixInMethodInvoker(mapping.mixInType, new ReflectionMethodInvoker(mapper));
+ overrideMethodInvoker = mixInMethodInvoker;
+ }
+ Object proxy = Proxy.newProxyInstance(wrapperType.getClassLoader(), new Class<?>[]{wrapperType}, new InvocationHandlerImpl(sourceObject, overrideMethodInvoker, mapper));
+ if (mixInMethodInvoker != null) {
+ mixInMethodInvoker.setProxy(proxy);
+ }
+ return wrapperType.cast(proxy);
+ }
+
+ /**
+ * Unpacks the source object from a given view object.
+ */
+ public Object unpack(Object viewObject) {
+ if (!Proxy.isProxyClass(viewObject.getClass()) || !(Proxy.getInvocationHandler(viewObject) instanceof InvocationHandlerImpl)) {
+ throw new IllegalArgumentException("The given object is not a view object");
+ }
+ InvocationHandlerImpl handler = (InvocationHandlerImpl) Proxy.getInvocationHandler(viewObject);
+ return handler.delegate;
+ }
+
+ private static class DefaultSourceObjectMapping implements SourceObjectMapping {
+ private final Object protocolObject;
+ private final Class<?> targetType;
+ private Class<?> wrapperType;
+ private Class<?> mixInType;
+ private MethodInvoker overrideInvoker = NO_OP_HANDLER;
+
+ public DefaultSourceObjectMapping(Object protocolObject, Class<?> targetType, Class<?> wrapperType) {
+ this.protocolObject = protocolObject;
+ this.targetType = targetType;
+ this.wrapperType = wrapperType;
+ }
+
+ public Object getSourceObject() {
+ return protocolObject;
+ }
+
+ public Class<?> getTargetType() {
+ return targetType;
+ }
+
+ public void mapToType(Class<?> type) {
+ if (!targetType.isAssignableFrom(type)) {
+ throw new IllegalArgumentException(String.format("requested wrapper type '%s' is not assignable to target type '%s'.", type.getSimpleName(), targetType.getSimpleName()));
+ }
+ wrapperType = type;
+ }
+
+ public void mixIn(Class<?> mixInBeanType) {
+ if (mixInType != null) {
+ throw new UnsupportedOperationException("Mixing in multiple beans is currently not supported.");
+ }
+ mixInType = mixInBeanType;
+ }
+
+ public void mixIn(MethodInvoker invoker) {
+ if (overrideInvoker != NO_OP_HANDLER) {
+ throw new UnsupportedOperationException("Mixing in multiple invokers is currently not supported.");
+ }
+ overrideInvoker = invoker;
+ }
+ }
+
+ private static class NoOpMapping implements Action<SourceObjectMapping>, Serializable {
+ public void execute(SourceObjectMapping mapping) {
+ }
+ }
+
+ private class InvocationHandlerImpl implements InvocationHandler, Serializable {
+ private final Object delegate;
+ private final MethodInvoker overrideMethodInvoker;
+ private final Action<? super SourceObjectMapping> mapper;
+ private transient Method equalsMethod;
+ private transient Method hashCodeMethod;
+ private transient MethodInvoker invoker;
+
+ public InvocationHandlerImpl(Object delegate, MethodInvoker overrideMethodInvoker, Action<? super SourceObjectMapping> mapper) {
+ this.delegate = delegate;
+ this.overrideMethodInvoker = overrideMethodInvoker;
+ this.mapper = mapper;
+ setup();
+ }
+
+ private void readObject(java.io.ObjectInputStream in)
+ throws IOException, ClassNotFoundException {
+ in.defaultReadObject();
+ setup();
+ }
+
+ private void setup() {
+ invoker = new SupportedPropertyInvoker(
+ new SafeMethodInvoker(
+ new PropertyCachingMethodInvoker(
+ new ChainedMethodInvoker(
+ overrideMethodInvoker,
+ new ReflectionMethodInvoker(mapper)))));
+ try {
+ equalsMethod = Object.class.getMethod("equals", Object.class);
+ hashCodeMethod = Object.class.getMethod("hashCode");
+ } catch (NoSuchMethodException e) {
+ throw UncheckedException.throwAsUncheckedException(e);
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (o == null || o.getClass() != getClass()) {
+ return false;
+ }
+
+ InvocationHandlerImpl other = (InvocationHandlerImpl) o;
+ return delegate.equals(other.delegate);
+ }
+
+ @Override
+ public int hashCode() {
+ return delegate.hashCode();
+ }
+
+ public Object invoke(Object target, Method method, Object[] params) throws Throwable {
+ if (method.equals(equalsMethod)) {
+ Object param = params[0];
+ if (param == null || !Proxy.isProxyClass(param.getClass())) {
+ return false;
+ }
+ InvocationHandler other = Proxy.getInvocationHandler(param);
+ return equals(other);
+ } else if (method.equals(hashCodeMethod)) {
+ return hashCode();
+ }
+
+ MethodInvocation invocation = new MethodInvocation(method.getName(), method.getReturnType(), method.getGenericReturnType(), method.getParameterTypes(), delegate, params);
+ invoker.invoke(invocation);
+ if (!invocation.found()) {
+ String methodName = method.getDeclaringClass().getSimpleName() + "." + method.getName() + "()";
+ throw Exceptions.unsupportedMethod(methodName);
+ }
+ return invocation.getResult();
+ }
+ }
+
+ private static class ChainedMethodInvoker implements MethodInvoker {
+ private final MethodInvoker[] invokers;
+
+ private ChainedMethodInvoker(MethodInvoker... invokers) {
+ this.invokers = invokers;
+ }
+
+ public void invoke(MethodInvocation method) throws Throwable {
+ for (int i = 0; !method.found() && i < invokers.length; i++) {
+ MethodInvoker invoker = invokers[i];
+ invoker.invoke(method);
+ }
+ }
+ }
+
+ private class ReflectionMethodInvoker implements MethodInvoker {
+ private final Action<? super SourceObjectMapping> mapping;
+
+ private ReflectionMethodInvoker(Action<? super SourceObjectMapping> mapping) {
+ this.mapping = mapping;
+ }
+
+ public void invoke(MethodInvocation invocation) throws Throwable {
+ // TODO - cache method lookup
+ Method targetMethod = locateMethod(invocation);
+ if (targetMethod == null) {
+ return;
+ }
+
+ Object returnValue;
+ try {
+ returnValue = targetMethod.invoke(invocation.getDelegate(), invocation.getParameters());
+ } catch (InvocationTargetException e) {
+ throw e.getCause();
+ }
+
+ if (returnValue == null) {
+ invocation.setResult(returnValue);
+ return;
+ }
+
+ invocation.setResult(convert(returnValue, invocation.getGenericReturnType()));
+ }
+
+ private Method locateMethod(MethodInvocation invocation) {
+ Class<?> sourceClass = invocation.getDelegate().getClass();
+ Method match;
+ try {
+ match = sourceClass.getMethod(invocation.getName(), invocation.getParameterTypes());
+ } catch (NoSuchMethodException e) {
+ return null;
+ }
+
+ LinkedList<Class<?>> queue = new LinkedList<Class<?>>();
+ queue.add(sourceClass);
+ while (!queue.isEmpty()) {
+ Class<?> c = queue.removeFirst();
+ try {
+ match = c.getMethod(invocation.getName(), invocation.getParameterTypes());
+ } catch (NoSuchMethodException e) {
+ // ignore
+ }
+ for (Class<?> interfaceType : c.getInterfaces()) {
+ queue.addFirst(interfaceType);
+ }
+ if (c.getSuperclass() != null) {
+ queue.addFirst(c.getSuperclass());
+ }
+ }
+ match.setAccessible(true);
+ return match;
+ }
+
+ private Object convert(Object value, Type targetType) {
+ if (targetType instanceof ParameterizedType) {
+ ParameterizedType parameterizedTargetType = (ParameterizedType) targetType;
+ if (parameterizedTargetType.getRawType() instanceof Class) {
+ Class<?> rawClass = (Class<?>) parameterizedTargetType.getRawType();
+ if (Iterable.class.isAssignableFrom(rawClass)) {
+ Type targetElementType = getElementType(parameterizedTargetType, 0);
+ Collection<Object> convertedElements = collectionMapper.createEmptyCollection(rawClass);
+ for (Object element : (Iterable<?>) value) {
+ convertedElements.add(convert(element, targetElementType));
+ }
+ if (rawClass.equals(DomainObjectSet.class)) {
+ return new ImmutableDomainObjectSet(convertedElements);
+ } else {
+ return convertedElements;
+ }
+ }
+ if (Map.class.isAssignableFrom(rawClass)) {
+ Type targetKeyType = getElementType(parameterizedTargetType, 0);
+ Type targetValueType = getElementType(parameterizedTargetType, 1);
+ Map<Object, Object> convertedElements = collectionMapper.createEmptyMap(rawClass);
+ for (Map.Entry<?, ?> entry : ((Map<?, ?>) value).entrySet()) {
+ convertedElements.put(convert(entry.getKey(), targetKeyType), convert(entry.getValue(), targetValueType));
+ }
+ return convertedElements;
+ }
+ }
+ }
+ if (targetType instanceof Class) {
+ if (((Class) targetType).isPrimitive()) {
+ return value;
+ }
+ return adapt((Class) targetType, value, mapping);
+ }
+ throw new UnsupportedOperationException(String.format("Cannot convert object of %s to %s.", value.getClass(), targetType));
+ }
+
+ private Type getElementType(ParameterizedType type, int index) {
+ Type elementType = type.getActualTypeArguments()[index];
+ if (elementType instanceof WildcardType) {
+ WildcardType wildcardType = (WildcardType) elementType;
+ return wildcardType.getUpperBounds()[0];
+ }
+ return elementType;
+ }
+ }
+
+ private static class PropertyCachingMethodInvoker implements MethodInvoker {
+ private final Map<String, Object> properties = new HashMap<String, Object>();
+ private final Set<String> unknown = new HashSet<String>();
+ private final MethodInvoker next;
+
+ private PropertyCachingMethodInvoker(MethodInvoker next) {
+ this.next = next;
+ }
+
+ public void invoke(MethodInvocation method) throws Throwable {
+ if ((GETTER_METHOD.matcher(method.getName()).matches() || IS_METHOD.matcher(method.getName()).matches()) && method.getParameterTypes().length == 0) {
+ if (properties.containsKey(method.getName())) {
+ method.setResult(properties.get(method.getName()));
+ return;
+ }
+ if (unknown.contains(method.getName())) {
+ return;
+ }
+
+ Object value;
+ next.invoke(method);
+ if (!method.found()) {
+ unknown.add(method.getName());
+ return;
+ }
+ value = method.getResult();
+ properties.put(method.getName(), value);
+ return;
+ }
+
+ next.invoke(method);
+ }
+ }
+
+ private static class SafeMethodInvoker implements MethodInvoker {
+ private final MethodInvoker next;
+
+ private SafeMethodInvoker(MethodInvoker next) {
+ this.next = next;
+ }
+
+ public void invoke(MethodInvocation invocation) throws Throwable {
+ next.invoke(invocation);
+ if (invocation.found()) {
+ return;
+ }
+
+ boolean getter = GETTER_METHOD.matcher(invocation.getName()).matches();
+ if (!getter || invocation.getParameterTypes().length != 1) {
+ return;
+ }
+
+ MethodInvocation getterInvocation = new MethodInvocation(invocation.getName(), invocation.getReturnType(), invocation.getGenericReturnType(), new Class[0], invocation.getDelegate(), EMPTY);
+ next.invoke(getterInvocation);
+ if (getterInvocation.found() && getterInvocation.getResult() != null) {
+ invocation.setResult(getterInvocation.getResult());
+ } else {
+ invocation.setResult(invocation.getParameters()[0]);
+ }
+ }
+ }
+
+ private static class SupportedPropertyInvoker implements MethodInvoker {
+ private final MethodInvoker next;
+
+ private SupportedPropertyInvoker(MethodInvoker next) {
+ this.next = next;
+ }
+
+ public void invoke(MethodInvocation invocation) throws Throwable {
+ Matcher matcher = IS_SUPPORT_METHOD.matcher(invocation.getName());
+ if (!matcher.matches()) {
+ next.invoke(invocation);
+ return;
+ }
+
+ String getterName = String.format("get%s", matcher.group(1));
+ MethodInvocation getterInvocation = new MethodInvocation(getterName, invocation.getReturnType(), invocation.getGenericReturnType(), new Class[0], invocation.getDelegate(), EMPTY);
+ next.invoke(getterInvocation);
+ invocation.setResult(getterInvocation.found());
+ }
+ }
+
+ private static class MixInMethodInvoker implements MethodInvoker {
+ private Object proxy;
+ private Object instance;
+ private final Class<?> mixInClass;
+ private final MethodInvoker next;
+ private final ThreadLocal<MethodInvocation> current = new ThreadLocal<MethodInvocation>();
+
+ public MixInMethodInvoker(Class<?> mixInClass, MethodInvoker next) {
+ this.mixInClass = mixInClass;
+ this.next = next;
+ }
+
+ public void invoke(MethodInvocation invocation) throws Throwable {
+ if (current.get() != null) {
+ // Already invoking a method on the mix-in
+ return;
+ }
+
+ if (instance == null) {
+ instance = new DirectInstantiator().newInstance(mixInClass, proxy);
+ }
+ MethodInvocation beanInvocation = new MethodInvocation(invocation.getName(), invocation.getReturnType(), invocation.getGenericReturnType(), invocation.getParameterTypes(), instance, invocation.getParameters());
+ current.set(beanInvocation);
+ try {
+ next.invoke(beanInvocation);
+ } finally {
+ current.set(null);
+ }
+ if (beanInvocation.found()) {
+ invocation.setResult(beanInvocation.getResult());
+ }
+ }
+
+ public void setProxy(Object proxy) {
+ this.proxy = proxy;
+ }
+
+ public Object getProxy() {
+ return proxy;
+ }
+ }
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/adapter/SourceObjectMapping.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/adapter/SourceObjectMapping.java
new file mode 100644
index 0000000..90b3147
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/adapter/SourceObjectMapping.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.adapter;
+
+public interface SourceObjectMapping {
+ Object getSourceObject();
+
+ Class<?> getTargetType();
+
+ void mapToType(Class<?> type);
+
+ void mixIn(Class<?> mixInBeanType);
+
+ void mixIn(MethodInvoker invoker);
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/adapter/TargetTypeProvider.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/adapter/TargetTypeProvider.java
new file mode 100644
index 0000000..6942681
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/adapter/TargetTypeProvider.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.adapter;
+
+import java.io.Serializable;
+
+public interface TargetTypeProvider extends Serializable {
+ /**
+ * Determines the model type to use to wrap the given protocol object.
+ */
+ <T> Class<? extends T> getTargetType(Class<T> initialTargetType, Object protocolObject);
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/build/DefaultBuildEnvironment.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/build/DefaultBuildEnvironment.java
index 03f354f..d723a3e 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/build/DefaultBuildEnvironment.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/build/DefaultBuildEnvironment.java
@@ -17,37 +17,22 @@
package org.gradle.tooling.internal.build;
import org.gradle.tooling.internal.protocol.InternalBuildEnvironment;
-import org.gradle.tooling.model.build.BuildEnvironment;
-import org.gradle.tooling.model.build.GradleEnvironment;
import org.gradle.tooling.model.build.JavaEnvironment;
import java.io.File;
import java.io.Serializable;
import java.util.List;
-/**
- * by Szczepan Faber, created at: 12/17/11
- */
-public class DefaultBuildEnvironment implements BuildEnvironment, InternalBuildEnvironment, Serializable {
-
- private final String gradleVersion;
+public class DefaultBuildEnvironment extends VersionOnlyBuildEnvironment implements InternalBuildEnvironment, Serializable {
private final File javaHome;
private final List<String> jvmArguments;
public DefaultBuildEnvironment(String gradleVersion, File javaHome, List<String> jvmArguments) {
- this.gradleVersion = gradleVersion;
+ super(gradleVersion);
this.javaHome = javaHome;
this.jvmArguments = jvmArguments;
}
- public GradleEnvironment getGradle() {
- return new GradleEnvironment() {
- public String getGradleVersion() {
- return gradleVersion;
- }
- };
- }
-
public JavaEnvironment getJava() {
return new JavaEnvironment() {
public File getJavaHome() {
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/build/VersionOnlyBuildEnvironment.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/build/VersionOnlyBuildEnvironment.java
index 4925d81..f1c9488 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/build/VersionOnlyBuildEnvironment.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/build/VersionOnlyBuildEnvironment.java
@@ -16,19 +16,20 @@
package org.gradle.tooling.internal.build;
-import org.gradle.tooling.model.build.JavaEnvironment;
-import org.gradle.tooling.model.internal.Exceptions;
+import org.gradle.tooling.model.build.GradleEnvironment;
-/**
- * by Szczepan Faber, created at: 12/22/11
- */
-public class VersionOnlyBuildEnvironment extends DefaultBuildEnvironment {
+public class VersionOnlyBuildEnvironment {
+ private final String gradleVersion;
public VersionOnlyBuildEnvironment(String gradleVersion) {
- super(gradleVersion, null, null);
+ this.gradleVersion = gradleVersion;
}
- public JavaEnvironment getJava() {
- throw Exceptions.unsupportedMethod("getJava()");
+ public GradleEnvironment getGradle() {
+ return new GradleEnvironment() {
+ public String getGradleVersion() {
+ return gradleVersion;
+ }
+ };
}
}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/AbstractLongRunningOperation.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/AbstractLongRunningOperation.java
new file mode 100644
index 0000000..1bd585f
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/AbstractLongRunningOperation.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.consumer;
+
+import org.gradle.tooling.LongRunningOperation;
+import org.gradle.tooling.ProgressListener;
+import org.gradle.tooling.internal.consumer.parameters.ConsumerOperationParameters;
+
+import java.io.File;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public abstract class AbstractLongRunningOperation<T extends LongRunningOperation> implements LongRunningOperation {
+ protected final ConsumerOperationParameters operationParameters;
+
+ protected AbstractLongRunningOperation(ConsumerOperationParameters operationParameters) {
+ this.operationParameters = operationParameters;
+ }
+
+ protected abstract T getThis();
+
+ public T withArguments(String... arguments) {
+ operationParameters.setArguments(arguments);
+ return getThis();
+ }
+
+ public T setStandardOutput(OutputStream outputStream) {
+ operationParameters.setStandardOutput(outputStream);
+ return getThis();
+ }
+
+ public T setStandardError(OutputStream outputStream) {
+ operationParameters.setStandardError(outputStream);
+ return getThis();
+ }
+
+ public T setStandardInput(InputStream inputStream) {
+ operationParameters.setStandardInput(inputStream);
+ return getThis();
+ }
+
+ public T setJavaHome(File javaHome) {
+ operationParameters.setJavaHome(javaHome);
+ return getThis();
+ }
+
+ public T setJvmArguments(String... jvmArguments) {
+ operationParameters.setJvmArguments(jvmArguments);
+ return getThis();
+ }
+
+ public T addProgressListener(ProgressListener listener) {
+ operationParameters.addProgressListener(listener);
+ return getThis();
+ }
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/BlockingResultHandler.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/BlockingResultHandler.java
index 516c3ef..5094d90 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/BlockingResultHandler.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/BlockingResultHandler.java
@@ -19,6 +19,9 @@ import org.gradle.internal.UncheckedException;
import org.gradle.tooling.GradleConnectionException;
import org.gradle.tooling.ResultHandler;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
@@ -40,7 +43,7 @@ class BlockingResultHandler<T> implements ResultHandler<T> {
}
if (result instanceof Throwable) {
- throw UncheckedException.throwAsUncheckedException((Throwable) result);
+ throw UncheckedException.throwAsUncheckedException(attachCallerThreadStackTrace((Throwable) result));
}
if (result == NULL) {
return null;
@@ -48,6 +51,17 @@ class BlockingResultHandler<T> implements ResultHandler<T> {
return resultType.cast(result);
}
+ private Throwable attachCallerThreadStackTrace(Throwable failure) {
+ List<StackTraceElement> adjusted = new ArrayList<StackTraceElement>();
+ adjusted.addAll(Arrays.asList(failure.getStackTrace()));
+ List<StackTraceElement> currentThreadStack = Arrays.asList(Thread.currentThread().getStackTrace());
+ if (!currentThreadStack.isEmpty()) {
+ adjusted.addAll(currentThreadStack.subList(2, currentThreadStack.size()));
+ }
+ failure.setStackTrace(adjusted.toArray(new StackTraceElement[adjusted.size()]));
+ return failure;
+ }
+
public void onComplete(T result) {
queue.add(result == null ? NULL : result);
}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/ConnectionFactory.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/ConnectionFactory.java
index c615983..c5d410f 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/ConnectionFactory.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/ConnectionFactory.java
@@ -17,17 +17,12 @@ package org.gradle.tooling.internal.consumer;
import org.gradle.internal.concurrent.DefaultExecutorFactory;
import org.gradle.tooling.ProjectConnection;
-import org.gradle.tooling.internal.consumer.async.AsyncConnection;
-import org.gradle.tooling.internal.consumer.async.DefaultAsyncConnection;
-import org.gradle.tooling.internal.consumer.connection.ConsumerConnection;
-import org.gradle.tooling.internal.consumer.connection.LazyConnection;
-import org.gradle.tooling.internal.consumer.connection.LoggingInitializerConnection;
-import org.gradle.tooling.internal.consumer.connection.ProgressLoggingConnection;
+import org.gradle.tooling.internal.consumer.async.AsyncConsumerActionExecutor;
+import org.gradle.tooling.internal.consumer.async.DefaultAsyncConsumerActionExecutor;
+import org.gradle.tooling.internal.consumer.connection.*;
import org.gradle.tooling.internal.consumer.loader.ToolingImplementationLoader;
-import org.gradle.tooling.internal.consumer.protocoladapter.ProtocolToModelAdapter;
public class ConnectionFactory {
- private final ProtocolToModelAdapter adapter = new ProtocolToModelAdapter();
private final ToolingImplementationLoader toolingImplementationLoader;
private final DefaultExecutorFactory executorFactory = new DefaultExecutorFactory();
@@ -37,11 +32,11 @@ public class ConnectionFactory {
public ProjectConnection create(Distribution distribution, ConnectionParameters parameters) {
SynchronizedLogging synchronizedLogging = new SynchronizedLogging();
- ConsumerConnection lazyConnection = new LazyConnection(distribution, toolingImplementationLoader, synchronizedLogging, parameters.getVerboseLogging());
- ConsumerConnection progressLoggingConnection = new ProgressLoggingConnection(lazyConnection, synchronizedLogging);
- ConsumerConnection initializingConnection = new LoggingInitializerConnection(progressLoggingConnection, synchronizedLogging);
- AsyncConnection asyncConnection = new DefaultAsyncConnection(initializingConnection, executorFactory);
- return new DefaultProjectConnection(asyncConnection, adapter, parameters);
+ ConsumerActionExecutor lazyConnection = new LazyConsumerActionExecutor(distribution, toolingImplementationLoader, synchronizedLogging, parameters.getVerboseLogging());
+ ConsumerActionExecutor progressLoggingConnection = new ProgressLoggingConsumerActionExecutor(lazyConnection, synchronizedLogging);
+ ConsumerActionExecutor initializingConnection = new LoggingInitializerConsumerActionExecutor(progressLoggingConnection, synchronizedLogging);
+ AsyncConsumerActionExecutor asyncConnection = new DefaultAsyncConsumerActionExecutor(initializingConnection, executorFactory);
+ return new DefaultProjectConnection(asyncConnection, parameters);
}
ToolingImplementationLoader getToolingImplementationLoader() {
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/ConnectorServices.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/ConnectorServices.java
index be2c2e3..5d9fc26 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/ConnectorServices.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/ConnectorServices.java
@@ -17,17 +17,14 @@
package org.gradle.tooling.internal.consumer;
import org.gradle.StartParameter;
-import org.gradle.internal.service.SynchronizedServiceRegistry;
-import org.gradle.internal.service.ServiceRegistry;
import org.gradle.internal.service.DefaultServiceRegistry;
+import org.gradle.internal.service.ServiceRegistry;
+import org.gradle.internal.service.SynchronizedServiceRegistry;
import org.gradle.tooling.internal.consumer.loader.CachingToolingImplementationLoader;
import org.gradle.tooling.internal.consumer.loader.DefaultToolingImplementationLoader;
import org.gradle.tooling.internal.consumer.loader.SynchronizedToolingImplementationLoader;
import org.gradle.tooling.internal.consumer.loader.ToolingImplementationLoader;
-/**
- * by Szczepan Faber, created at: 12/6/11
- */
public class ConnectorServices {
private static ServiceRegistry singletonRegistry = new SynchronizedServiceRegistry(new ConnectorServiceRegistry());
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/DefaultBuildActionExecuter.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/DefaultBuildActionExecuter.java
new file mode 100644
index 0000000..7b93a54
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/DefaultBuildActionExecuter.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.consumer;
+
+import org.gradle.tooling.*;
+import org.gradle.tooling.internal.consumer.async.AsyncConsumerActionExecutor;
+import org.gradle.tooling.internal.consumer.connection.ConsumerAction;
+import org.gradle.tooling.internal.consumer.connection.ConsumerConnection;
+import org.gradle.tooling.internal.consumer.parameters.ConsumerOperationParameters;
+
+class DefaultBuildActionExecuter<T> extends AbstractLongRunningOperation<DefaultBuildActionExecuter<T>> implements BuildActionExecuter<T> {
+ private final BuildAction<T> buildAction;
+ private final AsyncConsumerActionExecutor connection;
+
+ public DefaultBuildActionExecuter(BuildAction<T> buildAction, AsyncConsumerActionExecutor connection, ConnectionParameters parameters) {
+ super(new ConsumerOperationParameters(parameters));
+ this.buildAction = buildAction;
+ this.connection = connection;
+ }
+
+ @Override
+ protected DefaultBuildActionExecuter<T> getThis() {
+ return this;
+ }
+
+ public T run() throws GradleConnectionException {
+ BlockingResultHandler<Object> handler = new BlockingResultHandler<Object>(Object.class);
+ run(handler);
+ return (T) handler.getResult();
+ }
+
+ public void run(ResultHandler<? super T> handler) throws IllegalStateException {
+ connection.run(new ConsumerAction<T>() {
+ public ConsumerOperationParameters getParameters() {
+ return operationParameters;
+ }
+
+ public T run(ConsumerConnection connection) {
+ return connection.run(buildAction, operationParameters);
+ }
+ }, new ResultHandlerAdapter<T>(handler) {
+ @Override
+ protected String connectionFailureMessage(Throwable failure) {
+ return String.format("Could not run build action using %s.", connection.getDisplayName());
+ }
+ }
+ );
+ }
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/DefaultBuildLauncher.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/DefaultBuildLauncher.java
index 012561c..f2fc34e 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/DefaultBuildLauncher.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/DefaultBuildLauncher.java
@@ -16,30 +16,32 @@
package org.gradle.tooling.internal.consumer;
import org.gradle.tooling.BuildLauncher;
-import org.gradle.tooling.ProgressListener;
import org.gradle.tooling.ResultHandler;
-import org.gradle.tooling.internal.consumer.async.AsyncConnection;
+import org.gradle.tooling.internal.consumer.async.AsyncConsumerActionExecutor;
+import org.gradle.tooling.internal.consumer.connection.ConsumerAction;
+import org.gradle.tooling.internal.consumer.connection.ConsumerConnection;
import org.gradle.tooling.internal.consumer.parameters.ConsumerOperationParameters;
import org.gradle.tooling.model.Task;
-import java.io.File;
-import java.io.InputStream;
-import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
-class DefaultBuildLauncher implements BuildLauncher {
- private final AsyncConnection connection;
- private ConsumerOperationParameters operationParameters;
+class DefaultBuildLauncher extends AbstractLongRunningOperation<DefaultBuildLauncher> implements BuildLauncher {
+ private final AsyncConsumerActionExecutor connection;
- public DefaultBuildLauncher(AsyncConnection connection, ConnectionParameters parameters) {
- operationParameters = new ConsumerOperationParameters(parameters);
+ public DefaultBuildLauncher(AsyncConsumerActionExecutor connection, ConnectionParameters parameters) {
+ super(new ConsumerOperationParameters(parameters));
operationParameters.setTasks(Collections.<String>emptyList());
this.connection = connection;
}
+ @Override
+ protected DefaultBuildLauncher getThis() {
+ return this;
+ }
+
public BuildLauncher forTasks(String... tasks) {
operationParameters.setTasks(Arrays.asList(tasks));
return this;
@@ -59,41 +61,6 @@ class DefaultBuildLauncher implements BuildLauncher {
return this;
}
- public BuildLauncher withArguments(String... arguments) {
- operationParameters.setArguments(arguments);
- return this;
- }
-
- public DefaultBuildLauncher setStandardError(OutputStream outputStream) {
- operationParameters.setStandardError(outputStream);
- return this;
- }
-
- public DefaultBuildLauncher setStandardOutput(OutputStream outputStream) {
- operationParameters.setStandardOutput(outputStream);
- return this;
- }
-
- public DefaultBuildLauncher setStandardInput(InputStream inputStream) {
- operationParameters.setStandardInput(inputStream);
- return this;
- }
-
- public DefaultBuildLauncher setJavaHome(File javaHome) {
- operationParameters.setJavaHome(javaHome);
- return this;
- }
-
- public DefaultBuildLauncher setJvmArguments(String... jvmArguments) {
- operationParameters.setJvmArguments(jvmArguments);
- return this;
- }
-
- public DefaultBuildLauncher addProgressListener(ProgressListener listener) {
- operationParameters.addProgressListener(listener);
- return this;
- }
-
public void run() {
BlockingResultHandler<Void> handler = new BlockingResultHandler<Void>(Void.class);
run(handler);
@@ -101,11 +68,25 @@ class DefaultBuildLauncher implements BuildLauncher {
}
public void run(final ResultHandler<? super Void> handler) {
- connection.run(Void.class, operationParameters, new ResultHandlerAdapter<Void>(handler) {
- @Override
- protected String connectionFailureMessage(Throwable failure) {
- return String.format("Could not execute build using %s.", connection.getDisplayName());
+ connection.run(new ConsumerAction<Void>() {
+ public ConsumerOperationParameters getParameters() {
+ return operationParameters;
}
- });
+
+ public Void run(ConsumerConnection connection) {
+ return connection.run(Void.class, operationParameters);
+ }
+ }, new ResultHandlerAdapter(handler));
+ }
+
+ private class ResultHandlerAdapter extends org.gradle.tooling.internal.consumer.ResultHandlerAdapter<Void> {
+ public ResultHandlerAdapter(ResultHandler<? super Void> handler) {
+ super(handler);
+ }
+
+ @Override
+ protected String connectionFailureMessage(Throwable failure) {
+ return String.format("Could not execute build using %s.", connection.getDisplayName());
+ }
}
}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/DefaultGradleConnector.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/DefaultGradleConnector.java
index f414cac..d9162ee 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/DefaultGradleConnector.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/DefaultGradleConnector.java
@@ -116,8 +116,4 @@ public class DefaultGradleConnector extends GradleConnector {
ConnectionFactory getConnectionFactory() {
return connectionFactory;
}
-
- void setDistribution(Distribution distribution) {
- this.distribution = distribution;
- }
}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/DefaultModelBuilder.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/DefaultModelBuilder.java
index a4ff873..b596707 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/DefaultModelBuilder.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/DefaultModelBuilder.java
@@ -15,33 +15,31 @@
*/
package org.gradle.tooling.internal.consumer;
-import org.gradle.tooling.*;
-import org.gradle.tooling.internal.consumer.async.AsyncConnection;
+import org.gradle.tooling.GradleConnectionException;
+import org.gradle.tooling.ModelBuilder;
+import org.gradle.tooling.ResultHandler;
+import org.gradle.tooling.internal.consumer.async.AsyncConsumerActionExecutor;
+import org.gradle.tooling.internal.consumer.connection.ConsumerAction;
+import org.gradle.tooling.internal.consumer.connection.ConsumerConnection;
import org.gradle.tooling.internal.consumer.parameters.ConsumerOperationParameters;
-import org.gradle.tooling.internal.consumer.protocoladapter.ConsumerPropertyHandler;
-import org.gradle.tooling.internal.consumer.protocoladapter.ProtocolToModelAdapter;
-import org.gradle.tooling.model.Model;
import org.gradle.tooling.model.UnsupportedMethodException;
import org.gradle.tooling.model.internal.Exceptions;
-import java.io.File;
-import java.io.InputStream;
-import java.io.OutputStream;
import java.util.Arrays;
-public class DefaultModelBuilder<T extends Model, P> implements ModelBuilder<T> {
+public class DefaultModelBuilder<T> extends AbstractLongRunningOperation<DefaultModelBuilder<T>> implements ModelBuilder<T> {
private final Class<T> modelType;
- private final Class<P> protocolType;
- private final AsyncConnection connection;
- private final ProtocolToModelAdapter adapter;
- private ConsumerOperationParameters operationParameters;
+ private final AsyncConsumerActionExecutor connection;
- public DefaultModelBuilder(Class<T> modelType, Class<P> protocolType, AsyncConnection connection, ProtocolToModelAdapter adapter, ConnectionParameters parameters) {
- operationParameters = new ConsumerOperationParameters(parameters);
+ public DefaultModelBuilder(Class<T> modelType, AsyncConsumerActionExecutor connection, ConnectionParameters parameters) {
+ super(new ConsumerOperationParameters(parameters));
this.modelType = modelType;
- this.protocolType = protocolType;
this.connection = connection;
- this.adapter = adapter;
+ }
+
+ @Override
+ protected DefaultModelBuilder<T> getThis() {
+ return this;
}
public T get() throws GradleConnectionException {
@@ -51,73 +49,34 @@ public class DefaultModelBuilder<T extends Model, P> implements ModelBuilder<T>
}
public void get(final ResultHandler<? super T> handler) throws IllegalStateException {
- ResultHandler<P> adaptingHandler = new ProtocolToModelAdaptingHandler(handler);
- connection.run(protocolType, operationParameters, new ResultHandlerAdapter<P>(adaptingHandler) {
- @Override
- protected String connectionFailureMessage(Throwable failure) {
- String message = String.format("Could not fetch model of type '%s' using %s.", modelType.getSimpleName(), connection.getDisplayName());
- if (!(failure instanceof UnsupportedMethodException)
- && failure instanceof UnsupportedOperationException) {
- message += "\n" + Exceptions.INCOMPATIBLE_VERSION_HINT;
- }
- return message;
+ connection.run(new ConsumerAction<T>() {
+ public ConsumerOperationParameters getParameters() {
+ return operationParameters;
}
- });
- }
-
- public DefaultModelBuilder<T, P> withArguments(String... arguments) {
- operationParameters.setArguments(arguments);
- return this;
- }
-
- public DefaultModelBuilder<T, P> setStandardOutput(OutputStream outputStream) {
- operationParameters.setStandardOutput(outputStream);
- return this;
- }
-
- public DefaultModelBuilder<T, P> setStandardError(OutputStream outputStream) {
- operationParameters.setStandardError(outputStream);
- return this;
- }
-
- public DefaultModelBuilder<T, P> setStandardInput(InputStream inputStream) {
- operationParameters.setStandardInput(inputStream);
- return this;
- }
-
- public DefaultModelBuilder<T, P> setJavaHome(File javaHome) {
- operationParameters.setJavaHome(javaHome);
- return this;
- }
-
- public DefaultModelBuilder<T, P> setJvmArguments(String... jvmArguments) {
- operationParameters.setJvmArguments(jvmArguments);
- return this;
- }
- public DefaultModelBuilder<T, P> addProgressListener(ProgressListener listener) {
- operationParameters.addProgressListener(listener);
- return this;
+ public T run(ConsumerConnection connection) {
+ return connection.run(modelType, operationParameters);
+ }
+ }, new ResultHandlerAdapter<T>(handler));
}
- public DefaultModelBuilder<T, P> forTasks(String... tasks) {
+ public DefaultModelBuilder<T> forTasks(String... tasks) {
operationParameters.setTasks(Arrays.asList(tasks));
return this;
}
- private class ProtocolToModelAdaptingHandler implements ResultHandler<P> {
- private final ResultHandler<? super T> handler;
-
- public ProtocolToModelAdaptingHandler(ResultHandler<? super T> handler) {
- this.handler = handler;
+ private class ResultHandlerAdapter<T> extends org.gradle.tooling.internal.consumer.ResultHandlerAdapter<T> {
+ public ResultHandlerAdapter(ResultHandler<? super T> handler) {
+ super(handler);
}
- public void onComplete(P result) {
- handler.onComplete(adapter.adapt(modelType, result, new ConsumerPropertyHandler(connection.getVersionDetails())));
- }
-
- public void onFailure(GradleConnectionException failure) {
- handler.onFailure(failure);
+ @Override
+ protected String connectionFailureMessage(Throwable failure) {
+ String message = String.format("Could not fetch model of type '%s' using %s.", modelType.getSimpleName(), connection.getDisplayName());
+ if (!(failure instanceof UnsupportedMethodException) && failure instanceof UnsupportedOperationException) {
+ message += "\n" + Exceptions.INCOMPATIBLE_VERSION_HINT;
+ }
+ return message;
}
}
}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/DefaultProjectConnection.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/DefaultProjectConnection.java
index 663ea7d..198a581 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/DefaultProjectConnection.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/DefaultProjectConnection.java
@@ -16,52 +16,42 @@
package org.gradle.tooling.internal.consumer;
import org.gradle.tooling.*;
-import org.gradle.tooling.internal.consumer.async.AsyncConnection;
-import org.gradle.tooling.internal.consumer.protocoladapter.ProtocolToModelAdapter;
-import org.gradle.tooling.internal.consumer.versioning.ModelMapping;
-import org.gradle.tooling.model.Model;
+import org.gradle.tooling.internal.consumer.async.AsyncConsumerActionExecutor;
class DefaultProjectConnection implements ProjectConnection {
- private final AsyncConnection connection;
- private final ModelMapping modelMapping = new ModelMapping();
- private ProtocolToModelAdapter adapter;
+ private final AsyncConsumerActionExecutor connection;
private final ConnectionParameters parameters;
- public DefaultProjectConnection(AsyncConnection connection, ProtocolToModelAdapter adapter, ConnectionParameters parameters) {
+ public DefaultProjectConnection(AsyncConsumerActionExecutor connection, ConnectionParameters parameters) {
this.connection = connection;
this.parameters = parameters;
- this.adapter = adapter;
}
public void close() {
connection.stop();
}
- public <T extends Model> T getModel(Class<T> viewType) {
- return model(viewType).get();
+ public <T> T getModel(Class<T> modelType) {
+ return model(modelType).get();
}
- public <T extends Model> void getModel(final Class<T> viewType, final ResultHandler<? super T> handler) {
- model(viewType).get(handler);
+ public <T> void getModel(final Class<T> modelType, final ResultHandler<? super T> handler) {
+ model(modelType).get(handler);
}
public BuildLauncher newBuild() {
return new DefaultBuildLauncher(connection, parameters);
}
- public <T extends Model> ModelBuilder<T> model(Class<T> modelType) {
- return new DefaultModelBuilder<T, Class>(modelType, mapToProtocol(modelType), connection, adapter, parameters);
+ public <T> ModelBuilder<T> model(Class<T> modelType) {
+ if (!modelType.isInterface()) {
+ throw new IllegalArgumentException(String.format("Cannot fetch a model of type '%s' as this type is not an interface.", modelType.getName()));
+ }
+ return new DefaultModelBuilder<T>(modelType, connection, parameters);
}
- private Class mapToProtocol(Class<? extends Model> viewType) {
- Class protocolViewType = modelMapping.getInternalType(viewType);
- if (protocolViewType == null) {
- throw new UnknownModelException(
- "Unknown model: '" + viewType.getSimpleName() + "'.\n"
- + "Most likely you are trying to acquire a model for a class that is not a valid Tooling API model class.\n"
- + "Review the documentation on the version of Tooling API you use to find out what models can be build."
- );
- }
- return protocolViewType;
+ public <T> BuildActionExecuter<T> action(final BuildAction<T> buildAction) {
+ return new DefaultBuildActionExecuter<T>(buildAction, connection, parameters);
}
+
}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/LoggingProvider.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/LoggingProvider.java
index 9bfb606..3e945f1 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/LoggingProvider.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/LoggingProvider.java
@@ -19,9 +19,6 @@ package org.gradle.tooling.internal.consumer;
import org.gradle.listener.ListenerManager;
import org.gradle.logging.ProgressLoggerFactory;
-/**
- * by Szczepan Faber, created at: 12/14/11
- */
public interface LoggingProvider {
ListenerManager getListenerManager();
ProgressLoggerFactory getProgressLoggerFactory();
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/ModelProvider.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/ModelProvider.java
deleted file mode 100644
index 5b498c8..0000000
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/ModelProvider.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.consumer;
-
-import org.gradle.tooling.internal.build.VersionOnlyBuildEnvironment;
-import org.gradle.tooling.internal.consumer.connection.ConsumerConnection;
-import org.gradle.tooling.internal.consumer.converters.GradleProjectConverter;
-import org.gradle.tooling.internal.consumer.parameters.ConsumerOperationParameters;
-import org.gradle.tooling.internal.consumer.versioning.VersionDetails;
-import org.gradle.tooling.internal.protocol.InternalBuildEnvironment;
-import org.gradle.tooling.internal.protocol.InternalGradleProject;
-import org.gradle.tooling.internal.protocol.eclipse.EclipseProjectVersion3;
-import org.gradle.tooling.model.GradleProject;
-import org.gradle.tooling.model.internal.Exceptions;
-
-/**
- * by Szczepan Faber, created at: 12/21/11
- */
-public class ModelProvider {
-
- public <T> T provide(ConsumerConnection connection, Class<T> type, ConsumerOperationParameters operationParameters) {
- VersionDetails version = connection.getVersionDetails();
-
- if (operationParameters.getJavaHome() != null) {
- if(!version.supportsConfiguringJavaHome()) {
- throw Exceptions.unsupportedOperationConfiguration("modelBuilder.setJavaHome() and buildLauncher.setJavaHome()");
- }
- }
- if (operationParameters.getJvmArguments() != null) {
- if (!version.supportsConfiguringJvmArguments()) {
- throw Exceptions.unsupportedOperationConfiguration("modelBuilder.setJvmArguments() and buildLauncher.setJvmArguments()");
- }
- }
- if (operationParameters.getStandardInput() != null) {
- if (!version.supportsConfiguringStandardInput()) {
- throw Exceptions.unsupportedOperationConfiguration("modelBuilder.setStandardInput() and buildLauncher.setStandardInput()");
- }
- }
- if (type != Void.class && operationParameters.getTasks() != null) {
- if (!version.supportsRunningTasksWhenBuildingModel()) {
- throw Exceptions.unsupportedOperationConfiguration("modelBuilder.forTasks()");
- }
- }
-
- if (type == InternalBuildEnvironment.class && !version.supportsCompleteBuildEnvironment()) {
- //early versions of provider do not support BuildEnvironment model
- //since we know the gradle version at least we can give back some result
- VersionOnlyBuildEnvironment out = new VersionOnlyBuildEnvironment(version.getVersion());
- return type.cast(out);
- }
- if (version.clientHangsOnEarlyDaemonFailure() && version.isPostM6Model(type)) {
- //those version require special handling because of the client hanging bug
- //it is due to the exception handing on the daemon side in M5 and M6
- String message = String.format("I don't know how to build a model of type '%s'.", type.getSimpleName());
- throw new UnsupportedOperationException(message);
- }
- if (type == InternalGradleProject.class && !version.supportsGradleProjectModel()) {
- //we broke compatibility around M9 wrt getting the tasks of a project (issue GRADLE-1875)
- //this patch enables getting gradle tasks for target gradle version pre M5
- EclipseProjectVersion3 project = connection.run(EclipseProjectVersion3.class, operationParameters);
- GradleProject gradleProject = new GradleProjectConverter().convert(project);
- return (T) gradleProject;
- }
- return connection.run(type, operationParameters);
- }
-}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/SynchronizedLogging.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/SynchronizedLogging.java
index 6797a1d..070ebfd 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/SynchronizedLogging.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/SynchronizedLogging.java
@@ -16,9 +16,9 @@
package org.gradle.tooling.internal.consumer;
-import org.gradle.internal.concurrent.Synchronizer;
import org.gradle.internal.Factory;
import org.gradle.internal.TrueTimeProvider;
+import org.gradle.internal.concurrent.Synchronizer;
import org.gradle.listener.DefaultListenerManager;
import org.gradle.listener.ListenerManager;
import org.gradle.logging.internal.DefaultProgressLoggerFactory;
@@ -26,8 +26,6 @@ import org.gradle.logging.internal.ProgressListener;
/**
* Thread safe logging provider that needs to be initialized before use.
- * <p>
- * by Szczepan Faber, created at: 12/14/11
*/
public class SynchronizedLogging implements LoggingProvider {
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/async/AsyncConnection.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/async/AsyncConnection.java
deleted file mode 100644
index 707ff54..0000000
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/async/AsyncConnection.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.consumer.async;
-
-import org.gradle.tooling.internal.consumer.parameters.ConsumerOperationParameters;
-import org.gradle.tooling.internal.consumer.versioning.VersionDetails;
-import org.gradle.tooling.internal.protocol.ResultHandlerVersion1;
-
-public interface AsyncConnection {
- <T> void run(Class<T> type, ConsumerOperationParameters operationParameters, ResultHandlerVersion1<? super T> handler) throws UnsupportedOperationException, IllegalStateException;
-
- void stop();
-
- String getDisplayName();
-
- VersionDetails getVersionDetails();
-}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/async/AsyncConsumerActionExecutor.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/async/AsyncConsumerActionExecutor.java
new file mode 100644
index 0000000..3e69c76
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/async/AsyncConsumerActionExecutor.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.consumer.async;
+
+import org.gradle.tooling.internal.consumer.connection.ConsumerAction;
+import org.gradle.tooling.internal.protocol.ResultHandlerVersion1;
+
+/**
+ * Implementations must be thread-safe.
+ */
+public interface AsyncConsumerActionExecutor {
+ /**
+ * Runs some operation asynchronously against a consumer connection. Notifies the provided handler when
+ * complete. Note that the action may have completed by the time this method returns.
+ *
+ * @throws IllegalStateException When this connection has been stopped or is stopping.
+ */
+ <T> void run(ConsumerAction<? extends T> action, ResultHandlerVersion1<? super T> handler);
+
+ /**
+ * Stops this connection, blocking until all operations on the connection have completed.
+ */
+ void stop();
+
+ String getDisplayName();
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/async/DefaultAsyncConnection.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/async/DefaultAsyncConnection.java
deleted file mode 100644
index 75c06bd..0000000
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/async/DefaultAsyncConnection.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.consumer.async;
-
-import org.gradle.internal.concurrent.ExecutorFactory;
-import org.gradle.internal.concurrent.StoppableExecutor;
-import org.gradle.tooling.internal.consumer.connection.ConsumerConnection;
-import org.gradle.tooling.internal.consumer.parameters.ConsumerOperationParameters;
-import org.gradle.tooling.internal.consumer.versioning.VersionDetails;
-import org.gradle.tooling.internal.protocol.ResultHandlerVersion1;
-
-import java.util.concurrent.atomic.AtomicBoolean;
-
-/**
- * Adapts a {@link ConsumerConnection} to an {@link AsyncConnection}.
- */
-public class DefaultAsyncConnection implements AsyncConnection {
- private final ConsumerConnection connection;
- private final StoppableExecutor executor;
- private final AtomicBoolean closed = new AtomicBoolean();
-
- public DefaultAsyncConnection(ConsumerConnection connection, ExecutorFactory executorFactory) {
- this.connection = connection;
- executor = executorFactory.create("Connection worker");
- }
-
- public String getDisplayName() {
- return connection.getDisplayName();
- }
-
- public VersionDetails getVersionDetails() {
- return connection.getVersionDetails();
- }
-
- public <T> void run(final Class<T> type, final ConsumerOperationParameters operationParameters, ResultHandlerVersion1<? super T> handler) throws UnsupportedOperationException, IllegalStateException {
- runLater(handler, new ConnectionAction<T>() {
- public T run() {
- return connection.run(type, operationParameters);
- }
- });
- }
-
- public void stop() {
- closed.set(true);
- executor.stop();
- connection.stop();
- }
-
- private <T> void runLater(final ResultHandlerVersion1<? super T> handler, final ConnectionAction<T> action) {
- onStartOperation();
-
- executor.execute(new Runnable() {
- public void run() {
- T result;
- try {
- result = action.run();
- } catch (Throwable t) {
- handler.onFailure(t);
- return;
- }
- handler.onComplete(result);
- }
- });
- }
-
- private void onStartOperation() {
- if (closed.get()) {
- throw new IllegalStateException("This connection has been closed.");
- }
- }
-
- private interface ConnectionAction<T> {
- T run();
- }
-}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/async/DefaultAsyncConsumerActionExecutor.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/async/DefaultAsyncConsumerActionExecutor.java
new file mode 100644
index 0000000..47c40f9
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/async/DefaultAsyncConsumerActionExecutor.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.consumer.async;
+
+import org.gradle.internal.CompositeStoppable;
+import org.gradle.internal.concurrent.ExecutorFactory;
+import org.gradle.internal.concurrent.ServiceLifecycle;
+import org.gradle.internal.concurrent.StoppableExecutor;
+import org.gradle.tooling.internal.consumer.connection.ConsumerAction;
+import org.gradle.tooling.internal.consumer.connection.ConsumerActionExecutor;
+import org.gradle.tooling.internal.protocol.ResultHandlerVersion1;
+
+/**
+ * Adapts a {@link ConsumerActionExecutor} to an {@link AsyncConsumerActionExecutor}.
+ */
+public class DefaultAsyncConsumerActionExecutor implements AsyncConsumerActionExecutor {
+ private final ConsumerActionExecutor actionExecutor;
+ private final StoppableExecutor executor;
+ private final ServiceLifecycle lifecycle;
+
+ public DefaultAsyncConsumerActionExecutor(ConsumerActionExecutor actionExecutor, ExecutorFactory executorFactory) {
+ this.actionExecutor = actionExecutor;
+ executor = executorFactory.create("Connection worker");
+ lifecycle = new ServiceLifecycle(actionExecutor.getDisplayName());
+ }
+
+ public String getDisplayName() {
+ return actionExecutor.getDisplayName();
+ }
+
+ public void stop() {
+ CompositeStoppable.stoppable(lifecycle, executor, actionExecutor).stop();
+ }
+
+ public <T> void run(final ConsumerAction<? extends T> action, final ResultHandlerVersion1<? super T> handler) {
+ lifecycle.use(new Runnable() {
+ public void run() {
+ executor.execute(new Runnable() {
+ public void run() {
+ T result;
+ try {
+ result = actionExecutor.run(action);
+ } catch (Throwable t) {
+ handler.onFailure(t);
+ return;
+ }
+ handler.onComplete(result);
+ }
+ });
+ }
+ });
+ }
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/AbstractConsumerConnection.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/AbstractConsumerConnection.java
index ff11944..599ccd9 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/AbstractConsumerConnection.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/AbstractConsumerConnection.java
@@ -16,15 +16,20 @@
package org.gradle.tooling.internal.consumer.connection;
+import org.gradle.tooling.BuildAction;
import org.gradle.tooling.internal.consumer.parameters.ConsumerConnectionParameters;
+import org.gradle.tooling.internal.consumer.parameters.ConsumerOperationParameters;
import org.gradle.tooling.internal.consumer.versioning.VersionDetails;
import org.gradle.tooling.internal.protocol.ConnectionVersion4;
+import org.gradle.tooling.model.internal.Exceptions;
public abstract class AbstractConsumerConnection implements ConsumerConnection {
private final ConnectionVersion4 delegate;
+ private final VersionDetails providerMetaData;
- public AbstractConsumerConnection(ConnectionVersion4 delegate) {
+ public AbstractConsumerConnection(ConnectionVersion4 delegate, VersionDetails providerMetaData) {
this.delegate = delegate;
+ this.providerMetaData = providerMetaData;
}
public void stop() {
@@ -36,7 +41,7 @@ public abstract class AbstractConsumerConnection implements ConsumerConnection {
}
public VersionDetails getVersionDetails() {
- return new VersionDetails(delegate.getMetaData().getVersion());
+ return providerMetaData;
}
public ConnectionVersion4 getDelegate() {
@@ -44,4 +49,8 @@ public abstract class AbstractConsumerConnection implements ConsumerConnection {
}
public abstract void configure(ConsumerConnectionParameters connectionParameters);
+
+ public <T> T run(BuildAction<T> action, ConsumerOperationParameters operationParameters) throws UnsupportedOperationException, IllegalStateException {
+ throw Exceptions.unsupportedFeature("execution of build actions provided by the tooling API client", getVersionDetails().getVersion(), "1.8");
+ }
}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/AbstractPost12ConsumerConnection.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/AbstractPost12ConsumerConnection.java
new file mode 100644
index 0000000..51e0fba
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/AbstractPost12ConsumerConnection.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.consumer.connection;
+
+import org.gradle.tooling.internal.consumer.parameters.ConsumerConnectionParameters;
+import org.gradle.tooling.internal.consumer.versioning.VersionDetails;
+import org.gradle.tooling.internal.protocol.ConfigurableConnection;
+import org.gradle.tooling.internal.protocol.ConnectionVersion4;
+
+/**
+ * An adapter for a post Gradle 1.2 provider.
+ */
+public abstract class AbstractPost12ConsumerConnection extends AbstractConsumerConnection {
+ private final ConfigurableConnection configurableConnection;
+
+ public AbstractPost12ConsumerConnection(ConnectionVersion4 delegate, VersionDetails providerMetaData) {
+ super(delegate, providerMetaData);
+ configurableConnection = (ConfigurableConnection) delegate;
+ }
+
+ public void configure(ConsumerConnectionParameters connectionParameters) {
+ configurableConnection.configure(connectionParameters);
+ }
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/AbstractPre12ConsumerConnection.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/AbstractPre12ConsumerConnection.java
new file mode 100644
index 0000000..7573228
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/AbstractPre12ConsumerConnection.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.consumer.connection;
+
+import org.gradle.tooling.internal.adapter.CompatibleIntrospector;
+import org.gradle.tooling.internal.adapter.ProtocolToModelAdapter;
+import org.gradle.tooling.internal.consumer.converters.PropertyHandlerFactory;
+import org.gradle.tooling.internal.consumer.parameters.ConsumerConnectionParameters;
+import org.gradle.tooling.internal.consumer.parameters.ConsumerOperationParameters;
+import org.gradle.tooling.internal.consumer.versioning.VersionDetails;
+import org.gradle.tooling.internal.protocol.ConnectionVersion4;
+import org.gradle.tooling.model.internal.Exceptions;
+
+/**
+ * An adapter to a pre 1.2 provider.
+ */
+public abstract class AbstractPre12ConsumerConnection extends AbstractConsumerConnection {
+ private final ProtocolToModelAdapter adapter;
+
+ public AbstractPre12ConsumerConnection(ConnectionVersion4 delegate, VersionDetails providerMetaData, ProtocolToModelAdapter adapter) {
+ super(delegate, providerMetaData);
+ this.adapter = adapter;
+ }
+
+ public void configure(ConsumerConnectionParameters connectionParameters) {
+ new CompatibleIntrospector(getDelegate()).callSafely("configureLogging", connectionParameters.getVerboseLogging());
+ }
+
+ public <T> T run(Class<T> type, ConsumerOperationParameters operationParameters) throws UnsupportedOperationException, IllegalStateException {
+ if (type.equals(Void.class)) {
+ doRunBuild(operationParameters);
+ return null;
+ } else {
+ if (operationParameters.getTasks() != null) {
+ throw Exceptions.unsupportedOperationConfiguration("modelBuilder.forTasks()", getVersionDetails().getVersion());
+ }
+
+ Object model = doGetModel(type, operationParameters);
+ return adapter.adapt(type, model, new PropertyHandlerFactory().forVersion(getVersionDetails()));
+ }
+ }
+
+ protected abstract Object doGetModel(Class<?> modelType, ConsumerOperationParameters operationParameters);
+
+ protected void doRunBuild(ConsumerOperationParameters operationParameters) {
+ getDelegate().executeBuild(operationParameters, operationParameters);
+ }
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/ActionAwareConsumerConnection.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/ActionAwareConsumerConnection.java
new file mode 100644
index 0000000..c2c3d1f
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/ActionAwareConsumerConnection.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.consumer.connection;
+
+import org.gradle.tooling.BuildAction;
+import org.gradle.tooling.BuildActionFailureException;
+import org.gradle.tooling.internal.adapter.ProtocolToModelAdapter;
+import org.gradle.tooling.internal.consumer.parameters.ConsumerOperationParameters;
+import org.gradle.tooling.internal.consumer.versioning.ModelMapping;
+import org.gradle.tooling.internal.protocol.*;
+
+public class ActionAwareConsumerConnection extends ModelBuilderBackedConsumerConnection {
+ private final InternalBuildActionExecutor executor;
+
+ public ActionAwareConsumerConnection(ConnectionVersion4 delegate, ModelMapping modelMapping, ProtocolToModelAdapter adapter) {
+ super(delegate, modelMapping, adapter);
+ executor = (InternalBuildActionExecutor) delegate;
+ }
+
+ @Override
+ public <T> T run(final BuildAction<T> action, ConsumerOperationParameters operationParameters) throws UnsupportedOperationException, IllegalStateException {
+ BuildResult<T> result;
+ try {
+ result = executor.run(new BuildActionAdapter<T>(action, adapter), operationParameters);
+ } catch (InternalBuildActionFailureException e) {
+ throw new BuildActionFailureException("The supplied build action failed with an exception.", e.getCause());
+ }
+ return result.getModel();
+ }
+
+ private static class BuildActionAdapter<T> implements InternalBuildAction<T> {
+ private final BuildAction<T> action;
+ private final ProtocolToModelAdapter adapter;
+
+ public BuildActionAdapter(BuildAction<T> action, ProtocolToModelAdapter adapter) {
+ this.action = action;
+ this.adapter = adapter;
+ }
+
+ public T execute(final InternalBuildController buildController) {
+ return action.execute(new BuildControllerAdapter(adapter, buildController, new ModelMapping()));
+ }
+ }
+
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/AdaptedConnection.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/AdaptedConnection.java
deleted file mode 100644
index a14eb28..0000000
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/AdaptedConnection.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.consumer.connection;
-
-import org.gradle.tooling.internal.consumer.parameters.ConsumerConnectionParameters;
-import org.gradle.tooling.internal.consumer.parameters.ConsumerOperationParameters;
-import org.gradle.tooling.internal.protocol.ConnectionVersion4;
-import org.gradle.tooling.internal.reflect.CompatibleIntrospector;
-
-/**
- * An implementation that wraps a protocol instance that has rigid compatibility policy.
- * <p>
- * by Szczepan Faber, created at: 12/22/11
- */
-public class AdaptedConnection extends AbstractConsumerConnection {
-
- public AdaptedConnection(ConnectionVersion4 delegate) {
- super(delegate);
- }
-
- public void configure(ConsumerConnectionParameters connectionParameters) {
- new CompatibleIntrospector(getDelegate()).callSafely("configureLogging", connectionParameters.getVerboseLogging());
- }
-
- public <T> T run(Class<T> type, ConsumerOperationParameters operationParameters) throws UnsupportedOperationException, IllegalStateException {
- if (type.equals(Void.class)) {
- doRunBuild(operationParameters);
- return null;
- } else {
- return doGetModel(type, operationParameters);
- }
- }
-
- protected <T> T doGetModel(Class<T> type, ConsumerOperationParameters operationParameters) {
- return (T) getDelegate().getModel((Class) type, operationParameters);
- }
-
- protected void doRunBuild(ConsumerOperationParameters operationParameters) {
- getDelegate().executeBuild(operationParameters, operationParameters);
- }
-}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/BuildActionRunnerBackedConsumerConnection.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/BuildActionRunnerBackedConsumerConnection.java
index b14db9e..39b6a2c 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/BuildActionRunnerBackedConsumerConnection.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/BuildActionRunnerBackedConsumerConnection.java
@@ -16,25 +16,68 @@
package org.gradle.tooling.internal.consumer.connection;
-import org.gradle.tooling.internal.consumer.parameters.ConsumerConnectionParameters;
+import org.gradle.tooling.internal.adapter.ProtocolToModelAdapter;
import org.gradle.tooling.internal.consumer.parameters.ConsumerOperationParameters;
+import org.gradle.tooling.internal.consumer.versioning.ModelMapping;
+import org.gradle.tooling.internal.consumer.versioning.VersionDetails;
import org.gradle.tooling.internal.protocol.BuildActionRunner;
-import org.gradle.tooling.internal.protocol.ConfigurableConnection;
import org.gradle.tooling.internal.protocol.ConnectionVersion4;
+import org.gradle.tooling.model.GradleProject;
+import org.gradle.tooling.model.build.BuildEnvironment;
+import org.gradle.tooling.model.eclipse.EclipseProject;
+import org.gradle.tooling.model.eclipse.HierarchicalEclipseProject;
+import org.gradle.tooling.model.idea.BasicIdeaProject;
+import org.gradle.tooling.model.idea.IdeaProject;
+import org.gradle.tooling.model.internal.Exceptions;
+import org.gradle.tooling.model.internal.outcomes.ProjectOutcomes;
-public class BuildActionRunnerBackedConsumerConnection extends AbstractConsumerConnection {
+/**
+ * An adapter for a {@link BuildActionRunner} based provider.
+ */
+public class BuildActionRunnerBackedConsumerConnection extends AbstractPost12ConsumerConnection {
private final BuildActionRunner buildActionRunner;
+ private final ModelMapping modelMapping;
+ private final ProtocolToModelAdapter adapter;
- public BuildActionRunnerBackedConsumerConnection(ConnectionVersion4 delegate) {
- super(delegate);
+ public BuildActionRunnerBackedConsumerConnection(ConnectionVersion4 delegate, ModelMapping modelMapping, ProtocolToModelAdapter adapter) {
+ super(delegate, new R12VersionDetails(delegate.getMetaData().getVersion()));
+ this.modelMapping = modelMapping;
+ this.adapter = adapter;
buildActionRunner = (BuildActionRunner) delegate;
}
- public void configure(ConsumerConnectionParameters connectionParameters) {
- ((ConfigurableConnection) buildActionRunner).configure(connectionParameters);
+ public <T> T run(Class<T> type, ConsumerOperationParameters operationParameters) throws UnsupportedOperationException, IllegalStateException {
+ VersionDetails versionDetails = getVersionDetails();
+ if (!versionDetails.isModelSupported(type)) {
+ //don't bother asking the provider for this model
+ throw Exceptions.unsupportedModel(type, versionDetails.getVersion());
+ }
+
+ Class<?> protocolType = modelMapping.getProtocolType(type);
+ Object model = buildActionRunner.run(protocolType, operationParameters).getModel();
+ return adapter.adapt(type, model);
}
- public <T> T run(Class<T> type, ConsumerOperationParameters operationParameters) throws UnsupportedOperationException, IllegalStateException {
- return buildActionRunner.run(type, operationParameters).getModel();
+ private static class R12VersionDetails extends VersionDetails {
+ public R12VersionDetails(String version) {
+ super(version);
+ }
+
+ @Override
+ public boolean supportsGradleProjectModel() {
+ return true;
+ }
+
+ @Override
+ public boolean isModelSupported(Class<?> modelType) {
+ return modelType.equals(ProjectOutcomes.class)
+ || modelType.equals(HierarchicalEclipseProject.class)
+ || modelType.equals(EclipseProject.class)
+ || modelType.equals(IdeaProject.class)
+ || modelType.equals(BasicIdeaProject.class)
+ || modelType.equals(BuildEnvironment.class)
+ || modelType.equals(GradleProject.class)
+ || modelType.equals(Void.class);
+ }
}
}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/BuildControllerAdapter.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/BuildControllerAdapter.java
new file mode 100644
index 0000000..e77afa4
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/BuildControllerAdapter.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.consumer.connection;
+
+import org.gradle.tooling.BuildController;
+import org.gradle.tooling.UnknownModelException;
+import org.gradle.tooling.internal.adapter.ProtocolToModelAdapter;
+import org.gradle.tooling.internal.consumer.versioning.ModelMapping;
+import org.gradle.tooling.internal.protocol.BuildResult;
+import org.gradle.tooling.internal.protocol.InternalBuildController;
+import org.gradle.tooling.internal.protocol.InternalUnsupportedModelException;
+import org.gradle.tooling.internal.protocol.ModelIdentifier;
+import org.gradle.tooling.model.gradle.GradleBuild;
+import org.gradle.tooling.model.Model;
+import org.gradle.tooling.model.internal.Exceptions;
+
+class BuildControllerAdapter implements BuildController {
+ private final InternalBuildController buildController;
+ private final ProtocolToModelAdapter adapter;
+ private final ModelMapping modelMapping;
+
+ public BuildControllerAdapter(ProtocolToModelAdapter adapter, InternalBuildController buildController, ModelMapping modelMapping) {
+ this.adapter = adapter;
+ this.buildController = buildController;
+ this.modelMapping = modelMapping;
+ }
+
+ public <T> T getModel(Class<T> modelType) throws UnknownModelException {
+ return getModel(null, modelType);
+ }
+
+ public <T> T findModel(Class<T> modelType) {
+ try {
+ return getModel(modelType);
+ } catch (UnknownModelException e) {
+ // Ignore
+ return null;
+ }
+ }
+
+ public GradleBuild getBuildModel() {
+ return getModel(null, GradleBuild.class);
+ }
+
+ public <T> T findModel(Model target, Class<T> modelType) {
+ try {
+ return getModel(target, modelType);
+ } catch (UnknownModelException e) {
+ // Ignore
+ return null;
+ }
+ }
+
+ public <T> T getModel(Model target, Class<T> modelType) throws UnknownModelException {
+ ModelIdentifier modelIdentifier = modelMapping.getModelIdentifierFromModelType(modelType);
+ Object originalTarget = target == null ? null : adapter.unpack(target);
+
+ BuildResult<?> result;
+ try {
+ result = buildController.getModel(originalTarget, modelIdentifier);
+ } catch (InternalUnsupportedModelException e) {
+ throw Exceptions.unknownModel(modelType, e);
+ }
+
+ return adapter.adapt(modelType, result.getModel());
+ }
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/ConnectionVersion4BackedConsumerConnection.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/ConnectionVersion4BackedConsumerConnection.java
new file mode 100644
index 0000000..cdcc33f
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/ConnectionVersion4BackedConsumerConnection.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.consumer.connection;
+
+import org.gradle.tooling.internal.adapter.ProtocolToModelAdapter;
+import org.gradle.tooling.internal.build.VersionOnlyBuildEnvironment;
+import org.gradle.tooling.internal.consumer.converters.GradleProjectConverter;
+import org.gradle.tooling.internal.consumer.parameters.ConsumerOperationParameters;
+import org.gradle.tooling.internal.consumer.versioning.ModelMapping;
+import org.gradle.tooling.internal.consumer.versioning.VersionDetails;
+import org.gradle.tooling.internal.protocol.ConnectionVersion4;
+import org.gradle.tooling.internal.protocol.ProjectVersion3;
+import org.gradle.tooling.internal.protocol.eclipse.EclipseProjectVersion3;
+import org.gradle.tooling.model.GradleProject;
+import org.gradle.tooling.model.build.BuildEnvironment;
+import org.gradle.tooling.model.eclipse.EclipseProject;
+import org.gradle.tooling.model.eclipse.HierarchicalEclipseProject;
+import org.gradle.tooling.model.idea.BasicIdeaProject;
+import org.gradle.tooling.model.idea.IdeaProject;
+import org.gradle.tooling.model.internal.Exceptions;
+import org.gradle.util.GradleVersion;
+
+/**
+ * An adapter that wraps a {@link ConnectionVersion4} based provider.
+ */
+public class ConnectionVersion4BackedConsumerConnection extends AbstractPre12ConsumerConnection {
+ private final ModelMapping modelMapping;
+
+ public ConnectionVersion4BackedConsumerConnection(ConnectionVersion4 delegate, ModelMapping modelMapping, ProtocolToModelAdapter adapter) {
+ super(delegate, getMetaData(delegate), adapter);
+ this.modelMapping = modelMapping;
+ }
+
+ private static VersionDetails getMetaData(final ConnectionVersion4 delegate) {
+ GradleVersion version = GradleVersion.version(delegate.getMetaData().getVersion());
+ if (version.compareTo(GradleVersion.version("1.0-milestone-5")) < 0) {
+ return new R10M3VersionDetails(delegate);
+ } else {
+ return new R10M5VersionDetails(delegate);
+ }
+ }
+
+ @Override
+ public <T> T run(Class<T> type, ConsumerOperationParameters operationParameters) throws UnsupportedOperationException, IllegalStateException {
+ VersionDetails versionDetails = getVersionDetails();
+ if (operationParameters.getJavaHome() != null) {
+ throw Exceptions.unsupportedOperationConfiguration("modelBuilder.setJavaHome() and buildLauncher.setJavaHome()", versionDetails.getVersion());
+ }
+ if (operationParameters.getJvmArguments() != null) {
+ throw Exceptions.unsupportedOperationConfiguration("modelBuilder.setJvmArguments() and buildLauncher.setJvmArguments()", versionDetails.getVersion());
+ }
+ if (operationParameters.getStandardInput() != null) {
+ throw Exceptions.unsupportedOperationConfiguration("modelBuilder.setStandardInput() and buildLauncher.setStandardInput()", versionDetails.getVersion());
+ }
+ return super.run(type, operationParameters);
+ }
+
+ @Override
+ protected Object doGetModel(Class<?> modelType, ConsumerOperationParameters operationParameters) {
+ VersionDetails versionDetails = getVersionDetails();
+ if (modelType == BuildEnvironment.class && !versionDetails.isModelSupported(BuildEnvironment.class)) {
+ //early versions of provider do not support BuildEnvironment model
+ //since we know the gradle version at least we can give back some result
+ return new VersionOnlyBuildEnvironment(versionDetails.getVersion());
+ }
+ if (modelType == GradleProject.class && !versionDetails.isModelSupported(GradleProject.class)) {
+ //we broke compatibility around M9 wrt getting the tasks of a project (issue GRADLE-1875)
+ //this patch enables getting gradle tasks for target gradle version pre M5
+ EclipseProjectVersion3 project = (EclipseProjectVersion3) getDelegate().getModel(EclipseProjectVersion3.class, operationParameters);
+ return new GradleProjectConverter().convert(project);
+ }
+ if (!versionDetails.isModelSupported(modelType)) {
+ //don't bother asking the provider for this model
+ throw Exceptions.unsupportedModel(modelType, versionDetails.getVersion());
+ }
+ Class<? extends ProjectVersion3> protocolType = modelMapping.getProtocolType(modelType).asSubclass(ProjectVersion3.class);
+ return getDelegate().getModel(protocolType, operationParameters);
+ }
+
+ private static class R10M3VersionDetails extends VersionDetails {
+ public R10M3VersionDetails(ConnectionVersion4 delegate) {
+ super(delegate.getMetaData().getVersion());
+ }
+
+ @Override
+ public boolean isModelSupported(Class<?> modelType) {
+ return modelType.equals(HierarchicalEclipseProject.class) || modelType.equals(EclipseProject.class) || modelType.equals(Void.class);
+ }
+ }
+
+ private static class R10M5VersionDetails extends VersionDetails {
+ public R10M5VersionDetails(ConnectionVersion4 delegate) {
+ super(delegate.getMetaData().getVersion());
+ }
+
+ @Override
+ public boolean supportsGradleProjectModel() {
+ return true;
+ }
+
+ @Override
+ public boolean isModelSupported(Class<?> modelType) {
+ return modelType.equals(HierarchicalEclipseProject.class)
+ || modelType.equals(EclipseProject.class)
+ || modelType.equals(IdeaProject.class)
+ || modelType.equals(BasicIdeaProject.class)
+ || modelType.equals(GradleProject.class)
+ || modelType.equals(Void.class);
+ }
+ }
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/ConsumerAction.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/ConsumerAction.java
new file mode 100644
index 0000000..47f1764
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/ConsumerAction.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.consumer.connection;
+
+import org.gradle.tooling.internal.consumer.parameters.ConsumerOperationParameters;
+
+public interface ConsumerAction<T> {
+ ConsumerOperationParameters getParameters();
+
+ T run(ConsumerConnection connection);
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/ConsumerActionExecutor.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/ConsumerActionExecutor.java
new file mode 100644
index 0000000..ddc4f06
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/ConsumerActionExecutor.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.consumer.connection;
+
+/**
+ * Implementations must be thread-safe.
+ */
+public interface ConsumerActionExecutor {
+
+ void stop();
+
+ String getDisplayName();
+
+ <T> T run(ConsumerAction<T> action) throws UnsupportedOperationException, IllegalStateException;
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/ConsumerConnection.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/ConsumerConnection.java
index 3a7494e..49ab2b1 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/ConsumerConnection.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/ConsumerConnection.java
@@ -16,19 +16,19 @@
package org.gradle.tooling.internal.consumer.connection;
+import org.gradle.tooling.BuildAction;
import org.gradle.tooling.internal.consumer.parameters.ConsumerOperationParameters;
-import org.gradle.tooling.internal.consumer.versioning.VersionDetails;
/**
- * by Szczepan Faber, created at: 12/22/11
+ * Implementations must be thread-safe.
*/
public interface ConsumerConnection {
void stop();
String getDisplayName();
-
- VersionDetails getVersionDetails();
<T> T run(Class<T> type, ConsumerOperationParameters operationParameters) throws UnsupportedOperationException, IllegalStateException;
+
+ <T> T run(BuildAction<T> action, ConsumerOperationParameters operationParameters) throws UnsupportedOperationException, IllegalStateException;
}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/ConsumerConnectionMetadata.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/ConsumerConnectionMetadata.java
deleted file mode 100644
index cf5d37b..0000000
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/ConsumerConnectionMetadata.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.consumer.connection;
-
-import org.gradle.tooling.internal.consumer.versioning.VersionDetails;
-
-/**
- * by Szczepan Faber, created at: 1/13/12
- */
-public class ConsumerConnectionMetadata {
-
- private final String displayName;
- private final String version;
-
- public ConsumerConnectionMetadata(String displayName, String version) {
- this.displayName = displayName;
- this.version = version;
- }
-
- public String getDisplayName() {
- return displayName;
- }
-
- public VersionDetails getVersionDetails() {
- if (version == null) {
- throw new UnsupportedOperationException();
- }
- return new VersionDetails(version);
- }
-}
\ No newline at end of file
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/InternalConnectionBackedConsumerConnection.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/InternalConnectionBackedConsumerConnection.java
index 26e7b05..e8dbb4f 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/InternalConnectionBackedConsumerConnection.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/InternalConnectionBackedConsumerConnection.java
@@ -16,20 +16,63 @@
package org.gradle.tooling.internal.consumer.connection;
+import org.gradle.tooling.internal.adapter.ProtocolToModelAdapter;
import org.gradle.tooling.internal.consumer.parameters.ConsumerOperationParameters;
+import org.gradle.tooling.internal.consumer.versioning.ModelMapping;
+import org.gradle.tooling.internal.consumer.versioning.VersionDetails;
import org.gradle.tooling.internal.protocol.ConnectionVersion4;
import org.gradle.tooling.internal.protocol.InternalConnection;
+import org.gradle.tooling.model.GradleProject;
+import org.gradle.tooling.model.build.BuildEnvironment;
+import org.gradle.tooling.model.eclipse.EclipseProject;
+import org.gradle.tooling.model.eclipse.HierarchicalEclipseProject;
+import org.gradle.tooling.model.idea.BasicIdeaProject;
+import org.gradle.tooling.model.idea.IdeaProject;
+import org.gradle.tooling.model.internal.Exceptions;
-public class InternalConnectionBackedConsumerConnection extends AdaptedConnection {
+/**
+ * An adapter for a {@link InternalConnection} based provider.
+ */
+public class InternalConnectionBackedConsumerConnection extends AbstractPre12ConsumerConnection {
private final InternalConnection connection;
+ private final ModelMapping modelMapping;
- public InternalConnectionBackedConsumerConnection(ConnectionVersion4 delegate) {
- super(delegate);
+ public InternalConnectionBackedConsumerConnection(ConnectionVersion4 delegate, ModelMapping modelMapping, ProtocolToModelAdapter adapter) {
+ super(delegate, new R10M8VersionDetails(delegate.getMetaData().getVersion()), adapter);
connection = (InternalConnection) delegate;
+ this.modelMapping = modelMapping;
}
@Override
- protected <T> T doGetModel(Class<T> type, ConsumerOperationParameters operationParameters) {
- return connection.getTheModel(type, operationParameters);
+ protected Object doGetModel(Class<?> modelType, ConsumerOperationParameters operationParameters) {
+ VersionDetails versionDetails = getVersionDetails();
+ if (!versionDetails.isModelSupported(modelType)) {
+ //don't bother asking the provider for this model
+ throw Exceptions.unsupportedModel(modelType, versionDetails.getVersion());
+ }
+ Class<?> protocolType = modelMapping.getProtocolType(modelType);
+ return connection.getTheModel(protocolType, operationParameters);
+ }
+
+ private static class R10M8VersionDetails extends VersionDetails {
+ public R10M8VersionDetails(String version) {
+ super(version);
+ }
+
+ @Override
+ public boolean supportsGradleProjectModel() {
+ return true;
+ }
+
+ @Override
+ public boolean isModelSupported(Class<?> modelType) {
+ return modelType.equals(Void.class)
+ || modelType.equals(HierarchicalEclipseProject.class)
+ || modelType.equals(EclipseProject.class)
+ || modelType.equals(IdeaProject.class)
+ || modelType.equals(BasicIdeaProject.class)
+ || modelType.equals(GradleProject.class)
+ || modelType.equals(BuildEnvironment.class);
+ }
}
}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/LazyConnection.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/LazyConnection.java
deleted file mode 100644
index afd99f0..0000000
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/LazyConnection.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.consumer.connection;
-
-import org.gradle.internal.UncheckedException;
-import org.gradle.tooling.internal.consumer.Distribution;
-import org.gradle.tooling.internal.consumer.LoggingProvider;
-import org.gradle.tooling.internal.consumer.ModelProvider;
-import org.gradle.tooling.internal.consumer.loader.ToolingImplementationLoader;
-import org.gradle.tooling.internal.consumer.parameters.ConsumerConnectionParameters;
-import org.gradle.tooling.internal.consumer.parameters.ConsumerOperationParameters;
-import org.gradle.tooling.internal.consumer.versioning.VersionDetails;
-
-import java.util.HashSet;
-import java.util.Set;
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
-
-/**
- * Creates the actual connection implementation on demand.
- */
-public class LazyConnection implements ConsumerConnection {
- private final Distribution distribution;
- private final ToolingImplementationLoader implementationLoader;
- private final LoggingProvider loggingProvider;
-
- private final Lock lock = new ReentrantLock();
- private final Condition condition = lock.newCondition();
- private Set<Thread> executing = new HashSet<Thread>();
- private boolean stopped;
- private ConsumerConnection connection;
-
- ConsumerConnectionParameters connectionParameters;
-
- ModelProvider modelProvider = new ModelProvider();
-
- public LazyConnection(Distribution distribution, ToolingImplementationLoader implementationLoader, LoggingProvider loggingProvider, boolean verboseLogging) {
- this.distribution = distribution;
- this.implementationLoader = implementationLoader;
- this.loggingProvider = loggingProvider;
- this.connectionParameters = new ConsumerConnectionParameters(verboseLogging);
- }
-
- public void stop() {
- ConsumerConnection connection = null;
- lock.lock();
- try {
- stopped = true;
- while (!executing.isEmpty()) {
- try {
- condition.await();
- } catch (InterruptedException e) {
- throw UncheckedException.throwAsUncheckedException(e);
- }
- }
- connection = this.connection;
- this.connection = null;
- } finally {
- lock.unlock();
- }
- if (connection != null) {
- connection.stop();
- }
- }
-
- public ConsumerConnectionMetadata getMetaData() {
- return new ConsumerConnectionMetadata(distribution.getDisplayName(), null);
- }
-
- public String getDisplayName() {
- return distribution.getDisplayName();
- }
-
- public VersionDetails getVersionDetails() {
- if (connection == null) {
- throw new IllegalStateException("Cannot provide version details just yet. You need to execute build or acquire some model first.");
- }
- return connection.getVersionDetails();
- }
-
- public <T> T run(final Class<T> type, final ConsumerOperationParameters operationParameters) {
- return withConnection(new ConnectionAction<T>() {
- public T run(ConsumerConnection connection) {
- return modelProvider.provide(connection, type, operationParameters);
- }
- });
- }
-
- private <T> T withConnection(ConnectionAction<T> action) {
- try {
- ConsumerConnection connection = onStartAction();
- return action.run(connection);
- } finally {
- onEndAction();
- }
- }
-
- private ConsumerConnection onStartAction() {
- lock.lock();
- try {
- if (stopped) {
- throw new IllegalStateException("This connection has been stopped.");
- }
- executing.add(Thread.currentThread());
- if (connection == null) {
- // Hold the lock while creating the connection. Not generally good form.
- // In this instance, blocks other threads from creating the connection at the same time
- connection = implementationLoader.create(distribution, loggingProvider.getProgressLoggerFactory(), connectionParameters);
- }
- return connection;
- } finally {
- lock.unlock();
- }
- }
-
- private void onEndAction() {
- lock.lock();
- try {
- executing.remove(Thread.currentThread());
- condition.signalAll();
- } finally {
- lock.unlock();
- }
- }
-
- private interface ConnectionAction<T> {
- T run(ConsumerConnection connection);
- }
-}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/LazyConsumerActionExecutor.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/LazyConsumerActionExecutor.java
new file mode 100644
index 0000000..cc1349e
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/LazyConsumerActionExecutor.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.consumer.connection;
+
+import org.gradle.internal.UncheckedException;
+import org.gradle.tooling.internal.consumer.Distribution;
+import org.gradle.tooling.internal.consumer.LoggingProvider;
+import org.gradle.tooling.internal.consumer.loader.ToolingImplementationLoader;
+import org.gradle.tooling.internal.consumer.parameters.ConsumerConnectionParameters;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * Creates the actual executor implementation on demand.
+ */
+public class LazyConsumerActionExecutor implements ConsumerActionExecutor {
+ private final Distribution distribution;
+ private final ToolingImplementationLoader implementationLoader;
+ private final LoggingProvider loggingProvider;
+
+ private final Lock lock = new ReentrantLock();
+ private final Condition condition = lock.newCondition();
+ private Set<Thread> executing = new HashSet<Thread>();
+ private boolean stopped;
+ private ConsumerConnection connection;
+
+ ConsumerConnectionParameters connectionParameters;
+
+ public LazyConsumerActionExecutor(Distribution distribution, ToolingImplementationLoader implementationLoader, LoggingProvider loggingProvider, boolean verboseLogging) {
+ this.distribution = distribution;
+ this.implementationLoader = implementationLoader;
+ this.loggingProvider = loggingProvider;
+ this.connectionParameters = new ConsumerConnectionParameters(verboseLogging);
+ }
+
+ public void stop() {
+ ConsumerConnection connection = null;
+ lock.lock();
+ try {
+ stopped = true;
+ while (!executing.isEmpty()) {
+ try {
+ condition.await();
+ } catch (InterruptedException e) {
+ throw UncheckedException.throwAsUncheckedException(e);
+ }
+ }
+ connection = this.connection;
+ this.connection = null;
+ } finally {
+ lock.unlock();
+ }
+ if (connection != null) {
+ connection.stop();
+ }
+ }
+
+ public String getDisplayName() {
+ return distribution.getDisplayName();
+ }
+
+ public <T> T run(ConsumerAction<T> action) throws UnsupportedOperationException, IllegalStateException {
+ try {
+ ConsumerConnection connection = onStartAction();
+ return action.run(connection);
+ } finally {
+ onEndAction();
+ }
+ }
+
+ private ConsumerConnection onStartAction() {
+ lock.lock();
+ try {
+ if (stopped) {
+ throw new IllegalStateException("This connection has been stopped.");
+ }
+ executing.add(Thread.currentThread());
+ if (connection == null) {
+ // Hold the lock while creating the connection. Not generally good form.
+ // In this instance, blocks other threads from creating the connection at the same time
+ connection = implementationLoader.create(distribution, loggingProvider.getProgressLoggerFactory(), connectionParameters);
+ }
+ return connection;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ private void onEndAction() {
+ lock.lock();
+ try {
+ executing.remove(Thread.currentThread());
+ condition.signalAll();
+ } finally {
+ lock.unlock();
+ }
+ }
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/LoggingInitializerConnection.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/LoggingInitializerConnection.java
deleted file mode 100644
index 1090170..0000000
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/LoggingInitializerConnection.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.consumer.connection;
-
-import org.gradle.tooling.internal.consumer.SynchronizedLogging;
-import org.gradle.tooling.internal.consumer.parameters.ConsumerOperationParameters;
-import org.gradle.tooling.internal.consumer.versioning.VersionDetails;
-
-/**
- * The idea is to initialize the logging infrastructure before we actually build the model or run a build.
- * <p>
- * by Szczepan Faber, created at: 12/14/11
- */
-public class LoggingInitializerConnection implements ConsumerConnection {
-
- private final ConsumerConnection connection;
- private final SynchronizedLogging synchronizedLogging;
-
- public LoggingInitializerConnection(ConsumerConnection connection, SynchronizedLogging synchronizedLogging) {
- this.connection = connection;
- this.synchronizedLogging = synchronizedLogging;
- }
-
- public void stop() {
- connection.stop();
- }
-
- public String getDisplayName() {
- return connection.getDisplayName();
- }
-
- public VersionDetails getVersionDetails() {
- return connection.getVersionDetails();
- }
-
- public <T> T run(Class<T> type, ConsumerOperationParameters operationParameters) throws UnsupportedOperationException, IllegalStateException {
- synchronizedLogging.init();
- return connection.run(type, operationParameters);
- }
-}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/LoggingInitializerConsumerActionExecutor.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/LoggingInitializerConsumerActionExecutor.java
new file mode 100644
index 0000000..5483805
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/LoggingInitializerConsumerActionExecutor.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.consumer.connection;
+
+import org.gradle.tooling.internal.consumer.SynchronizedLogging;
+
+/**
+ * The idea is to initialize the logging infrastructure before we actually build the model or run a build.
+ */
+public class LoggingInitializerConsumerActionExecutor implements ConsumerActionExecutor {
+
+ private final ConsumerActionExecutor actionExecutor;
+ private final SynchronizedLogging synchronizedLogging;
+
+ public LoggingInitializerConsumerActionExecutor(ConsumerActionExecutor actionExecutor, SynchronizedLogging synchronizedLogging) {
+ this.actionExecutor = actionExecutor;
+ this.synchronizedLogging = synchronizedLogging;
+ }
+
+ public void stop() {
+ actionExecutor.stop();
+ }
+
+ public String getDisplayName() {
+ return actionExecutor.getDisplayName();
+ }
+
+ public <T> T run(ConsumerAction<T> action) throws UnsupportedOperationException, IllegalStateException {
+ synchronizedLogging.init();
+ return actionExecutor.run(action);
+ }
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/ModelBuilderBackedConsumerConnection.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/ModelBuilderBackedConsumerConnection.java
new file mode 100644
index 0000000..adb588b
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/ModelBuilderBackedConsumerConnection.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.consumer.connection;
+
+import org.gradle.tooling.internal.adapter.ProtocolToModelAdapter;
+import org.gradle.tooling.internal.consumer.parameters.ConsumerOperationParameters;
+import org.gradle.tooling.internal.consumer.versioning.ModelMapping;
+import org.gradle.tooling.internal.consumer.versioning.VersionDetails;
+import org.gradle.tooling.internal.protocol.*;
+import org.gradle.tooling.model.internal.Exceptions;
+
+/**
+ * An adapter for a {@link ModelBuilder} based provider.
+ */
+public class ModelBuilderBackedConsumerConnection extends AbstractPost12ConsumerConnection {
+ private final ModelBuilder builder;
+ private final ModelMapping modelMapping;
+ protected final ProtocolToModelAdapter adapter;
+
+ public ModelBuilderBackedConsumerConnection(ConnectionVersion4 delegate, ModelMapping modelMapping, ProtocolToModelAdapter adapter) {
+ super(delegate, new R16VersionDetails(delegate.getMetaData().getVersion()));
+ this.adapter = adapter;
+ this.modelMapping = modelMapping;
+ builder = (ModelBuilder) delegate;
+ }
+
+ public <T> T run(Class<T> type, ConsumerOperationParameters operationParameters) throws UnsupportedOperationException, IllegalStateException {
+ ModelIdentifier modelIdentifier = modelMapping.getModelIdentifierFromModelType(type);
+ BuildResult<?> result;
+ try {
+ result = builder.getModel(modelIdentifier, operationParameters);
+ } catch (InternalUnsupportedModelException e) {
+ throw Exceptions.unknownModel(type, e);
+ }
+ Object model = result.getModel();
+ return adapter.adapt(type, model);
+ }
+
+ private static class R16VersionDetails extends VersionDetails {
+ public R16VersionDetails(String version) {
+ super(version);
+ }
+
+ @Override
+ public boolean isModelSupported(Class<?> modelType) {
+ return true;
+ }
+
+ @Override
+ public boolean supportsGradleProjectModel() {
+ return true;
+ }
+
+ }
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/NoToolingApiConnection.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/NoToolingApiConnection.java
new file mode 100644
index 0000000..aad5c14
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/NoToolingApiConnection.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.consumer.connection;
+
+import org.gradle.tooling.BuildAction;
+import org.gradle.tooling.UnsupportedVersionException;
+import org.gradle.tooling.internal.consumer.Distribution;
+import org.gradle.tooling.internal.consumer.parameters.ConsumerOperationParameters;
+
+public class NoToolingApiConnection implements ConsumerConnection {
+ private final Distribution distribution;
+
+ public NoToolingApiConnection(Distribution distribution) {
+ this.distribution = distribution;
+ }
+
+ public void stop() {
+ }
+
+ public String getDisplayName() {
+ return distribution.getDisplayName();
+ }
+
+ public <T> T run(Class<T> type, ConsumerOperationParameters operationParameters) throws UnsupportedOperationException, IllegalStateException {
+ throw fail();
+ }
+
+ public <T> T run(BuildAction<T> action, ConsumerOperationParameters operationParameters) throws UnsupportedOperationException, IllegalStateException {
+ throw fail();
+ }
+
+ private UnsupportedVersionException fail() {
+ return new UnsupportedVersionException(String.format("The specified %s does not implement the tooling API. Support for the tooling API was added in Gradle 1.0-milestone-3 and is available in all later versions.", distribution.getDisplayName()));
+ }
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/ProgressLoggingConnection.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/ProgressLoggingConnection.java
deleted file mode 100644
index c60724d..0000000
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/ProgressLoggingConnection.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.consumer.connection;
-
-import org.gradle.listener.ListenerManager;
-import org.gradle.logging.ProgressLogger;
-import org.gradle.logging.internal.ProgressCompleteEvent;
-import org.gradle.logging.internal.ProgressEvent;
-import org.gradle.logging.internal.ProgressListener;
-import org.gradle.logging.internal.ProgressStartEvent;
-import org.gradle.tooling.internal.consumer.LoggingProvider;
-import org.gradle.tooling.internal.consumer.parameters.ConsumerOperationParameters;
-import org.gradle.tooling.internal.consumer.versioning.VersionDetails;
-import org.gradle.tooling.internal.protocol.BuildOperationParametersVersion1;
-import org.gradle.tooling.internal.protocol.ProgressListenerVersion1;
-
-/**
- * Provides some high-level progress information.
- */
-public class ProgressLoggingConnection implements ConsumerConnection {
- private final ConsumerConnection connection;
- private final LoggingProvider loggingProvider;
-
- public ProgressLoggingConnection(ConsumerConnection connection, LoggingProvider loggingProvider) {
- this.connection = connection;
- this.loggingProvider = loggingProvider;
- }
-
- public void stop() {
- connection.stop();
- }
-
- public String getDisplayName() {
- return connection.getDisplayName();
- }
-
- public VersionDetails getVersionDetails() {
- return connection.getVersionDetails();
- }
-
- public <T> T run(final Class<T> type, final ConsumerOperationParameters operationParameters) {
- return run("Build", operationParameters, new BuildAction<T>() {
- public T run(ConsumerConnection connection) {
- return connection.run(type, operationParameters);
- }
- });
- }
-
- private <T> T run(String description, BuildOperationParametersVersion1 parameters, BuildAction<T> action) {
- ProgressListenerAdapter listener = new ProgressListenerAdapter(parameters.getProgressListener());
- ListenerManager listenerManager = loggingProvider.getListenerManager();
- listenerManager.addListener(listener);
- try {
- ProgressLogger progressLogger = loggingProvider.getProgressLoggerFactory().newOperation(ProgressLoggingConnection.class);
- progressLogger.setDescription(description);
- progressLogger.started();
- try {
- return action.run(connection);
- } finally {
- progressLogger.completed();
- }
- } finally {
- listenerManager.removeListener(listener);
- }
- }
-
- private interface BuildAction<T> {
- T run(ConsumerConnection connection);
- }
-
- private static class ProgressListenerAdapter implements ProgressListener {
- private final ProgressListenerVersion1 progressListener;
-
- public ProgressListenerAdapter(ProgressListenerVersion1 progressListener) {
- this.progressListener = progressListener;
- }
-
- public void started(ProgressStartEvent event) {
- progressListener.onOperationStart(event.getDescription());
- }
-
- public void progress(ProgressEvent event) {
- }
-
- public void completed(ProgressCompleteEvent event) {
- progressListener.onOperationEnd();
- }
- }
-}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/ProgressLoggingConsumerActionExecutor.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/ProgressLoggingConsumerActionExecutor.java
new file mode 100644
index 0000000..36e91aa
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/ProgressLoggingConsumerActionExecutor.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.consumer.connection;
+
+import org.gradle.listener.ListenerManager;
+import org.gradle.logging.ProgressLogger;
+import org.gradle.logging.internal.ProgressCompleteEvent;
+import org.gradle.logging.internal.ProgressEvent;
+import org.gradle.logging.internal.ProgressListener;
+import org.gradle.logging.internal.ProgressStartEvent;
+import org.gradle.tooling.internal.consumer.LoggingProvider;
+import org.gradle.tooling.internal.consumer.parameters.ConsumerOperationParameters;
+import org.gradle.tooling.internal.protocol.ProgressListenerVersion1;
+
+/**
+ * Provides some high-level progress information.
+ */
+public class ProgressLoggingConsumerActionExecutor implements ConsumerActionExecutor {
+ private final ConsumerActionExecutor actionExecutor;
+ private final LoggingProvider loggingProvider;
+
+ public ProgressLoggingConsumerActionExecutor(ConsumerActionExecutor actionExecutor, LoggingProvider loggingProvider) {
+ this.actionExecutor = actionExecutor;
+ this.loggingProvider = loggingProvider;
+ }
+
+ public void stop() {
+ actionExecutor.stop();
+ }
+
+ public String getDisplayName() {
+ return actionExecutor.getDisplayName();
+ }
+
+ public <T> T run(ConsumerAction<T> action) throws UnsupportedOperationException, IllegalStateException {
+ ConsumerOperationParameters parameters = action.getParameters();
+ ProgressListenerAdapter listener = new ProgressListenerAdapter(parameters.getProgressListener());
+ ListenerManager listenerManager = loggingProvider.getListenerManager();
+ listenerManager.addListener(listener);
+ try {
+ ProgressLogger progressLogger = loggingProvider.getProgressLoggerFactory().newOperation(ProgressLoggingConsumerActionExecutor.class);
+ progressLogger.setDescription("Build");
+ progressLogger.started();
+ try {
+ return actionExecutor.run(action);
+ } finally {
+ progressLogger.completed();
+ }
+ } finally {
+ listenerManager.removeListener(listener);
+ }
+ }
+
+ private static class ProgressListenerAdapter implements ProgressListener {
+ private final ProgressListenerVersion1 progressListener;
+
+ public ProgressListenerAdapter(ProgressListenerVersion1 progressListener) {
+ this.progressListener = progressListener;
+ }
+
+ public void started(ProgressStartEvent event) {
+ progressListener.onOperationStart(event.getDescription());
+ }
+
+ public void progress(ProgressEvent event) {
+ }
+
+ public void completed(ProgressCompleteEvent event) {
+ progressListener.onOperationEnd();
+ }
+ }
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/converters/ConsumerTargetTypeProvider.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/converters/ConsumerTargetTypeProvider.java
new file mode 100644
index 0000000..1930bff
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/converters/ConsumerTargetTypeProvider.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.consumer.converters;
+
+import org.gradle.tooling.internal.adapter.TargetTypeProvider;
+import org.gradle.tooling.model.idea.IdeaModuleDependency;
+import org.gradle.tooling.model.idea.IdeaSingleEntryLibraryDependency;
+import org.gradle.tooling.model.internal.outcomes.GradleFileBuildOutcome;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class ConsumerTargetTypeProvider implements TargetTypeProvider {
+
+ Map<String, Class<?>> configuredTargetTypes = new HashMap<String, Class<?>>();
+
+ public ConsumerTargetTypeProvider() {
+ configuredTargetTypes.put(IdeaSingleEntryLibraryDependency.class.getCanonicalName(), IdeaSingleEntryLibraryDependency.class);
+ configuredTargetTypes.put(IdeaModuleDependency.class.getCanonicalName(), IdeaModuleDependency.class);
+ configuredTargetTypes.put(GradleFileBuildOutcome.class.getCanonicalName(), GradleFileBuildOutcome.class);
+ }
+
+ public <T> Class<? extends T> getTargetType(Class<T> initialTargetType, Object protocolObject) {
+ Class<?>[] interfaces = protocolObject.getClass().getInterfaces();
+ for (Class<?> i : interfaces) {
+ if (configuredTargetTypes.containsKey(i.getName())) {
+ return configuredTargetTypes.get(i.getName()).asSubclass(initialTargetType);
+ }
+ }
+
+ return initialTargetType;
+ }
+}
\ No newline at end of file
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/converters/GradleProjectConverter.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/converters/GradleProjectConverter.java
index 18f50da..eb37838 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/converters/GradleProjectConverter.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/converters/GradleProjectConverter.java
@@ -25,9 +25,6 @@ import org.gradle.tooling.model.GradleTask;
import java.util.LinkedList;
import java.util.List;
-/**
- * by Szczepan Faber, created at: 3/27/12
- */
public class GradleProjectConverter {
public DefaultGradleProject convert(EclipseProjectVersion3 project) {
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/converters/GradleProjectMixInHandler.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/converters/GradleProjectMixInHandler.java
new file mode 100644
index 0000000..36b326a
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/converters/GradleProjectMixInHandler.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.consumer.converters;
+
+import org.gradle.tooling.internal.adapter.MethodInvocation;
+import org.gradle.tooling.internal.adapter.MethodInvoker;
+import org.gradle.tooling.internal.protocol.eclipse.EclipseProjectVersion3;
+
+public class GradleProjectMixInHandler implements MethodInvoker {
+ public void invoke(MethodInvocation invocation) throws Throwable {
+ if (invocation.getName().equals("getGradleProject")
+ && invocation.getDelegate() instanceof EclipseProjectVersion3) {
+ invocation.setResult(new GradleProjectConverter().convert((EclipseProjectVersion3) invocation.getDelegate()));
+ }
+ }
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/converters/PropertyHandlerFactory.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/converters/PropertyHandlerFactory.java
new file mode 100644
index 0000000..8ed687b
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/converters/PropertyHandlerFactory.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.consumer.converters;
+
+import org.gradle.api.Action;
+import org.gradle.tooling.internal.adapter.SourceObjectMapping;
+import org.gradle.tooling.internal.consumer.versioning.VersionDetails;
+import org.gradle.tooling.model.eclipse.EclipseProject;
+
+import java.io.Serializable;
+
+public class PropertyHandlerFactory {
+ public Action<SourceObjectMapping> forVersion(VersionDetails versionDetails) {
+ return new ConsumerMapping(versionDetails);
+ }
+
+ private static class ConsumerMapping implements Action<SourceObjectMapping>, Serializable {
+ private final VersionDetails versionDetails;
+
+ public ConsumerMapping(VersionDetails versionDetails) {
+ this.versionDetails = versionDetails;
+ }
+
+ public void execute(SourceObjectMapping mapping) {
+ if (EclipseProject.class.isAssignableFrom(mapping.getTargetType()) && !versionDetails.supportsGradleProjectModel()) {
+ mapping.mixIn(new GradleProjectMixInHandler());
+ }
+ }
+ }
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/loader/DefaultToolingImplementationLoader.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/loader/DefaultToolingImplementationLoader.java
index 2050e04..76ce903 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/loader/DefaultToolingImplementationLoader.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/loader/DefaultToolingImplementationLoader.java
@@ -16,26 +16,24 @@
package org.gradle.tooling.internal.consumer.loader;
import org.gradle.internal.Factory;
+import org.gradle.internal.classloader.FilteringClassLoader;
+import org.gradle.internal.classloader.MultiParentClassLoader;
+import org.gradle.internal.classloader.MutableURLClassLoader;
import org.gradle.internal.classpath.ClassPath;
import org.gradle.internal.service.ServiceLocator;
import org.gradle.logging.ProgressLoggerFactory;
import org.gradle.tooling.GradleConnectionException;
import org.gradle.tooling.UnsupportedVersionException;
+import org.gradle.tooling.internal.adapter.ProtocolToModelAdapter;
import org.gradle.tooling.internal.consumer.Distribution;
import org.gradle.tooling.internal.consumer.connection.*;
+import org.gradle.tooling.internal.consumer.converters.ConsumerTargetTypeProvider;
import org.gradle.tooling.internal.consumer.parameters.ConsumerConnectionParameters;
-import org.gradle.tooling.internal.protocol.BuildActionRunner;
-import org.gradle.tooling.internal.protocol.ConnectionVersion4;
-import org.gradle.tooling.internal.protocol.InternalConnection;
-import org.gradle.util.FilteringClassLoader;
-import org.gradle.util.GradleVersion;
-import org.gradle.util.MutableURLClassLoader;
+import org.gradle.tooling.internal.consumer.versioning.ModelMapping;
+import org.gradle.tooling.internal.protocol.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
public class DefaultToolingImplementationLoader implements ToolingImplementationLoader {
private static final Logger LOGGER = LoggerFactory.getLogger(DefaultToolingImplementationLoader.class);
private final ClassLoader classLoader;
@@ -55,22 +53,26 @@ public class DefaultToolingImplementationLoader implements ToolingImplementation
try {
Factory<ConnectionVersion4> factory = serviceLocator.findFactory(ConnectionVersion4.class);
if (factory == null) {
- Matcher m = Pattern.compile("\\w+Version(\\d+)").matcher(ConnectionVersion4.class.getSimpleName());
- m.matches();
- String protocolVersion = m.group(1);
- throw new UnsupportedVersionException(String.format("The specified %s is not supported by this tooling API version (%s, protocol version %s)", distribution.getDisplayName(), GradleVersion.current().getVersion(), protocolVersion));
+ return new NoToolingApiConnection(distribution);
}
// ConnectionVersion4 is a part of the protocol and cannot be easily changed.
ConnectionVersion4 connection = factory.create();
+ ProtocolToModelAdapter adapter = new ProtocolToModelAdapter(new ConsumerTargetTypeProvider());
+ ModelMapping modelMapping = new ModelMapping();
+
// Adopting the connection to a refactoring friendly type that the consumer owns
AbstractConsumerConnection adaptedConnection;
- if (connection instanceof BuildActionRunner) {
- adaptedConnection = new BuildActionRunnerBackedConsumerConnection(connection);
+ if (connection instanceof ModelBuilder && connection instanceof InternalBuildActionExecutor) {
+ adaptedConnection = new ActionAwareConsumerConnection(connection, modelMapping, adapter);
+ } else if (connection instanceof ModelBuilder) {
+ adaptedConnection = new ModelBuilderBackedConsumerConnection(connection, modelMapping, adapter);
+ } else if (connection instanceof BuildActionRunner) {
+ adaptedConnection = new BuildActionRunnerBackedConsumerConnection(connection, modelMapping, adapter);
} else if (connection instanceof InternalConnection) {
- adaptedConnection = new InternalConnectionBackedConsumerConnection(connection);
+ adaptedConnection = new InternalConnectionBackedConsumerConnection(connection, modelMapping, adapter);
} else {
- adaptedConnection = new AdaptedConnection(connection);
+ adaptedConnection = new ConnectionVersion4BackedConsumerConnection(connection, modelMapping, adapter);
}
adaptedConnection.configure(connectionParameters);
return adaptedConnection;
@@ -84,7 +86,11 @@ public class DefaultToolingImplementationLoader implements ToolingImplementation
private ClassLoader createImplementationClassLoader(Distribution distribution, ProgressLoggerFactory progressLoggerFactory) {
ClassPath implementationClasspath = distribution.getToolingImplementationClasspath(progressLoggerFactory);
LOGGER.debug("Using tooling provider classpath: {}", implementationClasspath);
- FilteringClassLoader filteringClassLoader = new FilteringClassLoader(classLoader);
+ // On IBM JVM 5, ClassLoader.getResources() uses a combination of findResources() and getParent() and traverses the hierarchy rather than just calling getResources()
+ // Wrap our real classloader in one that hides the parent.
+ // TODO - move this into FilteringClassLoader
+ MultiParentClassLoader parentObfuscatingClassLoader = new MultiParentClassLoader(classLoader);
+ FilteringClassLoader filteringClassLoader = new FilteringClassLoader(parentObfuscatingClassLoader);
filteringClassLoader.allowPackage("org.gradle.tooling.internal.protocol");
return new MutableURLClassLoader(filteringClassLoader, implementationClasspath.getAsURLArray());
}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/loader/SynchronizedToolingImplementationLoader.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/loader/SynchronizedToolingImplementationLoader.java
index 2bbb0fc..0ee0de7 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/loader/SynchronizedToolingImplementationLoader.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/loader/SynchronizedToolingImplementationLoader.java
@@ -25,9 +25,6 @@ import org.gradle.tooling.internal.consumer.parameters.ConsumerConnectionParamet
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
-/**
- * by Szczepan Faber, created at: 12/6/11
- */
public class SynchronizedToolingImplementationLoader implements ToolingImplementationLoader {
Lock lock = new ReentrantLock();
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/parameters/ConsumerOperationParameters.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/parameters/ConsumerOperationParameters.java
index f3c84ad..34f51f0 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/parameters/ConsumerOperationParameters.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/parameters/ConsumerOperationParameters.java
@@ -30,9 +30,7 @@ import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
-/**
- * by Szczepan Faber, created at: 1/9/12
- */
+// TODO:ADAM - Need to make an immutable copy before passing to connection
public class ConsumerOperationParameters implements BuildOperationParametersVersion1, BuildParametersVersion1, BuildParameters {
private final ProgressListenerAdapter progressListener = new ProgressListenerAdapter();
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/protocoladapter/ConsumerPropertyHandler.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/protocoladapter/ConsumerPropertyHandler.java
deleted file mode 100644
index 996ac73..0000000
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/protocoladapter/ConsumerPropertyHandler.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.consumer.protocoladapter;
-
-import org.gradle.tooling.internal.consumer.converters.GradleProjectConverter;
-import org.gradle.tooling.internal.consumer.versioning.VersionDetails;
-import org.gradle.tooling.internal.protocol.eclipse.EclipseProjectVersion3;
-
-/**
- * by Szczepan Faber, created at: 4/2/12
- */
-public class ConsumerPropertyHandler implements MethodInvoker {
-
- private final VersionDetails versionDetails;
-
- public ConsumerPropertyHandler(VersionDetails versionDetails) {
- this.versionDetails = versionDetails;
- }
-
- public void invoke(MethodInvocation invocation) throws Throwable {
- if (invocation.getName().equals("getGradleProject")
- && invocation.getDelegate() instanceof EclipseProjectVersion3
- && !versionDetails.supportsGradleProjectModel()) {
- invocation.setResult(new GradleProjectConverter().convert((EclipseProjectVersion3) invocation.getDelegate()));
- }
- }
-}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/protocoladapter/MethodInvocation.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/protocoladapter/MethodInvocation.java
deleted file mode 100644
index c223d38..0000000
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/protocoladapter/MethodInvocation.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.consumer.protocoladapter;
-
-import java.lang.reflect.Type;
-
-public class MethodInvocation {
- private final Object[] parameters;
- private final Class returnType;
- private final Type genericReturnType;
- private final String name;
- private final Class<?>[] parameterTypes;
- private Object result;
- private boolean found;
- private Object delegate;
-
- MethodInvocation(String name, Class returnType, Type genericReturnType, Class<?>[] parameterTypes, Object delegate, Object[] parameters) {
- this.name = name;
- this.returnType = returnType;
- this.genericReturnType = genericReturnType;
- this.parameterTypes = parameterTypes;
- this.delegate = delegate;
- this.parameters = parameters;
- }
-
- public Object[] getParameters() {
- return parameters;
- }
-
- public Class getReturnType() {
- return returnType;
- }
-
- public Type getGenericReturnType() {
- return genericReturnType;
- }
-
- public void setResult(Object result) {
- found = true;
- this.result = result;
- }
-
- public Object getResult() {
- return result;
- }
-
- public String getName() {
- return name;
- }
-
- public Class<?>[] getParameterTypes() {
- return parameterTypes;
- }
-
- public boolean found() {
- return found;
- }
-
- public Object getDelegate() {
- return delegate;
- }
-}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/protocoladapter/MethodInvoker.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/protocoladapter/MethodInvoker.java
deleted file mode 100644
index 2e4a473..0000000
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/protocoladapter/MethodInvoker.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.consumer.protocoladapter;
-
-public interface MethodInvoker {
- void invoke(MethodInvocation invocation) throws Throwable;
-}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/protocoladapter/ProtocolToModelAdapter.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/protocoladapter/ProtocolToModelAdapter.java
deleted file mode 100644
index 2428939..0000000
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/protocoladapter/ProtocolToModelAdapter.java
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.consumer.protocoladapter;
-
-import org.gradle.internal.UncheckedException;
-import org.gradle.internal.reflect.DirectInstantiator;
-import org.gradle.tooling.model.DomainObjectSet;
-import org.gradle.tooling.model.internal.Exceptions;
-import org.gradle.tooling.model.internal.ImmutableDomainObjectSet;
-
-import java.lang.reflect.*;
-import java.util.*;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Adapts some source object to some target type.
- */
-public class ProtocolToModelAdapter {
- private static final MethodInvoker NO_OP_HANDLER = new MethodInvoker() {
- public void invoke(MethodInvocation invocation) throws Throwable {
- }
- };
- private static final Object[] EMPTY = new Object[0];
- private static final Pattern IS_SUPPORT_METHOD = Pattern.compile("is(\\w+)Supported");
- private static final Pattern GETTER_METHOD = Pattern.compile("get(\\w+)");
- private static final Pattern IS_METHOD = Pattern.compile("is(\\w+)");
- private final TargetTypeProvider targetTypeProvider = new TargetTypeProvider();
-
- public <T, S> T adapt(Class<T> targetType, S protocolObject) {
- return adapt(targetType, protocolObject, NO_OP_HANDLER);
- }
-
- public <T, S> T adapt(Class<T> targetType, S protocolObject, MethodInvoker overrideMethodInvoker) {
- Class<T> target = targetTypeProvider.getTargetType(targetType, protocolObject);
- if (target.isInstance(protocolObject)) {
- return target.cast(protocolObject);
- }
- Object proxy = Proxy.newProxyInstance(target.getClassLoader(), new Class<?>[]{target}, new InvocationHandlerImpl(protocolObject, overrideMethodInvoker));
- return target.cast(proxy);
- }
-
- /**
- * Adapts the source object.
- *
- * @param mixInClass A bean that provides implementations for methods of the target type. If this bean implements the given method, it is preferred over the source object's implementation.
- */
- public <T, S> T adapt(Class<T> targetType, S protocolObject, Class<?> mixInClass) {
- MixInMethodInvoker mixInMethodInvoker = new MixInMethodInvoker(mixInClass, new ReflectionMethodInvoker(NO_OP_HANDLER));
- T proxy = adapt(targetType, protocolObject, mixInMethodInvoker);
- mixInMethodInvoker.setProxy(proxy);
- return proxy;
- }
-
- private class InvocationHandlerImpl implements InvocationHandler {
- private final Object delegate;
- private final Method equalsMethod;
- private final Method hashCodeMethod;
- private final MethodInvoker invoker;
-
- public InvocationHandlerImpl(Object delegate, MethodInvoker overrideMethodInvoker) {
- this.delegate = delegate;
- invoker = new SupportedPropertyInvoker(
- new SafeMethodInvoker(
- new PropertyCachingMethodInvoker(
- new ChainedMethodInvoker(
- overrideMethodInvoker,
- new ReflectionMethodInvoker(overrideMethodInvoker)))));
- try {
- equalsMethod = Object.class.getMethod("equals", Object.class);
- hashCodeMethod = Object.class.getMethod("hashCode");
- } catch (NoSuchMethodException e) {
- throw UncheckedException.throwAsUncheckedException(e);
- }
- }
-
- @Override
- public boolean equals(Object o) {
- if (o == this) {
- return true;
- }
- if (o == null || o.getClass() != getClass()) {
- return false;
- }
-
- InvocationHandlerImpl other = (InvocationHandlerImpl) o;
- return delegate.equals(other.delegate);
- }
-
- @Override
- public int hashCode() {
- return delegate.hashCode();
- }
-
- public Object invoke(Object target, Method method, Object[] params) throws Throwable {
- if (method.equals(equalsMethod)) {
- Object param = params[0];
- if (param == null || !Proxy.isProxyClass(param.getClass())) {
- return false;
- }
- InvocationHandler other = Proxy.getInvocationHandler(param);
- return equals(other);
- } else if (method.equals(hashCodeMethod)) {
- return hashCode();
- }
-
- MethodInvocation invocation = new MethodInvocation(method.getName(), method.getReturnType(), method.getGenericReturnType(), method.getParameterTypes(), delegate, params);
- invoker.invoke(invocation);
- if (!invocation.found()) {
- String methodName = method.getDeclaringClass().getSimpleName() + "." + method.getName() + "()";
- throw Exceptions.unsupportedMethod(methodName);
- }
- return invocation.getResult();
- }
- }
-
- private static class ChainedMethodInvoker implements MethodInvoker {
- private final MethodInvoker[] invokers;
-
- private ChainedMethodInvoker(MethodInvoker... invokers) {
- this.invokers = invokers;
- }
-
- public void invoke(MethodInvocation method) throws Throwable {
- for (int i = 0; !method.found() && i < invokers.length; i++) {
- MethodInvoker invoker = invokers[i];
- invoker.invoke(method);
- }
- }
- }
-
- private class ReflectionMethodInvoker implements MethodInvoker {
- private final MethodInvoker override;
-
- private ReflectionMethodInvoker(MethodInvoker override) {
- this.override = override;
- }
-
- public void invoke(MethodInvocation invocation) throws Throwable {
- // TODO - cache method lookup
- Method targetMethod = locateMethod(invocation);
- if (targetMethod == null) {
- return;
- }
-
- Object returnValue;
- try {
- returnValue = targetMethod.invoke(invocation.getDelegate(), invocation.getParameters());
- } catch (InvocationTargetException e) {
- throw e.getCause();
- }
-
- if (returnValue == null || invocation.getReturnType().isInstance(returnValue)) {
- invocation.setResult(returnValue);
- return;
- }
-
- invocation.setResult(convert(returnValue, invocation.getGenericReturnType()));
- }
-
- private Method locateMethod(MethodInvocation invocation) {
- Class<?> sourceClass = invocation.getDelegate().getClass();
- Method match;
- try {
- match = sourceClass.getMethod(invocation.getName(), invocation.getParameterTypes());
- } catch (NoSuchMethodException e) {
- return null;
- }
-
- LinkedList<Class<?>> queue = new LinkedList<Class<?>>();
- queue.add(sourceClass);
- while (!queue.isEmpty()) {
- Class<?> c = queue.removeFirst();
- try {
- match = c.getMethod(invocation.getName(), invocation.getParameterTypes());
- } catch (NoSuchMethodException e) {
- // ignore
- }
- for (Class<?> interfaceType : c.getInterfaces()) {
- queue.addFirst(interfaceType);
- }
- if (c.getSuperclass() != null) {
- queue.addFirst(c.getSuperclass());
- }
- }
- match.setAccessible(true);
- return match;
- }
-
- private Object convert(Object value, Type targetType) {
- if (targetType instanceof ParameterizedType) {
- ParameterizedType parameterizedTargetType = (ParameterizedType) targetType;
- if (parameterizedTargetType.getRawType().equals(DomainObjectSet.class)) {
- Type targetElementType = getElementType(parameterizedTargetType);
- List<Object> convertedElements = new ArrayList<Object>();
- for (Object element : (Iterable) value) {
- convertedElements.add(convert(element, targetElementType));
- }
- return new ImmutableDomainObjectSet(convertedElements);
- }
- }
- if (targetType instanceof Class) {
- if (((Class) targetType).isPrimitive()) {
- return value;
- }
- return adapt((Class) targetType, value, override);
- }
- throw new UnsupportedOperationException(String.format("Cannot convert object of %s to %s.", value.getClass(), targetType));
- }
-
- private Type getElementType(ParameterizedType type) {
- Type elementType = type.getActualTypeArguments()[0];
- if (elementType instanceof WildcardType) {
- WildcardType wildcardType = (WildcardType) elementType;
- return wildcardType.getUpperBounds()[0];
- }
- return elementType;
- }
- }
-
- private static class PropertyCachingMethodInvoker implements MethodInvoker {
- private final Map<String, Object> properties = new HashMap<String, Object>();
- private final Set<String> unknown = new HashSet<String>();
- private final MethodInvoker next;
-
- private PropertyCachingMethodInvoker(MethodInvoker next) {
- this.next = next;
- }
-
- public void invoke(MethodInvocation method) throws Throwable {
- if ((GETTER_METHOD.matcher(method.getName()).matches() || IS_METHOD.matcher(method.getName()).matches()) && method.getParameterTypes().length == 0) {
- if (properties.containsKey(method.getName())) {
- method.setResult(properties.get(method.getName()));
- return;
- }
- if (unknown.contains(method.getName())) {
- return;
- }
-
- Object value;
- next.invoke(method);
- if (!method.found()) {
- unknown.add(method.getName());
- return;
- }
- value = method.getResult();
- properties.put(method.getName(), value);
- return;
- }
-
- next.invoke(method);
- }
- }
-
- private static class SafeMethodInvoker implements MethodInvoker {
- private final MethodInvoker next;
-
- private SafeMethodInvoker(MethodInvoker next) {
- this.next = next;
- }
-
- public void invoke(MethodInvocation invocation) throws Throwable {
- next.invoke(invocation);
- if (invocation.found()) {
- return;
- }
-
- boolean getter = GETTER_METHOD.matcher(invocation.getName()).matches();
- if (!getter || invocation.getParameterTypes().length != 1) {
- return;
- }
-
- MethodInvocation getterInvocation = new MethodInvocation(invocation.getName(), invocation.getReturnType(), invocation.getGenericReturnType(), new Class[0], invocation.getDelegate(), EMPTY);
- next.invoke(getterInvocation);
- if (getterInvocation.found() && getterInvocation.getResult() != null) {
- invocation.setResult(getterInvocation.getResult());
- } else {
- invocation.setResult(invocation.getParameters()[0]);
- }
- }
- }
-
- private static class SupportedPropertyInvoker implements MethodInvoker {
- private final MethodInvoker next;
-
- private SupportedPropertyInvoker(MethodInvoker next) {
- this.next = next;
- }
-
- public void invoke(MethodInvocation invocation) throws Throwable {
- Matcher matcher = IS_SUPPORT_METHOD.matcher(invocation.getName());
- if (!matcher.matches()) {
- next.invoke(invocation);
- return;
- }
-
- String getterName = String.format("get%s", matcher.group(1));
- MethodInvocation getterInvocation = new MethodInvocation(getterName, invocation.getReturnType(), invocation.getGenericReturnType(), new Class[0], invocation.getDelegate(), EMPTY);
- next.invoke(getterInvocation);
- invocation.setResult(getterInvocation.found());
- }
- }
-
- private static class MixInMethodInvoker implements MethodInvoker {
- private Object proxy;
- private Object instance;
- private final Class<?> mixInClass;
- private final MethodInvoker next;
- private final ThreadLocal<MethodInvocation> current = new ThreadLocal<MethodInvocation>();
-
- public MixInMethodInvoker(Class<?> mixInClass, MethodInvoker next) {
- this.mixInClass = mixInClass;
- this.next = next;
- }
-
- public void invoke(MethodInvocation invocation) throws Throwable {
- if (current.get() != null) {
- // Already invoking a method on the mix-in
- return;
- }
-
- if (instance == null) {
- instance = new DirectInstantiator().newInstance(mixInClass, proxy);
- }
- MethodInvocation beanInvocation = new MethodInvocation(invocation.getName(), invocation.getReturnType(), invocation.getGenericReturnType(), invocation.getParameterTypes(), instance, invocation.getParameters());
- current.set(beanInvocation);
- try {
- next.invoke(beanInvocation);
- } finally {
- current.set(null);
- }
- if (beanInvocation.found()) {
- invocation.setResult(beanInvocation.getResult());
- }
- }
-
- public void setProxy(Object proxy) {
- this.proxy = proxy;
- }
-
- public Object getProxy() {
- return proxy;
- }
- }
-}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/protocoladapter/TargetTypeProvider.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/protocoladapter/TargetTypeProvider.java
deleted file mode 100644
index 95e5be6..0000000
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/protocoladapter/TargetTypeProvider.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.consumer.protocoladapter;
-
-import org.gradle.tooling.model.idea.IdeaModuleDependency;
-import org.gradle.tooling.model.idea.IdeaSingleEntryLibraryDependency;
-import org.gradle.tooling.model.internal.outcomes.GradleFileBuildOutcome;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * by Szczepan Faber, created at: 4/2/12
- */
-public class TargetTypeProvider {
-
- Map<String, Class<?>> configuredTargetTypes = new HashMap<String, Class<?>>();
-
- public TargetTypeProvider() {
- configuredTargetTypes.put(IdeaSingleEntryLibraryDependency.class.getCanonicalName(), IdeaSingleEntryLibraryDependency.class);
- configuredTargetTypes.put(IdeaModuleDependency.class.getCanonicalName(), IdeaModuleDependency.class);
- configuredTargetTypes.put(GradleFileBuildOutcome.class.getCanonicalName(), GradleFileBuildOutcome.class);
- }
-
- /**
- * Occasionally we want to use preconfigured target type instead of passed target type.
- *
- * @param initialTargetType
- * @param protocolObject
- */
- public <T, S> Class<T> getTargetType(Class<T> initialTargetType, S protocolObject) {
- Class<?>[] interfaces = protocolObject.getClass().getInterfaces();
- for (Class<?> i : interfaces) {
- if (configuredTargetTypes.containsKey(i.getName())) {
- return (Class<T>) configuredTargetTypes.get(i.getName());
- }
- }
-
- return initialTargetType;
- }
-}
\ No newline at end of file
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/versioning/ModelMapping.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/versioning/ModelMapping.java
index 024cc26..eac9e6f 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/versioning/ModelMapping.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/versioning/ModelMapping.java
@@ -16,52 +16,130 @@
package org.gradle.tooling.internal.consumer.versioning;
+import com.google.common.collect.BiMap;
+import com.google.common.collect.HashBiMap;
+import org.gradle.api.Nullable;
import org.gradle.tooling.internal.protocol.*;
import org.gradle.tooling.internal.protocol.eclipse.EclipseProjectVersion3;
import org.gradle.tooling.internal.protocol.eclipse.HierarchicalEclipseProjectVersion1;
-import org.gradle.tooling.model.*;
+import org.gradle.tooling.model.gradle.GradleBuild;
+import org.gradle.tooling.model.GradleProject;
import org.gradle.tooling.model.build.BuildEnvironment;
import org.gradle.tooling.model.eclipse.EclipseProject;
import org.gradle.tooling.model.eclipse.HierarchicalEclipseProject;
import org.gradle.tooling.model.idea.BasicIdeaProject;
import org.gradle.tooling.model.idea.IdeaProject;
-import org.gradle.tooling.model.internal.TestModel;
import org.gradle.tooling.model.internal.outcomes.ProjectOutcomes;
import java.util.HashMap;
import java.util.Map;
-/**
- * by Szczepan Faber, created at: 1/13/12
- */
public class ModelMapping {
-
- private static final Map<Class<? extends Model>, Class> MODEL_TYPE_MAP = new HashMap<Class<? extends Model>, Class>();
+ private static final BiMap<Class<?>, Class<?>> MODEL_TO_PROTOCOL_MAP = HashBiMap.create();
+ private static final BiMap<Class<?>, String> MODEL_NAME_MAP = HashBiMap.create();
+ private static final Map<Class<?>, String> MODEL_VERSIONS = new HashMap<Class<?>, String>();
static {
- MODEL_TYPE_MAP.putAll(getModelsUpToM6());
- MODEL_TYPE_MAP.putAll(getModelsPostM6());
+ addModelToProtocolMappings(MODEL_TO_PROTOCOL_MAP);
+ addModelNameMappings(MODEL_NAME_MAP);
+ addModelVersions(MODEL_VERSIONS);
+ }
+
+ private static void addModelVersions(Map<Class<?>, String> map) {
+ map.put(HierarchicalEclipseProject.class, "1.0-milestone-3");
+ map.put(EclipseProject.class, "1.0-milestone-3");
+ map.put(IdeaProject.class, "1.0-milestone-5");
+ map.put(GradleProject.class, "1.0-milestone-5");
+ map.put(BasicIdeaProject.class, "1.0-milestone-5");
+ map.put(BuildEnvironment.class, "1.0-milestone-8");
+ map.put(ProjectOutcomes.class, "1.2");
+ map.put(Void.class, "1.0-milestone-3");
+ map.put(GradleBuild.class, "1.8");
}
- static Map<Class<? extends Model>, Class> getModelsUpToM6() {
- Map<Class<? extends Model>, Class> map = new HashMap<Class<? extends Model>, Class>();
+ static void addModelToProtocolMappings(Map<Class<?>, Class<?>> map) {
map.put(HierarchicalEclipseProject.class, HierarchicalEclipseProjectVersion1.class);
map.put(EclipseProject.class, EclipseProjectVersion3.class);
map.put(IdeaProject.class, InternalIdeaProject.class);
map.put(GradleProject.class, InternalGradleProject.class);
map.put(BasicIdeaProject.class, InternalBasicIdeaProject.class);
- return map;
- }
-
- private static Map<Class<? extends Model>, Class> getModelsPostM6() {
- Map<Class<? extends Model>, Class> map = new HashMap<Class<? extends Model>, Class>();
map.put(BuildEnvironment.class, InternalBuildEnvironment.class);
- map.put(TestModel.class, InternalTestModel.class);
map.put(ProjectOutcomes.class, InternalProjectOutcomes.class);
- return map;
+ map.put(Void.class, Void.class);
+ }
+
+ static void addModelNameMappings(Map<Class<?>, String> map) {
+ map.put(HierarchicalEclipseProject.class, "org.gradle.tooling.model.eclipse.HierarchicalEclipseProject");
+ map.put(EclipseProject.class, "org.gradle.tooling.model.eclipse.EclipseProject");
+ map.put(IdeaProject.class, "org.gradle.tooling.model.idea.IdeaProject");
+ map.put(GradleProject.class, "org.gradle.tooling.model.GradleProject");
+ map.put(BasicIdeaProject.class, "org.gradle.tooling.model.idea.BasicIdeaProject");
+ map.put(BuildEnvironment.class, "org.gradle.tooling.model.build.BuildEnvironment");
+ map.put(ProjectOutcomes.class, "org.gradle.tooling.model.outcomes.ProjectOutcomes");
+ map.put(Void.class, Void.class.getName());
+ }
+
+ public ModelIdentifier getModelIdentifierFromModelType(final Class<?> modelType) {
+ if (modelType.equals(Void.class)) {
+ return new DefaultModelIdentifier(ModelIdentifier.NULL_MODEL);
+ }
+ String modelName = getModelName(modelType);
+ if (modelName != null) {
+ return new DefaultModelIdentifier(modelName);
+ }
+ return new DefaultModelIdentifier(modelType.getName());
+ }
+
+ @Nullable
+ public Class<?> getProtocolType(Class<?> modelType) {
+ if (MODEL_TO_PROTOCOL_MAP.containsValue(modelType)) {
+ return modelType;
+ }
+ return MODEL_TO_PROTOCOL_MAP.get(modelType);
}
- public Class getInternalType(Class<? extends Model> viewType) {
- return MODEL_TYPE_MAP.get(viewType);
+ @Nullable
+ public String getModelName(Class<?> modelType) {
+ return MODEL_NAME_MAP.get(modelType);
+ }
+
+ @Nullable
+ public String getModelNameFromProtocolType(Class<?> protocolType) {
+ Class<?> modelType = MODEL_TO_PROTOCOL_MAP.inverse().get(protocolType);
+ if (modelType == null) {
+ return null;
+ }
+ return MODEL_NAME_MAP.get(modelType);
+ }
+
+ @Nullable
+ public Class<?> getProtocolTypeFromModelName(String name) {
+ Class<?> modelType = MODEL_NAME_MAP.inverse().get(name);
+ if (modelType == null) {
+ return null;
+ }
+ return getProtocolType(modelType);
+ }
+
+ @Nullable
+ public String getVersionAdded(Class<?> modelType) {
+ return MODEL_VERSIONS.get(modelType);
+ }
+
+ private static class DefaultModelIdentifier implements ModelIdentifier {
+ private final String model;
+
+ public DefaultModelIdentifier(String model) {
+ this.model = model;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("tooling model %s", model);
+ }
+
+ public String getName() {
+ return model;
+ }
}
}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/versioning/VersionDetails.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/versioning/VersionDetails.java
index 9c644ff..4a903c9 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/versioning/VersionDetails.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/versioning/VersionDetails.java
@@ -16,56 +16,26 @@
package org.gradle.tooling.internal.consumer.versioning;
-import org.gradle.util.GradleVersion;
-
-/**
- * by Szczepan Faber, created at: 1/13/12
- */
-public class VersionDetails {
-
- private final GradleVersion gradleVersion;
- private static final GradleVersion M5 = GradleVersion.version("1.0-milestone-5");
- private static final GradleVersion M6 = GradleVersion.version("1.0-milestone-6");
- private static final GradleVersion M7 = GradleVersion.version("1.0-milestone-7");
- private static final GradleVersion V1_1 = GradleVersion.version("1.1");
+public abstract class VersionDetails {
+ private final String providerVersion;
public VersionDetails(String version) {
- gradleVersion = GradleVersion.version(version);
+ providerVersion = version;
}
public String getVersion() {
- return gradleVersion.getVersion();
- }
-
- public boolean supportsCompleteBuildEnvironment() {
- return gradleVersion.compareTo(M7) > 0;
- }
-
- public boolean clientHangsOnEarlyDaemonFailure() {
- return gradleVersion.equals(M5) || gradleVersion.equals(M6);
- }
-
- public boolean isPostM6Model(Class<?> internalModelType) {
- return !ModelMapping.getModelsUpToM6().containsValue(internalModelType) && internalModelType != Void.class;
- }
-
- public boolean supportsConfiguringJavaHome() {
- return gradleVersion.compareTo(M7) > 0;
- }
-
- public boolean supportsConfiguringJvmArguments() {
- return gradleVersion.compareTo(M7) > 0;
- }
-
- public boolean supportsConfiguringStandardInput() {
- return gradleVersion.compareTo(M7) > 0;
+ return providerVersion;
}
- public boolean supportsRunningTasksWhenBuildingModel() {
- return gradleVersion.compareTo(V1_1) > 0;
+ /**
+ * Returns true if this provider may support the given model type. Returns false if it is known that the
+ * provider does not support the given model type and <em>should not</em> be asked to provide it.
+ */
+ public boolean isModelSupported(Class<?> modelType) {
+ return false;
}
public boolean supportsGradleProjectModel() {
- return gradleVersion.compareTo(M5) >= 0;
+ return false;
}
}
\ No newline at end of file
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/eclipse/DefaultEclipseExternalDependency.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/eclipse/DefaultEclipseExternalDependency.java
deleted file mode 100644
index 0f1067c..0000000
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/eclipse/DefaultEclipseExternalDependency.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.eclipse;
-
-import org.gradle.api.artifacts.ModuleVersionIdentifier;
-import org.gradle.tooling.internal.gradle.DefaultGradleModuleVersion;
-import org.gradle.tooling.internal.protocol.ExternalDependencyVersion1;
-import org.gradle.tooling.model.GradleModuleVersion;
-
-import java.io.File;
-import java.io.Serializable;
-
-public class DefaultEclipseExternalDependency implements ExternalDependencyVersion1, Serializable {
- private final File file;
- private final File javadoc;
- private final File source;
- private final GradleModuleVersion moduleVersion;
-
- public DefaultEclipseExternalDependency(File file, File javadoc, File source, ModuleVersionIdentifier identifier) {
- this.file = file;
- this.javadoc = javadoc;
- this.source = source;
- moduleVersion = (identifier == null)? null : new DefaultGradleModuleVersion(identifier);
- }
-
- public File getFile() {
- return file;
- }
-
- public File getJavadoc() {
- return javadoc;
- }
-
- public File getSource() {
- return source;
- }
-
- public GradleModuleVersion getGradleModuleVersion() {
- return moduleVersion;
- }
-}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/eclipse/DefaultEclipseLinkedResource.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/eclipse/DefaultEclipseLinkedResource.java
deleted file mode 100644
index d50f281..0000000
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/eclipse/DefaultEclipseLinkedResource.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.eclipse;
-
-import org.gradle.tooling.internal.protocol.eclipse.EclipseLinkedResourceVersion1;
-
-import java.io.Serializable;
-
-/**
- * @author: Szczepan Faber, created at: 6/11/11
- */
-public class DefaultEclipseLinkedResource implements Serializable, EclipseLinkedResourceVersion1 {
-
- private String name;
- private String type;
- private String location;
- private String locationUri;
-
- public DefaultEclipseLinkedResource(String name, String type, String location, String locationUri) {
- this.name = name;
- this.type = type;
- this.location = location;
- this.locationUri = locationUri;
- }
-
- public String getName() {
- return name;
- }
-
- public String getType() {
- return type;
- }
-
- public String getLocation() {
- return location;
- }
-
- public String getLocationUri() {
- return locationUri;
- }
-}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/eclipse/DefaultEclipseProject.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/eclipse/DefaultEclipseProject.java
deleted file mode 100644
index 9a0e141..0000000
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/eclipse/DefaultEclipseProject.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.eclipse;
-
-import com.google.common.collect.Lists;
-import org.gradle.tooling.internal.protocol.ExternalDependencyVersion1;
-import org.gradle.tooling.internal.protocol.eclipse.*;
-import org.gradle.tooling.model.GradleProject;
-
-import java.io.File;
-import java.io.Serializable;
-import java.util.Collections;
-import java.util.List;
-
-public class DefaultEclipseProject implements EclipseProjectVersion3, Serializable {
- private final String name;
- private final String path;
- private EclipseProjectVersion3 parent;
- private List<ExternalDependencyVersion1> classpath;
- private final List<EclipseProjectVersion3> children;
- private List<EclipseSourceDirectoryVersion1> sourceDirectories;
- private List<EclipseProjectDependencyVersion2> projectDependencies;
- private final String description;
- private final File projectDirectory;
- private Iterable<? extends EclipseTaskVersion1> tasks;
- private Iterable<? extends EclipseLinkedResourceVersion1> linkedResources;
- private GradleProject gradleProject;
-
- public DefaultEclipseProject(String name, String path, String description, File projectDirectory, Iterable<? extends EclipseProjectVersion3> children) {
- this.name = name;
- this.path = path;
- this.description = description;
- this.projectDirectory = projectDirectory;
- this.tasks = Collections.emptyList();
- this.children = Lists.newArrayList(children);
- this.classpath = Collections.emptyList();
- this.sourceDirectories = Collections.emptyList();
- this.projectDependencies = Collections.emptyList();
- }
-
- @Override
- public String toString() {
- return String.format("project '%s'", path);
- }
-
- public String getPath() {
- return path;
- }
-
- public String getName() {
- return name;
- }
-
- public String getDescription() {
- return description;
- }
-
- public EclipseProjectVersion3 getParent() {
- return parent;
- }
-
- public File getProjectDirectory() {
- return projectDirectory;
- }
-
- public void setParent(EclipseProjectVersion3 parent) {
- this.parent = parent;
- }
-
- public List<EclipseProjectVersion3> getChildren() {
- return children;
- }
-
- public Iterable<? extends EclipseSourceDirectoryVersion1> getSourceDirectories() {
- return sourceDirectories;
- }
-
- public void setSourceDirectories(List<EclipseSourceDirectoryVersion1> sourceDirectories) {
- this.sourceDirectories = sourceDirectories;
- }
-
- public Iterable<? extends EclipseProjectDependencyVersion2> getProjectDependencies() {
- return projectDependencies;
- }
-
- public void setProjectDependencies(List<EclipseProjectDependencyVersion2> projectDependencies) {
- this.projectDependencies = projectDependencies;
- }
-
- public List<ExternalDependencyVersion1> getClasspath() {
- return classpath;
- }
- public void setClasspath(List<ExternalDependencyVersion1> classpath) {
- this.classpath = classpath;
- }
-
- public Iterable<? extends EclipseTaskVersion1> getTasks() {
- return tasks;
- }
-
- public void setTasks(Iterable<? extends EclipseTaskVersion1> tasks) {
- this.tasks = tasks;
- }
-
- public Iterable<? extends EclipseLinkedResourceVersion1> getLinkedResources() {
- return linkedResources;
- }
-
- public void setLinkedResources(Iterable<? extends EclipseLinkedResourceVersion1> linkedResources) {
- this.linkedResources = linkedResources;
- }
-
- public GradleProject getGradleProject() {
- return gradleProject;
- }
-
- public DefaultEclipseProject setGradleProject(GradleProject gradleProject) {
- this.gradleProject = gradleProject;
- return this;
- }
-}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/eclipse/DefaultEclipseProjectDependency.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/eclipse/DefaultEclipseProjectDependency.java
deleted file mode 100644
index 6a97814..0000000
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/eclipse/DefaultEclipseProjectDependency.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.eclipse;
-
-import org.gradle.tooling.internal.protocol.eclipse.EclipseProjectDependencyVersion2;
-import org.gradle.tooling.internal.protocol.eclipse.HierarchicalEclipseProjectVersion1;
-
-import java.io.Serializable;
-
-public class DefaultEclipseProjectDependency implements EclipseProjectDependencyVersion2, Serializable {
- private final String path;
- private final HierarchicalEclipseProjectVersion1 target;
-
- public DefaultEclipseProjectDependency(String path, HierarchicalEclipseProjectVersion1 target) {
- this.target = target;
- this.path = path;
- }
-
- public HierarchicalEclipseProjectVersion1 getTargetProject() {
- return target;
- }
-
- public String getPath() {
- return path;
- }
-
- @Override
- public String toString() {
- return String.format("project dependency %s (%s)", path, target);
- }
-}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/eclipse/DefaultEclipseSourceDirectory.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/eclipse/DefaultEclipseSourceDirectory.java
deleted file mode 100644
index 4d5939e..0000000
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/eclipse/DefaultEclipseSourceDirectory.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.eclipse;
-
-import org.gradle.tooling.internal.protocol.eclipse.EclipseSourceDirectoryVersion1;
-
-import java.io.File;
-import java.io.Serializable;
-
-public class DefaultEclipseSourceDirectory implements EclipseSourceDirectoryVersion1, Serializable {
- private final String path;
- private final File directory;
-
- public DefaultEclipseSourceDirectory(String path, File directory) {
- this.path = path;
- this.directory = directory;
- }
-
- @Override
- public String toString() {
- return String.format("source directory '%s'", path);
- }
-
- public File getDirectory() {
- return directory;
- }
-
- public String getPath() {
- return path;
- }
-}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/eclipse/DefaultEclipseTask.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/eclipse/DefaultEclipseTask.java
deleted file mode 100644
index d00db49..0000000
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/eclipse/DefaultEclipseTask.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.eclipse;
-
-import org.gradle.tooling.internal.protocol.eclipse.EclipseProjectVersion3;
-import org.gradle.tooling.internal.protocol.eclipse.EclipseTaskVersion1;
-
-import java.io.Serializable;
-
-public class DefaultEclipseTask implements EclipseTaskVersion1, Serializable {
- private final EclipseProjectVersion3 project;
- private final String path;
- private final String name;
- private final String description;
-
- public DefaultEclipseTask(EclipseProjectVersion3 project, String path, String name, String description) {
- this.project = project;
- this.path = path;
- this.name = name;
- this.description = description;
- }
-
- @Override
- public String toString() {
- return String.format("task '%s'", path);
- }
-
- public EclipseProjectVersion3 getProject() {
- return project;
- }
-
- public String getPath() {
- return path;
- }
-
- public String getName() {
- return name;
- }
-
- public String getDescription() {
- return description;
- }
-}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/gradle/BasicGradleProject.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/gradle/BasicGradleProject.java
new file mode 100644
index 0000000..109af01
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/gradle/BasicGradleProject.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.gradle;
+
+import java.io.File;
+import java.io.Serializable;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+public class BasicGradleProject implements Serializable, GradleProjectIdentity {
+ private String name;
+ private String path;
+ private File projectDirectory;
+ private BasicGradleProject parent;
+ private Set<BasicGradleProject> children = new LinkedHashSet<BasicGradleProject>();
+
+ @Override
+ public String toString() {
+ return "GradleProject{path='" + path + "\'}";
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public BasicGradleProject setPath(String path) {
+ this.path = path;
+ return this;
+ }
+
+ public BasicGradleProject getParent() {
+ return parent;
+ }
+
+ public BasicGradleProject setParent(BasicGradleProject parent) {
+ this.parent = parent;
+ return this;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public BasicGradleProject setName(String name) {
+ this.name = name;
+ return this;
+ }
+
+ public File getProjectDirectory() {
+ return projectDirectory;
+ }
+
+ public BasicGradleProject setProjectDirectory(File projectDirectory) {
+ this.projectDirectory = projectDirectory;
+ return this;
+ }
+
+ public Set<? extends BasicGradleProject> getChildren() {
+ return children;
+ }
+
+ public BasicGradleProject addChild(BasicGradleProject child) {
+ children.add(child);
+ return this;
+ }
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/gradle/DefaultGradleBuild.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/gradle/DefaultGradleBuild.java
new file mode 100644
index 0000000..be4dd88
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/gradle/DefaultGradleBuild.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.gradle;
+
+import java.io.Serializable;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+public class DefaultGradleBuild implements Serializable {
+ private BasicGradleProject rootProject;
+ private Set<BasicGradleProject> projects = new LinkedHashSet<BasicGradleProject>();
+
+ public BasicGradleProject getRootProject() {
+ return rootProject;
+ }
+
+ public DefaultGradleBuild setRootProject(BasicGradleProject rootProject) {
+ this.rootProject = rootProject;
+ return this;
+ }
+
+ public Set<? extends BasicGradleProject> getProjects() {
+ return projects;
+ }
+
+ public void addProject(BasicGradleProject project) {
+ projects.add(project);
+ }
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/gradle/DefaultGradleModuleVersion.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/gradle/DefaultGradleModuleVersion.java
index 203bb56..fb9e43b 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/gradle/DefaultGradleModuleVersion.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/gradle/DefaultGradleModuleVersion.java
@@ -21,9 +21,6 @@ import org.gradle.tooling.model.GradleModuleVersion;
import java.io.Serializable;
-/**
- * by Szczepan Faber, created at: 5/11/12
- */
public class DefaultGradleModuleVersion implements GradleModuleVersion, Serializable {
private final String group;
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/gradle/DefaultGradleProject.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/gradle/DefaultGradleProject.java
index 34db911..cfb9e6e 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/gradle/DefaultGradleProject.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/gradle/DefaultGradleProject.java
@@ -16,7 +16,7 @@
package org.gradle.tooling.internal.gradle;
-import org.gradle.tooling.internal.protocol.ProjectVersion3;
+import org.gradle.tooling.internal.protocol.InternalGradleProject;
import org.gradle.tooling.model.DomainObjectSet;
import org.gradle.tooling.model.GradleProject;
import org.gradle.tooling.model.GradleTask;
@@ -27,10 +27,7 @@ import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;
-/**
- * @author: Szczepan Faber, created at: 7/27/11
- */
-public class DefaultGradleProject implements ProjectVersion3, GradleProject, Serializable {
+public class DefaultGradleProject implements InternalGradleProject, GradleProject, Serializable, GradleProjectIdentity {
private String name;
private String description;
@@ -38,6 +35,7 @@ public class DefaultGradleProject implements ProjectVersion3, GradleProject, Ser
private GradleProject parent;
private List<? extends GradleProject> children = new LinkedList<GradleProject>();
private List<GradleTask> tasks = new LinkedList<GradleTask>();
+ private DefaultGradleScript buildScript = new DefaultGradleScript();
public DefaultGradleProject() {}
@@ -117,6 +115,10 @@ public class DefaultGradleProject implements ProjectVersion3, GradleProject, Ser
return null;
}
+ public DefaultGradleScript getBuildScript() {
+ return buildScript;
+ }
+
public String toString() {
return "GradleProject{"
+ "path='" + path + '\''
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/gradle/DefaultGradleScript.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/gradle/DefaultGradleScript.java
new file mode 100644
index 0000000..51ddbcd
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/gradle/DefaultGradleScript.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.gradle;
+
+import org.gradle.tooling.model.gradle.GradleScript;
+
+import java.io.File;
+import java.io.Serializable;
+
+public class DefaultGradleScript implements GradleScript, Serializable {
+ private File sourceFile;
+
+ public File getSourceFile() {
+ return sourceFile;
+ }
+
+ public void setSourceFile(File sourceFile) {
+ this.sourceFile = sourceFile;
+ }
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/gradle/DefaultGradleTask.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/gradle/DefaultGradleTask.java
index bf0c39e..d105be5 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/gradle/DefaultGradleTask.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/gradle/DefaultGradleTask.java
@@ -21,9 +21,6 @@ import org.gradle.tooling.model.GradleTask;
import java.io.Serializable;
-/**
- * @author: Szczepan Faber, created at: 7/27/11
- */
public class DefaultGradleTask implements GradleTask, Serializable {
String path;
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/gradle/GradleProjectIdentity.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/gradle/GradleProjectIdentity.java
new file mode 100644
index 0000000..c5e9021
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/gradle/GradleProjectIdentity.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.gradle;
+
+public interface GradleProjectIdentity {
+ String getPath();
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/idea/DefaultIdeaCompilerOutput.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/idea/DefaultIdeaCompilerOutput.java
deleted file mode 100644
index e7d9856..0000000
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/idea/DefaultIdeaCompilerOutput.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.idea;
-
-import org.gradle.tooling.model.idea.IdeaCompilerOutput;
-
-import java.io.File;
-import java.io.Serializable;
-
-/**
- * @author: Szczepan Faber, created at: 8/5/11
- */
-public class DefaultIdeaCompilerOutput implements IdeaCompilerOutput, Serializable {
-
- private boolean inheritOutputDirs;
- private File outputDir;
- private File testOutputDir;
-
- public boolean getInheritOutputDirs() {
- return inheritOutputDirs;
- }
-
- public DefaultIdeaCompilerOutput setInheritOutputDirs(boolean inheritOutputDirs) {
- this.inheritOutputDirs = inheritOutputDirs;
- return this;
- }
-
- public File getOutputDir() {
- return outputDir;
- }
-
- public DefaultIdeaCompilerOutput setOutputDir(File outputDir) {
- this.outputDir = outputDir;
- return this;
- }
-
- public File getTestOutputDir() {
- return testOutputDir;
- }
-
- public DefaultIdeaCompilerOutput setTestOutputDir(File testOutputDir) {
- this.testOutputDir = testOutputDir;
- return this;
- }
-
- @Override
- public String toString() {
- return "IdeaCompilerOutput{"
- + "inheritOutputDirs=" + inheritOutputDirs
- + ", outputDir=" + outputDir
- + ", testOutputDir=" + testOutputDir
- + '}';
- }
-}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/idea/DefaultIdeaContentRoot.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/idea/DefaultIdeaContentRoot.java
deleted file mode 100644
index 6620ee5..0000000
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/idea/DefaultIdeaContentRoot.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.idea;
-
-import org.gradle.tooling.model.DomainObjectSet;
-import org.gradle.tooling.model.idea.IdeaContentRoot;
-import org.gradle.tooling.model.idea.IdeaSourceDirectory;
-import org.gradle.tooling.model.internal.ImmutableDomainObjectSet;
-
-import java.io.File;
-import java.io.Serializable;
-import java.util.LinkedHashSet;
-import java.util.Set;
-
-/**
- * @author: Szczepan Faber, created at: 8/3/11
- */
-public class DefaultIdeaContentRoot implements IdeaContentRoot, Serializable {
-
- File rootDirectory;
- Set<IdeaSourceDirectory> sourceDirectories = new LinkedHashSet<IdeaSourceDirectory>();
- Set<IdeaSourceDirectory> testDirectories = new LinkedHashSet<IdeaSourceDirectory>();
- Set<File> excludeDirectories = new LinkedHashSet<File>();
-
- public File getRootDirectory() {
- return rootDirectory;
- }
-
- public DefaultIdeaContentRoot setRootDirectory(File rootDirectory) {
- this.rootDirectory = rootDirectory;
- return this;
- }
-
- public DomainObjectSet<IdeaSourceDirectory> getSourceDirectories() {
- return new ImmutableDomainObjectSet<IdeaSourceDirectory>(sourceDirectories);
- }
-
- public DefaultIdeaContentRoot setSourceDirectories(Set<IdeaSourceDirectory> sourceDirectories) {
- this.sourceDirectories = sourceDirectories;
- return this;
- }
-
- public DomainObjectSet<IdeaSourceDirectory> getTestDirectories() {
- return new ImmutableDomainObjectSet<IdeaSourceDirectory>(testDirectories);
- }
-
- public DefaultIdeaContentRoot setTestDirectories(Set<IdeaSourceDirectory> testDirectories) {
- this.testDirectories = testDirectories;
- return this;
- }
-
- public Set<File> getExcludeDirectories() {
- return excludeDirectories;
- }
-
- public DefaultIdeaContentRoot setExcludeDirectories(Set<File> excludeDirectories) {
- this.excludeDirectories = excludeDirectories;
- return this;
- }
-
- public String toString() {
- return "IdeaContentRoot{"
- + "rootDirectory=" + rootDirectory
- + ", sourceDirectories count=" + sourceDirectories.size()
- + ", testDirectories count=" + testDirectories.size()
- + ", excludeDirectories count=" + excludeDirectories.size()
- + '}';
- }
-}
\ No newline at end of file
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/idea/DefaultIdeaDependencyScope.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/idea/DefaultIdeaDependencyScope.java
deleted file mode 100644
index 815e4d2..0000000
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/idea/DefaultIdeaDependencyScope.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.idea;
-
-import org.gradle.tooling.model.idea.IdeaDependencyScope;
-
-import java.io.Serializable;
-
-/**
- * @author: Szczepan Faber, created at: 8/3/11
- */
-public class DefaultIdeaDependencyScope implements IdeaDependencyScope, Serializable {
-
- String scope;
-
- public DefaultIdeaDependencyScope(String scope) {
- this.scope = scope;
- }
-
- public String getScope() {
- return scope;
- }
-
- @Override
- public String toString() {
- return "IdeaDependencyScope{"
- + "scope='" + scope + '\''
- + '}';
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (!(o instanceof DefaultIdeaDependencyScope)) {
- return false;
- }
-
- DefaultIdeaDependencyScope that = (DefaultIdeaDependencyScope) o;
-
- if (scope != null ? !scope.equals(that.scope) : that.scope != null) {
- return false;
- }
-
- return true;
- }
-
- @Override
- public int hashCode() {
- return scope != null ? scope.hashCode() : 0;
- }
-}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/idea/DefaultIdeaLanguageLevel.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/idea/DefaultIdeaLanguageLevel.java
deleted file mode 100644
index fa0313a..0000000
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/idea/DefaultIdeaLanguageLevel.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.idea;
-
-import org.gradle.tooling.model.idea.IdeaLanguageLevel;
-
-import java.io.Serializable;
-
-/**
- * @author: Szczepan Faber, created at: 7/30/11
- */
-public class DefaultIdeaLanguageLevel implements IdeaLanguageLevel, Serializable {
-
- private final String level;
-
- public DefaultIdeaLanguageLevel(String level) {
- this.level = level;
- }
-
- public boolean isJDK_1_4() {
- return "JDK_1_4".equals(level);
- }
-
- public boolean isJDK_1_5() {
- return "JDK_1_5".equals(level);
- }
-
- public boolean isJDK_1_6() {
- return "JDK_1_6".equals(level);
- }
-
- public boolean isJDK_1_7() {
- return "JDK_1_7".equals(level);
- }
-
- public boolean isJDK_1_8() {
- return "JDK_1_8".equals(level);
- }
-
- public String getLevel() {
- return level;
- }
-
- @Override
- public String toString() {
- return "IdeaLanguageLevel{level='" + level + "'}";
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (!(o instanceof DefaultIdeaLanguageLevel)) {
- return false;
- }
-
- DefaultIdeaLanguageLevel that = (DefaultIdeaLanguageLevel) o;
-
- if (level != null ? !level.equals(that.level) : that.level != null) {
- return false;
- }
-
- return true;
- }
-
- @Override
- public int hashCode() {
- return level != null ? level.hashCode() : 0;
- }
-}
\ No newline at end of file
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/idea/DefaultIdeaModule.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/idea/DefaultIdeaModule.java
deleted file mode 100644
index aaf5dfe..0000000
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/idea/DefaultIdeaModule.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.idea;
-
-import org.gradle.tooling.model.DomainObjectSet;
-import org.gradle.tooling.model.GradleProject;
-import org.gradle.tooling.model.HierarchicalElement;
-import org.gradle.tooling.model.Task;
-import org.gradle.tooling.model.idea.*;
-import org.gradle.tooling.model.internal.ImmutableDomainObjectSet;
-
-import java.io.Serializable;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * @author: Szczepan Faber, created at: 7/25/11
- */
-public class DefaultIdeaModule implements Serializable, IdeaModule {
-
- private String name;
- private List<? extends IdeaContentRoot> contentRoots = new LinkedList<IdeaContentRoot>();
- private IdeaProject parent;
-
- private List<IdeaDependency> dependencies = new LinkedList<IdeaDependency>();
- private GradleProject gradleProject;
-
- private IdeaCompilerOutput compilerOutput;
-
- public String getName() {
- return name;
- }
-
- public DefaultIdeaModule setName(String name) {
- this.name = name;
- return this;
- }
-
- public DomainObjectSet<? extends IdeaContentRoot> getContentRoots() {
- return new ImmutableDomainObjectSet<IdeaContentRoot>(contentRoots);
- }
-
- public DefaultIdeaModule setContentRoots(List<? extends IdeaContentRoot> contentRoots) {
- this.contentRoots = contentRoots;
- return this;
- }
-
- public IdeaProject getParent() {
- return parent;
- }
-
- public IdeaProject getProject() {
- return parent;
- }
-
- public DefaultIdeaModule setParent(IdeaProject parent) {
- this.parent = parent;
- return this;
- }
-
- public DomainObjectSet<IdeaDependency> getDependencies() {
- return new ImmutableDomainObjectSet<IdeaDependency>(dependencies);
- }
-
- public DefaultIdeaModule setDependencies(List<IdeaDependency> dependencies) {
- this.dependencies = dependencies;
- return this;
- }
-
- public DomainObjectSet<? extends Task> getTasks() {
- throw new RuntimeException("not yet implemented");
- }
-
- public DomainObjectSet<? extends HierarchicalElement> getChildren() {
- return new ImmutableDomainObjectSet<HierarchicalElement>(Collections.<HierarchicalElement>emptySet());
- }
-
- public String getDescription() {
- return null;
- }
-
- public GradleProject getGradleProject() {
- return gradleProject;
- }
-
- public DefaultIdeaModule setGradleProject(GradleProject gradleProject) {
- this.gradleProject = gradleProject;
- return this;
- }
-
- public IdeaCompilerOutput getCompilerOutput() {
- return compilerOutput;
- }
-
- public DefaultIdeaModule setCompilerOutput(IdeaCompilerOutput compilerOutput) {
- this.compilerOutput = compilerOutput;
- return this;
- }
-
- @Override
- public String toString() {
- return "IdeaModule{"
- + "name='" + name + '\''
- + ", gradleProject='" + gradleProject + '\''
- + ", contentRoots=" + contentRoots
- + ", compilerOutput=" + compilerOutput
- + ", dependencies count=" + dependencies.size()
- + '}';
- }
-}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/idea/DefaultIdeaModuleDependency.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/idea/DefaultIdeaModuleDependency.java
deleted file mode 100644
index f77ed76..0000000
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/idea/DefaultIdeaModuleDependency.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.idea;
-
-import org.gradle.tooling.model.idea.IdeaDependencyScope;
-import org.gradle.tooling.model.idea.IdeaModule;
-import org.gradle.tooling.model.idea.IdeaModuleDependency;
-
-import java.io.Serializable;
-
-/**
- * @author: Szczepan Faber, created at: 7/26/11
- */
-public class DefaultIdeaModuleDependency implements IdeaModuleDependency, Serializable {
-
- private IdeaDependencyScope scope;
- private IdeaModule dependencyModule;
- private boolean exported;
-
- public IdeaDependencyScope getScope() {
- return scope;
- }
-
- public DefaultIdeaModuleDependency setScope(IdeaDependencyScope scope) {
- this.scope = scope;
- return this;
- }
-
- public IdeaModule getDependencyModule() {
- return dependencyModule;
- }
-
- public DefaultIdeaModuleDependency setDependencyModule(IdeaModule dependencyModule) {
- this.dependencyModule = dependencyModule;
- return this;
- }
-
- public boolean getExported() {
- return exported;
- }
-
- public DefaultIdeaModuleDependency setExported(boolean exported) {
- this.exported = exported;
- return this;
- }
-
- @Override
- public String toString() {
- return "DefaultIdeaModuleDependency{"
- + "scope='" + scope + '\''
- + ", dependencyModule name='" + dependencyModule.getName() + '\''
- + ", exported=" + exported
- + '}';
- }
-}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/idea/DefaultIdeaProject.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/idea/DefaultIdeaProject.java
deleted file mode 100644
index 8afa04c..0000000
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/idea/DefaultIdeaProject.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.idea;
-
-import org.gradle.tooling.internal.protocol.InternalIdeaProject;
-import org.gradle.tooling.model.DomainObjectSet;
-import org.gradle.tooling.model.HierarchicalElement;
-import org.gradle.tooling.model.idea.IdeaLanguageLevel;
-import org.gradle.tooling.model.idea.IdeaModule;
-import org.gradle.tooling.model.idea.IdeaProject;
-import org.gradle.tooling.model.internal.ImmutableDomainObjectSet;
-
-import java.io.File;
-import java.io.Serializable;
-import java.util.Collection;
-import java.util.LinkedList;
-
-/**
- * @author: Szczepan Faber, created at: 7/25/11
- */
-public class DefaultIdeaProject implements InternalIdeaProject, IdeaProject, Serializable {
-
-// public static final long serialVersionUID = 1L;
-
- private String id;
- private String name;
- private String description;
- private Collection<? extends IdeaModule> children = new LinkedList<IdeaModule>();
- private IdeaLanguageLevel languageLevel;
- private String jdkName;
-
- public IdeaLanguageLevel getLanguageLevel() {
- return languageLevel;
- }
-
- public DefaultIdeaProject setLanguageLevel(IdeaLanguageLevel languageLevel) {
- this.languageLevel = languageLevel;
- return this;
- }
-
- public String getJdkName() {
- return jdkName;
- }
-
- public DefaultIdeaProject setJdkName(String jdkName) {
- this.jdkName = jdkName;
- return this;
- }
-
- public String getName() {
- return name;
- }
-
- public DefaultIdeaProject setName(String name) {
- this.name = name;
- return this;
- }
-
- public String getDescription() {
- return description;
- }
-
- public DefaultIdeaProject setDescription(String description) {
- this.description = description;
- return this;
- }
-
- public HierarchicalElement getParent() {
- return null;
- }
-
- public File getProjectDirectory() {
- throw new UnsupportedOperationException("This method should not be used.");
- }
-
- public String getPath() {
- throw new UnsupportedOperationException("This method should not be used.");
- }
-
- public DefaultIdeaProject setChildren(Collection<? extends IdeaModule> children) {
- this.children = children;
- return this;
- }
-
- public DomainObjectSet<? extends IdeaModule> getChildren() {
- return new ImmutableDomainObjectSet<IdeaModule>(children);
- }
-
- public DomainObjectSet<? extends IdeaModule> getModules() {
- return new ImmutableDomainObjectSet<IdeaModule>(children);
- }
-
- @Override
- public String toString() {
- return "DefaultIdeaProject{"
- + " name='" + name + '\''
- + ", description='" + description + '\''
- + ", children count=" + children.size()
- + ", languageLevel='" + languageLevel + '\''
- + ", jdkName='" + jdkName + '\''
- + '}';
- }
-}
\ No newline at end of file
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/idea/DefaultIdeaSingleEntryLibraryDependency.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/idea/DefaultIdeaSingleEntryLibraryDependency.java
deleted file mode 100644
index 02221f9..0000000
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/idea/DefaultIdeaSingleEntryLibraryDependency.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.idea;
-
-import org.gradle.tooling.model.GradleModuleVersion;
-import org.gradle.tooling.model.idea.IdeaDependencyScope;
-import org.gradle.tooling.model.idea.IdeaSingleEntryLibraryDependency;
-
-import java.io.File;
-import java.io.Serializable;
-
-/**
- * @author: Szczepan Faber, created at: 7/26/11
- */
-public class DefaultIdeaSingleEntryLibraryDependency implements IdeaSingleEntryLibraryDependency, Serializable {
-
- private File file;
- private File source;
- private File javadoc;
- private Boolean exported;
- private IdeaDependencyScope scope;
- private GradleModuleVersion moduleVersion;
-
- public File getFile() {
- return file;
- }
-
- public DefaultIdeaSingleEntryLibraryDependency setFile(File file) {
- this.file = file;
- return this;
- }
-
- public File getSource() {
- return source;
- }
-
- public DefaultIdeaSingleEntryLibraryDependency setSource(File source) {
- this.source = source;
- return this;
- }
-
- public File getJavadoc() {
- return javadoc;
- }
-
- public GradleModuleVersion getGradleModuleVersion() {
- return moduleVersion;
- }
-
- public DefaultIdeaSingleEntryLibraryDependency setJavadoc(File javadoc) {
- this.javadoc = javadoc;
- return this;
- }
-
- public boolean getExported() {
- return exported;
- }
-
- public DefaultIdeaSingleEntryLibraryDependency setExported(Boolean exported) {
- this.exported = exported;
- return this;
- }
-
- public IdeaDependencyScope getScope() {
- return scope;
- }
-
- public DefaultIdeaSingleEntryLibraryDependency setScope(IdeaDependencyScope scope) {
- this.scope = scope;
- return this;
- }
-
- public DefaultIdeaSingleEntryLibraryDependency setGradleModuleVersion(GradleModuleVersion moduleVersion) {
- this.moduleVersion = moduleVersion;
- return this;
- }
-
- @Override
- public String toString() {
- return "IdeaLibraryDependency{"
- + "file=" + file
- + ", source=" + source
- + ", javadoc=" + javadoc
- + ", exported=" + exported
- + ", scope='" + scope + '\''
- + ", id='" + moduleVersion + '\''
- + '}';
- }
-}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/idea/DefaultIdeaSourceDirectory.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/idea/DefaultIdeaSourceDirectory.java
deleted file mode 100644
index 72021d1..0000000
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/idea/DefaultIdeaSourceDirectory.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.idea;
-
-import org.gradle.tooling.model.idea.IdeaSourceDirectory;
-
-import java.io.File;
-import java.io.Serializable;
-
-/**
- * @author: Szczepan Faber, created at: 7/27/11
- */
-public class DefaultIdeaSourceDirectory implements IdeaSourceDirectory, Serializable {
-
- private File directory;
-
- public File getDirectory() {
- return directory;
- }
-
- public DefaultIdeaSourceDirectory setDirectory(File directory) {
- this.directory = directory;
- return this;
- }
-
- @Override
- public String toString() {
- return "DefaultIdeaSourceDirectory{"
- + "directory=" + directory
- + '}';
- }
-}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/outcomes/DefaultGradleBuildOutcome.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/outcomes/DefaultGradleBuildOutcome.java
deleted file mode 100644
index 6bebd3d..0000000
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/outcomes/DefaultGradleBuildOutcome.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.outcomes;
-
-import org.gradle.tooling.model.internal.outcomes.GradleBuildOutcome;
-
-import java.io.Serializable;
-
-public class DefaultGradleBuildOutcome implements GradleBuildOutcome, Serializable {
-
- private final String id;
- private final String description;
- private final String taskPath;
-
- public DefaultGradleBuildOutcome(String id, String description, String taskPath) {
- this.id = id;
- this.description = description;
- this.taskPath = taskPath;
- }
-
- public String getId() {
- return id;
- }
-
- public String getDescription() {
- return description;
- }
-
- public String getTaskPath() {
- return taskPath;
- }
-}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/outcomes/DefaultGradleFileBuildOutcome.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/outcomes/DefaultGradleFileBuildOutcome.java
deleted file mode 100644
index 64f480a..0000000
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/outcomes/DefaultGradleFileBuildOutcome.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.outcomes;
-
-import org.gradle.tooling.model.internal.outcomes.GradleFileBuildOutcome;
-
-import java.io.File;
-
-public class DefaultGradleFileBuildOutcome extends DefaultGradleBuildOutcome implements GradleFileBuildOutcome {
-
- private final File file;
- private final String typeIdentifier;
-
- public DefaultGradleFileBuildOutcome(String id, String description, String taskPath, File file, String typeIdentifier) {
- super(id, description, taskPath);
- this.file = file;
- this.typeIdentifier = typeIdentifier;
- }
-
- public File getFile() {
- return file;
- }
-
- public String getTypeIdentifier() {
- return typeIdentifier;
- }
-
-}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/outcomes/DefaultProjectOutcomes.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/outcomes/DefaultProjectOutcomes.java
deleted file mode 100644
index 4e27335..0000000
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/outcomes/DefaultProjectOutcomes.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.outcomes;
-
-import com.google.common.collect.Lists;
-import org.gradle.tooling.internal.protocol.InternalProjectOutcomes;
-import org.gradle.tooling.model.DomainObjectSet;
-import org.gradle.tooling.model.internal.ImmutableDomainObjectSet;
-import org.gradle.tooling.model.internal.outcomes.GradleBuildOutcome;
-import org.gradle.tooling.model.internal.outcomes.ProjectOutcomes;
-
-import java.io.File;
-import java.io.Serializable;
-import java.util.List;
-
-public class DefaultProjectOutcomes implements InternalProjectOutcomes, ProjectOutcomes, Serializable {
- private final String name;
- private final String projectPath;
- private final String description;
- private final File projectDirectory;
- private final DomainObjectSet<? extends GradleBuildOutcome> outcomes;
- private final ProjectOutcomes parent;
- private final List<ProjectOutcomes> children = Lists.newArrayList();
-
- public DefaultProjectOutcomes(String name, String projectPath, String description, File projectDirectory,
- DomainObjectSet<? extends GradleBuildOutcome> outcomes, ProjectOutcomes parent) {
- this.name = name;
- this.projectPath = projectPath;
- this.description = description;
- this.projectDirectory = projectDirectory;
- this.outcomes = outcomes;
- this.parent = parent;
- }
-
- public String getName() {
- return name;
- }
-
- public String getPath() {
- return projectPath;
- }
-
- public String getDescription() {
- return description;
- }
-
- public File getProjectDirectory() {
- return projectDirectory;
- }
-
- public DomainObjectSet<? extends GradleBuildOutcome> getOutcomes() {
- return outcomes;
- }
-
- public ProjectOutcomes getParent() {
- return parent;
- }
-
- public DomainObjectSet<ProjectOutcomes> getChildren() {
- return new ImmutableDomainObjectSet<ProjectOutcomes>(children);
- }
-
- public void addChild(ProjectOutcomes child) {
- children.add(child);
- }
-}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/BuildActionRunner.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/BuildActionRunner.java
index 984f810..f6bdcb6 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/BuildActionRunner.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/BuildActionRunner.java
@@ -19,15 +19,31 @@ package org.gradle.tooling.internal.protocol;
/**
* Mixed into a provider connection, to run actions against a build.
*
+ * <p>DO NOT CHANGE THIS INTERFACE - it is part of the cross-version protocol.
+ *
+ * <p>Consumer compatibility: This interface is used by all consumer versions from 1.2-rc-1 to 1.5. It is also used by later consumers when the provider does not
+ * implement {@link ModelBuilder}.
+ * </p>
+ * <p>Provider compatibility: This interface is implemented by all provider versions from 1.2-rc-1.</p>
+ *
* @since 1.2-rc-1
+ * @deprecated 1.6-rc-1. Use {@link ModelBuilder} instead.
+ * @see ConnectionVersion4
*/
+ at Deprecated
public interface BuildActionRunner extends InternalProtocolInterface {
/**
* Performs some action against a build and returns some result of the given type.
*
+ * <p>Consumer compatibility: This method is used by all consumer versions from 1.2-rc-1 to 1.5.</p>
+ * <p>Provider compatibility: This method is implemented by all provider versions from 1.2-rc-1.</p>
+ *
* @param type The desired result type. Use {@link Void} to indicate that no result is desired.
* @throws UnsupportedOperationException When the given model type is not supported.
* @throws IllegalStateException When this connection has been stopped.
+ * @since 1.2-rc-1
+ * @deprecated 1.6-rc-1. Use {@link ModelBuilder#getModel(ModelIdentifier, BuildParameters)} instead.
*/
+ @Deprecated
<T> BuildResult<T> run(Class<T> type, BuildParameters operationParameters) throws UnsupportedOperationException, IllegalStateException;
}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/BuildExceptionVersion1.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/BuildExceptionVersion1.java
index 029b9e1..fff915f 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/BuildExceptionVersion1.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/BuildExceptionVersion1.java
@@ -16,9 +16,12 @@
package org.gradle.tooling.internal.protocol;
/**
- * A wrapper around a build failure, to distinguish it from an infrastructure failure.
+ * A wrapper around a build failure, to distinguish it from an infrastructure failure. The details of the
+ * failure are made available in the cause of this exception.
*
* DO NOT CHANGE THIS CLASS. It is part of the cross-version protocol.
+ *
+ * @since 1.0-milestone-3
*/
public class BuildExceptionVersion1 extends RuntimeException {
public BuildExceptionVersion1(Throwable throwable) {
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/BuildOperationParametersVersion1.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/BuildOperationParametersVersion1.java
index 853f6b2..69538d3 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/BuildOperationParametersVersion1.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/BuildOperationParametersVersion1.java
@@ -20,36 +20,59 @@ import java.util.concurrent.TimeUnit;
/**
* DO NOT CHANGE THIS INTERFACE. It is part of the cross-version protocol.
+ *
+ * @since 1.0-milestone-3
+ * @deprecated 1.2-rc-1. Use {@link BuildParameters} instead.
*/
+ at Deprecated
public interface BuildOperationParametersVersion1 extends LongRunningOperationParametersVersion1 {
+ /**
+ * @since 1.0-milestone-3
+ */
File getProjectDir();
/**
* Specifies whether to search for root project, or null to use default.
+ *
+ * @since 1.0-milestone-3
*/
Boolean isSearchUpwards();
/**
* Returns the Gradle user home directory, or null to use default.
+ *
+ * @since 1.0-milestone-3
*/
File getGradleUserHomeDir();
/**
* Specifies whether to run the build in this process, or null to use default.
+ *
+ * @since 1.0-milestone-3
*/
Boolean isEmbedded();
/**
* Specifies the maximum idle time for any daemon process launched by the provider, or null to use the default.
+ *
+ * @since 1.0-milestone-3
*/
Integer getDaemonMaxIdleTimeValue();
/**
* Specifies the units for the maximum idle time.
+ *
+ * @since 1.0-milestone-3
*/
TimeUnit getDaemonMaxIdleTimeUnits();
+ /**
+ * @since 1.0-milestone-3
+ */
long getStartTime();
+ /**
+ * @since 1.0-milestone-7
+ */
boolean getVerboseLogging();
}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/BuildParameters.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/BuildParameters.java
index 8b90eb9..6f1edf1 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/BuildParameters.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/BuildParameters.java
@@ -19,8 +19,8 @@ package org.gradle.tooling.internal.protocol;
/**
* The parameters for running a build.
*
- * <p>This is a marker interface. Instances are queried dynamically to see which parameters they support. See {@code ProviderOperationParameters} for details of the methods that provider expects,
- * and {@code ConsumerOperationParameters} for details of what the consumer currently provides.
+ * <p>This is a marker interface. Instances are queried dynamically to see which parameters they support. See {@code ProviderOperationParameters}
+ * for details of the methods that provider expects, and {@code ConsumerOperationParameters} for details of what the consumer currently provides.
*
* @since 1.2-rc-1
*/
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/BuildParametersVersion1.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/BuildParametersVersion1.java
index bd20a9e..e90f31a 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/BuildParametersVersion1.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/BuildParametersVersion1.java
@@ -19,7 +19,14 @@ import java.util.List;
/**
* DO NOT CHANGE THIS INTERFACE. It is part of the cross-version protocol.
+ *
+ * @since 1.0-milestone-3
+ * @deprecated 1.2-rc-1. Use {@link BuildParameters} instead.
*/
+ at Deprecated
public interface BuildParametersVersion1 {
+ /**
+ * @since 1.0-milestone-3
+ */
List<String> getTasks();
}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/ConfigurableConnection.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/ConfigurableConnection.java
index f99ddb1..bc1aac9 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/ConfigurableConnection.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/ConfigurableConnection.java
@@ -19,8 +19,22 @@ package org.gradle.tooling.internal.protocol;
/**
* Mixed into a provider connection, to allow the connection to be configured.
*
+ * <p>DO NOT CHANGE THIS INTERFACE - it is part of the cross-version protocol.
+ *
+ * <p>Consumer compatibility: This interface is used by all consumer versions from 1.2-rc-1.</p>
+ * <p>Provider compatibility: This interface is implemented by all provider versions from 1.2-rc-1.</p>
+ *
* @since 1.2-rc-1
+ * @see ConnectionVersion4
*/
public interface ConfigurableConnection extends InternalProtocolInterface {
+ /**
+ * Configures this connection with the given parameters.
+ *
+ * <p>Consumer compatibility: This method is used by all consumer versions from 1.2-rc-1.</p>
+ * <p>Provider compatibility: This method is implemented by all provider versions from 1.2-rc-1.</p>
+ *
+ * @since 1.2-rc-1
+ */
void configure(ConnectionParameters parameters);
}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/ConnectionVersion4.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/ConnectionVersion4.java
index 38e164b..6667a2d 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/ConnectionVersion4.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/ConnectionVersion4.java
@@ -16,51 +16,78 @@
package org.gradle.tooling.internal.protocol;
/**
- * <p>Represents a connection to a particular Gradle implementation.
+ * <p>Represents a connection to a Gradle implementation.
*
* <p>The following constraints apply to implementations:
* <ul>
* <li>Implementations must be thread-safe.
- * <li>Implementations should implement {@link BuildActionRunner}.
- * <li>Implementations should implement {@link ConfigurableConnection}.
- * <li>Implementations should provide a zero-args constructor
- * <li>For backwards compatibility, implementations should implement {@link InternalConnection}.
- * <li>For backwards compatibility, implementations should provide a {@code void configureLogging(boolean verboseLogging)} method.
+ * <li>Implementations should implement {@link ModelBuilder}. This is used by all consumer versions from 1.6-rc-1.
+ * <li>Implementations should implement {@link InternalBuildActionExecutor}. This is used by all consumer versions from 1.8-rc-1.
+ * <li>Implementations should implement {@link ConfigurableConnection}. This is used by all consumer versions from 1.2-rc-1.
+ * <li>Implementations should provide a zero-args constructor. This is used by all consumer versions from 1.0-milestone-3.
+ * <li>For backwards compatibility, implementations should implement {@link BuildActionRunner}. This is used by consumer versions from 1.2-rc-1 to 1.5.
+ * <li>For backwards compatibility, implementations should implement {@link InternalConnection}. This is used by consumer versions from 1.0-milestone-8 to 1.1.
+ * <li>For backwards compatibility, implementations should provide a {@code void configureLogging(boolean verboseLogging)} method. This is used by consumer versions
+ * 1.0-rc-1 to 1.1.
* </ul>
*
- * <p>
- * Changes to this interface may break the cross-version protocol.
- * If you change it, make sure you run the all tooling api tests to flush out compatibility issues.
+ * <p>DO NOT CHANGE THIS INTERFACE - it is part of the cross-version protocol.
+ *
+ * <p>Consumer compatibility: This interface is used by all consumer versions from 1.0-milestone-3.</p>
+ * <p>Provider compatibility: This interface is implemented by all provider versions from 1.0-milestone-3.</p>
+ *
+ * @since 1.0-milestone-3
*/
public interface ConnectionVersion4 {
/**
- * Stops this connection, blocking until complete.
+ * <p>Stops this connection, blocking until complete.
+ *
+ * <p>Consumer compatibility: This method is used by all consumer versions from 1.0-milestone-3.</p>
+ * <p>Provider compatibility: This method is implemented by all provider versions from 1.0-milestone-3.</p>
+ *
+ * @since 1.0-milestone-3
*/
void stop();
/**
- * Returns the meta-data for this connection. The implementation of this method should be fast, and should continue to work after the connection has been stopped.
+ * <p>Returns the meta-data for this connection. The implementation of this method should be fast, and should continue to work after the connection has been stopped.
+ *
+ * <p>Consumer compatibility: This method is used by all consumer versions from 1.0-milestone-3.</p>
+ * <p>Provider compatibility: This method is implemented by all provider versions from 1.0-milestone-3.</p>
+ *
* @return The meta-data.
+ * @since 1.0-milestone-3
*/
ConnectionMetaDataVersion1 getMetaData();
/**
- * Fetches a snapshot of the model for the project.
- * <p>
+ * <p>Fetches a snapshot of the model for the project.
+ *
+ * <p>Consumer compatibility: This method is used by all consumer versions from 1.0-milestone-3 to 1.0-milestone-7. It is also used by later consumers when the provider
+ * does not implement {@link InternalConnection} or {@link BuildActionRunner}
+ * </p>
+ * <p>Provider compatibility: This method is implemented by all provider versions from 1.0-milestone-3.</p>
*
* @throws UnsupportedOperationException When the given model type is not supported.
* @throws IllegalStateException When this connection has been stopped.
- * @deprecated Use {@link BuildActionRunner#run(Class, BuildParameters)} instead.
+ * @since 1.0-milestone-3
+ * @deprecated 1.0-milestone-8. Use {@link ModelBuilder#getModel(ModelIdentifier, BuildParameters)} instead.
*/
@Deprecated
ProjectVersion3 getModel(Class<? extends ProjectVersion3> type, BuildOperationParametersVersion1 operationParameters) throws UnsupportedOperationException, IllegalStateException;
/**
- * Executes a build.
+ * <p>Executes a build.
+ *
+ * <p>Consumer compatibility: This method is used by all consumer versions from 1.0-milestone-3 to 1.1. It is also used by later consumers when the provider
+ * does not implement {@link BuildActionRunner}
+ * </p>
+ * <p>Provider compatibility: This method is implemented by all provider versions from 1.0-milestone-3.</p>
*
* @param buildParameters The parameters for the build.
* @throws IllegalStateException When this connection has been stopped.
- * @deprecated Use {@link BuildActionRunner#run(Class, BuildParameters)} instead.
+ * @since 1.0-milestone-3
+ * @deprecated 1.2-rc-1. Use {@link ModelBuilder#getModel(ModelIdentifier, BuildParameters)} instead.
*/
@Deprecated
void executeBuild(BuildParametersVersion1 buildParameters, BuildOperationParametersVersion1 operationParameters) throws IllegalStateException;
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalBasicIdeaProject.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalBasicIdeaProject.java
index 6b4a3f4..3f39c9c 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalBasicIdeaProject.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalBasicIdeaProject.java
@@ -17,6 +17,8 @@
package org.gradle.tooling.internal.protocol;
/**
- * See {@link org.gradle.tooling.internal.protocol.InternalProtocolInterface}
+ * See {@link InternalProtocolInterface}
+ *
+ * @since 1.0-milestone-5
*/
public interface InternalBasicIdeaProject extends ProjectVersion3, InternalProtocolInterface {}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalBuildAction.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalBuildAction.java
new file mode 100644
index 0000000..d3d45d9
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalBuildAction.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.protocol;
+
+import java.io.Serializable;
+
+/**
+ * <p>DO NOT CHANGE THIS INTERFACE - it is part of the cross-version protocol.
+ *
+ * <p>Consumer compatibility: This interface is implemented by all consumer versions from 1.8-rc-1.</p>
+ * <p>Provider compatibility: This interface is consumed by all provider versions from 1.8-rc-1.</p>
+ *
+ * @since 1.8-rc-1
+ */
+public interface InternalBuildAction<T> extends InternalProtocolInterface, Serializable {
+ /**
+ * Performs some action against a build and returns a result.
+ *
+ * @since 1.8-rc-1
+ */
+ T execute(InternalBuildController buildController);
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalBuildActionExecutor.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalBuildActionExecutor.java
new file mode 100644
index 0000000..7064361
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalBuildActionExecutor.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.protocol;
+
+import org.gradle.tooling.internal.protocol.exceptions.InternalUnsupportedBuildArgumentException;
+
+/**
+ * Mixed into a provider connection, to allow client-provided build actions to be executed.
+ *
+ * <p>DO NOT CHANGE THIS INTERFACE - it is part of the cross-version protocol.
+ *
+ * <p>Consumer compatibility: This interface is used by all consumer versions from 1.8-rc-1.</p>
+ * <p>Provider compatibility: This interface is implemented by all provider versions from 1.8-rc-1.</p>
+ *
+ * @since 1.8-rc-1
+ * @see ConnectionVersion4
+ */
+public interface InternalBuildActionExecutor extends InternalProtocolInterface {
+ /**
+ * Performs some action against a build and returns the result.
+ *
+ * <p>Consumer compatibility: This method is used by all consumer versions from 1.8-rc-1.</p>
+ * <p>Provider compatibility: This method is implemented by all provider versions from 1.8-rc-1.</p>
+ *
+ * @throws BuildExceptionVersion1 On build failure.
+ * @throws InternalUnsupportedBuildArgumentException When the specified command-line options are not supported.
+ * @throws InternalBuildActionFailureException When the action fails with an exception.
+ * @throws IllegalStateException When this connection has been stopped.
+ * @since 1.8-rc-1
+ */
+ <T> BuildResult<T> run(InternalBuildAction<T> action,
+ BuildParameters operationParameters) throws
+ BuildExceptionVersion1,
+ InternalUnsupportedBuildArgumentException,
+ InternalBuildActionFailureException,
+ IllegalStateException;
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalBuildActionFailureException.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalBuildActionFailureException.java
new file mode 100644
index 0000000..08e6269
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalBuildActionFailureException.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.protocol;
+
+/**
+ * A wrapper thrown when a build action fails with an exception. The failure will be attached as the cause of this exception.
+ *
+ * DO NOT CHANGE THIS CLASS. It is part of the cross-version protocol.
+ *
+ * @since 1.8-rc-1
+ */
+public class InternalBuildActionFailureException extends RuntimeException {
+ public InternalBuildActionFailureException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalBuildController.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalBuildController.java
new file mode 100644
index 0000000..1134c70
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalBuildController.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.protocol;
+
+/**
+ * <p>DO NOT CHANGE THIS INTERFACE - it is part of the cross-version protocol.
+ *
+ * <p>Consumer compatibility: This interface is used by all consumer versions from 1.8-rc-1.</p>
+ * <p>Provider compatibility: This interface is implemented by all provider versions from 1.8-rc-1.</p>
+ *
+ * @since 1.8-rc-1
+ */
+public interface InternalBuildController {
+ /**
+ * Returns the version-specific build model.
+ *
+ * <p>Consumer compatibility: This method is not used by any consumer versions.</p>
+ * <p>Provider compatibility: This method is implemented by all provider versions from 1.8-rc-1.</p>
+ *
+ * @throws BuildExceptionVersion1 On build failure.
+ * @since 1.8-rc-1
+ */
+ BuildResult<?> getBuildModel() throws BuildExceptionVersion1;
+
+ /**
+ * Returns the requested model for a target object.
+ *
+ * <p>Consumer compatibility: This method is used by all consumer versions from 1.8-rc-1.</p>
+ * <p>Provider compatibility: This method is implemented by all provider versions from 1.8-rc-1.</p>
+ *
+ * @param target The target object. May be null, in which case a default target is used.
+ * @param modelIdentifier The identifier of the model to build.
+ * @throws BuildExceptionVersion1 On build failure.
+ * @throws InternalUnsupportedModelException When the requested model is not supported.
+ * @since 1.8-rc-1
+ */
+ BuildResult<?> getModel(Object target, ModelIdentifier modelIdentifier) throws BuildExceptionVersion1,
+ InternalUnsupportedModelException;
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalBuildEnvironment.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalBuildEnvironment.java
index 332d79b..892b302 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalBuildEnvironment.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalBuildEnvironment.java
@@ -20,6 +20,7 @@ package org.gradle.tooling.internal.protocol;
* Marker interface for the internal protocol purposes.
* Corresponding client facing model is {@link org.gradle.tooling.model.build.BuildEnvironment}
* <p>
- * by Szczepan Faber, created at: 12/17/11
+ *
+ * @since 1.0-milestone-8
*/
public interface InternalBuildEnvironment extends InternalProtocolInterface {}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalConnection.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalConnection.java
index b716e72..a538431 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalConnection.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalConnection.java
@@ -17,9 +17,15 @@
package org.gradle.tooling.internal.protocol;
/**
- * by Szczepan Faber, created at: 1/1/12
+ * <p>DO NOT CHANGE THIS INTERFACE - it is part of the cross-version protocol.
*
- * @deprecated Use {@link BuildActionRunner} instead.
+ * <p>Consumer compatibility: This interface is used by all consumer versions from 1.0-milestone-8 to 1.1. It is also used by later consumers when the
+ * provider does not implement {@link BuildActionRunner} or {@link ModelBuilder}.</p>
+ * <p>Provider compatibility: This interface is implemented by all provider versions from 1.0-milestone-8.</p>
+ *
+ * @since 1.0-milestone-8
+ * @deprecated 1.2-rc-1. Use {@link BuildActionRunner} instead.
+ * @see ConnectionVersion4
*/
@Deprecated
public interface InternalConnection extends ConnectionVersion4, InternalProtocolInterface {
@@ -29,9 +35,14 @@ public interface InternalConnection extends ConnectionVersion4, InternalProtocol
* <p>
* The other method on the interface, e.g. {@link #getModel(Class, BuildOperationParametersVersion1)} should be considered deprecated
*
+ * <p>Consumer compatibility: This method is used by all consumer versions from 1.0-milestone-8 to 1.1. It is also used by later consumers when the
+ * provider does not implement {@link BuildActionRunner} or {@link ModelBuilder}.</p>
+ * <p>Provider compatibility: This interface is implemented by all provider versions from 1.0-milestone-8.</p>
+ *
* @throws UnsupportedOperationException When the given model type is not supported.
* @throws IllegalStateException When this connection has been stopped.
- * @deprecated Use {@link BuildActionRunner#run(Class, BuildOperationParametersVersion1)} instead.
+ * @since 1.0-milestone-8
+ * @deprecated 1.2-rc-1 Use {@link ModelBuilder#getModel(ModelIdentifier, BuildParameters)} instead.
*/
@Deprecated
<T> T getTheModel(Class<T> type, BuildOperationParametersVersion1 operationParameters) throws UnsupportedOperationException, IllegalStateException;
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalGradleProject.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalGradleProject.java
index 3c03a83..e903a8d 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalGradleProject.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalGradleProject.java
@@ -18,5 +18,7 @@ package org.gradle.tooling.internal.protocol;
/**
* See {@link InternalProtocolInterface}
+ *
+ * @since 1.0-milestone-5
*/
public interface InternalGradleProject extends ProjectVersion3, InternalProtocolInterface {}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalIdeaProject.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalIdeaProject.java
index 4186fac..6457f6c 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalIdeaProject.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalIdeaProject.java
@@ -18,6 +18,8 @@ package org.gradle.tooling.internal.protocol;
/**
* See {@link InternalProtocolInterface}
+ *
+ * @since 1.0-milestone-5
*/
public interface InternalIdeaProject extends ProjectVersion3, InternalProtocolInterface {
}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalProjectOutcomes.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalProjectOutcomes.java
index dd2172f..cc2f6dc 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalProjectOutcomes.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalProjectOutcomes.java
@@ -16,5 +16,10 @@
package org.gradle.tooling.internal.protocol;
-public interface InternalProjectOutcomes extends ProjectVersion3, InternalProtocolInterface {
+/**
+ * <p>Consumer compatibility: This interface used to extend {@link ProjectVersion3} until 1.6-rc-1.</p>
+ *
+ * @since 1.2-rc-1
+ */
+public interface InternalProjectOutcomes extends InternalProtocolInterface {
}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalProtocolInterface.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalProtocolInterface.java
index f97648d..521e0aa 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalProtocolInterface.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalProtocolInterface.java
@@ -17,16 +17,10 @@
package org.gradle.tooling.internal.protocol;
/**
- * I needed this interface so that it is possible to develop new features incrementally.
- * In general I'd like to avoid growing VersionX interfaces
- * because we have an excellent test suite that tells the story of what has changed and when
- * <p>
- * A marker interface to document the problem consistently.
- * Might live only until we gradually remove old VersionX types.
- * <p>
- * If you make changes to inheritor of this interfaces make sure you run all compatibility tests.
+ * <p>A marker interface for some type that participates in the cross-version tooling protocol.
*
- * @author: Szczepan Faber, created at: 8/5/11
+ * <p>Subtypes generally define only a few methods statically. Instances are usually inspected dynamically to
+ * determine which methods are actually supported.
*/
public interface InternalProtocolInterface {
}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalTestModel.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalTestModel.java
deleted file mode 100644
index 53fecb3..0000000
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalTestModel.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.protocol;
-
-/**
- * For testing purposes only
- * <p>
- * by Szczepan Faber, created at: 12/21/11
- */
-public interface InternalTestModel extends ProjectVersion3 {}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalUnsupportedModelException.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalUnsupportedModelException.java
new file mode 100644
index 0000000..ebd2c4f
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/InternalUnsupportedModelException.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.protocol;
+
+/**
+ * A wrapper thrown when some requested model is not available. Any details will be made available in the cause of
+ * the exception.
+ *
+ * <p>Consumer compatibility: Versions 1.6-rc-1 and later use this type.</p>
+ * <p>Provider compatibility: Versions prior to 1.8-rc-1 did not attach any cause to this exception.</p>
+ *
+ * DO NOT CHANGE THIS CLASS. It is part of the cross-version protocol.
+ *
+ * @since 1.6-rc-1
+ */
+public class InternalUnsupportedModelException extends RuntimeException {
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/LongRunningOperationParametersVersion1.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/LongRunningOperationParametersVersion1.java
index 5eec6bd..11a2b6c 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/LongRunningOperationParametersVersion1.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/LongRunningOperationParametersVersion1.java
@@ -20,12 +20,17 @@ import java.io.OutputStream;
/**
* DO NOT CHANGE THIS INTERFACE. It is part of the cross-version protocol.
+ *
+ * @since 1.0-milestone-3
+ * @deprecated 1.2-rc-1. Use {@link BuildParameters} instead.
*/
+ at Deprecated
public interface LongRunningOperationParametersVersion1 {
/**
* Returns the output stream to write stdout logging to.
*
* @return The output stream. May be null.
+ * @since 1.0-milestone-3
*/
OutputStream getStandardOutput();
@@ -33,6 +38,7 @@ public interface LongRunningOperationParametersVersion1 {
* Returns the output stream to write stderr logging to.
*
* @return The output stream. May be null.
+ * @since 1.0-milestone-3
*/
OutputStream getStandardError();
@@ -40,6 +46,7 @@ public interface LongRunningOperationParametersVersion1 {
* Returns the listener to receive progress events.
*
* @return The listener. Must not be null.
+ * @since 1.0-milestone-3
*/
ProgressListenerVersion1 getProgressListener();
@@ -47,6 +54,7 @@ public interface LongRunningOperationParametersVersion1 {
* Returns the input stream to that can be consumed.
*
* @return The input stream. May be null.
+ * @since 1.0-milestone-8
*/
InputStream getStandardInput();
}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/ModelBuilder.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/ModelBuilder.java
new file mode 100644
index 0000000..b31ff5a
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/ModelBuilder.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.protocol;
+
+import org.gradle.tooling.internal.protocol.exceptions.InternalUnsupportedBuildArgumentException;
+
+/**
+ * Mixed into a provider connection, to allow tooling models to be requested by the client.
+ *
+ * <p>DO NOT CHANGE THIS INTERFACE - it is part of the cross-version protocol.
+ *
+ * <p>Consumer compatibility: This interface is used by all consumer versions from 1.6-rc-1.</p>
+ * <p>Provider compatibility: This interface is implemented by all provider versions from 1.6-rc-1.</p>
+ *
+ * @since 1.6-rc-1
+ * @see ConnectionVersion4
+ */
+public interface ModelBuilder extends InternalProtocolInterface {
+ /**
+ * Performs some action against a build and returns the requested model.
+ *
+ * <p>Consumer compatibility: This method is used by all consumer versions from 1.6-rc-1.</p>
+ * <p>Provider compatibility: This method is implemented by all provider versions from 1.6-rc-1.</p>
+ *
+ * @param modelIdentifier The identifier of the model to build.
+ * @throws BuildExceptionVersion1 On build failure.
+ * @throws InternalUnsupportedModelException When the requested model is not supported.
+ * @throws InternalUnsupportedBuildArgumentException When the specified command-line options are not supported.
+ * @throws IllegalStateException When this connection has been stopped.
+ * @since 1.6-rc-1
+ */
+ BuildResult<?> getModel(ModelIdentifier modelIdentifier, BuildParameters operationParameters) throws
+ BuildExceptionVersion1,
+ InternalUnsupportedModelException,
+ InternalUnsupportedBuildArgumentException,
+ IllegalStateException;
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/ModelIdentifier.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/ModelIdentifier.java
new file mode 100644
index 0000000..bc1464d
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/ModelIdentifier.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.protocol;
+
+/**
+ * Identity information for a model.
+ *
+ * <p>DO NOT CHANGE THIS INTERFACE - it is part of the cross-version protocol.
+ *
+ * <p>Consumer compatibility: This interface is used by all consumer versions from 1.6-rc-1.</p>
+ * <p>Provider compatibility: This interface is uses by all provider versions from 1.6-rc-1.</p>
+ *
+ * @since 1.6-rc-1
+ */
+public interface ModelIdentifier extends InternalProtocolInterface {
+ /**
+ * The name of the null model.
+ */
+ final String NULL_MODEL = Void.class.getName();
+
+ /**
+ * The name of the model.
+ *
+ * Note that the model name is not necessarily a class name. It simply uniquely identifies the model.
+ * Use {@link #NULL_MODEL} to indicate that no model is desired.
+ */
+ String getName();
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/ProjectVersion3.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/ProjectVersion3.java
index 8a9378e..b28573e 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/ProjectVersion3.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/ProjectVersion3.java
@@ -19,13 +19,30 @@ import java.io.File;
/**
* DO NOT CHANGE THIS INTERFACE. It is part of the cross-version protocol.
+ *
+ * <p>Consumer compatibility: This interface is used by all consumer versions from 1.0-milestone-3 to 1.0-milestone-7 to represent the model objects. Later consumer versions don't require that the
+ * model objects implement this interface. </p>
+ *
+ * @since 1.0-milestone-3
*/
public interface ProjectVersion3 {
+ /**
+ * @since 1.0-milestone-3
+ */
String getPath();
+ /**
+ * @since 1.0-milestone-3
+ */
String getName();
+ /**
+ * @since 1.0-milestone-3
+ */
String getDescription();
+ /**
+ * @since 1.0-milestone-3
+ */
File getProjectDirectory();
}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/eclipse/EclipseLinkedResourceVersion1.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/eclipse/EclipseLinkedResourceVersion1.java
index 1e6eebe..00dfa05 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/eclipse/EclipseLinkedResourceVersion1.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/eclipse/EclipseLinkedResourceVersion1.java
@@ -18,8 +18,6 @@ package org.gradle.tooling.internal.protocol.eclipse;
/**
* DO NOT CHANGE THIS INTERFACE. It is part of the cross-version protocol.
- *
- * @author: Szczepan Faber, created at: 6/11/11
*/
public interface EclipseLinkedResourceVersion1 {
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/eclipse/EclipseProjectVersion3.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/eclipse/EclipseProjectVersion3.java
index 1dcfe30..96aad9a 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/eclipse/EclipseProjectVersion3.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/eclipse/EclipseProjectVersion3.java
@@ -20,6 +20,8 @@ import org.gradle.tooling.internal.protocol.ExternalDependencyVersion1;
/**
* DO NOT CHANGE THIS INTERFACE. It is part of the cross-version protocol.
+ *
+ * @since 1.0-milestone-3
*/
public interface EclipseProjectVersion3 extends HierarchicalEclipseProjectVersion1, BuildableProjectVersion1 {
EclipseProjectVersion3 getParent();
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/eclipse/HierarchicalEclipseProjectVersion1.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/eclipse/HierarchicalEclipseProjectVersion1.java
index 2b5d798..c2f817b 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/eclipse/HierarchicalEclipseProjectVersion1.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/protocol/eclipse/HierarchicalEclipseProjectVersion1.java
@@ -19,6 +19,8 @@ import org.gradle.tooling.internal.protocol.HierarchicalProjectVersion1;
/**
* DO NOT CHANGE THIS INTERFACE. It is part of the cross-version protocol.
+ *
+ * @since 1.0-milestone-3
*/
public interface HierarchicalEclipseProjectVersion1 extends HierarchicalProjectVersion1 {
HierarchicalEclipseProjectVersion1 getParent();
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/reflect/CompatibleIntrospector.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/reflect/CompatibleIntrospector.java
deleted file mode 100644
index bb2a863..0000000
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/reflect/CompatibleIntrospector.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.reflect;
-
-import java.lang.reflect.Method;
-
-/**
- * Uses reflection to find out / call methods.
- *
- * by Szczepan Faber, created at: 12/9/11
- */
-public class CompatibleIntrospector {
-
- private final Object target;
-
- public CompatibleIntrospector(Object target) {
- this.target = target;
- }
-
- private Method getMethod(String methodName) throws NoSuchMethodException {
- Method[] methods = target.getClass().getDeclaredMethods();
- for (Method m : methods) {
- if (m.getName().equals(methodName)) {
- return m;
- }
- }
- throw new NoSuchMethodException("No such method: '" + methodName + "' on type: '" + target.getClass().getSimpleName() + "'.");
- }
-
- public <T> T getSafely(T defaultValue, String methodName) {
- try {
- Method method = getMethod(methodName);
- method.setAccessible(true);
- return (T) method.invoke(target);
- } catch (NoSuchMethodException e) {
- return defaultValue;
- } catch (Exception e) {
- throw new RuntimeException("Unable to get value reflectively", e);
- }
- }
-
- public void callSafely(String methodName, Object ... params) {
- Method method;
- try {
- method = getMethod(methodName);
- } catch (NoSuchMethodException e) {
- return; // ignore
- }
-
- method.setAccessible(true);
- try {
- method.invoke(target, params);
- } catch (Exception e) {
- throw new RuntimeException("Unable to call method reflectively", e);
- }
- }
-}
\ No newline at end of file
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/BuildableElement.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/BuildableElement.java
index e8bf402..c4274b9 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/BuildableElement.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/BuildableElement.java
@@ -27,6 +27,7 @@ public interface BuildableElement extends Element {
* Returns the tasks of this project.
*
* @return The tasks of this project.
+ * @since 1.0-milestone-5
*/
DomainObjectSet<? extends Task> getTasks();
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/Element.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/Element.java
index 9529eaf..4623b84 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/Element.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/Element.java
@@ -29,6 +29,7 @@ public interface Element extends Model {
* Returns the name of the element. Note that the name is not a unique identifier.
*
* @return The name of the element.
+ * @since 1.0-milestone-5
*/
String getName();
@@ -36,6 +37,7 @@ public interface Element extends Model {
* Returns the description of the element, or {@code null} if it has no description.
*
* @return The description of the element, or {@code null} if it has no description.
+ * @since 1.0-milestone-5
*/
@Nullable
String getDescription();
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/ExternalDependency.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/ExternalDependency.java
index 49afadb..b2cc4e2 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/ExternalDependency.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/ExternalDependency.java
@@ -53,7 +53,7 @@ public interface ExternalDependency extends Dependency {
*
* @return The Gradle module information for this dependency, or {@code null} if the dependency does not
* originate from a remote repository.
- * @since 1.1-rc-1
+ * @since 1.1
*/
@Nullable
@Incubating
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/GradleModuleVersion.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/GradleModuleVersion.java
index 4a79ad0..a12f417 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/GradleModuleVersion.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/GradleModuleVersion.java
@@ -21,7 +21,7 @@ import org.gradle.api.Incubating;
/**
* Informs about a module version, i.e. group, name, version.
*
- * @since 1.1-rc-1
+ * @since 1.1
*/
@Incubating
public interface GradleModuleVersion {
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/GradleProject.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/GradleProject.java
index 98b9968..01602ba 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/GradleProject.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/GradleProject.java
@@ -16,19 +16,19 @@
package org.gradle.tooling.model;
+import org.gradle.api.Incubating;
import org.gradle.api.Nullable;
+import org.gradle.tooling.model.gradle.GradleScript;
/**
- * Gradle project.
+ * Represents a Gradle project.
*
* @since 1.0-milestone-5
*/
public interface GradleProject extends HierarchicalElement, BuildableElement {
/**
- * Returns the tasks of this project.
- *
- * @return The tasks.
+ * {@inheritDoc}
*/
DomainObjectSet<? extends GradleTask> getTasks();
@@ -43,17 +43,26 @@ public interface GradleProject extends HierarchicalElement, BuildableElement {
DomainObjectSet<? extends GradleProject> getChildren();
/**
- * Returns Gradle path.
+ * Returns the path of this project. This is a unique identifier for this project.
*
* @return The path.
*/
String getPath();
/**
- * Searches all descendants (children, grand children, etc.), including self, by given path.
+ * Searches all descendants (children, grand-children, etc.), including self, by given path.
*
* @return Gradle project with matching path or {@code null} if not found.
*/
@Nullable
GradleProject findByPath(String path);
+
+ /**
+ * Returns the build script for this project.
+ *
+ * @return The build script.
+ * @since 1.8
+ */
+ @Incubating
+ GradleScript getBuildScript();
}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/HierarchicalElement.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/HierarchicalElement.java
index d858c88..66cb93a 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/HierarchicalElement.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/HierarchicalElement.java
@@ -29,6 +29,7 @@ public interface HierarchicalElement extends Element {
* Returns the parent of this element, or {@code null} if there is no parent.
*
* @return The parent of this element, or {@code null} if there is no parent.
+ * @since 1.0-milestone-5
*/
@Nullable
HierarchicalElement getParent();
@@ -37,6 +38,7 @@ public interface HierarchicalElement extends Element {
* Returns the child elements, or the empty set if there are no child elements.
*
* @return The child elements, or the empty set if there are no child elements.
+ * @since 1.0-milestone-5
*/
DomainObjectSet<? extends HierarchicalElement> getChildren();
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/Model.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/Model.java
index d01bf9d..f423257 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/Model.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/Model.java
@@ -16,6 +16,7 @@
package org.gradle.tooling.model;
+// TODO:ADAM - Deprecate
/**
* A model that is buildable by the Tooling API. Models contain various information regarding the build.
* Models are typically tailored to a specific domain, for example build environment or IDE.
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/Task.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/Task.java
index 02ddddb..14c2cc2 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/Task.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/Task.java
@@ -19,12 +19,15 @@ import org.gradle.api.Nullable;
/**
* Represents a task which is executable by Gradle.
+ *
+ * @since 1.0-milestone-3
*/
public interface Task {
/**
* Returns the path of this task. This is a fully qualified unique name for this task.
*
* @return The path of this task.
+ * @since 1.0-milestone-3
*/
String getPath();
@@ -32,6 +35,7 @@ public interface Task {
* Returns the name of this task. Note that the name is not necessarily a unique identifier for the task.
*
* @return The name of this task.
+ * @since 1.0-milestone-3
*/
String getName();
@@ -39,6 +43,7 @@ public interface Task {
* Returns the description of this task, or {@code null} if it has no description.
*
* @return The description of this task, or {@code null} if it has no description.
+ * @since 1.0-milestone-3
*/
@Nullable
String getDescription();
@@ -47,6 +52,7 @@ public interface Task {
* Returns the element which this task belongs to.
*
* @return The element which this task belongs to.
+ * @since 1.0-milestone-3
*/
Element getProject();
}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/build/BuildEnvironment.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/build/BuildEnvironment.java
index 7319247..784944c 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/build/BuildEnvironment.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/build/BuildEnvironment.java
@@ -42,13 +42,16 @@ import org.gradle.tooling.model.UnsupportedMethodException;
public interface BuildEnvironment extends Model {
/**
- * Informs about the Gradle environment, for example the Gradle version.
+ * Returns information about the Gradle environment, for example the Gradle version.
+ *
+ * @since 1.0-milestone-8
*/
GradleEnvironment getGradle();
/**
- * Informs about the Java environment, for example the Java home or the JVM args used.
+ * Returns information about the Java environment, for example the Java home or the JVM args used.
*
+ * @since 1.0-milestone-8
* @throws org.gradle.tooling.model.UnsupportedMethodException
* when the Gradle version the tooling API is connected to does not support the Java environment information.
*/
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/build/GradleEnvironment.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/build/GradleEnvironment.java
index f4fe35c..e96d5ad 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/build/GradleEnvironment.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/build/GradleEnvironment.java
@@ -27,6 +27,8 @@ public interface GradleEnvironment {
/**
* Informs about the Gradle version.
+ *
+ * @since 1.0-milestone-8
*/
String getGradleVersion();
}
\ No newline at end of file
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/build/JavaEnvironment.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/build/JavaEnvironment.java
index 6571b69..f76c0de 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/build/JavaEnvironment.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/build/JavaEnvironment.java
@@ -29,6 +29,8 @@ public interface JavaEnvironment {
/**
* The Java home used for Gradle operations (for example running tasks or acquiring model information).
+ *
+ * @since 1.0-milestone-8
*/
File getJavaHome();
@@ -37,6 +39,8 @@ public interface JavaEnvironment {
* (for example running tasks or acquiring model information).
* The returned arguments do not include system properties passed as -Dfoo=bar.
* They may include implicitly immutable system properties like "file.encoding".
+ *
+ * @since 1.0-milestone-8
*/
List<String> getJvmArguments();
}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/build/package-info.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/build/package-info.java
index 1b23dc3..1f4f3df 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/build/package-info.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/build/package-info.java
@@ -15,6 +15,6 @@
*/
/**
- * Models the build environment information like Gradle or Java versions.
+ * Tooling models for the build environment, which includes information such as Gradle or Java versions.
*/
package org.gradle.tooling.model.build;
\ No newline at end of file
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/eclipse/EclipseLinkedResource.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/eclipse/EclipseLinkedResource.java
index f007053..ebbcdcc 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/eclipse/EclipseLinkedResource.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/eclipse/EclipseLinkedResource.java
@@ -26,7 +26,7 @@ public interface EclipseLinkedResource {
/**
* The project-relative path of the linked resource as it appears in the workspace.
* <p>
- * See the official eclipse documentation for most up-to-date information on properties of a linked resource
+ * See the official Eclipse documentation for most up-to-date information on properties of a linked resource
* <p>
* For example, a linked resource to a file system folder /some/path/to/someFolder can have a name 'someFolder'
*
@@ -43,9 +43,9 @@ public interface EclipseLinkedResource {
* "1" for file or folder when 'locationUri' first segment is a workspace path variable (or path variable navigation element),
* "2" for an eclipse virtual folder.
* <p>
- * See the official eclipse documentation for most up-to-date information on properties of a linked resource
+ * See the official Eclipse documentation for most up-to-date information on properties of a linked resource
*
- * @return eclipse link type
+ * @return Eclipse link type
*/
String getType();
@@ -53,7 +53,7 @@ public interface EclipseLinkedResource {
* The local file system absolute path of the target of the linked resource. For example: '/path/to/somewhere'.
* Mutually exclusive with 'locationUri'
* <p>
- * See the official eclipse documentation for most up-to-date information on properties of a linked resource
+ * See the official Eclipse documentation for most up-to-date information on properties of a linked resource
*
* @return location
*/
@@ -67,7 +67,7 @@ public interface EclipseLinkedResource {
* <p>
* Used for virtual folders. In that case the value is: 'virtual:/virtual'
* <p>
- * See the official eclipse documentation for most up-to-date information on properties of a linked resource
+ * See the official Eclipse documentation for most up-to-date information on properties of a linked resource
*
* @return location uri
*/
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/eclipse/EclipseProject.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/eclipse/EclipseProject.java
index 3d662c9..9160c1c 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/eclipse/EclipseProject.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/eclipse/EclipseProject.java
@@ -20,12 +20,12 @@ import org.gradle.tooling.model.ExternalDependency;
import org.gradle.tooling.model.GradleProject;
import org.gradle.tooling.model.HasGradleProject;
-import java.io.File;
-
/**
* The complete model of an Eclipse project.
*
* <p>Note that the names of Eclipse projects are unique, and can be used as an identifier for the project.
+ *
+ * @since 1.0-milestone-3
*/
public interface EclipseProject extends HierarchicalEclipseProject, HasGradleProject {
/**
@@ -40,7 +40,7 @@ public interface EclipseProject extends HierarchicalEclipseProject, HasGradlePro
/**
* The gradle project that is associated with this project.
- * Typically, a single eclipse project corresponds to a single gradle project.
+ * Typically, a single Eclipse project corresponds to a single gradle project.
* <p>
* See {@link HasGradleProject}
*
@@ -53,14 +53,7 @@ public interface EclipseProject extends HierarchicalEclipseProject, HasGradlePro
* Returns the external dependencies which make up the classpath of this project.
*
* @return The dependencies. Returns an empty set if the project has no external dependencies.
+ * @since 1.0-milestone-3
*/
DomainObjectSet<? extends ExternalDependency> getClasspath();
-
- /**
- * Returns the project directory for this project.
- *
- * @return The project directory.
- */
- File getProjectDirectory();
-
}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/eclipse/EclipseTask.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/eclipse/EclipseTask.java
index 8c3d7b2..4de0531 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/eclipse/EclipseTask.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/eclipse/EclipseTask.java
@@ -18,7 +18,10 @@ package org.gradle.tooling.model.eclipse;
import org.gradle.tooling.model.Task;
/**
- * Deprecated because gradle tasks are not associated with eclipse projects.
+ * Deprecated because Gradle tasks are not associated with Eclipse projects.
+ *
+ * @deprecated Use {@link EclipseProject#getGradleProject()} to determine the associated Gradle project for an Eclipse project,
+ * then use {@link org.gradle.tooling.model.GradleProject#getTasks()} to determine the tasks for the Gradle project.
*/
@Deprecated
public interface EclipseTask extends Task {
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/eclipse/HierarchicalEclipseProject.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/eclipse/HierarchicalEclipseProject.java
index 1c5e460..3010fd0 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/eclipse/HierarchicalEclipseProject.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/eclipse/HierarchicalEclipseProject.java
@@ -23,6 +23,8 @@ import java.io.File;
/**
* Represents the basic information about an Eclipse project.
+ *
+ * @since 1.0-milestone-3
*/
public interface HierarchicalEclipseProject extends HierarchicalElement {
/**
@@ -39,6 +41,7 @@ public interface HierarchicalEclipseProject extends HierarchicalElement {
* Returns the project dependencies for this project.
*
* @return The project dependencies. Returns an empty set if the project has no project dependencies.
+ * @since 1.0-milestone-3
*/
DomainObjectSet<? extends EclipseProjectDependency> getProjectDependencies();
@@ -46,6 +49,7 @@ public interface HierarchicalEclipseProject extends HierarchicalElement {
* Returns the source directories for this project.
*
* @return The source directories. Returns an empty set if the project has no source directories.
+ * @since 1.0-milestone-3
*/
DomainObjectSet<? extends EclipseSourceDirectory> getSourceDirectories();
@@ -64,6 +68,7 @@ public interface HierarchicalEclipseProject extends HierarchicalElement {
* Returns the project directory for this project.
*
* @return The project directory.
+ * @since 1.0-milestone-9
*/
File getProjectDirectory();
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/eclipse/package-info.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/eclipse/package-info.java
index a9281c3..2aaec75 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/eclipse/package-info.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/eclipse/package-info.java
@@ -15,6 +15,6 @@
*/
/**
- * An Eclipse-centric model of a Gradle build, provided by the Gradle tooling API.
+ * Eclipse-centric tooling models.
*/
package org.gradle.tooling.model.eclipse;
\ No newline at end of file
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/gradle/BasicGradleProject.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/gradle/BasicGradleProject.java
new file mode 100644
index 0000000..85a79cd
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/gradle/BasicGradleProject.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.model.gradle;
+
+import org.gradle.api.Incubating;
+import org.gradle.api.Nullable;
+import org.gradle.tooling.model.DomainObjectSet;
+import org.gradle.tooling.model.Model;
+
+import java.io.File;
+
+/**
+ * Provides some basic details about a Gradle project.
+ *
+ * @since 1.8
+ */
+ at Incubating
+public interface BasicGradleProject extends Model {
+ /**
+ * Returns the name of this project. Note that the name is not a unique identifier for the project.
+ *
+ * @return The name of this project.
+ */
+ String getName();
+
+ /**
+ * Returns the path of this project. The path can be used as a unique identifier for the project within a given build.
+ *
+ * @return The path of this project.
+ */
+ String getPath();
+
+ /**
+ * Returns the project directory for this project.
+ *
+ * @return The project directory.
+ */
+ File getProjectDirectory();
+
+ /**
+ * Returns the parent of this project, or {@code null} if this is the root project.
+ *
+ * @return The parent of this project, or {@code null} if this is the root project.
+ */
+ @Nullable
+ BasicGradleProject getParent();
+
+ /**
+ * Returns the child projects of this project, or the empty set if there are no child projects.
+ *
+ * @return The child projects of this project, or the empty set if there are no child projects.
+ * @since 1.0-milestone-5
+ */
+ DomainObjectSet<? extends BasicGradleProject> getChildren();
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/gradle/GradleBuild.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/gradle/GradleBuild.java
new file mode 100644
index 0000000..136fe8a
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/gradle/GradleBuild.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.model.gradle;
+
+import org.gradle.api.Incubating;
+import org.gradle.tooling.model.DomainObjectSet;
+
+/**
+ * Provides information about the structure of a Gradle build.
+ *
+ * @since 1.8
+ */
+ at Incubating
+public interface GradleBuild {
+ /**
+ * Returns the root project for this build.
+ *
+ * @return The root project
+ */
+ BasicGradleProject getRootProject();
+
+ /**
+ * Returns the set of all projects for this build. Will include the root project and any ancestors.
+ *
+ * @return The set of all projects.
+ */
+ DomainObjectSet<? extends BasicGradleProject> getProjects();
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/gradle/GradleScript.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/gradle/GradleScript.java
new file mode 100644
index 0000000..6632a12
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/gradle/GradleScript.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.model.gradle;
+
+import org.gradle.api.Incubating;
+import org.gradle.api.Nullable;
+
+import java.io.File;
+
+/**
+ * Represents a Gradle script. A Gradle script may be a build script, settings script or initialization script.
+ *
+ * @since 1.8
+ */
+ at Incubating
+public interface GradleScript {
+ /**
+ * Returns the source file for this script, or {@code null} if this script has no associated source file.
+ * If this method returns a non-null value, the given source file will exist.
+ *
+ * @return The source file. Returns null if the script has no associated source file.
+ * @since 1.8
+ */
+ @Nullable
+ File getSourceFile();
+}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/gradle/package-info.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/gradle/package-info.java
new file mode 100644
index 0000000..b9a6afe
--- /dev/null
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/gradle/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+/**
+ * The tooling models for Gradle builds and projects.
+ */
+package org.gradle.tooling.model.gradle;
\ No newline at end of file
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/idea/BasicIdeaProject.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/idea/BasicIdeaProject.java
index 578ac5b..8007ac1 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/idea/BasicIdeaProject.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/idea/BasicIdeaProject.java
@@ -21,6 +21,8 @@ package org.gradle.tooling.model.idea;
* Only project dependencies and local file dependencies are included on the modules' classpath.
* <p>
* Useful for 'previewing' the output model of IdeaProject because it is supposed to be fast (e.g. does not download dependencies from the web).
+ *
+ * @since 1.0-milestone-5
*/
public interface BasicIdeaProject extends IdeaProject {
}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/idea/IdeaModule.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/idea/IdeaModule.java
index b354858..592fe26 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/idea/IdeaModule.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/idea/IdeaModule.java
@@ -32,6 +32,7 @@ public interface IdeaModule extends HierarchicalElement, HasGradleProject {
* All content roots. Most idea modules have a single content root.
*
* @return content roots
+ * @since 1.0-milestone-5
*/
DomainObjectSet<? extends IdeaContentRoot> getContentRoots();
@@ -42,6 +43,7 @@ public interface IdeaModule extends HierarchicalElement, HasGradleProject {
* See {@link HasGradleProject}
*
* @return associated gradle project
+ * @since 1.0-milestone-5
*/
GradleProject getGradleProject();
@@ -50,6 +52,7 @@ public interface IdeaModule extends HierarchicalElement, HasGradleProject {
* Alias to {@link #getProject()}
*
* @return idea project
+ * @since 1.0-milestone-5
*/
IdeaProject getParent();
@@ -58,11 +61,14 @@ public interface IdeaModule extends HierarchicalElement, HasGradleProject {
* Alias to {@link #getParent()}
*
* @return idea project
+ * @since 1.0-milestone-5
*/
IdeaProject getProject();
/**
- * information about idea compiler output (output dirs, inheritance of output dir, etc.)
+ * Returns information about idea compiler output (output dirs, inheritance of output dir, etc.)
+ *
+ * @since 1.0-milestone-5
*/
IdeaCompilerOutput getCompilerOutput();
@@ -70,6 +76,7 @@ public interface IdeaModule extends HierarchicalElement, HasGradleProject {
* dependencies of this module (i.e. module dependencies, library dependencies, etc.)
*
* @return dependencies
+ * @since 1.0-milestone-5
*/
DomainObjectSet<? extends IdeaDependency> getDependencies();
}
\ No newline at end of file
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/idea/IdeaProject.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/idea/IdeaProject.java
index 5f43e3a..26bfb0f 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/idea/IdeaProject.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/idea/IdeaProject.java
@@ -17,7 +17,6 @@
package org.gradle.tooling.model.idea;
import org.gradle.tooling.model.DomainObjectSet;
-import org.gradle.tooling.model.Element;
import org.gradle.tooling.model.HierarchicalElement;
/**
@@ -25,12 +24,13 @@ import org.gradle.tooling.model.HierarchicalElement;
*
* @since 1.0-milestone-5
*/
-public interface IdeaProject extends HierarchicalElement, Element {
+public interface IdeaProject extends HierarchicalElement {
/**
* Returns the name of the JDK.
*
* @return The name of the JDK.
+ * @since 1.0-milestone-5
*/
String getJdkName();
@@ -38,6 +38,7 @@ public interface IdeaProject extends HierarchicalElement, Element {
* Returns the language level to use within the current project.
*
* @return The language level to use within the current project.
+ * @since 1.0-milestone-5
*/
IdeaLanguageLevel getLanguageLevel();
@@ -46,6 +47,7 @@ public interface IdeaProject extends HierarchicalElement, Element {
* Alias for {@link #getModules()}.
*
* @return The modules of this IDEA project.
+ * @since 1.0-milestone-5
*/
DomainObjectSet<? extends IdeaModule> getChildren();
@@ -54,6 +56,7 @@ public interface IdeaProject extends HierarchicalElement, Element {
* Alias for {@link #getChildren()}.
*
* @return The modules of this IDEA project.
+ * @since 1.0-milestone-5
*/
DomainObjectSet<? extends IdeaModule> getModules();
}
\ No newline at end of file
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/idea/package-info.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/idea/package-info.java
index 42ca84b..1911501 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/idea/package-info.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/idea/package-info.java
@@ -15,6 +15,6 @@
*/
/**
- * IntelliJ IDEA related API of the tooling API.
+ * IntelliJ IDEA centric tooling models.
*/
package org.gradle.tooling.model.idea;
\ No newline at end of file
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/internal/Exceptions.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/internal/Exceptions.java
index 85409dd..019aa4b 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/internal/Exceptions.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/internal/Exceptions.java
@@ -16,17 +16,18 @@
package org.gradle.tooling.model.internal;
+import org.gradle.tooling.UnknownModelException;
+import org.gradle.tooling.UnsupportedVersionException;
import org.gradle.tooling.exceptions.UnsupportedOperationConfigurationException;
+import org.gradle.tooling.internal.consumer.versioning.ModelMapping;
+import org.gradle.tooling.internal.protocol.InternalUnsupportedModelException;
import org.gradle.tooling.model.UnsupportedMethodException;
-/**
- * by Szczepan Faber, created at: 12/22/11
- */
public class Exceptions {
public final static String INCOMPATIBLE_VERSION_HINT =
"Most likely the model of that type is not supported in the target Gradle version."
- + "\nTo resolve the problem you can change/upgrade the Gradle version the tooling api connects to.";
+ + "\nTo resolve the problem you can change/upgrade the Gradle version the tooling api connects to.";
public static UnsupportedMethodException unsupportedMethod(String method) {
return new UnsupportedMethodException(formatUnsupportedModelMethod(method));
@@ -40,14 +41,32 @@ public class Exceptions {
, method);
}
- public static UnsupportedOperationConfigurationException unsupportedOperationConfiguration(String operation) {
- //we only need that cause for backwards-compatibility.
- UnsupportedMethodException cause = new UnsupportedMethodException(operation);
+ public static UnsupportedOperationConfigurationException unsupportedOperationConfiguration(String operation, String targetVersion) {
return new UnsupportedOperationConfigurationException(String.format("Unsupported configuration: %s."
+ "\nYou configured the LongRunningOperation (ModelBuilder or BuildLauncher) with an unsupported option."
- + "\nThe version of Gradle you connect to does not support this configuration option."
- + "\nTo resolve the problem you can change/upgrade the target version of Gradle you connect to."
- + "\nAlternatively, you may stop using this configuration option."
- , operation), cause);
+ + "\nThe version of Gradle are using (%s) does not support this configuration option."
+ + "\nTo resolve the problem you can change/upgrade the target version of Gradle."
+ , operation, targetVersion));
+ }
+
+ public static UnknownModelException unsupportedModel(Class<?> modelType, String targetVersion) {
+ ModelMapping modelMapping = new ModelMapping();
+ String versionAdded = modelMapping.getVersionAdded(modelType);
+ if (versionAdded != null) {
+ return new UnknownModelException(String.format("The version of Gradle you are using (%s) does not support building a model of type '%s'. Support for building '%s' models was added in Gradle %s and is available in all later versions.",
+ targetVersion, modelType.getSimpleName(), modelType.getSimpleName(), versionAdded));
+ } else {
+ return new UnknownModelException(String.format("The version of Gradle you are using (%s) does not support building a model of type '%s'. Support for building custom tooling models was added in Gradle 1.6 and is available in all later versions.",
+ targetVersion, modelType.getSimpleName()));
+ }
+ }
+
+ public static UnknownModelException unknownModel(Class<?> type, InternalUnsupportedModelException failure) {
+ return new UnknownModelException(String.format("No model of type '%s' is available in this build.", type.getSimpleName()), failure.getCause());
+ }
+
+ public static UnsupportedVersionException unsupportedFeature(String feature, String targetVersion, String versionAdded) {
+ return new UnsupportedVersionException(String.format("The version of Gradle you are using (%s) does not support %s. Support for this was added in Gradle %s and is available in all later versions.",
+ targetVersion, feature, versionAdded));
}
}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/internal/TestModel.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/internal/TestModel.java
deleted file mode 100644
index f93382e..0000000
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/internal/TestModel.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.model.internal;
-
-import org.gradle.tooling.model.Element;
-
-/**
- * For testing purposes only
- * <p>
- * by Szczepan Faber, created at: 12/21/11
- */
-public interface TestModel extends Element {}
diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/package-info.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/package-info.java
index 4280ecb..0ee0633 100644
--- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/package-info.java
+++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/package-info.java
@@ -15,6 +15,6 @@
*/
/**
- * A UI-centric model of a Gradle build, provided by the Gradle tooling API.
+ * The general-purpose tooling model types, provided by the tooling API.
*/
package org.gradle.tooling.model;
\ No newline at end of file
diff --git a/subprojects/tooling-api/src/test/groovy/org/gradle/integtests/tooling/fixture/GradleVersionSpecTest.groovy b/subprojects/tooling-api/src/test/groovy/org/gradle/integtests/tooling/fixture/GradleVersionSpecTest.groovy
new file mode 100644
index 0000000..9063ce9
--- /dev/null
+++ b/subprojects/tooling-api/src/test/groovy/org/gradle/integtests/tooling/fixture/GradleVersionSpecTest.groovy
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests.tooling.fixture
+
+import org.gradle.util.GradleVersion
+import spock.lang.Specification
+
+class GradleVersionSpecTest extends Specification {
+ def "greater-than-or-equal version constraint matches all versions with specified base version and later"() {
+ def spec = GradleVersionSpec.toSpec(">=1.0")
+
+ expect:
+ spec.isSatisfiedBy(GradleVersion.version("1.0"))
+ spec.isSatisfiedBy(GradleVersion.version("1.0-rc-1"))
+ spec.isSatisfiedBy(GradleVersion.version("1.0-12341010120000+1000"))
+ spec.isSatisfiedBy(GradleVersion.version("1.1"))
+ spec.isSatisfiedBy(GradleVersion.version("1.1-rc-7"))
+ spec.isSatisfiedBy(GradleVersion.version("1.1-12341010120000+1000"))
+ spec.isSatisfiedBy(GradleVersion.version("2.56"))
+
+ !spec.isSatisfiedBy(GradleVersion.version("1.0-milestone-9"))
+ !spec.isSatisfiedBy(GradleVersion.version("0.9.2"))
+ !spec.isSatisfiedBy(GradleVersion.version("0.5"))
+ }
+
+ def "less-than-or-equal version constraint matches all versions with specified base version and earlier"() {
+ def spec = GradleVersionSpec.toSpec("<=1.4")
+
+ expect:
+ spec.isSatisfiedBy(GradleVersion.version("1.4"))
+ spec.isSatisfiedBy(GradleVersion.version("1.4-rc-1"))
+ spec.isSatisfiedBy(GradleVersion.version("1.4-12341010120000+1000"))
+ spec.isSatisfiedBy(GradleVersion.version("1.3"))
+ spec.isSatisfiedBy(GradleVersion.version("1.3-rc-7"))
+ spec.isSatisfiedBy(GradleVersion.version("1.3-12341010120000+1000"))
+ spec.isSatisfiedBy(GradleVersion.version("1.0-milestone-9"))
+ spec.isSatisfiedBy(GradleVersion.version("0.9.2"))
+
+ !spec.isSatisfiedBy(GradleVersion.version("1.5"))
+ !spec.isSatisfiedBy(GradleVersion.version("1.5-rc-1"))
+ !spec.isSatisfiedBy(GradleVersion.version("12.45"))
+ }
+
+ def "less-than version constraint matches versions earlier than specified version"() {
+ def spec = GradleVersionSpec.toSpec("<1.4")
+
+ expect:
+ spec.isSatisfiedBy(GradleVersion.version("1.3"))
+ spec.isSatisfiedBy(GradleVersion.version("1.3-rc-7"))
+ spec.isSatisfiedBy(GradleVersion.version("1.3-12341010120000+1000"))
+ spec.isSatisfiedBy(GradleVersion.version("1.0-milestone-9"))
+ spec.isSatisfiedBy(GradleVersion.version("0.9.2"))
+
+ !spec.isSatisfiedBy(GradleVersion.version("1.4"))
+ !spec.isSatisfiedBy(GradleVersion.version("1.4-rc-1"))
+ !spec.isSatisfiedBy(GradleVersion.version("1.4-12341010120000+1000"))
+ !spec.isSatisfiedBy(GradleVersion.version("1.5"))
+ !spec.isSatisfiedBy(GradleVersion.version("1.5-rc-1"))
+ !spec.isSatisfiedBy(GradleVersion.version("12.45"))
+ }
+
+ def "equals version constraint matches versions with same base version"() {
+ def spec = GradleVersionSpec.toSpec("=1.4")
+
+ expect:
+ spec.isSatisfiedBy(GradleVersion.version("1.4"))
+ spec.isSatisfiedBy(GradleVersion.version("1.4-rc-7"))
+ spec.isSatisfiedBy(GradleVersion.version("1.4-12341010120000+1000"))
+
+ !spec.isSatisfiedBy(GradleVersion.version("1.0-milestone-9"))
+ !spec.isSatisfiedBy(GradleVersion.version("0.9.2"))
+ !spec.isSatisfiedBy(GradleVersion.version("1.5"))
+ !spec.isSatisfiedBy(GradleVersion.version("1.5-rc-1"))
+ !spec.isSatisfiedBy(GradleVersion.version("1.5-12341010120000+1000"))
+ !spec.isSatisfiedBy(GradleVersion.version("12.45"))
+ }
+
+ def "current version constraint matches current version"() {
+ def spec = GradleVersionSpec.toSpec("current")
+
+ expect:
+ spec.isSatisfiedBy(GradleVersion.current())
+
+ !spec.isSatisfiedBy(GradleVersion.version("1.0-milestone-9"))
+ !spec.isSatisfiedBy(GradleVersion.version("1.4-rc-7"))
+ !spec.isSatisfiedBy(GradleVersion.version("1.4-12341010120000+1000"))
+ !spec.isSatisfiedBy(GradleVersion.version("0.9.2"))
+ !spec.isSatisfiedBy(GradleVersion.version("1.5"))
+ !spec.isSatisfiedBy(GradleVersion.version("1.5-rc-1"))
+ !spec.isSatisfiedBy(GradleVersion.version("1.5-12341010120000+1000"))
+ !spec.isSatisfiedBy(GradleVersion.version("12.45"))
+ }
+
+ def "not current version constraint matches everything other than current version"() {
+ def spec = GradleVersionSpec.toSpec("!current")
+
+ expect:
+ !spec.isSatisfiedBy(GradleVersion.current())
+
+ spec.isSatisfiedBy(GradleVersion.version("1.0-milestone-9"))
+ spec.isSatisfiedBy(GradleVersion.version("1.4-rc-7"))
+ spec.isSatisfiedBy(GradleVersion.version("1.4-12341010120000+1000"))
+ spec.isSatisfiedBy(GradleVersion.version("0.9.2"))
+ spec.isSatisfiedBy(GradleVersion.version("1.5"))
+ spec.isSatisfiedBy(GradleVersion.version("1.5-rc-1"))
+ spec.isSatisfiedBy(GradleVersion.version("1.5-12341010120000+1000"))
+ spec.isSatisfiedBy(GradleVersion.version("12.45"))
+ }
+
+ def "range constraint matches all versions inside range"() {
+ def spec = GradleVersionSpec.toSpec(">=1.0 <=1.4")
+
+ expect:
+ spec.isSatisfiedBy(GradleVersion.version("1.0"))
+ spec.isSatisfiedBy(GradleVersion.version("1.0-rc-1"))
+ spec.isSatisfiedBy(GradleVersion.version("1.0-12341010120000+1000"))
+ spec.isSatisfiedBy(GradleVersion.version("1.1"))
+ spec.isSatisfiedBy(GradleVersion.version("1.1-rc-1"))
+ spec.isSatisfiedBy(GradleVersion.version("1.1-12341010120000+1000"))
+ spec.isSatisfiedBy(GradleVersion.version("1.4"))
+ spec.isSatisfiedBy(GradleVersion.version("1.4-rc-1"))
+ spec.isSatisfiedBy(GradleVersion.version("1.4-12341010120000+1000"))
+
+ !spec.isSatisfiedBy(GradleVersion.version("1.0-milestone-9"))
+ !spec.isSatisfiedBy(GradleVersion.version("0.9.2"))
+ !spec.isSatisfiedBy(GradleVersion.version("0.5"))
+
+ !spec.isSatisfiedBy(GradleVersion.version("1.5"))
+ !spec.isSatisfiedBy(GradleVersion.version("1.5-rc-1"))
+ !spec.isSatisfiedBy(GradleVersion.version("12.45"))
+ }
+}
diff --git a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/adapter/CollectionMapperTest.groovy b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/adapter/CollectionMapperTest.groovy
new file mode 100644
index 0000000..ba47a16
--- /dev/null
+++ b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/adapter/CollectionMapperTest.groovy
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.adapter
+
+import org.gradle.tooling.model.DomainObjectSet
+import spock.lang.Specification
+
+class CollectionMapperTest extends Specification {
+ final def mapper = new CollectionMapper()
+
+ def "maps collection types"() {
+ expect:
+ def collection = mapper.createEmptyCollection(sourceType)
+ collection.class == collectionType
+
+ where:
+ sourceType | collectionType
+ Collection | ArrayList
+ List | ArrayList
+ DomainObjectSet | ArrayList
+ Set | LinkedHashSet
+ SortedSet | TreeSet
+ }
+
+ def "maps map types"() {
+ expect:
+ def map = mapper.createEmptyMap(sourceType)
+ map.getClass() == mapType
+
+ where:
+ sourceType | mapType
+ Map | LinkedHashMap
+ SortedMap | TreeMap
+ }
+}
diff --git a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/adapter/CompatibleIntrospectorTest.groovy b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/adapter/CompatibleIntrospectorTest.groovy
new file mode 100644
index 0000000..ebe4072
--- /dev/null
+++ b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/adapter/CompatibleIntrospectorTest.groovy
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.adapter
+
+import spock.lang.Specification
+
+class CompatibleIntrospectorTest extends Specification {
+
+ class Foo {
+
+ int number
+
+ String getMessage() {
+ "Hello!"
+ }
+
+ String getBroken() {
+ throw new ArithmeticException("broken")
+ }
+
+ void setNumber(int number) {
+ this.number = number
+ }
+ }
+
+ def foo = new Foo()
+ def intro = new CompatibleIntrospector(foo)
+
+ def "gets stuff safely"() {
+ expect:
+ 'Hello!' == intro.getSafely('blah', 'getMessage')
+ 'blah' == intro.getSafely('blah', 'doesNotExist')
+ }
+
+ def "propagates failure to get value"() {
+ when:
+ intro.getSafely('default', 'getBroken')
+
+ then:
+ ArithmeticException e = thrown()
+ e.message == 'broken'
+ }
+
+ def "calls methods safely"() {
+ when:
+ intro.callSafely('doesNotExist', 10)
+ then:
+ foo.number == 0
+
+ when:
+ intro.callSafely('setNumber', 10)
+ then:
+ foo.number == 10
+ }
+
+ def "propagates failure to call method"() {
+ when:
+ intro.callSafely('getBroken')
+
+ then:
+ ArithmeticException e = thrown()
+ e.message == 'broken'
+ }
+
+}
diff --git a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/adapter/ProtocolToModelAdapterTest.groovy b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/adapter/ProtocolToModelAdapterTest.groovy
new file mode 100644
index 0000000..72d3531
--- /dev/null
+++ b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/adapter/ProtocolToModelAdapterTest.groovy
@@ -0,0 +1,467 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.adapter
+
+import org.gradle.api.Action
+import org.gradle.messaging.remote.internal.Message
+import org.gradle.tooling.model.DomainObjectSet
+import org.gradle.tooling.model.UnsupportedMethodException
+import org.gradle.util.Matchers
+import spock.lang.Specification
+
+import java.lang.reflect.InvocationHandler
+import java.nio.channels.ByteChannel
+import java.nio.channels.Channel
+
+class ProtocolToModelAdapterTest extends Specification {
+ final ProtocolToModelAdapter adapter = new ProtocolToModelAdapter()
+
+ def mapsNullToNull() {
+ expect:
+ adapter.adapt(TestModel.class, null) == null
+ }
+
+ def createsProxyAdapterForProtocolModel() {
+ TestProtocolModel protocolModel = Mock()
+
+ expect:
+ adapter.adapt(TestModel.class, protocolModel) instanceof TestModel
+ }
+
+ def proxiesAreEqualWhenTargetProtocolObjectsAreEqual() {
+ TestProtocolModel protocolModel1 = Mock()
+ TestProtocolModel protocolModel2 = Mock()
+
+ def model = adapter.adapt(TestModel.class, protocolModel1)
+ def equal = adapter.adapt(TestModel.class, protocolModel1)
+ def different = adapter.adapt(TestModel.class, protocolModel2)
+
+ expect:
+ Matchers.strictlyEquals(model, equal)
+ model != different
+ }
+
+ def methodInvocationOnModelDelegatesToTheProtocolModelObject() {
+ TestProtocolModel protocolModel = Mock()
+ _ * protocolModel.getName() >> 'name'
+
+ expect:
+ def model = adapter.adapt(TestModel.class, protocolModel)
+ model.name == 'name'
+ }
+
+ def createsProxyAdapterForMethodReturnValue() {
+ TestProtocolModel protocolModel = Mock()
+ TestProtocolProject protocolProject = Mock()
+ _ * protocolModel.getProject() >> protocolProject
+ _ * protocolProject.getName() >> 'name'
+
+ expect:
+ def model = adapter.adapt(TestModel.class, protocolModel)
+ model.project instanceof TestProject
+ model.project.name == 'name'
+ }
+
+ def doesNotAdaptNullReturnValue() {
+ TestProtocolModel protocolModel = Mock()
+ _ * protocolModel.getProject() >> null
+
+ expect:
+ def model = adapter.adapt(TestModel.class, protocolModel)
+ model.project == null
+ }
+
+ def adaptsIterableToDomainObjectSet() {
+ TestProtocolModel protocolModel = Mock()
+ TestProtocolProject protocolProject = Mock()
+ _ * protocolModel.getChildren() >> [protocolProject]
+ _ * protocolProject.getName() >> 'name'
+
+ expect:
+ def model = adapter.adapt(TestModel.class, protocolModel)
+ model.children.size() == 1
+ model.children[0] instanceof TestProject
+ model.children[0].name == 'name'
+ }
+
+ def adaptsIterableToCollectionType() {
+ TestProtocolModel protocolModel = Mock()
+ TestProtocolProject protocolProject = Mock()
+ _ * protocolModel.getChildList() >> [protocolProject]
+ _ * protocolProject.getName() >> 'name'
+
+ expect:
+ def model = adapter.adapt(TestModel.class, protocolModel)
+ model.childList.size() == 1
+ model.childList[0] instanceof TestProject
+ model.childList[0].name == 'name'
+ }
+
+ def adaptsMapElements() {
+ TestProtocolModel protocolModel = Mock()
+ TestProtocolProject protocolProject = Mock()
+ _ * protocolModel.project >> protocolProject
+ _ * protocolModel.getChildMap() >> Collections.singletonMap(protocolProject, protocolProject)
+ _ * protocolProject.getName() >> 'name'
+
+ expect:
+ def model = adapter.adapt(TestModel.class, protocolModel)
+ model.childMap.size() == 1
+ model.childMap[model.project] == model.project
+ }
+
+ def cachesPropertyValues() {
+ TestProtocolModel protocolModel = Mock()
+ TestProtocolProject protocolProject = Mock()
+ _ * protocolModel.getProject() >> protocolProject
+ _ * protocolModel.getChildren() >> [protocolProject]
+ _ * protocolProject.getName() >> 'name'
+
+ expect:
+ def model = adapter.adapt(TestModel.class, protocolModel)
+ model.project.is(model.project)
+ model.children.is(model.children)
+ }
+
+ def reportsMethodWhichDoesNotExistOnProtocolObject() {
+ PartialTestProtocolModel protocolModel = Mock()
+
+ when:
+ def model = adapter.adapt(TestModel.class, protocolModel)
+ model.project
+
+ then:
+ UnsupportedMethodException e = thrown()
+ e.message.contains "TestModel.getProject()"
+ }
+
+ def propagatesExceptionThrownByProtocolObject() {
+ TestProtocolModel protocolModel = Mock()
+ RuntimeException failure = new RuntimeException()
+
+ when:
+ def model = adapter.adapt(TestModel.class, protocolModel)
+ model.name
+
+ then:
+ protocolModel.name >> { throw failure }
+ RuntimeException e = thrown()
+ e == failure
+ }
+
+ def isPropertySupportedMethodReturnsTrueWhenProtocolObjectHasAssociatedProperty() {
+ TestProtocolModel protocolModel = Mock()
+
+ when:
+ def model = adapter.adapt(TestModel.class, protocolModel)
+
+ then:
+ model.configSupported
+ }
+
+ def isPropertySupportedMethodReturnsFalseWhenProtocolObjectDoesNotHaveAssociatedProperty() {
+ PartialTestProtocolModel protocolModel = Mock()
+
+ when:
+ def model = adapter.adapt(TestModel.class, protocolModel)
+
+ then:
+ !model.configSupported
+ }
+
+ def safeGetterDelegatesToProtocolObject() {
+ TestProtocolModel protocolModel = Mock()
+
+ given:
+ protocolModel.config >> "value"
+
+ when:
+ def model = adapter.adapt(TestModel.class, protocolModel)
+
+ then:
+ model.getConfig("default") == "value"
+ }
+
+ def safeGetterDelegatesReturnsDefaultValueWhenProtocolObjectDoesNotHaveAssociatedProperty() {
+ PartialTestProtocolModel protocolModel = Mock()
+
+ when:
+ def model = adapter.adapt(TestModel.class, protocolModel)
+
+ then:
+ model.getConfig("default") == "default"
+ }
+
+ def safeGetterDelegatesReturnsDefaultValueWhenPropertyValueIsNull() {
+ TestProtocolModel protocolModel = Mock()
+
+ given:
+ protocolModel.config >> null
+
+ when:
+ def model = adapter.adapt(TestModel.class, protocolModel)
+
+ then:
+ model.getConfig("default") == "default"
+ }
+
+ def "mapper can override getter method"() {
+ MethodInvoker methodInvoker = Mock()
+ Action mapper = Mock()
+ TestProtocolModel protocolModel = Mock()
+ TestProject project = Mock()
+
+ given:
+ mapper.execute(_) >> { SourceObjectMapping mapping ->
+ mapping.mixIn(methodInvoker)
+ }
+ methodInvoker.invoke({ it.name == 'getProject' }) >> { MethodInvocation method -> method.result = project }
+
+ when:
+ def model = adapter.adapt(TestModel.class, protocolModel, mapper)
+
+ then:
+ model.project == project
+
+ and:
+ 0 * protocolModel._
+ }
+
+ def "mapper can provider getter method implementation"() {
+ MethodInvoker methodInvoker = Mock()
+ Action mapper = Mock()
+ PartialTestProtocolModel protocolModel = Mock()
+ TestProject project = Mock()
+
+ given:
+ mapper.execute(_) >> { SourceObjectMapping mapping ->
+ mapping.mixIn(methodInvoker)
+ }
+ methodInvoker.invoke({ it.name == 'getProject' }) >> { MethodInvocation method -> method.result = project }
+
+ when:
+ def model = adapter.adapt(TestModel.class, protocolModel, mapper)
+
+ then:
+ model.project == project
+
+ and:
+ 0 * protocolModel._
+ }
+
+ def methodInvokerPropertiesAreCached() {
+ MethodInvoker methodInvoker = Mock()
+ Action mapper = Mock()
+ PartialTestProtocolModel protocolModel = Mock()
+ TestProject project = Mock()
+
+ given:
+ mapper.execute(_) >> { SourceObjectMapping mapping ->
+ mapping.mixIn(methodInvoker)
+ }
+
+ when:
+ def model = adapter.adapt(TestModel.class, protocolModel, mapper)
+ model.project
+ model.project
+
+ then:
+ 1 * methodInvoker.invoke(!null) >> { MethodInvocation method -> method.result = project }
+ 0 * methodInvoker._
+ 0 * protocolModel._
+ }
+
+ def canMixInMethodsFromAnotherBean() {
+ PartialTestProtocolModel protocolModel = Mock()
+
+ given:
+ protocolModel.name >> 'name'
+
+ when:
+ def model = adapter.adapt(TestModel.class, protocolModel, ConfigMixin)
+
+ then:
+ model.name == "[name]"
+ model.getConfig('default') == "[default]"
+ }
+
+ def "mapper can mix in methods from another bean"() {
+ def mapper = Mock(Action)
+ def protocolModel = Mock(PartialTestProtocolModel)
+
+ given:
+ protocolModel.name >> 'name'
+
+ when:
+ def model = adapter.adapt(TestModel.class, protocolModel, mapper)
+
+ then:
+ 1 * mapper.execute({it.sourceObject == protocolModel}) >> { SourceObjectMapping mapping ->
+ mapping.mixIn(ConfigMixin)
+ }
+
+ and:
+ model.name == "[name]"
+ model.getConfig('default') == "[default]"
+ }
+
+ def "delegates to type provider to determine type to wrap an object in"() {
+ def typeProvider = Mock(TargetTypeProvider)
+ def adapter = new ProtocolToModelAdapter(typeProvider)
+ def sourceObject = new Object()
+
+ given:
+ _ * typeProvider.getTargetType(Channel, sourceObject) >> ByteChannel
+
+ when:
+ def result = adapter.adapt(Channel.class, sourceObject)
+
+ then:
+ result instanceof ByteChannel
+ }
+
+ def "mapper can specify the type to wrap an object in"() {
+ def mapper = Mock(Action)
+ def sourceObject = Mock(TestProtocolModel)
+ def sourceProject = Mock(TestProtocolProject)
+ def adapter = new ProtocolToModelAdapter()
+
+ given:
+ sourceObject.project >> sourceProject
+
+ when:
+ def result = adapter.adapt(TestModel.class, sourceObject, mapper)
+
+ then:
+ 1 * mapper.execute({it.sourceObject == sourceObject})
+
+ when:
+ def project = result.project
+
+ then:
+ project instanceof TestExtendedProject
+
+ and:
+ 1 * mapper.execute({it.sourceObject == sourceProject}) >> { SourceObjectMapping mapping ->
+ mapping.mapToType(TestExtendedProject)
+ }
+ }
+
+ def "view objects can be serialized"() {
+ def protocolModel = new TestProtocolProjectImpl()
+
+ given:
+ def model = adapter.adapt(TestProject.class, protocolModel)
+
+ expect:
+ def serialized = new ByteArrayOutputStream()
+ Message.send(model, serialized)
+ def copiedModel = Message.receive(new ByteArrayInputStream(serialized.toByteArray()), getClass().classLoader)
+ copiedModel instanceof TestProject
+ copiedModel != model
+ copiedModel.name == "name"
+ }
+
+ def "unpacks source object from view"() {
+ def source = new Object()
+
+ given:
+ def view = adapter.adapt(TestProject.class, source)
+
+ expect:
+ adapter.unpack(view).is(source)
+ }
+
+ def "fails when source object is not a view object"() {
+ when:
+ adapter.unpack("not a view")
+
+ then:
+ thrown(IllegalArgumentException)
+
+ when:
+ adapter.unpack(java.lang.reflect.Proxy.newProxyInstance(getClass().classLoader, [Runnable] as Class[], Stub(InvocationHandler)))
+
+ then:
+ thrown(IllegalArgumentException)
+ }
+}
+
+interface TestModel {
+ String getName()
+
+ TestProject getProject()
+
+ boolean isConfigSupported()
+
+ String getConfig(String defaultValue)
+
+ DomainObjectSet<? extends TestProject> getChildren()
+
+ List<TestProject> getChildList()
+
+ Map<TestProject, TestProject> getChildMap()
+}
+
+interface TestProject {
+ String getName()
+}
+
+interface TestExtendedProject extends TestProject {
+}
+
+interface TestProtocolModel {
+ String getName()
+
+ TestProtocolProject getProject()
+
+ Iterable<? extends TestProtocolProject> getChildren()
+
+ Iterable<? extends TestProtocolProject> getChildList()
+
+ Map<String, ? extends TestProtocolProject> getChildMap()
+
+ String getConfig();
+}
+
+interface PartialTestProtocolModel {
+ String getName()
+}
+
+interface TestProtocolProject {
+ String getName()
+}
+
+class TestProtocolProjectImpl implements Serializable {
+ String name = "name"
+}
+
+class ConfigMixin {
+ TestModel model
+
+ ConfigMixin(TestModel model) {
+ this.model = model
+ }
+
+ String getConfig(String value) {
+ return "[${model.getConfig(value)}]"
+ }
+
+ String getName() {
+ return "[${model.name}]"
+ }
+}
diff --git a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/ConnectionFactoryTest.groovy b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/ConnectionFactoryTest.groovy
index 5095c2d..0502d77 100644
--- a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/ConnectionFactoryTest.groovy
+++ b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/ConnectionFactoryTest.groovy
@@ -17,10 +17,10 @@ package org.gradle.tooling.internal.consumer
import org.gradle.listener.ListenerManager
import org.gradle.logging.ProgressLoggerFactory
-import org.gradle.tooling.internal.consumer.async.DefaultAsyncConnection
-import org.gradle.tooling.internal.consumer.connection.LazyConnection
-import org.gradle.tooling.internal.consumer.connection.LoggingInitializerConnection
-import org.gradle.tooling.internal.consumer.connection.ProgressLoggingConnection
+import org.gradle.tooling.internal.consumer.async.DefaultAsyncConsumerActionExecutor
+import org.gradle.tooling.internal.consumer.connection.LazyConsumerActionExecutor
+import org.gradle.tooling.internal.consumer.connection.LoggingInitializerConsumerActionExecutor
+import org.gradle.tooling.internal.consumer.connection.ProgressLoggingConsumerActionExecutor
import org.gradle.tooling.internal.consumer.loader.ToolingImplementationLoader
import spock.lang.Specification
@@ -38,10 +38,11 @@ class ConnectionFactoryTest extends Specification {
then:
result instanceof DefaultProjectConnection
- result.connection instanceof DefaultAsyncConnection
- result.connection.connection instanceof LoggingInitializerConnection
- result.connection.connection.connection instanceof ProgressLoggingConnection
- result.connection.connection.connection.connection instanceof LazyConnection
+ result.connection instanceof DefaultAsyncConsumerActionExecutor
+ result.connection.actionExecutor instanceof LoggingInitializerConsumerActionExecutor
+ result.connection.actionExecutor.actionExecutor instanceof ProgressLoggingConsumerActionExecutor
+ result.connection.actionExecutor.actionExecutor.actionExecutor instanceof LazyConsumerActionExecutor
+ _ * distribution.displayName >> "[some distribution]"
0 * _._
}
}
diff --git a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/ConnectorServicesTest.groovy b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/ConnectorServicesTest.groovy
index 8d15931..c5c581e 100644
--- a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/ConnectorServicesTest.groovy
+++ b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/ConnectorServicesTest.groovy
@@ -19,9 +19,6 @@ package org.gradle.tooling.internal.consumer;
import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 12/6/11
- */
public class ConnectorServicesTest extends Specification {
def "services sharing configuration"() {
diff --git a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/DefaultBuildActionExecuterTest.groovy b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/DefaultBuildActionExecuterTest.groovy
new file mode 100644
index 0000000..6384451
--- /dev/null
+++ b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/DefaultBuildActionExecuterTest.groovy
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.consumer
+
+import org.gradle.test.fixtures.concurrent.ConcurrentSpec
+import org.gradle.tooling.BuildAction
+import org.gradle.tooling.GradleConnectionException
+import org.gradle.tooling.ResultHandler
+import org.gradle.tooling.internal.consumer.async.AsyncConsumerActionExecutor
+import org.gradle.tooling.internal.consumer.connection.ConsumerAction
+import org.gradle.tooling.internal.consumer.connection.ConsumerConnection
+import org.gradle.tooling.internal.protocol.ResultHandlerVersion1
+import org.gradle.tooling.model.GradleProject
+
+class DefaultBuildActionExecuterTest extends ConcurrentSpec {
+ def asyncConnection = Mock(AsyncConsumerActionExecutor)
+ def connection = Mock(ConsumerConnection)
+ def parameters = Mock(ConnectionParameters)
+ def action = Mock(BuildAction)
+ def executer = new DefaultBuildActionExecuter(action, asyncConnection, parameters)
+
+ def "delegates to connection to run action"() {
+ ResultHandlerVersion1<GradleProject> adaptedHandler
+ ResultHandler<GradleProject> handler = Mock()
+ GradleProject result = Mock()
+
+ when:
+ executer.run(handler)
+
+ then:
+ 1 * asyncConnection.run(!null, !null) >> {args ->
+ ConsumerAction<GradleProject> action = args[0]
+ action.run(connection)
+ adaptedHandler = args[1]
+ }
+ 1 * connection.run(action, _) >> result
+
+ when:
+ adaptedHandler.onComplete(result)
+
+ then:
+ 1 * handler.onComplete(result)
+ 0 * _._
+ }
+
+ def "notifies handler of failure"() {
+ ResultHandlerVersion1<GradleProject> adaptedHandler
+ ResultHandler<GradleProject> handler = Mock()
+ RuntimeException failure = new RuntimeException()
+ GradleConnectionException wrappedFailure
+
+ when:
+ executer.run(handler)
+
+ then:
+ 1 * asyncConnection.run(!null, !null) >> {args ->
+ adaptedHandler = args[1]
+ adaptedHandler.onFailure(failure)
+ }
+
+ and:
+ 1 * handler.onFailure(!null) >> {args -> wrappedFailure = args[0] }
+ _ * asyncConnection.displayName >> '[connection]'
+ wrappedFailure.message == 'Could not run build action using [connection].'
+ wrappedFailure.cause.is(failure)
+ 0 * _._
+ }
+
+ def "running action does not block"() {
+ GradleProject result = Mock()
+ ResultHandler<GradleProject> handler = Mock()
+
+ given:
+ asyncConnection.run(!null, !null) >> { args ->
+ def wrappedHandler = args[1]
+ start {
+ thread.blockUntil.dispatched
+ instant.resultAvailable
+ wrappedHandler.onComplete(result)
+ }
+ }
+ handler.onComplete(result) >> {
+ instant.resultReceived
+ }
+
+ when:
+ async {
+ executer.run(handler)
+ instant.dispatched
+ thread.blockUntil.resultReceived
+ }
+
+ then:
+ instant.dispatched < instant.resultAvailable
+ instant.resultAvailable < instant.resultReceived
+ }
+
+ def "run() blocks until result is available"() {
+ GradleProject result = Mock()
+
+ given:
+ asyncConnection.run(!null, !null) >> { args ->
+ def handler = args[1]
+ start {
+ thread.block()
+ instant.resultAvailable
+ handler.onComplete(result)
+ }
+ }
+
+ when:
+ def model
+ operation.fetchResult {
+ model = executer.run()
+ }
+
+ then:
+ model == result
+
+ and:
+ operation.fetchResult.end > instant.resultAvailable
+ }
+
+ def "run() blocks until request fails"() {
+ RuntimeException failure = new RuntimeException()
+
+ given:
+ asyncConnection.run(!null, !null) >> { args ->
+ def handler = args[1]
+ start {
+ thread.block()
+ instant.failureAvailable
+ handler.onFailure(failure)
+ }
+ }
+
+ when:
+ operation.fetchResult {
+ executer.run()
+ }
+
+ then:
+ GradleConnectionException e = thrown()
+ e.cause.is(failure)
+
+ and:
+ operation.fetchResult.end > instant.failureAvailable
+ }
+
+}
diff --git a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/DefaultBuildLauncherTest.groovy b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/DefaultBuildLauncherTest.groovy
index a04f8b7..d5030cf 100644
--- a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/DefaultBuildLauncherTest.groovy
+++ b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/DefaultBuildLauncherTest.groovy
@@ -15,140 +15,184 @@
*/
package org.gradle.tooling.internal.consumer
+import org.gradle.test.fixtures.concurrent.ConcurrentSpec
import org.gradle.tooling.GradleConnectionException
import org.gradle.tooling.ResultHandler
-import org.gradle.tooling.internal.consumer.async.AsyncConnection
+import org.gradle.tooling.internal.consumer.async.AsyncConsumerActionExecutor
+import org.gradle.tooling.internal.consumer.connection.ConsumerAction
+import org.gradle.tooling.internal.consumer.connection.ConsumerConnection
+import org.gradle.tooling.internal.consumer.parameters.ConsumerOperationParameters
+import org.gradle.tooling.internal.protocol.ResultHandlerVersion1
+import org.gradle.tooling.model.GradleProject
import org.gradle.tooling.model.Task
-import org.gradle.util.ConcurrentSpecification
-class DefaultBuildLauncherTest extends ConcurrentSpecification {
- final AsyncConnection protocolConnection = Mock()
+class DefaultBuildLauncherTest extends ConcurrentSpec {
+ final AsyncConsumerActionExecutor asyncConnection = Mock()
+ final ConsumerConnection connection = Mock()
final ConnectionParameters parameters = Mock()
- final DefaultBuildLauncher launcher = new DefaultBuildLauncher(protocolConnection, parameters)
+ final DefaultBuildLauncher launcher = new DefaultBuildLauncher(asyncConnection, parameters)
- def buildDelegatesToProtocolConnection() {
+ def "requests consumer connection run build"() {
ResultHandler<Void> handler = Mock()
+ ResultHandlerVersion1<Void> adaptedHandler
when:
launcher.run(handler)
then:
- 1 * protocolConnection.run(Void.class, !null, !null) >> { args ->
- def params = args[1]
+ 1 * asyncConnection.run(!null, !null) >> { args ->
+ ConsumerAction<GradleProject> action = args[0]
+ action.run(connection)
+ adaptedHandler = args[1]
+ adaptedHandler.onComplete(null)
+ }
+ 1 * connection.run(Void, _) >> {args ->
+ ConsumerOperationParameters params = args[1]
assert params.tasks == []
assert params.standardOutput == null
assert params.standardError == null
+ assert params.standardInput == null
+ assert params.javaHome == null
+ assert params.jvmArguments == null
+ assert params.arguments == null
assert params.progressListener != null
- def wrappedHandler = args[2]
- wrappedHandler.onComplete(null)
+ return null
}
1 * handler.onComplete(null)
- 0 * protocolConnection._
+ 0 * asyncConnection._
0 * handler._
}
- def canConfigureTheOperation() {
+ def "can configure the operation"() {
Task task1 = task(':task1')
Task task2 = task(':task2')
+ ResultHandlerVersion1<Void> adaptedHandler
ResultHandler<Void> handler = Mock()
-
- when:
- launcher.forTasks(task1, task2).run(handler)
-
- then:
- 1 * protocolConnection.run(Void.class, !null, !null) >> { args ->
- def params = args[1]
- assert params.tasks == [':task1', ':task2']
- assert params.standardOutput == null
- assert params.standardError == null
- assert params.progressListener != null
- def wrappedHandler = args[2]
- wrappedHandler.onComplete(null)
- }
- 1 * handler.onComplete(null)
- 0 * protocolConnection._
- 0 * handler._
- }
-
- def canRedirectStandardOutputAndError() {
- ResultHandler<Void> handler = Mock()
- OutputStream stdout = Mock()
- OutputStream stderr = Mock()
+ OutputStream stdout = Stub()
+ OutputStream stderr = Stub()
when:
launcher.standardOutput = stdout
launcher.standardError = stderr
+ launcher.forTasks(task1, task2)
launcher.run(handler)
then:
- 1 * protocolConnection.run(Void.class, !null, !null) >> { args ->
- def params = args[1]
+ 1 * asyncConnection.run(!null, !null) >> { args ->
+ ConsumerAction<GradleProject> action = args[0]
+ action.run(connection)
+ adaptedHandler = args[1]
+ adaptedHandler.onComplete(null)
+ }
+ 1 * connection.run(Void, _) >> {args ->
+ ConsumerOperationParameters params = args[1]
+ assert params.tasks == [':task1', ':task2']
assert params.standardOutput == stdout
assert params.standardError == stderr
- def wrappedHandler = args[2]
- wrappedHandler.onComplete(null)
+ return null
}
+ 1 * handler.onComplete(null)
+ 0 * asyncConnection._
+ 0 * handler._
}
- def notifiesHandlerOnFailure() {
+ def "notifies handler on failure"() {
ResultHandler<Void> handler = Mock()
+ ResultHandlerVersion1<Void> adaptedHandler
RuntimeException failure = new RuntimeException()
when:
launcher.run(handler)
then:
- 1 * protocolConnection.run(Void.class, !null, !null) >> { args ->
- def wrappedHandler = args[2]
- wrappedHandler.onFailure(failure)
+ 1 * asyncConnection.run(!null, !null) >> { args ->
+ ConsumerAction<GradleProject> action = args[0]
+ action.run(connection)
+ adaptedHandler = args[1]
+ adaptedHandler.onFailure(failure)
}
1 * handler.onFailure(!null) >> { args ->
def e = args[0]
assert e instanceof GradleConnectionException
assert e.message == 'Could not execute build using <connection>.'
}
- _ * protocolConnection.displayName >> '<connection>'
- 0 * protocolConnection._
+ _ * asyncConnection.displayName >> '<connection>'
+ 0 * asyncConnection._
0 * handler._
}
- def buildBlocksUntilResultReceived() {
- def supplyResult = waitsForAsyncCallback()
- Task task = Mock()
+ def "running build does not block"() {
+ ResultHandler<Void> handler = Mock()
+
+ given:
+ asyncConnection.run(!null, !null) >> { args ->
+ def wrappedHandler = args[1]
+ start {
+ thread.blockUntil.dispatched
+ instant.resultAvailable
+ wrappedHandler.onComplete(null)
+ }
+ }
+ handler.onComplete(_) >> {
+ instant.resultReceived
+ }
when:
- supplyResult.start {
- launcher.forTasks(task).run()
+ async {
+ launcher.run(handler)
+ instant.dispatched
+ thread.blockUntil.resultReceived
}
then:
- 1 * protocolConnection.run(Void.class, !null, !null) >> { args ->
- def handler = args[2]
- supplyResult.callbackLater {
+ instant.dispatched < instant.resultAvailable
+ instant.resultAvailable < instant.resultReceived
+ }
+
+ def "run() blocks until build is finished"() {
+ given:
+ asyncConnection.run(!null, !null) >> { args ->
+ def handler = args[1]
+ start {
+ thread.block()
+ instant.resultAvailable
handler.onComplete(null)
}
}
- }
-
- def buildBlocksUntilFailureReceived() {
- def supplyResult = waitsForAsyncCallback()
- def failure = new RuntimeException()
- Task task = Mock()
when:
- supplyResult.start {
- launcher.forTasks(task).run()
+ operation.runBuild {
+ launcher.run()
}
then:
- GradleConnectionException e = thrown()
- e.cause == failure
- 1 * protocolConnection.run(Void.class, !null, !null) >> { args ->
- def handler = args[2]
- supplyResult.callbackLater {
+ operation.runBuild.end > instant.resultAvailable
+ }
+
+ def "run() blocks until build fails"() {
+ RuntimeException failure = new RuntimeException()
+
+ given:
+ asyncConnection.run(!null, !null) >> { args ->
+ def handler = args[1]
+ start {
+ thread.block()
+ instant.failureAvailable
handler.onFailure(failure)
}
}
+
+ when:
+ operation.runBuild {
+ launcher.run()
+ }
+
+ then:
+ GradleConnectionException e = thrown()
+ e.cause.is(failure)
+
+ and:
+ operation.runBuild.end > instant.failureAvailable
}
def task(String path) {
diff --git a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/DefaultModelBuilderTest.groovy b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/DefaultModelBuilderTest.groovy
index 6e97958..5a18048 100644
--- a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/DefaultModelBuilderTest.groovy
+++ b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/DefaultModelBuilderTest.groovy
@@ -15,82 +15,91 @@
*/
package org.gradle.tooling.internal.consumer
+import org.gradle.test.fixtures.concurrent.ConcurrentSpec
import org.gradle.tooling.GradleConnectionException
import org.gradle.tooling.ResultHandler
-import org.gradle.tooling.internal.consumer.async.AsyncConnection
-import org.gradle.tooling.internal.consumer.protocoladapter.ConsumerPropertyHandler
-import org.gradle.tooling.internal.consumer.protocoladapter.ProtocolToModelAdapter
+import org.gradle.tooling.internal.consumer.async.AsyncConsumerActionExecutor
+import org.gradle.tooling.internal.consumer.connection.ConsumerAction
+import org.gradle.tooling.internal.consumer.connection.ConsumerConnection
+import org.gradle.tooling.internal.consumer.parameters.ConsumerOperationParameters
import org.gradle.tooling.internal.protocol.ProjectVersion3
import org.gradle.tooling.internal.protocol.ResultHandlerVersion1
import org.gradle.tooling.model.GradleProject
import org.gradle.tooling.model.internal.Exceptions
-import org.gradle.util.ConcurrentSpecification
-class DefaultModelBuilderTest extends ConcurrentSpecification {
- final AsyncConnection protocolConnection = Mock()
- final ProtocolToModelAdapter adapter = Mock()
+class DefaultModelBuilderTest extends ConcurrentSpec {
+ final AsyncConsumerActionExecutor asyncConnection = Mock()
+ final ConsumerConnection connection = Mock()
final ConnectionParameters parameters = Mock()
- final DefaultModelBuilder<GradleProject, ProjectVersion3> builder = new DefaultModelBuilder<GradleProject, ProjectVersion3>(GradleProject, ProjectVersion3, protocolConnection, adapter, parameters)
+ final DefaultModelBuilder<GradleProject> builder = new DefaultModelBuilder<GradleProject>(GradleProject, asyncConnection, parameters)
- def getModelDelegatesToProtocolConnectionToFetchModel() {
- ResultHandlerVersion1<ProjectVersion3> adaptedHandler
+ def "requests model from consumer connection"() {
+ ResultHandlerVersion1<GradleProject> adaptedHandler
ResultHandler<GradleProject> handler = Mock()
- ProjectVersion3 result = Mock()
- GradleProject adaptedResult = Mock()
+ GradleProject result = Mock()
when:
builder.get(handler)
then:
- 1 * protocolConnection.run(ProjectVersion3, !null, !null) >> {args ->
- def params = args[1]
+ 1 * asyncConnection.run(!null, !null) >> {args ->
+ ConsumerAction<GradleProject> action = args[0]
+ action.run(connection)
+ adaptedHandler = args[1]
+ }
+ 1 * connection.run(GradleProject, _) >> {args ->
+ ConsumerOperationParameters params = args[1]
assert params.standardOutput == null
assert params.standardError == null
+ assert params.standardInput == null
+ assert params.javaHome == null
+ assert params.jvmArguments == null
+ assert params.arguments == null
assert params.progressListener != null
assert params.tasks == null
- adaptedHandler = args[2]
+ return result
}
when:
adaptedHandler.onComplete(result)
then:
- 1 * protocolConnection.versionDetails
- 1 * adapter.adapt(GradleProject.class, result, _ as ConsumerPropertyHandler) >> adaptedResult
- 1 * handler.onComplete(adaptedResult)
+ 1 * handler.onComplete(result)
0 * _._
}
- def canConfigureTheOperation() {
+ def "can configure the operation"() {
ResultHandler<GradleProject> handler = Mock()
ResultHandlerVersion1<ProjectVersion3> adaptedHandler
- ProjectVersion3 result = Mock()
- GradleProject adaptedResult = Mock()
+ GradleProject result = Mock()
when:
builder.forTasks('a', 'b').get(handler)
then:
- 1 * protocolConnection.run(ProjectVersion3, !null, !null) >> {args ->
- def params = args[1]
+ 1 * asyncConnection.run(!null, !null) >> {args ->
+ ConsumerAction<GradleProject> action = args[0]
+ action.run(connection)
+ adaptedHandler = args[1]
+ }
+ 1 * connection.run(GradleProject, _) >> {args ->
+ ConsumerOperationParameters params = args[1]
assert params.standardOutput == null
assert params.standardError == null
assert params.progressListener != null
assert params.tasks == ['a', 'b']
- adaptedHandler = args[2]
+ return result
}
when:
adaptedHandler.onComplete(result)
then:
- 1 * protocolConnection.versionDetails
- 1 * adapter.adapt(GradleProject.class, result, _ as ConsumerPropertyHandler) >> adaptedResult
- 1 * handler.onComplete(adaptedResult)
+ 1 * handler.onComplete(result)
0 * _._
}
- def getModelWrapsFailureToFetchModel() {
+ def "wraps failure to fetch model"() {
ResultHandler<GradleProject> handler = Mock()
ResultHandlerVersion1<ProjectVersion3> adaptedHandler
RuntimeException failure = new RuntimeException()
@@ -100,14 +109,16 @@ class DefaultModelBuilderTest extends ConcurrentSpecification {
builder.get(handler)
then:
- 1 * protocolConnection.run(!null, !null, !null) >> {args -> adaptedHandler = args[2]}
+ 1 * asyncConnection.run(!null, !null) >> {args ->
+ adaptedHandler = args[1]
+ }
when:
adaptedHandler.onFailure(failure)
then:
1 * handler.onFailure(!null) >> {args -> wrappedFailure = args[0] }
- _ * protocolConnection.displayName >> '[connection]'
+ _ * asyncConnection.displayName >> '[connection]'
wrappedFailure.message == 'Could not fetch model of type \'GradleProject\' using [connection].'
wrappedFailure.cause.is(failure)
0 * _._
@@ -123,7 +134,9 @@ class DefaultModelBuilderTest extends ConcurrentSpecification {
builder.get(handler)
then:
- 1 * protocolConnection.run(!null, !null, !null) >> {args -> adaptedHandler = args[2]}
+ 1 * asyncConnection.run(!null, !null) >> {args ->
+ adaptedHandler = args[1]
+ }
when:
adaptedHandler.onFailure(failure)
@@ -134,47 +147,85 @@ class DefaultModelBuilderTest extends ConcurrentSpecification {
wrappedFailure.cause.is(failure)
}
- def getModelBlocksUntilResultReceivedFromProtocolConnection() {
- def supplyResult = waitsForAsyncCallback()
- ProjectVersion3 result = Mock()
- GradleProject adaptedResult = Mock()
- _ * adapter.adapt(GradleProject.class, result, _) >> adaptedResult
+ def "fetching model does not block"() {
+ GradleProject result = Mock()
+ ResultHandler<GradleProject> handler = Mock()
+
+ given:
+ asyncConnection.run(!null, !null) >> { args ->
+ def wrappedHandler = args[1]
+ start {
+ thread.blockUntil.dispatched
+ instant.resultAvailable
+ wrappedHandler.onComplete(result)
+ }
+ }
+ handler.onComplete(result) >> {
+ instant.resultReceived
+ }
when:
- def model
- supplyResult.start {
- model = builder.get()
+ async {
+ builder.get(handler)
+ instant.dispatched
+ thread.blockUntil.resultReceived
}
then:
- model == adaptedResult
- 1 * protocolConnection.run(!null, !null, !null) >> { args ->
- def handler = args[2]
- supplyResult.callbackLater {
+ instant.dispatched < instant.resultAvailable
+ instant.resultAvailable < instant.resultReceived
+ }
+
+ def "get() blocks until model is available"() {
+ GradleProject result = Mock()
+
+ given:
+ asyncConnection.run(!null, !null) >> { args ->
+ def handler = args[1]
+ start {
+ thread.block()
+ instant.resultAvailable
handler.onComplete(result)
}
}
- }
-
- def getModelBlocksUntilFailureReceivedFromProtocolConnectionAndRethrowsFailure() {
- def supplyResult = waitsForAsyncCallback()
- RuntimeException failure = new RuntimeException()
when:
def model
- supplyResult.start {
+ operation.fetchResult {
model = builder.get()
}
then:
- GradleConnectionException e = thrown()
- e.cause.is(failure)
- 1 * protocolConnection.run(!null, !null, !null) >> { args ->
- def handler = args[2]
- supplyResult.callbackLater {
+ model == result
+
+ and:
+ operation.fetchResult.end > instant.resultAvailable
+ }
+
+ def "get() blocks until request fails"() {
+ RuntimeException failure = new RuntimeException()
+
+ given:
+ asyncConnection.run(!null, !null) >> { args ->
+ def handler = args[1]
+ start {
+ thread.block()
+ instant.failureAvailable
handler.onFailure(failure)
}
}
+
+ when:
+ operation.fetchResult {
+ builder.get()
+ }
+
+ then:
+ GradleConnectionException e = thrown()
+ e.cause.is(failure)
+
+ and:
+ operation.fetchResult.end > instant.failureAvailable
}
}
diff --git a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/DefaultProjectConnectionTest.groovy b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/DefaultProjectConnectionTest.groovy
index d18f2a0..d991431 100644
--- a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/DefaultProjectConnectionTest.groovy
+++ b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/DefaultProjectConnectionTest.groovy
@@ -15,34 +15,32 @@
*/
package org.gradle.tooling.internal.consumer
-import org.gradle.tooling.UnknownModelException
-import org.gradle.tooling.internal.consumer.async.AsyncConnection
-import org.gradle.tooling.internal.consumer.protocoladapter.ProtocolToModelAdapter
+import org.gradle.tooling.internal.consumer.async.AsyncConsumerActionExecutor
import org.gradle.tooling.model.GradleProject
import spock.lang.Specification
class DefaultProjectConnectionTest extends Specification {
- final AsyncConnection protocolConnection = Mock()
- final ProtocolToModelAdapter adapter = Mock()
+ final AsyncConsumerActionExecutor protocolConnection = Mock()
final ConnectionParameters parameters = Mock()
- final DefaultProjectConnection connection = new DefaultProjectConnection(protocolConnection, adapter, parameters)
+ final DefaultProjectConnection connection = new DefaultProjectConnection(protocolConnection, parameters)
def canCreateAModelBuilder() {
expect:
connection.model(GradleProject.class) instanceof DefaultModelBuilder
}
- def canCreateABuildLauncher() {
- expect:
- connection.newBuild() instanceof DefaultBuildLauncher
- }
-
- def modelFailsForUnknownModelType() {
+ def modelTypeMustBeAnInterface() {
when:
- connection.model(TestBuild.class)
+ connection.model(String.class)
then:
- thrown(UnknownModelException)
+ IllegalArgumentException e = thrown()
+ e.message == "Cannot fetch a model of type 'java.lang.String' as this type is not an interface."
+ }
+
+ def canCreateABuildLauncher() {
+ expect:
+ connection.newBuild() instanceof DefaultBuildLauncher
}
def closeStopsBackingConnection() {
@@ -53,7 +51,3 @@ class DefaultProjectConnectionTest extends Specification {
1 * protocolConnection.stop()
}
}
-
-interface TestBuild extends GradleProject {
-
-}
diff --git a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/DistributionFactoryTest.groovy b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/DistributionFactoryTest.groovy
index aec9852..d269b5d 100644
--- a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/DistributionFactoryTest.groovy
+++ b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/DistributionFactoryTest.groovy
@@ -19,11 +19,11 @@ import org.gradle.logging.ProgressLogger
import org.gradle.logging.ProgressLoggerFactory
import org.gradle.test.fixtures.file.TestFile
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
-import org.gradle.testing.internal.util.Network
import org.gradle.util.DistributionLocator
import org.gradle.util.GradleVersion
+import org.gradle.util.Requires
+import org.gradle.util.TestPrecondition
import org.junit.Rule
-import spock.lang.IgnoreIf
import spock.lang.Specification
class DistributionFactoryTest extends Specification {
@@ -157,7 +157,7 @@ class DistributionFactoryTest extends Specification {
0 * _._
}
- @IgnoreIf({ Network.offline })
+ @Requires(TestPrecondition.ONLINE)
def failsWhenDistributionZipDoesNotExist() {
URI zipFile = new URI("http://google.com/does-not-exist/gradle-1.0.zip")
def dist = factory.getDistribution(zipFile)
diff --git a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/ProtocolToModelAdapterTest.groovy b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/ProtocolToModelAdapterTest.groovy
deleted file mode 100644
index fe93200..0000000
--- a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/ProtocolToModelAdapterTest.groovy
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.consumer
-
-import org.gradle.tooling.model.DomainObjectSet
-
-interface TestModel {
- String getName()
-
- TestProject getProject()
-
- boolean isConfigSupported()
-
- String getConfig(String defaultValue)
-
- DomainObjectSet<? extends TestProject> getChildren()
-}
-
-interface TestProject {
- String getName()
-}
-
-interface TestProtocolModel {
- String getName()
-
- TestProtocolProject getProject()
-
- Iterable<? extends TestProtocolProject> getChildren()
-
- String getConfig();
-}
-
-interface PartialTestProtocolModel {
- String getName()
-}
-
-interface TestProtocolProject {
- String getName()
-}
-
-class ConfigMixin {
- TestModel model
-
- ConfigMixin(TestModel model) {
- this.model = model
- }
-
- String getConfig(String value) {
- return "[${model.getConfig(value)}]"
- }
-
- String getName() {
- return "[${model.name}]"
- }
-}
\ No newline at end of file
diff --git a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/SynchronizedLoggingTest.groovy b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/SynchronizedLoggingTest.groovy
index edbb634..b21cf7c 100644
--- a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/SynchronizedLoggingTest.groovy
+++ b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/SynchronizedLoggingTest.groovy
@@ -22,9 +22,6 @@ import spock.lang.Specification
import java.util.concurrent.CopyOnWriteArraySet
-/**
- * by Szczepan Faber, created at: 12/16/11
- */
public class SynchronizedLoggingTest extends Specification {
def logging = new SynchronizedLogging()
diff --git a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/async/DefaultAsyncConsumerActionExecutorTest.groovy b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/async/DefaultAsyncConsumerActionExecutorTest.groovy
new file mode 100644
index 0000000..62d8025
--- /dev/null
+++ b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/async/DefaultAsyncConsumerActionExecutorTest.groovy
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.consumer.async
+
+import org.gradle.test.fixtures.concurrent.ConcurrentSpec
+import org.gradle.tooling.internal.consumer.connection.ConsumerAction
+import org.gradle.tooling.internal.consumer.connection.ConsumerActionExecutor
+import org.gradle.tooling.internal.protocol.ResultHandlerVersion1
+
+class DefaultAsyncConsumerActionExecutorTest extends ConcurrentSpec {
+ def actionExecuter = Mock(ConsumerActionExecutor) {
+ getDisplayName() >> "[executer]"
+ }
+ def action = Mock(ConsumerAction)
+ def handler = Mock(ResultHandlerVersion1)
+ def connection = new DefaultAsyncConsumerActionExecutor(actionExecuter, executorFactory)
+
+ def cleanup() {
+ connection.stop()
+ }
+
+ def "runs action asynchronously"() {
+ when:
+ async {
+ connection.run(action, handler)
+ instant.dispatched
+ }
+
+ then:
+ 1 * actionExecuter.run(action) >> {
+ thread.blockUntil.dispatched
+ instant.actionStarted
+ return "result"
+ }
+ 1 * handler.onComplete("result") >> {
+ instant.resultReceived
+ }
+
+ and:
+ instant.actionStarted < instant.resultReceived
+ }
+
+ def "notifies handler on failure"() {
+ def failure = new RuntimeException()
+
+ when:
+ async {
+ connection.run(action, handler)
+ }
+
+ then:
+ 1 * actionExecuter.run(action) >> {
+ throw failure
+ }
+ 1 * handler.onFailure(failure)
+ }
+
+ def "cannot use connection after it has stopped"() {
+ when:
+ connection.stop()
+ connection.run(action, handler)
+
+ then:
+ IllegalStateException e = thrown()
+ e.message == 'Cannot use [executer] as it has been stopped.'
+ }
+}
diff --git a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/connection/ActionAwareConsumerConnectionTest.groovy b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/connection/ActionAwareConsumerConnectionTest.groovy
new file mode 100644
index 0000000..053dca2
--- /dev/null
+++ b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/connection/ActionAwareConsumerConnectionTest.groovy
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.consumer.connection
+
+import org.gradle.tooling.BuildAction
+import org.gradle.tooling.BuildActionFailureException
+import org.gradle.tooling.internal.adapter.ProtocolToModelAdapter
+import org.gradle.tooling.internal.consumer.parameters.ConsumerOperationParameters
+import org.gradle.tooling.internal.consumer.versioning.ModelMapping
+import org.gradle.tooling.internal.protocol.*
+import spock.lang.Specification
+
+class ActionAwareConsumerConnectionTest extends Specification {
+ final target = Mock(TestModelBuilder) {
+ getMetaData() >> Mock(ConnectionMetaDataVersion1)
+ }
+ final adapter = Mock(ProtocolToModelAdapter)
+ final modelMapping = Stub(ModelMapping)
+ final connection = new ActionAwareConsumerConnection(target, modelMapping, adapter)
+
+ def "delegates to connection to run build action"() {
+ def action = Mock(BuildAction)
+ def parameters = Stub(ConsumerOperationParameters)
+ def buildController = Mock(InternalBuildController)
+
+ when:
+ def result = connection.run(action, parameters)
+
+ then:
+ result == 'result'
+
+ and:
+ 1 * target.run(_, parameters) >> { InternalBuildAction protocolAction, def params ->
+ def actionResult = protocolAction.execute(buildController)
+ return Stub(BuildResult) {
+ getModel() >> actionResult
+ }
+ }
+ 1 * action.execute({ it instanceof BuildControllerAdapter }) >> 'result'
+ }
+
+ def "adapts build action failure"() {
+ def action = Mock(BuildAction)
+ def parameters = Stub(ConsumerOperationParameters)
+ def failure = new RuntimeException()
+
+ when:
+ connection.run(action, parameters)
+
+ then:
+ BuildActionFailureException e = thrown()
+ e.message == /The supplied build action failed with an exception./
+ e.cause == failure
+
+ and:
+ 1 * target.run(_, parameters) >> { throw new InternalBuildActionFailureException(failure) }
+ }
+
+ interface TestModelBuilder extends ModelBuilder, ConnectionVersion4, ConfigurableConnection, InternalBuildActionExecutor {
+ }
+}
diff --git a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/connection/AdaptedConnectionTest.groovy b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/connection/AdaptedConnectionTest.groovy
deleted file mode 100644
index c15308f..0000000
--- a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/connection/AdaptedConnectionTest.groovy
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.consumer.connection
-
-import org.gradle.tooling.internal.consumer.parameters.ConsumerOperationParameters
-import org.gradle.tooling.internal.protocol.ConnectionVersion4
-import org.gradle.tooling.internal.protocol.ProjectVersion3
-import spock.lang.Specification
-
-class AdaptedConnectionTest extends Specification {
- final ConnectionVersion4 target = Mock()
- final ConsumerOperationParameters parameters = Mock()
- final AdaptedConnection connection = new AdaptedConnection(target)
-
- def "builds model using getModel() method"() {
- ProjectVersion3 model = Mock()
-
- when:
- def result = connection.run(ProjectVersion3.class, parameters)
-
- then:
- result == model
-
- and:
- 1 * target.getModel(ProjectVersion3.class, parameters) >> model
- 0 * target._
- }
-
- def "runs build using executeBuild() method"() {
- when:
- connection.run(Void.class, parameters)
-
- then:
- 1 * target.executeBuild(parameters, parameters)
- 0 * target._
- }
-}
diff --git a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/connection/BuildActionRunnerBackedConsumerConnectionTest.groovy b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/connection/BuildActionRunnerBackedConsumerConnectionTest.groovy
index 0e5ffd8..26476cd 100644
--- a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/connection/BuildActionRunnerBackedConsumerConnectionTest.groovy
+++ b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/connection/BuildActionRunnerBackedConsumerConnectionTest.groovy
@@ -16,18 +16,56 @@
package org.gradle.tooling.internal.consumer.connection
+import org.gradle.tooling.BuildAction
+import org.gradle.tooling.UnknownModelException
+import org.gradle.tooling.UnsupportedVersionException
+import org.gradle.tooling.internal.adapter.ProtocolToModelAdapter
import org.gradle.tooling.internal.consumer.parameters.ConsumerConnectionParameters
import org.gradle.tooling.internal.consumer.parameters.ConsumerOperationParameters
-import org.gradle.tooling.internal.protocol.BuildActionRunner
-import org.gradle.tooling.internal.protocol.BuildResult
-import org.gradle.tooling.internal.protocol.ConfigurableConnection
-import org.gradle.tooling.internal.protocol.ConnectionVersion4
+import org.gradle.tooling.internal.consumer.versioning.CustomModel
+import org.gradle.tooling.internal.consumer.versioning.ModelMapping
+import org.gradle.tooling.internal.protocol.*
+import org.gradle.tooling.model.GradleProject
+import org.gradle.tooling.model.build.BuildEnvironment
+import org.gradle.tooling.model.eclipse.EclipseProject
+import org.gradle.tooling.model.eclipse.HierarchicalEclipseProject
+import org.gradle.tooling.model.idea.BasicIdeaProject
+import org.gradle.tooling.model.idea.IdeaProject
+import org.gradle.tooling.model.internal.outcomes.ProjectOutcomes
import spock.lang.Specification
class BuildActionRunnerBackedConsumerConnectionTest extends Specification {
- final TestBuildActionRunner target = Mock()
- final ConsumerOperationParameters parameters = Mock()
- final BuildActionRunnerBackedConsumerConnection connection = new BuildActionRunnerBackedConsumerConnection(target)
+ final ConnectionMetaDataVersion1 metaData = Stub() {
+ getVersion() >> '1.2'
+ }
+ final TestBuildActionRunner target = Mock() {
+ getMetaData() >> metaData
+ }
+ final ConsumerOperationParameters parameters = Stub()
+ final ModelMapping modelMapping = Stub()
+ final ProtocolToModelAdapter adapter = Mock()
+ final BuildActionRunnerBackedConsumerConnection connection = new BuildActionRunnerBackedConsumerConnection(target, modelMapping, adapter)
+
+ def "describes capabilities of the provider"() {
+ given:
+ def details = connection.versionDetails
+
+ expect:
+ details.supportsGradleProjectModel()
+
+ and:
+ details.isModelSupported(HierarchicalEclipseProject)
+ details.isModelSupported(EclipseProject)
+ details.isModelSupported(IdeaProject)
+ details.isModelSupported(BasicIdeaProject)
+ details.isModelSupported(GradleProject)
+ details.isModelSupported(BuildEnvironment)
+ details.isModelSupported(ProjectOutcomes)
+ details.isModelSupported(Void)
+
+ and:
+ !details.isModelSupported(CustomModel)
+ }
def "configures connection"() {
def parameters = new ConsumerConnectionParameters(false)
@@ -37,25 +75,48 @@ class BuildActionRunnerBackedConsumerConnectionTest extends Specification {
then:
1 * target.configure(parameters)
+ 0 * target._
}
- def "builds model using run() method"() {
- BuildResult<String> result = Mock()
-
- given:
- result.model >> 'ok'
+ def "builds model using connection's run() method"() {
+ BuildResult<String> result = Stub()
+ GradleProject adapted = Stub()
when:
- def model = connection.run(String.class, parameters)
+ def model = connection.run(GradleProject.class, parameters)
then:
- model == 'ok'
+ model == adapted
and:
- 1 * target.run(String.class, parameters) >> result
+ _ * modelMapping.getProtocolType(GradleProject.class) >> Integer.class
+ 1 * target.run(Integer.class, parameters) >> result
+ _ * result.model >> 12
+ 1 * adapter.adapt(GradleProject.class, 12) >> adapted
0 * target._
}
+ def "fails when unknown model is requested"() {
+ when:
+ connection.run(CustomModel.class, parameters)
+
+ then:
+ UnknownModelException e = thrown()
+ e.message == /The version of Gradle you are using (1.2) does not support building a model of type 'CustomModel'. Support for building custom tooling models was added in Gradle 1.6 and is available in all later versions./
+ }
+
+ def "fails when build action requested"() {
+ given:
+ parameters.tasks >> ['a']
+
+ when:
+ connection.run(Stub(BuildAction), parameters)
+
+ then:
+ UnsupportedVersionException e = thrown()
+ e.message == /The version of Gradle you are using (1.2) does not support execution of build actions provided by the tooling API client. Support for this was added in Gradle 1.8 and is available in all later versions./
+ }
+
interface TestBuildActionRunner extends ConnectionVersion4, BuildActionRunner, ConfigurableConnection {
}
}
diff --git a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/connection/BuildControllerAdapterTest.groovy b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/connection/BuildControllerAdapterTest.groovy
new file mode 100644
index 0000000..f0a173b
--- /dev/null
+++ b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/connection/BuildControllerAdapterTest.groovy
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.consumer.connection
+
+import org.gradle.tooling.UnknownModelException
+import org.gradle.tooling.internal.adapter.ProtocolToModelAdapter
+import org.gradle.tooling.internal.consumer.versioning.ModelMapping
+import org.gradle.tooling.internal.protocol.*
+import org.gradle.tooling.model.Element
+import org.gradle.tooling.model.gradle.GradleBuild
+import spock.lang.Specification
+
+class BuildControllerAdapterTest extends Specification {
+ def internalController = Mock(InternalBuildController)
+ def adapter = Mock(ProtocolToModelAdapter)
+ def mapping = Stub(ModelMapping) {
+ getModelIdentifierFromModelType(_) >> { Class type ->
+ return Stub(ModelIdentifier) {
+ getName() >> type.simpleName
+ }
+ }
+ }
+ def controller = new BuildControllerAdapter(adapter, internalController, mapping)
+
+ def "unpacks unsupported model exception"() {
+ def failure = new RuntimeException()
+
+ given:
+ _ * internalController.getModel(null, _) >> { throw new InternalUnsupportedModelException().initCause(failure) }
+
+ when:
+ controller.getModel(String)
+
+ then:
+ UnknownModelException e = thrown()
+ e.message == /No model of type 'String' is available in this build./
+ e.cause == failure
+ }
+
+ def "fetches model for target object"() {
+ def model = new Object()
+ def targetElement = new Object()
+ def modelElement = Stub(Element)
+ def modelView = Stub(GradleBuild)
+
+ when:
+ def result = controller.getModel(modelElement, GradleBuild)
+
+ then:
+ result == modelView
+
+ and:
+ 1 * adapter.unpack(modelElement) >> targetElement
+ 1 * internalController.getModel(targetElement, _) >> { def target, ModelIdentifier identifier ->
+ assert identifier.name == 'GradleBuild'
+ return Stub(BuildResult) {
+ getModel() >> model
+ }
+ }
+ 1 * adapter.adapt(GradleBuild, model) >> modelView
+ }
+
+ def "fetches missing model for target object"() {
+ def targetElement = new Object()
+ def modelElement = Stub(Element)
+
+ when:
+ def result = controller.findModel(modelElement, GradleBuild)
+
+ then:
+ result == null
+
+ and:
+ 1 * adapter.unpack(modelElement) >> targetElement
+ 1 * internalController.getModel(targetElement, _) >> { throw new InternalUnsupportedModelException() }
+ }
+
+ def "fetches build model"() {
+ def model = Stub(InternalProtocolInterface)
+ def modelView = Stub(GradleBuild)
+
+ when:
+ def result = controller.buildModel
+
+ then:
+ result == modelView
+
+ and:
+ 1 * internalController.getModel(null, _) >> { def target, ModelIdentifier identifier ->
+ assert identifier.name == 'GradleBuild'
+ return Stub(BuildResult) {
+ getModel() >> model
+ }
+ }
+ 1 * adapter.adapt(GradleBuild, model) >> modelView
+ }
+
+ def "fetches missing model"() {
+ when:
+ def result = controller.findModel(GradleBuild)
+
+ then:
+ result == null
+
+ and:
+ 1 * internalController.getModel(null, _) >> { throw new InternalUnsupportedModelException() }
+ }
+}
diff --git a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/connection/ConnectionVersion4BackedConsumerConnectionTest.groovy b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/connection/ConnectionVersion4BackedConsumerConnectionTest.groovy
new file mode 100644
index 0000000..3603920
--- /dev/null
+++ b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/connection/ConnectionVersion4BackedConsumerConnectionTest.groovy
@@ -0,0 +1,258 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.consumer.connection
+
+import org.gradle.tooling.BuildAction
+import org.gradle.tooling.UnknownModelException
+import org.gradle.tooling.UnsupportedVersionException
+import org.gradle.tooling.exceptions.UnsupportedOperationConfigurationException
+import org.gradle.tooling.internal.adapter.ProtocolToModelAdapter
+import org.gradle.tooling.internal.build.VersionOnlyBuildEnvironment
+import org.gradle.tooling.internal.consumer.parameters.ConsumerOperationParameters
+import org.gradle.tooling.internal.consumer.versioning.CustomModel
+import org.gradle.tooling.internal.consumer.versioning.ModelMapping
+import org.gradle.tooling.internal.protocol.ConnectionMetaDataVersion1
+import org.gradle.tooling.internal.protocol.ConnectionVersion4
+import org.gradle.tooling.internal.protocol.ProjectVersion3
+import org.gradle.tooling.internal.protocol.eclipse.EclipseProjectVersion3
+import org.gradle.tooling.model.GradleProject
+import org.gradle.tooling.model.build.BuildEnvironment
+import org.gradle.tooling.model.eclipse.EclipseProject
+import org.gradle.tooling.model.eclipse.HierarchicalEclipseProject
+import org.gradle.tooling.model.idea.BasicIdeaProject
+import org.gradle.tooling.model.idea.IdeaProject
+import org.gradle.tooling.model.internal.outcomes.ProjectOutcomes
+import spock.lang.Specification
+
+class ConnectionVersion4BackedConsumerConnectionTest extends Specification {
+ final ConnectionMetaDataVersion1 metaData = Stub()
+ final ConnectionVersion4 target = Mock() {
+ getMetaData() >> metaData
+ }
+ final ConsumerOperationParameters parameters = Mock()
+ final ModelMapping modelMapping = Stub()
+ final ProtocolToModelAdapter adapter = Mock()
+
+ def "describes capabilities of a 1.0-m3 provider"() {
+ given:
+ metaData.version >> "1.0-milestone-3"
+ def connection = new ConnectionVersion4BackedConsumerConnection(target, modelMapping, adapter)
+ def details = connection.versionDetails
+
+ expect:
+ !details.supportsGradleProjectModel()
+
+ and:
+ details.isModelSupported(HierarchicalEclipseProject)
+ details.isModelSupported(EclipseProject)
+ details.isModelSupported(Void)
+
+ and:
+ !details.isModelSupported(IdeaProject)
+ !details.isModelSupported(BasicIdeaProject)
+ !details.isModelSupported(GradleProject)
+ !details.isModelSupported(BuildEnvironment)
+ !details.isModelSupported(ProjectOutcomes)
+ !details.isModelSupported(CustomModel)
+ }
+
+ def "describes capabilities of a 1.0-m5 provider"() {
+ given:
+ metaData.version >> "1.0-milestone-5"
+ def connection = new ConnectionVersion4BackedConsumerConnection(target, modelMapping, adapter)
+ def details = connection.versionDetails
+
+ expect:
+ details.supportsGradleProjectModel()
+
+ and:
+ details.isModelSupported(HierarchicalEclipseProject)
+ details.isModelSupported(EclipseProject)
+ details.isModelSupported(IdeaProject)
+ details.isModelSupported(BasicIdeaProject)
+ details.isModelSupported(GradleProject)
+ details.isModelSupported(Void)
+
+ and:
+ !details.isModelSupported(BuildEnvironment)
+ !details.isModelSupported(ProjectOutcomes)
+ !details.isModelSupported(CustomModel)
+ }
+
+ def "builds model using connection's getModel() method"() {
+ ProjectVersion3 protocolModel = Mock()
+ GradleProject model = Mock()
+ metaData.version >> "1.0-milestone-5"
+ def connection = new ConnectionVersion4BackedConsumerConnection(target, modelMapping, adapter)
+
+ when:
+ def result = connection.run(GradleProject.class, parameters)
+
+ then:
+ result == model
+
+ and:
+ _ * modelMapping.getProtocolType(GradleProject.class) >> ProjectVersion3.class
+ 1 * target.getModel(ProjectVersion3.class, parameters) >> protocolModel
+ 1 * adapter.adapt(GradleProject.class, protocolModel, _) >> model
+ 0 * target._
+ }
+
+ def "runs build using connection's executeBuild() method"() {
+ metaData.version >> "1.0-milestone-5"
+ def connection = new ConnectionVersion4BackedConsumerConnection(target, modelMapping, adapter)
+
+ when:
+ connection.run(Void.class, parameters)
+
+ then:
+ 1 * target.executeBuild(parameters, parameters)
+ 0 * target._
+ }
+
+ def "builds partial BuildEnvironment model locally"() {
+ metaData.version >> "1.0-milestone-5"
+ def connection = new ConnectionVersion4BackedConsumerConnection(target, modelMapping, adapter)
+ BuildEnvironment model = Stub()
+
+ when:
+ def result = connection.run(BuildEnvironment.class, parameters)
+
+ then:
+ result == model
+
+ and:
+ 1 * adapter.adapt(BuildEnvironment.class, {it instanceof VersionOnlyBuildEnvironment}, _) >> model
+ 0 * target._
+ }
+
+ def "builds partial GradleProject model using the Eclipse model for a 1.0-m3 provider"() {
+ metaData.version >> "1.0-milestone-3"
+ def connection = new ConnectionVersion4BackedConsumerConnection(target, modelMapping, adapter)
+ EclipseProjectVersion3 protocolModel = Stub()
+ GradleProject model = Stub()
+
+ when:
+ def result = connection.run(GradleProject.class, parameters)
+
+ then:
+ result == model
+
+ and:
+ 1 * target.getModel(EclipseProjectVersion3.class, parameters) >> protocolModel
+ 1 * adapter.adapt(GradleProject.class, _, _) >> model
+ 0 * target._
+ }
+
+ def "fails when unknown model is requested"() {
+ metaData.version >> "1.0-milestone-5"
+ def connection = new ConnectionVersion4BackedConsumerConnection(target, modelMapping, adapter)
+
+ when:
+ connection.run(CustomModel.class, parameters)
+
+ then:
+ UnknownModelException e = thrown()
+ e.message == /The version of Gradle you are using (1.0-milestone-5) does not support building a model of type 'CustomModel'. Support for building custom tooling models was added in Gradle 1.6 and is available in all later versions./
+ }
+
+ def "fails when unsupported model is requested"() {
+ metaData.version >> "1.0-milestone-5"
+ def connection = new ConnectionVersion4BackedConsumerConnection(target, modelMapping, adapter)
+
+ when:
+ connection.run(ProjectOutcomes.class, parameters)
+
+ then:
+ UnknownModelException e = thrown()
+ e.message == /The version of Gradle you are using (1.0-milestone-5) does not support building a model of type 'ProjectOutcomes'. Support for building 'ProjectOutcomes' models was added in Gradle 1.2 and is available in all later versions./
+ }
+
+ def "fails when both tasks and model requested"() {
+ metaData.version >> "1.0-milestone-5"
+ def connection = new ConnectionVersion4BackedConsumerConnection(target, modelMapping, adapter)
+
+ given:
+ parameters.tasks >> ['a']
+
+ when:
+ connection.run(GradleProject.class, parameters)
+
+ then:
+ UnsupportedOperationConfigurationException e = thrown()
+ e.message.startsWith("Unsupported configuration: modelBuilder.forTasks()")
+ }
+
+ def "fails when build action requested"() {
+ metaData.version >> "1.0-milestone-5"
+ def connection = new ConnectionVersion4BackedConsumerConnection(target, modelMapping, adapter)
+
+ given:
+ parameters.tasks >> ['a']
+
+ when:
+ connection.run(Stub(BuildAction), parameters)
+
+ then:
+ UnsupportedVersionException e = thrown()
+ e.message == /The version of Gradle you are using (1.0-milestone-5) does not support execution of build actions provided by the tooling API client. Support for this was added in Gradle 1.8 and is available in all later versions./
+ }
+
+ def "fails when stdin provided"() {
+ metaData.version >> "1.0-milestone-5"
+ def connection = new ConnectionVersion4BackedConsumerConnection(target, modelMapping, adapter)
+
+ given:
+ parameters.standardInput >> new ByteArrayInputStream("hi".bytes)
+
+ when:
+ connection.run(CustomModel.class, parameters)
+
+ then:
+ UnsupportedOperationConfigurationException e = thrown()
+ e.message.startsWith("Unsupported configuration: modelBuilder.setStandardInput()")
+ }
+
+ def "fails when Java home specified"() {
+ metaData.version >> "1.0-milestone-5"
+ def connection = new ConnectionVersion4BackedConsumerConnection(target, modelMapping, adapter)
+
+ given:
+ parameters.javaHome >> new File("java-home")
+
+ when:
+ connection.run(CustomModel.class, parameters)
+
+ then:
+ UnsupportedOperationConfigurationException e = thrown()
+ e.message.startsWith("Unsupported configuration: modelBuilder.setJavaHome()")
+ }
+
+ def "fails when JVM args specified"() {
+ metaData.version >> "1.0-milestone-5"
+ def connection = new ConnectionVersion4BackedConsumerConnection(target, modelMapping, adapter)
+
+ given:
+ parameters.jvmArguments >> ['-Dsome.arg']
+
+ when:
+ connection.run(CustomModel.class, parameters)
+
+ then:
+ UnsupportedOperationConfigurationException e = thrown()
+ e.message.startsWith("Unsupported configuration: modelBuilder.setJvmArguments()")
+ }
+}
diff --git a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/connection/InternalConnectionBackedConsumerConnectionTest.groovy b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/connection/InternalConnectionBackedConsumerConnectionTest.groovy
index d5c0bf3..4bbbe27 100644
--- a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/connection/InternalConnectionBackedConsumerConnectionTest.groovy
+++ b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/connection/InternalConnectionBackedConsumerConnectionTest.groovy
@@ -15,28 +15,75 @@
*/
package org.gradle.tooling.internal.consumer.connection
+import org.gradle.tooling.BuildAction
+import org.gradle.tooling.UnknownModelException
+import org.gradle.tooling.UnsupportedVersionException
+import org.gradle.tooling.exceptions.UnsupportedOperationConfigurationException
+import org.gradle.tooling.internal.adapter.ProtocolToModelAdapter
import org.gradle.tooling.internal.consumer.parameters.ConsumerOperationParameters
+import org.gradle.tooling.internal.consumer.versioning.CustomModel
+import org.gradle.tooling.internal.consumer.versioning.ModelMapping
+import org.gradle.tooling.internal.protocol.ConnectionMetaDataVersion1
import org.gradle.tooling.internal.protocol.InternalConnection
+import org.gradle.tooling.model.GradleProject
+import org.gradle.tooling.model.build.BuildEnvironment
+import org.gradle.tooling.model.eclipse.EclipseProject
+import org.gradle.tooling.model.eclipse.HierarchicalEclipseProject
+import org.gradle.tooling.model.idea.BasicIdeaProject
+import org.gradle.tooling.model.idea.IdeaProject
+import org.gradle.tooling.model.internal.outcomes.ProjectOutcomes
import spock.lang.Specification
class InternalConnectionBackedConsumerConnectionTest extends Specification {
- final InternalConnection target = Mock()
+ final ConnectionMetaDataVersion1 metaData = Stub() {
+ getVersion() >> '1.0-milestone-8'
+ }
+ final InternalConnection target = Mock() {
+ getMetaData() >> metaData
+ }
final ConsumerOperationParameters parameters = Mock()
- final InternalConnectionBackedConsumerConnection connection = new InternalConnectionBackedConsumerConnection(target)
+ final ProtocolToModelAdapter adapter = Mock()
+ final ModelMapping modelMapping = Stub()
+ final InternalConnectionBackedConsumerConnection connection = new InternalConnectionBackedConsumerConnection(target, modelMapping, adapter)
+
+ def "describes capabilities of the provider"() {
+ given:
+ def details = connection.versionDetails
+
+ expect:
+ details.supportsGradleProjectModel()
+
+ and:
+ details.isModelSupported(HierarchicalEclipseProject)
+ details.isModelSupported(EclipseProject)
+ details.isModelSupported(IdeaProject)
+ details.isModelSupported(BasicIdeaProject)
+ details.isModelSupported(GradleProject)
+ details.isModelSupported(BuildEnvironment)
+ details.isModelSupported(Void)
+
+ and:
+ !details.isModelSupported(ProjectOutcomes)
+ !details.isModelSupported(CustomModel)
+ }
+
+ def "builds model using connection's getTheModel() method"() {
+ def model = Stub(GradleProject)
- def "builds model using getTheModel() method"() {
when:
- def result = connection.run(String.class, parameters)
+ def result = connection.run(GradleProject.class, parameters)
then:
- result == 'ok'
+ result == model
and:
- 1 * target.getTheModel(String.class, parameters) >> 'ok'
+ _ * modelMapping.getProtocolType(GradleProject.class) >> Integer.class
+ 1 * target.getTheModel(Integer.class, parameters) >> 12
+ 1 * adapter.adapt(GradleProject.class, 12, _) >> model
0 * target._
}
- def "runs build using executeBuild() method"() {
+ def "runs build using connection's executeBuild() method"() {
when:
connection.run(Void.class, parameters)
@@ -44,4 +91,37 @@ class InternalConnectionBackedConsumerConnectionTest extends Specification {
1 * target.executeBuild(parameters, parameters)
0 * target._
}
+
+ def "fails when unknown model is requested"() {
+ when:
+ connection.run(CustomModel.class, parameters)
+
+ then:
+ UnknownModelException e = thrown()
+ e.message == /The version of Gradle you are using (1.0-milestone-8) does not support building a model of type 'CustomModel'. Support for building custom tooling models was added in Gradle 1.6 and is available in all later versions./
+ }
+
+ def "fails when both tasks and model requested"() {
+ given:
+ parameters.tasks >> ['a']
+
+ when:
+ connection.run(GradleProject.class, parameters)
+
+ then:
+ UnsupportedOperationConfigurationException e = thrown()
+ e.message.startsWith("Unsupported configuration: modelBuilder.forTasks()")
+ }
+
+ def "fails when build action requested"() {
+ given:
+ parameters.tasks >> ['a']
+
+ when:
+ connection.run(Stub(BuildAction), parameters)
+
+ then:
+ UnsupportedVersionException e = thrown()
+ e.message == /The version of Gradle you are using (1.0-milestone-8) does not support execution of build actions provided by the tooling API client. Support for this was added in Gradle 1.8 and is available in all later versions./
+ }
}
diff --git a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/connection/LazyConnectionTest.groovy b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/connection/LazyConnectionTest.groovy
deleted file mode 100644
index 194a7b5..0000000
--- a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/connection/LazyConnectionTest.groovy
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.consumer.connection
-
-import org.gradle.logging.ProgressLoggerFactory
-import org.gradle.tooling.internal.consumer.Distribution
-import org.gradle.tooling.internal.consumer.LoggingProvider
-import org.gradle.tooling.internal.consumer.ModelProvider
-import org.gradle.tooling.internal.consumer.loader.ToolingImplementationLoader
-import org.gradle.tooling.internal.consumer.parameters.ConsumerConnectionParameters
-import org.gradle.tooling.internal.consumer.parameters.ConsumerOperationParameters
-import spock.lang.Specification
-
-class LazyConnectionTest extends Specification {
- final Distribution distribution = Mock()
- final ToolingImplementationLoader implementationLoader = Mock()
- final ConsumerOperationParameters params = Mock()
- final ConsumerConnectionParameters connectionParams = Mock()
- final ConsumerConnection consumerConnection = Mock()
- final LoggingProvider loggingProvider = Mock()
- final ProgressLoggerFactory progressLoggerFactory = Mock()
- final LazyConnection connection = new LazyConnection(distribution, implementationLoader, loggingProvider, false)
-
- static class SomeModel {}
-
- def setup() {
- connection.connectionParameters = connectionParams
- connection.modelProvider = Mock(ModelProvider)
- }
-
- def createsConnectionOnDemandToBuildModel() {
- when:
- connection.run(SomeModel, params)
-
- then:
- 1 * loggingProvider.getProgressLoggerFactory() >> progressLoggerFactory
- 1 * implementationLoader.create(distribution, progressLoggerFactory, connectionParams) >> consumerConnection
- 1 * connection.modelProvider.provide(!null, SomeModel, params)
- 0 * _._
- }
-
- def reusesConnection() {
- when:
- connection.run(SomeModel, params)
- connection.run(String, params)
-
- then:
- 1 * loggingProvider.getProgressLoggerFactory() >> progressLoggerFactory
- 1 * implementationLoader.create(distribution, progressLoggerFactory, connectionParams) >> consumerConnection
- 1 * connection.modelProvider.provide(consumerConnection, SomeModel, params)
- 1 * connection.modelProvider.provide(consumerConnection, String, params)
- 0 * _._
- }
-
- def stopsConnectionOnStop() {
- when:
- connection.run(SomeModel, params)
- connection.stop()
-
- then:
- 1 * loggingProvider.getProgressLoggerFactory() >> progressLoggerFactory
- 1 * implementationLoader.create(distribution, progressLoggerFactory, connectionParams) >> consumerConnection
- 1 * connection.modelProvider.provide(consumerConnection, SomeModel, params)
- 1 * consumerConnection.stop()
- 0 * _._
- }
-
- def doesNotStopConnectionOnStopIfNotCreated() {
- when:
- connection.stop()
-
- then:
- 0 * _._
- }
-
- def doesNotStopConnectionOnStopIfConnectionCouldNotBeCreated() {
- def failure = new RuntimeException()
-
- when:
- connection.run(SomeModel, params)
-
- then:
- RuntimeException e = thrown()
- e == failure
- 1 * loggingProvider.getProgressLoggerFactory() >> progressLoggerFactory
- 1 * implementationLoader.create(distribution, progressLoggerFactory, connectionParams) >> { throw failure }
-
- when:
- connection.stop()
-
- then:
- 0 * _._
- }
-}
diff --git a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/connection/LazyConsumerActionExecutorTest.groovy b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/connection/LazyConsumerActionExecutorTest.groovy
new file mode 100644
index 0000000..b8345b7
--- /dev/null
+++ b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/connection/LazyConsumerActionExecutorTest.groovy
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.consumer.connection
+
+import org.gradle.logging.ProgressLoggerFactory
+import org.gradle.tooling.internal.consumer.Distribution
+import org.gradle.tooling.internal.consumer.LoggingProvider
+import org.gradle.tooling.internal.consumer.loader.ToolingImplementationLoader
+import org.gradle.tooling.internal.consumer.parameters.ConsumerConnectionParameters
+import org.gradle.tooling.internal.consumer.parameters.ConsumerOperationParameters
+import spock.lang.Specification
+
+class LazyConsumerActionExecutorTest extends Specification {
+ final Distribution distribution = Mock()
+ final ToolingImplementationLoader implementationLoader = Mock()
+ final ConsumerOperationParameters params = Mock()
+ final ConsumerAction<String> action = Mock()
+ final ConsumerConnectionParameters connectionParams = Mock()
+ final ConsumerConnection consumerConnection = Mock()
+ final LoggingProvider loggingProvider = Mock()
+ final ProgressLoggerFactory progressLoggerFactory = Mock()
+ final LazyConsumerActionExecutor connection = new LazyConsumerActionExecutor(distribution, implementationLoader, loggingProvider, false)
+
+ def setup() {
+ connection.connectionParameters = connectionParams
+ }
+
+ def createsConnectionOnDemandToBuildModel() {
+ when:
+ connection.run(action)
+
+ then:
+ 1 * loggingProvider.progressLoggerFactory >> progressLoggerFactory
+ 1 * implementationLoader.create(distribution, progressLoggerFactory, connectionParams) >> consumerConnection
+ 1 * action.run(consumerConnection)
+ 0 * _._
+ }
+
+ def reusesConnection() {
+ def action2 = Mock(ConsumerAction)
+
+ when:
+ connection.run(action)
+ connection.run(action2)
+
+ then:
+ 1 * loggingProvider.getProgressLoggerFactory() >> progressLoggerFactory
+ 1 * implementationLoader.create(distribution, progressLoggerFactory, connectionParams) >> consumerConnection
+ 1 * action.run(consumerConnection)
+ 1 * action2.run(consumerConnection)
+ 0 * _._
+ }
+
+ def stopsConnectionOnStop() {
+ when:
+ connection.run(action)
+ connection.stop()
+
+ then:
+ 1 * loggingProvider.getProgressLoggerFactory() >> progressLoggerFactory
+ 1 * implementationLoader.create(distribution, progressLoggerFactory, connectionParams) >> consumerConnection
+ 1 * action.run(consumerConnection)
+ 1 * consumerConnection.stop()
+ 0 * _._
+ }
+
+ def doesNotStopConnectionOnStopIfNotCreated() {
+ when:
+ connection.stop()
+
+ then:
+ 0 * _._
+ }
+
+ def doesNotStopConnectionOnStopIfConnectionCouldNotBeCreated() {
+ def failure = new RuntimeException()
+
+ when:
+ connection.run(action)
+
+ then:
+ RuntimeException e = thrown()
+ e == failure
+ 1 * loggingProvider.getProgressLoggerFactory() >> progressLoggerFactory
+ 1 * implementationLoader.create(distribution, progressLoggerFactory, connectionParams) >> { throw failure }
+
+ when:
+ connection.stop()
+
+ then:
+ 0 * _._
+ }
+}
diff --git a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/connection/ModelBuilderBackedConsumerConnectionTest.groovy b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/connection/ModelBuilderBackedConsumerConnectionTest.groovy
new file mode 100644
index 0000000..ff7a598
--- /dev/null
+++ b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/connection/ModelBuilderBackedConsumerConnectionTest.groovy
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.consumer.connection
+
+import org.gradle.tooling.BuildAction
+import org.gradle.tooling.UnknownModelException
+import org.gradle.tooling.UnsupportedVersionException
+import org.gradle.tooling.internal.adapter.ProtocolToModelAdapter
+import org.gradle.tooling.internal.consumer.parameters.ConsumerOperationParameters
+import org.gradle.tooling.internal.consumer.versioning.CustomModel
+import org.gradle.tooling.internal.consumer.versioning.ModelMapping
+import org.gradle.tooling.internal.protocol.*
+import org.gradle.tooling.model.GradleProject
+import org.gradle.tooling.model.build.BuildEnvironment
+import org.gradle.tooling.model.eclipse.EclipseProject
+import org.gradle.tooling.model.eclipse.HierarchicalEclipseProject
+import org.gradle.tooling.model.idea.BasicIdeaProject
+import org.gradle.tooling.model.idea.IdeaProject
+import org.gradle.tooling.model.internal.outcomes.ProjectOutcomes
+import spock.lang.Specification
+
+class ModelBuilderBackedConsumerConnectionTest extends Specification {
+ final target = Mock(TestModelBuilder) {
+ getMetaData() >> Mock(ConnectionMetaDataVersion1) {
+ getVersion() >> '1.2'
+ }
+ }
+ final adapter = Stub(ProtocolToModelAdapter)
+ final modelMapping = Mock(ModelMapping)
+ final connection = new ModelBuilderBackedConsumerConnection(target, modelMapping, adapter)
+
+ def "describes capabilities of the provider"() {
+ given:
+ def details = connection.versionDetails
+
+ expect:
+ details.supportsGradleProjectModel()
+
+ and:
+ details.isModelSupported(HierarchicalEclipseProject)
+ details.isModelSupported(EclipseProject)
+ details.isModelSupported(IdeaProject)
+ details.isModelSupported(BasicIdeaProject)
+ details.isModelSupported(GradleProject)
+ details.isModelSupported(BuildEnvironment)
+ details.isModelSupported(ProjectOutcomes)
+ details.isModelSupported(Void)
+ details.isModelSupported(CustomModel)
+ }
+
+ def "maps model type to model identifier"() {
+ def parameters = Stub(ConsumerOperationParameters)
+ def modelIdentifier = Stub(ModelIdentifier)
+
+ when:
+ connection.run(GradleProject, parameters)
+
+ then:
+ 1 * modelMapping.getModelIdentifierFromModelType(GradleProject) >> modelIdentifier
+ 1 * target.getModel(modelIdentifier, parameters) >> Stub(BuildResult)
+ }
+
+ def "maps internal unknown model exception to API exception"() {
+ def parameters = Stub(ConsumerOperationParameters)
+ def modelIdentifier = Stub(ModelIdentifier)
+
+ given:
+ _ * modelMapping.getModelIdentifierFromModelType(GradleProject) >> modelIdentifier
+ _ * target.getModel(modelIdentifier, parameters) >> { throw new InternalUnsupportedModelException() }
+
+ when:
+ connection.run(GradleProject, parameters)
+
+ then:
+ UnknownModelException e = thrown()
+ e.message == /No model of type 'GradleProject' is available in this build./
+ }
+
+ def "fails when build action requested"() {
+ def parameters = Stub(ConsumerOperationParameters)
+
+ given:
+ parameters.tasks >> ['a']
+
+ when:
+ connection.run(Stub(BuildAction), parameters)
+
+ then:
+ UnsupportedVersionException e = thrown()
+ e.message == /The version of Gradle you are using (1.2) does not support execution of build actions provided by the tooling API client. Support for this was added in Gradle 1.8 and is available in all later versions./
+ }
+
+ interface TestModelBuilder extends ModelBuilder, ConnectionVersion4, ConfigurableConnection {
+ }
+}
diff --git a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/connection/ProgressLoggingConnectionTest.groovy b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/connection/ProgressLoggingConnectionTest.groovy
deleted file mode 100644
index 5c60bd2..0000000
--- a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/connection/ProgressLoggingConnectionTest.groovy
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.consumer.connection
-
-import org.gradle.listener.ListenerManager
-import org.gradle.logging.ProgressLogger
-import org.gradle.logging.ProgressLoggerFactory
-import org.gradle.tooling.internal.consumer.LoggingProvider
-import org.gradle.tooling.internal.consumer.parameters.ConsumerOperationParameters
-import org.gradle.tooling.internal.protocol.ProgressListenerVersion1
-import spock.lang.Specification
-
-class ProgressLoggingConnectionTest extends Specification {
- final ConsumerConnection target = Mock()
- final ConsumerOperationParameters params = Mock()
- final ProgressListenerVersion1 listener = Mock()
- final ProgressLogger progressLogger = Mock()
- final ProgressLoggerFactory progressLoggerFactory = Mock()
- final ListenerManager listenerManager = Mock()
- final LoggingProvider loggingProvider = Mock()
- final ProgressLoggingConnection connection = new ProgressLoggingConnection(target, loggingProvider)
-
- static class SomeModel {}
-
- def notifiesProgressListenerOfStartAndEndOfFetchingModel() {
- when:
- connection.run(SomeModel, params)
-
- then:
- 1 * loggingProvider.getListenerManager() >> listenerManager
- 1 * loggingProvider.getProgressLoggerFactory() >> progressLoggerFactory
- 1 * listenerManager.addListener(!null)
- 1 * progressLoggerFactory.newOperation(ProgressLoggingConnection.class) >> progressLogger
- 1 * progressLogger.setDescription('Build')
- 1 * progressLogger.started()
- 1 * target.run(SomeModel, params)
- 1 * progressLogger.completed()
- 1 * listenerManager.removeListener(!null)
- _ * params.progressListener >> listener
- 0 * _._
- }
-}
diff --git a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/connection/ProgressLoggingConsumerActionExecutorTest.groovy b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/connection/ProgressLoggingConsumerActionExecutorTest.groovy
new file mode 100644
index 0000000..e54567e
--- /dev/null
+++ b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/connection/ProgressLoggingConsumerActionExecutorTest.groovy
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.consumer.connection
+
+import org.gradle.listener.ListenerManager
+import org.gradle.logging.ProgressLogger
+import org.gradle.logging.ProgressLoggerFactory
+import org.gradle.tooling.internal.consumer.LoggingProvider
+import org.gradle.tooling.internal.consumer.parameters.ConsumerOperationParameters
+import org.gradle.tooling.internal.protocol.ProgressListenerVersion1
+import spock.lang.Specification
+
+class ProgressLoggingConsumerActionExecutorTest extends Specification {
+ final ConsumerActionExecutor target = Mock()
+ final ConsumerAction<String> action = Mock()
+ final ConsumerOperationParameters params = Mock()
+ final ProgressListenerVersion1 listener = Mock()
+ final ProgressLogger progressLogger = Mock()
+ final ProgressLoggerFactory progressLoggerFactory = Mock()
+ final ListenerManager listenerManager = Mock()
+ final LoggingProvider loggingProvider = Mock()
+ final ProgressLoggingConsumerActionExecutor connection = new ProgressLoggingConsumerActionExecutor(target, loggingProvider)
+
+ def notifiesProgressListenerOfStartAndEndOfFetchingModel() {
+ when:
+ connection.run(action)
+
+ then:
+ 1 * loggingProvider.listenerManager >> listenerManager
+ 1 * loggingProvider.progressLoggerFactory >> progressLoggerFactory
+ 1 * listenerManager.addListener(!null)
+ 1 * progressLoggerFactory.newOperation(ProgressLoggingConsumerActionExecutor.class) >> progressLogger
+ 1 * progressLogger.setDescription('Build')
+ 1 * progressLogger.started()
+ 1 * target.run(action)
+ 1 * progressLogger.completed()
+ 1 * listenerManager.removeListener(!null)
+ _ * params.progressListener >> listener
+ _ * action.parameters >> params
+ 0 * _._
+ }
+}
diff --git a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/loader/DefaultToolingImplementationLoaderTest.groovy b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/loader/DefaultToolingImplementationLoaderTest.groovy
index 7b87549..4b51377 100644
--- a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/loader/DefaultToolingImplementationLoaderTest.groovy
+++ b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/loader/DefaultToolingImplementationLoaderTest.groovy
@@ -15,31 +15,30 @@
*/
package org.gradle.tooling.internal.consumer.loader
+import org.gradle.internal.classloader.ClasspathUtil
import org.gradle.internal.classpath.DefaultClassPath
import org.gradle.logging.ProgressLoggerFactory
import org.gradle.messaging.actor.ActorFactory
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
-import org.gradle.tooling.UnsupportedVersionException
import org.gradle.tooling.internal.consumer.Distribution
-import org.gradle.tooling.internal.consumer.connection.AdaptedConnection
-import org.gradle.tooling.internal.consumer.connection.BuildActionRunnerBackedConsumerConnection
-import org.gradle.tooling.internal.consumer.connection.InternalConnectionBackedConsumerConnection
+import org.gradle.tooling.internal.consumer.connection.*
import org.gradle.tooling.internal.consumer.parameters.ConsumerConnectionParameters
import org.gradle.tooling.internal.protocol.*
-import org.gradle.util.ClasspathUtil
+import org.gradle.tooling.internal.protocol.exceptions.InternalUnsupportedBuildArgumentException
import org.gradle.util.GradleVersion
import org.junit.Rule
import org.slf4j.Logger
import spock.lang.Specification
class DefaultToolingImplementationLoaderTest extends Specification {
- @Rule public final TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider()
+ @Rule
+ public final TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider()
Distribution distribution = Mock()
ProgressLoggerFactory loggerFactory = Mock()
+ final loader = new DefaultToolingImplementationLoader()
def "locates connection implementation using meta-inf service then instantiates and configures the connection"() {
given:
- def loader = new DefaultToolingImplementationLoader()
distribution.getToolingImplementationClasspath(loggerFactory) >> new DefaultClassPath(
getToolingApiResourcesDir(connectionImplementation),
ClasspathUtil.getClasspathForClass(TestConnection.class),
@@ -61,10 +60,12 @@ class DefaultToolingImplementationLoaderTest extends Specification {
adaptedConnection.class == adapter
where:
- connectionImplementation | adapter
- TestConnection.class | BuildActionRunnerBackedConsumerConnection.class
- TestOldConnection.class | InternalConnectionBackedConsumerConnection.class
- TestEvenOlderConnection.class | AdaptedConnection.class
+ connectionImplementation | adapter
+ TestConnection.class | ActionAwareConsumerConnection.class
+ TestR16Connection.class | ModelBuilderBackedConsumerConnection.class
+ TestR12Connection.class | BuildActionRunnerBackedConsumerConnection.class
+ TestR10M8Connection.class | InternalConnectionBackedConsumerConnection.class
+ TestR10M3Connection.class | ConnectionVersion4BackedConsumerConnection.class
}
private getToolingApiResourcesDir(Class implementation) {
@@ -76,78 +77,65 @@ class DefaultToolingImplementationLoaderTest extends Specification {
return ClasspathUtil.getClasspathForResource(getClass().classLoader, "org/gradle/build-receipt.properties")
}
- def failsWhenNoImplementationDeclared() {
- ClassLoader cl = new ClassLoader() {}
- def loader = new DefaultToolingImplementationLoader(cl)
+ def "creates broken connection when resource not found"() {
+ def loader = new DefaultToolingImplementationLoader()
- when:
- loader.create(distribution, loggerFactory, new ConsumerConnectionParameters(true))
+ given:
+ distribution.getToolingImplementationClasspath(loggerFactory) >> new DefaultClassPath()
- then:
- UnsupportedVersionException e = thrown()
- e.message == "The specified <dist-display-name> is not supported by this tooling API version (${GradleVersion.current().version}, protocol version 4)"
- _ * distribution.getToolingImplementationClasspath(loggerFactory) >> new DefaultClassPath()
- _ * distribution.displayName >> '<dist-display-name>'
+ expect:
+ loader.create(distribution, loggerFactory, new ConsumerConnectionParameters(true)) instanceof NoToolingApiConnection
}
}
-class TestConnection implements ConnectionVersion4, BuildActionRunner, ConfigurableConnection {
- boolean configured
-
- void configure(ConnectionParameters parameters) {
- configured = parameters.verboseLogging
- }
-
- def <T> BuildResult<T> run(Class<T> type, BuildParameters parameters) {
- throw new UnsupportedOperationException()
+class TestMetaData implements ConnectionMetaDataVersion1 {
+ String getVersion() {
+ return "1.1"
}
- void stop() {
- throw new UnsupportedOperationException()
- }
-
- ConnectionMetaDataVersion1 getMetaData() {
+ String getDisplayName() {
throw new UnsupportedOperationException()
}
+}
- ProjectVersion3 getModel(Class<? extends ProjectVersion3> type, BuildOperationParametersVersion1 operationParameters) {
+class TestConnection extends TestR16Connection implements InternalBuildActionExecutor {
+ def <T> BuildResult<T> run(InternalBuildAction<T> action, BuildParameters operationParameters) throws BuildExceptionVersion1, InternalUnsupportedBuildArgumentException, IllegalStateException {
throw new UnsupportedOperationException()
}
+}
- void executeBuild(BuildParametersVersion1 buildParameters, BuildOperationParametersVersion1 operationParameters) {
+class TestR16Connection extends TestR12Connection implements ModelBuilder {
+ BuildResult<Object> getModel(ModelIdentifier modelIdentifier, BuildParameters operationParameters) throws UnsupportedOperationException, IllegalStateException {
throw new UnsupportedOperationException()
}
}
-class TestOldConnection implements InternalConnection {
- boolean configured
-
- void configureLogging(boolean verboseLogging) {
- configured = verboseLogging
- }
-
- def <T> T getTheModel(Class<T> type, BuildOperationParametersVersion1 operationParameters) {
- throw new UnsupportedOperationException()
+class TestR12Connection extends TestR10M8Connection implements BuildActionRunner, ConfigurableConnection {
+ void configure(ConnectionParameters parameters) {
+ configured = parameters.verboseLogging
}
- void stop() {
+ @Override
+ void configureLogging(boolean verboseLogging) {
throw new UnsupportedOperationException()
}
- ConnectionMetaDataVersion1 getMetaData() {
+ def <T> BuildResult<T> run(Class<T> type, BuildParameters parameters) {
throw new UnsupportedOperationException()
}
+}
- ProjectVersion3 getModel(Class<? extends ProjectVersion3> type, BuildOperationParametersVersion1 operationParameters) {
+class TestR10M8Connection extends TestR10M3Connection implements InternalConnection {
+ def <T> T getTheModel(Class<T> type, BuildOperationParametersVersion1 operationParameters) {
throw new UnsupportedOperationException()
}
- void executeBuild(BuildParametersVersion1 buildParameters, BuildOperationParametersVersion1 operationParameters) {
- throw new UnsupportedOperationException()
+ void configureLogging(boolean verboseLogging) {
+ configured = verboseLogging
}
}
-class TestEvenOlderConnection implements ConnectionVersion4 {
+class TestR10M3Connection implements ConnectionVersion4 {
boolean configured
void configureLogging(boolean verboseLogging) {
@@ -159,7 +147,7 @@ class TestEvenOlderConnection implements ConnectionVersion4 {
}
ConnectionMetaDataVersion1 getMetaData() {
- throw new UnsupportedOperationException()
+ return new TestMetaData()
}
ProjectVersion3 getModel(Class<? extends ProjectVersion3> type, BuildOperationParametersVersion1 operationParameters) {
diff --git a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/loader/SynchronizedToolingImplementationLoaderTest.groovy b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/loader/SynchronizedToolingImplementationLoaderTest.groovy
index 1fec08d..edb77e3 100644
--- a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/loader/SynchronizedToolingImplementationLoaderTest.groovy
+++ b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/loader/SynchronizedToolingImplementationLoaderTest.groovy
@@ -26,9 +26,6 @@ import spock.lang.Specification
import java.util.concurrent.locks.Lock
import java.util.concurrent.locks.ReentrantLock
-/**
- * by Szczepan Faber, created at: 12/15/11
- */
public class SynchronizedToolingImplementationLoaderTest extends Specification {
def factory = Mock(ProgressLoggerFactory)
diff --git a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/parameters/ConsumerOperationParametersTest.groovy b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/parameters/ConsumerOperationParametersTest.groovy
index fd7f727..06ba955 100644
--- a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/parameters/ConsumerOperationParametersTest.groovy
+++ b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/parameters/ConsumerOperationParametersTest.groovy
@@ -18,9 +18,6 @@ package org.gradle.tooling.internal.consumer.parameters
import spock.lang.Specification
-/**
- * by Szczepan Faber, created at: 3/12/12
- */
class ConsumerOperationParametersTest extends Specification {
def params = new ConsumerOperationParameters(null)
diff --git a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/protocoladapter/ProtocolToModelAdapterTest.groovy b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/protocoladapter/ProtocolToModelAdapterTest.groovy
deleted file mode 100644
index add0d55..0000000
--- a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/protocoladapter/ProtocolToModelAdapterTest.groovy
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.consumer.protocoladapter
-
-import org.gradle.tooling.internal.idea.DefaultIdeaModuleDependency
-import org.gradle.tooling.internal.idea.DefaultIdeaSingleEntryLibraryDependency
-import org.gradle.tooling.model.UnsupportedMethodException
-import org.gradle.tooling.model.idea.IdeaDependency
-import org.gradle.tooling.model.idea.IdeaModuleDependency
-import org.gradle.tooling.model.idea.IdeaSingleEntryLibraryDependency
-import org.gradle.util.Matchers
-import spock.lang.Specification
-import org.gradle.tooling.internal.consumer.*
-
-/**
- * by Szczepan Faber, created at: 4/2/12
- */
-class ProtocolToModelAdapterTest extends Specification {
- final ProtocolToModelAdapter adapter = new ProtocolToModelAdapter()
-
- def createsProxyAdapterForProtocolModel() {
- TestProtocolModel protocolModel = Mock()
-
- expect:
- adapter.adapt(TestModel.class, protocolModel) instanceof TestModel
- }
-
- def proxiesAreEqualWhenTargetProtocolObjectsAreEqual() {
- TestProtocolModel protocolModel1 = Mock()
- TestProtocolModel protocolModel2 = Mock()
-
- def model = adapter.adapt(TestModel.class, protocolModel1)
- def equal = adapter.adapt(TestModel.class, protocolModel1)
- def different = adapter.adapt(TestModel.class, protocolModel2)
-
- expect:
- Matchers.strictlyEquals(model, equal)
- model != different
- }
-
- def methodInvocationOnModelDelegatesToTheProtocolModelObject() {
- TestProtocolModel protocolModel = Mock()
- _ * protocolModel.getName() >> 'name'
-
- expect:
- def model = adapter.adapt(TestModel.class, protocolModel)
- model.name == 'name'
- }
-
- def createsProxyAdapterForMethodReturnValue() {
- TestProtocolModel protocolModel = Mock()
- TestProtocolProject protocolProject = Mock()
- _ * protocolModel.getProject() >> protocolProject
- _ * protocolProject.getName() >> 'name'
-
- expect:
- def model = adapter.adapt(TestModel.class, protocolModel)
- model.project instanceof TestProject
- model.project.name == 'name'
- }
-
- def doesNotAdaptNullReturnValue() {
- TestProtocolModel protocolModel = Mock()
- _ * protocolModel.getProject() >> null
-
- expect:
- def model = adapter.adapt(TestModel.class, protocolModel)
- model.project == null
- }
-
- def adaptsIterableToDomainObjectSet() {
- TestProtocolModel protocolModel = Mock()
- TestProtocolProject protocolProject = Mock()
- _ * protocolModel.getChildren() >> [protocolProject]
- _ * protocolProject.getName() >> 'name'
-
- expect:
- def model = adapter.adapt(TestModel.class, protocolModel)
- model.children.size() == 1
- model.children[0] instanceof TestProject
- model.children[0].name == 'name'
- }
-
- def cachesPropertyValues() {
- TestProtocolModel protocolModel = Mock()
- TestProtocolProject protocolProject = Mock()
- _ * protocolModel.getProject() >> protocolProject
- _ * protocolModel.getChildren() >> [protocolProject]
- _ * protocolProject.getName() >> 'name'
-
- expect:
- def model = adapter.adapt(TestModel.class, protocolModel)
- model.project.is(model.project)
- model.children.is(model.children)
- }
-
- def reportsMethodWhichDoesNotExistOnProtocolObject() {
- PartialTestProtocolModel protocolModel = Mock()
-
- when:
- def model = adapter.adapt(TestModel.class, protocolModel)
- model.project
-
- then:
- UnsupportedMethodException e = thrown()
- e.message.contains "TestModel.getProject()"
- }
-
- def propagatesExceptionThrownByProtocolObject() {
- TestProtocolModel protocolModel = Mock()
- RuntimeException failure = new RuntimeException()
-
- when:
- def model = adapter.adapt(TestModel.class, protocolModel)
- model.name
-
- then:
- protocolModel.name >> { throw failure }
- RuntimeException e = thrown()
- e == failure
- }
-
- def isPropertySupportedMethodReturnsTrueWhenProtocolObjectHasAssociatedProperty() {
- TestProtocolModel protocolModel = Mock()
-
- when:
- def model = adapter.adapt(TestModel.class, protocolModel)
-
- then:
- model.configSupported
- }
-
- def isPropertySupportedMethodReturnsFalseWhenProtocolObjectDoesNotHaveAssociatedProperty() {
- PartialTestProtocolModel protocolModel = Mock()
-
- when:
- def model = adapter.adapt(TestModel.class, protocolModel)
-
- then:
- !model.configSupported
- }
-
- def safeGetterDelegatesToProtocolObject() {
- TestProtocolModel protocolModel = Mock()
-
- given:
- protocolModel.config >> "value"
-
- when:
- def model = adapter.adapt(TestModel.class, protocolModel)
-
- then:
- model.getConfig("default") == "value"
- }
-
- def safeGetterDelegatesReturnsDefaultValueWhenProtocolObjectDoesNotHaveAssociatedProperty() {
- PartialTestProtocolModel protocolModel = Mock()
-
- when:
- def model = adapter.adapt(TestModel.class, protocolModel)
-
- then:
- model.getConfig("default") == "default"
- }
-
- def safeGetterDelegatesReturnsDefaultValueWhenPropertyValueIsNull() {
- TestProtocolModel protocolModel = Mock()
-
- given:
- protocolModel.config >> null
-
- when:
- def model = adapter.adapt(TestModel.class, protocolModel)
-
- then:
- model.getConfig("default") == "default"
- }
-
- def methodInvokerCanOverrideGetterMethod() {
- MethodInvoker propertyHandler = Mock()
- TestProtocolModel protocolModel = Mock()
- TestProject project = Mock()
-
- given:
- propertyHandler.invoke({it.name == 'getProject'}) >> { MethodInvocation method -> method.result = project }
-
- when:
- def model = adapter.adapt(TestModel.class, protocolModel, propertyHandler)
-
- then:
- model.project == project
-
- and:
- 0 * protocolModel._
- }
-
- def methodInvokerCanProvideGetterMethodImplementation() {
- MethodInvoker propertyHandler = Mock()
- PartialTestProtocolModel protocolModel = Mock()
- TestProject project = Mock()
-
- given:
- propertyHandler.invoke({it.name == 'getProject'}) >> { MethodInvocation method -> method.result = project }
-
- when:
- def model = adapter.adapt(TestModel.class, protocolModel, propertyHandler)
-
- then:
- model.project == project
-
- and:
- 0 * protocolModel._
- }
-
- def methodInvokerPropertiesAreCached() {
- MethodInvoker propertyHandler = Mock()
- PartialTestProtocolModel protocolModel = Mock()
- TestProject project = Mock()
-
- when:
- def model = adapter.adapt(TestModel.class, protocolModel, propertyHandler)
- model.project
- model.project
-
- then:
- 1 * propertyHandler.invoke(!null) >> { MethodInvocation method -> method.result = project }
- 0 * propertyHandler._
- 0 * protocolModel._
- }
-
- def canMixInMethodsFromAnotherBean() {
- PartialTestProtocolModel protocolModel = Mock()
-
- given:
- protocolModel.name >> 'name'
-
- when:
- def model = adapter.adapt(TestModel.class, protocolModel, ConfigMixin)
-
- then:
- model.name == "[name]"
- model.getConfig('default') == "[default]"
- }
-
- def "adapts idea dependencies"() {
- def libraryDep = new GroovyClassLoader().loadClass(DefaultIdeaSingleEntryLibraryDependency.class.getCanonicalName()).newInstance()
- def moduleDep = new GroovyClassLoader().loadClass(DefaultIdeaModuleDependency.class.getCanonicalName()).newInstance()
-
- when:
- def library = adapter.adapt(IdeaDependency.class, libraryDep)
- def module = adapter.adapt(IdeaDependency.class, moduleDep)
-
- then:
- library instanceof IdeaSingleEntryLibraryDependency
- module instanceof IdeaModuleDependency
- }
-}
diff --git a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/versioning/ModelMappingTest.groovy b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/versioning/ModelMappingTest.groovy
new file mode 100644
index 0000000..f8b7d58
--- /dev/null
+++ b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/consumer/versioning/ModelMappingTest.groovy
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.tooling.internal.consumer.versioning
+
+import org.gradle.tooling.internal.protocol.*
+import org.gradle.tooling.internal.protocol.eclipse.EclipseProjectVersion3
+import org.gradle.tooling.internal.protocol.eclipse.HierarchicalEclipseProjectVersion1
+import org.gradle.tooling.model.gradle.GradleBuild
+import org.gradle.tooling.model.GradleProject
+import org.gradle.tooling.model.build.BuildEnvironment
+import org.gradle.tooling.model.eclipse.EclipseProject
+import org.gradle.tooling.model.eclipse.HierarchicalEclipseProject
+import org.gradle.tooling.model.idea.BasicIdeaProject
+import org.gradle.tooling.model.idea.IdeaProject
+import org.gradle.tooling.model.internal.outcomes.ProjectOutcomes
+import spock.lang.Specification
+
+class ModelMappingTest extends Specification {
+ final mapping = new ModelMapping()
+
+ def "maps model type to protocol type"() {
+ expect:
+ mapping.getProtocolType(modelType) == protocolType
+
+ where:
+ modelType | protocolType
+ Void | Void
+ HierarchicalEclipseProject | HierarchicalEclipseProjectVersion1
+ EclipseProject | EclipseProjectVersion3
+ IdeaProject | InternalIdeaProject
+ GradleProject | InternalGradleProject
+ BasicIdeaProject | InternalBasicIdeaProject
+ BuildEnvironment | InternalBuildEnvironment
+ ProjectOutcomes | InternalProjectOutcomes
+ }
+
+ def "can use a protocol type as model type"() {
+ expect:
+ mapping.getProtocolType(modelType) == modelType
+
+ where:
+ modelType << [
+ HierarchicalEclipseProjectVersion1,
+ EclipseProjectVersion3,
+ InternalIdeaProject,
+ InternalGradleProject,
+ InternalBasicIdeaProject,
+ InternalBuildEnvironment,
+ InternalProjectOutcomes
+ ]
+ }
+
+ def "uses null protocol type for custom model type"() {
+ expect:
+ mapping.getProtocolType(CustomModel) == null
+ }
+
+ def "uses null protocol type for model types added after 1.6"() {
+ expect:
+ mapping.getProtocolType(GradleBuild) == null
+ }
+
+ def "maps model type to model identifier"() {
+ expect:
+ def id = mapping.getModelIdentifierFromModelType(modelType)
+ id.name == modelName
+
+ where:
+ modelType | modelName
+ Void | ModelIdentifier.NULL_MODEL
+ HierarchicalEclipseProject | "org.gradle.tooling.model.eclipse.HierarchicalEclipseProject"
+ EclipseProject | "org.gradle.tooling.model.eclipse.EclipseProject"
+ IdeaProject | "org.gradle.tooling.model.idea.IdeaProject"
+ GradleProject | "org.gradle.tooling.model.GradleProject"
+ BasicIdeaProject | "org.gradle.tooling.model.idea.BasicIdeaProject"
+ BuildEnvironment | "org.gradle.tooling.model.build.BuildEnvironment"
+ ProjectOutcomes | "org.gradle.tooling.model.outcomes.ProjectOutcomes"
+ GradleBuild | "org.gradle.tooling.model.gradle.GradleBuild"
+ CustomModel | CustomModel.name
+ }
+
+ def "maps model type to version it was added in"() {
+ expect:
+ mapping.getVersionAdded(modelType) == since
+
+ where:
+ modelType | since
+ Void | "1.0-milestone-3"
+ HierarchicalEclipseProject | "1.0-milestone-3"
+ EclipseProject | "1.0-milestone-3"
+ IdeaProject | "1.0-milestone-5"
+ GradleProject | "1.0-milestone-5"
+ BasicIdeaProject | "1.0-milestone-5"
+ BuildEnvironment | "1.0-milestone-8"
+ ProjectOutcomes | "1.2"
+ GradleBuild | "1.8"
+ CustomModel | null
+ }
+}
+
+interface CustomModel {}
diff --git a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/eclipse/DefaultEclipseProjectTest.groovy b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/eclipse/DefaultEclipseProjectTest.groovy
deleted file mode 100644
index 5fdbc7f..0000000
--- a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/eclipse/DefaultEclipseProjectTest.groovy
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.eclipse
-
-import spock.lang.Specification
-
-class DefaultEclipseProjectTest extends Specification {
- def usesPathForToStringValue() {
- def project = new DefaultEclipseProject("name", ":path", null, null, [])
-
- expect:
- project.toString() == "project ':path'"
- }
-}
diff --git a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/reflect/CompatibleIntrospectorTest.groovy b/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/reflect/CompatibleIntrospectorTest.groovy
deleted file mode 100644
index bd12f78..0000000
--- a/subprojects/tooling-api/src/test/groovy/org/gradle/tooling/internal/reflect/CompatibleIntrospectorTest.groovy
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gradle.tooling.internal.reflect
-
-import spock.lang.Specification
-
-/**
- * by Szczepan Faber, created at: 3/16/12
- */
-class CompatibleIntrospectorTest extends Specification {
-
- class Foo {
-
- int number
-
- String getMessage() {
- "Hello!"
- }
-
- void setNumber(int number) {
- this.number = number
- }
- }
-
- def foo = new Foo()
- def intro = new CompatibleIntrospector(foo)
-
- def "gets stuff safely"() {
- expect:
- 'Hello!' == intro.getSafely('blah', 'getMessage')
- 'blah' == intro.getSafely('blah', 'doesNotExist')
- }
-
- def "calls methods safely"() {
- when:
- intro.callSafely('doesNotExist', 10)
- then:
- foo.number == 0
-
- when:
- intro.callSafely('setNumber', 10)
- then:
- foo.number == 10
- }
-}
diff --git a/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/GradleVersionSpec.java b/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/GradleVersionSpec.java
new file mode 100644
index 0000000..d915a14
--- /dev/null
+++ b/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/GradleVersionSpec.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests.tooling.fixture;
+
+import org.gradle.api.specs.Spec;
+import org.gradle.api.specs.Specs;
+import org.gradle.util.GradleVersion;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class GradleVersionSpec {
+ public static Spec<GradleVersion> toSpec(String constraint) {
+ String trimmed = constraint.trim();
+ if (trimmed.equals("current")) {
+ return new Spec<GradleVersion>() {
+ public boolean isSatisfiedBy(GradleVersion element) {
+ return element.equals(GradleVersion.current());
+ }
+ };
+ }
+ if (trimmed.equals("!current")) {
+ return new Spec<GradleVersion>() {
+ public boolean isSatisfiedBy(GradleVersion element) {
+ return !element.equals(GradleVersion.current());
+ }
+ };
+ }
+ if (trimmed.startsWith("=")) {
+ final GradleVersion target = GradleVersion.version(trimmed.substring(1)).getBaseVersion();
+ return new Spec<GradleVersion>() {
+ public boolean isSatisfiedBy(GradleVersion element) {
+ return element.getBaseVersion().equals(target);
+ }
+ };
+ }
+
+ List<Spec> specs = new ArrayList<Spec>();
+ String[] patterns = trimmed.split("\\s+");
+ for (String value : patterns) {
+ if (value.startsWith(">=")) {
+ final GradleVersion minVersion = GradleVersion.version(value.substring(2));
+ specs.add(new Spec<GradleVersion>() {
+ public boolean isSatisfiedBy(GradleVersion element) {
+ return element.getBaseVersion().compareTo(minVersion) >= 0;
+ }
+ });
+ } else if (value.startsWith("<=")) {
+ final GradleVersion maxVersion = GradleVersion.version(value.substring(2));
+ specs.add(new Spec<GradleVersion>() {
+ public boolean isSatisfiedBy(GradleVersion element) {
+ return element.getBaseVersion().compareTo(maxVersion) <= 0;
+ }
+ });
+ } else if (value.startsWith("<")) {
+ final GradleVersion maxVersion = GradleVersion.version(value.substring(1));
+ specs.add(new Spec<GradleVersion>() {
+ public boolean isSatisfiedBy(GradleVersion element) {
+ return element.getBaseVersion().compareTo(maxVersion) < 0;
+ }
+ });
+ } else {
+ throw new RuntimeException(String.format("Unsupported version range '%s' specified in constraint '%s'. Supported formats: '>=nnn' or '<=nnn' or space-separate patterns", value, constraint));
+ }
+ }
+ return Specs.and(specs.toArray(new Spec[specs.size()]));
+ }
+
+}
diff --git a/subprojects/tooling-api/tooling-api.gradle b/subprojects/tooling-api/tooling-api.gradle
index e8e76a7..0d6f0b9 100644
--- a/subprojects/tooling-api/tooling-api.gradle
+++ b/subprojects/tooling-api/tooling-api.gradle
@@ -2,15 +2,19 @@ import org.gradle.build.*
import org.gradle.api.internal.artifacts.publish.ArchivePublishArtifact
dependencies {
- groovy libraries.groovy
compile project(path: ':core', configuration: "publishCompileWithProjectJar")
compile project(':messaging')
compile project(':wrapper')
compile project(':baseServices')
publishCompile libraries.slf4j_api
+ testFixturesCompile project(':baseServicesGroovy')
+ testCompile libraries.groovy
+
// lots of integTest errors otherwise
integTestRuntime project(':ide')
+ integTestRuntime project(':buildSetup')
+ integTestRuntime project(':buildComparison')
}
useTestFixtures()
@@ -35,7 +39,6 @@ task jarjarJar(type: JarJarJar) {
exclude "META-INF/**"
exclude "*classpath.properties"
-
rule('org.gradle.**', '@0')
rule('org.slf4j.**', '@0')
diff --git a/subprojects/ui/src/integTest/groovy/org/gradle/integtests/FavoritesIntegrationTest.java b/subprojects/ui/src/integTest/groovy/org/gradle/integtests/FavoritesIntegrationTest.java
index 54cb773..1e99fb3 100644
--- a/subprojects/ui/src/integTest/groovy/org/gradle/integtests/FavoritesIntegrationTest.java
+++ b/subprojects/ui/src/integTest/groovy/org/gradle/integtests/FavoritesIntegrationTest.java
@@ -38,8 +38,6 @@ import java.util.List;
/**
* Performs integration tests on favorite tasks.
- *
- * @author mhunsicker
*/
public class FavoritesIntegrationTest {
@Rule
diff --git a/subprojects/ui/src/integTest/groovy/org/gradle/integtests/LiveOutputIntegrationTest.groovy b/subprojects/ui/src/integTest/groovy/org/gradle/integtests/LiveOutputIntegrationTest.groovy
index b6a4cf1..8ab2eda 100644
--- a/subprojects/ui/src/integTest/groovy/org/gradle/integtests/LiveOutputIntegrationTest.groovy
+++ b/subprojects/ui/src/integTest/groovy/org/gradle/integtests/LiveOutputIntegrationTest.groovy
@@ -37,7 +37,6 @@ import java.util.concurrent.locks.ReentrantLock
/**
This tests the that live output is gathered while executing a task.
- at author mhunsicker
*/
class LiveOutputIntegrationTest extends AbstractIntegrationTest {
@@ -61,8 +60,6 @@ class LiveOutputIntegrationTest extends AbstractIntegrationTest {
This executes 'build' on the java multiproject sample. We want to make sure that
we do get live output from gradle. We're not concerned with what it is, because
that's likely to change over time. This version executes the command via GradlePlugin.
-
- at author mhunsicker
*/
@Test
@@ -89,8 +86,6 @@ that's likely to change over time. This version executes the command via GradleP
This executes 'build' on the java multiproject sample. We want to make sure that
we do get live output from gradle. We're not concerned with what it is, because
that's likely to change over time. This version executes the command via GradleRunner.
-
- at author mhunsicker
*/
@Test
public void liveOutputObtainedViaGradleRunner() {
diff --git a/subprojects/ui/src/integTest/groovy/org/gradle/integtests/MultiprojectProjectAndTaskListIntegrationTest.groovy b/subprojects/ui/src/integTest/groovy/org/gradle/integtests/MultiprojectProjectAndTaskListIntegrationTest.groovy
index a16c95e..e77daf7 100644
--- a/subprojects/ui/src/integTest/groovy/org/gradle/integtests/MultiprojectProjectAndTaskListIntegrationTest.groovy
+++ b/subprojects/ui/src/integTest/groovy/org/gradle/integtests/MultiprojectProjectAndTaskListIntegrationTest.groovy
@@ -32,7 +32,6 @@ import java.util.concurrent.TimeUnit
/**
This tests the multiproject sample with the GradleView mechanism.
- @author mhunsicker
*/
class MultiprojectProjectAndTaskListIntegrationTest extends AbstractIntegrationTest {
@@ -59,8 +58,6 @@ class MultiprojectProjectAndTaskListIntegrationTest extends AbstractIntegrationT
(services:webservice). This isn't really interested in the actual tasks
themselves (I fear those may change too often to worry with keeping the
test up to date).
-
- @author mhunsicker
*/
@Test
diff --git a/subprojects/ui/src/main/java/org/gradle/foundation/CommandLineAssistant.java b/subprojects/ui/src/main/java/org/gradle/foundation/CommandLineAssistant.java
index d2ce564..c5bd06f 100644
--- a/subprojects/ui/src/main/java/org/gradle/foundation/CommandLineAssistant.java
+++ b/subprojects/ui/src/main/java/org/gradle/foundation/CommandLineAssistant.java
@@ -23,8 +23,6 @@ import java.util.List;
/**
* Some helpful functions for manipulating command line arguments.
- *
- * @author mhunsicker
*/
public class CommandLineAssistant {
private final LoggingCommandLineConverter loggingCommandLineConverter = new LoggingCommandLineConverter();
diff --git a/subprojects/ui/src/main/java/org/gradle/foundation/PathParserPortion.java b/subprojects/ui/src/main/java/org/gradle/foundation/PathParserPortion.java
index 67f8d92..53afe34 100644
--- a/subprojects/ui/src/main/java/org/gradle/foundation/PathParserPortion.java
+++ b/subprojects/ui/src/main/java/org/gradle/foundation/PathParserPortion.java
@@ -17,8 +17,6 @@ package org.gradle.foundation;
/**
* Small helper class that aids walking a full task path which can be multiple projects deep with a task on the end.
- *
- * @author mhunsicker
*/
public class PathParserPortion {
private String firstPart;
diff --git a/subprojects/ui/src/main/java/org/gradle/foundation/ProjectConverter.java b/subprojects/ui/src/main/java/org/gradle/foundation/ProjectConverter.java
index fd3b2fc..92d96c0 100644
--- a/subprojects/ui/src/main/java/org/gradle/foundation/ProjectConverter.java
+++ b/subprojects/ui/src/main/java/org/gradle/foundation/ProjectConverter.java
@@ -24,8 +24,6 @@ import java.util.*;
/**
* This converts Gradle's projects into ProjectView objects. These can be safely reused unlike Gradle's projects.
- *
- * @author mhunsicker
*/
public class ProjectConverter {
private List<ProjectView> rootLevelResultingProjects = new ArrayList<ProjectView>();
diff --git a/subprojects/ui/src/main/java/org/gradle/foundation/ProjectView.java b/subprojects/ui/src/main/java/org/gradle/foundation/ProjectView.java
index ff708a9..de3fe02 100644
--- a/subprojects/ui/src/main/java/org/gradle/foundation/ProjectView.java
+++ b/subprojects/ui/src/main/java/org/gradle/foundation/ProjectView.java
@@ -27,8 +27,6 @@ import java.util.List;
/**
* Analog to gradle's Project but more light-weight and is better suited for using the gradle API from an IDE plugin. It is also easily serializable for passing across a socket. A project is a
* collection of source files that have tasks associated with them. The tasks build the project. Projects can contain other projects. This is immutable and ultimately comes from gradle files.
- *
- * @author mhunsicker
*/
public class ProjectView implements Comparable<ProjectView>, Serializable {
private final String name;
diff --git a/subprojects/ui/src/main/java/org/gradle/foundation/TaskView.java b/subprojects/ui/src/main/java/org/gradle/foundation/TaskView.java
index 1df6805..f1fe7ea 100644
--- a/subprojects/ui/src/main/java/org/gradle/foundation/TaskView.java
+++ b/subprojects/ui/src/main/java/org/gradle/foundation/TaskView.java
@@ -22,8 +22,6 @@ import java.io.Serializable;
/**
* Analog to gradle's Task but more light-weight and better suited for using the gradle API from an IDE plugin. It is also easily serializable for passing across a socket. A task is something you can
* execute and is part of a project. This is immutable and ultimately comes from gradle files.
- *
- * @author mhunsicker
*/
public class TaskView implements Comparable<TaskView>, Serializable {
private ProjectView project;
diff --git a/subprojects/ui/src/main/java/org/gradle/foundation/common/ListReorderer.java b/subprojects/ui/src/main/java/org/gradle/foundation/common/ListReorderer.java
index 14198a4..3f1f673 100644
--- a/subprojects/ui/src/main/java/org/gradle/foundation/common/ListReorderer.java
+++ b/subprojects/ui/src/main/java/org/gradle/foundation/common/ListReorderer.java
@@ -19,8 +19,6 @@ import java.util.*;
/**
* Utility class that allows lists to be reordered.
- *
- * @author Chris Hampton
*/
public class ListReorderer {
/**
diff --git a/subprojects/ui/src/main/java/org/gradle/foundation/common/ObserverLord.java b/subprojects/ui/src/main/java/org/gradle/foundation/common/ObserverLord.java
index 58d5ae3..235998e 100644
--- a/subprojects/ui/src/main/java/org/gradle/foundation/common/ObserverLord.java
+++ b/subprojects/ui/src/main/java/org/gradle/foundation/common/ObserverLord.java
@@ -33,10 +33,7 @@ import java.util.List;
* functions that call the add and remove functions here. Lastly, implement ObserverNotification and have it call the aforementioned observer interface appropriately. Note: you should actually
* implement ObserverNotification for each "message" you want to send. Example: One that would tell a view a node was added. One that would tell a view a node was deleted, etc. While you have multiple
* notification classes, you only need 1 (or few) actual observer interfaces, containing all the possible functions called by all notifications.
- *
- * @author mhunsicker
*/
-
public class ObserverLord<E> {
private List<E> regularObservers = new ArrayList<E>();
private List<E> eventQueueObservers = new ArrayList<E>();
diff --git a/subprojects/ui/src/main/java/org/gradle/foundation/common/ReorderableList.java b/subprojects/ui/src/main/java/org/gradle/foundation/common/ReorderableList.java
index f98fba0..59c952e 100644
--- a/subprojects/ui/src/main/java/org/gradle/foundation/common/ReorderableList.java
+++ b/subprojects/ui/src/main/java/org/gradle/foundation/common/ReorderableList.java
@@ -28,8 +28,6 @@ import java.util.*;
Unfortunately, we can't use Java's Object.clone() method because it is
protected and must be overridden as public to be used. So we can't call
obj.clone() on an Object instance.
-
- @author champton
*/
public class ReorderableList<E> implements List<E> {
@@ -516,7 +514,6 @@ public class ReorderableList<E> implements List<E> {
@param elementsToMove the elements that were moved
@return an integer array of the items to select.
- @author mhunsicker
*/
public int[] getIndices(List<E> elementsToMove) {
diff --git a/subprojects/ui/src/main/java/org/gradle/foundation/ipc/basic/ClientProcess.java b/subprojects/ui/src/main/java/org/gradle/foundation/ipc/basic/ClientProcess.java
index ff75244..5cc8a62 100644
--- a/subprojects/ui/src/main/java/org/gradle/foundation/ipc/basic/ClientProcess.java
+++ b/subprojects/ui/src/main/java/org/gradle/foundation/ipc/basic/ClientProcess.java
@@ -26,8 +26,6 @@ import java.net.Socket;
/**
* The client of what the ProcessLauncherServer launches. The client makes a connection to the server and sends messages to it. The server responds to those messages, but does not initiate
* communications otherwise. You implement the Protocol interface to handle the specifics of the communications.
- *
- * @author mhunsicker
*/
public class ClientProcess {
private final Logger logger = Logging.getLogger(ClientProcess.class);
diff --git a/subprojects/ui/src/main/java/org/gradle/foundation/ipc/basic/ExecutionInfo.java b/subprojects/ui/src/main/java/org/gradle/foundation/ipc/basic/ExecutionInfo.java
index 390bd52..30e0977 100644
--- a/subprojects/ui/src/main/java/org/gradle/foundation/ipc/basic/ExecutionInfo.java
+++ b/subprojects/ui/src/main/java/org/gradle/foundation/ipc/basic/ExecutionInfo.java
@@ -18,12 +18,8 @@ package org.gradle.foundation.ipc.basic;
import java.io.File;
import java.util.HashMap;
-/**
- * @author mhunsicker
- */
/*
Fill this in with whatever you need to launch your external process.
- @author mhunsicker
*/
public interface ExecutionInfo {
/**
diff --git a/subprojects/ui/src/main/java/org/gradle/foundation/ipc/basic/MessageObject.java b/subprojects/ui/src/main/java/org/gradle/foundation/ipc/basic/MessageObject.java
index 5bb9b09..c3834d8 100644
--- a/subprojects/ui/src/main/java/org/gradle/foundation/ipc/basic/MessageObject.java
+++ b/subprojects/ui/src/main/java/org/gradle/foundation/ipc/basic/MessageObject.java
@@ -21,8 +21,6 @@ import java.io.Serializable;
/**
* A holder for a message that is sent over a socket.
- *
- * @author mhunsicker
*/
public class MessageObject implements Serializable {
private String messageType;
diff --git a/subprojects/ui/src/main/java/org/gradle/foundation/ipc/basic/ObjectSocketWrapper.java b/subprojects/ui/src/main/java/org/gradle/foundation/ipc/basic/ObjectSocketWrapper.java
index 1f26353..4426671 100644
--- a/subprojects/ui/src/main/java/org/gradle/foundation/ipc/basic/ObjectSocketWrapper.java
+++ b/subprojects/ui/src/main/java/org/gradle/foundation/ipc/basic/ObjectSocketWrapper.java
@@ -26,8 +26,6 @@ import java.net.SocketException;
/**
* Wrapper around a java.net.Socket just to simplify usage.
- *
- * @author mhunsicker
*/
public class ObjectSocketWrapper {
private Socket socket;
diff --git a/subprojects/ui/src/main/java/org/gradle/foundation/ipc/basic/ProcessLauncherServer.java b/subprojects/ui/src/main/java/org/gradle/foundation/ipc/basic/ProcessLauncherServer.java
index 8e50e37..a5c6914 100644
--- a/subprojects/ui/src/main/java/org/gradle/foundation/ipc/basic/ProcessLauncherServer.java
+++ b/subprojects/ui/src/main/java/org/gradle/foundation/ipc/basic/ProcessLauncherServer.java
@@ -28,8 +28,6 @@ import java.io.ByteArrayOutputStream;
/**
* This launches an application as a separate process then listens for messages from it. You implement the Protocol interface to handle the specifics of the communications. To use this, instantiate
* it, then call start. When the communications are finished, call requestShutdown(). Your server's protocol can call sendMessage once communication is started to respond to client's messages.
- *
- * @author mhunsicker
*/
public class ProcessLauncherServer extends Server<ProcessLauncherServer.Protocol, ProcessLauncherServer.ServerObserver> {
private volatile ExecHandle externalProcess;
diff --git a/subprojects/ui/src/main/java/org/gradle/foundation/ipc/basic/Server.java b/subprojects/ui/src/main/java/org/gradle/foundation/ipc/basic/Server.java
index 6cbe2aa..7ac6364 100644
--- a/subprojects/ui/src/main/java/org/gradle/foundation/ipc/basic/Server.java
+++ b/subprojects/ui/src/main/java/org/gradle/foundation/ipc/basic/Server.java
@@ -27,8 +27,6 @@ import java.net.Socket;
/**
* This is a server that talks to a client via sockets (Rudimentary form of Inter-Process Communication (IPC)). This does the work of locating a free socket and starting the connection. To use this,
* you really only have to define a Protocol that handles the actual messages. You'll want to make your client startup a ClientProcess object that implements a corresponding Protocol.
- *
- * @author mhunsicker
*/
public class Server<P extends Server.Protocol, O extends Server.ServerObserver> {
private final Logger logger = Logging.getLogger(Server.class);
diff --git a/subprojects/ui/src/main/java/org/gradle/foundation/ipc/gradle/AbstractGradleServerProtocol.java b/subprojects/ui/src/main/java/org/gradle/foundation/ipc/gradle/AbstractGradleServerProtocol.java
index f1c80dd..de9d796 100644
--- a/subprojects/ui/src/main/java/org/gradle/foundation/ipc/gradle/AbstractGradleServerProtocol.java
+++ b/subprojects/ui/src/main/java/org/gradle/foundation/ipc/gradle/AbstractGradleServerProtocol.java
@@ -45,8 +45,6 @@ import java.util.List;
* This defines the basic behavior of all gradle protocols for interprocess communication. It manages handshaking, detecting if the client executed prematurely, as well as executing alternate external
* processes. All you need to do is extend this, implement the abstract functions, and make sure you call setHasReceivedBuildCompleteNotification() when whatever you were doing is complete (so we know
* any exiting is not premature).
- *
- * @author mhunsicker
*/
public abstract class AbstractGradleServerProtocol implements ProcessLauncherServer.Protocol {
private static final String INIT_SCRIPT_EXTENSION = ".gradle";
diff --git a/subprojects/ui/src/main/java/org/gradle/foundation/ipc/gradle/ExecuteGradleCommandClientProtocol.java b/subprojects/ui/src/main/java/org/gradle/foundation/ipc/gradle/ExecuteGradleCommandClientProtocol.java
index 3ab3ca5..55d6a30 100644
--- a/subprojects/ui/src/main/java/org/gradle/foundation/ipc/gradle/ExecuteGradleCommandClientProtocol.java
+++ b/subprojects/ui/src/main/java/org/gradle/foundation/ipc/gradle/ExecuteGradleCommandClientProtocol.java
@@ -40,8 +40,6 @@ import java.util.TimerTask;
/**
* This manages the communication between the UI and an externally-launched copy of Gradle when using socket-based inter-process communication. This is the client (gradle) side used when executing
* commands (the most common case). We add gradle listeners and send their notifications as messages back to the server.
- *
- * @author mhunsicker
*/
public class ExecuteGradleCommandClientProtocol implements ClientProcess.Protocol {
private final Logger logger = Logging.getLogger(ExecuteGradleCommandClientProtocol.class);
diff --git a/subprojects/ui/src/main/java/org/gradle/foundation/ipc/gradle/ExecuteGradleCommandServerProtocol.java b/subprojects/ui/src/main/java/org/gradle/foundation/ipc/gradle/ExecuteGradleCommandServerProtocol.java
index 1a6172a..8af79a8 100644
--- a/subprojects/ui/src/main/java/org/gradle/foundation/ipc/gradle/ExecuteGradleCommandServerProtocol.java
+++ b/subprojects/ui/src/main/java/org/gradle/foundation/ipc/gradle/ExecuteGradleCommandServerProtocol.java
@@ -24,8 +24,6 @@ import java.io.File;
/**
* This manages the communication between the UI and an externally-launched copy of Gradle when using socket-based inter-process communication. This is the server side for executing a gradle command.
* This listens for messages from the gradle client.
- *
- * @author mhunsicker
*/
public class ExecuteGradleCommandServerProtocol extends AbstractGradleServerProtocol {
private static final String INIT_SCRIPT_NAME = "execute-command-init-script";
diff --git a/subprojects/ui/src/main/java/org/gradle/foundation/ipc/gradle/IPCUtilities.java b/subprojects/ui/src/main/java/org/gradle/foundation/ipc/gradle/IPCUtilities.java
index 3bfd9c6..5218aa7 100644
--- a/subprojects/ui/src/main/java/org/gradle/foundation/ipc/gradle/IPCUtilities.java
+++ b/subprojects/ui/src/main/java/org/gradle/foundation/ipc/gradle/IPCUtilities.java
@@ -21,8 +21,6 @@ import org.gradle.api.logging.Logging;
/**
* Just some convenience functions to startup a GradleClient. See GradleClient for more information.
- *
- * @author mhunsicker
*/
public class IPCUtilities {
private static final Logger LOGGER = Logging.getLogger(IPCUtilities.class);
diff --git a/subprojects/ui/src/main/java/org/gradle/foundation/ipc/gradle/KillGradleClientProtocol.java b/subprojects/ui/src/main/java/org/gradle/foundation/ipc/gradle/KillGradleClientProtocol.java
index ace7156..de691d8 100644
--- a/subprojects/ui/src/main/java/org/gradle/foundation/ipc/gradle/KillGradleClientProtocol.java
+++ b/subprojects/ui/src/main/java/org/gradle/foundation/ipc/gradle/KillGradleClientProtocol.java
@@ -22,8 +22,6 @@ import java.net.Socket;
/**
* This protocol is used by the process that launches gradle (the launching server - but in this case its the client) so that it can tell gradle to kill itself. This is used to cancel gradle
* execution. There is no other clean way to do it but kill it. All this does is send a 'kill' message.
- *
- * @author mhunsicker
*/
public class KillGradleClientProtocol implements ClientProcess.Protocol {
private ClientProcess client;
diff --git a/subprojects/ui/src/main/java/org/gradle/foundation/ipc/gradle/KillGradleServerProtocol.java b/subprojects/ui/src/main/java/org/gradle/foundation/ipc/gradle/KillGradleServerProtocol.java
index 910dd35..13323c0 100644
--- a/subprojects/ui/src/main/java/org/gradle/foundation/ipc/gradle/KillGradleServerProtocol.java
+++ b/subprojects/ui/src/main/java/org/gradle/foundation/ipc/gradle/KillGradleServerProtocol.java
@@ -20,8 +20,6 @@ import org.gradle.foundation.ipc.basic.Server;
/**
* This protocol is used by a client that launches its own server. See KillGradleClientProtocol.
- *
- * @author mhunsicker
*/
public class KillGradleServerProtocol implements Server.Protocol<Server> {
private Server server;
diff --git a/subprojects/ui/src/main/java/org/gradle/foundation/ipc/gradle/ProtocolConstants.java b/subprojects/ui/src/main/java/org/gradle/foundation/ipc/gradle/ProtocolConstants.java
index 45afd46..05d52ea 100644
--- a/subprojects/ui/src/main/java/org/gradle/foundation/ipc/gradle/ProtocolConstants.java
+++ b/subprojects/ui/src/main/java/org/gradle/foundation/ipc/gradle/ProtocolConstants.java
@@ -17,8 +17,6 @@ package org.gradle.foundation.ipc.gradle;
/**
* Constants related to interprocess communication between gradle and the gradle UI.
- *
- * @author mhunsicker
*/
public class ProtocolConstants {
//these are the message types we'll receive from the client.
diff --git a/subprojects/ui/src/main/java/org/gradle/foundation/ipc/gradle/TaskListClientProtocol.java b/subprojects/ui/src/main/java/org/gradle/foundation/ipc/gradle/TaskListClientProtocol.java
index bfa894c..cff7b00 100644
--- a/subprojects/ui/src/main/java/org/gradle/foundation/ipc/gradle/TaskListClientProtocol.java
+++ b/subprojects/ui/src/main/java/org/gradle/foundation/ipc/gradle/TaskListClientProtocol.java
@@ -36,8 +36,6 @@ import java.util.List;
/**
* This manages the communication between the UI and an externally-launched copy of Gradle when using socket-based inter-process communication. This is the client (gradle) side used to build a task
* list (tree actually). We add gradle listeners and send their notifications as messages back to the server.
- *
- * @author mhunsicker
*/
public class TaskListClientProtocol implements ClientProcess.Protocol {
private final Logger logger = Logging.getLogger(TaskListClientProtocol.class);
diff --git a/subprojects/ui/src/main/java/org/gradle/foundation/ipc/gradle/TaskListServerProtocol.java b/subprojects/ui/src/main/java/org/gradle/foundation/ipc/gradle/TaskListServerProtocol.java
index 4963768..531afa9 100644
--- a/subprojects/ui/src/main/java/org/gradle/foundation/ipc/gradle/TaskListServerProtocol.java
+++ b/subprojects/ui/src/main/java/org/gradle/foundation/ipc/gradle/TaskListServerProtocol.java
@@ -26,8 +26,6 @@ import java.util.List;
/**
* This manages the communication between the UI and an externally-launched copy of Gradle when using socket-based inter-process communication. This is the server side for building a task list. This
* listens for messages from the gradle client.
- *
- * @author mhunsicker
*/
public class TaskListServerProtocol extends AbstractGradleServerProtocol {
private static final String INIT_SCRIPT_NAME = "refresh-tasks-init-script";
diff --git a/subprojects/ui/src/main/java/org/gradle/foundation/output/FileLink.java b/subprojects/ui/src/main/java/org/gradle/foundation/output/FileLink.java
index 30cd87e..5320964 100644
--- a/subprojects/ui/src/main/java/org/gradle/foundation/output/FileLink.java
+++ b/subprojects/ui/src/main/java/org/gradle/foundation/output/FileLink.java
@@ -22,8 +22,6 @@ import java.io.File;
/**
* This represents a link to a file inside gradle's output. This is so the gradle UI/plugins can open the file. This is useful for a user when gradle displays a build error, test failure or compile
* error.
- *
- * @author mhunsicker
*/
public class FileLink {
private File file;
diff --git a/subprojects/ui/src/main/java/org/gradle/foundation/output/FileLinkDefinitionLord.java b/subprojects/ui/src/main/java/org/gradle/foundation/output/FileLinkDefinitionLord.java
index 25f35b4..e5bd4a4 100644
--- a/subprojects/ui/src/main/java/org/gradle/foundation/output/FileLinkDefinitionLord.java
+++ b/subprojects/ui/src/main/java/org/gradle/foundation/output/FileLinkDefinitionLord.java
@@ -23,8 +23,6 @@ import java.util.regex.Pattern;
/**
* This class holds on FileLinkDefinitions used for searching output.
- *
- * @author mhunsicker
*/
public class FileLinkDefinitionLord {
private List<String> extensions = new ArrayList<String>();
diff --git a/subprojects/ui/src/main/java/org/gradle/foundation/output/LiveOutputParser.java b/subprojects/ui/src/main/java/org/gradle/foundation/output/LiveOutputParser.java
index 0fd04a0..3b02808 100644
--- a/subprojects/ui/src/main/java/org/gradle/foundation/output/LiveOutputParser.java
+++ b/subprojects/ui/src/main/java/org/gradle/foundation/output/LiveOutputParser.java
@@ -23,8 +23,6 @@ import java.util.List;
/**
* This is a special type of OutputParser. It handles tracking live output. The unique thing about live output is that we're not guaranteed to get whole lines. Also, we don't want to parse parts that
* have already been parsed. This holds onto the output until a newline is reached, then parses it. It also tracks the overall index into the output (even though its only parsing a part of it).
- *
- * @author mhunsicker
*/
public class LiveOutputParser {
private OutputParser parser;
diff --git a/subprojects/ui/src/main/java/org/gradle/foundation/output/OutputParser.java b/subprojects/ui/src/main/java/org/gradle/foundation/output/OutputParser.java
index c92e7bb..87931be 100644
--- a/subprojects/ui/src/main/java/org/gradle/foundation/output/OutputParser.java
+++ b/subprojects/ui/src/main/java/org/gradle/foundation/output/OutputParser.java
@@ -27,8 +27,6 @@ import java.util.regex.Pattern;
* easily. To accomplish this, this works with FileLinkDefinitions. They require a basic RegEx pattern to match some initial part of the a file link, however, they can be implemented to do more
* advanced parsing of the text. The definitions are built-up and held by FileLinkDefinitionLord. This just handles the tedium of matching the all-inclusive pattern with text, managing indices, and
* calling the matching FileLinkDefinition to refine the match.
- *
- * @author mhunsicker
*/
public class OutputParser {
private FileLinkDefinitionLord fileLinkDefinitionLord;
diff --git a/subprojects/ui/src/main/java/org/gradle/foundation/output/definitions/ExtensionFileLinkDefinition.java b/subprojects/ui/src/main/java/org/gradle/foundation/output/definitions/ExtensionFileLinkDefinition.java
index 5553a14..fb3b9eb 100644
--- a/subprojects/ui/src/main/java/org/gradle/foundation/output/definitions/ExtensionFileLinkDefinition.java
+++ b/subprojects/ui/src/main/java/org/gradle/foundation/output/definitions/ExtensionFileLinkDefinition.java
@@ -25,8 +25,6 @@ import java.util.List;
* a delimiter after the path to specify a line number (the delimiter cannot be before the path).
*
* Here's a sample line output from a compile error: /home/someguy/path/etc/etc.java:186: cannot find symbol
- *
- * @author mhunsicker
*/
public class ExtensionFileLinkDefinition implements FileLinkDefinition {
private String expression;
diff --git a/subprojects/ui/src/main/java/org/gradle/foundation/output/definitions/FileLinkDefinition.java b/subprojects/ui/src/main/java/org/gradle/foundation/output/definitions/FileLinkDefinition.java
index 4629727..41e001e 100644
--- a/subprojects/ui/src/main/java/org/gradle/foundation/output/definitions/FileLinkDefinition.java
+++ b/subprojects/ui/src/main/java/org/gradle/foundation/output/definitions/FileLinkDefinition.java
@@ -21,8 +21,6 @@ import java.util.List;
/**
* .
- *
- * @author mhunsicker
*/
public interface FileLinkDefinition {
/**
diff --git a/subprojects/ui/src/main/java/org/gradle/foundation/output/definitions/OptionalLineNumberFileLinkDefinition.java b/subprojects/ui/src/main/java/org/gradle/foundation/output/definitions/OptionalLineNumberFileLinkDefinition.java
index 55a31c4..479a05e 100644
--- a/subprojects/ui/src/main/java/org/gradle/foundation/output/definitions/OptionalLineNumberFileLinkDefinition.java
+++ b/subprojects/ui/src/main/java/org/gradle/foundation/output/definitions/OptionalLineNumberFileLinkDefinition.java
@@ -17,8 +17,6 @@ package org.gradle.foundation.output.definitions;
/**
* This is just like BasicFileLinkDefinition except that the line number delimiter is optional and it allows spaces between the file and the delimiter.
- *
- * @author mhunsicker
*/
public class OptionalLineNumberFileLinkDefinition extends PrefixedFileLinkDefinition {
public OptionalLineNumberFileLinkDefinition(String name, String prefix, String extension, String lineNumberDelimiter) {
diff --git a/subprojects/ui/src/main/java/org/gradle/foundation/output/definitions/PrefixedFileLinkDefinition.java b/subprojects/ui/src/main/java/org/gradle/foundation/output/definitions/PrefixedFileLinkDefinition.java
index ed5b346..655b57d 100644
--- a/subprojects/ui/src/main/java/org/gradle/foundation/output/definitions/PrefixedFileLinkDefinition.java
+++ b/subprojects/ui/src/main/java/org/gradle/foundation/output/definitions/PrefixedFileLinkDefinition.java
@@ -27,8 +27,6 @@ import java.util.List;
* Here's a sample line output from an ant compile error: [ant:javac] /home/someguy/path/etc/etc.java:186: cannot find symbol
*
* Here's a sample line output from gradle when it encounters an exception: Build file '/home/someguy/path/etc/etc/build.gradle'
- *
- * @author mhunsicker
*/
public class PrefixedFileLinkDefinition implements FileLinkDefinition {
private String expression;
diff --git a/subprojects/ui/src/main/java/org/gradle/foundation/output/definitions/TestReportFileLinkDefinition.java b/subprojects/ui/src/main/java/org/gradle/foundation/output/definitions/TestReportFileLinkDefinition.java
index b2b68f8..b9dfa1c 100644
--- a/subprojects/ui/src/main/java/org/gradle/foundation/output/definitions/TestReportFileLinkDefinition.java
+++ b/subprojects/ui/src/main/java/org/gradle/foundation/output/definitions/TestReportFileLinkDefinition.java
@@ -23,8 +23,6 @@ import java.util.List;
/**
* This is a special FileLinkDefinition for handling test reports. At the time of this writing, the test reports error message merely told you the directory to visit, not the actual file. So this
* appends 'index.html' to the directory to generate the file.
- *
- * @author mhunsicker
*/
public class TestReportFileLinkDefinition implements FileLinkDefinition {
private String expression;
diff --git a/subprojects/ui/src/main/java/org/gradle/foundation/queue/ExecutionQueue.java b/subprojects/ui/src/main/java/org/gradle/foundation/queue/ExecutionQueue.java
index 405ab68..e9c0b18 100644
--- a/subprojects/ui/src/main/java/org/gradle/foundation/queue/ExecutionQueue.java
+++ b/subprojects/ui/src/main/java/org/gradle/foundation/queue/ExecutionQueue.java
@@ -25,8 +25,6 @@ import java.util.concurrent.LinkedBlockingQueue;
/**
* This class abstracts running multiple tasks consecutively. This exists because I'm not certain that Gradle is thread-safe and on Windows, running tasks that require lots of disk I/O get
* considerably slower when run concurrently. This will allow requests to be made and they will run as soon as any previous requests have finished.
- *
- * @author mhunsicker
*/
public class ExecutionQueue<R extends ExecutionQueue.Request> {
private final Logger logger = Logging.getLogger(ExecutionQueue.class);
diff --git a/subprojects/ui/src/main/java/org/gradle/foundation/visitors/AllProjectsAndTasksVisitor.java b/subprojects/ui/src/main/java/org/gradle/foundation/visitors/AllProjectsAndTasksVisitor.java
index 771582e..5574114 100644
--- a/subprojects/ui/src/main/java/org/gradle/foundation/visitors/AllProjectsAndTasksVisitor.java
+++ b/subprojects/ui/src/main/java/org/gradle/foundation/visitors/AllProjectsAndTasksVisitor.java
@@ -26,13 +26,10 @@ import java.util.List;
/**
* This visits all projects and their subprojects and tasks in a hierarchal manner. Useful if you need to do some processing with each one.
- *
- * @author mhunsicker
*/
public class AllProjectsAndTasksVisitor {
/*
Visitor allowing you to do whatever you like with a project or task.
- @author mhunsicker
*/
public interface Visitor<P, T> {
@@ -44,7 +41,6 @@ public class AllProjectsAndTasksVisitor {
was passed into the visitPojectsAndTasks function.
@return an object that will be handed back to you for each of this
project's tasks.
- @author mhunsicker
*/
public P visitProject(ProjectView project, P parentProjectObject);
@@ -55,7 +51,6 @@ public class AllProjectsAndTasksVisitor {
@param task the task
@param tasksProject the project for this task
@param userProjectObject whatever you returned from the parent project's visitProject
- @author mhunsicker
*/
public T visitTask(TaskView task, ProjectView tasksProject, P userProjectObject);
@@ -68,8 +63,6 @@ public class AllProjectsAndTasksVisitor {
This is the same as the other version of visitProjectsAndTasks except this
one visits everything.
-
- @author mhunsicker
*/
public static <P, T> void visitProjectAndTasks(List<ProjectView> projects, Visitor<P, T> visitor, P rootProjectObject) {
@@ -85,7 +78,6 @@ public class AllProjectsAndTasksVisitor {
@param filter allows you to skip projects and tasks as specified by the filter.
@param rootProjectObject whatever you pass here will be passed to the
root-level projects as parentProjectObject.
- @author mhunsicker
*/
public static <P, T> void visitProjectAndTasks(List<ProjectView> projects, Visitor<P, T> visitor, ProjectAndTaskFilter filter, P rootProjectObject) {
@@ -116,8 +108,6 @@ public class AllProjectsAndTasksVisitor {
/*
Add the list of tasks to the parent tree node.
-
- @author mhunsicker
*/
private static <P, T> List<T> visitTasks(Visitor<P, T> visitor, ProjectAndTaskFilter filter, ProjectView project, P userProjectObject) {
diff --git a/subprojects/ui/src/main/java/org/gradle/foundation/visitors/TaskTreePopulationVisitor.java b/subprojects/ui/src/main/java/org/gradle/foundation/visitors/TaskTreePopulationVisitor.java
index 59869dc..dd54fa0 100644
--- a/subprojects/ui/src/main/java/org/gradle/foundation/visitors/TaskTreePopulationVisitor.java
+++ b/subprojects/ui/src/main/java/org/gradle/foundation/visitors/TaskTreePopulationVisitor.java
@@ -26,8 +26,6 @@ import java.util.*;
/**
* This visits each project and task in a hierarchical manner. This visitor is specifically meant to walk the projects first and tasks second for the purpose of populating a tree where the
* projects/subprojects are first and the tasks are second.
- *
- * @author mhunsicker
*/
public class TaskTreePopulationVisitor {
public interface Visitor<P, T> {
@@ -40,7 +38,6 @@ public class TaskTreePopulationVisitor {
was passed into the visitPojectsAndTasks function.
@return an object that will be handed back to you for each of this
project's tasks.
- @author mhunsicker
*/
public P visitProject(ProjectView project, int indexOfProject, P parentProjectObject);
@@ -52,7 +49,6 @@ public class TaskTreePopulationVisitor {
@param indexOfTask
@param tasksProject the project for this task
@param userProjectObject whatever you returned from the parent project's visitProject
- @author mhunsicker
*/
public T visitTask(TaskView task, int indexOfTask, ProjectView tasksProject, P userProjectObject);
@@ -67,7 +63,6 @@ public class TaskTreePopulationVisitor {
the project and task objects below
@param projectObjects a list of whatever you returned from visitProject
@param taskObjects a list of whatever you returned from visitTask
- @author mhunsicker
*/
public void completedVisitingProject(P parentProjectObject, List<P> projectObjects, List<T> taskObjects);
@@ -80,8 +75,6 @@ public class TaskTreePopulationVisitor {
This is the same as the other version of visitProjectsAndTasks except this
one visits everything.
-
- @author mhunsicker
*/
public static <P, T> void visitProjectAndTasks(List<ProjectView> projects, Visitor<P, T> visitor,
@@ -98,7 +91,6 @@ public class TaskTreePopulationVisitor {
@param filter allows you to skip projects and tasks as specified by the filter.
@param rootProjectObject whatever you pass here will be passed to the
root-level projects as parentProjectObject.
- @author mhunsicker
*/
public static <P, T> void visitProjectAndTasks(List<ProjectView> projects, Visitor<P, T> visitor,
@@ -141,8 +133,6 @@ public class TaskTreePopulationVisitor {
/*
Add the list of tasks to the parent tree node.
-
- @author mhunsicker
*/
private static <P, T> List<T> visitTasks(Visitor<P, T> visitor, ProjectAndTaskFilter filter, ProjectView project,
diff --git a/subprojects/ui/src/main/java/org/gradle/foundation/visitors/UniqueNameProjectAndTaskVisitor.java b/subprojects/ui/src/main/java/org/gradle/foundation/visitors/UniqueNameProjectAndTaskVisitor.java
index ad09ed0..9a80dec 100644
--- a/subprojects/ui/src/main/java/org/gradle/foundation/visitors/UniqueNameProjectAndTaskVisitor.java
+++ b/subprojects/ui/src/main/java/org/gradle/foundation/visitors/UniqueNameProjectAndTaskVisitor.java
@@ -24,8 +24,6 @@ import java.util.List;
/**
* This visitor builds up a list of unqiuely named projects and tasks. The projects will be their full path, so they're all unique.
- *
- * @author mhunsicker
*/
public class UniqueNameProjectAndTaskVisitor implements AllProjectsAndTasksVisitor.Visitor<Object, Object> {
private List<String> taskNames = new ArrayList<String>();
@@ -59,7 +57,6 @@ public class UniqueNameProjectAndTaskVisitor implements AllProjectsAndTasksVisit
it'll be whatever was passed into the
visitPojectsAndTasks function.
@return always null
- @author mhunsicker
*/
public Object visitProject(ProjectView project, Object parentProjectObject) {
@@ -76,7 +73,6 @@ public class UniqueNameProjectAndTaskVisitor implements AllProjectsAndTasksVisit
@param task the task
@param tasksProject the project for this task
@param userProjectObject always null.
- @author mhunsicker
*/
public Object visitTask(TaskView task, ProjectView tasksProject, Object userProjectObject) {
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/CommandLineArgumentAlteringListener.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/CommandLineArgumentAlteringListener.java
index 542e2b8..18459ba 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/CommandLineArgumentAlteringListener.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/CommandLineArgumentAlteringListener.java
@@ -18,8 +18,6 @@ package org.gradle.gradleplugin.foundation;
/**
* This allows you to add a listener that can add additional command line arguments whenever gradle is executed. This is useful if you've customized your gradle build and need to specify, for example,
* an init script.
- *
- * @author mhunsicker
*/
public interface CommandLineArgumentAlteringListener {
/**
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/DOM4JSerializer.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/DOM4JSerializer.java
index 1a72eb6..362af5d 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/DOM4JSerializer.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/DOM4JSerializer.java
@@ -32,8 +32,6 @@ import java.io.*;
/**
* This saves and reads thing to and from DOM structures.
- *
- * @author mhunsicker
*/
public class DOM4JSerializer {
private static final Logger LOGGER = Logging.getLogger(DOM4JSerializer.class);
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/Dom4JUtility.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/Dom4JUtility.java
index 25dbc32..e298f31 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/Dom4JUtility.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/Dom4JUtility.java
@@ -25,7 +25,6 @@ import java.util.List;
/*
Just some utility functions that really should be in Dom4J already.
- @author mhunsicker
*/
public class Dom4JUtility {
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/ExtensionFileFilter.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/ExtensionFileFilter.java
index e29977b..6658cb4 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/ExtensionFileFilter.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/ExtensionFileFilter.java
@@ -21,8 +21,6 @@ import java.io.File;
/**
* Man! Why doesn't this get put into java's standard library?! Well, they did, but it doesn't hide hidden files. By definition of them being hidden, you probably don't want to see them. <p/> While
* FileFilter is technically a Swing class, it shouldn't be. The foundation needs to drive what is allowed in the UI.
- *
- * @author mhunsicker
*/
public class ExtensionFileFilter extends FileFilter {
private String extension;
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/GradlePluginLord.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/GradlePluginLord.java
index f4e3470..564b362 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/GradlePluginLord.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/GradlePluginLord.java
@@ -45,8 +45,6 @@ import java.util.concurrent.LinkedBlockingQueue;
* This class has nothing to do with plugins inside of gradle, but are related to making a plugin that uses gradle, such as for an IDE. It is also used by the standalone IDE (that way the standalone
* UI and plugin UIs are kept in synch). <p/> This is the class that stores most of the information that the Gradle plugin works directly with. It is meant to simplify creating a plugin that uses
* gradle. It maintains a queue of commands to execute and executes them in a separate process due to some complexities with gradle and its dependencies classpaths and potential memory issues.
- *
- * @author mhunsicker
*/
public class GradlePluginLord {
private final Logger logger = Logging.getLogger(GradlePluginLord.class);
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/favorites/FavoriteTask.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/favorites/FavoriteTask.java
index 777438e..58fde1c 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/favorites/FavoriteTask.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/favorites/FavoriteTask.java
@@ -18,8 +18,6 @@ package org.gradle.gradleplugin.foundation.favorites;
/**
* This holds onto a favorite task. Note: a user may define a favorite task, but it may or may be not present (or may be hidden because of a temporary error in gradle files). So we hold onto the full
* name of the task so we can get to the task should it become available.
- *
- * @author mhunsicker
*/
public class FavoriteTask {
private String fullCommandLine;
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/favorites/FavoritesEditor.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/favorites/FavoritesEditor.java
index d4b2f21..72f2b39 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/favorites/FavoritesEditor.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/favorites/FavoritesEditor.java
@@ -30,8 +30,6 @@ import java.util.List;
/**
* This holds onto and edits favorite tasks. 'Favorite tasks' provides a quick way to run frequently used tasks.
- *
- * @author mhunsicker
*/
public class FavoritesEditor implements SettingsSerializable {
private ReorderableList<FavoriteTask> favoriteTasks = new ReorderableList<FavoriteTask>();
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/favorites/FavoritesSerializable.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/favorites/FavoritesSerializable.java
index 40053ea..e4a2eba 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/favorites/FavoritesSerializable.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/favorites/FavoritesSerializable.java
@@ -25,10 +25,7 @@ import java.util.List;
/**
* Inner class that handles serializing favorites. You can either pass it a favorites list and serialize them out or use the default constructor and serialize it. This allows you to serialize a
* favorites list with or without an editor.
- *
- * @author mhunsicker
- */
-class FavoritesSerializable implements SettingsSerializable {
+ */class FavoritesSerializable implements SettingsSerializable {
private List<FavoriteTask> favorites;
private static final String FAVORITE_ELEMENT_TAG = "favorite";
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/filters/AllowAllProjectAndTaskFilter.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/filters/AllowAllProjectAndTaskFilter.java
index 4da8f88..2a50dce 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/filters/AllowAllProjectAndTaskFilter.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/filters/AllowAllProjectAndTaskFilter.java
@@ -20,8 +20,6 @@ import org.gradle.foundation.TaskView;
/**
* This filter actually doesn't filter. It allows everything through.
- *
- * @author mhunsicker
*/
public class AllowAllProjectAndTaskFilter implements ProjectAndTaskFilter {
/**
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/filters/BasicFilterEditor.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/filters/BasicFilterEditor.java
index 75b53fa..c15b4c5 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/filters/BasicFilterEditor.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/filters/BasicFilterEditor.java
@@ -32,8 +32,6 @@ import java.util.List;
During the editing process, you often need to fire off notifications that
normally aren't required. This is where those notifications would come from.
This also has some extra validation that isn't present in the filter itself.
-
- @author mhunsicker
*/
public class BasicFilterEditor implements ProjectAndTaskFilter {
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/filters/BasicProjectAndTaskFilter.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/filters/BasicProjectAndTaskFilter.java
index a3ea651..1ba9d70 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/filters/BasicProjectAndTaskFilter.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/filters/BasicProjectAndTaskFilter.java
@@ -26,8 +26,6 @@ import java.util.List;
/**
* This is a basic filter where you can specify specific projects and tasks that will be filtered out.
- *
- * @author mhunsicker
*/
public class BasicProjectAndTaskFilter implements ProjectAndTaskFilter, SettingsSerializable {
private static final String BASIC_PROJECT_AND_TASK_FILTER = "basic-project-and-task-filter";
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/filters/ProjectAndTaskFilter.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/filters/ProjectAndTaskFilter.java
index 44e806b..7eff1dc 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/filters/ProjectAndTaskFilter.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/filters/ProjectAndTaskFilter.java
@@ -20,8 +20,6 @@ import org.gradle.foundation.TaskView;
/**
* Interface for a filter that weeds out certain projects and tasks. Useful when trying to walk the projects and tasks.
- *
- * @author mhunsicker
*/
public interface ProjectAndTaskFilter {
/**
@@ -37,7 +35,6 @@ public interface ProjectAndTaskFilter {
*
* @param task the task in question
* @return true to allow it, false not to.
- * @author mhunsicker
*/
public boolean doesAllowTask(TaskView task);
}
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/request/AbstractRequest.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/request/AbstractRequest.java
index 52af986..f62187a 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/request/AbstractRequest.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/request/AbstractRequest.java
@@ -22,8 +22,6 @@ import org.gradle.foundation.queue.ExecutionQueue;
/**
* This represents a basic reques to gradle that is executed in a separate process using the ProcessLauncherServer. This stores the command line to execute and has the ability to cancel itself by
* either removing it from the queue if it hasn't started yet, or killing the external process.
- *
- * @author mhunsicker
*/
public abstract class AbstractRequest implements Request {
private long requestID;
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/request/ExecutionRequest.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/request/ExecutionRequest.java
index 3c19970..de280ea 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/request/ExecutionRequest.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/request/ExecutionRequest.java
@@ -27,8 +27,6 @@ import java.io.File;
/**
* This represents a reques to gradle that is executed in a separate process using the ProcessLauncherServer. This version is for directly executing commands in gradle (the most common type of
* request).
- *
- * @author mhunsicker
*/
public class ExecutionRequest extends AbstractRequest {
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/request/RefreshTaskListRequest.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/request/RefreshTaskListRequest.java
index 08bb430..e717379 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/request/RefreshTaskListRequest.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/request/RefreshTaskListRequest.java
@@ -29,8 +29,6 @@ import java.util.List;
/**
* This represents a request to gradle that is executed in a separate process using the ProcessLauncherServer. This is a special request where the results are to build up a project/task tree.
- *
- * @author mhunsicker
*/
public class RefreshTaskListRequest extends AbstractRequest {
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/request/Request.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/request/Request.java
index ea7c4ba..59609af 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/request/Request.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/request/Request.java
@@ -26,8 +26,6 @@ import java.io.File;
/**
* This represents a reques to gradle that is executed in a separate process using the ProcessLauncherServer.
- *
- * @author mhunsicker
*/
public interface Request extends ExecutionQueue.Request {
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/runner/GradleRunner.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/runner/GradleRunner.java
index c448d1d..87cb237 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/runner/GradleRunner.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/runner/GradleRunner.java
@@ -24,8 +24,6 @@ import java.io.File;
/**
* This executes a command line in an external process.
- *
- * @author mhunsicker
*/
public class GradleRunner {
private File currentDirectory;
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/search/BasicTextSearchCriteria.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/search/BasicTextSearchCriteria.java
index 5fea746..8931d97 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/search/BasicTextSearchCriteria.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/search/BasicTextSearchCriteria.java
@@ -19,8 +19,6 @@ import java.util.regex.Pattern;
/**
* This is basic search criteria for searching text. This could be extended for more advanced searches.
- *
- * @author mhunsicker
*/
public class BasicTextSearchCriteria {
private String textToMatch = "";
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/search/TextBlockSearchEditor.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/search/TextBlockSearchEditor.java
index c081b18..845dd1f 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/search/TextBlockSearchEditor.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/search/TextBlockSearchEditor.java
@@ -24,8 +24,6 @@ import java.util.regex.Pattern;
/**
* This searches within a block of text. The bulk of the work is handled by RegEx. This builds a list of results.
- *
- * @author mhunsicker
*/
public class TextBlockSearchEditor {
private List<SearchResult> matchedResults = new ArrayList<SearchResult>();
@@ -83,7 +81,6 @@ public class TextBlockSearchEditor {
/**
* Information about a search's results.
*
- * @author mhunsicker
*/
public static class SearchResult {
private String matchedText;
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/settings/DOM4JSettingsNode.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/settings/DOM4JSettingsNode.java
index 188f8b7..b2be592 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/settings/DOM4JSettingsNode.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/settings/DOM4JSettingsNode.java
@@ -23,8 +23,6 @@ import java.util.List;
/**
* An implementation of SettingsNode that uses DOM4J nodes as its actual storage medium.
- *
- * @author mhunsicker
*/
public class DOM4JSettingsNode implements SettingsNode {
public static final String TAG_NAME = "setting";
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/settings/SettingsNode.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/settings/SettingsNode.java
index 4c19b96..3dabfd8 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/settings/SettingsNode.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/settings/SettingsNode.java
@@ -45,8 +45,6 @@ import java.util.List;
*
* This has several convenience functions for setting and getting values from child nodes. These are meant to be used in more of a java preferences replacement. You should create your own root node of
* your settings (by call addChildIfNotPresent from a node that is given to you) then you can use these functions and you only need to worry about uniqueness within your own node.
- *
- * @author mhunsicker
*/
public interface SettingsNode {
/**
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/settings/SettingsSerializable.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/settings/SettingsSerializable.java
index 9d42132..434071b 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/settings/SettingsSerializable.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/foundation/settings/SettingsSerializable.java
@@ -17,8 +17,6 @@ package org.gradle.gradleplugin.foundation.settings;
/**
* Something that can be serialized to an XML structure. This is meant to store any preferences or settings (lightweight and heavyweight).
- *
- * @author mhunsicker
*/
public interface SettingsSerializable {
/**
@@ -32,7 +30,6 @@ public interface SettingsSerializable {
* Call this to read in this object's settings. The reverse of serializeOut.
*
* @param settings where you read your settings.
- * @author mhunsicker
*/
public void serializeIn(SettingsNode settings);
}
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/AlternateUIInteraction.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/AlternateUIInteraction.java
index 4605c8c..467d7e2 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/AlternateUIInteraction.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/AlternateUIInteraction.java
@@ -20,8 +20,6 @@ import java.io.File;
/**
* This allows this plugin to interact with alternative UIs. Specifically, this has callbacks for IDE's so tell it to edit a project file or the like. This is the 'alternate' UI interaction because it
* interacts with other UIs (other than the built-in UI).
- *
- * @author mhunsicker
*/
public interface AlternateUIInteraction {
@@ -40,7 +38,6 @@ public interface AlternateUIInteraction {
@param file the file to open
@param line the line to go to. -1 if no line is specified.
- @author mhunsicker
*/
public void editFile(File file, int line);
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/common/BorderlessImageButton.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/common/BorderlessImageButton.java
index dd47c88..80a67c0 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/common/BorderlessImageButton.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/common/BorderlessImageButton.java
@@ -25,8 +25,6 @@ import java.awt.geom.Rectangle2D;
/**
* This is button that has no border and only an image. It highlights when the user moves over it. This style was modeled after Idea. This was used because the borders on toolbars can get a little
* busy and this looks a little cleaner.
- *
- * @author mhunsicker
*/
public class BorderlessImageButton extends JButton {
private Color oldBackgroundColor;
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/common/BorderlessImageToggleButton.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/common/BorderlessImageToggleButton.java
index 4756a02..f914b64 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/common/BorderlessImageToggleButton.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/common/BorderlessImageToggleButton.java
@@ -26,8 +26,6 @@ import java.awt.geom.Rectangle2D;
/**
* This is button that has no border and only an image. It highlights when the user moves over it. This version is a toggle button. This style was modeled after Idea. This was used because the borders
* on toolbars can get a little busy and this looks a little cleaner.
- *
- * @author mhunsicker
*/
public class BorderlessImageToggleButton extends JToggleButton {
public Border selectedBorder = BorderFactory.createLoweredBevelBorder();
@@ -78,7 +76,6 @@ public class BorderlessImageToggleButton extends JToggleButton {
* into account our need to change the border depending on the selection state of the button. This overrides negates that effect causing the button to behave as intended.
*
* @param border The new border to set for this button the we disregard and replace with our own.
- * @author wwhitaker
*/
public void setBorder(Border border) {
super.setBorder(BorderlessImageToggleButton.this.isSelected() ? selectedBorder : BorderlessUtility.DEFAULT_BORDER);
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/common/BorderlessUtility.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/common/BorderlessUtility.java
index 52c5968..343941b 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/common/BorderlessUtility.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/common/BorderlessUtility.java
@@ -21,8 +21,6 @@ import java.awt.*;
/**
* Utility functions/constants for borderless buttons
- *
- * @author mhunsicker
*/
public class BorderlessUtility {
public static final Color ON_MOUSE_OVER_BACKGROUND = new Color(181, 190, 214);
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/common/PreferencesAssistant.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/common/PreferencesAssistant.java
index 40b890d..0d6348d 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/common/PreferencesAssistant.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/common/PreferencesAssistant.java
@@ -25,8 +25,6 @@ import java.io.IOException;
/**
* This class just helps do some of the mundane tasks of saving and restoring the location of something.
- *
- * @author mhunsicker
*/
public class PreferencesAssistant {
private static final String WINDOW_X = "window_x";
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/common/SearchPanel.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/common/SearchPanel.java
index 02f92b3..4afc264 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/common/SearchPanel.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/common/SearchPanel.java
@@ -21,22 +21,10 @@ import org.gradle.gradleplugin.foundation.search.BasicTextSearchCriteria;
import org.gradle.gradleplugin.foundation.search.TextBlockSearchEditor;
import org.gradle.gradleplugin.userinterface.swing.generic.Utility;
-import javax.swing.AbstractAction;
-import javax.swing.Box;
-import javax.swing.BoxLayout;
-import javax.swing.JButton;
-import javax.swing.JCheckBox;
-import javax.swing.JComponent;
-import javax.swing.JPanel;
-import javax.swing.JTextField;
-import javax.swing.KeyStroke;
-import javax.swing.SwingUtilities;
-import javax.swing.UIManager;
+import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
-import java.awt.Color;
-import java.awt.Component;
-import java.awt.Dimension;
+import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
@@ -52,8 +40,6 @@ import java.util.concurrent.LinkedBlockingQueue;
*
* This performs a threaded search. Its not that the search will take a particularly long time (although it certainly could). Its that we're doing work and we can't do that in the Swing EDT. We'll be
* searching every time a user types a letter, As such, we queue up our requests and then perform a search on the latest request.
- *
- * @author mhunsicker
*/
public class SearchPanel {
private final Logger logger = Logging.getLogger(SearchPanel.class);
@@ -341,7 +327,6 @@ public class SearchPanel {
* <! Name Description>
*
* @param panel where to add your additional fields.
- * @author mhunsicker
*/
protected void addAdditionalFields(JPanel panel) {
@@ -350,7 +335,6 @@ public class SearchPanel {
/**
* Call this to hide this panel.
*
- * @author mhunsicker
*/
public void hide() {
if (this.searchInteraction != null) {
@@ -363,7 +347,6 @@ public class SearchPanel {
/**
* Call this to show this panel so that a search can begin. <! Name Description>
*
- * @author mhunsicker
*/
public void show() {
mainPanel.setVisible(true);
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/common/TextPaneSearchInteraction.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/common/TextPaneSearchInteraction.java
index 382cc09..9d60483 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/common/TextPaneSearchInteraction.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/common/TextPaneSearchInteraction.java
@@ -18,7 +18,7 @@ package org.gradle.gradleplugin.userinterface.swing.common;
import org.gradle.gradleplugin.foundation.search.TextBlockSearchEditor;
import org.gradle.gradleplugin.userinterface.swing.generic.Utility;
-import javax.swing.JTextPane;
+import javax.swing.*;
import javax.swing.text.AttributeSet;
import javax.swing.text.DefaultStyledDocument;
import java.util.ArrayList;
@@ -30,8 +30,6 @@ import java.util.List;
*
* Note: there's something kind of goofy here. This draws and 'undraws' highlights on text (using AttributeSets). If you use this and you draw your own highlights in the JTextPane, you need to
* override removeResultHighlights() and reset your AttributeSets. Otherwise, this assumes there is a default style that all non-highlighted text uses.
- *
- * @author mhunsicker
*/
public class TextPaneSearchInteraction implements SearchPanel.SearchInteraction {
private JTextPane textComponentToSearch;
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/AbstractGradleUIInstance.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/AbstractGradleUIInstance.java
index 2d936c2..a30b3c7 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/AbstractGradleUIInstance.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/AbstractGradleUIInstance.java
@@ -26,8 +26,6 @@ import java.io.File;
/**
* A simple UI for gradle that is meant to be embedded into an IDE. This doesn't have it own output since most IDEs have their own mechanism for that.
- *
- * @author mhunsicker
*/
public abstract class AbstractGradleUIInstance implements BasicGradleUI {
protected MainGradlePanel gradlePanel;
@@ -169,7 +167,6 @@ public abstract class AbstractGradleUIInstance implements BasicGradleUI {
@param commandLineArguments the command line arguments to pass to gradle.
@param displayName the name displayed in the UI for this command
- @author mhunsicker
*/
public void executeCommand(String commandLineArguments, String displayName) {
gradlePluginLord.addExecutionRequestToQueue(commandLineArguments, displayName);
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/BasicGradleUI.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/BasicGradleUI.java
index 37307b0..4b92bfe 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/BasicGradleUI.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/BasicGradleUI.java
@@ -23,22 +23,18 @@ import java.awt.*;
/**
* .
- *
- * @author mhunsicker
*/
public interface BasicGradleUI {
public GradlePluginLord getGradlePluginLord();
/*
@return the panel for this pane. This can be inserted directly into your UI.
- @author mhunsicker
*/
public JComponent getComponent();
/*
Call this whenever you're about to show this panel. We'll do whatever
initialization is necessary.
- @author mhunsicker
*/
public void aboutToShow();
@@ -48,7 +44,6 @@ public interface BasicGradleUI {
This is called if gradle tasks are being executed and you want to know if
we can close. Ask the user.
@return true if the user confirms cancelling the current tasks. False if not.
- @author mhunsicker
*/
public boolean promptUserToConfirmClosingWhileBusy();
}
@@ -59,7 +54,6 @@ public interface BasicGradleUI {
@param closeInteraction allows us to interact with the user
@return true if we can close, false if not.
- @author mhunsicker
*/
public boolean canClose(CloseInteraction closeInteraction);
@@ -67,20 +61,17 @@ public interface BasicGradleUI {
Call this before you close the pane. This gives it an opportunity to do
cleanup. You probably should call canClose before this. It gives the
app a chance to cancel if its busy.
- @author mhunsicker
*/
public void close();
/*
@return the total number of tabs.
- @author mhunsicker
*/
public int getGradleTabCount();
/*
@param index the index of the tab
@return the name of the tab at the specified index.
- @author mhunsicker
*/
public String getGradleTabName(int index);
@@ -109,7 +100,6 @@ public interface BasicGradleUI {
@param commandLineArguments the command line arguments to pass to gradle.
@param displayName the name displayed in the UI for this command
- @author mhunsicker
*/
public void executeCommand(String commandLineArguments, String displayName);
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/DualPaneUIInstance.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/DualPaneUIInstance.java
index 55d91a6..a1e9e8f 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/DualPaneUIInstance.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/DualPaneUIInstance.java
@@ -24,8 +24,6 @@ import java.awt.*;
/**
* A simple UI for gradle. This has two panels that can be inserted into a stand-alone application or an IDE. This is meant to hide most of the complexities of gradle. The two panes are a tabbed pane
* for executing tasks and an output pane.
- *
- * @author mhunsicker
*/
public class DualPaneUIInstance extends AbstractGradleUIInstance {
private OutputPanelLord outputPanelLord;
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/MainGradlePanel.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/MainGradlePanel.java
index 1493d00..cf0172b 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/MainGradlePanel.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/MainGradlePanel.java
@@ -31,8 +31,6 @@ import java.util.List;
/**
* This is a tabbed pane meant to handle several tabs of gradle-related things. To use this, instantiate it, place it some Swing container (dialog, frame), then call aboutToShow() before you show the
* parent container. You can also add your own tabs to this (just call addGradleTab before calling aboutToShow()). When you shut down, call aboutToClose() before doing so.
- *
- * @author mhunsicker
*/
public class MainGradlePanel extends JPanel {
private static final String CURRENT_TAB = "current-tab";
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/OutputPanel.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/OutputPanel.java
index 2af8fc7..9a52d45 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/OutputPanel.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/OutputPanel.java
@@ -28,36 +28,20 @@ import org.gradle.gradleplugin.userinterface.swing.common.SearchPanel;
import org.gradle.gradleplugin.userinterface.swing.common.TextPaneSearchInteraction;
import org.gradle.logging.ShowStacktrace;
-import javax.swing.BorderFactory;
-import javax.swing.Box;
-import javax.swing.BoxLayout;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-import javax.swing.JProgressBar;
-import javax.swing.JTextPane;
-import javax.swing.JToggleButton;
-import javax.swing.SwingUtilities;
-import javax.swing.UIManager;
-import javax.swing.JButton;
-import javax.swing.AbstractAction;
+import javax.swing.*;
import javax.swing.text.AttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
-import java.awt.BorderLayout;
-import java.awt.Color;
-import java.awt.Component;
-import java.awt.Font;
+import java.awt.*;
+import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
-import java.awt.event.ActionEvent;
+import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Calendar;
-import java.io.File;
/**
* This is a panel that displays the results of executing a gradle command. It shows gradle's output as well as progress.
- *
- * @author mhunsicker
*/
public class OutputPanel extends JPanel implements ExecuteGradleCommandServerProtocol.ExecutionInteraction {
@@ -582,7 +566,6 @@ public class OutputPanel extends JPanel implements ExecuteGradleCommandServerPro
* Report real-time output from gradle and its subsystems (such as ant).
*
* @param output a single line of text to show.
- * @author mhunsicker
*/
public void reportLiveOutput(String output) {
appendGradleOutput(output);
@@ -591,7 +574,6 @@ public class OutputPanel extends JPanel implements ExecuteGradleCommandServerPro
/**
* Determines if this panel is ready to be reused. Currently, if its not busy or pinned, it can be reused.
*
- * @author mhunsicker
*/
public boolean canBeReusedNow() {
return !isPending && !isBusy && !isPinned;
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/OutputPanelLord.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/OutputPanelLord.java
index c3288b1..c10f1ae 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/OutputPanelLord.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/OutputPanelLord.java
@@ -15,9 +15,9 @@
*/
package org.gradle.gradleplugin.userinterface.swing.generic;
+import org.gradle.foundation.common.ObserverLord;
import org.gradle.foundation.output.FileLinkDefinitionLord;
import org.gradle.foundation.queue.ExecutionQueue;
-import org.gradle.foundation.common.ObserverLord;
import org.gradle.gradleplugin.foundation.GradlePluginLord;
import org.gradle.gradleplugin.foundation.request.ExecutionRequest;
import org.gradle.gradleplugin.foundation.request.RefreshTaskListRequest;
@@ -25,9 +25,7 @@ import org.gradle.gradleplugin.foundation.request.Request;
import org.gradle.gradleplugin.userinterface.AlternateUIInteraction;
import javax.swing.*;
-import java.awt.BorderLayout;
-import java.awt.Point;
-import java.awt.Font;
+import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
@@ -37,8 +35,6 @@ import java.util.List;
/**
* This class manages displaying the results of a gradle execution in a panel inside a JTabbedPane. It can reuse existing tabs but creates new ones if you run multiple things concurrently.
- *
- * @author mhunsicker
*/
public class OutputPanelLord implements OutputUILord, GradlePluginLord.RequestObserver, OutputPanel.OutputPanelParent {
@@ -375,7 +371,6 @@ public class OutputPanelLord implements OutputUILord, GradlePluginLord.RequestOb
* Notification that a command is about to be executed. This is mostly useful for IDE's that may need to save their files.
*
* @param request the request to be executed
- * @author mhunsicker
*/
public void aboutToExecuteRequest(Request request) {
}
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/OutputTab.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/OutputTab.java
index b3c65a8..7264c57 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/OutputTab.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/OutputTab.java
@@ -20,24 +20,18 @@ import org.gradle.api.logging.Logging;
import org.gradle.gradleplugin.foundation.GradlePluginLord;
import org.gradle.gradleplugin.userinterface.AlternateUIInteraction;
-import javax.swing.Box;
-import javax.swing.BoxLayout;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-import javax.swing.ImageIcon;
import javax.imageio.ImageIO;
-import java.awt.Component;
-import java.awt.image.BufferedImage;
+import javax.swing.*;
+import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
-import java.io.InputStream;
+import java.awt.image.BufferedImage;
import java.io.IOException;
+import java.io.InputStream;
/**
* This just wraps up an OutputPanel so it has a tab header that can be dynamic. The current (rather awkward) JTabbedPane implementation is to separate the tab contents from its component. This only
* works with java 1.6 or later.
- *
- * @author mhunsicker
*/
public class OutputTab extends OutputPanel {
@@ -124,7 +118,6 @@ public class OutputTab extends OutputPanel {
/**
* Call this before you use this tab. It resets its output as well as enabling buttons appropriately.
*
- * @author mhunsicker
*/
@Override
public void reset() {
@@ -155,7 +148,6 @@ public class OutputTab extends OutputPanel {
* Overridden so we can indicate the pinned state.
*
* @param pinned whether or not we're pinned
- * @author mhunsicker
*/
@Override
public void setPinned(boolean pinned) {
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/SinglePaneUIInstance.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/SinglePaneUIInstance.java
index c2efdf2..5088b44 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/SinglePaneUIInstance.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/SinglePaneUIInstance.java
@@ -30,8 +30,6 @@ import java.beans.PropertyChangeListener;
* A simple UI for gradle. This is a single panel that can be inserted into a stand-alone application or an IDE. This is meant to hide most of the complexities of gradle. 'single pane' means that both
* the tabbed pane and the output pane are contained within a single pane that this maintains. Meaning, you add this to a UI and its a self-contained gradle UI. This is opposed to a multi-pane concept
* where the output would be separated from the tabbed pane.
- *
- * @author mhunsicker
*/
public class SinglePaneUIInstance extends AbstractGradleUIInstance {
private static final String SPLITTER_PREFERENCES_ID = "splitter-id";
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/SwingAddMultipleFavoritesInteraction.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/SwingAddMultipleFavoritesInteraction.java
index 64e0db6..ba09798 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/SwingAddMultipleFavoritesInteraction.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/SwingAddMultipleFavoritesInteraction.java
@@ -25,8 +25,6 @@ import java.util.List;
/**
* This handles prompting the user how to handle adding multiple tasks as favorites.
- *
- * @author mhunsicker
*/
public class SwingAddMultipleFavoritesInteraction implements FavoritesEditor.AddMultipleFavoritesInteraction {
private Window parent;
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/SwingEditFavoriteInteraction.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/SwingEditFavoriteInteraction.java
index e6c0600..f73dbc5 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/SwingEditFavoriteInteraction.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/SwingEditFavoriteInteraction.java
@@ -18,18 +18,14 @@ package org.gradle.gradleplugin.userinterface.swing.generic;
import org.gradle.gradleplugin.foundation.favorites.FavoritesEditor;
import javax.swing.*;
-import javax.swing.text.BadLocationException;
-import javax.swing.event.DocumentListener;
import javax.swing.event.DocumentEvent;
-import java.awt.BorderLayout;
-import java.awt.Component;
-import java.awt.Window;
+import javax.swing.event.DocumentListener;
+import javax.swing.text.BadLocationException;
+import java.awt.*;
import java.awt.event.*;
/**
* This edits the properties of a single favorite task.
- *
- * @author mhunsicker
*/
public class SwingEditFavoriteInteraction implements FavoritesEditor.EditFavoriteInteraction {
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/SwingExportInteraction.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/SwingExportInteraction.java
index 4b1d135..c84a789 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/SwingExportInteraction.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/SwingExportInteraction.java
@@ -17,17 +17,13 @@ package org.gradle.gradleplugin.userinterface.swing.generic;
import org.gradle.gradleplugin.foundation.DOM4JSerializer;
-import javax.swing.JFileChooser;
-import javax.swing.JOptionPane;
-import javax.swing.SwingUtilities;
+import javax.swing.*;
import javax.swing.filechooser.FileFilter;
-import java.awt.Window;
+import java.awt.*;
import java.io.File;
/**
* Swing implementation of ExportInteraction. This prompts the user for a file via the JFileChooser and handles reporting errors.
- *
- * @author mhunsicker
*/
public class SwingExportInteraction implements DOM4JSerializer.ExportInteraction {
private Window parent;
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/SwingImportInteraction.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/SwingImportInteraction.java
index 251d31f..77ff57f 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/SwingImportInteraction.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/SwingImportInteraction.java
@@ -24,8 +24,6 @@ import java.io.File;
/**
* Swing implementation of ImportInteraction. This prompts the user for a file via the JFileChooser and handles reporting errors.
- *
- * @author mhunsicker
*/
public class SwingImportInteraction implements DOM4JSerializer.ImportInteraction {
private Window parent;
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/TaskTreeComponent.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/TaskTreeComponent.java
index e2b765a..139bd64 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/TaskTreeComponent.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/TaskTreeComponent.java
@@ -33,8 +33,6 @@ import java.util.List;
/**
* This displays a tree of projects, subprojects, and tasks. You implement the Interaction to detemine how to handle right clicks and double clicking tasks. To use this, call populate and pass it a
* filter (allows you to change exactly what is displayed). There are several functions to obtaining the selected items, plus you can get the tree directly for any advanced functionality.
- *
- * @author mhunsicker
*/
public class TaskTreeComponent {
private GradlePluginLord gradlePluginLord;
@@ -116,7 +114,7 @@ public class TaskTreeComponent {
/**
* This renders our projects and tasks. This removes the icon and optionally shows the description in a different color. Since there's quite a bit of code for handling rendering tree cells, I'm
- * just going to mooch off of the DefaultTreeCellRenderer. I'll just modify it's behavior a little (I probably don't need that or the description since it's not going to draw a selection or
+ * just going to mooch off of the DefaultTreeCellRenderer. I'll just modify its behavior a little (I probably don't need that or the description since it's not going to draw a selection or
* highlight).
*/
private class Renderer implements TreeCellRenderer {
@@ -667,4 +665,4 @@ public class TaskTreeComponent {
node.executeTask(isCtrlKeyDown);
}
}
-}
\ No newline at end of file
+}
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/Utility.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/Utility.java
index d3a0ee3..0cece5c 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/Utility.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/Utility.java
@@ -21,22 +21,10 @@ import org.gradle.gradleplugin.userinterface.swing.common.BorderlessImageButton;
import org.gradle.gradleplugin.userinterface.swing.common.BorderlessImageToggleButton;
import javax.imageio.ImageIO;
-import javax.swing.Action;
-import javax.swing.Box;
-import javax.swing.BoxLayout;
-import javax.swing.ImageIcon;
-import javax.swing.JButton;
-import javax.swing.JDialog;
-import javax.swing.JFrame;
-import javax.swing.JPanel;
-import javax.swing.JTabbedPane;
-import javax.swing.JToggleButton;
-import javax.swing.JMenuItem;
+import javax.swing.*;
import javax.swing.text.BadLocationException;
import javax.swing.text.JTextComponent;
-import java.awt.Component;
-import java.awt.Rectangle;
-import java.awt.Window;
+import java.awt.*;
import java.awt.event.InputEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
@@ -45,8 +33,6 @@ import java.lang.reflect.Method;
/**
* Just some utility functions.
- *
- * @author mhunsicker
*/
public class Utility {
private static final Logger LOGGER = Logging.getLogger(Utility.class);
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/filter/AbstractFilterEditorPanel.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/filter/AbstractFilterEditorPanel.java
index ec65697..33d8b0d 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/filter/AbstractFilterEditorPanel.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/filter/AbstractFilterEditorPanel.java
@@ -27,8 +27,6 @@ import java.util.List;
/**
* This panel displays something that is filtered. Its really just a list with show/hide buttons. You populate it with whatever you like (in String form).
- *
- * @author mhunsicker
*/
public abstract class AbstractFilterEditorPanel {
private JPanel mainPanel;
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/filter/ProjectAndTaskFilterDialog.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/filter/ProjectAndTaskFilterDialog.java
index 7ace00b..90fa8f6 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/filter/ProjectAndTaskFilterDialog.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/filter/ProjectAndTaskFilterDialog.java
@@ -33,8 +33,6 @@ import java.util.List;
/**
* This dialog allows you to edit what tasks and projects are visible when a filter is enabled. Filters are used to weed out rarely-used things to make finding things easier.
- *
- * @author mhunsicker
*/
public class ProjectAndTaskFilterDialog {
private JDialog dialog;
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/tabs/CommandLineTab.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/tabs/CommandLineTab.java
index 4a7d72a..80607b6 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/tabs/CommandLineTab.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/tabs/CommandLineTab.java
@@ -27,8 +27,6 @@ import java.awt.event.KeyEvent;
/**
* A tab that allows you to just type a straight command line that is sent to Gradle.
- *
- * @author mhunsicker
*/
public class CommandLineTab implements GradleTab {
private GradlePluginLord gradlePluginLord;
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/tabs/FavoriteTasksTab.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/tabs/FavoriteTasksTab.java
index 8d32a2e..47f2f79 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/tabs/FavoriteTasksTab.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/tabs/FavoriteTasksTab.java
@@ -36,8 +36,6 @@ import java.util.List;
/**
* This displays a list of favorites and allows the user to add/remove items as well as change their order.
- *
- * @author mhunsicker
*/
public class FavoriteTasksTab implements GradleTab, GradlePluginLord.GeneralPluginObserver, FavoritesEditor.FavoriteTasksObserver {
private GradlePluginLord gradlePluginLord;
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/tabs/GradleTab.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/tabs/GradleTab.java
index fd642bf..80c001e 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/tabs/GradleTab.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/tabs/GradleTab.java
@@ -19,13 +19,10 @@ import java.awt.*;
/**
* Interface for a tab in the gradle UI.
- *
- * @author mhunsicker
*/
public interface GradleTab {
/**
* @return the name of this tab
- * @author mhunsicker
*/
public String getName();
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/tabs/SetupTab.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/tabs/SetupTab.java
index b3b888c..80d079c 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/tabs/SetupTab.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/tabs/SetupTab.java
@@ -35,8 +35,6 @@ import java.util.*;
/**
* This tab contains general settings for the plugin.
- *
- * @author mhunsicker
*/
public class SetupTab implements GradleTab, GradlePluginLord.SettingsObserver {
private final Logger logger = Logging.getLogger(SetupTab.class);
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/tabs/TaskTreeTab.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/tabs/TaskTreeTab.java
index 94c67c7..414fa3f 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/tabs/TaskTreeTab.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/generic/tabs/TaskTreeTab.java
@@ -48,8 +48,6 @@ import java.util.List;
/**
* This displays a tree of projects and tasks.
- *
- * @author mhunsicker
*/
public class TaskTreeTab implements GradleTab, GradlePluginLord.GeneralPluginObserver, GradlePluginLord.RequestObserver {
private final Logger logger = Logging.getLogger(TaskTreeTab.class);
@@ -290,7 +288,6 @@ public class TaskTreeTab implements GradleTab, GradlePluginLord.GeneralPluginObs
* Notification that a command is about to be executed. This is mostly useful for IDE's that may need to save their files.
*
* @param request the request that's about to be executed.
- * @author mhunsicker
*/
public void aboutToExecuteRequest(Request request) {
//we don't really care
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/standalone/Application.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/standalone/Application.java
index 7a3e958..751e819 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/standalone/Application.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/standalone/Application.java
@@ -36,8 +36,6 @@ import java.net.URI;
/**
* The main entry point for a stand-alone application for Gradle. The real work is not done here. This is just a UI containing components that are meant to be reuseable in other UIs (say an IDE
* plugin). Those other components do the real work. Most of the work is wrapped inside SinglePaneUIInstance.
- *
- * @author mhunsicker
*/
public class Application implements AlternateUIInteraction {
private static final int DEFAULT_WIDTH = 800;
diff --git a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/standalone/BlockingApplication.java b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/standalone/BlockingApplication.java
index 42d6433..1cbd2c5 100644
--- a/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/standalone/BlockingApplication.java
+++ b/subprojects/ui/src/main/java/org/gradle/gradleplugin/userinterface/swing/standalone/BlockingApplication.java
@@ -22,8 +22,6 @@ import java.lang.reflect.InvocationTargetException;
/**
* This is the same as Application, but this version blocks the calling thread until the Application shuts down.
- *
- * @author mhunsicker
*/
public class BlockingApplication {
diff --git a/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/RunnerWrapperFactory.java b/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/RunnerWrapperFactory.java
index 4b3f730..8ec718a 100644
--- a/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/RunnerWrapperFactory.java
+++ b/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/RunnerWrapperFactory.java
@@ -29,8 +29,6 @@ import java.io.File;
*
* This class should not be moved or renamed, nor should its functions be renamed or have arguments added to/removed from them. This is to ensure forward/backward compatibility with multiple versions
* of IDE plugins. Instead, consider changing the interaction that is passed to the functions as a means of having the caller provide different functionality.
- *
- * @author mhunsicker
*/
public class RunnerWrapperFactory {
@@ -54,7 +52,6 @@ public class RunnerWrapperFactory {
may be helpful diagnosing problems is this
fails
@return a gradle runner
- @author mhunsicker
*/
public static GradleRunnerVersion1 createGradleRunner(File gradleHomeDirectory, GradleRunnerInteractionVersion1 interaction, boolean showDebugInfo) throws Exception {
return new GradleRunnerWrapper(gradleHomeDirectory, interaction);
diff --git a/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/UIWrapperFactory.java b/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/UIWrapperFactory.java
index abdfaa2..138f497 100644
--- a/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/UIWrapperFactory.java
+++ b/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/UIWrapperFactory.java
@@ -30,8 +30,6 @@ import org.gradle.openapi.wrappers.ui.SinglePaneUIWrapper;
*
* This class should not be moved or renamed, nor should its functions be renamed or have arguments added to/removed from them. This is to ensure forward/backward compatibility with multiple versions
* of IDE plugins. Instead, consider changing the interaction that is passed to the functions as a means of having the caller provide different functionality.
- *
- * @author mhunsicker
*/
public class UIWrapperFactory {
diff --git a/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/foundation/GradleInterfaceWrapperVersion1.java b/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/foundation/GradleInterfaceWrapperVersion1.java
index 82a78fe..35d363a 100644
--- a/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/foundation/GradleInterfaceWrapperVersion1.java
+++ b/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/foundation/GradleInterfaceWrapperVersion1.java
@@ -30,8 +30,6 @@ import java.util.Map;
/**
* Implementation of GradleInterfaceVersion1 meant to help shield external users from internal changes.
- *
- * @author mhunsicker
*/
public class GradleInterfaceWrapperVersion1 implements GradleInterfaceVersion1 {
diff --git a/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/foundation/GradleInterfaceWrapperVersion2.java b/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/foundation/GradleInterfaceWrapperVersion2.java
index aaee959..c6b7e5a 100644
--- a/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/foundation/GradleInterfaceWrapperVersion2.java
+++ b/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/foundation/GradleInterfaceWrapperVersion2.java
@@ -29,8 +29,6 @@ import java.util.List;
/**
* Implementation of GradleInterfaceVersion2 meant to help shield external users from internal changes. This adds new functionality to GradleInterfaceWrapperVersion1.
- *
- * @author mhunsicker
*/
public class GradleInterfaceWrapperVersion2 extends GradleInterfaceWrapperVersion1 implements GradleInterfaceVersion2 {
diff --git a/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/foundation/ProjectWrapper.java b/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/foundation/ProjectWrapper.java
index 080e84a..1168f8d 100644
--- a/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/foundation/ProjectWrapper.java
+++ b/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/foundation/ProjectWrapper.java
@@ -27,8 +27,6 @@ import java.util.List;
/**
* Implementation of ProjectVersion1 meant to help shield external users from internal changes.
- *
- * @author mhunsicker
*/
public class ProjectWrapper implements ProjectVersion1 {
diff --git a/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/foundation/RequestObserverWrapper.java b/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/foundation/RequestObserverWrapper.java
index 0bb15e2..854bd9f 100644
--- a/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/foundation/RequestObserverWrapper.java
+++ b/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/foundation/RequestObserverWrapper.java
@@ -23,8 +23,6 @@ import org.gradle.openapi.external.foundation.RequestObserverVersion1;
/**
* * Implementation of RequestObserverVersion1 meant to help shield external users from internal changes.
- *
- * @author mhunsicker
*/
public class RequestObserverWrapper implements GradlePluginLord.RequestObserver {
diff --git a/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/foundation/RequestWrapper.java b/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/foundation/RequestWrapper.java
index 561802f..aa8f56e 100644
--- a/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/foundation/RequestWrapper.java
+++ b/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/foundation/RequestWrapper.java
@@ -22,8 +22,6 @@ import org.gradle.openapi.external.foundation.RequestVersion1;
/**
* Implementation of RequestVersion1 meant to help shield external users from internal changes.
- *
- * @author mhunsicker
*/
public class RequestWrapper implements RequestVersion1 {
private Request request;
diff --git a/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/foundation/TaskWrapper.java b/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/foundation/TaskWrapper.java
index c68ca1c..8f825c3 100644
--- a/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/foundation/TaskWrapper.java
+++ b/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/foundation/TaskWrapper.java
@@ -25,8 +25,6 @@ import java.util.List;
/**
* Implementation of TaskVersion1 meant to help shield external users from internal changes.
- *
- * @author mhunsicker
*/
public class TaskWrapper implements TaskVersion1 {
diff --git a/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/foundation/favorites/FavoriteTaskWrapper.java b/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/foundation/favorites/FavoriteTaskWrapper.java
index 4c53ec7..6fd2d2d 100644
--- a/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/foundation/favorites/FavoriteTaskWrapper.java
+++ b/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/foundation/favorites/FavoriteTaskWrapper.java
@@ -20,8 +20,6 @@ import org.gradle.openapi.external.foundation.favorites.FavoriteTaskVersion1;
/**
* Implementation of FavoriteTaskVersion1 meant to help shield external users from internal changes.
- *
- * @author mhunsicker
*/
public class FavoriteTaskWrapper implements FavoriteTaskVersion1 {
diff --git a/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/foundation/favorites/FavoritesEditorWrapper.java b/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/foundation/favorites/FavoritesEditorWrapper.java
index 8d3c486..a7214a3 100644
--- a/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/foundation/favorites/FavoritesEditorWrapper.java
+++ b/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/foundation/favorites/FavoritesEditorWrapper.java
@@ -29,8 +29,6 @@ import java.util.List;
/**
* Implementation of FavoritesEditorVersion1 meant to help shield external users from internal changes.
- *
- * @author mhunsicker
*/
public class FavoritesEditorWrapper implements FavoritesEditorVersion1 {
private FavoritesEditor favoritesEditor;
diff --git a/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/runner/GradleRunnerInteractionWrapper.java b/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/runner/GradleRunnerInteractionWrapper.java
index 0e27749..11df951 100644
--- a/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/runner/GradleRunnerInteractionWrapper.java
+++ b/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/runner/GradleRunnerInteractionWrapper.java
@@ -24,8 +24,6 @@ import java.io.File;
/**
* Wrapper to shield version changes in GradleRunnerInteractionVersion1 from an external user of gradle open API.
- *
- * @author mhunsicker
*/
public class GradleRunnerInteractionWrapper implements ExecuteGradleCommandServerProtocol.ExecutionInteraction {
private GradleRunnerInteractionVersion1 interactionVersion1;
diff --git a/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/runner/GradleRunnerWrapper.java b/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/runner/GradleRunnerWrapper.java
index 866df99..f3eb7bd 100644
--- a/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/runner/GradleRunnerWrapper.java
+++ b/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/runner/GradleRunnerWrapper.java
@@ -23,8 +23,6 @@ import java.io.File;
/**
* Wrapper to shield version changes in GradleRunner from an external user of gradle open API.
- *
- * @author mhunsicker
*/
public class GradleRunnerWrapper implements GradleRunnerVersion1 {
private GradleRunner gradleRunner;
diff --git a/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/ui/AbstractOpenAPIUIWrapper.java b/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/ui/AbstractOpenAPIUIWrapper.java
index ddc9c7c..2968cbd 100644
--- a/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/ui/AbstractOpenAPIUIWrapper.java
+++ b/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/ui/AbstractOpenAPIUIWrapper.java
@@ -33,8 +33,6 @@ import java.util.Map;
/**
* Implementation of BasicGradleUI meant to help shield external users from internal changes. This also provides the basics for the UI regardless of whether the output is in a separate pane or not.
- *
- * @author mhunsicker
*/
public abstract class AbstractOpenAPIUIWrapper<U extends BasicGradleUI> {
private U basicGradleUI;
@@ -59,7 +57,6 @@ public abstract class AbstractOpenAPIUIWrapper<U extends BasicGradleUI> {
for IDE's that may need to save their files.
@param request the request that's about to be executed
- @author mhunsicker
*/
public void aboutToExecuteRequest(Request request) {
alternateUIInteractionVersionWrapper.aboutToExecuteCommand(request.getFullCommandLine());
diff --git a/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/ui/AlternateUIInteractionVersionWrapper.java b/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/ui/AlternateUIInteractionVersionWrapper.java
index 68be510..05b9d49 100644
--- a/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/ui/AlternateUIInteractionVersionWrapper.java
+++ b/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/ui/AlternateUIInteractionVersionWrapper.java
@@ -23,8 +23,6 @@ import java.io.File;
/**
* Wrapper to shield version changes in AlternateUIInteraction from an external user of gradle open API.
- *
- * @author mhunsicker
*/
public class AlternateUIInteractionVersionWrapper implements AlternateUIInteraction {
private AlternateUIInteractionVersion1 alternateUIInteractionVersion1;
diff --git a/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/ui/CommandLineArgumentAlteringListenerWrapper.java b/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/ui/CommandLineArgumentAlteringListenerWrapper.java
index 30f3603..96a4d78 100644
--- a/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/ui/CommandLineArgumentAlteringListenerWrapper.java
+++ b/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/ui/CommandLineArgumentAlteringListenerWrapper.java
@@ -20,8 +20,6 @@ import org.gradle.openapi.external.ui.CommandLineArgumentAlteringListenerVersion
/**
* Wrapper to shield version changes in GradleTab from an external user of the gradle open API.
- *
- * @author mhunsicker
*/
public class CommandLineArgumentAlteringListenerWrapper implements CommandLineArgumentAlteringListener {
private CommandLineArgumentAlteringListenerVersion1 listenerVersion1;
diff --git a/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/ui/DualPaneUIWrapper.java b/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/ui/DualPaneUIWrapper.java
index 0afeae6..7005120 100644
--- a/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/ui/DualPaneUIWrapper.java
+++ b/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/ui/DualPaneUIWrapper.java
@@ -25,8 +25,6 @@ import java.awt.*;
/**
* This wraps a DualPaneUIVersion1 for the purpose of being instantiated for an external tool such an IDE plugin. It wraps several interfaces and uses delegation in an effort to make this backward and
* forward compatible. Most of the work is done in AbstractOpenAPIUIWrapper
- *
- * @author mhunsicker
*/
public class DualPaneUIWrapper extends AbstractOpenAPIUIWrapper<DualPaneUIInstance> implements DualPaneUIVersion1 {
public DualPaneUIWrapper(DualPaneUIInteractionVersion1 dualPaneUIArguments) {
diff --git a/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/ui/GradleTabVersionWrapper.java b/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/ui/GradleTabVersionWrapper.java
index b1b4353..ae30750 100644
--- a/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/ui/GradleTabVersionWrapper.java
+++ b/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/ui/GradleTabVersionWrapper.java
@@ -22,8 +22,6 @@ import java.awt.*;
/**
* Wrapper to shield version changes in GradleTab from an external user of the gradle open API.
- *
- * @author mhunsicker
*/
public class GradleTabVersionWrapper implements GradleTab {
private GradleTabVersion1 gradleTabVersion1;
diff --git a/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/ui/OutputObserverWrapper.java b/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/ui/OutputObserverWrapper.java
index 8ea8e19..4be8c08 100644
--- a/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/ui/OutputObserverWrapper.java
+++ b/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/ui/OutputObserverWrapper.java
@@ -23,8 +23,6 @@ import org.gradle.openapi.external.ui.OutputObserverVersion1;
/**
* Wrapper to shield version changes in OutputUILord.OutputObserver from an external user of the gradle open API.
- *
- * @author mhunsicker
*/
public class OutputObserverWrapper implements OutputUILord.OutputObserver {
private OutputObserverVersion1 outputObserverVersion1;
diff --git a/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/ui/OutputUILordWrapper.java b/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/ui/OutputUILordWrapper.java
index 8e0e815..11cf86e 100644
--- a/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/ui/OutputUILordWrapper.java
+++ b/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/ui/OutputUILordWrapper.java
@@ -26,8 +26,6 @@ import java.util.Map;
/**
* Wrapper to shield version changes in OutputUILord from an external user of gradle open API.
- *
- * @author mhunsicker
*/
public class OutputUILordWrapper implements OutputUILordVersion1 {
diff --git a/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/ui/SettingsNodeVersionWrapper.java b/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/ui/SettingsNodeVersionWrapper.java
index bed33e9..d49e0db 100644
--- a/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/ui/SettingsNodeVersionWrapper.java
+++ b/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/ui/SettingsNodeVersionWrapper.java
@@ -24,8 +24,6 @@ import java.util.List;
/**
* Wrapper to shield version changes in SettingsNode from an external user of gradle open API.
- *
- * @author mhunsicker
*/
public class SettingsNodeVersionWrapper implements SettingsNode {
private SettingsNodeVersion1 settingsNodeVersion1;
diff --git a/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/ui/SinglePaneUIWrapper.java b/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/ui/SinglePaneUIWrapper.java
index d9791b8..442f96a 100644
--- a/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/ui/SinglePaneUIWrapper.java
+++ b/subprojects/ui/src/main/java/org/gradle/openapi/wrappers/ui/SinglePaneUIWrapper.java
@@ -24,8 +24,6 @@ import javax.swing.*;
/**
* This wraps a SinglePaneUIVersion1 for the purpose of being instantiated for an external tool such an IDE plugin. It wraps several interfaces and uses delegation in an effort to make this backward
* and forward compatible. Most of the work is done in AbstractOpenAPIUIWrapper
- *
- * @author mhunsicker
*/
public class SinglePaneUIWrapper extends AbstractOpenAPIUIWrapper<SinglePaneUIInstance> implements SinglePaneUIVersion1 {
public SinglePaneUIWrapper(SinglePaneUIInteractionVersion1 singlePaneUIArguments) {
diff --git a/subprojects/ui/src/test/groovy/org/gradle/foundation/BuildInformation.java b/subprojects/ui/src/test/groovy/org/gradle/foundation/BuildInformation.java
index d3c2fb2..dee43fc 100644
--- a/subprojects/ui/src/test/groovy/org/gradle/foundation/BuildInformation.java
+++ b/subprojects/ui/src/test/groovy/org/gradle/foundation/BuildInformation.java
@@ -17,14 +17,12 @@ package org.gradle.foundation;
import org.gradle.api.Project;
+import java.util.Collections;
import java.util.Iterator;
import java.util.List;
-import java.util.Collections;
/**
* This provides a simple way to hold onto and obtain projects and tasks for testing purposes.
- *
- * @author mhunsicker
*/
public class BuildInformation {
private List<ProjectView> projects;
@@ -42,7 +40,6 @@ public class BuildInformation {
Call this to get the root level project with the given name.
@param name the name of the project.
@return the project if it exists.
- @author mhunsicker
*/
public ProjectView getRootLevelProject(String name) {
@@ -65,7 +62,6 @@ public class BuildInformation {
Locates the project that has the specified full path
@param fullProjectPath the full path of the sought project.
@return a project or null.
- @author mhunsicker
*/
public ProjectView getProjectFromFullPath(String fullProjectPath) {
@@ -104,7 +100,6 @@ public class BuildInformation {
@param fullTaskName the full task name (root_project:sub_project:sub_sub_project:task.).
@return the task or null if not found.
- @author mhunsicker
*/
public TaskView getTaskFromFullPath(String fullTaskName) {
diff --git a/subprojects/ui/src/test/groovy/org/gradle/foundation/CommandLineParsingTest.java b/subprojects/ui/src/test/groovy/org/gradle/foundation/CommandLineParsingTest.java
index ec32f8b..4ed9331 100644
--- a/subprojects/ui/src/test/groovy/org/gradle/foundation/CommandLineParsingTest.java
+++ b/subprojects/ui/src/test/groovy/org/gradle/foundation/CommandLineParsingTest.java
@@ -22,8 +22,6 @@ import static org.gradle.foundation.CommandLineAssistant.breakUpCommandLine;
/**
* This tests aspects of command line parsing that the UI does.
- *
- * @author mhunsicker
*/
public class CommandLineParsingTest extends TestCase {
/**
diff --git a/subprojects/ui/src/test/groovy/org/gradle/foundation/DOM4JSettingsNodeTest.java b/subprojects/ui/src/test/groovy/org/gradle/foundation/DOM4JSettingsNodeTest.java
index dd2b52b..d644156 100644
--- a/subprojects/ui/src/test/groovy/org/gradle/foundation/DOM4JSettingsNodeTest.java
+++ b/subprojects/ui/src/test/groovy/org/gradle/foundation/DOM4JSettingsNodeTest.java
@@ -27,8 +27,6 @@ import java.util.List;
/**
* Tests the DOM4JSettingsNode class.
- *
- * @author mhunsicker
*/
public class DOM4JSettingsNodeTest extends TestCase {
private DOM4JSettingsNode rootNode;
diff --git a/subprojects/ui/src/test/groovy/org/gradle/foundation/FavoritesTest.java b/subprojects/ui/src/test/groovy/org/gradle/foundation/FavoritesTest.java
index e1ae29c..993438d 100644
--- a/subprojects/ui/src/test/groovy/org/gradle/foundation/FavoritesTest.java
+++ b/subprojects/ui/src/test/groovy/org/gradle/foundation/FavoritesTest.java
@@ -31,8 +31,6 @@ import java.util.List;
/**
* Tests aspects of favorite tasks and the favorites editor.
- *
- * @author mhunsicker
*/
public class FavoritesTest extends TestCase {
private BuildInformation buildInformation;
diff --git a/subprojects/ui/src/test/groovy/org/gradle/foundation/FileLinkTests.java b/subprojects/ui/src/test/groovy/org/gradle/foundation/FileLinkTests.java
index 4ff1dea..a5de7b4 100644
--- a/subprojects/ui/src/test/groovy/org/gradle/foundation/FileLinkTests.java
+++ b/subprojects/ui/src/test/groovy/org/gradle/foundation/FileLinkTests.java
@@ -25,7 +25,6 @@ import java.util.List;
/**
These test several aspects of parsing output looking for files.
- @author mhunsicker
*/
public class FileLinkTests extends TestCase {
public static void parseOutputTest(String textToSearch, FileLink... expectedResults) {
diff --git a/subprojects/ui/src/test/groovy/org/gradle/foundation/FilterTest.java b/subprojects/ui/src/test/groovy/org/gradle/foundation/FilterTest.java
index d84b750..2c924eb 100644
--- a/subprojects/ui/src/test/groovy/org/gradle/foundation/FilterTest.java
+++ b/subprojects/ui/src/test/groovy/org/gradle/foundation/FilterTest.java
@@ -30,8 +30,6 @@ import java.util.List;
/**
* Test various aspects of filtering out tasks and projects from the GradlePluginLord.
- *
- * @author mhunsicker
*/
public class FilterTest extends TestCase {
private BuildInformation buildInformation;
diff --git a/subprojects/ui/src/test/groovy/org/gradle/foundation/LiveOutputParserTests.java b/subprojects/ui/src/test/groovy/org/gradle/foundation/LiveOutputParserTests.java
index 56a3c53..6f89d60 100644
--- a/subprojects/ui/src/test/groovy/org/gradle/foundation/LiveOutputParserTests.java
+++ b/subprojects/ui/src/test/groovy/org/gradle/foundation/LiveOutputParserTests.java
@@ -25,8 +25,6 @@ import java.util.List;
/**
* Tests aspects of LiveOutputParser. This finds FileLinks within text that is being output constantly.
- *
- * @author mhunsicker
*/
public class LiveOutputParserTests extends TestCase {
private LiveOutputParser parser;
diff --git a/subprojects/ui/src/test/groovy/org/gradle/foundation/TestUtility.java b/subprojects/ui/src/test/groovy/org/gradle/foundation/TestUtility.java
index c0390ac..e0034e5 100644
--- a/subprojects/ui/src/test/groovy/org/gradle/foundation/TestUtility.java
+++ b/subprojects/ui/src/test/groovy/org/gradle/foundation/TestUtility.java
@@ -15,7 +15,6 @@
*/
package org.gradle.foundation;
-import junit.framework.Assert;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.tasks.TaskContainer;
@@ -28,6 +27,7 @@ import org.gradle.gradleplugin.foundation.request.Request;
import org.gradle.internal.UncheckedException;
import org.jmock.Expectations;
import org.jmock.integration.junit4.JUnit4Mockery;
+import org.junit.Assert;
import javax.swing.filechooser.FileFilter;
import java.io.File;
@@ -38,8 +38,6 @@ import java.util.concurrent.atomic.AtomicReference;
/**
* Utility class for initializing various test objects related.
- *
- * @author mhunsicker
*/
public class TestUtility {
private static long uniqueNameCounter = 1; //used to make unique names for JMock objects.
diff --git a/subprojects/ui/src/test/groovy/org/gradle/foundation/TextBlockSearchEditorTests.java b/subprojects/ui/src/test/groovy/org/gradle/foundation/TextBlockSearchEditorTests.java
index 500de05..0cbe8be 100644
--- a/subprojects/ui/src/test/groovy/org/gradle/foundation/TextBlockSearchEditorTests.java
+++ b/subprojects/ui/src/test/groovy/org/gradle/foundation/TextBlockSearchEditorTests.java
@@ -21,8 +21,6 @@ import org.gradle.gradleplugin.foundation.search.TextBlockSearchEditor;
/**
* Tests for TextBlockSearchEditor
- *
- * @author mhunsicker
*/
public class TextBlockSearchEditorTests extends TestCase {
private final static String TEXT_1 = "blah blah\n" + //ends on index 9
diff --git a/subprojects/ui/ui.gradle b/subprojects/ui/ui.gradle
index 0683f61..d72449a 100644
--- a/subprojects/ui/ui.gradle
+++ b/subprojects/ui/ui.gradle
@@ -18,7 +18,7 @@ dependencies {
compile project(':core')
compile project(':openApi')
- groovy libraries.groovy
+ compile libraries.groovy
compile libraries.dom4j
compile libraries.commons_io
diff --git a/subprojects/wrapper/src/integTest/groovy/org/gradle/integtests/WrapperConcurrentDownloadTest.groovy b/subprojects/wrapper/src/integTest/groovy/org/gradle/integtests/WrapperConcurrentDownloadTest.groovy
new file mode 100644
index 0000000..2da94dd
--- /dev/null
+++ b/subprojects/wrapper/src/integTest/groovy/org/gradle/integtests/WrapperConcurrentDownloadTest.groovy
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests
+
+import org.apache.commons.io.IOUtils
+import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+import org.gradle.test.fixtures.file.TestFile
+import org.junit.Rule
+import org.junit.rules.ExternalResource
+import org.mortbay.jetty.Connector
+import org.mortbay.jetty.Server
+import org.mortbay.jetty.bio.SocketConnector
+import org.mortbay.jetty.handler.AbstractHandler
+import spock.lang.Issue
+
+import javax.servlet.ServletException
+import javax.servlet.http.HttpServletRequest
+import javax.servlet.http.HttpServletResponse
+
+class WrapperConcurrentDownloadTest extends AbstractIntegrationSpec {
+ @Rule BlockingDownloadHttpServer server = new BlockingDownloadHttpServer(distribution.binDistribution)
+
+ def setup() {
+ executer.beforeExecute(new WrapperSetup())
+ }
+
+ @Issue("http://issues.gradle.org/browse/GRADLE-2699")
+ def "concurrent downloads do not stomp over each other"() {
+ given:
+ buildFile << """
+ wrapper {
+ distributionUrl = '${server.distUri}'
+ }
+"""
+
+ succeeds('wrapper')
+
+ when:
+ def results = [1..4].collect { executer.usingExecutable("gradlew").start() }*.waitForFinish()
+
+ then:
+ results.findAll { it.output.contains("Downloading") }.size() == 1
+ }
+
+ static class BlockingDownloadHttpServer extends ExternalResource {
+ private final Server server = new Server()
+ private final TestFile binZip
+
+ BlockingDownloadHttpServer(TestFile binZip) {
+ this.binZip = binZip
+ }
+
+ URI getDistUri() {
+ return new URI("http://localhost:${server.connectors[0].localPort}/gradle-bin.zip")
+ }
+
+ @Override
+ protected void before() throws Throwable {
+ server.connectors = [new SocketConnector()] as Connector[]
+ server.addHandler(new AbstractHandler() {
+ void handle(String target, HttpServletRequest request, HttpServletResponse response, int dispatch) throws IOException, ServletException {
+ binZip.withInputStream { instr ->
+ IOUtils.copy(instr, response.outputStream)
+ }
+ request.handled = true
+ }
+ })
+ server.start()
+ }
+
+ @Override
+ protected void after() {
+ server.stop()
+ }
+ }
+}
diff --git a/subprojects/wrapper/src/integTest/groovy/org/gradle/integtests/WrapperGenerationIntegrationTest.groovy b/subprojects/wrapper/src/integTest/groovy/org/gradle/integtests/WrapperGenerationIntegrationTest.groovy
new file mode 100644
index 0000000..91d6f3d
--- /dev/null
+++ b/subprojects/wrapper/src/integTest/groovy/org/gradle/integtests/WrapperGenerationIntegrationTest.groovy
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests
+
+import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+import org.gradle.util.TextUtil
+
+class WrapperGenerationIntegrationTest extends AbstractIntegrationSpec {
+ def setup() {
+ buildFile << """
+ wrapper {
+ distributionUrl = 'http://localhost:8080/gradlew/dist'
+ }
+ """
+ }
+
+ def "generated wrapper scripts use correct line separators"() {
+ when:
+ run "wrapper"
+
+ then:
+ file("gradlew").text.split(TextUtil.unixLineSeparator).length > 1
+ file("gradlew").text.split(TextUtil.windowsLineSeparator).length == 1
+ file("gradlew.bat").text.split(TextUtil.windowsLineSeparator).length > 1
+ }
+
+ def "wrapper jar is small"() {
+ when:
+ run "wrapper"
+
+ then:
+ // wrapper needs to be small. Let's check it's smaller than some arbitrary 'small' limit
+ file("gradle/wrapper/gradle-wrapper.jar").length() < 51 * 1024
+ }
+}
diff --git a/subprojects/wrapper/src/integTest/groovy/org/gradle/integtests/WrapperHttpIntegrationTest.groovy b/subprojects/wrapper/src/integTest/groovy/org/gradle/integtests/WrapperHttpIntegrationTest.groovy
new file mode 100644
index 0000000..7d22c49
--- /dev/null
+++ b/subprojects/wrapper/src/integTest/groovy/org/gradle/integtests/WrapperHttpIntegrationTest.groovy
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests
+
+import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+import org.gradle.integtests.fixtures.executer.GradleExecuter
+import org.gradle.test.fixtures.server.http.HttpServer
+import org.gradle.test.fixtures.server.http.TestProxyServer
+import org.gradle.util.GradleVersion
+import org.junit.Rule
+
+import static org.gradle.test.matchers.UserAgentMatcher.matchesNameAndVersion
+import static org.hamcrest.Matchers.containsString
+import static org.junit.Assert.assertThat
+
+class WrapperHttpIntegrationTest extends AbstractIntegrationSpec {
+ @Rule HttpServer server = new HttpServer()
+ @Rule TestProxyServer proxyServer = new TestProxyServer(server)
+
+ void setup() {
+ assert distribution.binDistribution.exists(): "bin distribution must exist to run this test, you need to run the :distributions:binZip task"
+ executer.beforeExecute(new WrapperSetup())
+ server.start()
+ server.expectUserAgent(matchesNameAndVersion("gradlew", GradleVersion.current().getVersion()))
+ }
+
+ GradleExecuter getWrapperExecuter() {
+ executer.usingExecutable('gradlew').inDirectory(testDirectory)
+ }
+
+ private prepareWrapper(String baseUrl) {
+ file("build.gradle") << """
+ wrapper {
+ distributionUrl = '${baseUrl}/gradlew/dist'
+ }
+
+ task hello << {
+ println 'hello'
+ }
+
+ task echoProperty << {
+ println "fooD=" + project.properties["fooD"]
+ }
+"""
+
+ executer.withTasks('wrapper').run()
+ }
+
+ public void "downloads wrapper from http server and caches"() {
+ given:
+ prepareWrapper("http://localhost:${server.port}")
+ server.expectGet("/gradlew/dist", distribution.binDistribution)
+
+ when:
+ def result = wrapperExecuter.withTasks('hello').run()
+
+ then:
+ assertThat(result.output, containsString('hello'))
+
+ when:
+ result = wrapperExecuter.withTasks('hello').run()
+
+ then:
+ assertThat(result.output, containsString('hello'))
+ }
+
+ public void "recovers from failed download"() {
+ given:
+ prepareWrapper("http://localhost:${server.port}")
+ server.addBroken("/")
+
+ when:
+ wrapperExecuter.withStackTraceChecksDisabled()
+ def failure = wrapperExecuter.runWithFailure()
+
+ then:
+ failure.error.contains('Server returned HTTP response code: 500')
+
+ when:
+ server.resetExpectations()
+ server.expectGet("/gradlew/dist", distribution.binDistribution)
+
+ and:
+ wrapperExecuter.run()
+
+ then:
+ noExceptionThrown()
+ }
+
+ public void "downloads wrapper via proxy"() {
+ given:
+ proxyServer.start()
+ prepareWrapper("http://not.a.real.domain")
+ file("gradle.properties") << """
+ systemProp.http.proxyHost=localhost
+ systemProp.http.proxyPort=${proxyServer.port}
+"""
+ server.expectGet("/gradlew/dist", distribution.binDistribution)
+
+ when:
+ def result = wrapperExecuter.withTasks('hello').run()
+
+ then:
+ assertThat(result.output, containsString('hello'))
+
+ and:
+ proxyServer.requestCount == 1
+ }
+
+ public void "downloads wrapper via authenticated proxy"() {
+ given:
+ proxyServer.start()
+ proxyServer.requireAuthentication('my_user', 'my_password')
+
+ and:
+ prepareWrapper("http://not.a.real.domain")
+ server.expectGet("/gradlew/dist", distribution.binDistribution)
+ file("gradle.properties") << """
+ systemProp.http.proxyHost=localhost
+ systemProp.http.proxyPort=${proxyServer.port}
+ systemProp.http.proxyUser=my_user
+ systemProp.http.proxyPassword=my_password
+"""
+
+ when:
+ def result = wrapperExecuter.withTasks('hello').run()
+
+ then:
+ assertThat(result.output, containsString('hello'))
+
+ and:
+ proxyServer.requestCount == 1
+ }
+}
diff --git a/subprojects/wrapper/src/integTest/groovy/org/gradle/integtests/WrapperProjectIntegrationTest.groovy b/subprojects/wrapper/src/integTest/groovy/org/gradle/integtests/WrapperProjectIntegrationTest.groovy
index b142b66..0f4dd1a 100644
--- a/subprojects/wrapper/src/integTest/groovy/org/gradle/integtests/WrapperProjectIntegrationTest.groovy
+++ b/subprojects/wrapper/src/integTest/groovy/org/gradle/integtests/WrapperProjectIntegrationTest.groovy
@@ -17,49 +17,27 @@
package org.gradle.integtests
import org.gradle.integtests.fixtures.AbstractIntegrationSpec
-import org.gradle.integtests.fixtures.executer.ExecutionFailure
-import org.gradle.integtests.fixtures.executer.ExecutionResult
import org.gradle.integtests.fixtures.executer.GradleExecuter
-import org.gradle.test.fixtures.server.http.HttpServer
-import org.gradle.test.fixtures.server.http.TestProxyServer
-import org.gradle.util.GradleVersion
-import org.gradle.util.SetSystemProperties
-import org.gradle.util.TextUtil
-import org.junit.Rule
+import org.hamcrest.Matchers
import spock.lang.Issue
-import static org.gradle.test.matchers.UserAgentMatcher.matchesNameAndVersion
import static org.hamcrest.Matchers.containsString
import static org.junit.Assert.assertThat
-/**
- * @author Hans Dockter
- */
class WrapperProjectIntegrationTest extends AbstractIntegrationSpec {
- @Rule HttpServer server = new HttpServer()
- @Rule TestProxyServer proxyServer = new TestProxyServer(server)
- @Rule SetSystemProperties systemProperties = new SetSystemProperties()
-
void setup() {
- server.start()
- server.expectUserAgent(matchesNameAndVersion("gradlew", GradleVersion.current().getVersion()))
+ assert distribution.binDistribution.exists(): "bin distribution must exist to run this test, you need to run the :distributions:binZip task"
+ executer.beforeExecute(new WrapperSetup())
}
GradleExecuter getWrapperExecuter() {
executer.usingExecutable('gradlew').inDirectory(testDirectory)
}
- private prepareWrapper(String baseUrl) {
- assert distribution.binDistribution.exists(): "bin distribution must exist to run this test, you need to run the :binZip task"
-
+ private prepareWrapper() {
file("build.gradle") << """
- import org.gradle.api.tasks.wrapper.Wrapper
- task wrapper(type: Wrapper) {
- archiveBase = Wrapper.PathBase.PROJECT
- archivePath = 'dist'
- distributionUrl = '${baseUrl}/gradlew/dist'
- distributionBase = Wrapper.PathBase.PROJECT
- distributionPath = 'dist'
+ wrapper {
+ distributionUrl = '${distribution.binDistribution.toURI()}'
}
task hello << {
@@ -72,109 +50,28 @@ class WrapperProjectIntegrationTest extends AbstractIntegrationSpec {
"""
executer.withTasks('wrapper').run()
- server.allowGetOrHead("/gradlew/dist", distribution.binDistribution)
}
public void "has non-zero exit code on build failure"() {
given:
- prepareWrapper("http://localhost:${server.port}")
-
- expect:
- server.allowGetOrHead("/gradlew/dist", distribution.binDistribution)
+ prepareWrapper()
when:
- ExecutionFailure failure = wrapperExecuter.withTasks('unknown').runWithFailure()
+ def failure = wrapperExecuter.withTasks('unknown').runWithFailure()
then:
- failure.assertHasDescription("Task 'unknown' not found in root project")
- }
-
- public void "runs sample target using wrapper"() {
- given:
- prepareWrapper("http://localhost:${server.port}")
-
- when:
- ExecutionResult result = wrapperExecuter.withTasks('hello').run()
-
- then:
- assertThat(result.output, containsString('hello'))
- }
-
- public void "downloads wrapper via proxy"() {
- given:
- proxyServer.start()
- prepareWrapper("http://not.a.real.domain")
- file("gradle.properties") << """
- systemProp.http.proxyHost=localhost
- systemProp.http.proxyPort=${proxyServer.port}
-"""
-
- when:
- ExecutionResult result = wrapperExecuter.withTasks('hello').run()
-
- then:
- assertThat(result.output, containsString('hello'))
-
- and:
- proxyServer.requestCount == 1
- }
-
- public void "downloads wrapper via authenticated proxy"() {
- given:
- proxyServer.start()
- proxyServer.requireAuthentication('my_user', 'my_password')
-
- and:
- prepareWrapper("http://not.a.real.domain")
- file("gradle.properties") << """
- systemProp.http.proxyHost=localhost
- systemProp.http.proxyPort=${proxyServer.port}
- systemProp.http.proxyUser=my_user
- systemProp.http.proxyPassword=my_password
-"""
- when:
- ExecutionResult result = wrapperExecuter.withTasks('hello').run()
-
- then:
- assertThat(result.output, containsString('hello'))
-
- and:
- proxyServer.requestCount == 1
+ failure.assertThatDescription(Matchers.startsWith("Task 'unknown' not found in root project"))
}
@Issue("http://issues.gradle.org/browse/GRADLE-1871")
public void "can specify project properties containing D"() {
given:
- prepareWrapper("http://localhost:${server.port}")
+ prepareWrapper()
when:
- ExecutionResult result = wrapperExecuter.withArguments("-PfooD=bar").withTasks('echoProperty').run()
+ def result = wrapperExecuter.withArguments("-PfooD=bar").withTasks('echoProperty').run()
then:
assertThat(result.output, containsString("fooD=bar"))
}
-
- public void "generated wrapper scripts use correct line separators"() {
- given:
- assert distribution.binDistribution.exists(): "bin distribution must exist to run this test, you need to run the :binZip task"
-
- file("build.gradle") << """
- import org.gradle.api.tasks.wrapper.Wrapper
- task wrapper(type: Wrapper) {
- archiveBase = Wrapper.PathBase.PROJECT
- archivePath = 'dist'
- distributionUrl = 'http://localhost:${server.port}/gradlew/dist'
- distributionBase = Wrapper.PathBase.PROJECT
- distributionPath = 'dist'
- }
- """
-
- when:
- run "wrapper"
- then:
- assert file("gradlew").text.split(TextUtil.unixLineSeparator).length > 1
- assert file("gradlew").text.split(TextUtil.windowsLineSeparator).length == 1
- assert file("gradlew.bat").text.split(TextUtil.windowsLineSeparator).length > 1
- noExceptionThrown()
- }
}
diff --git a/subprojects/wrapper/src/integTest/groovy/org/gradle/integtests/WrapperSetup.groovy b/subprojects/wrapper/src/integTest/groovy/org/gradle/integtests/WrapperSetup.groovy
new file mode 100644
index 0000000..8398ffc
--- /dev/null
+++ b/subprojects/wrapper/src/integTest/groovy/org/gradle/integtests/WrapperSetup.groovy
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests
+
+import org.gradle.api.Action
+import org.gradle.integtests.fixtures.executer.GradleExecuter
+
+class WrapperSetup implements Action<GradleExecuter> {
+ void execute(GradleExecuter executer) {
+ executer.requireOwnGradleUserHomeDir()
+ executer.requireIsolatedDaemons()
+ executer.withEnvironmentVars(GRADLE_USER_HOME: executer.gradleUserHomeDir)
+ }
+}
diff --git a/subprojects/wrapper/src/integTest/groovy/org/gradle/integtests/WrapperUserHomeIntegrationTest.groovy b/subprojects/wrapper/src/integTest/groovy/org/gradle/integtests/WrapperUserHomeIntegrationTest.groovy
new file mode 100644
index 0000000..aac1714
--- /dev/null
+++ b/subprojects/wrapper/src/integTest/groovy/org/gradle/integtests/WrapperUserHomeIntegrationTest.groovy
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2007 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.integtests
+
+import org.gradle.integtests.fixtures.AbstractIntegrationSpec
+import org.gradle.test.fixtures.file.TestFile
+import spock.lang.Issue
+
+class WrapperUserHomeIntegrationTest extends AbstractIntegrationSpec {
+
+ void setup() {
+ assert distribution.binDistribution.exists() : "bin distribution must exist to run this test, you need to run the :distributions:binZip task"
+ executer.requireIsolatedDaemons()
+ }
+
+ private prepareWrapper() {
+ file("build.gradle") << """
+ wrapper {
+ distributionUrl = '${distribution.binDistribution.toURI()}'
+ }
+ """
+ executer.withTasks('wrapper').run()
+ executer.usingExecutable('gradlew').inDirectory(testDirectory).withGradleUserHomeDir(null)
+ }
+
+ private def installationIn(TestFile userHomeDir) {
+ def distDir = userHomeDir.file("wrapper/dists/gradle-${distribution.version.version}-bin").assertIsDir()
+ assert distDir.listFiles().length == 1
+ return distDir.listFiles()[0].file("gradle-${distribution.version.version}").assertIsDir()
+ }
+
+ void 'uses gradle user home set by -Dgradle.user.home'() {
+ given:
+ prepareWrapper()
+ def gradleUserHome = testDirectory.file('user-home')
+
+ when:
+ args "-Dgradle.user.home=$gradleUserHome.absolutePath"
+ succeeds()
+
+ then:
+ installationIn gradleUserHome exists()
+ }
+
+ @Issue('http://issues.gradle.org/browse/GRADLE-2802')
+ void 'uses gradle user home set by -g'() {
+ given:
+ prepareWrapper()
+ def gradleUserHome = testDirectory.file('user-home')
+
+ when:
+ args '-g', gradleUserHome.absolutePath
+ succeeds()
+
+ then:
+ installationIn gradleUserHome exists()
+ }
+}
diff --git a/subprojects/wrapper/src/main/java/org/gradle/wrapper/BootstrapMainStarter.java b/subprojects/wrapper/src/main/java/org/gradle/wrapper/BootstrapMainStarter.java
index 05a3085..f3b02a6 100644
--- a/subprojects/wrapper/src/main/java/org/gradle/wrapper/BootstrapMainStarter.java
+++ b/subprojects/wrapper/src/main/java/org/gradle/wrapper/BootstrapMainStarter.java
@@ -20,9 +20,6 @@ import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
-/**
- * @author Hans Dockter
- */
public class BootstrapMainStarter {
public void start(String[] args, File gradleHome) throws Exception {
File gradleJar = findLauncherJar(gradleHome);
diff --git a/subprojects/wrapper/src/main/java/org/gradle/wrapper/Download.java b/subprojects/wrapper/src/main/java/org/gradle/wrapper/Download.java
index e0d2210..39e6b4c 100644
--- a/subprojects/wrapper/src/main/java/org/gradle/wrapper/Download.java
+++ b/subprojects/wrapper/src/main/java/org/gradle/wrapper/Download.java
@@ -19,9 +19,6 @@ package org.gradle.wrapper;
import java.io.*;
import java.net.*;
-/**
- * @author Hans Dockter
- */
public class Download implements IDownload {
private static final int PROGRESS_CHUNK = 20000;
private static final int BUFFER_SIZE = 10000;
@@ -41,11 +38,7 @@ public class Download implements IDownload {
}
public void download(URI address, File destination) throws Exception {
- if (destination.exists()) {
- return;
- }
destination.getParentFile().mkdirs();
-
downloadInternal(address, destination);
}
diff --git a/subprojects/wrapper/src/main/java/org/gradle/wrapper/ExclusiveFileAccessManager.java b/subprojects/wrapper/src/main/java/org/gradle/wrapper/ExclusiveFileAccessManager.java
new file mode 100644
index 0000000..f63ef49
--- /dev/null
+++ b/subprojects/wrapper/src/main/java/org/gradle/wrapper/ExclusiveFileAccessManager.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gradle.wrapper;
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.RandomAccessFile;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
+import java.util.concurrent.Callable;
+
+public class ExclusiveFileAccessManager {
+
+ public static final String LOCK_FILE_SUFFIX = ".lck";
+
+ private final int timeoutMs;
+ private final int pollIntervalMs;
+
+ public ExclusiveFileAccessManager(int timeoutMs, int pollIntervalMs) {
+ this.timeoutMs = timeoutMs;
+ this.pollIntervalMs = pollIntervalMs;
+ }
+
+ public <T> T access(File exclusiveFile, Callable<T> task) {
+ final File lockFile = new File(exclusiveFile.getParentFile(), exclusiveFile.getName() + LOCK_FILE_SUFFIX);
+ lockFile.getParentFile().mkdirs();
+ RandomAccessFile randomAccessFile = null;
+ FileChannel channel = null;
+ try {
+
+ long startAt = System.currentTimeMillis();
+ FileLock lock = null;
+
+ while (lock == null && System.currentTimeMillis() < startAt + timeoutMs) {
+ randomAccessFile = new RandomAccessFile(lockFile, "rw");
+ channel = randomAccessFile.getChannel();
+ lock = channel.tryLock();
+
+ if (lock == null) {
+ maybeCloseQuietly(channel);
+ maybeCloseQuietly(randomAccessFile);
+ Thread.sleep(pollIntervalMs);
+ }
+ }
+
+ if (lock == null) {
+ throw new RuntimeException("Timeout of " + timeoutMs + " reached waiting for exclusive access to file: " + exclusiveFile.getAbsolutePath());
+ }
+
+ try {
+ return task.call();
+ } finally {
+ lock.release();
+
+ maybeCloseQuietly(channel);
+ channel = null;
+ maybeCloseQuietly(randomAccessFile);
+ randomAccessFile = null;
+ }
+ } catch (Exception e) {
+ if (e instanceof RuntimeException) {
+ throw (RuntimeException) e;
+ } else {
+ throw new RuntimeException(e);
+ }
+ } finally {
+ maybeCloseQuietly(channel);
+ maybeCloseQuietly(randomAccessFile);
+ }
+ }
+
+ private static void maybeCloseQuietly(Closeable closeable) {
+ if (closeable != null) {
+ try {
+ closeable.close();
+ } catch (Exception ignore) {
+ //
+ }
+ }
+ }
+}
diff --git a/subprojects/wrapper/src/main/java/org/gradle/wrapper/GradleWrapperMain.java b/subprojects/wrapper/src/main/java/org/gradle/wrapper/GradleWrapperMain.java
index bb03dbb..8ae1e7f 100644
--- a/subprojects/wrapper/src/main/java/org/gradle/wrapper/GradleWrapperMain.java
+++ b/subprojects/wrapper/src/main/java/org/gradle/wrapper/GradleWrapperMain.java
@@ -17,20 +17,19 @@
package org.gradle.wrapper;
import org.gradle.cli.CommandLineParser;
+import org.gradle.cli.ParsedCommandLine;
import org.gradle.cli.SystemPropertiesCommandLineConverter;
import java.io.File;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
-import java.util.Map;
import java.util.Properties;
-/**
- * @author Hans Dockter
- */
public class GradleWrapperMain {
public static final String DEFAULT_GRADLE_USER_HOME = System.getProperty("user.home") + "/.gradle";
+ public static final String GRADLE_USER_HOME_OPTION = "g";
+ public static final String GRADLE_USER_HOME_DETAILED_OPTION = "gradle-user-home";
public static final String GRADLE_USER_HOME_PROPERTY_KEY = "gradle.user.home";
public static final String GRADLE_USER_HOME_ENV_KEY = "GRADLE_USER_HOME";
@@ -39,28 +38,31 @@ public class GradleWrapperMain {
File propertiesFile = wrapperProperties(wrapperJar);
File rootDir = rootDir(wrapperJar);
+ CommandLineParser parser = new CommandLineParser();
+ parser.allowUnknownOptions();
+ parser.option(GRADLE_USER_HOME_OPTION, GRADLE_USER_HOME_DETAILED_OPTION).hasArgument();
+
+ SystemPropertiesCommandLineConverter converter = new SystemPropertiesCommandLineConverter();
+ converter.configure(parser);
+
+ ParsedCommandLine options = parser.parse(args);
+
Properties systemProperties = System.getProperties();
- systemProperties.putAll(parseSystemPropertiesFromArgs(args));
+ systemProperties.putAll(converter.convert(options));
+
+ File gradleUserHome = gradleUserHome(options);
- addSystemProperties(rootDir);
+ addSystemProperties(gradleUserHome, rootDir);
WrapperExecutor wrapperExecutor = WrapperExecutor.forWrapperPropertiesFile(propertiesFile, System.out);
wrapperExecutor.execute(
args,
- new Install(new Download("gradlew", wrapperVersion()), new PathAssembler(gradleUserHome())),
+ new Install(new Download("gradlew", wrapperVersion()), new PathAssembler(gradleUserHome)),
new BootstrapMainStarter());
}
- private static Map<String, String> parseSystemPropertiesFromArgs(String[] args) {
- SystemPropertiesCommandLineConverter converter = new SystemPropertiesCommandLineConverter();
- CommandLineParser commandLineParser = new CommandLineParser();
- converter.configure(commandLineParser);
- commandLineParser.allowUnknownOptions();
- return converter.convert(commandLineParser.parse(args));
- }
-
- private static void addSystemProperties(File rootDir) {
- System.getProperties().putAll(SystemPropertiesHandler.getSystemProperties(new File(gradleUserHome(), "gradle.properties")));
+ private static void addSystemProperties(File gradleHome, File rootDir) {
+ System.getProperties().putAll(SystemPropertiesHandler.getSystemProperties(new File(gradleHome, "gradle.properties")));
System.getProperties().putAll(SystemPropertiesHandler.getSystemProperties(new File(rootDir, "gradle.properties")));
}
@@ -107,14 +109,17 @@ public class GradleWrapperMain {
}
}
- private static File gradleUserHome() {
- String gradleUserHome = System.getProperty(GRADLE_USER_HOME_PROPERTY_KEY);
- if (gradleUserHome != null) {
+ private static File gradleUserHome(ParsedCommandLine options) {
+ if (options.hasOption(GRADLE_USER_HOME_OPTION)) {
+ return new File(options.option(GRADLE_USER_HOME_OPTION).getValue());
+ }
+ String gradleUserHome;
+ if ((gradleUserHome = System.getProperty(GRADLE_USER_HOME_PROPERTY_KEY)) != null) {
return new File(gradleUserHome);
- } else if ((gradleUserHome = System.getenv(GRADLE_USER_HOME_ENV_KEY)) != null) {
+ }
+ if ((gradleUserHome = System.getenv(GRADLE_USER_HOME_ENV_KEY)) != null) {
return new File(gradleUserHome);
- } else {
- return new File(DEFAULT_GRADLE_USER_HOME);
}
+ return new File(DEFAULT_GRADLE_USER_HOME);
}
}
diff --git a/subprojects/wrapper/src/main/java/org/gradle/wrapper/IDownload.java b/subprojects/wrapper/src/main/java/org/gradle/wrapper/IDownload.java
index fbab4df..078490c 100644
--- a/subprojects/wrapper/src/main/java/org/gradle/wrapper/IDownload.java
+++ b/subprojects/wrapper/src/main/java/org/gradle/wrapper/IDownload.java
@@ -18,9 +18,6 @@ package org.gradle.wrapper;
import java.io.File;
import java.net.URI;
-/**
- * @author Hans Dockter
- */
public interface IDownload {
void download(URI address, File destination) throws Exception;
}
diff --git a/subprojects/wrapper/src/main/java/org/gradle/wrapper/Install.java b/subprojects/wrapper/src/main/java/org/gradle/wrapper/Install.java
index 04938ac..144fcb0 100644
--- a/subprojects/wrapper/src/main/java/org/gradle/wrapper/Install.java
+++ b/subprojects/wrapper/src/main/java/org/gradle/wrapper/Install.java
@@ -19,16 +19,15 @@ package org.gradle.wrapper;
import java.io.*;
import java.net.URI;
import java.util.*;
+import java.util.concurrent.Callable;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
-/**
- * @author Hans Dockter
- */
public class Install {
public static final String DEFAULT_DISTRIBUTION_PATH = "wrapper/dists";
private final IDownload download;
private final PathAssembler pathAssembler;
+ private final ExclusiveFileAccessManager exclusiveFileAccessManager = new ExclusiveFileAccessManager(120000, 200);
public Install(IDownload download, PathAssembler pathAssembler) {
this.download = download;
@@ -36,41 +35,53 @@ public class Install {
}
public File createDist(WrapperConfiguration configuration) throws Exception {
- URI distributionUrl = configuration.getDistribution();
- boolean alwaysDownload = configuration.isAlwaysDownload();
- boolean alwaysUnpack = configuration.isAlwaysUnpack();
-
- PathAssembler.LocalDistribution localDistribution = pathAssembler.getDistribution(configuration);
-
- File localZipFile = localDistribution.getZipFile();
- boolean downloaded = false;
- if (alwaysDownload || !localZipFile.exists()) {
- File tmpZipFile = new File(localZipFile.getParentFile(), localZipFile.getName() + ".part");
- tmpZipFile.delete();
- System.out.println("Downloading " + distributionUrl);
- download.download(distributionUrl, tmpZipFile);
- tmpZipFile.renameTo(localZipFile);
- downloaded = true;
- }
+ final URI distributionUrl = configuration.getDistribution();
- File distDir = localDistribution.getDistributionDir();
- List<File> dirs = listDirs(distDir);
+ final PathAssembler.LocalDistribution localDistribution = pathAssembler.getDistribution(configuration);
+ final File distDir = localDistribution.getDistributionDir();
+ final File localZipFile = localDistribution.getZipFile();
- if (downloaded || alwaysUnpack || dirs.isEmpty()) {
- for (File dir : dirs) {
- System.out.println("Deleting directory " + dir.getAbsolutePath());
- deleteDir(dir);
- }
- System.out.println("Unzipping " + localZipFile.getAbsolutePath() + " to " + distDir.getAbsolutePath());
- unzip(localZipFile, distDir);
- dirs = listDirs(distDir);
- if (dirs.isEmpty()) {
- throw new RuntimeException(String.format("Gradle distribution '%s' does not contain any directories. Expected to find exactly 1 directory.", distributionUrl));
+ return exclusiveFileAccessManager.access(localZipFile, new Callable<File>() {
+ public File call() throws Exception {
+ final File markerFile = new File(localZipFile.getParentFile(), localZipFile.getName() + ".ok");
+ if (distDir.isDirectory() && markerFile.isFile()) {
+ return getDistributionRoot(distDir, distDir.getAbsolutePath());
+ }
+
+ boolean needsDownload = !localZipFile.isFile();
+
+ if (needsDownload) {
+ File tmpZipFile = new File(localZipFile.getParentFile(), localZipFile.getName() + ".part");
+ tmpZipFile.delete();
+ System.out.println("Downloading " + distributionUrl);
+ download.download(distributionUrl, tmpZipFile);
+ tmpZipFile.renameTo(localZipFile);
+ }
+
+ List<File> topLevelDirs = listDirs(distDir);
+ for (File dir : topLevelDirs) {
+ System.out.println("Deleting directory " + dir.getAbsolutePath());
+ deleteDir(dir);
+ }
+ System.out.println("Unzipping " + localZipFile.getAbsolutePath() + " to " + distDir.getAbsolutePath());
+ unzip(localZipFile, distDir);
+
+ File root = getDistributionRoot(distDir, distributionUrl.toString());
+ setExecutablePermissions(root);
+ markerFile.createNewFile();
+
+ return root;
}
- setExecutablePermissions(dirs.get(0));
+ });
+ }
+
+ private File getDistributionRoot(File distDir, String distributionDescription) {
+ List<File> dirs = listDirs(distDir);
+ if (dirs.isEmpty()) {
+ throw new RuntimeException(String.format("Gradle distribution '%s' does not contain any directories. Expected to find exactly 1 directory.", distributionDescription));
}
if (dirs.size() != 1) {
- throw new RuntimeException(String.format("Gradle distribution '%s' contains too many directories. Expected to find exactly 1 directory.", distributionUrl));
+ throw new RuntimeException(String.format("Gradle distribution '%s' contains too many directories. Expected to find exactly 1 directory.", distributionDescription));
}
return dirs.get(0);
}
@@ -141,29 +152,34 @@ public class Install {
return dir.delete();
}
- public void unzip(File zip, File dest) throws IOException {
+ private void unzip(File zip, File dest) throws IOException {
Enumeration entries;
- ZipFile zipFile;
+ ZipFile zipFile = new ZipFile(zip);
- zipFile = new ZipFile(zip);
+ try {
+ entries = zipFile.entries();
- entries = zipFile.entries();
+ while (entries.hasMoreElements()) {
+ ZipEntry entry = (ZipEntry) entries.nextElement();
- while (entries.hasMoreElements()) {
- ZipEntry entry = (ZipEntry) entries.nextElement();
+ if (entry.isDirectory()) {
+ (new File(dest, entry.getName())).mkdirs();
+ continue;
+ }
- if (entry.isDirectory()) {
- (new File(dest, entry.getName())).mkdirs();
- continue;
+ OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(new File(dest, entry.getName())));
+ try {
+ copyInputStream(zipFile.getInputStream(entry), outputStream);
+ } finally {
+ outputStream.close();
+ }
}
-
- copyInputStream(zipFile.getInputStream(entry),
- new BufferedOutputStream(new FileOutputStream(new File(dest, entry.getName()))));
+ } finally {
+ zipFile.close();
}
- zipFile.close();
}
- public void copyInputStream(InputStream in, OutputStream out) throws IOException {
+ private void copyInputStream(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024];
int len;
@@ -175,4 +191,5 @@ public class Install {
out.close();
}
+
}
diff --git a/subprojects/wrapper/src/main/java/org/gradle/wrapper/PathAssembler.java b/subprojects/wrapper/src/main/java/org/gradle/wrapper/PathAssembler.java
index eb7b6c9..d3c51bd 100644
--- a/subprojects/wrapper/src/main/java/org/gradle/wrapper/PathAssembler.java
+++ b/subprojects/wrapper/src/main/java/org/gradle/wrapper/PathAssembler.java
@@ -20,9 +20,6 @@ import java.math.BigInteger;
import java.net.URI;
import java.security.MessageDigest;
-/**
- * @author Hans Dockter
- */
public class PathAssembler {
public static final String GRADLE_USER_HOME_STRING = "GRADLE_USER_HOME";
public static final String PROJECT_STRING = "PROJECT";
diff --git a/subprojects/wrapper/src/main/java/org/gradle/wrapper/SystemPropertiesHandler.java b/subprojects/wrapper/src/main/java/org/gradle/wrapper/SystemPropertiesHandler.java
index e2d0ed1..a25f598 100644
--- a/subprojects/wrapper/src/main/java/org/gradle/wrapper/SystemPropertiesHandler.java
+++ b/subprojects/wrapper/src/main/java/org/gradle/wrapper/SystemPropertiesHandler.java
@@ -24,9 +24,6 @@ import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-/**
- * @author Hans Dockter
- */
public class SystemPropertiesHandler {
public static Map<String, String> getSystemProperties(File propertiesFile) {
diff --git a/subprojects/wrapper/src/main/java/org/gradle/wrapper/WrapperConfiguration.java b/subprojects/wrapper/src/main/java/org/gradle/wrapper/WrapperConfiguration.java
index b7b1002..c5da7f0 100644
--- a/subprojects/wrapper/src/main/java/org/gradle/wrapper/WrapperConfiguration.java
+++ b/subprojects/wrapper/src/main/java/org/gradle/wrapper/WrapperConfiguration.java
@@ -18,33 +18,12 @@ package org.gradle.wrapper;
import java.net.URI;
public class WrapperConfiguration {
- public static final String ALWAYS_UNPACK_ENV = "GRADLE_WRAPPER_ALWAYS_UNPACK";
- public static final String ALWAYS_DOWNLOAD_ENV = "GRADLE_WRAPPER_ALWAYS_DOWNLOAD";
-
- private boolean alwaysUnpack = Boolean.parseBoolean(System.getenv(ALWAYS_UNPACK_ENV));
- private boolean alwaysDownload = Boolean.parseBoolean(System.getenv(ALWAYS_DOWNLOAD_ENV));
private URI distribution;
private String distributionBase = PathAssembler.GRADLE_USER_HOME_STRING;
private String distributionPath = Install.DEFAULT_DISTRIBUTION_PATH;
private String zipBase = PathAssembler.GRADLE_USER_HOME_STRING;
private String zipPath = Install.DEFAULT_DISTRIBUTION_PATH;
- public boolean isAlwaysDownload() {
- return alwaysDownload;
- }
-
- public void setAlwaysDownload(boolean alwaysDownload) {
- this.alwaysDownload = alwaysDownload;
- }
-
- public boolean isAlwaysUnpack() {
- return alwaysUnpack;
- }
-
- public void setAlwaysUnpack(boolean alwaysUnpack) {
- this.alwaysUnpack = alwaysUnpack;
- }
-
public URI getDistribution() {
return distribution;
}
diff --git a/subprojects/wrapper/src/main/java/org/gradle/wrapper/WrapperExecutor.java b/subprojects/wrapper/src/main/java/org/gradle/wrapper/WrapperExecutor.java
index d7e58e7..aac4ff3 100644
--- a/subprojects/wrapper/src/main/java/org/gradle/wrapper/WrapperExecutor.java
+++ b/subprojects/wrapper/src/main/java/org/gradle/wrapper/WrapperExecutor.java
@@ -24,9 +24,6 @@ import java.net.URISyntaxException;
import java.util.Formatter;
import java.util.Properties;
-/**
- * @author Hans Dockter
- */
public class WrapperExecutor {
public static final String DISTRIBUTION_URL_PROPERTY = "distributionUrl";
public static final String DISTRIBUTION_BASE_PROPERTY = "distributionBase";
diff --git a/subprojects/wrapper/src/test/groovy/org/gradle/wrapper/DownloadTest.groovy b/subprojects/wrapper/src/test/groovy/org/gradle/wrapper/DownloadTest.groovy
index 57ba024..2c178b0 100644
--- a/subprojects/wrapper/src/test/groovy/org/gradle/wrapper/DownloadTest.groovy
+++ b/subprojects/wrapper/src/test/groovy/org/gradle/wrapper/DownloadTest.groovy
@@ -23,9 +23,6 @@ import org.junit.Test
import static org.junit.Assert.assertEquals
-/**
- * @author Hans Dockter
- */
class DownloadTest {
Download download
File testDir
diff --git a/subprojects/wrapper/src/test/groovy/org/gradle/wrapper/InstallTest.groovy b/subprojects/wrapper/src/test/groovy/org/gradle/wrapper/InstallTest.groovy
index 55f5d38..f1748c8 100644
--- a/subprojects/wrapper/src/test/groovy/org/gradle/wrapper/InstallTest.groovy
+++ b/subprojects/wrapper/src/test/groovy/org/gradle/wrapper/InstallTest.groovy
@@ -20,19 +20,11 @@ import org.gradle.test.fixtures.file.TestFile
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
import org.junit.Before
import org.junit.Rule
-import org.junit.Test
import spock.lang.Specification
-import static org.junit.Assert.assertEquals
-
-/**
- * @author Hans Dockter
- */
class InstallTest extends Specification {
File testDir
Install install
- IDownload downloadMock
- PathAssembler pathAssemblerMock;
boolean downloadCalled
File zip
TestFile distributionDir
@@ -54,8 +46,6 @@ class InstallTest extends Specification {
configuration.distributionBase = PathAssembler.GRADLE_USER_HOME_STRING
configuration.distributionPath = 'someDistPath'
configuration.distribution = new URI('http://server/gradle-0.9.zip')
- configuration.alwaysDownload = false
- configuration.alwaysUnpack = false
distributionDir = new TestFile(testDir, 'someDistPath')
gradleHomeDir = new TestFile(distributionDir, 'gradle-0.9')
zipStore = new File(testDir, 'zips');
@@ -63,29 +53,6 @@ class InstallTest extends Specification {
install = new Install(download, pathAssembler)
}
- IDownload createDownloadMock() {
- [download: {URI url, File destination ->
- assertEquals(configuration.distribution, url)
- assertEquals(zipDestination.getAbsolutePath() + '.part', destination.getAbsolutePath())
- zip = createTestZip()
- downloadCalled = true
- }] as IDownload
- }
-
- PathAssembler createPathAssemblerMock() {
- [gradleHome: {String distBase, String distPath, URI distUrl ->
- assertEquals(configuration.distributionBase, distBase)
- assertEquals(configuration.distributionPath, distPath)
- assertEquals(configuration.distribution, distUrl)
- gradleHomeDir},
- distZip: { String zipBase, String zipPath, URI distUrl ->
- assertEquals(configuration.zipBase, zipBase)
- assertEquals(configuration.zipPath, zipPath)
- assertEquals(configuration.distribution, distUrl)
- zipDestination
- }] as PathAssembler
- }
-
void createTestZip(File zipDestination) {
TestFile explodedZipDir = tmpDir.createDir('explodedZip')
TestFile gradleScript = explodedZipDir.file('gradle-0.9/bin/gradle')
@@ -94,7 +61,12 @@ class InstallTest extends Specification {
explodedZipDir.zipTo(new TestFile(zipDestination))
}
- public void testCreateDist() {
+ def "installs distribution and reuses on subsequent access"() {
+ given:
+ _ * pathAssembler.getDistribution(configuration) >> localDistribution
+ _ * localDistribution.distributionDir >> distributionDir
+ _ * localDistribution.zipFile >> zipDestination
+
when:
def homeDir = install.createDist(configuration)
@@ -105,77 +77,48 @@ class InstallTest extends Specification {
zipDestination.assertIsFile()
and:
- 1 * pathAssembler.getDistribution(configuration) >> localDistribution
- _ * localDistribution.distributionDir >> distributionDir
- _ * localDistribution.zipFile >> zipDestination
1 * download.download(configuration.distribution, _) >> { createTestZip(it[1]) }
0 * download._
- }
-
- @Test public void testCreateDistWithExistingDistribution() {
- given:
- zipDestination.createFile()
- gradleHomeDir.file('some-file').createFile()
- gradleHomeDir.createDir()
when:
- def homeDir = install.createDist(configuration)
+ homeDir = install.createDist(configuration)
then:
homeDir == gradleHomeDir
- gradleHomeDir.assertIsDir()
- gradleHomeDir.file('some-file').assertIsFile()
- zipDestination.assertIsFile()
and:
- 1 * pathAssembler.getDistribution(configuration) >> localDistribution
- _ * localDistribution.distributionDir >> distributionDir
- _ * localDistribution.zipFile >> zipDestination
0 * download._
}
- @Test public void testCreateDistWithExistingDistAndZipAndAlwaysUnpackTrue() {
+ def "recovers from download failure"() {
+ def failure = new RuntimeException("broken")
+
given:
- createTestZip(zipDestination)
- gradleHomeDir.file('garbage').createFile()
- configuration.alwaysUnpack = true
+ _ * pathAssembler.getDistribution(configuration) >> localDistribution
+ _ * localDistribution.distributionDir >> distributionDir
+ _ * localDistribution.zipFile >> zipDestination
when:
- def homeDir = install.createDist(configuration)
+ install.createDist(configuration)
then:
- homeDir == gradleHomeDir
- gradleHomeDir.assertIsDir()
- gradleHomeDir.file('garbage').assertDoesNotExist()
- zipDestination.assertIsFile()
+ RuntimeException e = thrown()
+ e == failure
and:
- 1 * pathAssembler.getDistribution(configuration) >> localDistribution
- _ * localDistribution.distributionDir >> distributionDir
- _ * localDistribution.zipFile >> zipDestination
+ 1 * download.download(configuration.distribution, _) >> {
+ it[1].text = 'broken!'
+ throw failure
+ }
0 * download._
- }
-
- @Test public void testCreateDistWithExistingZipAndDistAndAlwaysDownloadTrue() {
- given:
- createTestZip(zipDestination)
- gradleHomeDir.file('garbage').createFile()
- configuration.alwaysDownload = true
when:
def homeDir = install.createDist(configuration)
then:
homeDir == gradleHomeDir
- gradleHomeDir.assertIsDir()
- gradleHomeDir.file("bin/gradle").assertIsFile()
- gradleHomeDir.file('garbage').assertDoesNotExist()
- zipDestination.assertIsFile()
and:
- 1 * pathAssembler.getDistribution(configuration) >> localDistribution
- _ * localDistribution.distributionDir >> distributionDir
- _ * localDistribution.zipFile >> zipDestination
1 * download.download(configuration.distribution, _) >> { createTestZip(it[1]) }
0 * download._
}
diff --git a/subprojects/wrapper/src/test/groovy/org/gradle/wrapper/PathAssemblerTest.java b/subprojects/wrapper/src/test/groovy/org/gradle/wrapper/PathAssemblerTest.java
index 1e8adbf..e7fab02 100644
--- a/subprojects/wrapper/src/test/groovy/org/gradle/wrapper/PathAssemblerTest.java
+++ b/subprojects/wrapper/src/test/groovy/org/gradle/wrapper/PathAssemblerTest.java
@@ -25,9 +25,6 @@ import static org.gradle.util.Matchers.matchesRegexp;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.*;
-/**
- * @author Hans Dockter
- */
public class PathAssemblerTest {
public static final String TEST_GRADLE_USER_HOME = "someUserHome";
private PathAssembler pathAssembler = new PathAssembler(new File(TEST_GRADLE_USER_HOME));
diff --git a/subprojects/wrapper/src/test/groovy/org/gradle/wrapper/SystemPropertiesHandlerTest.groovy b/subprojects/wrapper/src/test/groovy/org/gradle/wrapper/SystemPropertiesHandlerTest.groovy
index bb7cf9e..124a137 100644
--- a/subprojects/wrapper/src/test/groovy/org/gradle/wrapper/SystemPropertiesHandlerTest.groovy
+++ b/subprojects/wrapper/src/test/groovy/org/gradle/wrapper/SystemPropertiesHandlerTest.groovy
@@ -19,9 +19,6 @@ import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
import org.junit.Rule
import spock.lang.Specification
-/**
- * @author Hans Dockter
- */
class SystemPropertiesHandlerTest extends Specification {
@Rule
TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider()
diff --git a/subprojects/wrapper/wrapper.gradle b/subprojects/wrapper/wrapper.gradle
index e03ed74..8e1c896 100644
--- a/subprojects/wrapper/wrapper.gradle
+++ b/subprojects/wrapper/wrapper.gradle
@@ -14,8 +14,9 @@
* limitations under the License.
*/
dependencies {
- groovy libraries.groovy
compile project(":cli")
+
+ testCompile libraries.groovy
testCompile libraries.ant
integTestRuntime rootProject.configurations.testRuntime.allDependencies
diff --git a/version.txt b/version.txt
index 400122e..6259340 100644
--- a/version.txt
+++ b/version.txt
@@ -1 +1 @@
-1.5
\ No newline at end of file
+1.8
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/gradle.git
More information about the pkg-java-commits
mailing list